2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/rapps/misc.cpp
5 * PURPOSE: Misc functions
6 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
7 * Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
11 #include <atlsimpcoll.h>
14 /* SESSION Operation */
15 #define EXTRACT_FILLFILELIST 0x00000001
16 #define EXTRACT_EXTRACTFILES 0x00000002
18 static HANDLE hLog
= NULL
;
19 WCHAR szCachedINISectionLocale
[MAX_PATH
] = L
"Section.";
20 WCHAR szCachedINISectionLocaleNeutral
[MAX_PATH
] = {0};
21 BYTE bCachedSectionStatus
= FALSE
;
23 #define STR_VERSION_CURRENT L"CURRENT"
35 struct FILELIST
*next
;
43 struct FILELIST
*FileList
;
46 CHAR Destination
[MAX_PATH
];
47 CHAR CurrentFile
[MAX_PATH
];
48 CHAR Reserved
[MAX_PATH
];
49 struct FILELIST
*FilterList
;
52 typedef HRESULT(WINAPI
*fnExtract
)(SESSION
*dest
, LPCSTR szCabName
);
57 GetSystemColorDepth(VOID
)
62 pDevMode
.dmSize
= sizeof(pDevMode
);
63 pDevMode
.dmDriverExtra
= 0;
65 if (!EnumDisplaySettings(NULL
, ENUM_CURRENT_SETTINGS
, &pDevMode
))
67 /* TODO: Error message */
71 switch (pDevMode
.dmBitsPerPel
)
73 case 32: ColorDepth
= ILC_COLOR32
; break;
74 case 24: ColorDepth
= ILC_COLOR24
; break;
75 case 16: ColorDepth
= ILC_COLOR16
; break;
76 case 8: ColorDepth
= ILC_COLOR8
; break;
77 case 4: ColorDepth
= ILC_COLOR4
; break;
78 default: ColorDepth
= ILC_COLOR
; break;
85 GetWindowWidth(HWND hwnd
)
89 GetWindowRect(hwnd
, &Rect
);
90 return (Rect
.right
- Rect
.left
);
94 GetWindowHeight(HWND hwnd
)
98 GetWindowRect(hwnd
, &Rect
);
99 return (Rect
.bottom
- Rect
.top
);
103 GetClientWindowWidth(HWND hwnd
)
107 GetClientRect(hwnd
, &Rect
);
108 return (Rect
.right
- Rect
.left
);
112 GetClientWindowHeight(HWND hwnd
)
116 GetClientRect(hwnd
, &Rect
);
117 return (Rect
.bottom
- Rect
.top
);
121 CopyTextToClipboard(LPCWSTR lpszText
)
125 if (OpenClipboard(NULL
))
132 cchBuffer
= wcslen(lpszText
) + 1;
133 ClipBuffer
= GlobalAlloc(GMEM_DDESHARE
, cchBuffer
* sizeof(WCHAR
));
134 Buffer
= (PWCHAR
)GlobalLock(ClipBuffer
);
135 hr
= StringCchCopyW(Buffer
, cchBuffer
, lpszText
);
136 GlobalUnlock(ClipBuffer
);
139 SetClipboardData(CF_UNICODETEXT
, ClipBuffer
);
148 WCHAR szText
[MAX_STR_LEN
*3];
150 LoadStringW(hInst
, IDS_WELCOME_TITLE
, szText
, _countof(szText
));
151 NewRichEditText(szText
, CFE_BOLD
);
153 LoadStringW(hInst
, IDS_WELCOME_TEXT
, szText
, _countof(szText
));
154 InsertRichEditText(szText
, 0);
156 LoadStringW(hInst
, IDS_WELCOME_URL
, szText
, _countof(szText
));
157 InsertRichEditText(szText
, CFM_LINK
);
161 ShowPopupMenu(HWND hwnd
, UINT MenuID
, UINT DefaultItem
)
170 hMenu
= LoadMenuW(hInst
, MAKEINTRESOURCEW(MenuID
));
171 hPopupMenu
= GetSubMenu(hMenu
, 0);
174 hPopupMenu
= GetMenu(hwnd
);
176 ZeroMemory(&mii
, sizeof(mii
));
177 mii
.cbSize
= sizeof(mii
);
178 mii
.fMask
= MIIM_STATE
;
179 GetMenuItemInfo(hPopupMenu
, DefaultItem
, FALSE
, &mii
);
181 if (!(mii
.fState
& MFS_GRAYED
))
182 SetMenuDefaultItem(hPopupMenu
, DefaultItem
, FALSE
);
186 SetForegroundWindow(hwnd
);
187 TrackPopupMenu(hPopupMenu
, 0, pt
.x
, pt
.y
, 0, hMainWnd
, NULL
);
194 StartProcess(LPWSTR lpPath
, BOOL Wait
)
196 PROCESS_INFORMATION pi
;
201 ZeroMemory(&si
, sizeof(si
));
203 si
.dwFlags
= STARTF_USESHOWWINDOW
;
204 si
.wShowWindow
= SW_SHOW
;
206 if (!CreateProcessW(NULL
, lpPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
211 CloseHandle(pi
.hThread
);
212 if (Wait
) EnableWindow(hMainWnd
, FALSE
);
216 dwRet
= MsgWaitForMultipleObjects(1, &pi
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
217 if (dwRet
== WAIT_OBJECT_0
+ 1)
219 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
221 TranslateMessage(&msg
);
222 DispatchMessage(&msg
);
227 if (dwRet
== WAIT_OBJECT_0
|| dwRet
== WAIT_FAILED
)
232 CloseHandle(pi
.hProcess
);
236 EnableWindow(hMainWnd
, TRUE
);
237 SetForegroundWindow(hMainWnd
);
245 GetStorageDirectory(PWCHAR lpDirectory
, DWORD cch
)
250 if (!SHGetSpecialFolderPathW(NULL
, lpDirectory
, CSIDL_LOCAL_APPDATA
, TRUE
))
253 if (FAILED(StringCchCatW(lpDirectory
, cch
, L
"\\rapps")))
256 if (!CreateDirectoryW(lpDirectory
, NULL
) &&
257 GetLastError() != ERROR_ALREADY_EXISTS
)
266 ExtractFilesFromCab(LPWSTR lpCabName
, LPWSTR lpOutputPath
)
268 HINSTANCE hCabinetDll
;
269 CHAR szCabName
[MAX_PATH
];
273 hCabinetDll
= LoadLibraryW(L
"cabinet.dll");
276 pfnExtract
= (fnExtract
) GetProcAddress(hCabinetDll
, "Extract");
279 ZeroMemory(&Dest
, sizeof(Dest
));
281 WideCharToMultiByte(CP_ACP
, 0, lpOutputPath
, -1, Dest
.Destination
, MAX_PATH
, NULL
, NULL
);
282 WideCharToMultiByte(CP_ACP
, 0, lpCabName
, -1, szCabName
, MAX_PATH
, NULL
, NULL
);
283 Dest
.Operation
= EXTRACT_FILLFILELIST
;
285 Result
= pfnExtract(&Dest
, szCabName
);
288 Dest
.Operation
= EXTRACT_EXTRACTFILES
;
289 Result
= pfnExtract(&Dest
, szCabName
);
292 FreeLibrary(hCabinetDll
);
297 FreeLibrary(hCabinetDll
);
306 WCHAR szBuf
[MAX_PATH
] = L
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager";
307 WCHAR szPath
[MAX_PATH
];
308 DWORD dwCategoryNum
= 1;
309 DWORD dwDisp
, dwData
;
312 if (!SettingsInfo
.bLogEnabled
) return;
314 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
316 REG_OPTION_NON_VOLATILE
,
317 KEY_WRITE
, NULL
, &hKey
, &dwDisp
) != ERROR_SUCCESS
)
322 if (!GetModuleFileNameW(NULL
, szPath
, _countof(szPath
)))
325 if (RegSetValueExW(hKey
,
330 (DWORD
)(wcslen(szPath
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
336 dwData
= EVENTLOG_ERROR_TYPE
| EVENTLOG_WARNING_TYPE
|
337 EVENTLOG_INFORMATION_TYPE
;
339 if (RegSetValueExW(hKey
,
344 sizeof(DWORD
)) != ERROR_SUCCESS
)
350 if (RegSetValueExW(hKey
,
351 L
"CategoryMessageFile",
355 (DWORD
)(wcslen(szPath
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
361 if (RegSetValueExW(hKey
,
365 (LPBYTE
)&dwCategoryNum
,
366 sizeof(DWORD
)) != ERROR_SUCCESS
)
374 hLog
= RegisterEventSourceW(NULL
, L
"ReactOS Application Manager");
381 if (hLog
) DeregisterEventSource(hLog
);
386 WriteLogMessage(WORD wType
, DWORD dwEventID
, LPWSTR lpMsg
)
388 if (!SettingsInfo
.bLogEnabled
) return TRUE
;
390 if (!ReportEventW(hLog
,
407 LPWSTR
GetINIFullPath(LPCWSTR lpFileName
)
409 WCHAR szDir
[MAX_PATH
];
410 static WCHAR szBuffer
[MAX_PATH
];
412 GetStorageDirectory(szDir
, _countof(szDir
));
413 StringCbPrintfW(szBuffer
, sizeof(szBuffer
), L
"%ls\\rapps\\%ls", szDir
, lpFileName
);
419 UINT
ParserGetString(LPCWSTR lpKeyName
, LPWSTR lpReturnedString
, UINT nSize
, LPCWSTR lpFileName
)
421 PWSTR lpFullFileName
= GetINIFullPath(lpFileName
);
424 /* we don't have cached section strings for the current system language, create them */
425 if(bCachedSectionStatus
== FALSE
)
427 WCHAR szLocale
[4 + 1];
430 /* find out what is the current system lang code (e.g. "0a") and append it to SectionLocale */
431 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE
,
432 szLocale
, _countof(szLocale
));
434 StringCbCatW(szCachedINISectionLocale
, sizeof(szCachedINISectionLocale
), szLocale
);
436 /* copy the locale-dependent string into the buffer of the future neutral one */
437 StringCbCopyW(szCachedINISectionLocaleNeutral
,
438 sizeof(szCachedINISectionLocaleNeutral
),
439 szCachedINISectionLocale
);
441 /* turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part */
442 len
= wcslen(szCachedINISectionLocale
);
444 memmove((szCachedINISectionLocaleNeutral
+ len
) - 4,
445 (szCachedINISectionLocaleNeutral
+ len
) - 2,
446 (2 * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
));
448 /* finally, mark us as cache-friendly for the next time */
449 bCachedSectionStatus
= TRUE
;
452 /* 1st - find localized strings (e.g. "Section.0c0a") */
453 dwResult
= GetPrivateProfileStringW(szCachedINISectionLocale
,
463 /* 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a") */
464 dwResult
= GetPrivateProfileStringW(szCachedINISectionLocaleNeutral
,
474 /* 3rd - if they weren't present fallback to standard english strings (just "Section") */
475 dwResult
= GetPrivateProfileStringW(L
"Section",
482 return (dwResult
!= 0 ? TRUE
: FALSE
);
485 UINT
ParserGetInt(LPCWSTR lpKeyName
, LPCWSTR lpFileName
)
488 UNICODE_STRING BufferW
;
491 /* grab the text version of our entry */
492 if (!ParserGetString(lpKeyName
, Buffer
, _countof(Buffer
), lpFileName
))
498 /* convert it to an actual integer */
499 RtlInitUnicodeString(&BufferW
, Buffer
);
500 RtlUnicodeStringToInteger(&BufferW
, 0, &Result
);
505 template<typename XCHAR
>
506 inline BOOL
IsCharNumeric(XCHAR ch
)
508 return IsCharAlphaNumeric(ch
) && !IsCharAlpha(ch
);
512 //Parses version string that can be formatted as 1.2.3-4b (or CURRENT)
513 //Returns int buffer and it's size
515 ParseVersion(_In_z_ LPCWSTR szVersion
, _Outptr_ PVERSION_INFO Version
)
517 ATL::CStringW szVersionSingleInt
= L
"";
518 BOOL bHasParsed
= TRUE
;
519 INT VersionCharCount
= 0;
520 INT VersionLength
= lstrlenW(szVersion
);
521 StringCbCopyW(Version
->szVersion
, VersionLength
* sizeof(szVersion
), szVersion
);
523 if (!StrCmpW(szVersion
, STR_VERSION_CURRENT
))
525 Version
->VersionSize
= NULL
;
529 Version
->VersionSize
= 0;
530 //int expected every iteration, quit the loop if its not a number
531 while (Version
->VersionSize
< MAX_VERSION
532 && IsCharNumeric(szVersion
[VersionCharCount
])
533 && VersionCharCount
< VersionLength
)
535 for (; IsCharNumeric(szVersion
[VersionCharCount
]) && VersionCharCount
< VersionLength
; ++VersionCharCount
)
537 szVersionSingleInt
+= szVersion
[VersionCharCount
];
539 if (szVersionSingleInt
.IsEmpty())
544 INT IntResult
= StrToIntW(szVersionSingleInt
.GetBuffer());
545 Version
->arrVersion
[Version
->VersionSize
] = IntResult
;
546 ++Version
->VersionSize
;
547 szVersionSingleInt
.Empty();
551 if (IsCharAlphaW(szVersion
[VersionCharCount
]))
553 Version
->cVersionSuffix
= szVersion
[VersionCharCount
];
556 Version
->cVersionSuffix
= NULL
;
561 //In: Zero terminated strings of versions
562 //Out: TRUE if first is bigger than second, FALSE if else
564 CompareVersionsStrings(_In_z_ LPCWSTR sczVersionLeft
, _In_z_ LPCWSTR sczVersionRight
)
566 VERSION_INFO LeftVersion
, RightVersion
;
568 if (!ParseVersion(sczVersionLeft
, &LeftVersion
)
569 || !ParseVersion(sczVersionRight
, &RightVersion
))
574 return CompareVersions(&LeftVersion
, &RightVersion
);
578 CompareVersions(_In_ PVERSION_INFO LeftVersion
, _In_ PVERSION_INFO RightVersion
)
581 if (!LeftVersion
->VersionSize
|| !RightVersion
->VersionSize
)
586 INT SizeDiff
= LeftVersion
->VersionSize
- RightVersion
->VersionSize
;
596 for (INT i
= 0; i
< LeftVersion
->VersionSize
&& i
< RightVersion
->VersionSize
&& i
< MAX_VERSION
; ++i
)
598 if (LeftVersion
->arrVersion
[i
] > RightVersion
->arrVersion
[i
])
602 if (LeftVersion
->arrVersion
[i
] < RightVersion
->arrVersion
[i
])
608 if (LeftVersion
->cVersionSuffix
> RightVersion
->cVersionSuffix
)