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)
8 * Alexander Shaposhnikov (chaez.san@gmail.com)
15 /* SESSION Operation */
16 #define EXTRACT_FILLFILELIST 0x00000001
17 #define EXTRACT_EXTRACTFILES 0x00000002
19 static HANDLE hLog
= NULL
;
42 CHAR Destination
[MAX_PATH
];
43 CHAR CurrentFile
[MAX_PATH
];
44 CHAR Reserved
[MAX_PATH
];
48 typedef HRESULT(WINAPI
*fnExtract
)(SESSION
*dest
, LPCSTR szCabName
);
51 INT
GetWindowWidth(HWND hwnd
)
55 GetWindowRect(hwnd
, &Rect
);
56 return (Rect
.right
- Rect
.left
);
59 INT
GetWindowHeight(HWND hwnd
)
63 GetWindowRect(hwnd
, &Rect
);
64 return (Rect
.bottom
- Rect
.top
);
67 INT
GetClientWindowWidth(HWND hwnd
)
71 GetClientRect(hwnd
, &Rect
);
72 return (Rect
.right
- Rect
.left
);
75 INT
GetClientWindowHeight(HWND hwnd
)
79 GetClientRect(hwnd
, &Rect
);
80 return (Rect
.bottom
- Rect
.top
);
83 VOID
CopyTextToClipboard(LPCWSTR lpszText
)
85 if (!OpenClipboard(NULL
))
96 cchBuffer
= wcslen(lpszText
) + 1;
97 ClipBuffer
= GlobalAlloc(GMEM_DDESHARE
, cchBuffer
* sizeof(WCHAR
));
99 Buffer
= (PWCHAR
) GlobalLock(ClipBuffer
);
100 hr
= StringCchCopyW(Buffer
, cchBuffer
, lpszText
);
101 GlobalUnlock(ClipBuffer
);
104 SetClipboardData(CF_UNICODETEXT
, ClipBuffer
);
109 VOID
SetWelcomeText()
111 ATL::CStringW szText
;
113 szText
.LoadStringW(hInst
, IDS_WELCOME_TITLE
);
114 NewRichEditText(szText
, CFE_BOLD
);
116 szText
.LoadStringW(hInst
, IDS_WELCOME_TEXT
);
117 InsertRichEditText(szText
, 0);
119 szText
.LoadStringW(hInst
, IDS_WELCOME_URL
);
120 InsertRichEditText(szText
, CFM_LINK
);
123 VOID
ShowPopupMenu(HWND hwnd
, UINT MenuID
, UINT DefaultItem
)
127 MENUITEMINFO ItemInfo
;
132 hMenu
= LoadMenuW(hInst
, MAKEINTRESOURCEW(MenuID
));
133 hPopupMenu
= GetSubMenu(hMenu
, 0);
137 hPopupMenu
= GetMenu(hwnd
);
140 ZeroMemory(&ItemInfo
, sizeof(ItemInfo
));
141 ItemInfo
.cbSize
= sizeof(ItemInfo
);
142 ItemInfo
.fMask
= MIIM_STATE
;
144 GetMenuItemInfoW(hPopupMenu
, DefaultItem
, FALSE
, &ItemInfo
);
146 if (!(ItemInfo
.fState
& MFS_GRAYED
))
148 SetMenuDefaultItem(hPopupMenu
, DefaultItem
, FALSE
);
153 SetForegroundWindow(hwnd
);
154 TrackPopupMenu(hPopupMenu
, 0, pt
.x
, pt
.y
, 0, hMainWnd
, NULL
);
162 BOOL
StartProcess(ATL::CStringW
&Path
, BOOL Wait
)
164 return StartProcess(const_cast<LPWSTR
>(Path
.GetString()), Wait
);;
167 BOOL
StartProcess(LPWSTR lpPath
, BOOL Wait
)
169 PROCESS_INFORMATION pi
;
174 ZeroMemory(&si
, sizeof(si
));
176 si
.dwFlags
= STARTF_USESHOWWINDOW
;
177 si
.wShowWindow
= SW_SHOW
;
179 if (!CreateProcessW(NULL
, lpPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
184 CloseHandle(pi
.hThread
);
188 EnableWindow(hMainWnd
, FALSE
);
193 dwRet
= MsgWaitForMultipleObjects(1, &pi
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
194 if (dwRet
== WAIT_OBJECT_0
+ 1)
196 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
198 TranslateMessage(&msg
);
199 DispatchMessageW(&msg
);
204 if (dwRet
== WAIT_OBJECT_0
|| dwRet
== WAIT_FAILED
)
209 CloseHandle(pi
.hProcess
);
213 EnableWindow(hMainWnd
, TRUE
);
214 SetForegroundWindow(hMainWnd
);
221 BOOL
GetStorageDirectory(ATL::CStringW
& Directory
)
223 if (!SHGetSpecialFolderPathW(NULL
, Directory
.GetBuffer(MAX_PATH
), CSIDL_LOCAL_APPDATA
, TRUE
))
225 Directory
.ReleaseBuffer();
229 Directory
.ReleaseBuffer();
230 Directory
+= L
"\\rapps";
232 return (CreateDirectoryW(Directory
.GetString(), NULL
) || GetLastError() == ERROR_ALREADY_EXISTS
);
235 BOOL
ExtractFilesFromCab(const ATL::CStringW
&CabName
, const ATL::CStringW
&OutputPath
)
237 return ExtractFilesFromCab(CabName
.GetString(), OutputPath
.GetString());
240 BOOL
ExtractFilesFromCab(LPCWSTR lpCabName
, LPCWSTR lpOutputPath
)
242 HINSTANCE hCabinetDll
;
243 CHAR szCabName
[MAX_PATH
];
247 hCabinetDll
= LoadLibraryW(L
"cabinet.dll");
250 pfnExtract
= (fnExtract
) GetProcAddress(hCabinetDll
, "Extract");
253 ZeroMemory(&Dest
, sizeof(Dest
));
255 WideCharToMultiByte(CP_ACP
, 0, lpOutputPath
, -1, Dest
.Destination
, MAX_PATH
, NULL
, NULL
);
256 WideCharToMultiByte(CP_ACP
, 0, lpCabName
, -1, szCabName
, MAX_PATH
, NULL
, NULL
);
257 Dest
.Operation
= EXTRACT_FILLFILELIST
;
259 Result
= pfnExtract(&Dest
, szCabName
);
262 Dest
.Operation
= EXTRACT_EXTRACTFILES
;
263 CreateDirectoryW(lpOutputPath
, NULL
);
265 Result
= pfnExtract(&Dest
, szCabName
);
268 FreeLibrary(hCabinetDll
);
273 FreeLibrary(hCabinetDll
);
281 if (!SettingsInfo
.bLogEnabled
)
286 WCHAR szPath
[MAX_PATH
];
287 DWORD dwCategoryNum
= 1;
288 DWORD dwDisp
, dwData
;
291 if (key
.Create(HKEY_LOCAL_MACHINE
,
292 L
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager",
293 REG_NONE
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &dwDisp
) != ERROR_SUCCESS
)
298 if (!GetModuleFileNameW(NULL
, szPath
, _countof(szPath
)))
303 dwData
= EVENTLOG_ERROR_TYPE
| EVENTLOG_WARNING_TYPE
|
304 EVENTLOG_INFORMATION_TYPE
;
306 if ((key
.SetStringValue(L
"EventMessageFile",
308 REG_EXPAND_SZ
) == ERROR_SUCCESS
)
309 && (key
.SetStringValue(L
"CategoryMessageFile",
311 REG_EXPAND_SZ
) == ERROR_SUCCESS
)
312 && (key
.SetDWORDValue(L
"TypesSupported",
313 dwData
) == ERROR_SUCCESS
)
314 && (key
.SetDWORDValue(L
"CategoryCount",
315 dwCategoryNum
) == ERROR_SUCCESS
))
318 hLog
= RegisterEventSourceW(NULL
, L
"ReactOS Application Manager");
329 DeregisterEventSource(hLog
);
334 BOOL
WriteLogMessage(WORD wType
, DWORD dwEventID
, LPCWSTR lpMsg
)
336 if (!SettingsInfo
.bLogEnabled
)
341 if (!ReportEventW(hLog
, wType
, 0, dwEventID
,
342 NULL
, 1, 0, &lpMsg
, NULL
))
350 BOOL
GetInstalledVersion_WowUser(ATL::CStringW
* szVersionResult
,
351 const ATL::CStringW
& RegName
,
355 BOOL bHasSucceded
= FALSE
;
357 ATL::CStringW szVersion
;
358 ATL::CStringW szPath
= L
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + RegName
;
360 if (key
.Open(IsUserKey
? HKEY_CURRENT_USER
: HKEY_LOCAL_MACHINE
,
362 keyWow
| KEY_READ
) != ERROR_SUCCESS
)
367 if (szVersionResult
!= NULL
)
369 ULONG dwSize
= MAX_PATH
* sizeof(WCHAR
);
371 if (key
.QueryStringValue(L
"DisplayVersion",
372 szVersion
.GetBuffer(MAX_PATH
),
373 &dwSize
) == ERROR_SUCCESS
)
375 szVersion
.ReleaseBuffer();
376 *szVersionResult
= szVersion
;
381 szVersion
.ReleaseBuffer();
387 szVersion
.ReleaseBuffer();
394 BOOL
GetInstalledVersion(ATL::CStringW
*pszVersion
, const ATL::CStringW
&szRegName
)
396 return (!szRegName
.IsEmpty()
397 && (GetInstalledVersion_WowUser(pszVersion
, szRegName
, TRUE
, KEY_WOW64_32KEY
)
398 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, FALSE
, KEY_WOW64_32KEY
)
399 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, TRUE
, KEY_WOW64_64KEY
)
400 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, FALSE
, KEY_WOW64_64KEY
)));
404 ATL::CStringW
CConfigParser::m_szLocaleID
;
405 ATL::CStringW
CConfigParser::m_szCachedINISectionLocale
;
406 ATL::CStringW
CConfigParser::m_szCachedINISectionLocaleNeutral
;
408 CConfigParser::CConfigParser(const ATL::CStringW
& FileName
) : szConfigPath(GetINIFullPath(FileName
))
410 // we don't have cached section strings for the current system language, create them, lazy
411 CacheINILocaleLazy();
414 ATL::CStringW
CConfigParser::GetINIFullPath(const ATL::CStringW
& FileName
)
417 ATL::CStringW szBuffer
;
419 GetStorageDirectory(szDir
);
420 szBuffer
.Format(L
"%ls\\rapps\\%ls", szDir
, FileName
);
425 VOID
CConfigParser::CacheINILocaleLazy()
427 if (m_szLocaleID
.IsEmpty())
429 // TODO: Set default locale if call fails
430 // find out what is the current system lang code (e.g. "0a") and append it to SectionLocale
431 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE
,
432 m_szLocaleID
.GetBuffer(m_cchLocaleSize
), m_cchLocaleSize
);
434 m_szLocaleID
.ReleaseBuffer();
435 m_szCachedINISectionLocale
= L
"Section." + m_szLocaleID
;
437 // turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
438 m_szCachedINISectionLocaleNeutral
= m_szCachedINISectionLocale
+ m_szLocaleID
.Right(2);
442 const ATL::CStringW
& CConfigParser::GetLocale()
444 CacheINILocaleLazy();
448 INT
CConfigParser::GetLocaleSize()
450 return m_cchLocaleSize
;
453 UINT
CConfigParser::GetString(const ATL::CStringW
& KeyName
, ATL::CStringW
& ResultString
)
457 LPWSTR ResultStringBuffer
= ResultString
.GetBuffer(MAX_PATH
);
458 // 1st - find localized strings (e.g. "Section.0c0a")
459 dwResult
= GetPrivateProfileStringW(m_szCachedINISectionLocale
.GetString(),
464 szConfigPath
.GetString());
468 // 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a")
469 dwResult
= GetPrivateProfileStringW(m_szCachedINISectionLocaleNeutral
.GetString(),
474 szConfigPath
.GetString());
477 // 3rd - if they weren't present fallback to standard english strings (just "Section")
478 dwResult
= GetPrivateProfileStringW(L
"Section",
483 szConfigPath
.GetString());
487 ResultString
.ReleaseBuffer();
488 return (dwResult
!= 0 ? TRUE
: FALSE
);
491 UINT
CConfigParser::GetInt(const ATL::CStringW
& KeyName
)
493 ATL::CStringW Buffer
;
495 // grab the text version of our entry
496 if (!GetString(KeyName
, Buffer
))
499 if (Buffer
.IsEmpty())
502 // convert it to an actual integer
503 INT result
= StrToIntW(Buffer
.GetString());
505 return (UINT
) (result
<= 0) ? 0 : result
;