/* * PROJECT: ReactOS Applications Manager * LICENSE: GPL - See COPYING in the top level directory * FILE: base/applications/rapps_new/misc.cpp * PURPOSE: Misc functions * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org) * Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com) */ #include "rapps.h" /* SESSION Operation */ #define EXTRACT_FILLFILELIST 0x00000001 #define EXTRACT_EXTRACTFILES 0x00000002 static HANDLE hLog = NULL; WCHAR szCachedINISectionLocale[MAX_PATH] = L"Section."; WCHAR szCachedINISectionLocaleNeutral[MAX_PATH] = {0}; BYTE bCachedSectionStatus = FALSE; typedef struct { int erfOper; int erfType; BOOL fError; } ERF, *PERF; struct FILELIST { LPSTR FileName; struct FILELIST *next; BOOL DoExtract; }; typedef struct { INT FileSize; ERF Error; struct FILELIST *FileList; INT FileCount; INT Operation; CHAR Destination[MAX_PATH]; CHAR CurrentFile[MAX_PATH]; CHAR Reserved[MAX_PATH]; struct FILELIST *FilterList; } SESSION; typedef HRESULT(WINAPI *fnExtract)(SESSION *dest, LPCSTR szCabName); fnExtract pfnExtract; INT GetSystemColorDepth(VOID) { DEVMODE pDevMode; INT ColorDepth; pDevMode.dmSize = sizeof(DEVMODE); pDevMode.dmDriverExtra = 0; if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &pDevMode)) { /* TODO: Error message */ return ILC_COLOR; } switch (pDevMode.dmBitsPerPel) { case 32: ColorDepth = ILC_COLOR32; break; case 24: ColorDepth = ILC_COLOR24; break; case 16: ColorDepth = ILC_COLOR16; break; case 8: ColorDepth = ILC_COLOR8; break; case 4: ColorDepth = ILC_COLOR4; break; default: ColorDepth = ILC_COLOR; break; } return ColorDepth; } int GetWindowWidth(HWND hwnd) { RECT Rect; GetWindowRect(hwnd, &Rect); return (Rect.right - Rect.left); } int GetWindowHeight(HWND hwnd) { RECT Rect; GetWindowRect(hwnd, &Rect); return (Rect.bottom - Rect.top); } int GetClientWindowWidth(HWND hwnd) { RECT Rect; GetClientRect(hwnd, &Rect); return (Rect.right - Rect.left); } int GetClientWindowHeight(HWND hwnd) { RECT Rect; GetClientRect(hwnd, &Rect); return (Rect.bottom - Rect.top); } VOID CopyTextToClipboard(LPCWSTR lpszText) { HRESULT hr; if (OpenClipboard(NULL)) { HGLOBAL ClipBuffer; WCHAR *Buffer; DWORD cchBuffer; EmptyClipboard(); cchBuffer = wcslen(lpszText) + 1; ClipBuffer = GlobalAlloc(GMEM_DDESHARE, cchBuffer * sizeof(WCHAR)); Buffer = (PWCHAR)GlobalLock(ClipBuffer); hr = StringCchCopyW(Buffer, cchBuffer, lpszText); GlobalUnlock(ClipBuffer); if (SUCCEEDED(hr)) SetClipboardData(CF_UNICODETEXT, ClipBuffer); CloseClipboard(); } } VOID SetWelcomeText(VOID) { WCHAR szText[MAX_STR_LEN*3]; LoadStringW(hInst, IDS_WELCOME_TITLE, szText, sizeof(szText) / sizeof(WCHAR)); NewRichEditText(szText, CFE_BOLD); LoadStringW(hInst, IDS_WELCOME_TEXT, szText, sizeof(szText) / sizeof(WCHAR)); InsertRichEditText(szText, 0); LoadStringW(hInst, IDS_WELCOME_URL, szText, sizeof(szText) / sizeof(WCHAR)); InsertRichEditText(szText, CFM_LINK); } VOID ShowPopupMenu(HWND hwnd, UINT MenuID, UINT DefaultItem) { HMENU hMenu = NULL; HMENU hPopupMenu; MENUITEMINFO mii; POINT pt; if (MenuID) { hMenu = LoadMenuW(hInst, MAKEINTRESOURCEW(MenuID)); hPopupMenu = GetSubMenu(hMenu, 0); } else hPopupMenu = GetMenu(hwnd); ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STATE; GetMenuItemInfo(hPopupMenu, DefaultItem, FALSE, &mii); if (!(mii.fState & MFS_GRAYED)) SetMenuDefaultItem(hPopupMenu, DefaultItem, FALSE); GetCursorPos(&pt); SetForegroundWindow(hwnd); TrackPopupMenu(hPopupMenu, 0, pt.x, pt.y, 0, hMainWnd, NULL); if (hMenu) DestroyMenu(hMenu); } BOOL StartProcess(LPWSTR lpPath, BOOL Wait) { PROCESS_INFORMATION pi; STARTUPINFOW si; DWORD dwRet; MSG msg; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_SHOW; if (!CreateProcessW(NULL, lpPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { return FALSE; } CloseHandle(pi.hThread); if (Wait) EnableWindow(hMainWnd, FALSE); while (Wait) { dwRet = MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLEVENTS); if (dwRet == WAIT_OBJECT_0 + 1) { while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else { if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_FAILED) break; } } CloseHandle(pi.hProcess); if (Wait) { EnableWindow(hMainWnd, TRUE); SetForegroundWindow(hMainWnd); SetFocus(hMainWnd); } return TRUE; } BOOL GetStorageDirectory(PWCHAR lpDirectory, DWORD cch) { if (cch < MAX_PATH) return FALSE; if (!SHGetSpecialFolderPathW(NULL, lpDirectory, CSIDL_LOCAL_APPDATA, TRUE)) return FALSE; if (FAILED(StringCchCatW(lpDirectory, cch, L"\\rapps"))) return FALSE; if (!CreateDirectoryW(lpDirectory, NULL) && GetLastError() != ERROR_ALREADY_EXISTS) { return FALSE; } return TRUE; } BOOL ExtractFilesFromCab(LPWSTR lpCabName, LPWSTR lpOutputPath) { HINSTANCE hCabinetDll; CHAR szCabName[MAX_PATH]; SESSION Dest; HRESULT Result; hCabinetDll = LoadLibraryW(L"cabinet.dll"); if (hCabinetDll) { pfnExtract = (fnExtract) GetProcAddress(hCabinetDll, "Extract"); if (pfnExtract) { ZeroMemory(&Dest, sizeof(SESSION)); WideCharToMultiByte(CP_ACP, 0, lpOutputPath, -1, Dest.Destination, MAX_PATH, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, lpCabName, -1, szCabName, MAX_PATH, NULL, NULL); Dest.Operation = EXTRACT_FILLFILELIST; Result = pfnExtract(&Dest, szCabName); if (Result == S_OK) { Dest.Operation = EXTRACT_EXTRACTFILES; Result = pfnExtract(&Dest, szCabName); if (Result == S_OK) { FreeLibrary(hCabinetDll); return TRUE; } } } FreeLibrary(hCabinetDll); } return FALSE; } VOID InitLogs(VOID) { WCHAR szBuf[MAX_PATH] = L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager"; WCHAR szPath[MAX_PATH]; DWORD dwCategoryNum = 1; DWORD dwDisp, dwData; HKEY hKey; if (!SettingsInfo.bLogEnabled) return; if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szBuf, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp) != ERROR_SUCCESS) { return; } if (!GetModuleFileName(NULL, szPath, sizeof(szPath) / sizeof(szPath[0]))) return; if (RegSetValueExW(hKey, L"EventMessageFile", 0, REG_EXPAND_SZ, (LPBYTE)szPath, (DWORD)(wcslen(szPath) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) { RegCloseKey(hKey); return; } dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; if (RegSetValueExW(hKey, L"TypesSupported", 0, REG_DWORD, (LPBYTE)&dwData, sizeof(DWORD)) != ERROR_SUCCESS) { RegCloseKey(hKey); return; } if (RegSetValueExW(hKey, L"CategoryMessageFile", 0, REG_EXPAND_SZ, (LPBYTE)szPath, (DWORD)(wcslen(szPath) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) { RegCloseKey(hKey); return; } if (RegSetValueExW(hKey, L"CategoryCount", 0, REG_DWORD, (LPBYTE)&dwCategoryNum, sizeof(DWORD)) != ERROR_SUCCESS) { RegCloseKey(hKey); return; } RegCloseKey(hKey); hLog = RegisterEventSourceW(NULL, L"ReactOS Application Manager"); } VOID FreeLogs(VOID) { if (hLog) DeregisterEventSource(hLog); } BOOL WriteLogMessage(WORD wType, DWORD dwEventID, LPWSTR lpMsg) { if (!SettingsInfo.bLogEnabled) return TRUE; if (!ReportEventW(hLog, wType, 0, dwEventID, NULL, 1, 0, (LPCWSTR*)&lpMsg, NULL)) { return FALSE; } return TRUE; } LPWSTR GetINIFullPath(LPCWSTR lpFileName) { WCHAR szDir[MAX_PATH]; static WCHAR szBuffer[MAX_PATH]; GetStorageDirectory(szDir, _countof(szDir)); StringCbPrintfW(szBuffer, sizeof(szBuffer), L"%ls\\rapps\\%ls", szDir, lpFileName); return szBuffer; } UINT ParserGetString(LPCWSTR lpKeyName, LPWSTR lpReturnedString, UINT nSize, LPCWSTR lpFileName) { PWSTR lpFullFileName = GetINIFullPath(lpFileName); DWORD dwResult; /* we don't have cached section strings for the current system language, create them */ if(bCachedSectionStatus == FALSE) { WCHAR szLocale[4 + 1]; DWORD len; /* find out what is the current system lang code (e.g. "0a") and append it to SectionLocale */ GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE, szLocale, _countof(szLocale)); StringCbCatW(szCachedINISectionLocale, sizeof(szCachedINISectionLocale), szLocale); /* copy the locale-dependent string into the buffer of the future neutral one */ StringCbCopyW(szCachedINISectionLocaleNeutral, sizeof(szCachedINISectionLocaleNeutral), szCachedINISectionLocale); /* turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part */ len = wcslen(szCachedINISectionLocale); memmove((szCachedINISectionLocaleNeutral + len) - 4, (szCachedINISectionLocaleNeutral + len) - 2, (2 * sizeof(WCHAR)) + sizeof(UNICODE_NULL)); /* finally, mark us as cache-friendly for the next time */ bCachedSectionStatus = TRUE; } /* 1st - find localized strings (e.g. "Section.0c0a") */ dwResult = GetPrivateProfileStringW(szCachedINISectionLocale, lpKeyName, NULL, lpReturnedString, nSize, lpFullFileName); if (dwResult != 0) return TRUE; /* 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a") */ dwResult = GetPrivateProfileStringW(szCachedINISectionLocaleNeutral, lpKeyName, NULL, lpReturnedString, nSize, lpFullFileName); if (dwResult != 0) return TRUE; /* 3rd - if they weren't present fallback to standard english strings (just "Section") */ dwResult = GetPrivateProfileStringW(L"Section", lpKeyName, NULL, lpReturnedString, nSize, lpFullFileName); return (dwResult != 0 ? TRUE : FALSE); } UINT ParserGetInt(LPCWSTR lpKeyName, LPCWSTR lpFileName) { WCHAR Buffer[30]; UNICODE_STRING BufferW; ULONG Result; /* grab the text version of our entry */ if (!ParserGetString(lpKeyName, Buffer, _countof(Buffer), lpFileName)) return FALSE; if (!Buffer[0]) return FALSE; /* convert it to an actual integer */ RtlInitUnicodeString(&BufferW, Buffer); RtlUnicodeStringToInteger(&BufferW, 0, &Result); return Result; }