[RAPPS] CMainWindow: remove unused functions , and the globals g_MainWindow and hListView
[reactos.git] / base / applications / rapps / misc.cpp
1 /*
2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/misc.cpp
5 * PURPOSE: Misc functions
6 * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
7 * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
8 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
9 */
10 #include "rapps.h"
11
12 #include "misc.h"
13
14 static HANDLE hLog = NULL;
15
16 INT GetWindowWidth(HWND hwnd)
17 {
18 RECT Rect;
19
20 GetWindowRect(hwnd, &Rect);
21 return (Rect.right - Rect.left);
22 }
23
24 INT GetWindowHeight(HWND hwnd)
25 {
26 RECT Rect;
27
28 GetWindowRect(hwnd, &Rect);
29 return (Rect.bottom - Rect.top);
30 }
31
32 INT GetClientWindowWidth(HWND hwnd)
33 {
34 RECT Rect;
35
36 GetClientRect(hwnd, &Rect);
37 return (Rect.right - Rect.left);
38 }
39
40 INT GetClientWindowHeight(HWND hwnd)
41 {
42 RECT Rect;
43
44 GetClientRect(hwnd, &Rect);
45 return (Rect.bottom - Rect.top);
46 }
47
48 VOID CopyTextToClipboard(LPCWSTR lpszText)
49 {
50 if (!OpenClipboard(NULL))
51 {
52 return;
53 }
54
55 HRESULT hr;
56 HGLOBAL ClipBuffer;
57 LPWSTR Buffer;
58 DWORD cchBuffer;
59
60 EmptyClipboard();
61 cchBuffer = wcslen(lpszText) + 1;
62 ClipBuffer = GlobalAlloc(GMEM_DDESHARE, cchBuffer * sizeof(WCHAR));
63
64 Buffer = (PWCHAR) GlobalLock(ClipBuffer);
65 hr = StringCchCopyW(Buffer, cchBuffer, lpszText);
66 GlobalUnlock(ClipBuffer);
67
68 if (SUCCEEDED(hr))
69 SetClipboardData(CF_UNICODETEXT, ClipBuffer);
70
71 CloseClipboard();
72 }
73
74 VOID ShowPopupMenu(HWND hwnd, UINT MenuID, UINT DefaultItem)
75 {
76 HMENU hMenu = NULL;
77 HMENU hPopupMenu;
78 MENUITEMINFO ItemInfo;
79 POINT pt;
80
81 if (MenuID)
82 {
83 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(MenuID));
84 hPopupMenu = GetSubMenu(hMenu, 0);
85 }
86 else
87 {
88 hPopupMenu = GetMenu(hwnd);
89 }
90
91 ZeroMemory(&ItemInfo, sizeof(ItemInfo));
92 ItemInfo.cbSize = sizeof(ItemInfo);
93 ItemInfo.fMask = MIIM_STATE;
94
95 GetMenuItemInfoW(hPopupMenu, DefaultItem, FALSE, &ItemInfo);
96
97 if (!(ItemInfo.fState & MFS_GRAYED))
98 {
99 SetMenuDefaultItem(hPopupMenu, DefaultItem, FALSE);
100 }
101
102 GetCursorPos(&pt);
103
104 SetForegroundWindow(hwnd);
105 TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hMainWnd, NULL);
106
107 if (hMenu)
108 {
109 DestroyMenu(hMenu);
110 }
111 }
112
113 BOOL StartProcess(ATL::CStringW &Path, BOOL Wait)
114 {
115 return StartProcess(const_cast<LPWSTR>(Path.GetString()), Wait);;
116 }
117
118 BOOL StartProcess(LPWSTR lpPath, BOOL Wait)
119 {
120 PROCESS_INFORMATION pi;
121 STARTUPINFOW si;
122 DWORD dwRet;
123 MSG msg;
124
125 ZeroMemory(&si, sizeof(si));
126 si.cb = sizeof(si);
127 si.dwFlags = STARTF_USESHOWWINDOW;
128 si.wShowWindow = SW_SHOW;
129
130 if (!CreateProcessW(NULL, lpPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
131 {
132 return FALSE;
133 }
134
135 CloseHandle(pi.hThread);
136
137 if (Wait)
138 {
139 EnableWindow(hMainWnd, FALSE);
140 }
141
142 while (Wait)
143 {
144 dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS);
145 if (dwRet == WAIT_OBJECT_0 + 1)
146 {
147 while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
148 {
149 TranslateMessage(&msg);
150 DispatchMessageW(&msg);
151 }
152 }
153 else
154 {
155 if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED)
156 break;
157 }
158 }
159
160 CloseHandle(pi.hProcess);
161
162 if (Wait)
163 {
164 EnableWindow(hMainWnd, TRUE);
165 SetForegroundWindow(hMainWnd);
166 SetFocus(hMainWnd);
167 }
168
169 return TRUE;
170 }
171
172 BOOL GetStorageDirectory(ATL::CStringW& Directory)
173 {
174 if (!SHGetSpecialFolderPathW(NULL, Directory.GetBuffer(MAX_PATH), CSIDL_LOCAL_APPDATA, TRUE))
175 {
176 Directory.ReleaseBuffer();
177 return FALSE;
178 }
179
180 Directory.ReleaseBuffer();
181 Directory += L"\\rapps";
182
183 return (CreateDirectoryW(Directory.GetString(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS);
184 }
185
186 VOID InitLogs()
187 {
188 if (!SettingsInfo.bLogEnabled)
189 {
190 return;
191 }
192
193 WCHAR szPath[MAX_PATH];
194 DWORD dwCategoryNum = 1;
195 DWORD dwDisp, dwData;
196 ATL::CRegKey key;
197
198 if (key.Create(HKEY_LOCAL_MACHINE,
199 L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager",
200 REG_NONE, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &dwDisp) != ERROR_SUCCESS)
201 {
202 return;
203 }
204
205 if (!GetModuleFileNameW(NULL, szPath, _countof(szPath)))
206 {
207 return;
208 }
209
210 dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
211 EVENTLOG_INFORMATION_TYPE;
212
213 if ((key.SetStringValue(L"EventMessageFile",
214 szPath,
215 REG_EXPAND_SZ) == ERROR_SUCCESS)
216 && (key.SetStringValue(L"CategoryMessageFile",
217 szPath,
218 REG_EXPAND_SZ) == ERROR_SUCCESS)
219 && (key.SetDWORDValue(L"TypesSupported",
220 dwData) == ERROR_SUCCESS)
221 && (key.SetDWORDValue(L"CategoryCount",
222 dwCategoryNum) == ERROR_SUCCESS))
223
224 {
225 hLog = RegisterEventSourceW(NULL, L"ReactOS Application Manager");
226 }
227
228 key.Close();
229 }
230
231
232 VOID FreeLogs()
233 {
234 if (hLog)
235 {
236 DeregisterEventSource(hLog);
237 }
238 }
239
240
241 BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg)
242 {
243 if (!SettingsInfo.bLogEnabled)
244 {
245 return TRUE;
246 }
247
248 if (!ReportEventW(hLog, wType, 0, dwEventID,
249 NULL, 1, 0, &lpMsg, NULL))
250 {
251 return FALSE;
252 }
253
254 return TRUE;
255 }
256
257 BOOL GetInstalledVersion_WowUser(ATL::CStringW* szVersionResult,
258 const ATL::CStringW& szRegName,
259 BOOL IsUserKey,
260 REGSAM keyWow)
261 {
262 BOOL bHasSucceded = FALSE;
263 ATL::CRegKey key;
264 ATL::CStringW szVersion;
265 ATL::CStringW szPath = ATL::CStringW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls") + szRegName;
266
267 if (key.Open(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE,
268 szPath.GetString(),
269 keyWow | KEY_READ) != ERROR_SUCCESS)
270 {
271 return FALSE;
272 }
273
274 if (szVersionResult != NULL)
275 {
276 ULONG dwSize = MAX_PATH * sizeof(WCHAR);
277
278 if (key.QueryStringValue(L"DisplayVersion",
279 szVersion.GetBuffer(MAX_PATH),
280 &dwSize) == ERROR_SUCCESS)
281 {
282 szVersion.ReleaseBuffer();
283 *szVersionResult = szVersion;
284 bHasSucceded = TRUE;
285 }
286 else
287 {
288 szVersion.ReleaseBuffer();
289 }
290 }
291 else
292 {
293 bHasSucceded = TRUE;
294 szVersion.ReleaseBuffer();
295 }
296 key.Close();
297
298 return bHasSucceded;
299 }
300
301 BOOL GetInstalledVersion(ATL::CStringW *pszVersion, const ATL::CStringW &szRegName)
302 {
303 return (!szRegName.IsEmpty()
304 && (GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_32KEY)
305 || GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_32KEY)
306 || GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_64KEY)
307 || GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_64KEY)));
308 }
309
310 // CConfigParser
311
312 CConfigParser::CConfigParser(const ATL::CStringW& FileName) : szConfigPath(GetINIFullPath(FileName))
313 {
314 CacheINILocale();
315 }
316
317 ATL::CStringW CConfigParser::GetINIFullPath(const ATL::CStringW& FileName)
318 {
319 ATL::CStringW szDir;
320 ATL::CStringW szBuffer;
321
322 GetStorageDirectory(szDir);
323 szBuffer.Format(L"%ls\\rapps\\%ls", szDir.GetString(), FileName.GetString());
324
325 return szBuffer;
326 }
327
328 VOID CConfigParser::CacheINILocale()
329 {
330 // TODO: Set default locale if call fails
331 // find out what is the current system lang code (e.g. "0a") and append it to SectionLocale
332 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE,
333 m_szLocaleID.GetBuffer(m_cchLocaleSize), m_cchLocaleSize);
334
335 m_szLocaleID.ReleaseBuffer();
336 m_szCachedINISectionLocale = L"Section." + m_szLocaleID;
337
338 // turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
339 m_szCachedINISectionLocaleNeutral = m_szCachedINISectionLocale + m_szLocaleID.Right(2);
340 }
341
342 BOOL CConfigParser::GetString(const ATL::CStringW& KeyName, ATL::CStringW& ResultString)
343 {
344 DWORD dwResult;
345
346 LPWSTR ResultStringBuffer = ResultString.GetBuffer(MAX_PATH);
347 // 1st - find localized strings (e.g. "Section.0c0a")
348 dwResult = GetPrivateProfileStringW(m_szCachedINISectionLocale.GetString(),
349 KeyName.GetString(),
350 NULL,
351 ResultStringBuffer,
352 MAX_PATH,
353 szConfigPath.GetString());
354
355 if (!dwResult)
356 {
357 // 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a")
358 dwResult = GetPrivateProfileStringW(m_szCachedINISectionLocaleNeutral.GetString(),
359 KeyName.GetString(),
360 NULL,
361 ResultStringBuffer,
362 MAX_PATH,
363 szConfigPath.GetString());
364 if (!dwResult)
365 {
366 // 3rd - if they weren't present fallback to standard english strings (just "Section")
367 dwResult = GetPrivateProfileStringW(L"Section",
368 KeyName.GetString(),
369 NULL,
370 ResultStringBuffer,
371 MAX_PATH,
372 szConfigPath.GetString());
373 }
374 }
375
376 ResultString.ReleaseBuffer();
377 return (dwResult != 0 ? TRUE : FALSE);
378 }
379
380 BOOL CConfigParser::GetInt(const ATL::CStringW& KeyName, INT& iResult)
381 {
382 ATL::CStringW Buffer;
383
384 iResult = 0;
385
386 // grab the text version of our entry
387 if (!GetString(KeyName, Buffer))
388 return FALSE;
389
390 if (Buffer.IsEmpty())
391 return FALSE;
392
393 // convert it to an actual integer
394 iResult = StrToIntW(Buffer.GetString());
395
396 // we only care about values > 0
397 return (iResult > 0);
398 }
399 // CConfigParser