2 * PROJECT: ReactOS Applications Manager
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * FILE: base/applications/rapps/misc.cpp
5 * PURPOSE: Misc functions
6 * COPYRIGHT: Copyright 2009 Dmitry Chapyshev (dmitry@reactos.org)
7 * Copyright 2015 Ismael Ferreras Morezuelas (swyterzone+ros@gmail.com)
8 * Copyright 2017 Alexander Shaposhnikov (sanchaez@reactos.org)
15 static HANDLE hLog
= NULL
;
17 INT
GetWindowWidth(HWND hwnd
)
21 GetWindowRect(hwnd
, &Rect
);
22 return (Rect
.right
- Rect
.left
);
25 INT
GetWindowHeight(HWND hwnd
)
29 GetWindowRect(hwnd
, &Rect
);
30 return (Rect
.bottom
- Rect
.top
);
33 INT
GetClientWindowWidth(HWND hwnd
)
37 GetClientRect(hwnd
, &Rect
);
38 return (Rect
.right
- Rect
.left
);
41 INT
GetClientWindowHeight(HWND hwnd
)
45 GetClientRect(hwnd
, &Rect
);
46 return (Rect
.bottom
- Rect
.top
);
49 VOID
CopyTextToClipboard(LPCWSTR lpszText
)
51 if (!OpenClipboard(NULL
))
62 cchBuffer
= wcslen(lpszText
) + 1;
63 ClipBuffer
= GlobalAlloc(GMEM_DDESHARE
, cchBuffer
* sizeof(WCHAR
));
65 Buffer
= (PWCHAR
) GlobalLock(ClipBuffer
);
66 hr
= StringCchCopyW(Buffer
, cchBuffer
, lpszText
);
67 GlobalUnlock(ClipBuffer
);
70 SetClipboardData(CF_UNICODETEXT
, ClipBuffer
);
79 szText
.LoadStringW(IDS_WELCOME_TITLE
);
80 NewRichEditText(szText
, CFE_BOLD
);
82 szText
.LoadStringW(IDS_WELCOME_TEXT
);
83 InsertRichEditText(szText
, 0);
85 szText
.LoadStringW(IDS_WELCOME_URL
);
86 InsertRichEditText(szText
, CFM_LINK
);
89 VOID
ShowPopupMenu(HWND hwnd
, UINT MenuID
, UINT DefaultItem
)
93 MENUITEMINFO ItemInfo
;
98 hMenu
= LoadMenuW(hInst
, MAKEINTRESOURCEW(MenuID
));
99 hPopupMenu
= GetSubMenu(hMenu
, 0);
103 hPopupMenu
= GetMenu(hwnd
);
106 ZeroMemory(&ItemInfo
, sizeof(ItemInfo
));
107 ItemInfo
.cbSize
= sizeof(ItemInfo
);
108 ItemInfo
.fMask
= MIIM_STATE
;
110 GetMenuItemInfoW(hPopupMenu
, DefaultItem
, FALSE
, &ItemInfo
);
112 if (!(ItemInfo
.fState
& MFS_GRAYED
))
114 SetMenuDefaultItem(hPopupMenu
, DefaultItem
, FALSE
);
119 SetForegroundWindow(hwnd
);
120 TrackPopupMenu(hPopupMenu
, 0, pt
.x
, pt
.y
, 0, hMainWnd
, NULL
);
128 BOOL
StartProcess(ATL::CStringW
&Path
, BOOL Wait
)
130 return StartProcess(const_cast<LPWSTR
>(Path
.GetString()), Wait
);;
133 BOOL
StartProcess(LPWSTR lpPath
, BOOL Wait
)
135 PROCESS_INFORMATION pi
;
140 ZeroMemory(&si
, sizeof(si
));
142 si
.dwFlags
= STARTF_USESHOWWINDOW
;
143 si
.wShowWindow
= SW_SHOW
;
145 if (!CreateProcessW(NULL
, lpPath
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
))
150 CloseHandle(pi
.hThread
);
154 EnableWindow(hMainWnd
, FALSE
);
159 dwRet
= MsgWaitForMultipleObjects(1, &pi
.hProcess
, FALSE
, INFINITE
, QS_ALLEVENTS
);
160 if (dwRet
== WAIT_OBJECT_0
+ 1)
162 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
164 TranslateMessage(&msg
);
165 DispatchMessageW(&msg
);
170 if (dwRet
== WAIT_OBJECT_0
|| dwRet
== WAIT_FAILED
)
175 CloseHandle(pi
.hProcess
);
179 EnableWindow(hMainWnd
, TRUE
);
180 SetForegroundWindow(hMainWnd
);
187 BOOL
GetStorageDirectory(ATL::CStringW
& Directory
)
189 if (!SHGetSpecialFolderPathW(NULL
, Directory
.GetBuffer(MAX_PATH
), CSIDL_LOCAL_APPDATA
, TRUE
))
191 Directory
.ReleaseBuffer();
195 Directory
.ReleaseBuffer();
196 Directory
+= L
"\\rapps";
198 return (CreateDirectoryW(Directory
.GetString(), NULL
) || GetLastError() == ERROR_ALREADY_EXISTS
);
203 if (!SettingsInfo
.bLogEnabled
)
208 WCHAR szPath
[MAX_PATH
];
209 DWORD dwCategoryNum
= 1;
210 DWORD dwDisp
, dwData
;
213 if (key
.Create(HKEY_LOCAL_MACHINE
,
214 L
"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\ReactOS Application Manager",
215 REG_NONE
, REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
, &dwDisp
) != ERROR_SUCCESS
)
220 if (!GetModuleFileNameW(NULL
, szPath
, _countof(szPath
)))
225 dwData
= EVENTLOG_ERROR_TYPE
| EVENTLOG_WARNING_TYPE
|
226 EVENTLOG_INFORMATION_TYPE
;
228 if ((key
.SetStringValue(L
"EventMessageFile",
230 REG_EXPAND_SZ
) == ERROR_SUCCESS
)
231 && (key
.SetStringValue(L
"CategoryMessageFile",
233 REG_EXPAND_SZ
) == ERROR_SUCCESS
)
234 && (key
.SetDWORDValue(L
"TypesSupported",
235 dwData
) == ERROR_SUCCESS
)
236 && (key
.SetDWORDValue(L
"CategoryCount",
237 dwCategoryNum
) == ERROR_SUCCESS
))
240 hLog
= RegisterEventSourceW(NULL
, L
"ReactOS Application Manager");
251 DeregisterEventSource(hLog
);
256 BOOL
WriteLogMessage(WORD wType
, DWORD dwEventID
, LPCWSTR lpMsg
)
258 if (!SettingsInfo
.bLogEnabled
)
263 if (!ReportEventW(hLog
, wType
, 0, dwEventID
,
264 NULL
, 1, 0, &lpMsg
, NULL
))
272 BOOL
GetInstalledVersion_WowUser(ATL::CStringW
* szVersionResult
,
273 const ATL::CStringW
& szRegName
,
277 BOOL bHasSucceded
= FALSE
;
279 ATL::CStringW szVersion
;
280 ATL::CStringW szPath
= ATL::CStringW(L
"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\%ls") + szRegName
;
282 if (key
.Open(IsUserKey
? HKEY_CURRENT_USER
: HKEY_LOCAL_MACHINE
,
284 keyWow
| KEY_READ
) != ERROR_SUCCESS
)
289 if (szVersionResult
!= NULL
)
291 ULONG dwSize
= MAX_PATH
* sizeof(WCHAR
);
293 if (key
.QueryStringValue(L
"DisplayVersion",
294 szVersion
.GetBuffer(MAX_PATH
),
295 &dwSize
) == ERROR_SUCCESS
)
297 szVersion
.ReleaseBuffer();
298 *szVersionResult
= szVersion
;
303 szVersion
.ReleaseBuffer();
309 szVersion
.ReleaseBuffer();
316 BOOL
GetInstalledVersion(ATL::CStringW
*pszVersion
, const ATL::CStringW
&szRegName
)
318 return (!szRegName
.IsEmpty()
319 && (GetInstalledVersion_WowUser(pszVersion
, szRegName
, TRUE
, KEY_WOW64_32KEY
)
320 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, FALSE
, KEY_WOW64_32KEY
)
321 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, TRUE
, KEY_WOW64_64KEY
)
322 || GetInstalledVersion_WowUser(pszVersion
, szRegName
, FALSE
, KEY_WOW64_64KEY
)));
327 CConfigParser::CConfigParser(const ATL::CStringW
& FileName
) : szConfigPath(GetINIFullPath(FileName
))
332 ATL::CStringW
CConfigParser::GetINIFullPath(const ATL::CStringW
& FileName
)
335 ATL::CStringW szBuffer
;
337 GetStorageDirectory(szDir
);
338 szBuffer
.Format(L
"%ls\\rapps\\%ls", szDir
.GetString(), FileName
.GetString());
343 VOID
CConfigParser::CacheINILocale()
345 // TODO: Set default locale if call fails
346 // find out what is the current system lang code (e.g. "0a") and append it to SectionLocale
347 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_ILANGUAGE
,
348 m_szLocaleID
.GetBuffer(m_cchLocaleSize
), m_cchLocaleSize
);
350 m_szLocaleID
.ReleaseBuffer();
351 m_szCachedINISectionLocale
= L
"Section." + m_szLocaleID
;
353 // turn "Section.0c0a" into "Section.0a", keeping just the neutral lang part
354 m_szCachedINISectionLocaleNeutral
= m_szCachedINISectionLocale
+ m_szLocaleID
.Right(2);
357 UINT
CConfigParser::GetString(const ATL::CStringW
& KeyName
, ATL::CStringW
& ResultString
)
361 LPWSTR ResultStringBuffer
= ResultString
.GetBuffer(MAX_PATH
);
362 // 1st - find localized strings (e.g. "Section.0c0a")
363 dwResult
= GetPrivateProfileStringW(m_szCachedINISectionLocale
.GetString(),
368 szConfigPath
.GetString());
372 // 2nd - if they weren't present check for neutral sub-langs/ generic translations (e.g. "Section.0a")
373 dwResult
= GetPrivateProfileStringW(m_szCachedINISectionLocaleNeutral
.GetString(),
378 szConfigPath
.GetString());
381 // 3rd - if they weren't present fallback to standard english strings (just "Section")
382 dwResult
= GetPrivateProfileStringW(L
"Section",
387 szConfigPath
.GetString());
391 ResultString
.ReleaseBuffer();
392 return (dwResult
!= 0 ? TRUE
: FALSE
);
395 UINT
CConfigParser::GetInt(const ATL::CStringW
& KeyName
)
397 ATL::CStringW Buffer
;
399 // grab the text version of our entry
400 if (!GetString(KeyName
, Buffer
))
403 if (Buffer
.IsEmpty())
406 // convert it to an actual integer
407 INT result
= StrToIntW(Buffer
.GetString());
409 return (UINT
) (result
<= 0) ? 0 : result
;