15b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project 25b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// 35b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public 45b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and 55b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// may be copied, distributed, and modified under those terms. 65b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// 75b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// This program is distributed in the hope that it will be useful, 85b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of 95b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 105b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner// GNU General Public License for more details. 115b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 125b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#ifdef _WIN32 135b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 145b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#include <glib.h> 155b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 16f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner#include <assert.h> 175b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#include <wchar.h> 185b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#define WIN32_LEAN_AND_MEAN 195b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#include <windows.h> 205b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 21f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner// Atomic operations 22f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner 23f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turnervoid g_atomic_int_inc(int volatile* atomic) { 24f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner assert(sizeof(LONG) == sizeof(int)); 25f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner InterlockedIncrement((LONG volatile*)atomic); 26f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner} 27f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner 28f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turnergboolean g_atomic_int_dec_and_test(int volatile* atomic) { 29f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner assert(sizeof(LONG) == sizeof(int)); 30f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner return !InterlockedIncrement((LONG volatile*)atomic); 31f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner} 32f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner 33f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner// Win32 error messages. 34f3f3c9b864a902e10cefb0e666f2354672352fcaDavid 'Digit' Turner 355b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turnerstatic char* 365b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turnerutf16_to_utf8(const wchar_t* wstring, int wstring_len) 375b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner{ 385b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner int utf8_len = WideCharToMultiByte(CP_UTF8, // CodePage 395b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 0, // dwFlags 405b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner (LPWSTR) wstring, // lpWideCharStr 415b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner wstring_len, // cchWideChar 425b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner NULL, // lpMultiByteStr 435b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 0, // cbMultiByte 445b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner NULL, // lpDefaultChar 455b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner NULL); // lpUsedDefaultChar 465b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner if (utf8_len == 0) 475b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner return g_strdup(""); 485b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 495b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner char* result = g_malloc(utf8_len + 1); 505b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 515b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner WideCharToMultiByte(CP_UTF8, 0, (LPWSTR) wstring, wstring_len, 525b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner result, utf8_len, NULL, NULL); 535b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner result[utf8_len] = '\0'; 545b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner return result; 555b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner} 565b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 575b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turnerchar * 585b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turnerg_win32_error_message (int error) 595b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner{ 605b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner LPWSTR msg = NULL; 615b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner int nchars; 625b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner char* result; 635b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 645b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner // Work around for compiler warning, due to brain-dead API. 655b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner union { 665b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner LPWSTR* address; 675b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner LPWSTR value; 685b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner } msg_param; 695b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner msg_param.address = &msg; 705b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 715b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER 725b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner |FORMAT_MESSAGE_IGNORE_INSERTS 735b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner |FORMAT_MESSAGE_FROM_SYSTEM, 745b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner NULL, error, 0, 755b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner msg_param.value, 765b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 0, NULL); 775b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner if (!msg) 785b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner return g_strdup(""); 795b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 805b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner // Get rid of trailing \r\n if any. 815b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner nchars = wcslen (msg); 825b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner if (nchars > 2 && msg[nchars-1] == '\n' && msg[nchars-2] == '\r') 835b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner msg[nchars-2] = '\0'; 845b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 855b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner result = utf16_to_utf8 (msg, nchars); 865b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 875b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner LocalFree (msg); 885b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 895b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner return result; 905b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner} 915b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner 925b693bd24df715e5ea790784637d0d203fb5be0dDavid 'Digit' Turner#endif // _WIN32 93