1 /**
2 * Copyright: Copyright (c) 2011 Nick Sabalausky.
3 * Authors: Nick Sabalausky
4 * Version: Initial created: Jun 1, 2011
5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
6 */
7 module dvm.util.Windows;
8
9 version (Windows):
10
11 import mambo.core..string;
12 import dvm.dvm.Exceptions;
13 import tango.sys.win32.Types;
14 import tango.sys.win32.UserGdi;
15 import tango.util.Convert;
16
17 // If FORMAT_MESSAGE_ALLOCATE_BUFFER is used, then this is the correct
18 // signature. Otherwise, the signature in tango.sys.win32.UserGdi is corrent.
19 extern (Windows) DWORD FormatMessageW (DWORD, LPCVOID, DWORD, DWORD, LPWSTR*, DWORD, VA_LIST*);
20
21 class WinAPIException : DvmException
22 {
23 LONG code;
24 string windowsMsg;
25
26 this (LONG code, string msg = "", string file = __FILE__, size_t line = __LINE__)
27 {
28 this.code = code;
29
30 if(windowsMsg == "")
31 windowsMsg = getMessage(code);
32
33 super(msg == "" ? windowsMsg : msg, file, line);
34 }
35
36 static string getMessage (DWORD errorCode)
37 {
38 wchar* pMsg;
39
40 auto result = FormatMessageW(
41 FORMAT_MESSAGE_ALLOCATE_BUFFER |
42 FORMAT_MESSAGE_FROM_SYSTEM |
43 FORMAT_MESSAGE_IGNORE_INSERTS,
44 null, errorCode, 0, &pMsg, 0, null
45 );
46
47 if(result == 0)
48 return "Unknown WinAPI Error";
49
50 scope (exit)
51 LocalFree(pMsg);
52
53 auto msg = fromString16z(pMsg);
54 return to!(string)(msg);
55 }
56 }
57
58 private alias mambo.core..string.toString16z toString16z;
59
60 immutable(wchar)* toString16z (string str)
61 {
62 return to!(wstring)(str).toString16z();
63 }
64
65 /// For more info, see: http://msdn.microsoft.com/en-us/library/ms725497(VS.85).aspx
66 void broadcastSettingChange (string settingName, uint timeout=1)
67 {
68 auto result = SendMessageTimeoutW(
69 HWND_BROADCAST, WM_SETTINGCHANGE,
70 0, cast(LPARAM)(settingName.toString16z()),
71 SMTO_ABORTIFHUNG, timeout, null
72 );
73
74 if(result == 0)
75 {
76 auto errCode = GetLastError();
77
78 if (errCode != ERROR_SUCCESS)
79 throw new WinAPIException(errCode, "Problem broadcasting WM_SETTINGCHANGE of '" ~ settingName ~ "'", __FILE__, __LINE__);
80 }
81 }
82
83 string expandEnvironmentStrings(string str)
84 {
85 auto wstr = toString16z(str);
86
87 wchar[] result;
88 result.length = 32_000 / wchar.sizeof;
89
90 auto resultLength = ExpandEnvironmentStringsW(wstr, result.ptr, result.length);
91
92 if(resultLength == 0)
93 {
94 auto errCode = GetLastError();
95
96 if (errCode != ERROR_SUCCESS)
97 throw new WinAPIException(errCode, "Problem expanding environment variables", __FILE__, __LINE__);
98 }
99
100 return to!(string)(result[0..resultLength-1]);
101 }