OLD | NEW |
| (Empty) |
1 // Copyright 2005-2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 // | |
16 // Reuses most of the functionality of the classes within atlmfc_vc80 statreg.h. | |
17 // The only functional difference is that GenerateError() returns a unique | |
18 // HRESULT based on the component CLSID/APPID as well as one of the E_ATL_XXX | |
19 // codes, instead of the generic DISP_E_EXCEPTION. | |
20 | |
21 #ifndef OMAHA_BASE_STATREGEX_H__ | |
22 #define OMAHA_BASE_STATREGEX_H__ | |
23 | |
24 #include <atlbase.h> | |
25 #include <statreg.h> | |
26 | |
27 namespace omaha { | |
28 | |
29 class RegObject; | |
30 | |
31 class RegParser | |
32 { | |
33 public: | |
34 RegParser(RegObject* pRegObj); | |
35 | |
36 HRESULT PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z LPTSTR* ppszReg
); | |
37 HRESULT RegisterBuffer(__in_z LPTSTR szReg, BOOL bRegister); | |
38 | |
39 protected: | |
40 | |
41 void SkipWhiteSpace(); | |
42 HRESULT NextToken(__out_ecount_z(MAX_VALUE) LPTSTR szToken); | |
43 HRESULT AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR szValueName, __out
_ecount_z(MAX_VALUE) LPTSTR szToken); | |
44 BOOL CanForceRemoveKey(LPCTSTR szKey); | |
45 BOOL HasSubKeys(HKEY hkey); | |
46 BOOL HasValues(HKEY hkey); | |
47 HRESULT RegisterSubkeys(__out_ecount_z(MAX_VALUE) LPTSTR szToken, __in HKEY hk
Parent, __in BOOL bRegister, __in BOOL bInRecovery = FALSE); | |
48 BOOL IsSpace(TCHAR ch); | |
49 LPTSTR m_pchCur; | |
50 | |
51 RegObject* m_pRegObj; | |
52 unsigned long guid_prefix_; | |
53 | |
54 HRESULT GenerateError(UINT registrar_error) { | |
55 return MAKE_HRESULT(SEVERITY_ERROR, registrar_error, guid_prefix_); | |
56 } | |
57 | |
58 //HRESULT HandleReplacements(LPTSTR& szToken); | |
59 HRESULT SkipAssignment(__inout_ecount_z(MAX_VALUE) LPTSTR szToken); | |
60 | |
61 BOOL EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pch
Cur); } | |
62 static LPTSTR StrChr(__in_z LPTSTR lpsz, __in TCHAR ch); | |
63 static HKEY HKeyFromString(__in_z LPTSTR szToken); | |
64 static BYTE ChToByte(const TCHAR ch); | |
65 static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt); | |
66 static const TCHAR* const rgszNeverDelete[]; | |
67 static const int cbNeverDelete; | |
68 static const int MAX_VALUE = 4096; | |
69 static const int MAX_TYPE = 4096; | |
70 | |
71 // Implementation Helper | |
72 class CParseBuffer | |
73 { | |
74 public: | |
75 int nPos; | |
76 int nSize; | |
77 LPTSTR p; | |
78 CParseBuffer(int nInitial) | |
79 { | |
80 if (nInitial < 100) | |
81 nInitial = 1000; | |
82 nPos = 0; | |
83 nSize = nInitial; | |
84 p = (LPTSTR) ::ATL::AtlCoTaskMemCAlloc(nSize,static_cast<ULONG>(sizeof(TCH
AR))); | |
85 if (p != NULL) | |
86 *p = NULL; | |
87 } | |
88 ~CParseBuffer() | |
89 { | |
90 CoTaskMemFree(p); | |
91 } | |
92 BOOL Append(const TCHAR* pch, int nChars) | |
93 { | |
94 ATLASSERT(p != NULL); | |
95 int newSize = nPos + nChars + 1; | |
96 if ((newSize <= nPos) || (newSize <= nChars)) | |
97 return FALSE; | |
98 | |
99 if (newSize >= nSize) | |
100 { | |
101 while (newSize >= nSize) { | |
102 if (nSize > INT_MAX / 2) | |
103 return FALSE; | |
104 nSize *= 2; | |
105 } | |
106 LPTSTR pTemp = (LPTSTR)::ATL::AtlCoTaskMemRecalloc(p, nSize, sizeof(TCHA
R)); | |
107 if (pTemp == NULL) | |
108 return FALSE; | |
109 p = pTemp; | |
110 } | |
111 if ((nPos < 0) || (nPos >= nSize) || nSize - nPos > nSize) | |
112 return FALSE; | |
113 | |
114 #pragma warning(push) | |
115 #pragma warning(disable: 22008) | |
116 /* Prefast false warning is fired here despite the all above checks */ | |
117 Checked::memcpy_s(p + nPos, (nSize-nPos) * sizeof(TCHAR), pch, int(nChars
* sizeof(TCHAR))); | |
118 nPos += nChars; | |
119 *(p + nPos) = NULL; | |
120 #pragma warning(pop) | |
121 return TRUE; | |
122 } | |
123 | |
124 BOOL AddChar(const TCHAR* pch) | |
125 { | |
126 #ifndef _UNICODE | |
127 int nChars = int(CharNext(pch) - pch); | |
128 #else | |
129 int nChars = 1; | |
130 #endif | |
131 return Append(pch, nChars); | |
132 | |
133 } | |
134 BOOL AddString(LPCOLESTR lpsz) | |
135 { | |
136 if (lpsz == NULL) | |
137 { | |
138 return FALSE; | |
139 } | |
140 USES_CONVERSION_EX; | |
141 LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
142 if (lpszT == NULL) | |
143 { | |
144 return FALSE; | |
145 } | |
146 return Append(lpszT, (int)lstrlen(lpszT)); | |
147 } | |
148 LPTSTR Detach() | |
149 { | |
150 LPTSTR lp = p; | |
151 p = NULL; | |
152 nSize = nPos = 0; | |
153 return lp; | |
154 } | |
155 | |
156 }; | |
157 }; | |
158 | |
159 class RegObject : public IRegistrarBase | |
160 { | |
161 public: | |
162 | |
163 STDMETHOD(QueryInterface)(const IID &,void ** ) | |
164 { | |
165 ATLASSERT(_T("statically linked in RegObject is not a com object. Do not cal
lthis function")); | |
166 return E_NOTIMPL; | |
167 } | |
168 | |
169 STDMETHOD_(ULONG, AddRef)(void) | |
170 { | |
171 ATLASSERT(_T("statically linked in RegObject is not a com object. Do not cal
lthis function")); | |
172 return 1; | |
173 } | |
174 STDMETHOD_(ULONG, Release)(void) | |
175 { | |
176 ATLASSERT(_T("statically linked in RegObject is not a com object. Do not cal
lthis function")); | |
177 return 0; | |
178 } | |
179 | |
180 virtual ~RegObject(){ClearReplacements();} | |
181 HRESULT FinalConstruct() { return m_csMap.Init(); } | |
182 void FinalRelease() {} | |
183 | |
184 // Map based methods | |
185 HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR lpszKey, LPCOLESTR lpszItem
); | |
186 HRESULT STDMETHODCALLTYPE ClearReplacements(); | |
187 LPCOLESTR StrFromMap(__in_z LPTSTR lpszKey); | |
188 | |
189 // Register via a given mechanism | |
190 HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR pszFileName, UINT nID, LP
COLESTR pszType); | |
191 HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR pszFileName, LPCOLESTR
pszID, LPCOLESTR pszType); | |
192 HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR pszFileName, UINT nID,
LPCOLESTR pszType); | |
193 HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR pszFileName, LPCOLEST
R pszID, LPCOLESTR pszType); | |
194 HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR bstrFileName) | |
195 { | |
196 return CommonFileRegister(bstrFileName, TRUE); | |
197 } | |
198 | |
199 HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR bstrFileName) | |
200 { | |
201 return CommonFileRegister(bstrFileName, FALSE); | |
202 } | |
203 | |
204 HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR bstrData) | |
205 { | |
206 return RegisterWithString(bstrData, TRUE); | |
207 } | |
208 | |
209 HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR bstrData) | |
210 { | |
211 return RegisterWithString(bstrData, FALSE); | |
212 } | |
213 | |
214 protected: | |
215 | |
216 HRESULT CommonFileRegister(LPCOLESTR pszFileName, BOOL bRegister); | |
217 HRESULT RegisterFromResource(LPCOLESTR pszFileName, LPCTSTR pszID, LPCTSTR psz
Type, BOOL bRegister); | |
218 HRESULT RegisterWithString(LPCOLESTR pszData, BOOL bRegister); | |
219 | |
220 static HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;} | |
221 | |
222 CExpansionVector m_RepMap; | |
223 CComObjectThreadModel::AutoDeleteCriticalSection m_csMap; | |
224 }; | |
225 | |
226 inline HRESULT STDMETHODCALLTYPE RegObject::AddReplacement(LPCOLESTR lpszKey, LP
COLESTR lpszItem) | |
227 { | |
228 if (lpszKey == NULL || lpszItem == NULL) | |
229 return E_INVALIDARG; | |
230 m_csMap.Lock(); | |
231 USES_CONVERSION_EX; | |
232 | |
233 LPCTSTR lpszT = OLE2CT_EX(lpszKey, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
234 | |
235 #ifndef _UNICODE | |
236 if(lpszT == NULL) | |
237 return E_OUTOFMEMORY; | |
238 #endif | |
239 | |
240 BOOL bRet = m_RepMap.Add(lpszT, lpszItem); | |
241 | |
242 m_csMap.Unlock(); | |
243 return bRet ? S_OK : E_OUTOFMEMORY; | |
244 } | |
245 | |
246 inline HRESULT RegObject::RegisterFromResource(LPCOLESTR bstrFileName, LPCTSTR s
zID, | |
247 LPCTSTR szType, BOOL bRegister) | |
248 { | |
249 USES_CONVERSION_EX; | |
250 | |
251 HRESULT hr; | |
252 RegParser parser(this); | |
253 HINSTANCE hInstResDll; | |
254 HRSRC hrscReg; | |
255 HGLOBAL hReg; | |
256 DWORD dwSize; | |
257 LPSTR szRegA; | |
258 CTempBuffer<TCHAR, 1024> szReg; | |
259 | |
260 LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESH
OLD); | |
261 #ifndef _UNICODE | |
262 if (lpszBSTRFileName == NULL) | |
263 { | |
264 return E_OUTOFMEMORY; | |
265 } | |
266 #endif // _UNICODE | |
267 | |
268 hInstResDll = LoadLibraryEx(lpszBSTRFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); | |
269 | |
270 if (NULL == hInstResDll) | |
271 { | |
272 ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadLibrary on %s\n"), bstrFile
Name); | |
273 hr = AtlHresultFromLastError(); | |
274 goto ReturnHR; | |
275 } | |
276 | |
277 hrscReg =FindResource((HMODULE)hInstResDll, szID, szType); | |
278 | |
279 if (NULL == hrscReg) | |
280 { | |
281 ATLTRACE(atlTraceRegistrar, 0, (HIWORD(szID) == NULL) ? | |
282 _T("Failed to FindResource on ID:%d TYPE:%s\n") : | |
283 _T("Failed to FindResource on ID:%s TYPE:%s\n"), | |
284 szID, szType); | |
285 hr = AtlHresultFromLastError(); | |
286 goto ReturnHR; | |
287 } | |
288 hReg = LoadResource((HMODULE)hInstResDll, hrscReg); | |
289 | |
290 if (NULL == hReg) | |
291 { | |
292 ATLTRACE(atlTraceRegistrar, 0, _T("Failed to LoadResource\n")); | |
293 hr = AtlHresultFromLastError(); | |
294 goto ReturnHR; | |
295 } | |
296 | |
297 dwSize = SizeofResource((HMODULE)hInstResDll, hrscReg); | |
298 szRegA = (LPSTR)hReg; | |
299 | |
300 // Allocate extra space for NULL. | |
301 if (dwSize + 1 < dwSize) | |
302 return E_OUTOFMEMORY; | |
303 ATLTRY(szReg.Allocate(dwSize + 1)); | |
304 if (szReg == NULL) | |
305 { | |
306 hr = E_OUTOFMEMORY; | |
307 goto ReturnHR; | |
308 } | |
309 | |
310 #ifdef _UNICODE | |
311 DWORD uniSize = ::MultiByteToWideChar(_AtlGetConversionACP(), 0, szRegA, dwSiz
e, szReg, dwSize); | |
312 if (uniSize == 0) | |
313 { | |
314 hr = AtlHresultFromLastError(); | |
315 goto ReturnHR; | |
316 } | |
317 // Append a NULL at the end. | |
318 szReg[uniSize] = NULL; | |
319 #else | |
320 Checked::memcpy_s(szReg, dwSize, szRegA, dwSize); | |
321 // Append a NULL at the end. | |
322 szReg[dwSize] = NULL; | |
323 #endif | |
324 | |
325 | |
326 | |
327 hr = parser.RegisterBuffer(szReg, bRegister); | |
328 | |
329 ReturnHR: | |
330 | |
331 if (NULL != hInstResDll) | |
332 FreeLibrary((HMODULE)hInstResDll); | |
333 return hr; | |
334 } | |
335 | |
336 inline HRESULT STDMETHODCALLTYPE RegObject::ResourceRegister(LPCOLESTR szFileNam
e, UINT nID, LPCOLESTR szType) | |
337 { | |
338 USES_CONVERSION_EX; | |
339 | |
340 LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
341 #ifndef _UNICODE | |
342 if (lpszT == NULL) | |
343 { | |
344 return E_OUTOFMEMORY; | |
345 } | |
346 #endif // _UNICODE | |
347 | |
348 return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, TRUE); | |
349 } | |
350 | |
351 inline HRESULT STDMETHODCALLTYPE RegObject::ResourceRegisterSz(LPCOLESTR szFileN
ame, LPCOLESTR szID, LPCOLESTR szType) | |
352 { | |
353 USES_CONVERSION_EX; | |
354 if (szID == NULL || szType == NULL) | |
355 return E_INVALIDARG; | |
356 | |
357 LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
358 LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
359 #ifndef _UNICODE | |
360 if (lpszID == NULL || lpszType==NULL) | |
361 { | |
362 return E_OUTOFMEMORY; | |
363 } | |
364 #endif // _UNICODE | |
365 return RegisterFromResource(szFileName, lpszID, lpszType, TRUE); | |
366 } | |
367 | |
368 inline HRESULT STDMETHODCALLTYPE RegObject::ResourceUnregister(LPCOLESTR szFileN
ame, UINT nID, LPCOLESTR szType) | |
369 { | |
370 USES_CONVERSION_EX; | |
371 | |
372 LPCTSTR lpszT = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
373 #ifndef _UNICODE | |
374 if (lpszT == NULL) | |
375 { | |
376 return E_OUTOFMEMORY; | |
377 } | |
378 #endif // _UNICODE | |
379 return RegisterFromResource(szFileName, MAKEINTRESOURCE(nID), lpszT, FALSE); | |
380 } | |
381 | |
382 inline HRESULT STDMETHODCALLTYPE RegObject::ResourceUnregisterSz(LPCOLESTR szFil
eName, LPCOLESTR szID, LPCOLESTR szType) | |
383 { | |
384 USES_CONVERSION_EX; | |
385 if (szID == NULL || szType == NULL) | |
386 return E_INVALIDARG; | |
387 | |
388 LPCTSTR lpszID = OLE2CT_EX(szID, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
389 LPCTSTR lpszType = OLE2CT_EX(szType, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
390 #ifndef _UNICODE | |
391 if (lpszID == NULL || lpszType == NULL) | |
392 { | |
393 return E_OUTOFMEMORY; | |
394 } | |
395 #endif // _UNICODE | |
396 | |
397 return RegisterFromResource(szFileName, lpszID, lpszType, FALSE); | |
398 } | |
399 | |
400 inline HRESULT RegObject::RegisterWithString(LPCOLESTR bstrData, BOOL bRegister) | |
401 { | |
402 USES_CONVERSION_EX; | |
403 RegParser parser(this); | |
404 | |
405 LPCTSTR szReg = OLE2CT_EX(bstrData, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
406 #ifndef _UNICODE | |
407 if (szReg == NULL) | |
408 { | |
409 return E_OUTOFMEMORY; | |
410 } | |
411 #endif // _UNICODE | |
412 | |
413 HRESULT hr = parser.RegisterBuffer((LPTSTR)szReg, bRegister); | |
414 | |
415 return hr; | |
416 } | |
417 | |
418 inline HRESULT RegObject::ClearReplacements() | |
419 { | |
420 m_csMap.Lock(); | |
421 HRESULT hr = m_RepMap.ClearReplacements(); | |
422 m_csMap.Unlock(); | |
423 return hr; | |
424 } | |
425 | |
426 | |
427 inline LPCOLESTR RegObject::StrFromMap(__in_z LPTSTR lpszKey) | |
428 { | |
429 m_csMap.Lock(); | |
430 LPCOLESTR lpsz = m_RepMap.Lookup(lpszKey); | |
431 if (lpsz == NULL) // not found!! | |
432 ATLTRACE(atlTraceRegistrar, 0, _T("Map Entry not found\n")); | |
433 m_csMap.Unlock(); | |
434 return lpsz; | |
435 } | |
436 | |
437 inline HRESULT RegObject::CommonFileRegister(LPCOLESTR bstrFileName, BOOL bRegis
ter) | |
438 { | |
439 USES_CONVERSION_EX; | |
440 | |
441 RegParser parser(this); | |
442 | |
443 LPCTSTR lpszBSTRFileName = OLE2CT_EX(bstrFileName, _ATL_SAFE_ALLOCA_DEF_THRESH
OLD); | |
444 #ifndef _UNICODE | |
445 if (lpszBSTRFileName == NULL) | |
446 { | |
447 return E_OUTOFMEMORY; | |
448 } | |
449 #endif // _UNICODE | |
450 | |
451 HANDLE hFile = CreateFile(lpszBSTRFileName, GENERIC_READ, 0, NULL, | |
452 OPEN_EXISTING, | |
453 FILE_ATTRIBUTE_READONLY, | |
454 NULL); | |
455 if (INVALID_HANDLE_VALUE == hFile) | |
456 { | |
457 ATLTRACE2(atlTraceRegistrar, 0, _T("Failed to CreateFile on %s\n"), lpszBSTR
FileName); | |
458 return AtlHresultFromLastError(); | |
459 } | |
460 | |
461 HRESULT hRes = S_OK; | |
462 DWORD cbRead; | |
463 DWORD cbFile = GetFileSize(hFile, NULL); // No HiOrder DWORD required | |
464 | |
465 CTempBuffer<char, 1024> szReg; | |
466 // Extra space for NULL. | |
467 ATLTRY(szReg.Allocate(cbFile + 1)); | |
468 if (szReg == NULL) | |
469 { | |
470 hRes = E_OUTOFMEMORY; | |
471 goto ReturnHR; | |
472 } | |
473 | |
474 if (ReadFile(hFile, szReg, cbFile, &cbRead, NULL) == 0) | |
475 { | |
476 ATLTRACE2(atlTraceRegistrar, 0, "Read Failed on file%s\n", lpszBSTRFileName)
; | |
477 hRes = AtlHresultFromLastError(); | |
478 } | |
479 if (SUCCEEDED(hRes)) | |
480 { | |
481 szReg[cbRead] = NULL; | |
482 | |
483 #ifdef _UNICODE | |
484 CTempBuffer<WCHAR, 1024> szConverted; | |
485 ATLTRY(szConverted.Allocate(cbFile + 1)); | |
486 if (szConverted == NULL) | |
487 { | |
488 hRes = E_OUTOFMEMORY; | |
489 goto ReturnHR; | |
490 | |
491 } | |
492 if (::MultiByteToWideChar(_AtlGetConversionACP(), 0, szReg, cbFile + 1, szCo
nverted, cbFile + 1) == 0) | |
493 { | |
494 hRes = AtlHresultFromLastError(); | |
495 goto ReturnHR; | |
496 } | |
497 | |
498 | |
499 | |
500 | |
501 #else | |
502 LPTSTR szConverted = szReg; | |
503 #endif | |
504 hRes = parser.RegisterBuffer(szConverted, bRegister); | |
505 } | |
506 ReturnHR: | |
507 CloseHandle(hFile); | |
508 return hRes; | |
509 } | |
510 | |
511 __declspec(selectany) const TCHAR* const RegParser::rgszNeverDelete[] = | |
512 { | |
513 _T("AppID"), | |
514 _T("CLSID"), | |
515 _T("Component Categories"), | |
516 _T("FileType"), | |
517 _T("Interface"), | |
518 _T("Hardware"), | |
519 _T("Mime"), | |
520 _T("SAM"), | |
521 _T("SECURITY"), | |
522 _T("SYSTEM"), | |
523 _T("Software"), | |
524 _T("TypeLib") | |
525 }; | |
526 | |
527 __declspec(selectany) const int RegParser::cbNeverDelete = sizeof(rgszNeverDelet
e) / sizeof(LPCTSTR*); | |
528 | |
529 | |
530 inline BOOL RegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt) | |
531 { | |
532 struct typemap | |
533 { | |
534 LPCTSTR lpsz; | |
535 VARTYPE vt; | |
536 }; | |
537 #pragma warning (push) | |
538 #pragma warning (disable : 4640) // construction of local static object is not
thread-safe | |
539 | |
540 static const typemap map[] = { | |
541 {szStringVal, VT_BSTR}, | |
542 {multiszStringVal, VT_BSTR | VT_BYREF}, | |
543 {szDwordVal, VT_UI4}, | |
544 {szBinaryVal, VT_UI1} | |
545 }; | |
546 | |
547 #pragma warning (pop) | |
548 | |
549 for (int i=0;i<sizeof(map)/sizeof(typemap);i++) | |
550 { | |
551 if (!lstrcmpi(szValueType, map[i].lpsz)) | |
552 { | |
553 vt = map[i].vt; | |
554 return TRUE; | |
555 } | |
556 } | |
557 | |
558 return FALSE; | |
559 | |
560 } | |
561 | |
562 inline BYTE RegParser::ChToByte(const TCHAR ch) | |
563 { | |
564 switch (ch) | |
565 { | |
566 case '0': | |
567 case '1': | |
568 case '2': | |
569 case '3': | |
570 case '4': | |
571 case '5': | |
572 case '6': | |
573 case '7': | |
574 case '8': | |
575 case '9': | |
576 return (BYTE) (ch - '0'); | |
577 case 'A': | |
578 case 'B': | |
579 case 'C': | |
580 case 'D': | |
581 case 'E': | |
582 case 'F': | |
583 return (BYTE) (10 + (ch - 'A')); | |
584 case 'a': | |
585 case 'b': | |
586 case 'c': | |
587 case 'd': | |
588 case 'e': | |
589 case 'f': | |
590 return (BYTE) (10 + (ch - 'a')); | |
591 default: | |
592 ATLASSERT(FALSE); | |
593 ATLTRACE(atlTraceRegistrar, 0, _T("Bogus value %c passed as binary Hex v
alue\n"), ch); | |
594 return 0; | |
595 } | |
596 } | |
597 | |
598 inline HKEY RegParser::HKeyFromString(__in_z LPTSTR szToken) | |
599 { | |
600 struct keymap | |
601 { | |
602 LPCTSTR lpsz; | |
603 HKEY hkey; | |
604 }; | |
605 static const keymap map[] = { | |
606 {_T("HKCR"), HKEY_CLASSES_ROOT}, | |
607 {_T("HKCU"), HKEY_CURRENT_USER}, | |
608 {_T("HKLM"), HKEY_LOCAL_MACHINE}, | |
609 {_T("HKU"), HKEY_USERS}, | |
610 {_T("HKPD"), HKEY_PERFORMANCE_DATA}, | |
611 {_T("HKDD"), HKEY_DYN_DATA}, | |
612 {_T("HKCC"), HKEY_CURRENT_CONFIG}, | |
613 {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT}, | |
614 {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER}, | |
615 {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE}, | |
616 {_T("HKEY_USERS"), HKEY_USERS}, | |
617 {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA}, | |
618 {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA}, | |
619 {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG} | |
620 }; | |
621 | |
622 for (int i=0;i<sizeof(map)/sizeof(keymap);i++) | |
623 { | |
624 if (!lstrcmpi(szToken, map[i].lpsz)) | |
625 return map[i].hkey; | |
626 } | |
627 return NULL; | |
628 } | |
629 | |
630 inline LPTSTR RegParser::StrChr(__in_z LPTSTR lpsz, __in TCHAR ch) | |
631 { | |
632 LPTSTR p = NULL; | |
633 | |
634 if (lpsz == NULL) | |
635 return NULL; | |
636 | |
637 while (*lpsz) | |
638 { | |
639 if (*lpsz == ch) | |
640 { | |
641 p = lpsz; | |
642 break; | |
643 } | |
644 lpsz = CharNext(lpsz); | |
645 } | |
646 return p; | |
647 } | |
648 | |
649 inline RegParser::RegParser(RegObject* pRegObj) | |
650 { | |
651 m_pRegObj = pRegObj; | |
652 m_pchCur = NULL; | |
653 | |
654 CString guid(m_pRegObj->StrFromMap(_T("CLSID"))); | |
655 if (guid.IsEmpty()) { | |
656 guid = m_pRegObj->StrFromMap(_T("APPID")); | |
657 } | |
658 | |
659 guid_prefix_ = _tcstoul(guid.Mid(1, 4), NULL, 16); | |
660 | |
661 ATLASSERT(guid_prefix_); | |
662 } | |
663 | |
664 inline BOOL RegParser::IsSpace(TCHAR ch) | |
665 { | |
666 switch (ch) | |
667 { | |
668 case _T(' '): | |
669 case _T('\t'): | |
670 case _T('\r'): | |
671 case _T('\n'): | |
672 return TRUE; | |
673 } | |
674 | |
675 return FALSE; | |
676 } | |
677 | |
678 inline void RegParser::SkipWhiteSpace() | |
679 { | |
680 while(IsSpace(*m_pchCur)) | |
681 m_pchCur = CharNext(m_pchCur); | |
682 } | |
683 | |
684 inline HRESULT RegParser::NextToken(__out_ecount_z(MAX_VALUE) LPTSTR szToken) | |
685 { | |
686 SkipWhiteSpace(); | |
687 | |
688 // NextToken cannot be called at EOS | |
689 if (NULL == *m_pchCur) | |
690 return GenerateError(E_ATL_UNEXPECTED_EOS); | |
691 | |
692 LPCTSTR szOrig = szToken; | |
693 // handle quoted value / key | |
694 if (chQuote == *m_pchCur) | |
695 { | |
696 m_pchCur = CharNext(m_pchCur); | |
697 | |
698 while (NULL != *m_pchCur && !EndOfVar()) | |
699 { | |
700 if (chQuote == *m_pchCur) // If it is a quote that means we must skip it | |
701 m_pchCur = CharNext(m_pchCur); | |
702 | |
703 LPTSTR pchPrev = m_pchCur; | |
704 m_pchCur = CharNext(m_pchCur); | |
705 | |
706 INT_PTR nChars = m_pchCur - pchPrev; | |
707 | |
708 // Make sure we have room for nChars plus terminating NULL | |
709 if ((szToken + nChars + 1) >= szOrig + MAX_VALUE) | |
710 return GenerateError(E_ATL_VALUE_TOO_LARGE); | |
711 | |
712 for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) | |
713 *szToken = *pchPrev; | |
714 } | |
715 | |
716 if (NULL == *m_pchCur) | |
717 { | |
718 ATLTRACE(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File\n"))
; | |
719 return GenerateError(E_ATL_UNEXPECTED_EOS); | |
720 } | |
721 | |
722 *szToken = NULL; | |
723 m_pchCur = CharNext(m_pchCur); | |
724 } | |
725 | |
726 else | |
727 { | |
728 // Handle non-quoted ie parse up till first "White Space" | |
729 while (NULL != *m_pchCur && !IsSpace(*m_pchCur)) | |
730 { | |
731 LPTSTR pchPrev = m_pchCur; | |
732 m_pchCur = CharNext(m_pchCur); | |
733 | |
734 INT_PTR nChars = m_pchCur - pchPrev; | |
735 | |
736 // Make sure we have room for nChars plus terminating NULL | |
737 if ((szToken + nChars + 1) >= szOrig + MAX_VALUE) | |
738 return GenerateError(E_ATL_VALUE_TOO_LARGE); | |
739 | |
740 for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++) | |
741 *szToken = *pchPrev; | |
742 } | |
743 | |
744 *szToken = NULL; | |
745 } | |
746 return S_OK; | |
747 } | |
748 | |
749 inline HRESULT RegParser::AddValue(__in CRegKey& rkParent, __in_z_opt LPCTSTR sz
ValueName, __out_ecount_z(MAX_VALUE) LPTSTR szToken) | |
750 { | |
751 HRESULT hr; | |
752 | |
753 TCHAR szValue[MAX_VALUE]; | |
754 VARTYPE vt = VT_EMPTY; | |
755 LONG lRes = ERROR_SUCCESS; | |
756 UINT nIDRes = 0; | |
757 | |
758 if (FAILED(hr = NextToken(szValue))) | |
759 return hr; | |
760 if (!VTFromRegType(szValue, vt)) | |
761 { | |
762 ATLTRACE(atlTraceRegistrar, 0, _T("%s Type not supported\n"), szValue); | |
763 return GenerateError(E_ATL_TYPE_NOT_SUPPORTED); | |
764 } | |
765 | |
766 SkipWhiteSpace(); | |
767 if (FAILED(hr = NextToken(szValue))) | |
768 return hr; | |
769 | |
770 switch (vt) | |
771 { | |
772 case VT_BSTR: | |
773 { | |
774 lRes = rkParent.SetStringValue(szValueName, szValue); | |
775 ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !s
zValueName ? _T("default") : szValueName); | |
776 break; | |
777 } | |
778 case VT_BSTR | VT_BYREF: | |
779 { | |
780 ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s\n"), szValue, !s
zValueName ? _T("default") : szValueName); | |
781 int nLen = lstrlen(szValue) + 2; //Allocate space for double null terminat
ion. | |
782 CTempBuffer<TCHAR, 256> pszDestValue; | |
783 //nLen should be >= the max size of the target buffer. | |
784 ATLTRY(pszDestValue.Allocate(nLen)); | |
785 if (pszDestValue != NULL) | |
786 { | |
787 TCHAR* p = pszDestValue; | |
788 TCHAR* q = szValue; | |
789 nLen = 0; | |
790 while (*q != _T('\0')) | |
791 { | |
792 TCHAR* r = CharNext(q); | |
793 if (*q == _T('\\') && *r == _T('0')) | |
794 { | |
795 *p++ = NULL; | |
796 q = CharNext(r); | |
797 } | |
798 else | |
799 { | |
800 *p = *q; | |
801 #ifndef _UNICODE | |
802 if (IsDBCSLeadByte(*q)) | |
803 { | |
804 p++; | |
805 q++; | |
806 //Protect from Lead byte followed by the zero terminator.May skip
beyond the end of the string. | |
807 if (*q == _T('\0')) { break; } | |
808 *p = *q; | |
809 } | |
810 #endif | |
811 p++; | |
812 q++; | |
813 } | |
814 nLen ++; | |
815 } | |
816 //Always terminate with 2 NULLs. | |
817 *p = NULL; | |
818 p++; | |
819 *p = NULL; | |
820 lRes = rkParent.SetMultiStringValue(szValueName, pszDestValue); | |
821 } | |
822 else | |
823 { | |
824 lRes = ERROR_OUTOFMEMORY; | |
825 } | |
826 } | |
827 break; | |
828 case VT_UI4: | |
829 { | |
830 ULONG ulVal; | |
831 USES_CONVERSION_EX; | |
832 | |
833 LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD); | |
834 #ifndef _UNICODE | |
835 if(lpszV == NULL) | |
836 return E_OUTOFMEMORY; | |
837 #endif | |
838 VarUI4FromStr(lpszV, 0, 0, &ulVal); | |
839 | |
840 lRes = rkParent.SetDWORDValue(szValueName, ulVal); | |
841 ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %d at %s\n"), ulVal, !szV
alueName ? _T("default") : szValueName); | |
842 break; | |
843 } | |
844 case VT_UI1: | |
845 { | |
846 int cbValue = lstrlen(szValue); | |
847 if (cbValue & 0x00000001) | |
848 { | |
849 ATLTRACE(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE bou
ndries\n")); | |
850 return E_FAIL; | |
851 } | |
852 int cbValDiv2 = cbValue/2; | |
853 CTempBuffer<BYTE, 256> rgBinary; | |
854 ATLTRY(rgBinary.Allocate(cbValDiv2)); | |
855 if (rgBinary == NULL) | |
856 return E_FAIL; | |
857 memset(rgBinary, 0, cbValDiv2); | |
858 for (int irg = 0; irg < cbValue; irg++) | |
859 rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x000000
01))); | |
860 lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbVal
Div2); | |
861 break; | |
862 } | |
863 } | |
864 | |
865 if (ERROR_SUCCESS != lRes) | |
866 { | |
867 nIDRes = E_ATL_VALUE_SET_FAILED; | |
868 return AtlHresultFromWin32(lRes); | |
869 } | |
870 | |
871 if (FAILED(hr = NextToken(szToken))) | |
872 return hr; | |
873 | |
874 return S_OK; | |
875 } | |
876 | |
877 inline BOOL RegParser::CanForceRemoveKey(LPCTSTR szKey) | |
878 { | |
879 for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++) | |
880 if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel])) | |
881 return FALSE; // We cannot delete it | |
882 | |
883 return TRUE; | |
884 } | |
885 | |
886 inline BOOL RegParser::HasSubKeys(HKEY hkey) | |
887 { | |
888 DWORD cbSubKeys = 0; | |
889 | |
890 if (RegQueryInfoKey(hkey, NULL, NULL, NULL, | |
891 &cbSubKeys, NULL, NULL, | |
892 NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) | |
893 { | |
894 ATLTRACE(atlTraceRegistrar, 0, _T("Should not be here!!\n")); | |
895 ATLASSERT(FALSE); | |
896 return FALSE; | |
897 } | |
898 | |
899 return cbSubKeys > 0; | |
900 } | |
901 | |
902 inline BOOL RegParser::HasValues(HKEY hkey) | |
903 { | |
904 DWORD cbValues = 0; | |
905 | |
906 LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL, | |
907 NULL, NULL, NULL, | |
908 &cbValues, NULL, NULL, NULL, NULL); | |
909 if (ERROR_SUCCESS != lResult) | |
910 { | |
911 ATLTRACE(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed ")); | |
912 ATLASSERT(FALSE); | |
913 return FALSE; | |
914 } | |
915 | |
916 if (1 == cbValues) | |
917 { | |
918 DWORD cbMaxName= MAX_VALUE; | |
919 TCHAR szValueName[MAX_VALUE]; | |
920 // Check to see if the Value is default or named | |
921 lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, N
ULL); | |
922 if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL)) | |
923 return TRUE; // Named Value means we have a value | |
924 return FALSE; | |
925 } | |
926 | |
927 return cbValues > 0; // More than 1 means we have a non-default value | |
928 } | |
929 | |
930 inline HRESULT RegParser::SkipAssignment(__inout_ecount_z(MAX_VALUE) LPTSTR szTo
ken) | |
931 { | |
932 HRESULT hr; | |
933 TCHAR szValue[MAX_VALUE]; | |
934 | |
935 if (*szToken == chEquals) | |
936 { | |
937 if (FAILED(hr = NextToken(szToken))) | |
938 return hr; | |
939 // Skip assignment | |
940 SkipWhiteSpace(); | |
941 if (FAILED(hr = NextToken(szValue))) | |
942 return hr; | |
943 if (FAILED(hr = NextToken(szToken))) | |
944 return hr; | |
945 } | |
946 | |
947 return S_OK; | |
948 } | |
949 | |
950 inline HRESULT RegParser::PreProcessBuffer(__in_z LPTSTR lpszReg, __deref_out_z
LPTSTR* ppszReg) | |
951 { | |
952 ATLASSERT(lpszReg != NULL); | |
953 ATLASSERT(ppszReg != NULL); | |
954 | |
955 if (lpszReg == NULL || ppszReg == NULL) | |
956 return E_POINTER; | |
957 | |
958 *ppszReg = NULL; | |
959 int nSize = lstrlen(lpszReg)*2; | |
960 CParseBuffer pb(nSize); | |
961 if (pb.p == NULL) | |
962 return E_OUTOFMEMORY; | |
963 m_pchCur = lpszReg; | |
964 HRESULT hr = S_OK; | |
965 | |
966 while (*m_pchCur != NULL) // look for end | |
967 { | |
968 if (*m_pchCur == _T('%')) | |
969 { | |
970 m_pchCur = CharNext(m_pchCur); | |
971 if (*m_pchCur == _T('%')) | |
972 { | |
973 if (!pb.AddChar(m_pchCur)) | |
974 { | |
975 hr = E_OUTOFMEMORY; | |
976 break; | |
977 } | |
978 } | |
979 else | |
980 { | |
981 LPTSTR lpszNext = StrChr(m_pchCur, _T('%')); | |
982 if (lpszNext == NULL) | |
983 { | |
984 ATLTRACE(atlTraceRegistrar, 0, _T("Error no closing %% found\n")); | |
985 hr = GenerateError(E_ATL_UNEXPECTED_EOS); | |
986 break; | |
987 } | |
988 if ((lpszNext-m_pchCur) > 31) | |
989 { | |
990 hr = E_FAIL; | |
991 break; | |
992 } | |
993 int nLength = int(lpszNext - m_pchCur); | |
994 TCHAR buf[32]; | |
995 Checked::tcsncpy_s(buf, _countof(buf), m_pchCur, nLength); | |
996 LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf); | |
997 if (lpszVar == NULL) | |
998 { | |
999 hr = GenerateError(E_ATL_NOT_IN_MAP); | |
1000 break; | |
1001 } | |
1002 if (!pb.AddString(lpszVar)) | |
1003 { | |
1004 hr = E_OUTOFMEMORY; | |
1005 break; | |
1006 } | |
1007 | |
1008 while (m_pchCur != lpszNext) | |
1009 m_pchCur = CharNext(m_pchCur); | |
1010 } | |
1011 } | |
1012 else | |
1013 { | |
1014 if (!pb.AddChar(m_pchCur)) | |
1015 { | |
1016 hr = E_OUTOFMEMORY; | |
1017 break; | |
1018 } | |
1019 } | |
1020 | |
1021 m_pchCur = CharNext(m_pchCur); | |
1022 } | |
1023 if (SUCCEEDED(hr)) | |
1024 *ppszReg = pb.Detach(); | |
1025 return hr; | |
1026 } | |
1027 | |
1028 inline HRESULT RegParser::RegisterBuffer(__in_z LPTSTR szBuffer, __in BOOL bRegi
ster) | |
1029 { | |
1030 TCHAR szToken[MAX_VALUE]; | |
1031 HRESULT hr = S_OK; | |
1032 | |
1033 LPTSTR szReg = NULL; | |
1034 hr = PreProcessBuffer(szBuffer, &szReg); | |
1035 if (FAILED(hr)) | |
1036 return hr; | |
1037 | |
1038 ATLTRACE(atlTraceRegistrar, 0, _T("%s\n"), szReg); | |
1039 | |
1040 m_pchCur = szReg; | |
1041 | |
1042 // Preprocess szReg | |
1043 | |
1044 while (NULL != *m_pchCur) | |
1045 { | |
1046 if (FAILED(hr = NextToken(szToken))) | |
1047 break; | |
1048 HKEY hkBase; | |
1049 if ((hkBase = HKeyFromString(szToken)) == NULL) | |
1050 { | |
1051 ATLTRACE(atlTraceRegistrar, 0, _T("HKeyFromString failed on %s\n"), szToke
n); | |
1052 hr = GenerateError(E_ATL_BAD_HKEY); | |
1053 break; | |
1054 } | |
1055 | |
1056 if (FAILED(hr = NextToken(szToken))) | |
1057 break; | |
1058 | |
1059 if (chLeftBracket != *szToken) | |
1060 { | |
1061 ATLTRACE(atlTraceRegistrar, 0, _T("Syntax error, expecting a {, found a %s
\n"), szToken); | |
1062 hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN); | |
1063 break; | |
1064 } | |
1065 if (bRegister) | |
1066 { | |
1067 LPTSTR szRegAtRegister = m_pchCur; | |
1068 hr = RegisterSubkeys(szToken, hkBase, bRegister); | |
1069 if (FAILED(hr)) | |
1070 { | |
1071 ATLTRACE(atlTraceRegistrar, 0, _T("Failed to register, cleaning up!\n"))
; | |
1072 m_pchCur = szRegAtRegister; | |
1073 RegisterSubkeys(szToken, hkBase, FALSE); | |
1074 break; | |
1075 } | |
1076 } | |
1077 else | |
1078 { | |
1079 if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister))) | |
1080 break; | |
1081 } | |
1082 | |
1083 SkipWhiteSpace(); | |
1084 } | |
1085 CoTaskMemFree(szReg); | |
1086 return hr; | |
1087 } | |
1088 | |
1089 inline HRESULT RegParser::RegisterSubkeys(__out_ecount_z(MAX_VALUE) LPTSTR szTok
en, __in HKEY hkParent, __in BOOL bRegister, __in BOOL bRecover) | |
1090 { | |
1091 CRegKey keyCur; | |
1092 LONG lRes; | |
1093 TCHAR szKey[_MAX_PATH]; | |
1094 BOOL bDelete = TRUE; | |
1095 BOOL bInRecovery = bRecover; | |
1096 HRESULT hr = S_OK; | |
1097 | |
1098 ATLTRACE(atlTraceRegistrar, 2, _T("Num Els = %d\n"), cbNeverDelete); | |
1099 if (FAILED(hr = NextToken(szToken))) | |
1100 return hr; | |
1101 | |
1102 | |
1103 while (*szToken != chRightBracket) // Continue till we see a } | |
1104 { | |
1105 | |
1106 | |
1107 bDelete = TRUE; | |
1108 BOOL bTokenDelete = !lstrcmpi(szToken, szDelete); | |
1109 | |
1110 if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete) | |
1111 { | |
1112 if (FAILED(hr = NextToken(szToken))) | |
1113 break; | |
1114 | |
1115 if (bRegister) | |
1116 { | |
1117 CRegKey rkForceRemove; | |
1118 | |
1119 if (StrChr(szToken, chDirSep) != NULL) | |
1120 return GenerateError(E_ATL_COMPOUND_KEY); | |
1121 | |
1122 if (CanForceRemoveKey(szToken)) | |
1123 { | |
1124 rkForceRemove.Attach(hkParent); | |
1125 // Error not returned. We will overwrite the values any way. | |
1126 rkForceRemove.RecurseDeleteKey(szToken); | |
1127 rkForceRemove.Detach(); | |
1128 } | |
1129 if (bTokenDelete) | |
1130 { | |
1131 if (FAILED(hr = NextToken(szToken))) | |
1132 break; | |
1133 if (FAILED(hr = SkipAssignment(szToken))) | |
1134 break; | |
1135 goto EndCheck; | |
1136 } | |
1137 } | |
1138 | |
1139 } | |
1140 | |
1141 if (!lstrcmpi(szToken, szNoRemove)) | |
1142 { | |
1143 bDelete = FALSE; // set even for register | |
1144 if (FAILED(hr = NextToken(szToken))) | |
1145 break; | |
1146 } | |
1147 | |
1148 if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent | |
1149 { | |
1150 TCHAR szValueName[_MAX_PATH]; | |
1151 | |
1152 | |
1153 | |
1154 if (FAILED(hr = NextToken(szValueName))) | |
1155 break; | |
1156 if (FAILED(hr = NextToken(szToken))) | |
1157 break; | |
1158 | |
1159 if (*szToken != chEquals) | |
1160 return GenerateError(E_ATL_EXPECTING_EQUAL); | |
1161 | |
1162 if (bRegister) | |
1163 { | |
1164 CRegKey rk; | |
1165 | |
1166 rk.Attach(hkParent); | |
1167 hr = AddValue(rk, szValueName, szToken); | |
1168 rk.Detach(); | |
1169 | |
1170 if (FAILED(hr)) | |
1171 return hr; | |
1172 | |
1173 goto EndCheck; | |
1174 } | |
1175 else | |
1176 { | |
1177 if (!bRecover && bDelete) | |
1178 { | |
1179 ATLTRACE(atlTraceRegistrar, 1, _T("Deleting %s\n"), szValueName); | |
1180 // We have to open the key for write to be able to delete. | |
1181 CRegKey rkParent; | |
1182 lRes = rkParent.Open(hkParent, NULL, KEY_WRITE); | |
1183 if (lRes == ERROR_SUCCESS) | |
1184 { | |
1185 lRes = rkParent.DeleteValue(szValueName); | |
1186 if (lRes != ERROR_SUCCESS && lRes != ERROR_FILE_NOT_FOUND) | |
1187 { | |
1188 // Key not present is not an error | |
1189 hr = AtlHresultFromWin32(lRes); | |
1190 break; | |
1191 } | |
1192 } | |
1193 else | |
1194 { | |
1195 hr = AtlHresultFromWin32(lRes); | |
1196 break; | |
1197 } | |
1198 } | |
1199 if (FAILED(hr = SkipAssignment(szToken))) | |
1200 break; | |
1201 continue; // can never have a subkey | |
1202 } | |
1203 } | |
1204 | |
1205 if (StrChr(szToken, chDirSep) != NULL) | |
1206 return GenerateError(E_ATL_COMPOUND_KEY); | |
1207 | |
1208 if (bRegister) | |
1209 { | |
1210 lRes = keyCur.Open(hkParent, szToken, KEY_READ | KEY_WRITE); | |
1211 if (ERROR_SUCCESS != lRes) | |
1212 { | |
1213 // Failed all access try read only | |
1214 lRes = keyCur.Open(hkParent, szToken, KEY_READ); | |
1215 if (ERROR_SUCCESS != lRes) | |
1216 { | |
1217 // Finally try creating it | |
1218 ATLTRACE(atlTraceRegistrar, 2, _T("Creating key %s\n"), szToken); | |
1219 lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLAT
ILE, KEY_READ | KEY_WRITE); | |
1220 if (lRes != ERROR_SUCCESS) | |
1221 return AtlHresultFromWin32(lRes); | |
1222 } | |
1223 } | |
1224 | |
1225 if (FAILED(hr = NextToken(szToken))) | |
1226 break; | |
1227 | |
1228 | |
1229 if (*szToken == chEquals) | |
1230 { | |
1231 if (FAILED(hr = AddValue(keyCur, NULL, szToken))) // NULL == default | |
1232 break; | |
1233 } | |
1234 } | |
1235 else //Unregister | |
1236 { | |
1237 if (!bRecover) | |
1238 { | |
1239 lRes = keyCur.Open(hkParent, szToken, KEY_READ); | |
1240 | |
1241 } | |
1242 else | |
1243 lRes = ERROR_FILE_NOT_FOUND; | |
1244 | |
1245 | |
1246 // Open failed set recovery mode | |
1247 if (lRes != ERROR_SUCCESS) | |
1248 bRecover = true; | |
1249 | |
1250 // TRACE out Key open status and if in recovery mode | |
1251 #ifdef _DEBUG | |
1252 if (!bRecover) | |
1253 ATLTRACE(atlTraceRegistrar, 1, _T("Opened Key %s\n"), szToken); | |
1254 else | |
1255 ATLTRACE(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery
mode\n"), szToken); | |
1256 #endif //_DEBUG | |
1257 | |
1258 // Remember Subkey | |
1259 Checked::tcsncpy_s(szKey, _countof(szKey), szToken, _TRUNCATE); | |
1260 | |
1261 if (FAILED(hr = NextToken(szToken))) | |
1262 break; | |
1263 if (FAILED(hr = SkipAssignment(szToken))) | |
1264 break; | |
1265 | |
1266 if (*szToken == chLeftBracket && lstrlen(szToken) == 1) | |
1267 { | |
1268 hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover); | |
1269 // In recover mode ignore error | |
1270 if (FAILED(hr) && !bRecover) | |
1271 break; | |
1272 // Skip the } | |
1273 if (FAILED(hr = NextToken(szToken))) | |
1274 break; | |
1275 } | |
1276 | |
1277 #ifdef _DEBUG | |
1278 if (bRecover != bInRecovery) | |
1279 ATLTRACE(atlTraceRegistrar, 0, _T("Ending Recovery Mode\n")); | |
1280 #endif | |
1281 bRecover = bInRecovery; | |
1282 | |
1283 if (lRes == ERROR_FILE_NOT_FOUND) | |
1284 // Key already not present so not an error. | |
1285 continue; | |
1286 | |
1287 if (lRes != ERROR_SUCCESS) | |
1288 { | |
1289 // We are recovery mode continue on errors else break | |
1290 if (bRecover) | |
1291 continue; | |
1292 else | |
1293 { | |
1294 hr = AtlHresultFromWin32(lRes); | |
1295 break; | |
1296 } | |
1297 } | |
1298 | |
1299 // If in recovery mode | |
1300 if (bRecover && HasSubKeys(keyCur)) | |
1301 { | |
1302 // See if the KEY is in the NeverDelete list and if so, don't | |
1303 if (CanForceRemoveKey(szKey) && bDelete) | |
1304 { | |
1305 ATLTRACE(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by for
ce\n"), szKey); | |
1306 // Error not returned since we are in recovery mode. The error that ca
used recovery mode is returned | |
1307 keyCur.RecurseDeleteKey(szKey); | |
1308 } | |
1309 continue; | |
1310 } | |
1311 | |
1312 BOOL bHasSubKeys=HasSubKeys(keyCur); | |
1313 lRes = keyCur.Close(); | |
1314 if (lRes != ERROR_SUCCESS) | |
1315 return AtlHresultFromWin32(lRes); | |
1316 | |
1317 if (bDelete&& !bHasSubKeys) | |
1318 { | |
1319 ATLTRACE(atlTraceRegistrar, 0, _T("Deleting Key %s\n"), szKey); | |
1320 CRegKey rkParent; | |
1321 rkParent.Attach(hkParent); | |
1322 lRes = rkParent.DeleteSubKey(szKey); | |
1323 rkParent.Detach(); | |
1324 if (lRes != ERROR_SUCCESS) | |
1325 { | |
1326 | |
1327 hr = AtlHresultFromWin32(lRes); | |
1328 break; | |
1329 } | |
1330 } | |
1331 | |
1332 | |
1333 | |
1334 | |
1335 } | |
1336 | |
1337 EndCheck: | |
1338 | |
1339 if (bRegister) | |
1340 { | |
1341 if (*szToken == chLeftBracket && lstrlen(szToken) == 1) | |
1342 { | |
1343 if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE
))) | |
1344 break; | |
1345 if (FAILED(hr = NextToken(szToken))) | |
1346 break; | |
1347 } | |
1348 } | |
1349 } | |
1350 | |
1351 return hr; | |
1352 } | |
1353 | |
1354 }; //namespace omaha | |
1355 | |
1356 #endif //OMAHA_BASE_STATREGEX_H__ | |
1357 | |
OLD | NEW |