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
23void g_atomic_int_inc(int volatile* atomic) {
24  assert(sizeof(LONG) == sizeof(int));
25  InterlockedIncrement((LONG volatile*)atomic);
26}
27
28gboolean 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
35static char*
36utf16_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
57char *
58g_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