ReactOS  0.4.15-dev-5488-ge316d61
registry.cpp
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS system libraries
3  * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE: Functions to read RunOnceEx registry.
5  * COPYRIGHT: Copyright 2021 He Yang <1160386205@qq.com>
6  */
7 
8 #include "iernonce.h"
9 
11 
13  _In_ DWORD iIndex,
14  _Out_ LPTSTR pszName,
15  _Inout_ LPDWORD pnNameLength)
16 {
17  return RegEnumValueW(m_hKey, iIndex, pszName, pnNameLength,
18  NULL, NULL, NULL, NULL);
19 }
20 
22  _In_ const ATL::CStringW &Name,
23  _In_ const ATL::CStringW &Value) :
24  m_Value(Value), m_Name(Name)
25 { ; }
26 
28  _In_ CRegKeyEx &hParentKey)
29 {
30  return hParentKey.DeleteValue(m_Name) == ERROR_SUCCESS;
31 }
32 
34 {
35  CStringW CommandLine;
36  if (wcsncmp(m_Value, L"||", 2) == 0)
37  {
38  // Remove the prefix.
39  CommandLine = (LPCWSTR)m_Value + 2;
40  }
41  else
42  {
43  CommandLine = m_Value;
44  }
45 
46  // FIXME: SHEvaluateSystemCommandTemplate is not implemented
47  // using PathGetArgsW, PathRemoveArgsW as a workaround.
48  LPWSTR szCommandLine = CommandLine.GetBuffer();
49  LPCWSTR szParam = PathGetArgsW(szCommandLine);
50  PathRemoveArgsW(szCommandLine);
51 
52  SHELLEXECUTEINFOW Info = { 0 };
53  Info.cbSize = sizeof(Info);
55  Info.lpFile = szCommandLine;
56  Info.lpParameters = szParam;
57  Info.nShow = SW_SHOWNORMAL;
58 
60 
61  CommandLine.ReleaseBuffer();
62 
63  if (!bSuccess)
64  {
65  return FALSE;
66  }
67 
68  if (Info.hProcess)
69  {
71  CloseHandle(Info.hProcess);
72  }
73 
74  return TRUE;
75 }
76 
78  _In_ const void *a,
79  _In_ const void *b)
80 {
81  return lstrcmpW(((RunOnceExEntry *)a)->m_Name,
82  ((RunOnceExEntry *)b)->m_Name);
83 }
84 
87  _In_ const CStringW &ValueName)
88 {
89  DWORD dwType;
90  DWORD cbData;
91 
92  // Query data size
93  if (hKey.QueryValue(ValueName, &dwType, NULL, &cbData) != ERROR_SUCCESS)
94  return FALSE;
95 
96  // Validate its format and size.
97  if (dwType != REG_SZ)
98  return TRUE;
99 
100  if (cbData % sizeof(WCHAR) != 0)
101  return FALSE;
102 
104  LPWSTR szBuffer = Buffer.GetBuffer((cbData / sizeof(WCHAR)) + 1);
105 
106  if (hKey.QueryValue(ValueName, &dwType, szBuffer, &cbData) != ERROR_SUCCESS)
107  {
108  Buffer.ReleaseBuffer();
109  return FALSE;
110  }
111  szBuffer[cbData / sizeof(WCHAR)] = L'\0';
112  Buffer.ReleaseBuffer();
113 
114  CStringW ExpandStr;
115  DWORD dwcchExpand = ExpandEnvironmentStringsW(Buffer, NULL, 0);
116  ExpandEnvironmentStringsW(Buffer, ExpandStr.GetBuffer(dwcchExpand + 1), dwcchExpand);
117  ExpandStr.ReleaseBuffer();
118 
119  if (ValueName.IsEmpty())
120  {
121  // The default value specifies the section title.
123  }
124  else
125  {
127  }
128 
129  return TRUE;
130 }
131 
133  _In_ CRegKeyEx &hParentKey,
134  _In_ const CStringW &lpSubKeyName) :
135  m_SectionName(lpSubKeyName)
136 {
137  m_bSuccess = FALSE;
138  DWORD dwValueNum;
139  DWORD dwMaxValueNameLen;
140  LSTATUS Error;
142 
143  if (m_RegKey.Open(hParentKey, lpSubKeyName) != ERROR_SUCCESS)
144  return;
145 
147  &dwValueNum, &dwMaxValueNameLen,
148  NULL, NULL, NULL);
149  if (Error != ERROR_SUCCESS)
150  return;
151 
152  for (DWORD i = 0; i < dwValueNum; i++)
153  {
154  LPWSTR szValueName;
155  DWORD dwcchName = dwMaxValueNameLen + 1;
156 
157  szValueName = ValueName.GetBuffer(dwMaxValueNameLen + 1);
158  Error = m_RegKey.EnumValueName(i, szValueName, &dwcchName);
159  ValueName.ReleaseBuffer();
160 
161  if (Error != ERROR_SUCCESS)
162  {
163  // TODO: error handling
164  return;
165  }
166 
168  return;
169  }
170 
171  // Sort entries by name in string order.
174 
175  m_bSuccess = TRUE;
176  return;
177 }
178 
179 // Copy constructor, CSimpleArray needs it.
181  m_SectionName(Section.m_SectionName),
182  m_bSuccess(Section.m_bSuccess),
183  m_SectionTitle(Section.m_SectionTitle),
184  m_EntryList(Section.m_EntryList)
185 {
186  m_RegKey.Attach(Section.m_RegKey);
187 }
188 
190  _In_ CRegKeyEx &hParentKey)
191 {
192  m_RegKey.Close();
193  return hParentKey.RecurseDeleteKey(m_SectionName) == ERROR_SUCCESS;
194 }
195 
197 {
198  return m_EntryList.GetSize();
199 }
200 
202  _Inout_ UINT& iCompleteCnt,
203  _In_ const UINT iTotalCnt)
204 {
205  BOOL bSuccess = TRUE;
206 
207  for (int i = 0; i < m_EntryList.GetSize(); i++)
208  {
209  m_EntryList[i].Delete(m_RegKey);
210  bSuccess &= m_EntryList[i].Exec();
211  iCompleteCnt++;
212  // TODO: the meaning of the third param is still unknown, seems it's always 0.
213  if (g_Callback)
214  g_Callback(iCompleteCnt, iTotalCnt, NULL);
215  }
216  return bSuccess;
217 }
218 
220  _In_ const void *a,
221  _In_ const void *b)
222 {
223  return lstrcmpW(((RunOnceExSection *)a)->m_SectionName,
224  ((RunOnceExSection *)b)->m_SectionName);
225 }
226 
228 {
229  m_bSuccess = FALSE;
230  DWORD dwSubKeyNum;
231  DWORD dwMaxSubKeyNameLen;
232  LSTATUS Error;
234 
235  Error = m_RegKey.Open(BaseKey,
236  L"Software\\Microsoft\\Windows\\CurrentVersion\\RunOnceEx\\");
237  if (Error != ERROR_SUCCESS)
238  {
239  return;
240  }
241 
242  ULONG cchTitle;
243  Error = m_RegKey.QueryStringValue(L"Title", NULL, &cchTitle);
244  if (Error == ERROR_SUCCESS)
245  {
246  Error = m_RegKey.QueryStringValue(L"Title", m_Title.GetBuffer(cchTitle + 1), &cchTitle);
247  m_Title.ReleaseBuffer();
248  if (Error != ERROR_SUCCESS)
249  return;
250  }
251 
253  if (Error != ERROR_SUCCESS)
254  {
255  m_dwFlags = 0;
256  }
257 
259  &dwSubKeyNum, &dwMaxSubKeyNameLen,
260  NULL, NULL, NULL, NULL, NULL, NULL);
261  if (Error != ERROR_SUCCESS)
262  return;
263 
265 
266  for (DWORD i = 0; i < dwSubKeyNum; i++)
267  {
268  LPWSTR szSubKeyName;
269  DWORD dwcchName = dwMaxSubKeyNameLen + 1;
270 
271  szSubKeyName = SubKeyName.GetBuffer(dwMaxSubKeyNameLen + 1);
272  Error = m_RegKey.EnumKey(i, szSubKeyName, &dwcchName);
273  SubKeyName.ReleaseBuffer();
274 
275  if (Error != ERROR_SUCCESS)
276  {
277  // TODO: error handling
278  return;
279  }
280 
282  return;
283  }
284 
285  // Sort sections by name in string order.
288 
289  m_bSuccess = TRUE;
290  return;
291 }
292 
294 {
295  BOOL bSuccess = TRUE;
296 
297  UINT TotalCnt = 0;
298  UINT CompleteCnt = 0;
299  for (int i = 0; i < m_SectionList.GetSize(); i++)
300  {
301  TotalCnt += m_SectionList[i].GetEntryCnt();
302  }
303 
304  // Execute items from registry one by one, and remove them.
305  for (int i = 0; i < m_SectionList.GetSize(); i++)
306  {
307  if (hwnd)
309 
310  bSuccess &= m_SectionList[i].Exec(CompleteCnt, TotalCnt);
311  m_SectionList[i].CloseAndDelete(m_RegKey);
312  }
313 
314  m_RegKey.DeleteValue(L"Title");
315  m_RegKey.DeleteValue(L"Flags");
316 
317  // Notify the dialog all sections are handled.
318  if (hwnd)
320  return bSuccess;
321 }
322 
324 {
325  if (bSilence ||
327  !m_bShowDialog)
328  {
329  return Exec(NULL);
330  }
331  else
332  {
333  // The dialog is responsible to create a thread and execute.
334  ProgressDlg dlg(*this);
335  return dlg.RunDialogBox();
336  }
337 }
338 
341  _In_ const CStringW& SubKeyName)
342 {
343  RunOnceExSection Section(hKey, SubKeyName);
344  if (!Section.m_bSuccess)
345  {
346  return FALSE;
347  }
348 
349  if (!Section.m_SectionTitle.IsEmpty())
350  {
352  }
353  m_SectionList.Add(Section);
354 
355  // The copy constructor of RunOnceExSection didn't detach
356  // the m_RegKey while it's attached to the one in the array.
357  // So we have to detach it manually.
358  Section.m_RegKey.Detach();
359  return TRUE;
360 }
RunOnceExInstance(_In_ HKEY BaseKey)
Definition: registry.cpp:227
#define CloseHandle
Definition: compat.h:739
BOOL HandleSubKey(_In_ CRegKeyEx &hKey, _In_ const CStringW &SubKeyName)
Definition: registry.cpp:339
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
#define _In_opt_
Definition: ms_sal.h:309
#define _Inout_
Definition: ms_sal.h:378
#define ERROR_SUCCESS
Definition: deptool.c:10
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4723
int RunOnceExEntryCmp(_In_ const void *a, _In_ const void *b)
Definition: registry.cpp:77
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
Definition: path.c:779
CSimpleArray< RunOnceExSection > m_SectionList
Definition: registry.h:98
#define _Out_
Definition: ms_sal.h:345
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
#define TRUE
Definition: types.h:120
ATL::CStringW m_SectionName
Definition: registry.h:54
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
CRegKeyEx m_RegKey
Definition: registry.h:55
BOOL Exec(_Inout_ UINT &iCompleteCnt, _In_ const UINT iTotalCnt)
Definition: registry.cpp:201
CRegKeyEx m_RegKey
Definition: registry.h:90
int GetSize() const
Definition: atlsimpcoll.h:104
LONG Close()
Definition: atlbase.h:1055
static BOOLEAN bSuccess
Definition: drive.cpp:433
HKEY m_hKey
Definition: atlbase.h:1014
CHAR * LPTSTR
Definition: xmlstorage.h:192
UINT GetEntryCnt() const
Definition: registry.cpp:196
HKEY Detach()
Definition: atlbase.h:1065
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define L(x)
Definition: ntvdm.h:50
ATL::CStringW m_Name
Definition: registry.h:35
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
RUNONCEEX_CALLBACK g_Callback
Definition: iernonce.cpp:11
BOOL Delete(_In_ CRegKeyEx &hParentKey)
Definition: registry.cpp:27
void __cdecl qsort(_Inout_updates_bytes_(_NumOfElements *_SizeOfElements) void *_Base, _In_ size_t _NumOfElements, _In_ size_t _SizeOfElements, _In_ int(__cdecl *_PtFuncCompare)(const void *, const void *))
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2853
#define FLAGS_NO_STAT_DIALOG
Definition: registry.h:16
ATL::CStringW m_Value
Definition: registry.h:34
#define _In_
Definition: ms_sal.h:308
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2335
Definition: bufpool.h:45
LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD &dwValue)
Definition: atlbase.h:1128
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
ATL::CStringW m_SectionTitle
Definition: registry.h:63
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL Run(_In_ BOOL bSilence)
Definition: registry.cpp:323
BOOL Exec() const
Definition: registry.cpp:33
BOOL RunDialogBox()
Definition: dialog.cpp:30
LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, REGSAM samDesired=KEY_READ|KEY_WRITE)
Definition: atlbase.h:1072
unsigned long DWORD
Definition: ntddk_ex.h:95
LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG *pnChars)
Definition: atlbase.h:1151
BOOL Error
Definition: chkdsk.c:66
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
_Check_return_ _CRTIMP int __cdecl wcsncmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3690
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:240
LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength, FILETIME *pftLastWriteTime=NULL)
Definition: atlbase.h:1332
VOID(CALLBACK * RUNONCEEX_CALLBACK)(_In_ UINT CompleteCnt, _In_ UINT TotalCnt, _In_ DWORD_PTR dwReserved)
Definition: iernonce_undoc.h:9
CSimpleArray< RunOnceExEntry > m_EntryList
Definition: registry.h:64
#define WM_SETINDEX
Definition: dialog.h:18
RunOnceExSection(_In_ CRegKeyEx &hParentKey, _In_ const CStringW &lpSubKeyName)
bool IsEmpty() const
Definition: atlsimpstr.h:379
#define SW_SHOWNORMAL
Definition: winuser.h:764
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
FxAutoRegKey hKey
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
Definition: path.c:506
int RunOnceExSectionCmp(_In_ const void *a, _In_ const void *b)
Definition: registry.cpp:219
BOOL HandleValue(_In_ CRegKeyEx &hKey, _In_ const CStringW &ValueName)
Definition: registry.cpp:85
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
CStringW m_Title
Definition: registry.h:99
DWORD WINAPI ExpandEnvironmentStringsW(IN LPCWSTR lpSrc, IN LPWSTR lpDst, IN DWORD nSize)
Definition: environ.c:519
void Attach(HKEY hKey)
Definition: atlbase.h:1050
LONG EnumValueName(_In_ DWORD iIndex, _Out_ LPTSTR pszName, _Inout_ LPDWORD pnNameLength)
Definition: registry.cpp:12
uint32_t * LPDWORD
Definition: typedefs.h:59
unsigned int ULONG
Definition: retypes.h:1
BOOL Exec(_In_opt_ HWND hwnd)
Definition: registry.cpp:293
RunOnceExEntry(_In_ const ATL::CStringW &Name, _In_ const ATL::CStringW &Value)
Definition: registry.cpp:21
CAtlStringW CStringW
Definition: atlstr.h:130
LONG DeleteValue(LPCTSTR lpszValue)
Definition: atlbase.h:1312
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
WCHAR * LPWSTR
Definition: xmlstorage.h:184
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4022
#define INFINITE
Definition: serial.h:102
BOOL CloseAndDelete(_In_ CRegKeyEx &hParentKey)
Definition: registry.cpp:189
#define REG_SZ
Definition: layer.c:22