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