olereg.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 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. #include "stdafx.h"
  11. #include <shellapi.h>
  12. #ifdef AFX_OLE4_SEG
  13. #pragma code_seg(AFX_OLE4_SEG)
  14. #endif
  15. #ifdef _DEBUG
  16. #undef THIS_FILE
  17. static char THIS_FILE[] = __FILE__;
  18. #endif
  19. #define new DEBUG_NEW
  20. // from docmgr.cpp
  21. extern BOOL AFXAPI _AfxDeleteRegKey(LPCTSTR lpszKey);
  22. //////////////////////////////////////////////////////////////////////////////
  23. // data for UpdateRegistry functionality
  24. // %1 - class ID
  25. // %2 - class name
  26. // %3 - SFN executable path
  27. // %4 - short type name
  28. // %5 - long type name
  29. // %6 - long application name
  30. // %7 - icon index
  31. // %8 - Creator(xxxxxxxx) [mac-only]
  32. // %8 - File extension Description [non-mac only]
  33. // %9 - (not used yet) [mac-only]
  34. // %9 - File extension *.TLA [non-mac only]
  35. // %A - (not used yet)
  36. #define NUM_REG_VARS 10
  37. class CAfxOleSymbolTable
  38. {
  39. protected:
  40. LPTSTR* m_strEntries;
  41. int m_nEntries;
  42. public:
  43. CAfxOleSymbolTable(int nEntries);
  44. ~CAfxOleSymbolTable();
  45. LPCTSTR* GetArray() { return (LPCTSTR*) m_strEntries; }
  46. LPCTSTR GetAt(int nIndex) const;
  47. void SetAt(int nIndex, LPCTSTR pstr);
  48. LPCTSTR operator[](int nIndex) const { return GetAt(nIndex); }
  49. };
  50. CAfxOleSymbolTable::CAfxOleSymbolTable(int nEntries)
  51. {
  52. m_strEntries = new LPTSTR[nEntries];
  53. memset(m_strEntries, 0, sizeof(LPTSTR) * nEntries);
  54. m_nEntries = nEntries;
  55. }
  56. CAfxOleSymbolTable::~CAfxOleSymbolTable()
  57. {
  58. int nIndex;
  59. for (nIndex = 0; nIndex < m_nEntries; nIndex++)
  60. free(m_strEntries[nIndex]);
  61. delete [] m_strEntries;
  62. }
  63. void CAfxOleSymbolTable::SetAt(int nIndex, LPCTSTR pstr)
  64. {
  65. ASSERT(nIndex < m_nEntries && nIndex >= 0);
  66. free(m_strEntries[nIndex]);
  67. m_strEntries[nIndex] = pstr ? _tcsdup(pstr) : NULL;
  68. }
  69. LPCTSTR CAfxOleSymbolTable::GetAt(int nIndex) const
  70. {
  71. if (nIndex < m_nEntries || nIndex < 0)
  72. return m_strEntries[nIndex];
  73. else
  74. return NULL;
  75. }
  76. static const TCHAR sz00[] = _T("%2\0") _T("%5");
  77. static const TCHAR sz01[] = _T("%2\\CLSID\0") _T("%1");
  78. static const TCHAR sz02[] = _T("%2\\Insertable\0") _T("");
  79. static const TCHAR sz03[] = _T("%2\\protocol\\StdFileEditing\\verb\\0\0") _T("&Edit");
  80. static const TCHAR sz04[] = _T("%2\\protocol\\StdFileEditing\\server\0") _T("%3");
  81. static const TCHAR sz05[] = _T("CLSID\\%1\0") _T("%5");
  82. static const TCHAR sz06[] = _T("CLSID\\%1\\ProgID\0") _T("%2");
  83. static const TCHAR sz07[] = _T("CLSID\\%1\\InprocHandler32\0") _T("ole32.dll");
  84. static const TCHAR sz08[] = _T("CLSID\\%1\\LocalServer32\0") _T("%3");
  85. static const TCHAR sz09[] = _T("CLSID\\%1\\Verb\\0\0") _T("&Edit,0,2");
  86. static const TCHAR sz10[] = _T("CLSID\\%1\\Verb\\1\0") _T("&Open,0,2");
  87. static const TCHAR sz11[] = _T("CLSID\\%1\\Insertable\0") _T("");
  88. static const TCHAR sz12[] = _T("CLSID\\%1\\AuxUserType\\2\0") _T("%4");
  89. static const TCHAR sz13[] = _T("CLSID\\%1\\AuxUserType\\3\0") _T("%6");
  90. static const TCHAR sz14[] = _T("CLSID\\%1\\DefaultIcon\0") _T("%3,%7");
  91. static const TCHAR sz15[] = _T("CLSID\\%1\\MiscStatus\0") _T("32");
  92. static const TCHAR sz16[] = _T("\0") _T("");
  93. static const TCHAR sz17[] = _T("CLSID\\%1\\InProcServer32\0") _T("%3");
  94. static const TCHAR sz18[] = _T("CLSID\\%1\\DocObject\0" _T("0")); // CLSIDDocObject
  95. static const TCHAR sz19[] = _T("%2\\DocObject\0" _T("0")); // ProgIDDocObject
  96. static const TCHAR sz20[] = _T("CLSID\\%1\\Printable\0"); // szPrintable
  97. static const TCHAR sz21[] = _T("CLSID\\%1\\DefaultExtension\0%9, %8"); // szDefaultExt
  98. // registration for OAT_INPLACE_SERVER
  99. static const LPCTSTR rglpszInPlaceRegister[] =
  100. {
  101. sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12,
  102. sz13, sz15,
  103. NULL
  104. };
  105. // registration for OAT_SERVER
  106. static const LPCTSTR rglpszServerRegister[] =
  107. {
  108. sz00, sz02, sz03, sz05, sz09, sz11, sz12,
  109. sz13, sz15,
  110. NULL
  111. };
  112. // registration for OAT_DOC_OBJECT_SERVER
  113. static const LPCTSTR rglpszDocObjectRegister[] =
  114. {
  115. sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz12,
  116. sz13, sz15, sz18, sz19, sz20,
  117. NULL
  118. };
  119. // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER
  120. static const LPCTSTR rglpszServerOverwrite[] =
  121. {
  122. sz01, sz04, sz06, sz07, sz08, sz14, NULL
  123. };
  124. // overwrite entries for OAT_SERVER & OAT_INPLACE_SERVER (dll)
  125. static const LPCTSTR rglpszServerOverwriteDLL[] =
  126. {
  127. sz01, sz04, sz06,
  128. sz17,
  129. sz14,
  130. NULL
  131. };
  132. // registration for OAT_CONTAINER
  133. static const LPCTSTR rglpszContainerRegister[] =
  134. {
  135. sz00, sz05, NULL
  136. };
  137. // overwrite entries for OAT_CONTAINER
  138. static const LPCTSTR rglpszContainerOverwrite[] =
  139. {
  140. sz01, sz06, sz07, sz08, sz14, NULL
  141. };
  142. // registration for OAT_DISPATCH_OBJECT
  143. static const LPCTSTR rglpszDispatchRegister[] =
  144. {
  145. sz00, sz05, NULL
  146. };
  147. // overwrite entries for OAT_DISPATCH_OBJECT
  148. static const LPCTSTR rglpszDispatchOverwrite[] =
  149. {
  150. sz01, sz06, sz07, sz08, NULL
  151. };
  152. // overwrite entries for OAT_DISPATCH_OBJECT (dll)
  153. static const LPCTSTR rglpszDispatchOverwriteDLL[] =
  154. {
  155. sz01, sz06,
  156. sz17,
  157. NULL
  158. };
  159. // overwrite entries for OAT_DOC_OBJECT_SERVER
  160. static const LPCTSTR rglpszDocObjectOverwrite[] =
  161. {
  162. sz01, sz04, sz06, sz07, sz08, sz14, sz21,
  163. NULL
  164. };
  165. struct STANDARD_ENTRY
  166. {
  167. const LPCTSTR* rglpszRegister;
  168. const LPCTSTR* rglpszOverwrite;
  169. };
  170. static const STANDARD_ENTRY rgStdEntries[] =
  171. {
  172. { rglpszInPlaceRegister, rglpszServerOverwrite },
  173. { rglpszServerRegister, rglpszServerOverwrite },
  174. { rglpszContainerRegister, rglpszContainerOverwrite },
  175. { rglpszDispatchRegister, rglpszDispatchOverwrite },
  176. { rglpszDocObjectRegister, rglpszDocObjectOverwrite },
  177. };
  178. static const STANDARD_ENTRY rgStdEntriesDLL[] =
  179. {
  180. { rglpszInPlaceRegister, rglpszServerOverwriteDLL },
  181. { rglpszServerRegister, rglpszServerOverwriteDLL },
  182. { rglpszContainerRegister, rglpszContainerOverwrite },
  183. { rglpszDispatchRegister, rglpszDispatchOverwriteDLL },
  184. { rglpszDocObjectRegister, rglpszDocObjectOverwrite },
  185. };
  186. /////////////////////////////////////////////////////////////////////////////
  187. // Special registration for apps that wish not to use REGLOAD
  188. BOOL AFXAPI AfxOleRegisterServerClassCompat(
  189. REFCLSID clsid, LPCTSTR lpszClassName,
  190. LPCTSTR lpszShortTypeName, LPCTSTR lpszLongTypeName,
  191. OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister, LPCTSTR* rglpszOverwrite)
  192. {
  193. return AfxOleRegisterServerClass(clsid, lpszClassName, lpszShortTypeName,
  194. lpszLongTypeName, nAppType, rglpszRegister, rglpszOverwrite);
  195. }
  196. AFX_STATIC BOOL AFXAPI _AfxOleMakeSymbolTable(CAfxOleSymbolTable& refTable,
  197. REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  198. LPCTSTR lpszLongTypeName, int nIconIndex,
  199. LPCTSTR lpszFilterName, LPCTSTR lpszFilterExt)
  200. {
  201. // 0 - class ID
  202. // 1 - class name
  203. // 2 - SFN executable path
  204. // 3 - short type name
  205. // 4 - long type name
  206. // 5 - long application name
  207. // 6 - icon index
  208. // 7 - Creator(xxxxxxxx) [Mac only]
  209. // 8 - Creator(xxxxxxxx) [mac-only]
  210. // 9 - Filter description
  211. // convert the CLSID to a string
  212. LPTSTR lpszClassID;
  213. LPOLESTR lpOleStr;
  214. ::StringFromCLSID(clsid, &lpOleStr);
  215. lpszClassID = TASKSTRINGOLE2T(lpOleStr);
  216. if (lpszClassID == NULL)
  217. {
  218. TRACE0("Warning: StringFromCLSID failed in AfxOleRegisterServerName --\n");
  219. TRACE0("\tperhaps AfxOleInit() has not been called.\n");
  220. return FALSE;
  221. }
  222. refTable.SetAt(0, lpszClassID);
  223. refTable.SetAt(1, lpszClassName);
  224. // free memory for class ID
  225. ASSERT(lpszClassID != NULL);
  226. CoTaskMemFree(lpszClassID);
  227. // get path name to server
  228. CString strPathName;
  229. AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  230. refTable.SetAt(2, strPathName);
  231. // fill in rest of symbols
  232. refTable.SetAt(3, lpszShortTypeName);
  233. refTable.SetAt(4, lpszLongTypeName);
  234. refTable.SetAt(5, AfxGetAppName()); // will usually be long, readable name
  235. CString strIconIndex;
  236. if (nIconIndex != 0)
  237. {
  238. HICON hIcon = ::ExtractIcon(AfxGetInstanceHandle(), strPathName, nIconIndex);
  239. if (hIcon != NULL)
  240. DestroyIcon(hIcon);
  241. else
  242. nIconIndex = 0; // couldn't find specified icon so use default
  243. }
  244. strIconIndex.Format(_T("%d"), nIconIndex);
  245. refTable.SetAt(6, strIconIndex);
  246. refTable.SetAt(7, lpszFilterName);
  247. CString strFileExtension;
  248. if (lpszFilterExt != NULL && *lpszFilterExt != 0)
  249. {
  250. // use file extension provided
  251. strFileExtension = lpszFilterExt;
  252. }
  253. else
  254. {
  255. // otherwise, try to find the extension from the description
  256. // parse the actual extension (eg "*.TLA") from the
  257. // filter name (eg, "Three Letter Acronym Files (*.TLA)")
  258. strFileExtension = lpszFilterName;
  259. int nBeginning = strFileExtension.Find('(');
  260. if (nBeginning == -1)
  261. strFileExtension.Empty();
  262. else
  263. {
  264. strFileExtension = strFileExtension.Mid(1+nBeginning);
  265. nBeginning = strFileExtension.Find('.');
  266. if (nBeginning == -1)
  267. strFileExtension.Empty();
  268. else
  269. {
  270. strFileExtension = strFileExtension.Mid(nBeginning);
  271. int nEnd = strFileExtension.Find(')');
  272. if (nEnd == -1)
  273. strFileExtension.Empty();
  274. else
  275. strFileExtension = strFileExtension.Left(nEnd);
  276. }
  277. }
  278. }
  279. refTable.SetAt(8, strFileExtension);
  280. return TRUE;
  281. }
  282. BOOL AFXAPI AfxOleRegisterServerClass(
  283. REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  284. LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister,
  285. LPCTSTR* rglpszOverwrite, int nIconIndex,
  286. LPCTSTR lpszFilterName)
  287. {
  288. return AfxOleRegisterServerClass(clsid, lpszClassName, lpszShortTypeName,
  289. lpszLongTypeName, nAppType, rglpszRegister, rglpszOverwrite, nIconIndex,
  290. lpszFilterName, NULL);
  291. }
  292. BOOL AFXAPI AfxOleRegisterServerClass(
  293. REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  294. LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister,
  295. LPCTSTR* rglpszOverwrite, int nIconIndex,
  296. LPCTSTR lpszFilterName, LPCTSTR lpszFilterExt)
  297. {
  298. ASSERT(AfxIsValidString(lpszClassName));
  299. ASSERT(AfxIsValidString(lpszShortTypeName));
  300. ASSERT(*lpszShortTypeName != 0);
  301. ASSERT(AfxIsValidString(lpszLongTypeName));
  302. ASSERT(*lpszLongTypeName != 0);
  303. ASSERT(nAppType == OAT_INPLACE_SERVER || nAppType == OAT_SERVER ||
  304. nAppType == OAT_CONTAINER || nAppType == OAT_DISPATCH_OBJECT ||
  305. nAppType == OAT_DOC_OBJECT_SERVER);
  306. ASSERT(nAppType >= 0 && nAppType < _countof(rgStdEntries));
  307. // use standard registration entries if non given
  308. if (rglpszRegister == NULL)
  309. rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister;
  310. if (rglpszOverwrite == NULL)
  311. {
  312. // DLL contexts have special strings
  313. if (!afxContextIsDLL)
  314. rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite;
  315. else
  316. rglpszOverwrite = (LPCTSTR*)rgStdEntriesDLL[nAppType].rglpszOverwrite;
  317. }
  318. CAfxOleSymbolTable table(NUM_REG_VARS);
  319. if (!_AfxOleMakeSymbolTable(table, clsid, lpszClassName,
  320. lpszShortTypeName, lpszLongTypeName,
  321. nIconIndex, lpszFilterName, lpszFilterExt))
  322. {
  323. return FALSE;
  324. }
  325. // protect against registering an invalid DocObject server
  326. ASSERT(nAppType != OAT_DOC_OBJECT_SERVER ||
  327. (lstrlen(table.GetAt(8)) != 0 && lstrcmp(table.GetAt(8), _T(".*")) != 0));
  328. // update the registry with helper function
  329. BOOL bResult;
  330. bResult = AfxOleRegisterHelper(rglpszRegister, table.GetArray(),
  331. NUM_REG_VARS, FALSE);
  332. if (bResult && rglpszOverwrite != NULL)
  333. {
  334. bResult = AfxOleRegisterHelper(rglpszOverwrite, table.GetArray(),
  335. NUM_REG_VARS, TRUE);
  336. }
  337. // free memory for class ID
  338. return bResult;
  339. }
  340. BOOL AFXAPI AfxOleUnregisterServerClass(
  341. REFCLSID clsid, LPCTSTR lpszClassName, LPCTSTR lpszShortTypeName,
  342. LPCTSTR lpszLongTypeName, OLE_APPTYPE nAppType, LPCTSTR* rglpszRegister,
  343. LPCTSTR* rglpszOverwrite)
  344. {
  345. // use standard registration entries if non given
  346. if (rglpszRegister == NULL)
  347. rglpszRegister = (LPCTSTR*)rgStdEntries[nAppType].rglpszRegister;
  348. if (rglpszOverwrite == NULL)
  349. {
  350. // DLL contexts have special strings
  351. if (!afxContextIsDLL)
  352. rglpszOverwrite = (LPCTSTR*)rgStdEntries[nAppType].rglpszOverwrite;
  353. else
  354. rglpszOverwrite = (LPCTSTR*)rgStdEntriesDLL[nAppType].rglpszOverwrite;
  355. }
  356. CAfxOleSymbolTable table(NUM_REG_VARS);
  357. if (!_AfxOleMakeSymbolTable(table, clsid, lpszClassName,
  358. lpszShortTypeName, lpszLongTypeName, 0, NULL, NULL))
  359. {
  360. return FALSE;
  361. }
  362. // clean up the the registry with helper function
  363. BOOL bResult;
  364. bResult = AfxOleUnregisterHelper(rglpszRegister, table.GetArray(),
  365. NUM_REG_VARS);
  366. if (bResult && rglpszOverwrite != NULL)
  367. {
  368. bResult = AfxOleUnregisterHelper(rglpszOverwrite, table.GetArray(),
  369. NUM_REG_VARS);
  370. }
  371. return bResult;
  372. }
  373. // removes key/value pairs from system registry
  374. BOOL AFXAPI AfxOleUnregisterHelper(LPCTSTR const* rglpszRegister,
  375. LPCTSTR const* rglpszSymbols, int nSymbols,
  376. HKEY hKeyRoot /* = HKEY_CLASSES_ROOT */)
  377. {
  378. ASSERT(rglpszRegister != NULL);
  379. ASSERT(nSymbols == 0 || rglpszSymbols != NULL);
  380. CString strKey;
  381. CString strValue;
  382. // keeping a key open makes this go a bit faster
  383. HKEY hKeyTemp = NULL;
  384. if (hKeyRoot == HKEY_CLASSES_ROOT)
  385. RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKeyTemp);
  386. BOOL bResult = TRUE;
  387. while (*rglpszRegister != NULL)
  388. {
  389. LPCTSTR lpszKey = *rglpszRegister++;
  390. if ((hKeyRoot == HKEY_CLASSES_ROOT) && (*lpszKey == '\0'))
  391. continue;
  392. AfxFormatStrings(strKey, lpszKey, rglpszSymbols, nSymbols);
  393. if ((hKeyRoot == HKEY_CLASSES_ROOT) && strKey.IsEmpty())
  394. {
  395. TRACE1("Warning: skipping empty key '%s'.\n", lpszKey);
  396. continue;
  397. }
  398. _AfxDeleteRegKey(strKey);
  399. }
  400. if (hKeyTemp != NULL)
  401. RegCloseKey(hKeyTemp);
  402. return bResult;
  403. }
  404. // writes key/value pairs to system registry
  405. BOOL AFXAPI AfxOleRegisterHelper(LPCTSTR const* rglpszRegister,
  406. LPCTSTR const* rglpszSymbols, int nSymbols, BOOL bReplace,
  407. HKEY hKeyRoot /* = HKEY_CLASSES_ROOT */)
  408. {
  409. ASSERT(rglpszRegister != NULL);
  410. ASSERT(nSymbols == 0 || rglpszSymbols != NULL);
  411. CString strKey;
  412. CString strValue;
  413. // keeping a key open makes this go a bit faster
  414. HKEY hKeyTemp = NULL;
  415. if (hKeyRoot == HKEY_CLASSES_ROOT)
  416. RegOpenKey(HKEY_CLASSES_ROOT, _T("CLSID"), &hKeyTemp);
  417. BOOL bResult = TRUE;
  418. while (*rglpszRegister != NULL)
  419. {
  420. LPCTSTR lpszKey = *rglpszRegister++;
  421. if ((hKeyRoot == HKEY_CLASSES_ROOT) && (*lpszKey == '\0'))
  422. continue;
  423. LPCTSTR lpszValue = lpszKey + lstrlen(lpszKey) + 1;
  424. AfxFormatStrings(strKey, lpszKey, rglpszSymbols, nSymbols);
  425. AfxFormatStrings(strValue, lpszValue, rglpszSymbols, nSymbols);
  426. if ((hKeyRoot == HKEY_CLASSES_ROOT) && strKey.IsEmpty())
  427. {
  428. TRACE1("Warning: skipping empty key '%s'.\n", lpszKey);
  429. continue;
  430. }
  431. if (!bReplace)
  432. {
  433. TCHAR szBuffer[256];
  434. LONG lSize = sizeof(szBuffer);
  435. if (::RegQueryValue(hKeyRoot, strKey, szBuffer, &lSize) ==
  436. ERROR_SUCCESS)
  437. {
  438. #ifdef _DEBUG
  439. if (strValue != szBuffer)
  440. {
  441. TRACE2("Warning: Leaving value '%s' for key '%s' in registry\n",
  442. szBuffer, (LPCTSTR)strKey);
  443. TRACE1("\tintended value was '%s'.\n", (LPCTSTR)strValue);
  444. }
  445. #endif
  446. continue;
  447. }
  448. }
  449. if (::RegSetValue(hKeyRoot, strKey, REG_SZ, strValue, lstrlen(strValue) * sizeof(TCHAR))
  450. != ERROR_SUCCESS)
  451. {
  452. TRACE2("Error: failed setting key '%s' to value '%s'.\n",
  453. (LPCTSTR)strKey, (LPCTSTR)strValue);
  454. bResult = FALSE;
  455. break;
  456. }
  457. }
  458. if (hKeyTemp != NULL)
  459. RegCloseKey(hKeyTemp);
  460. return bResult;
  461. }
  462. /////////////////////////////////////////////////////////////////////////////