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