home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLEREG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-03  |  18.1 KB  |  630 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include <shellapi.h>
  13.  
  14. #ifdef _MAC
  15. #include <macname1.h>
  16. #include <Processes.h>
  17. #include <macname2.h>
  18. #endif
  19.  
  20. #ifdef AFX_OLE4_SEG
  21. #pragma code_seg(AFX_OLE4_SEG)
  22. #endif
  23.  
  24. #ifdef _DEBUG
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28.  
  29. #define new DEBUG_NEW
  30.  
  31. // from docmgr.cpp
  32. extern BOOL AFXAPI _AfxDeleteRegKey(LPCTSTR lpszKey);
  33.  
  34.  
  35. //////////////////////////////////////////////////////////////////////////////
  36. // data for UpdateRegistry functionality
  37.  
  38. // %1 - class ID
  39. // %2 - class name
  40. // %3 - SFN executable path
  41. // %4 - short type name
  42. // %5 - long type name
  43. // %6 - long application name
  44. // %7 - icon index
  45. // %8 - Creator(xxxxxxxx) [mac-only]
  46. // %8 - File extension Description [non-mac only]
  47. // %9 - (not used yet) [mac-only]
  48. // %9 - File extension *.TLA [non-mac only]
  49. // %A - (not used yet)
  50. #ifdef _MAC
  51. #define NUM_REG_VARS 9      // always one bigger
  52. #else
  53. #define NUM_REG_VARS 10
  54. #endif
  55.  
  56. class CAfxOleSymbolTable
  57. {
  58. protected:
  59.     LPTSTR* m_strEntries;
  60.     int m_nEntries;
  61.  
  62. public:
  63.     CAfxOleSymbolTable(int nEntries);
  64.     ~CAfxOleSymbolTable();
  65.  
  66.     LPCTSTR* GetArray() { return (LPCTSTR*) m_strEntries; }
  67.     LPCTSTR GetAt(int nIndex) const;
  68.     void SetAt(int nIndex, LPCTSTR pstr);
  69.     LPCTSTR operator[](int nIndex) const { return GetAt(nIndex); }
  70. };
  71.  
  72. CAfxOleSymbolTable::CAfxOleSymbolTable(int nEntries)
  73. {
  74.     m_strEntries = new LPTSTR[nEntries];
  75.     memset(m_strEntries, 0, sizeof(LPTSTR) * nEntries);
  76.     m_nEntries = nEntries;
  77. }
  78.  
  79. CAfxOleSymbolTable::~CAfxOleSymbolTable()
  80. {
  81.     int nIndex;
  82.     for (nIndex = 0; nIndex < m_nEntries; nIndex++)
  83.         free(m_strEntries[nIndex]);
  84.     delete [] m_strEntries;
  85. }
  86.  
  87. void CAfxOleSymbolTable::SetAt(int nIndex, LPCTSTR pstr)
  88. {
  89.     ASSERT(nIndex < m_nEntries && nIndex >= 0);
  90.  
  91.     free(m_strEntries[nIndex]);
  92.     m_strEntries[nIndex] = pstr ? _tcsdup(pstr) : NULL;
  93. }
  94.  
  95. LPCTSTR CAfxOleSymbolTable::GetAt(int nIndex) const
  96. {
  97.     if (nIndex < m_nEntries || nIndex < 0)
  98.         return m_strEntries[nIndex];
  99.     else
  100.         return NULL;
  101. }
  102.  
  103. #ifndef _MAC
  104. static const TCHAR sz00[] = _T("%2\0") _T("%5");
  105. static const TCHAR sz01[] = _T("%2\\CLSID\0") _T("%1");
  106. static const TCHAR sz02[] = _T("%2\\Insertable\0") _T("");
  107. static const TCHAR sz03[] = _T("%2\\protocol\\StdFileEditing\\verb\\0\0") _T("&Edit");
  108. static const TCHAR sz04[] = _T("%2\\protocol\\StdFileEditing\\server\0") _T("%3");
  109. static const TCHAR sz05[] = _T("CLSID\\%1\0") _T("%5");
  110. static const TCHAR sz06[] = _T("CLSID\\%1\\ProgID\0") _T("%2");
  111. static const TCHAR sz07[] = _T("CLSID\\%1\\InprocHandler32\0") _T("ole32.dll");
  112. static const TCHAR sz08[] = _T("CLSID\\%1\\LocalServer32\0") _T("%3");
  113. static const TCHAR sz09[] = _T("CLSID\\%1\\Verb\\0\0") _T("&Edit,0,2");
  114. static const TCHAR sz10[] = _T("CLSID\\%1\\Verb\\1\0") _T("&Open,0,2");
  115. static const TCHAR sz11[] = _T("CLSID\\%1\\Insertable\0") _T("");
  116. static const TCHAR sz12[] = _T("CLSID\\%1\\AuxUserType\\2\0") _T("%4");
  117. static const TCHAR sz13[] = _T("CLSID\\%1\\AuxUserType\\3\0") _T("%6");
  118. static const TCHAR sz14[] = _T("CLSID\\%1\\DefaultIcon\0") _T("%3,%7");
  119. static const TCHAR sz15[] = _T("CLSID\\%1\\MiscStatus\0") _T("32");
  120. static const TCHAR sz16[] = _T("\0") _T("");
  121. static const TCHAR sz17[] = _T("CLSID\\%1\\InProcServer32\0") _T("%3");
  122. static const TCHAR sz18[] = _T("CLSID\\%1\\DocObject\0" _T("0")); // CLSIDDocObject
  123. static const TCHAR sz19[] = _T("%2\\DocObject\0" _T("0")); // ProgIDDocObject
  124. static const TCHAR sz20[] = _T("CLSID\\%1\\Printable\0"); // szPrintable
  125. static const TCHAR sz21[] = _T("CLSID\\%1\\DefaultExtension\0%9, %8"); // szDefaultExt
  126. #else
  127. static const TCHAR sz00[] = _T("%2\0") _T("%5");
  128. static const TCHAR sz01[] = _T("%2\\CLSID\0") _T("%1");
  129. static const TCHAR sz02[] = _T("%2\\Insertable\0") _T("");
  130. static const TCHAR sz03[] = _T("%2\\protocol\\StdFileEditing\\verb\\0\0") _T("Edit");
  131. static const TCHAR sz04[] = _T("%2\\protocol\\StdFileEditing\\server\0") _T("%3");
  132. static const TCHAR sz05[] = _T("CLSID\\%1\0") _T("%5");
  133. static const TCHAR sz06[] = _T("CLSID\\%1\\ProgID\0") _T("%2");
  134. static const TCHAR sz07[] = _T("CLSID\\%1\\InprocHandler\0") _T("OLE2:Def$DefFSet");
  135. static const TCHAR sz08[] = _T("CLSID\\%1\\LocalServer\0") _T("%3");
  136. static const TCHAR sz09[] = _T("CLSID\\%1\\Verb\\0\0") _T("Edit,0,2");
  137. static const TCHAR sz10[] = _T("CLSID\\%1\\Verb\\1\0") _T("Open,0,2");
  138. static const TCHAR sz11[] = _T("CLSID\\%1\\Insertable\0") _T("");
  139. static const TCHAR sz12[] = _T("CLSID\\%1\\AuxUserType\\2\0") _T("%4");
  140. static const TCHAR sz13[] = _T("CLSID\\%1\\AuxUserType\\3\0") _T("%6");
  141. static const TCHAR sz14[] = _T("CLSID\\%1\\DefaultIcon\0") _T("%7");
  142. static const TCHAR sz15[] = _T("CLSID\\%1\\MiscStatus\0") _T("0");
  143. static const TCHAR sz16[] = _T("\0") _T("");
  144. #ifdef MACOCX
  145. static const TCHAR sz17[] = _T("CLSID\\%1\\InProcServer\0") _T("%3");
  146. static const TCHAR sz18[] = _T("CLSID\\%1\\DocObject\0" _T("0"));
  147. static const TCHAR sz19[] = _T("%2\\DocObject\0" _T("0"));
  148. static const TCHAR sz20[] = _T("CLSID\\%1\\Printable\0");
  149. static const TCHAR sz21[] = _T("CLSID\\%1\\DefaultCreator\0%4,%9");
  150. #endif
  151. static const TCHAR sz22[] = _T("MacFInfo\\%8\0") _T("%3");
  152. static const TCHAR sz23[] = _T("MacFInfo\\%8\\CLSID\0") _T("%1");
  153. #ifdef MACOCX
  154. static const TCHAR sz24[] = _T("CLSID\\%1\\CreatorAndType\0") _T("%8") _T("shlb");
  155. #endif
  156. #endif //_MAC
  157.  
  158.  
  159. // registration for OAT_INPLACE_SERVER
  160. static const LPCTSTR rglpszInPlaceRegister[] =
  161. {
  162.     sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12,
  163.     sz13, sz15,
  164. #ifdef _MAC
  165.     sz22, sz23,
  166. #endif
  167.     NULL
  168. };
  169.  
  170. // registration for OAT_SERVER
  171. static const LPCTSTR rglpszServerRegister[] =
  172. {
  173.     sz00, sz02, sz03, sz05, sz09, sz11, sz12,
  174.     sz13, sz15,
  175. #ifdef _MAC
  176.     sz22, sz23,
  177. #endif
  178.     NULL
  179. };
  180.  
  181. #if !defined(_MAC) || defined(MACOCX)
  182. // registration for OAT_DOC_OBJECT_SERVER
  183. static const LPCTSTR rglpszDocObjectRegister[] =
  184. {
  185.     sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12,
  186.     sz13, sz15, sz18, sz19, sz20,
  187. #ifdef _MAC
  188.     sz24,
  189. #endif
  190.     NULL
  191. };
  192. #endif
  193.  
  194. // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER
  195. static const LPCTSTR rglpszServerOverwrite[] =
  196. {
  197.     sz01, sz04, sz06, sz07, sz08, sz14, NULL
  198. };
  199. // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER (dll)
  200. static const LPCTSTR rglpszServerOverwriteDLL[] =
  201. {
  202.     sz01, sz04, sz06,
  203. #if !defined(_MAC) || defined(MACOCX)
  204.     sz17,
  205. #endif
  206.     sz14,
  207. #if defined(MACOCX)
  208.     sz24,
  209. #endif
  210.     NULL
  211. };
  212.  
  213. // registration for OAT_CONTAINER
  214. static const LPCTSTR rglpszContainerRegister[] =
  215. {
  216.     sz00, sz05, NULL
  217. };
  218. // overwrite entries for OAT_CONTAINER
  219. static const LPCTSTR rglpszContainerOverwrite[] =
  220. {
  221.     sz01, sz06, sz07, sz08, sz14, NULL
  222. };
  223.  
  224. // registration for OAT_DISPATCH_OBJECT
  225. static const LPCTSTR rglpszDispatchRegister[] =
  226. {
  227.     sz00, sz05, NULL
  228. };
  229. // overwrite entries for OAT_DISPATCH_OBJECT
  230. static const LPCTSTR rglpszDispatchOverwrite[] =
  231. {
  232.     sz01, sz06, sz07, sz08, NULL
  233. };
  234. // overwrite entries for OAT_DISPATCH_OBJECT (dll)
  235. static const LPCTSTR rglpszDispatchOverwriteDLL[] =
  236. {
  237.     sz01, sz06,
  238. #if !defined(_MAC) || defined(MACOCX)
  239.     sz17,
  240. #endif
  241.     NULL
  242. };
  243.  
  244. #if !defined(_MAC) || defined(MACOCX)
  245. // overwrite entries for OAT_DOC_OBJECT_SERVER
  246. static const LPCTSTR rglpszDocObjectOverwrite[] =
  247. {
  248.     sz01, sz04, sz06, sz07, sz08, sz14, sz21,
  249. #ifdef MACOCX
  250.     sz24,
  251. #endif
  252.     NULL
  253. };
  254. #endif
  255.  
  256. struct STANDARD_ENTRY
  257. {
  258.     const LPCTSTR* rglpszRegister;
  259.     const LPCTSTR* rglpszOverwrite;
  260. };
  261.  
  262. static const STANDARD_ENTRY rgStdEntries[] =
  263. {
  264.     { rglpszInPlaceRegister, rglpszServerOverwrite },
  265.     { rglpszServerRegister, rglpszServerOverwrite },
  266.     { rglpszContainerRegister, rglpszContainerOverwrite },
  267.     { rglpszDispatchRegister, rglpszDispatchOverwrite },
  268. #if !defined(_MAC) || defined(MACOCX)
  269.     { rglpszDocObjectRegister, rglpszDocObjectOverwrite },
  270. #endif
  271. };
  272.  
  273. static const STANDARD_ENTRY rgStdEntriesDLL[] =
  274. {
  275.     { rglpszInPlaceRegister, rglpszServerOverwriteDLL },
  276.     { rglpszServerRegister, rglpszServerOverwriteDLL },
  277.     { rglpszContainerRegister, rglpszContainerOverwrite },
  278.     { rglpszDispatchRegister, rglpszDispatchOverwriteDLL },
  279. #if !defined(_MAC) || defined(MACOCX)
  280.     { rglpszDocObjectRegister, rglpszDocObjectOverwrite },
  281. #endif
  282. };
  283.  
  284. /////////////////////////////////////////////////////////////////////////////
  285. // Special registration for apps that wish not to use REGLOAD
  286.  
  287. BOOL AFXAPI AfxOleRegisterServerClassCompat(
  288.     REFCLSID clsid, LPCTSTR lpszClassName,
  289.     LPCTSTR lpszShortTypeName, LPCTSTR lpszLongTypeName,
  290.     OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite)
  291. {
  292.     return AfxOleRegisterServerClass(clsid, lpszClassName, lpszShortTypeName,
  293.         lpszLongTypeName, nAppType, rglpszRegister, rglpszOverwrite);
  294. }
  295.  
  296. static BOOL _AfxOleMakeSymbolTable(CAfxOleSymbolTable& refTable,
  297.     REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  298.     LPCTSTR lpszLongTypeName, int nIconIndex, LPCTSTR lpszFilterName)
  299. {
  300.     // 0 - class ID
  301.     // 1 - class name
  302.     // 2 - SFN executable path
  303.     // 3 - short type name
  304.     // 4 - long type name
  305.     // 5 - long application name
  306.     // 6 - icon index
  307.     // 7 - Creator(xxxxxxxx) [Mac only]
  308.     // 8 - Creator(xxxxxxxx) [mac-only]
  309.     // 9 - Filter description
  310.  
  311.     // convert the CLSID to a string
  312.     LPTSTR lpszClassID;
  313.     LPOLESTR lpOleStr;
  314.     ::StringFromCLSID(clsid, &lpOleStr);
  315.     lpszClassID = TASKSTRINGOLE2T(lpOleStr);
  316.     if (lpszClassID == NULL)
  317.     {
  318.         TRACE0("Warning: StringFromCLSID failed in AfxOleRegisterServerName --\n");
  319.         TRACE0("\tperhaps AfxOleInit() has not been called.\n");
  320.         return FALSE;
  321.     }
  322.     refTable.SetAt(0, lpszClassID);
  323.     refTable.SetAt(1, lpszClassName);
  324.  
  325.     // free memory for class ID
  326.     ASSERT(lpszClassID != NULL);
  327.     CoTaskMemFree(lpszClassID);
  328.  
  329. #ifndef _MAC
  330.     // get path name to server
  331.     CString strPathName;
  332.     AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  333.     refTable.SetAt(2, strPathName);
  334. #else
  335.     // get the creator of the server
  336.     CHAR szCreator[5];
  337.     CHAR szLongCreator[18];
  338.     ProcessSerialNumber psn;
  339.     ProcessInfoRec pir;
  340.  
  341.     psn.highLongOfPSN = 0;
  342.     psn.lowLongOfPSN = kCurrentProcess;
  343.  
  344.     pir.processInfoLength = sizeof(ProcessInfoRec);
  345.     pir.processName = NULL;
  346.     pir.processAppSpec = NULL;
  347.     GetProcessInformation(&psn, &pir);
  348.  
  349.     *(OSType *)szCreator = pir.processSignature;
  350.     szCreator[4] = '\0';
  351.     refTable.SetAt(2, szCreator);
  352.  
  353.     wsprintf(szLongCreator, "Creator(%2x%2x%2x%2x)", szCreator[0], szCreator[1],
  354.         szCreator[2], szCreator[3]);
  355.     refTable.SetAt(7, szLongCreator);
  356. #endif //_MAC
  357.  
  358.     // fill in rest of symbols
  359.     refTable.SetAt(3, lpszShortTypeName);
  360.     refTable.SetAt(4, lpszLongTypeName);
  361.     refTable.SetAt(5, AfxGetAppName()); // will usually be long, readable name
  362.  
  363. #ifndef _MAC
  364.     CString strIconIndex;
  365.     if (nIconIndex != 0)
  366.     {
  367.         HICON hIcon = AfxDllExtractIcon(AfxGetInstanceHandle(), strPathName, nIconIndex);
  368.         if (hIcon != NULL)
  369.             DestroyIcon(hIcon);
  370.         else
  371.             nIconIndex = 0; // couldn't find specified icon so use default
  372.     }
  373.     strIconIndex.Format(_T("%d"), nIconIndex);
  374.     refTable.SetAt(6, strIconIndex);
  375.  
  376.     refTable.SetAt(7, lpszFilterName);
  377.  
  378.     // parse the actualy extension (eg "*.TLA") from the
  379.     // filter name (eg, "Three Letter Acronym Files (*.TLA)")
  380.  
  381.     CString strFileExtension = lpszFilterName;
  382.     int nBeginning = strFileExtension.Find('(');
  383.     if (nBeginning == -1)
  384.         strFileExtension.Empty();
  385.     else
  386.     {
  387.         strFileExtension = strFileExtension.Mid(1+nBeginning);
  388.         nBeginning = strFileExtension.Find('.');
  389.         if (nBeginning == -1)
  390.             strFileExtension.Empty();
  391.         else
  392.         {
  393.             strFileExtension = strFileExtension.Mid(nBeginning);
  394.  
  395.             int nEnd = strFileExtension.Find(')');
  396.             if (nEnd == -1)
  397.                 strFileExtension.Empty();
  398.             else
  399.                 strFileExtension = strFileExtension.Left(nEnd);
  400.         }
  401.     }
  402.     refTable.SetAt(8, strFileExtension);
  403.  
  404. #else
  405.     CHAR szIconIndex[10];
  406.     short rid = (short)nIconIndex; // nIconIndex is referenced but not used
  407.  
  408.     if (GetAppIconID(&rid))
  409.     {
  410.         wsprintf(szIconIndex, "%d", rid);
  411.         refTable.SetAt(6, szIconIndex);
  412.     }
  413.     else
  414.         refTable.SetAt(6, "128");
  415.  
  416.     UNUSED_ALWAYS(lpszFilterName);
  417.     refTable.SetAt(8, "");
  418. #endif //_MAC
  419.  
  420.     return TRUE;
  421. }
  422.  
  423. BOOL AFXAPI AfxOleRegisterServerClass(
  424.     REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  425.     LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister,
  426.     LPCTSTR* rglpszOverwrite, int nIconIndex,
  427.     LPCTSTR lpszFilterName)
  428. {
  429.     ASSERT(AfxIsValidString(lpszClassName));
  430.     ASSERT(AfxIsValidString(lpszShortTypeName));
  431.     ASSERT(*lpszShortTypeName != 0);
  432.     ASSERT(AfxIsValidString(lpszLongTypeName));
  433.     ASSERT(*lpszLongTypeName != 0);
  434.     ASSERT(nAppType == OAT_INPLACE_SERVER || nAppType == OAT_SERVER ||
  435.         nAppType == OAT_CONTAINER || nAppType == OAT_DISPATCH_OBJECT ||
  436.         nAppType == OAT_DOC_OBJECT_SERVER);
  437.     ASSERT(nAppType >= 0 && nAppType < _countof(rgStdEntries));
  438.  
  439.     // use standard registration entries if non given
  440.     if (rglpszRegister == NULL)
  441.         rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister;
  442.     if (rglpszOverwrite == NULL)
  443.     {
  444.         // DLL contexts have special strings
  445.         if (!afxContextIsDLL)
  446.             rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite;
  447.         else
  448.             rglpszOverwrite = (LPCTSTR*)rgStdEntriesDLL[nAppType].rglpszOverwrite;
  449.     }
  450.  
  451.     CAfxOleSymbolTable table(NUM_REG_VARS);
  452.  
  453.     if (!_AfxOleMakeSymbolTable(table, clsid, lpszClassName,
  454.                 lpszShortTypeName, lpszLongTypeName,
  455.                 nIconIndex, lpszFilterName))
  456.     {
  457.         return FALSE;
  458.     }
  459.  
  460.     // protect against registering an invalid DocObject server
  461.     if (nAppType == OAT_DOC_OBJECT_SERVER &&
  462.         (_tcslen(table.GetAt(8)) == 0 || _tcscmp(table.GetAt(8), _T(".*")) == 0))
  463.     {
  464.         ASSERT(FALSE);
  465.         return FALSE;
  466.     }
  467.  
  468.     // update the registry with helper function
  469.     BOOL bResult;
  470.     bResult = AfxOleRegisterHelper(rglpszRegister, table.GetArray(),
  471.         NUM_REG_VARS, FALSE);
  472.     if (bResult && rglpszOverwrite != NULL)
  473.     {
  474.         bResult = AfxOleRegisterHelper(rglpszOverwrite, table.GetArray(),
  475.             NUM_REG_VARS, TRUE);
  476.     }
  477.  
  478.     // free memory for class ID
  479.     return bResult;
  480. }
  481.  
  482. BOOL AFXAPI AfxOleUnregisterServerClass(
  483.     REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  484.     LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister,
  485.     LPCTSTR* rglpszOverwrite)
  486. {
  487.     // use standard registration entries if non given
  488.     if (rglpszRegister == NULL)
  489.         rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister;
  490.     if (rglpszOverwrite == NULL)
  491.     {
  492.         // DLL contexts have special strings
  493.         if (!afxContextIsDLL)
  494.             rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite;
  495.         else
  496.             rglpszOverwrite = (LPCTSTR*)rgStdEntriesDLL[nAppType].rglpszOverwrite;
  497.     }
  498.  
  499.     CAfxOleSymbolTable table(NUM_REG_VARS);
  500.  
  501.     if (!_AfxOleMakeSymbolTable(table, clsid, lpszClassName,
  502.                 lpszShortTypeName, lpszLongTypeName, 0, NULL))
  503.     {
  504.         return FALSE;
  505.     }
  506.  
  507.     // clean up the the registry with helper function
  508.     BOOL bResult;
  509.     bResult = AfxOleUnregisterHelper(rglpszRegister, table.GetArray(),
  510.         NUM_REG_VARS);
  511.     if (bResult && rglpszOverwrite != NULL)
  512.     {
  513.         bResult = AfxOleUnregisterHelper(rglpszOverwrite, table.GetArray(),
  514.             NUM_REG_VARS);
  515.     }
  516.  
  517.     return bResult;
  518. }
  519.  
  520. // removes key/value pairs from system registry
  521. BOOL AFXAPI AfxOleUnregisterHelper(LPCTSTR const* rglpszRegister,
  522.     LPCTSTR const* rglpszSymbols, int nSymbols,
  523.     HKEY hKeyRoot /* = HKEY_CLASSES_ROOT */)
  524. {
  525.     ASSERT(rglpszRegister != NULL);
  526.     ASSERT(nSymbols == 0 || rglpszSymbols != NULL);
  527.  
  528.     CString strKey;
  529.     CString strValue;
  530.  
  531.     // keeping a key open makes this go a bit faster
  532.     HKEY hKeyTemp = NULL;
  533.     if (hKeyRoot == HKEY_CLASSES_ROOT)
  534.         RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKeyTemp);
  535.  
  536.     BOOL bResult = TRUE;
  537.     while (*rglpszRegister != NULL)
  538.     {
  539.         LPCTSTR lpszKey = *rglpszRegister++;
  540.         if ((hKeyRoot == HKEY_CLASSES_ROOT) && (*lpszKey == '\0'))
  541.             continue;
  542.  
  543.         AfxFormatStrings(strKey, lpszKey, rglpszSymbols, nSymbols);
  544.  
  545.         if ((hKeyRoot == HKEY_CLASSES_ROOT) && strKey.IsEmpty())
  546.         {
  547.             TRACE1("Warning: skipping empty key '%s'.\n", lpszKey);
  548.             continue;
  549.         }
  550.  
  551.         _AfxDeleteRegKey(strKey);
  552.     }
  553.  
  554.     if (hKeyTemp != NULL)
  555.         RegCloseKey(hKeyTemp);
  556.  
  557.     return bResult;
  558. }
  559.  
  560. // writes key/value pairs to system registry
  561. BOOL AFXAPI AfxOleRegisterHelper(LPCTSTR const* rglpszRegister,
  562.     LPCTSTR const* rglpszSymbols, int nSymbols, BOOL bReplace,
  563.     HKEY hKeyRoot /* = HKEY_CLASSES_ROOT */)
  564. {
  565.     ASSERT(rglpszRegister != NULL);
  566.     ASSERT(nSymbols == 0 || rglpszSymbols != NULL);
  567.  
  568.     CString strKey;
  569.     CString strValue;
  570.  
  571.     // keeping a key open makes this go a bit faster
  572.     HKEY hKeyTemp = NULL;
  573.     if (hKeyRoot == HKEY_CLASSES_ROOT)
  574.         RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKeyTemp);
  575.  
  576.     BOOL bResult = TRUE;
  577.     while (*rglpszRegister != NULL)
  578.     {
  579.         LPCTSTR lpszKey = *rglpszRegister++;
  580.         if ((hKeyRoot == HKEY_CLASSES_ROOT) && (*lpszKey == '\0'))
  581.             continue;
  582.  
  583.         LPCTSTR lpszValue = lpszKey + lstrlen(lpszKey) + 1;
  584.  
  585.         AfxFormatStrings(strKey, lpszKey, rglpszSymbols, nSymbols);
  586.         AfxFormatStrings(strValue, lpszValue, rglpszSymbols, nSymbols);
  587.  
  588.         if ((hKeyRoot == HKEY_CLASSES_ROOT) && strKey.IsEmpty())
  589.         {
  590.             TRACE1("Warning: skipping empty key '%s'.\n", lpszKey);
  591.             continue;
  592.         }
  593.  
  594.         if (!bReplace)
  595.         {
  596.             TCHAR szBuffer[256];
  597.             LONG lSize = sizeof(szBuffer);
  598.             if (::RegQueryValue(hKeyRoot, strKey, szBuffer, &lSize) ==
  599.                 ERROR_SUCCESS)
  600.             {
  601. #ifdef _DEBUG
  602.                 if (strValue != szBuffer)
  603.                 {
  604.                     TRACE2("Warning: Leaving value '%s' for key '%s' in registry\n",
  605.                         szBuffer, (LPCTSTR)strKey);
  606.                     TRACE1("\tintended value was '%s'.\n", (LPCTSTR)strValue);
  607.                 }
  608. #endif
  609.                 continue;
  610.             }
  611.         }
  612.  
  613.         if (::RegSetValue(hKeyRoot, strKey, REG_SZ, strValue, lstrlen(strValue) * sizeof(TCHAR))
  614.             != ERROR_SUCCESS)
  615.         {
  616.             TRACE2("Error: failed setting key '%s' to value '%s'.\n",
  617.                 (LPCTSTR)strKey, (LPCTSTR)strValue);
  618.             bResult = FALSE;
  619.             break;
  620.         }
  621.     }
  622.  
  623.     if (hKeyTemp != NULL)
  624.         RegCloseKey(hKeyTemp);
  625.  
  626.     return bResult;
  627. }
  628.  
  629. /////////////////////////////////////////////////////////////////////////////
  630.