1 /* 2 * PROJECT: ReactOS Applications Manager 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Misc functions 5 * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org) 6 * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com) 7 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org) 8 */ 9 10 #include "rapps.h" 11 #include "misc.h" 12 13 static HANDLE hLog = NULL; 14 15 static BOOL bIsSys64ResultCached = FALSE; 16 static BOOL bIsSys64Result = FALSE; 17 18 VOID 19 CopyTextToClipboard(LPCWSTR lpszText) 20 { 21 if (!OpenClipboard(NULL)) 22 { 23 return; 24 } 25 26 HRESULT hr; 27 HGLOBAL ClipBuffer; 28 LPWSTR Buffer; 29 DWORD cchBuffer; 30 31 EmptyClipboard(); 32 cchBuffer = wcslen(lpszText) + 1; 33 ClipBuffer = GlobalAlloc(GMEM_DDESHARE, cchBuffer * sizeof(WCHAR)); 34 35 Buffer = (PWCHAR)GlobalLock(ClipBuffer); 36 hr = StringCchCopyW(Buffer, cchBuffer, lpszText); 37 GlobalUnlock(ClipBuffer); 38 39 if (SUCCEEDED(hr)) 40 SetClipboardData(CF_UNICODETEXT, ClipBuffer); 41 42 CloseClipboard(); 43 } 44 45 VOID 46 ShowPopupMenuEx(HWND hwnd, HWND hwndOwner, UINT MenuID, UINT DefaultItem) 47 { 48 HMENU hMenu = NULL; 49 HMENU hPopupMenu; 50 MENUITEMINFO ItemInfo; 51 POINT pt; 52 53 if (MenuID) 54 { 55 hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(MenuID)); 56 hPopupMenu = GetSubMenu(hMenu, 0); 57 } 58 else 59 { 60 hPopupMenu = GetMenu(hwnd); 61 } 62 63 ZeroMemory(&ItemInfo, sizeof(ItemInfo)); 64 ItemInfo.cbSize = sizeof(ItemInfo); 65 ItemInfo.fMask = MIIM_STATE; 66 67 GetMenuItemInfoW(hPopupMenu, DefaultItem, FALSE, &ItemInfo); 68 69 if (!(ItemInfo.fState & MFS_GRAYED)) 70 { 71 SetMenuDefaultItem(hPopupMenu, DefaultItem, FALSE); 72 } 73 74 GetCursorPos(&pt); 75 76 SetForegroundWindow(hwnd); 77 TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hwndOwner, NULL); 78 79 if (hMenu) 80 { 81 DestroyMenu(hMenu); 82 } 83 } 84 85 BOOL 86 StartProcess(const CStringW &Path, BOOL Wait) 87 { 88 PROCESS_INFORMATION pi; 89 STARTUPINFOW si; 90 DWORD dwRet; 91 MSG msg; 92 93 ZeroMemory(&si, sizeof(si)); 94 si.cb = sizeof(si); 95 si.dwFlags = STARTF_USESHOWWINDOW; 96 si.wShowWindow = SW_SHOW; 97 98 // The Unicode version of CreateProcess can modify the contents of this string. 99 CStringW Tmp = Path; 100 BOOL fSuccess = CreateProcessW(NULL, Tmp.GetBuffer(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 101 Tmp.ReleaseBuffer(); 102 if (!fSuccess) 103 { 104 return FALSE; 105 } 106 107 CloseHandle(pi.hThread); 108 109 if (Wait) 110 { 111 EnableWindow(hMainWnd, FALSE); 112 } 113 114 while (Wait) 115 { 116 dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS); 117 if (dwRet == WAIT_OBJECT_0 + 1) 118 { 119 while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) 120 { 121 TranslateMessage(&msg); 122 DispatchMessageW(&msg); 123 } 124 } 125 else 126 { 127 if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED) 128 break; 129 } 130 } 131 132 CloseHandle(pi.hProcess); 133 134 if (Wait) 135 { 136 EnableWindow(hMainWnd, TRUE); 137 SetForegroundWindow(hMainWnd); 138 SetFocus(hMainWnd); 139 } 140 141 return TRUE; 142 } 143 144 BOOL 145 GetStorageDirectory(CStringW &Directory) 146 { 147 static CStringW CachedDirectory; 148 static BOOL CachedDirectoryInitialized = FALSE; 149 150 if (!CachedDirectoryInitialized) 151 { 152 LPWSTR DirectoryStr = CachedDirectory.GetBuffer(MAX_PATH); 153 BOOL bHasPath = SHGetSpecialFolderPathW(NULL, DirectoryStr, CSIDL_LOCAL_APPDATA, TRUE); 154 if (bHasPath) 155 { 156 PathAppendW(DirectoryStr, RAPPS_NAME); 157 } 158 CachedDirectory.ReleaseBuffer(); 159 160 if (bHasPath) 161 { 162 if (!CreateDirectoryW(CachedDirectory, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) 163 { 164 CachedDirectory.Empty(); 165 } 166 } 167 else 168 { 169 CachedDirectory.Empty(); 170 } 171 172 CachedDirectoryInitialized = TRUE; 173 } 174 175 Directory = CachedDirectory; 176 return !Directory.IsEmpty(); 177 } 178 179 VOID 180 InitLogs() 181 { 182 if (!SettingsInfo.bLogEnabled) 183 { 184 return; 185 } 186 187 WCHAR szPath[MAX_PATH]; 188 DWORD dwCategoryNum = 1; 189 DWORD dwDisp, dwData; 190 ATL::CRegKey key; 191 192 if (key.Create( 193 HKEY_LOCAL_MACHINE, 194 L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager", REG_NONE, 195 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &dwDisp) != ERROR_SUCCESS) 196 { 197 return; 198 } 199 200 if (!GetModuleFileNameW(NULL, szPath, _countof(szPath))) 201 { 202 return; 203 } 204 205 dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; 206 207 if ((key.SetStringValue(L"EventMessageFile", szPath, REG_EXPAND_SZ) == ERROR_SUCCESS) && 208 (key.SetStringValue(L"CategoryMessageFile", szPath, REG_EXPAND_SZ) == ERROR_SUCCESS) && 209 (key.SetDWORDValue(L"TypesSupported", dwData) == ERROR_SUCCESS) && 210 (key.SetDWORDValue(L"CategoryCount", dwCategoryNum) == ERROR_SUCCESS)) 211 212 { 213 hLog = RegisterEventSourceW(NULL, L"ReactOS Application Manager"); 214 } 215 } 216 217 VOID 218 FreeLogs() 219 { 220 if (hLog) 221 { 222 DeregisterEventSource(hLog); 223 } 224 } 225 226 BOOL 227 WriteLogMessage(WORD wType, DWORD dwEventID, LPCWSTR lpMsg) 228 { 229 if (!SettingsInfo.bLogEnabled) 230 { 231 return TRUE; 232 } 233 234 if (!ReportEventW(hLog, wType, 0, dwEventID, NULL, 1, 0, &lpMsg, NULL)) 235 { 236 return FALSE; 237 } 238 239 return TRUE; 240 } 241 242 BOOL 243 GetInstalledVersion_WowUser(CStringW *szVersionResult, const CStringW &szRegName, BOOL IsUserKey, REGSAM keyWow) 244 { 245 BOOL bHasSucceded = FALSE; 246 ATL::CRegKey key; 247 CStringW szVersion; 248 CStringW szPath = CStringW(L"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\") + szRegName; 249 250 if (key.Open(IsUserKey ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, szPath.GetString(), keyWow | KEY_READ) != 251 ERROR_SUCCESS) 252 { 253 return FALSE; 254 } 255 256 if (szVersionResult != NULL) 257 { 258 ULONG dwSize = MAX_PATH * sizeof(WCHAR); 259 260 if (key.QueryStringValue(L"DisplayVersion", szVersion.GetBuffer(MAX_PATH), &dwSize) == ERROR_SUCCESS) 261 { 262 szVersion.ReleaseBuffer(); 263 *szVersionResult = szVersion; 264 bHasSucceded = TRUE; 265 } 266 else 267 { 268 szVersion.ReleaseBuffer(); 269 } 270 } 271 else 272 { 273 bHasSucceded = TRUE; 274 } 275 276 return bHasSucceded; 277 } 278 279 BOOL 280 GetInstalledVersion(CStringW *pszVersion, const CStringW &szRegName) 281 { 282 return ( 283 !szRegName.IsEmpty() && (GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_32KEY) || 284 GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_32KEY) || 285 GetInstalledVersion_WowUser(pszVersion, szRegName, TRUE, KEY_WOW64_64KEY) || 286 GetInstalledVersion_WowUser(pszVersion, szRegName, FALSE, KEY_WOW64_64KEY))); 287 } 288 289 BOOL 290 IsSystem64Bit() 291 { 292 if (bIsSys64ResultCached) 293 { 294 // just return cached result 295 return bIsSys64Result; 296 } 297 298 SYSTEM_INFO si; 299 typedef void(WINAPI * LPFN_PGNSI)(LPSYSTEM_INFO); 300 LPFN_PGNSI pGetNativeSystemInfo = 301 (LPFN_PGNSI)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "GetNativeSystemInfo"); 302 if (pGetNativeSystemInfo) 303 { 304 pGetNativeSystemInfo(&si); 305 if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || 306 si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) 307 { 308 bIsSys64Result = TRUE; 309 } 310 } 311 else 312 { 313 bIsSys64Result = FALSE; 314 } 315 316 bIsSys64ResultCached = TRUE; // next time calling this function, it will directly return bIsSys64Result 317 return bIsSys64Result; 318 } 319 320 INT 321 GetSystemColorDepth() 322 { 323 DEVMODEW pDevMode; 324 INT ColorDepth; 325 326 pDevMode.dmSize = sizeof(pDevMode); 327 pDevMode.dmDriverExtra = 0; 328 329 if (!EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &pDevMode)) 330 { 331 /* TODO: Error message */ 332 return ILC_COLOR; 333 } 334 335 switch (pDevMode.dmBitsPerPel) 336 { 337 case 32: 338 ColorDepth = ILC_COLOR32; 339 break; 340 case 24: 341 ColorDepth = ILC_COLOR24; 342 break; 343 case 16: 344 ColorDepth = ILC_COLOR16; 345 break; 346 case 8: 347 ColorDepth = ILC_COLOR8; 348 break; 349 case 4: 350 ColorDepth = ILC_COLOR4; 351 break; 352 default: 353 ColorDepth = ILC_COLOR; 354 break; 355 } 356 357 return ColorDepth; 358 } 359 360 void 361 UnixTimeToFileTime(DWORD dwUnixTime, LPFILETIME pFileTime) 362 { 363 // Note that LONGLONG is a 64-bit value 364 LONGLONG ll; 365 366 ll = Int32x32To64(dwUnixTime, 10000000) + 116444736000000000; 367 pFileTime->dwLowDateTime = (DWORD)ll; 368 pFileTime->dwHighDateTime = ll >> 32; 369 } 370 371 BOOL 372 SearchPatternMatch(LPCWSTR szHaystack, LPCWSTR szNeedle) 373 { 374 if (!*szNeedle) 375 return TRUE; 376 /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */ 377 return StrStrIW(szHaystack, szNeedle) != NULL; 378 } 379