利用atl中注册com组件的方法来访问注册表

工作中需要一个快速编辑修改注册表的功能。记得atl中有那么一个通过脚本来访问编辑注册表的东东。于是,抠出其代码如下。其中删除了部分代码。删除的部分,原先atl是用来进行预处理替换操作的。

代码如下:

  1. class CRegParser
  2. {
  3. public:
  4.     CRegParser();

  5.     HRESULT  PreProcessBuffer(_In_z_ LPTSTR lpszReg, _Deref_out_opt_z_ LPTSTR* ppszReg);
  6.     HRESULT  RegisterBuffer(_In_z_ LPTSTR szReg, _In_ BOOL bRegister);

  7. protected:

  8.     static const int MAX_VALUE = 4096;
  9.     void    SkipWhiteSpace();
  10.     HRESULT NextToken(LPTSTR szToken);
  11.     HRESULT AddValue(CRegKey& rkParent, LPCTSTR szValueName, LPTSTR szToken);
  12.     BOOL    CanForceRemoveKey(LPCTSTR szKey);
  13.     BOOL    HasSubKeys(HKEY hkey);
  14.     BOOL    HasValues(HKEY hkey);
  15.     HRESULT RegisterSubkeys(LPTSTR szToken, HKEY hkParent, BOOL bRegister, BOOL bInRecovery = FALSE);
  16.     BOOL    IsSpace(TCHAR ch);
  17.     LPTSTR  m_pchCur;

  18.     HRESULT GenerateError(UINT) {return DISP_E_EXCEPTION;}
  19.     //HRESULT HandleReplacements(LPTSTR& szToken);
  20.     HRESULT SkipAssignment(LPTSTR szToken);

  21.     BOOL    EndOfVar() { return chQuote == *m_pchCur && chQuote != *CharNext(m_pchCur); }
  22.     static LPTSTR StrChr(LPTSTR lpsz, TCHAR ch);
  23.     static HKEY HKeyFromString(LPTSTR szToken);
  24.     static BYTE ChToByte(const TCHAR ch);
  25.     static BOOL VTFromRegType(LPCTSTR szValueType, VARTYPE& vt);
  26.     static const TCHAR* const rgszNeverDelete[];
  27.     static const int cbNeverDelete;
  28.     static const int MAX_TYPE = 4096;

  29.     // Implementation Helper
  30.     class CParseBuffer
  31.     {
  32.     public:
  33.         int nPos;
  34.         int nSize;
  35.         LPTSTR p;
  36.         CParseBuffer(int nInitial)
  37.         {
  38.             if (nInitial < 100)
  39.                 nInitial = 1000;
  40.             nPos = 0;
  41.             nSize = nInitial;
  42.             p = (LPTSTR) ::ATL::AtlCoTaskMemCAlloc(nSize,static_cast<ULONG>(sizeof(TCHAR)));
  43.             if (p != NULL)
  44.                 *p = NULL;
  45.         }
  46.         ~CParseBuffer()
  47.         {
  48.             CoTaskMemFree(p);
  49.         }
  50.         BOOL Append(const TCHAR* pch, int nChars)
  51.         {
  52.             ATLASSERT(p != NULL);
  53.             int newSize = nPos + nChars + 1;
  54.             if ((newSize <= nPos) || (newSize <= nChars))
  55.                 return FALSE;

  56.             if (newSize >= nSize)
  57.             {
  58.                 while (newSize >= nSize) {
  59.                     if (nSize > INT_MAX / 2)
  60.                     return FALSE;
  61.                     nSize *= 2;
  62.                 }
  63.                 LPTSTR pTemp = (LPTSTR)::ATL::AtlCoTaskMemRecalloc(p, nSize, sizeof(TCHAR));
  64.                 if (pTemp == NULL)
  65.                     return FALSE;
  66.                 p = pTemp;
  67.             }
  68.             if ((nPos < 0) || (nPos >= nSize) || nSize - nPos > nSize)
  69.                 return FALSE;

  70. #pragma warning(push)
  71. #pragma warning(disable: 22008)
  72.             /* Prefast false warning is fired here despite the all above checks */
  73.             Checked::memcpy_s(p + nPos, (nSize-nPos) * sizeof(TCHAR), pch, int(nChars * sizeof(TCHAR)));
  74.             nPos += nChars;
  75.             *(p + nPos) = NULL;
  76. #pragma warning(pop)
  77.             return TRUE;            
  78.         }

  79.         BOOL AddChar(const TCHAR* pch)
  80.         {
  81. #ifndef _UNICODE        
  82.             int nChars = int(CharNext(pch) - pch);
  83. #else
  84.             int nChars = 1;
  85. #endif
  86.             return Append(pch, nChars);

  87.         }
  88.         BOOL AddString(LPCOLESTR lpsz)
  89.         {
  90.             if (lpsz == NULL)
  91.             {
  92.                 return FALSE;
  93.             }
  94.             USES_CONVERSION_EX;
  95.             LPCTSTR lpszT = OLE2CT_EX(lpsz, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  96.             if (lpszT == NULL)
  97.             {
  98.                 return FALSE;
  99.             }
  100.             return Append(lpszT, (int)lstrlen(lpszT));
  101.         }
  102.         LPTSTR Detach()
  103.         {
  104.             LPTSTR lp = p;
  105.             p = NULL;
  106.             nSize = nPos = 0;
  107.             return lp;
  108.         }

  109.     };
  110. };


  111. __declspec(selectany) const TCHAR* const CRegParser::rgszNeverDelete[] =
  112. {
  113.     _T("AppID"),
  114.     _T("CLSID"),
  115.     _T("Component Categories"),
  116.     _T("FileType"),
  117.     _T("Interface"),
  118.     _T("Hardware"),
  119.     _T("Mime"),
  120.     _T("SAM"),
  121.     _T("SECURITY"),
  122.     _T("SYSTEM"),
  123.     _T("Software"),
  124.     _T("TypeLib")
  125. };

  126. __declspec(selectany) const int CRegParser::cbNeverDelete = sizeof(rgszNeverDelete) / sizeof(LPCTSTR*);


  127. inline BOOL CRegParser::VTFromRegType(LPCTSTR szValueType, VARTYPE& vt)
  128. {
  129.     struct typemap
  130.     {
  131.         LPCTSTR lpsz;
  132.         VARTYPE vt;
  133.     };
  134. #pragma warning (push)
  135. #pragma warning (disable : 4640)    // construction of local static object is not thread-safe

  136.     static const typemap map[] = {
  137.         {szStringVal, VT_BSTR},
  138.         {multiszStringVal, VT_BSTR | VT_BYREF},
  139.         {szDwordVal,  VT_UI4},
  140.         {szBinaryVal, VT_UI1}
  141.     };

  142. #pragma warning (pop)

  143.     for (int i=0;i<sizeof(map)/sizeof(typemap);i++)
  144.     {
  145.         if (!lstrcmpi(szValueType, map[i].lpsz))
  146.         {
  147.             vt = map[i].vt;
  148.             return TRUE;
  149.         }
  150.     }

  151.     return FALSE;

  152. }

  153. inline BYTE CRegParser::ChToByte(const TCHAR ch)
  154. {
  155.     switch (ch)
  156.     {
  157.         case '0':
  158.         case '1':
  159.         case '2':
  160.         case '3':
  161.         case '4':
  162.         case '5':
  163.         case '6':
  164.         case '7':
  165.         case '8':
  166.         case '9':
  167.                 return (BYTE) (ch - '0');
  168.         case 'A':
  169.         case 'B':
  170.         case 'C':
  171.         case 'D':
  172.         case 'E':
  173.         case 'F':
  174.                 return (BYTE) (10 + (ch - 'A'));
  175.         case 'a':
  176.         case 'b':
  177.         case 'c':
  178.         case 'd':
  179.         case 'e':
  180.         case 'f':
  181.                 return (BYTE) (10 + (ch - 'a'));
  182.         default:
  183.                 ATLASSERT(FALSE);
  184.                 ATLTRACE(atlTraceRegistrar, 0, _T("Bogus value %c passed as binary Hex value/n"), ch);
  185.                 return 0;
  186.     }
  187. }

  188. inline HKEY CRegParser::HKeyFromString(_In_z_ LPTSTR szToken)
  189. {
  190.     struct keymap
  191.     {
  192.         LPCTSTR lpsz;
  193.         HKEY hkey;
  194.     };
  195.     static const keymap map[] = {
  196.         {_T("HKCR"), HKEY_CLASSES_ROOT},
  197.         {_T("HKCU"), HKEY_CURRENT_USER},
  198.         {_T("HKLM"), HKEY_LOCAL_MACHINE},
  199.         {_T("HKU"),  HKEY_USERS},
  200.         {_T("HKPD"), HKEY_PERFORMANCE_DATA},
  201.         {_T("HKDD"), HKEY_DYN_DATA},
  202.         {_T("HKCC"), HKEY_CURRENT_CONFIG},
  203.         {_T("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT},
  204.         {_T("HKEY_CURRENT_USER"), HKEY_CURRENT_USER},
  205.         {_T("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE},
  206.         {_T("HKEY_USERS"), HKEY_USERS},
  207.         {_T("HKEY_PERFORMANCE_DATA"), HKEY_PERFORMANCE_DATA},
  208.         {_T("HKEY_DYN_DATA"), HKEY_DYN_DATA},
  209.         {_T("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG}
  210.     };

  211.     for (int i=0;i<sizeof(map)/sizeof(keymap);i++)
  212.     {
  213.         if (!lstrcmpi(szToken, map[i].lpsz))
  214.             return map[i].hkey;
  215.     }
  216.     return NULL;
  217. }

  218. inline LPTSTR CRegParser::StrChr(_In_z_ LPTSTR lpsz, _In_ TCHAR ch)
  219. {
  220.     LPTSTR p = NULL;

  221.     if (lpsz == NULL)
  222.         return NULL;
  223.     
  224.     while (*lpsz)
  225.     {
  226.         if (*lpsz == ch)
  227.         {
  228.             p = lpsz;
  229.             break;
  230.         }
  231.         lpsz = CharNext(lpsz);
  232.     }
  233.     return p;
  234. }

  235. inline CRegParser::CRegParser()
  236. {
  237.     m_pchCur = NULL;
  238. }

  239. inline BOOL CRegParser::IsSpace(TCHAR ch)
  240. {
  241.     switch (ch)
  242.     {
  243.         case _T(' '):
  244.         case _T('/t'):
  245.         case _T('/r'):
  246.         case _T('/n'):
  247.                 return TRUE;
  248.     }

  249.     return FALSE;
  250. }

  251. inline void CRegParser::SkipWhiteSpace()
  252. {
  253.     while(IsSpace(*m_pchCur))
  254.         m_pchCur = CharNext(m_pchCur);
  255. }

  256. #pragma warning(push)
  257. #pragma warning(disable:6385) // suppressing code analysis warning on the GenerateError code path
  258. inline HRESULT CRegParser::NextToken(_Out_z_cap_c_(MAX_VALUE) LPTSTR szToken)
  259. {
  260.     SkipWhiteSpace();

  261.     // NextToken cannot be called at EOS
  262.     if (NULL == *m_pchCur)
  263.         return GenerateError(E_ATL_UNEXPECTED_EOS);
  264. #pragma warning(pop)

  265.     LPCTSTR szOrig = szToken;
  266.     // handle quoted value / key
  267.     if (chQuote == *m_pchCur)
  268.     {
  269.         m_pchCur = CharNext(m_pchCur);

  270.         while (NULL != *m_pchCur && !EndOfVar())
  271.         {
  272.             if (chQuote == *m_pchCur) // If it is a quote that means we must skip it
  273.                 m_pchCur = CharNext(m_pchCur);

  274.             LPTSTR pchPrev = m_pchCur;
  275.             m_pchCur = CharNext(m_pchCur);

  276.             INT_PTR nChars = m_pchCur - pchPrev;

  277.             // Make sure we have room for nChars plus terminating NULL
  278.             if ((szToken + nChars + 1) >= szOrig + MAX_VALUE)
  279.                 return GenerateError(E_ATL_VALUE_TOO_LARGE);

  280.             for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++)
  281.                 *szToken = *pchPrev;
  282.         }

  283.         if (NULL == *m_pchCur)
  284.         {
  285.             ATLTRACE(atlTraceRegistrar, 0, _T("NextToken : Unexpected End of File/n"));
  286.             return GenerateError(E_ATL_UNEXPECTED_EOS);
  287.         }

  288.         *szToken = NULL;
  289.         m_pchCur = CharNext(m_pchCur);
  290.     }

  291.     else
  292.     {   
  293.         // Handle non-quoted ie parse up till first "White Space"
  294.         while (NULL != *m_pchCur && !IsSpace(*m_pchCur))
  295.         {
  296.             LPTSTR pchPrev = m_pchCur;
  297.             m_pchCur = CharNext(m_pchCur);

  298.             INT_PTR nChars = m_pchCur - pchPrev;

  299.             // Make sure we have room for nChars plus terminating NULL
  300.             if ((szToken + nChars + 1) >= szOrig + MAX_VALUE)
  301.                 return GenerateError(E_ATL_VALUE_TOO_LARGE);

  302.             for (int i = 0; i < (int)nChars; i++, szToken++, pchPrev++)
  303.                 *szToken = *pchPrev;
  304.         }

  305.         *szToken = NULL;
  306.     }
  307.     return S_OK;
  308. }

  309. #pragma warning(push)
  310. #pragma warning(disable:6385) // suppressing code analysis warning on the GenerateError code path
  311. inline HRESULT CRegParser::AddValue(_In_ CRegKey& rkParent, _In_opt_z_ LPCTSTR szValueName, _Out_z_cap_c_(MAX_VALUE) LPTSTR szToken)
  312. {
  313.     HRESULT hr;

  314.     TCHAR       szValue[MAX_VALUE];
  315.     VARTYPE     vt = VT_EMPTY;
  316.     LONG        lRes = ERROR_SUCCESS;
  317.     UINT        nIDRes = 0;

  318.     if (FAILED(hr = NextToken(szValue)))
  319.         return hr;
  320.     if (!VTFromRegType(szValue, vt))
  321.     {
  322.         ATLTRACE(atlTraceRegistrar, 0, _T("%s Type not supported/n"), szValue);
  323.         return GenerateError(E_ATL_TYPE_NOT_SUPPORTED);
  324.     }
  325. #pragma warning(pop)

  326.     SkipWhiteSpace();
  327.     if (FAILED(hr = NextToken(szValue)))
  328.         return hr;

  329.     switch (vt)
  330.     {
  331.     case VT_BSTR:
  332.         {
  333.             lRes = rkParent.SetStringValue(szValueName, szValue);
  334.             ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s/n"), szValue, !szValueName ? _T("default") : szValueName);
  335.             break;
  336.         }
  337.     case VT_BSTR | VT_BYREF:
  338.         {
  339.             ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %s at %s/n"), szValue, !szValueName ? _T("default") : szValueName);
  340.             int nLen = lstrlen(szValue) + 2; //Allocate space for double null termination.
  341.             CTempBuffer<TCHAR, 256> pszDestValue;
  342.             //nLen should be >= the max size of the target buffer.
  343.             ATLTRY(pszDestValue.Allocate(nLen));
  344.             if (pszDestValue != NULL)
  345.             {
  346.                 TCHAR* p = pszDestValue;
  347.                 TCHAR* q = szValue;
  348.                 nLen = 0;
  349.                 while (*q != _T('/0'))
  350.                 {
  351.                     TCHAR* r = CharNext(q);
  352.                     if (*q == _T('//') && *r == _T('0'))
  353.                     {
  354.                         *p++ = NULL;
  355.                         q = CharNext(r);
  356.                     }
  357.                     else
  358.                     {
  359.                         *p = *q;
  360. #ifndef _UNICODE
  361.                         if (IsDBCSLeadByte(*q))
  362.                         {
  363.                             p++;
  364.                             q++;
  365.                             //Protect from Lead byte followed by the zero terminator.May skip beyond the end of the string.
  366.                             if (*q == _T('/0')) { break; }
  367.                             *p = *q;
  368.                         }
  369. #endif
  370.                         p++;
  371.                         q++;
  372.                     }
  373.                     nLen ++;
  374.                 }
  375.                //Always terminate with 2 NULLs.
  376.                 *p = NULL;
  377.                 p++;
  378.                 *p = NULL;
  379.                 lRes = rkParent.SetMultiStringValue(szValueName, pszDestValue);
  380.             }
  381.             else
  382.             {
  383.                 lRes = ERROR_OUTOFMEMORY;
  384.             }
  385.         }
  386.         break;
  387.     case VT_UI4:
  388.         {
  389.             ULONG ulVal;
  390.             USES_CONVERSION_EX;

  391.             LPOLESTR lpszV = T2OLE_EX(szValue, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
  392.     #ifndef _UNICODE
  393.             if(lpszV == NULL) 
  394.                 return E_OUTOFMEMORY;
  395.     #endif  
  396.             VarUI4FromStr(lpszV, 0, 0, &ulVal);
  397.             
  398.             lRes = rkParent.SetDWORDValue(szValueName, ulVal);
  399.             ATLTRACE(atlTraceRegistrar, 2, _T("Setting Value %d at %s/n"), ulVal, !szValueName ? _T("default") : szValueName);
  400.             break;
  401.         }
  402.     case VT_UI1:
  403.         {
  404.             int cbValue = lstrlen(szValue);
  405.             if (cbValue & 0x00000001)
  406.             {
  407.                 ATLTRACE(atlTraceRegistrar, 0, _T("Binary Data does not fall on BYTE boundries/n"));
  408.                 return E_FAIL;
  409.             }
  410.             int cbValDiv2 = cbValue/2;
  411.             CTempBuffer<BYTE, 256> rgBinary;
  412.             ATLTRY(rgBinary.Allocate(cbValDiv2));           
  413.             if (rgBinary == NULL)
  414.                 return E_FAIL;
  415.             memset(rgBinary, 0, cbValDiv2);             
  416.             for (int irg = 0; irg < cbValue; irg++)
  417.                 rgBinary[(irg/2)] |= (ChToByte(szValue[irg])) << (4*(1 - (irg & 0x00000001)));
  418.             lRes = RegSetValueEx(rkParent, szValueName, 0, REG_BINARY, rgBinary, cbValDiv2);
  419.             break;
  420.         }
  421.     }

  422.     if (ERROR_SUCCESS != lRes)
  423.     {
  424.         nIDRes = E_ATL_VALUE_SET_FAILED;
  425.         return AtlHresultFromWin32(lRes);
  426.     }

  427.     if (FAILED(hr = NextToken(szToken)))
  428.         return hr;

  429.     return S_OK;
  430. }

  431. inline BOOL CRegParser::CanForceRemoveKey(LPCTSTR szKey)
  432. {
  433.     for (int iNoDel = 0; iNoDel < cbNeverDelete; iNoDel++)
  434.         if (!lstrcmpi(szKey, rgszNeverDelete[iNoDel]))
  435.              return FALSE;                       // We cannot delete it

  436.     return TRUE;
  437. }

  438. inline BOOL CRegParser::HasSubKeys(HKEY hkey)
  439. {
  440.     DWORD       cbSubKeys = 0;

  441.     if (RegQueryInfoKey(hkey, NULL, NULL, NULL,
  442.                                &cbSubKeys, NULL, NULL,
  443.                                NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
  444.     {
  445.         ATLTRACE(atlTraceRegistrar, 0, _T("Should not be here!!/n"));
  446.         ATLASSERT(FALSE);
  447.         return FALSE;
  448.     }

  449.     return cbSubKeys > 0;
  450. }

  451. inline BOOL CRegParser::HasValues(HKEY hkey)
  452. {
  453.     DWORD       cbValues = 0;

  454.     LONG lResult = RegQueryInfoKey(hkey, NULL, NULL, NULL,
  455.                                   NULL, NULL, NULL,
  456.                                   &cbValues, NULL, NULL, NULL, NULL);
  457.     if (ERROR_SUCCESS != lResult)
  458.     {
  459.         ATLTRACE(atlTraceRegistrar, 0, _T("RegQueryInfoKey Failed "));
  460.         ATLASSERT(FALSE);
  461.         return FALSE;
  462.     }

  463.     if (1 == cbValues)
  464.     {
  465.         DWORD cbMaxName= MAX_VALUE;
  466.         TCHAR szValueName[MAX_VALUE];
  467.         // Check to see if the Value is default or named
  468.         lResult = RegEnumValue(hkey, 0, szValueName, &cbMaxName, NULL, NULL, NULL, NULL);
  469.         if (ERROR_SUCCESS == lResult && (szValueName[0] != NULL))
  470.             return TRUE; // Named Value means we have a value
  471.         return FALSE;
  472.     }

  473.     return cbValues > 0; // More than 1 means we have a non-default value
  474. }

  475. inline HRESULT CRegParser::SkipAssignment(_Inout_z_cap_c_(MAX_VALUE) LPTSTR szToken)
  476. {
  477.     HRESULT hr;
  478.     TCHAR szValue[MAX_VALUE];

  479.     if (*szToken == chEquals)
  480.     {
  481.         if (FAILED(hr = NextToken(szToken)))
  482.             return hr;
  483.         // Skip assignment
  484.         SkipWhiteSpace();
  485.         if (FAILED(hr = NextToken(szValue)))
  486.             return hr;
  487.         if (FAILED(hr = NextToken(szToken)))
  488.             return hr;
  489.     }

  490.     return S_OK;
  491. }

  492. inline HRESULT CRegParser::PreProcessBuffer(_In_z_ LPTSTR lpszReg, _Deref_out_opt_z_ LPTSTR* ppszReg)
  493. {
  494.     ATLASSERT(lpszReg != NULL);
  495.     ATLASSERT(ppszReg != NULL);

  496.     if (lpszReg == NULL || ppszReg == NULL)
  497.         return E_POINTER;
  498.     
  499.     *ppszReg = NULL;
  500.     int nSize = lstrlen(lpszReg)*2;
  501.     CParseBuffer pb(nSize);
  502.     if (pb.p == NULL)
  503.         return E_OUTOFMEMORY;
  504.     m_pchCur = lpszReg;
  505.     HRESULT hr = S_OK;

  506.     bool bRedirectionEnabled = false;
  507.     hr = AtlGetPerUserRegistration(&bRedirectionEnabled);
  508.     if( FAILED(hr) )
  509.     {
  510.         return hr;
  511.     }

  512.     // nNestingLevel is used to avoid checking for unnecessary root key replacements
  513.     // since all of them are expected to be at the top level.
  514.     int nNestingLevel = 0;
  515.     bool bRedirectionPresent = false;
  516.     bool bInsideQuotes = false;

  517.     while (*m_pchCur != NULL) // look for end
  518.     {
  519.         if ( true == bRedirectionEnabled )
  520.         {
  521.             LPCOLESTR szStartHKCU = L"HKCU/r/n{/tSoftware/r/n/t{/r/n/t/tClasses";
  522.             LPCOLESTR szEndHKCU = L"/r/n/t}/r/n}/r/n";

  523.             if ( 0 == nNestingLevel )
  524.             {
  525.                 // Then we should be reading a root key. HKCR, HKCU, etc
  526.                 TCHAR* szRootKey = NULL;
  527.                 if( NULL != ( szRootKey = _tcsstr(m_pchCur, _T("HKCR")) ) &&    // if HKCR is found.
  528.                     (szRootKey == m_pchCur) )   // if HKCR is the first token.
  529.                 {
  530.                     // Skip HKCR
  531.                     m_pchCur = CharNext(m_pchCur);
  532.                     m_pchCur = CharNext(m_pchCur);
  533.                     m_pchCur = CharNext(m_pchCur);
  534.                     m_pchCur = CharNext(m_pchCur);

  535.                     // Add HKCU
  536.                     if (!pb.AddString(szStartHKCU))
  537.                     {
  538.                         hr = E_OUTOFMEMORY;
  539.                         break;
  540.                     }

  541.                     bRedirectionPresent = true;
  542.                 }
  543.             }

  544.             if ( chQuote == *m_pchCur )
  545.             {
  546.                 iffalse == bInsideQuotes )
  547.                 {
  548.                     bInsideQuotes = true;
  549.                 }
  550.                 else
  551.                 {
  552.                     // Make sure it is not an escaped sequence.
  553.                     if( EndOfVar() )
  554.                     {
  555.                         bInsideQuotes = false;
  556.                     }
  557.                     else
  558.                     {
  559.                         // An escaped single quote...
  560.                         m_pchCur = CharNext(m_pchCur);
  561.                         if (!pb.AddChar(m_pchCur))
  562.                         {
  563.                             hr = E_OUTOFMEMORY;
  564.                             break;
  565.                         }
  566.                     }
  567.                 }
  568.             }

  569.             if ( (false == bInsideQuotes) && (*m_pchCur == _T('{')) )
  570.             {
  571.                 ++nNestingLevel;
  572.             }

  573.             if ( (false == bInsideQuotes) && (*m_pchCur == _T('}')) )
  574.             {
  575.                 --nNestingLevel;
  576.                 if ( (0 == nNestingLevel) && (true == bRedirectionPresent) )
  577.                 {
  578.                     if (!pb.AddString(szEndHKCU))
  579.                     {
  580.                         hr = E_OUTOFMEMORY;
  581.                         break;
  582.                     }

  583.                     bRedirectionPresent = false;
  584.                 }
  585.             }
  586.         }

  587.         if (*m_pchCur == _T('%'))
  588.         {
  589.             m_pchCur = CharNext(m_pchCur);
  590.             if (*m_pchCur == _T('%'))
  591.             {
  592.                 if (!pb.AddChar(m_pchCur))
  593.                 {
  594.                     hr = E_OUTOFMEMORY;
  595.                     break;
  596.                 }
  597.             }
  598.             else
  599.             {
  600.                 LPTSTR lpszNext = StrChr(m_pchCur, _T('%'));
  601.                 if (lpszNext == NULL)
  602.                 {
  603.                     ATLTRACE(atlTraceRegistrar, 0, _T("Error no closing %% found/n"));
  604.                     hr = GenerateError(E_ATL_UNEXPECTED_EOS);
  605.                     break;
  606.                 }
  607.                 if ((lpszNext-m_pchCur) > 31)
  608.                 {
  609.                     hr = E_FAIL;
  610.                     break;
  611.                 }
  612.                 int nLength = int(lpszNext - m_pchCur);
  613.                 TCHAR buf[32];
  614.                 Checked::tcsncpy_s(buf, _countof(buf), m_pchCur, nLength);
  615.                 //LPCOLESTR lpszVar = m_pRegObj->StrFromMap(buf);
  616.                 //if (lpszVar == NULL)
  617.                 //{
  618.                 //  hr = GenerateError(E_ATL_NOT_IN_MAP);
  619.                 //  break;
  620.                 //}
  621.                 //if (!pb.AddString(lpszVar))
  622.                 //{
  623.                 //  hr = E_OUTOFMEMORY;
  624.                 //  break;
  625.                 //}

  626.                 while (m_pchCur != lpszNext)
  627.                     m_pchCur = CharNext(m_pchCur);
  628.             }
  629.         }
  630.         else
  631.         {
  632.             if (!pb.AddChar(m_pchCur))
  633.             {
  634.                 hr = E_OUTOFMEMORY;
  635.                 break;
  636.             }
  637.         }

  638.         m_pchCur = CharNext(m_pchCur);
  639.     }
  640.     if (SUCCEEDED(hr))
  641.         *ppszReg = pb.Detach();
  642.     return hr;
  643. }

  644. inline HRESULT CRegParser::RegisterBuffer(LPTSTR szBuffer, BOOL bRegister)
  645. {
  646.     TCHAR   szToken[MAX_VALUE];
  647.     HRESULT hr = S_OK;

  648.     LPTSTR szReg = NULL;
  649.     hr = PreProcessBuffer(szBuffer, &szReg);
  650.     if (FAILED(hr))
  651.         return hr;

  652.     m_pchCur = szReg;

  653.     // Preprocess szReg

  654.     while (NULL != *m_pchCur)
  655.     {
  656.         if (FAILED(hr = NextToken(szToken)))
  657.             break;
  658.         HKEY hkBase;
  659.         if ((hkBase = HKeyFromString(szToken)) == NULL)
  660.         {
  661.             hr = GenerateError(E_ATL_BAD_HKEY);
  662.             break;
  663.         }

  664.         if (FAILED(hr = NextToken(szToken)))
  665.             break;

  666.         if (chLeftBracket != *szToken)
  667.         {
  668.             hr = GenerateError(E_ATL_MISSING_OPENKEY_TOKEN);
  669.             break;
  670.         }
  671.         if (bRegister)
  672.         {
  673.             LPTSTR szRegAtRegister = m_pchCur;
  674.             hr = RegisterSubkeys(szToken, hkBase, bRegister);
  675.             if (FAILED(hr))
  676.             {
  677.                 m_pchCur = szRegAtRegister;
  678.                 RegisterSubkeys(szToken, hkBase, FALSE);
  679.                 break;
  680.             }
  681.         }
  682.         else
  683.         {
  684.             if (FAILED(hr = RegisterSubkeys(szToken, hkBase, bRegister)))
  685.                 break;
  686.         }

  687.         SkipWhiteSpace();
  688.     }
  689.     CoTaskMemFree(szReg);
  690.     return hr;
  691. }

  692. inline HRESULT CRegParser::RegisterSubkeys(LPTSTR szToken, _In_ HKEY hkParent, _In_ BOOL bRegister, _In_ BOOL bRecover)
  693. {
  694.     CRegKey keyCur;
  695.     LONG    lRes;
  696.     TCHAR  szKey[_MAX_PATH];
  697.     BOOL    bDelete = TRUE;
  698.     BOOL    bInRecovery = bRecover;
  699.     HRESULT hr = S_OK;

  700.     if (FAILED(hr = NextToken(szToken)))
  701.         return hr;

  702.     while (*szToken != chRightBracket) // Continue till we see a }
  703.     {
  704.         bDelete = TRUE;
  705.         BOOL bTokenDelete = !lstrcmpi(szToken, szDelete);

  706.         if (!lstrcmpi(szToken, szForceRemove) || bTokenDelete)
  707.         {
  708.             if (FAILED(hr = NextToken(szToken)))
  709.                 break;

  710.             if (bRegister)
  711.             {
  712.                 CRegKey rkForceRemove;

  713.                 if (StrChr(szToken, chDirSep) != NULL)
  714.                     return GenerateError(E_ATL_COMPOUND_KEY);

  715.                 if (CanForceRemoveKey(szToken))
  716.                 {
  717.                     rkForceRemove.Attach(hkParent);
  718.                     // Error not returned. We will overwrite the values any way.
  719.                     rkForceRemove.RecurseDeleteKey(szToken);
  720.                     rkForceRemove.Detach();
  721.                 }
  722.                 if (bTokenDelete)
  723.                 {
  724.                     if (FAILED(hr = NextToken(szToken)))
  725.                         break;
  726.                     if (FAILED(hr = SkipAssignment(szToken)))
  727.                         break;
  728.                     goto EndCheck;
  729.                 }
  730.             }

  731.         }

  732.         if (!lstrcmpi(szToken, szNoRemove))
  733.         {
  734.             bDelete = FALSE;    // set even for register
  735.             if (FAILED(hr = NextToken(szToken)))
  736.                 break;
  737.         }

  738.         if (!lstrcmpi(szToken, szValToken)) // need to add a value to hkParent
  739.         {
  740.             TCHAR  szValueName[MAX_VALUE];


  741.          
  742.             if (FAILED(hr = NextToken(szValueName)))
  743.                 break;
  744.             if (FAILED(hr = NextToken(szToken)))
  745.                 break;
  746.  
  747.             if (*szToken != chEquals)
  748.                 return GenerateError(E_ATL_EXPECTING_EQUAL);

  749.             if (bRegister)
  750.             {
  751.                 CRegKey rk;

  752.                 rk.Attach(hkParent);
  753.                 hr = AddValue(rk, szValueName, szToken);
  754.                 rk.Detach();

  755.                 if (FAILED(hr))
  756.                     return hr;

  757.                 goto EndCheck;
  758.             }
  759.             else
  760.             {
  761.                 if (!bRecover && bDelete)
  762.                 {
  763.                     ATLTRACE(atlTraceRegistrar, 1, _T("Deleting %s/n"), szValueName);
  764.                     // We have to open the key for write to be able to delete.
  765.                     CRegKey rkParent;
  766.                     lRes = rkParent.Open(hkParent, NULL, KEY_WRITE);
  767.                     if (lRes == ERROR_SUCCESS)
  768.                     {
  769.                         lRes = rkParent.DeleteValue(szValueName);
  770.                         if (lRes != ERROR_SUCCESS && lRes != ERROR_FILE_NOT_FOUND)
  771.                         {
  772.                             // Key not present is not an error
  773.                             hr = AtlHresultFromWin32(lRes);
  774.                             break;
  775.                         }
  776.                     }
  777.                     else
  778.                     {
  779.                         hr = AtlHresultFromWin32(lRes);
  780.                         break;
  781.                     }
  782.                 }
  783.                 if (FAILED(hr = SkipAssignment(szToken)))
  784.                     break;
  785.                 continue;  // can never have a subkey
  786.             }
  787.         }

  788.         if (StrChr(szToken, chDirSep) != NULL)
  789.             return GenerateError(E_ATL_COMPOUND_KEY);

  790.         if (bRegister)
  791.         {
  792.             lRes = keyCur.Open(hkParent, szToken, KEY_READ | KEY_WRITE);
  793.             if (ERROR_SUCCESS != lRes)
  794.             {
  795.                 // Failed all access try read only
  796.                 lRes = keyCur.Open(hkParent, szToken, KEY_READ);
  797.                 if (ERROR_SUCCESS != lRes)
  798.                 {
  799.                     // Finally try creating it
  800.                     ATLTRACE(atlTraceRegistrar, 2, _T("Creating key %s/n"), szToken);
  801.                     lRes = keyCur.Create(hkParent, szToken, REG_NONE, REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE);
  802.                     if (lRes != ERROR_SUCCESS)
  803.                         return AtlHresultFromWin32(lRes);
  804.                 }
  805.             }

  806.             if (FAILED(hr = NextToken(szToken)))
  807.                 break;


  808.             if (*szToken == chEquals)
  809.             {
  810.                 if (FAILED(hr = AddValue(keyCur, NULL, szToken))) // NULL == default
  811.                     break;
  812.             }
  813.         }
  814.         else //Unregister
  815.         {
  816.             if (!bRecover)
  817.             {
  818.                 lRes = keyCur.Open(hkParent, szToken, KEY_READ);

  819.             }
  820.             else
  821.                 lRes = ERROR_FILE_NOT_FOUND;


  822.             // Open failed set recovery mode
  823.             if (lRes != ERROR_SUCCESS)
  824.                 bRecover = true;

  825.             // TRACE out Key open status and if in recovery mode
  826. #ifdef _DEBUG
  827.             if (!bRecover)
  828.                 ATLTRACE(atlTraceRegistrar, 1, _T("Opened Key %s/n"), szToken);
  829.             else
  830.                 ATLTRACE(atlTraceRegistrar, 0, _T("Ignoring Open key on %s : In Recovery mode/n"), szToken);
  831. #endif //_DEBUG

  832.             // Remember Subkey
  833.             Checked::tcsncpy_s(szKey, _countof(szKey), szToken, _TRUNCATE);

  834.             if (FAILED(hr = NextToken(szToken)))
  835.                 break;
  836.             if (FAILED(hr = SkipAssignment(szToken)))
  837.                 break;

  838.             if (*szToken == chLeftBracket && lstrlen(szToken) == 1)
  839.             {
  840.                 hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, bRecover);
  841.                 // In recover mode ignore error
  842.                 if (FAILED(hr) && !bRecover)
  843.                     break;
  844.                 // Skip the }
  845.                 if (FAILED(hr = NextToken(szToken)))
  846.                     break;
  847.             }

  848. #ifdef _DEBUG
  849.             if (bRecover != bInRecovery)
  850.                 ATLTRACE(atlTraceRegistrar, 0, _T("Ending Recovery Mode/n"));
  851. #endif
  852.             bRecover = bInRecovery;

  853.             if (lRes == ERROR_FILE_NOT_FOUND)
  854.                 // Key already not present so not an error.
  855.                 continue;

  856.             if (lRes != ERROR_SUCCESS)
  857.             {
  858.                 // We are recovery mode continue on errors else break
  859.                 if (bRecover)
  860.                     continue;
  861.                 else
  862.                 {
  863.                     hr = AtlHresultFromWin32(lRes);
  864.                     break;
  865.                 }
  866.             }

  867.             // If in recovery mode
  868.             if (bRecover && HasSubKeys(keyCur))
  869.             {
  870.                 // See if the KEY is in the NeverDelete list and if so, don't
  871.                 if (CanForceRemoveKey(szKey) && bDelete)
  872.                 {
  873.                     ATLTRACE(atlTraceRegistrar, 0, _T("Deleting non-empty subkey %s by force/n"), szKey);
  874.                     // Error not returned since we are in recovery mode. The error that caused recovery mode is returned
  875.                     keyCur.RecurseDeleteKey(szKey);
  876.                 }
  877.                 continue;
  878.             }
  879.             
  880.             BOOL bHasSubKeys=HasSubKeys(keyCur);
  881.             lRes = keyCur.Close();
  882.             if (lRes != ERROR_SUCCESS)
  883.             return AtlHresultFromWin32(lRes);

  884.             if (bDelete&& !bHasSubKeys)
  885.             {
  886.                 ATLTRACE(atlTraceRegistrar, 0, _T("Deleting Key %s/n"), szKey);
  887.                 CRegKey rkParent;
  888.                 rkParent.Attach(hkParent);
  889.                 lRes = rkParent.DeleteSubKey(szKey);
  890.                 rkParent.Detach();
  891.                 if (lRes != ERROR_SUCCESS)
  892.                 {
  893.                      
  894.                     hr = AtlHresultFromWin32(lRes);
  895.                     break;
  896.                 }
  897.             }
  898.         }

  899. EndCheck:

  900.         if (bRegister)
  901.         {
  902.             if (*szToken == chLeftBracket && lstrlen(szToken) == 1)
  903.             {
  904.                 if (FAILED(hr = RegisterSubkeys(szToken, keyCur.m_hKey, bRegister, FALSE)))
  905.                     break;
  906.                 if (FAILED(hr = NextToken(szToken)))
  907.                     break;
  908.             }
  909.         }
  910.     }

  911.     return hr;
  912. }
注意,该段代码需要包含atl的某些头文件。请自行查阅msdn
使用这段代码的方法如下:
  1. USES_CONVERSION;
  2. int r;
  3. char buffer[CRegParser::MAX_VALUE];
  4. CRegParser reg;
  5. CString str;
  6. CFile file;

  7. file.Open ();
  8. r = file.Read (buffer, sizeof (buffer));
  9. if (r >= sizeof (buffer))
  10. {
  11. // error;
  12. }

  13. buffer[r] = '/0';
  14. reg.RegisterBuffer (CA2CT(buffer), TRUE);
这是一段伪代码,该段代码从文件中读出注册表脚本,传入RegisterBuffer函数,该函数执行更新注册表的操作。需要MFC库、需要ATL的头文件。

下面的代码可以用来更新注册表,使得鼠标右击后可以选择使用notepad来打开选中的文件的菜单项。将这段代码保存到文件中。修改上面那段示例代码,将打开的文件名更改为保存的文件名即可。
  1. HKEY_LOCAL_MACHINE
  2. {
  3.  NoRemove SOFTWARE
  4.  {
  5.   NoRemove Classes
  6.   {
  7.     NoRemove *
  8.     {
  9.      NoRemove Shell
  10.      {
  11.       ForceRemove 使用记事本打开
  12.       {
  13.        Command = s 'Notepad "%%1"'
  14.       }
  15.      }
  16.     }
  17.   }
  18.  }
  19. }


注册表脚本的格式可以参见msdn的文章http://msdn.microsoft.com/zh-cn/library/cc451363(VS.71).aspx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值