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
;
33 struct FILELIST
*next
;
41 struct FILELIST
*FileList
;
44 CHAR Destination
[MAX_PATH
];
45 CHAR CurrentFile
[MAX_PATH
];
46 CHAR Reserved
[MAX_PATH
];
47 struct FILELIST
*FilterList
;
50 typedef HRESULT(WINAPI
*fnExtract
)(SESSION
*dest
, LPCSTR szCabName
);
55 GetSystemColorDepth(VOID
)
60 pDevMode
.dmSize
= sizeof(pDevMode
);
61 pDevMode
.dmDriverExtra
= 0;
63 if (!EnumDisplaySettings(NULL
, ENUM_CURRENT_SETTINGS
, &pDevMode
))
65 /* TODO: Error message */
69 switch (pDevMode
.dmBitsPerPel
)
71 case 32: ColorDepth
= ILC_COLOR32
; break;
72 case 24: ColorDepth
= ILC_COLOR24
; break;
73 case 16: ColorDepth
= ILC_COLOR16
; break;
74 case 8: ColorDepth
= ILC_COLOR8
; break;
75 case 4: ColorDepth
= ILC_COLOR4
; break;
76 default: ColorDepth
= ILC_COLOR
; break;
83 GetWindowWidth(HWND hwnd
)
87 GetWindowRect(hwnd
, &Rect
);
88 return (Rect
.right
- Rect
.left
);
92 GetWindowHeight(HWND hwnd
)
96 GetWindowRect(hwnd
, &Rect
);
97 return (Rect
.bottom
- Rect
.top
);
101 GetClientWindowWidth(HWND hwnd
)
105 GetClientRect(hwnd
, &Rect
);
106 return (Rect
.right
- Rect
.left
);
110 GetClientWindowHeight(HWND hwnd
)
114 GetClientRect(hwnd
, &Rect
);
115 return (Rect
.bottom
- Rect
.top
);
119 CopyTextToClipboard(LPCWSTR lpszText
)
123 if (OpenClipboard(NULL
))
130 cchBuffer
= wcslen(lpszText
) + 1;
131 ClipBuffer
= GlobalAlloc(GMEM_DDESHARE
, cchBuffer
* sizeof(WCHAR
));
132 Buffer
= (PWCHAR
)GlobalLock(ClipBuffer
);
133 hr
= StringCchCopyW(Buffer
, cchBuffer
, lpszText
);
134 GlobalUnlock(ClipBuffer
);
137 SetClipboardData(CF_UNICODETEXT
, ClipBuffer
);
146 WCHAR szText
[MAX_STR_LEN
*3];
148 LoadStringW(hInst
, IDS_WELCOME_TITLE
, szText
, _countof(szText
));
149 NewRichEditText(szText
, CFE_BOLD
);
151 LoadStringW(hInst
, IDS_WELCOME_TEXT
, szText
, _countof(szText
));
152 InsertRichEditText(szText
, 0);
154 LoadStringW(hInst
, IDS_WELCOME_URL
, szText
, _countof(szText
));
155 InsertRichEditText(szText
, CFM_LINK
);
159 ShowPopupMenu(HWND hwnd
, UINT MenuID
, UINT DefaultItem
)
168 hMenu
= LoadMenuW(hInst
, MAKEINTRESOURCEW(MenuID
));
169 hPopupMenu
= GetSubMenu(hMenu
, 0);
172 hPopupMenu
= GetMenu(hwnd
);
174 ZeroMemory(&mii
, sizeof(mii
));
175 mii
.cbSize
= sizeof(mii
);
176 mii
.fMask
= MIIM_STATE
;
177 GetMenuItemInfo(hPopupMenu
, DefaultItem
, FALSE
, &mii
);
179 if (!(mii
.fState
& MFS_GRAYED
))
180 SetMenuDefaultItem(hPopupMenu
, DefaultItem
, FALSE
);
184 SetForegroundWindow(hwnd
);
185 TrackPopupMenu(hPopupMenu
, 0, pt
.x
, pt
.y
, 0, hMainWnd
, NULL
);
192 StartProcess(LPWSTR lpPath
, BOOL Wait
)
194 PROCESS_INFORMATION pi
;
199 ZeroMemory(&si
, sizeof(si
));
201 si
.dwFlags
= STARTF_USESHOWWINDOW
;
202 si
.wShowWindow
= SW_SHOW
;
204 if (!CreateProcessW(NULL
, lpPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
209 CloseHandle(pi
.hThread
);
210 if (Wait
) EnableWindow(hMainWnd
, FALSE
);
214 dwRet
= MsgWaitForMultipleObjects(1, &pi
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
215 if (dwRet
== WAIT_OBJECT_0
+ 1)
217 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
219 TranslateMessage(&msg
);
220 DispatchMessage(&msg
);
225 if (dwRet
== WAIT_OBJECT_0
|| dwRet
== WAIT_FAILED
)
230 CloseHandle(pi
.hProcess
);
234 EnableWindow(hMainWnd
, TRUE
);
235 SetForegroundWindow(hMainWnd
);
243 GetStorageDirectory(PWCHAR lpDirectory
, DWORD cch
)
248 if (!SHGetSpecialFolderPathW(NULL
, lpDirectory
, CSIDL_LOCAL_APPDATA
, TRUE
))
251 if (FAILED(StringCchCatW(lpDirectory
, cch
, L
"\\rapps")))
254 if (!CreateDirectoryW(lpDirectory
, NULL
) &&
255 GetLastError() != ERROR_ALREADY_EXISTS
)
264 ExtractFilesFromCab(LPWSTR lpCabName
, LPWSTR lpOutputPath
)
266 HINSTANCE hCabinetDll
;
267 CHAR szCabName
[MAX_PATH
];
271 hCabinetDll
= LoadLibraryW(L
"cabinet.dll");
274 pfnExtract
= (fnExtract
) GetProcAddress(hCabinetDll
, "Extract");
277 ZeroMemory(&Dest
, sizeof(Dest
));
279 WideCharToMultiByte(CP_ACP
, 0, lpOutputPath
, -1, Dest
.Destination
, MAX_PATH
, NULL
, NULL
);
280 WideCharToMultiByte(CP_ACP
, 0, lpCabName
, -1, szCabName
, MAX_PATH
, NULL
, NULL
);
281 Dest
.Operation
= EXTRACT_FILLFILELIST
;
283 Result
= pfnExtract(&Dest
, szCabName
);
286 Dest
.Operation
= EXTRACT_EXTRACTFILES
;
287 Result
= pfnExtract(&Dest
, szCabName
);
290 FreeLibrary(hCabinetDll
);
295 FreeLibrary(hCabinetDll
);
304 WCHAR szBuf
[MAX_PATH
] = L
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager";
305 WCHAR szPath
[MAX_PATH
];
306 DWORD dwCategoryNum
= 1;
307 DWORD dwDisp
, dwData
;
310 if (!SettingsInfo
.bLogEnabled
) return;
312 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
314 REG_OPTION_NON_VOLATILE
,
315 KEY_WRITE
, NULL
, &hKey
, &dwDisp
) != ERROR_SUCCESS
)
320 if (!GetModuleFileNameW(NULL
, szPath
, _countof(szPath
)))
323 if (RegSetValueExW(hKey
,
328 (DWORD
)(wcslen(szPath
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
334 dwData
= EVENTLOG_ERROR_TYPE
| EVENTLOG_WARNING_TYPE
|
335 EVENTLOG_INFORMATION_TYPE
;
337 if (RegSetValueExW(hKey
,
342 sizeof(DWORD
)) != ERROR_SUCCESS
)
348 if (RegSetValueExW(hKey
,
349 L
"CategoryMessageFile",
353 (DWORD
)(wcslen(szPath
) + 1) * sizeof(WCHAR
)) != ERROR_SUCCESS
)
359 if (RegSetValueExW(hKey
,
363 (LPBYTE
)&dwCategoryNum
,
364 sizeof(DWORD
)) != ERROR_SUCCESS
)
372 hLog
= RegisterEventSourceW(NULL
, L
"ReactOS Application Manager");
379 if (hLog
) DeregisterEventSource(hLog
);
384 WriteLogMessage(WORD wType
, DWORD dwEventID
, LPWSTR lpMsg
)
386 if (!SettingsInfo
.bLogEnabled
) return TRUE
;
388 if (!ReportEventW(hLog
,
405 LPWSTR
GetINIFullPath(LPCWSTR lpFileName
)
407 WCHAR szDir
[MAX_PATH
];
408 static WCHAR szBuffer
[MAX_PATH
];
410 GetStorageDirectory(szDir
, _countof(szDir
));
411 StringCbPrintfW(szBuffer
, sizeof(szBuffer
), L
"%ls\\rapps\\%ls", szDir
, lpFileName
);
417 UINT
ParserGetString(LPCWSTR lpKeyName
, LPWSTR lpReturnedString
, UINT nSize
, LPCWSTR lpFileName
)
419 PWSTR lpFullFileName
= GetINIFullPath(lpFileName
);
422 /* we don't have cached section strings for the current system language, create them */
423 if(bCachedSectionStatus
== FALSE
)
425 WCHAR szLocale
[4 + 1];
428 /* find out what is the current system lang code (e.g. "0a") and append it to SectionLocale */
429 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE
,
430 szLocale
, _countof(szLocale
));
432 StringCbCatW(szCachedINISectionLocale
, sizeof(szCachedINISectionLocale
), szLocale
);
434 /* copy the locale-dependent string into the buffer of the future neutral one */
435 StringCbCopyW(szCachedINISectionLocaleNeutral
,
436 sizeof(szCachedINISectionLocaleNeutral
),
437 szCachedINISectionLocale
);
439 /* turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part */
440 len
= wcslen(szCachedINISectionLocale
);
442 memmove((szCachedINISectionLocaleNeutral
+ len
) - 4,
443 (szCachedINISectionLocaleNeutral
+ len
) - 2,
444 (2 * sizeof(WCHAR
)) + sizeof(UNICODE_NULL
));
446 /* finally, mark us as cache-friendly for the next time */
447 bCachedSectionStatus
= TRUE
;
450 /* 1st - find localized strings (e.g. "Section.0c0a") */
451 dwResult
= GetPrivateProfileStringW(szCachedINISectionLocale
,
461 /* 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a") */
462 dwResult
= GetPrivateProfileStringW(szCachedINISectionLocaleNeutral
,
472 /* 3rd - if they weren't present fallback to standard english strings (just "Section") */
473 dwResult
= GetPrivateProfileStringW(L
"Section",
480 return (dwResult
!= 0 ? TRUE
: FALSE
);
483 UINT
ParserGetInt(LPCWSTR lpKeyName
, LPCWSTR lpFileName
)
486 UNICODE_STRING BufferW
;
489 /* grab the text version of our entry */
490 if (!ParserGetString(lpKeyName
, Buffer
, _countof(Buffer
), lpFileName
))
496 /* convert it to an actual integer */
497 RtlInitUnicodeString(&BufferW
, Buffer
);
498 RtlUnicodeStringToInteger(&BufferW
, 0, &Result
);
503 //Parses version string that can be formatted as 1.2.3.4-5
504 //Returns int buffer and it's size
506 ParseVersion(_In_z_ LPCWSTR szVersion
, _Outptr_ INT
* parrVersion
, _Out_opt_ UINT iVersionSize
)
508 ATL::CSimpleArray
<int> arrVersionResult
;
509 ATL::CStringW szVersionSingleInt
= L
"";
510 ATL::CStringW sDelimiters
= L
".-";
511 BOOL bHasParsed
= TRUE
;
512 INT iVersionCharCount
= 0;
513 //INT iVersionSingleCharCount = 0;
516 while(szVersion
[iVersionCharCount
] != L
'\0')
518 for (;!sDelimiters
.Find(szVersion
[iVersionCharCount
]); ++iVersionCharCount
)
520 szVersionSingleInt
+= szVersion
[iVersionCharCount
];
522 szVersionSingleInt
+= L
'\0';
523 iIntResult
= StrToIntW(szVersionSingleInt
.GetBuffer());
526 arrVersionResult
.Add(iIntResult
);
535 parrVersion
= arrVersionResult
.GetData();
540 //In: Zero terminated strings of versions
541 //Out: TRUE if first is bigger than second, FALSE if else
543 CompareVersionsBigger(_In_z_ LPCWSTR sczVersion1
, _In_z_ LPCWSTR sczVersion2
, _Out_ BOOL bResult
)
545 UINT iVersionSize1
= 0;
546 UINT iVersionSize2
= 0;
547 INT
*parrVersion1
= NULL
, *parrVersion2
= NULL
;
550 if (!ParseVersion(sczVersion1
, parrVersion1
, iVersionSize1
)
551 || !ParseVersion(sczVersion2
, parrVersion2
, iVersionSize2
))
556 for (INT i
= 0; i
< iVersionSize1
&& i
< iVersionSize2
; ++i
)
558 if (parrVersion1
[i
] > parrVersion2
[i
])