1 /**
2  * Miscellaneous Windows utility code.
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <ae@cy.md>
12  */
13 
14 module ae.sys.windows.misc;
15 version (Windows):
16 
17 import std.string;
18 
19 import ae.sys.windows.imports;
20 mixin(importWin32!q{winbase});
21 mixin(importWin32!q{wincon});
22 mixin(importWin32!q{winnt});
23 mixin(importWin32!q{winuser});
24 
25 import ae.sys.windows.exception;
26 import ae.sys.windows.text;
27 
28 /// Construct a `LARGE_INTEGER`.
29 LARGE_INTEGER largeInteger(long n) pure nothrow @nogc
30 {
31 	LARGE_INTEGER li; li.QuadPart = n; return li;
32 }
33 
34 /// Construct a `ULARGE_INTEGER`.
35 ULARGE_INTEGER ulargeInteger(ulong n) pure nothrow @nogc
36 {
37 	ULARGE_INTEGER li; li.QuadPart = n; return li;
38 }
39 
40 /// Construct an `ulong` from two `DWORD`s using `ULANGE_INTEGER`.
41 ulong makeUlong(DWORD dwLow, DWORD dwHigh) pure nothrow @nogc
42 {
43 	ULARGE_INTEGER li;
44 	li.LowPart  = dwLow;
45 	li.HighPart = dwHigh;
46 	return li.QuadPart;
47 }
48 
49 // ***************************************************************************
50 
51 // Messages
52 
53 /// Pump pending messages.
54 void processWindowsMessages()()
55 {
56 	MSG m;
57 	while (PeekMessageW(&m, null, 0, 0, PM_REMOVE))
58 	{
59 		TranslateMessage(&m);
60 		DispatchMessageW(&m);
61 	}
62 }
63 
64 /// Pump messages until a WM_QUIT.
65 void messageLoop()()
66 {
67 	MSG m;
68 	while (GetMessageW(&m, null, 0, 0))
69 	{
70 		TranslateMessage(&m);
71 		DispatchMessageW(&m);
72 	}
73 }
74 
75 // ***************************************************************************
76 
77 /// `MessageBoxW` wrapper.
78 int messageBox()(string message, string title, int style=0)
79 {
80 	return MessageBoxW(null, toWStringz(message), toWStringz(title), style);
81 }
82 
83 /// `GetLastInputInfo` wrapper.
84 uint getLastInputInfo()()
85 {
86 	LASTINPUTINFO lii = { LASTINPUTINFO.sizeof };
87 	wenforce(GetLastInputInfo(&lii), "GetLastInputInfo");
88 	return lii.dwTime;
89 }
90 
91 // ***************************************************************************
92 
93 /// Hides the console window, but only if we are the owner.
94 void hideOwnConsoleWindow()()
95 {
96 	HWND w = GetConsoleWindow();
97 	if (!w)
98 		return;
99 	DWORD pid;
100 	GetWindowThreadProcessId(w, &pid);
101 	if (pid == GetCurrentProcessId())
102 		ShowWindow(w, SW_HIDE);
103 }
104 
105 // ***************************************************************************
106 
107 /// Returns true if the host Windows OS is 64-bit.
108 bool isWin64()
109 {
110 	version (D_LP64)
111 		return true; // host must be 64-bit if this compiles
112 	else
113 	{
114 		import core.sys.windows.winbase : IsWow64Process, GetCurrentProcess;
115 		int is64;
116 		IsWow64Process(GetCurrentProcess(), &is64).wenforce("IsWow64Process");
117 		return !!is64;
118 	}
119 }
120 
121 /// Returns Wine version, or null if not running under Wine.
122 string getWineVersion()
123 {
124 	auto ntdll = GetModuleHandle("ntdll.dll");
125 	if (!ntdll)
126 		return null;
127 	alias wine_get_version_t = extern(C) const(char*) function();
128 	auto wine_get_version = cast(wine_get_version_t)GetProcAddress(ntdll, "wine_get_version");
129 	if (!wine_get_version)
130 		return null;
131 	import std.conv : to;
132 	return wine_get_version().to!string();
133 }