Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(615)

Side by Side Diff: base/statregex.h

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/static_assert.h ('k') | base/store_watcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « base/static_assert.h ('k') | base/store_watcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698