1 // Copyright 2014 The Android Open Source Project
2 //
3 // This software is licensed under the terms of the GNU General Public
4 // License version 2, as published by the Free Software Foundation, and
5 // may be copied, distributed, and modified under those terms.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License for more details.
11
12 #ifdef _WIN32
13
14 #include <glib.h>
15
16 #include <assert.h>
17 #include <wchar.h>
18 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20
21 // Atomic operations
22
g_atomic_int_inc(int volatile * atomic)23 void g_atomic_int_inc(int volatile* atomic) {
24 assert(sizeof(LONG) == sizeof(int));
25 InterlockedIncrement((LONG volatile*)atomic);
26 }
27
g_atomic_int_dec_and_test(int volatile * atomic)28 gboolean g_atomic_int_dec_and_test(int volatile* atomic) {
29 assert(sizeof(LONG) == sizeof(int));
30 return !InterlockedIncrement((LONG volatile*)atomic);
31 }
32
33 // Win32 error messages.
34
35 static char*
utf16_to_utf8(const wchar_t * wstring,int wstring_len)36 utf16_to_utf8(const wchar_t* wstring, int wstring_len)
37 {
38 int utf8_len = WideCharToMultiByte(CP_UTF8, // CodePage
39 0, // dwFlags
40 (LPWSTR) wstring, // lpWideCharStr
41 wstring_len, // cchWideChar
42 NULL, // lpMultiByteStr
43 0, // cbMultiByte
44 NULL, // lpDefaultChar
45 NULL); // lpUsedDefaultChar
46 if (utf8_len == 0)
47 return g_strdup("");
48
49 char* result = g_malloc(utf8_len + 1);
50
51 WideCharToMultiByte(CP_UTF8, 0, (LPWSTR) wstring, wstring_len,
52 result, utf8_len, NULL, NULL);
53 result[utf8_len] = '\0';
54 return result;
55 }
56
57 char *
g_win32_error_message(int error)58 g_win32_error_message (int error)
59 {
60 LPWSTR msg = NULL;
61 int nchars;
62 char* result;
63
64 // Work around for compiler warning, due to brain-dead API.
65 union {
66 LPWSTR* address;
67 LPWSTR value;
68 } msg_param;
69 msg_param.address = &msg;
70
71 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
72 |FORMAT_MESSAGE_IGNORE_INSERTS
73 |FORMAT_MESSAGE_FROM_SYSTEM,
74 NULL, error, 0,
75 msg_param.value,
76 0, NULL);
77 if (!msg)
78 return g_strdup("");
79
80 // Get rid of trailing \r\n if any.
81 nchars = wcslen (msg);
82 if (nchars > 2 && msg[nchars-1] == '\n' && msg[nchars-2] == '\r')
83 msg[nchars-2] = '\0';
84
85 result = utf16_to_utf8 (msg, nchars);
86
87 LocalFree (msg);
88
89 return result;
90 }
91
92 #endif // _WIN32
93