ctlreg.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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. #ifdef AFXCTL_FACT_SEG
  12. #pragma code_seg(AFXCTL_FACT_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. #define GUID_CCH 39 // Characters in string form of guid, including '\0'
  20. inline BOOL _AfxRegDeleteKeySucceeded(LONG error)
  21. {
  22. return (error == ERROR_SUCCESS) || (error == ERROR_BADKEY) ||
  23. (error == ERROR_FILE_NOT_FOUND);
  24. }
  25. // Under Win32, a reg key may not be deleted unless it is empty.
  26. // Thus, to delete a tree, one must recursively enumerate and
  27. // delete all of the sub-keys.
  28. LONG AFXAPI _AfxRecursiveRegDeleteKey(HKEY hParentKey, LPTSTR szKeyName)
  29. {
  30. // one implementation for everybody
  31. return AfxDelRegTreeHelper(hParentKey, szKeyName);
  32. }
  33. void _AfxUnregisterInterfaces(ITypeLib* pTypeLib)
  34. {
  35. TCHAR szKey[128];
  36. lstrcpy(szKey, _T("Interface\\"));
  37. LPTSTR pszGuid = szKey + lstrlen(szKey);
  38. int cTypeInfo = pTypeLib->GetTypeInfoCount();
  39. for (int i = 0; i < cTypeInfo; i++)
  40. {
  41. TYPEKIND tk;
  42. if (SUCCEEDED(pTypeLib->GetTypeInfoType(i, &tk)) &&
  43. (tk == TKIND_DISPATCH || tk == TKIND_INTERFACE))
  44. {
  45. ITypeInfo* pTypeInfo = NULL;
  46. if (SUCCEEDED(pTypeLib->GetTypeInfo(i, &pTypeInfo)))
  47. {
  48. TYPEATTR* pTypeAttr;
  49. if (SUCCEEDED(pTypeInfo->GetTypeAttr(&pTypeAttr)))
  50. {
  51. #if defined(_UNICODE) || defined(OLE2ANSI)
  52. StringFromGUID2(pTypeAttr->guid, pszGuid, GUID_CCH);
  53. #else
  54. WCHAR wszGuid[39];
  55. StringFromGUID2(pTypeAttr->guid, wszGuid, GUID_CCH);
  56. _wcstombsz(pszGuid, wszGuid, GUID_CCH);
  57. #endif
  58. _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  59. pTypeInfo->ReleaseTypeAttr(pTypeAttr);
  60. }
  61. pTypeInfo->Release();
  62. }
  63. }
  64. }
  65. }
  66. BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
  67. LPCTSTR pszFileName, LPCTSTR pszHelpDir)
  68. {
  69. USES_CONVERSION;
  70. BOOL bSuccess = FALSE;
  71. CString strPathName;
  72. TCHAR *szPathName = strPathName.GetBuffer(_MAX_PATH);
  73. ::GetModuleFileName(hInstance, szPathName, _MAX_PATH);
  74. strPathName.ReleaseBuffer();
  75. LPTYPELIB ptlib = NULL;
  76. // If a filename was specified, replace final component of path with it.
  77. if (pszFileName != NULL)
  78. {
  79. int iBackslash = strPathName.ReverseFind('\\');
  80. if (iBackslash != -1)
  81. strPathName = strPathName.Left(iBackslash+1);
  82. strPathName += pszFileName;
  83. }
  84. if (SUCCEEDED(LoadTypeLib(T2COLE(strPathName), &ptlib)))
  85. {
  86. ASSERT_POINTER(ptlib, ITypeLib);
  87. LPTLIBATTR pAttr;
  88. GUID tlidActual = GUID_NULL;
  89. if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
  90. {
  91. ASSERT_POINTER(pAttr, TLIBATTR);
  92. tlidActual = pAttr->guid;
  93. ptlib->ReleaseTLibAttr(pAttr);
  94. }
  95. // Check that the guid of the loaded type library matches
  96. // the tlid parameter.
  97. ASSERT(IsEqualGUID(tlid, tlidActual));
  98. if (IsEqualGUID(tlid, tlidActual))
  99. {
  100. // Register the type library.
  101. if (SUCCEEDED(RegisterTypeLib(ptlib,
  102. T2OLE((LPTSTR)(LPCTSTR)strPathName), T2OLE((LPTSTR)pszHelpDir))))
  103. bSuccess = TRUE;
  104. }
  105. RELEASE(ptlib);
  106. }
  107. else
  108. {
  109. TRACE1("Warning: Could not load type library from %s\n", (LPCTSTR)strPathName);
  110. }
  111. return bSuccess;
  112. }
  113. #define TYPELIBWIN _T("win32")
  114. #define TYPELIBWIN_2 _T("win16")
  115. BOOL AFXAPI AfxOleUnregisterTypeLib(REFGUID tlid, WORD wVerMajor,
  116. WORD wVerMinor, LCID lcid)
  117. {
  118. USES_CONVERSION;
  119. // Load type library before unregistering it.
  120. ITypeLib* pTypeLib = NULL;
  121. if (wVerMajor != 0)
  122. {
  123. if (FAILED(LoadRegTypeLib(tlid, wVerMajor, wVerMinor, lcid, &pTypeLib)))
  124. pTypeLib = NULL;
  125. }
  126. // Format typelib guid as a string
  127. OLECHAR szTypeLibID[GUID_CCH];
  128. int cchGuid = ::StringFromGUID2(tlid, szTypeLibID, GUID_CCH);
  129. ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
  130. if (cchGuid != GUID_CCH)
  131. return FALSE;
  132. TCHAR szKeyTypeLib[_MAX_PATH];
  133. BOOL bSurgical = FALSE;
  134. LONG error = ERROR_SUCCESS;
  135. wsprintf(szKeyTypeLib, _T("TYPELIB\\%s"), OLE2CT(szTypeLibID));
  136. HKEY hKeyTypeLib;
  137. if (RegOpenKey(HKEY_CLASSES_ROOT, szKeyTypeLib, &hKeyTypeLib) ==
  138. ERROR_SUCCESS)
  139. {
  140. int iKeyVersion = 0;
  141. HKEY hKeyVersion;
  142. TCHAR szVersion[_MAX_PATH];
  143. // Iterate through all installed versions of the control
  144. while (RegEnumKey(hKeyTypeLib, iKeyVersion, szVersion, _MAX_PATH) ==
  145. ERROR_SUCCESS)
  146. {
  147. hKeyVersion = NULL;
  148. BOOL bSurgicalVersion = FALSE;
  149. if (RegOpenKey(hKeyTypeLib, szVersion, &hKeyVersion) !=
  150. ERROR_SUCCESS)
  151. {
  152. ++iKeyVersion;
  153. continue;
  154. }
  155. int iKeyLocale = 0;
  156. HKEY hKeyLocale;
  157. TCHAR szLocale[_MAX_PATH];
  158. // Iterate through all registered locales for this version
  159. while (RegEnumKey(hKeyVersion, iKeyLocale, szLocale, _MAX_PATH) ==
  160. ERROR_SUCCESS)
  161. {
  162. // Don't remove HELPDIR or FLAGS keys.
  163. if ((lstrcmpi(szLocale, _T("HELPDIR")) == 0) ||
  164. (lstrcmpi(szLocale, _T("FLAGS")) == 0))
  165. {
  166. ++iKeyLocale;
  167. continue;
  168. }
  169. hKeyLocale = NULL;
  170. if (RegOpenKey(hKeyVersion, szLocale, &hKeyLocale) !=
  171. ERROR_SUCCESS)
  172. {
  173. ++iKeyLocale;
  174. continue;
  175. }
  176. // Check if a 16-bit key is found when unregistering 32-bit
  177. HKEY hkey;
  178. if (RegOpenKey(hKeyLocale, TYPELIBWIN_2, &hkey) ==
  179. ERROR_SUCCESS)
  180. {
  181. RegCloseKey(hkey);
  182. // Only remove the keys specific to the 32-bit version
  183. // of control, leaving things intact for 16-bit version.
  184. error = _AfxRecursiveRegDeleteKey(hKeyLocale, TYPELIBWIN);
  185. bSurgicalVersion = TRUE;
  186. RegCloseKey(hKeyLocale);
  187. }
  188. else
  189. {
  190. // Delete everything for this locale.
  191. RegCloseKey(hKeyLocale);
  192. if (_AfxRecursiveRegDeleteKey(hKeyVersion, szLocale) ==
  193. ERROR_SUCCESS)
  194. {
  195. // Start over again, so we don't skip anything.
  196. iKeyLocale = 0;
  197. continue;
  198. }
  199. }
  200. ++iKeyLocale;
  201. }
  202. RegCloseKey(hKeyVersion);
  203. if (bSurgicalVersion)
  204. {
  205. bSurgical = TRUE;
  206. }
  207. else
  208. {
  209. if (_AfxRecursiveRegDeleteKey(hKeyTypeLib, szVersion) ==
  210. ERROR_SUCCESS)
  211. {
  212. // Start over again, to make sure we don't skip anything.
  213. iKeyVersion = 0;
  214. continue;
  215. }
  216. }
  217. ++iKeyVersion;
  218. }
  219. RegCloseKey(hKeyTypeLib);
  220. }
  221. if (!bSurgical)
  222. error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT, szKeyTypeLib);
  223. if (_AfxRegDeleteKeySucceeded(error))
  224. {
  225. // If type library was unregistered successfully, then also unregister
  226. // interfaces.
  227. if (pTypeLib != NULL)
  228. {
  229. ITypeLib* pDummy = NULL;
  230. if (FAILED(LoadRegTypeLib(tlid, wVerMajor, wVerMinor, lcid, &pDummy)))
  231. _AfxUnregisterInterfaces(pTypeLib);
  232. else
  233. pDummy->Release();
  234. pTypeLib->Release();
  235. }
  236. }
  237. return _AfxRegDeleteKeySucceeded(error);
  238. }
  239. AFX_STATIC_DATA const LPCTSTR _afxCtrlProgID[] =
  240. {
  241. _T("\0") _T("%1"),
  242. _T("CLSID\0") _T("%2"),
  243. NULL
  244. };
  245. #define INPROCSERVER _T("InprocServer32")
  246. #define INPROCSERVER_2 _T("InprocServer")
  247. #define TOOLBOXBITMAP _T("ToolboxBitmap32")
  248. AFX_STATIC_DATA const LPCTSTR _afxCtrlClassID[] =
  249. {
  250. _T("\0") _T("%1"),
  251. _T("ProgID\0") _T("%2"),
  252. INPROCSERVER _T("\0%3"),
  253. TOOLBOXBITMAP _T("\0%3, %4"),
  254. _T("MiscStatus\0") _T("0"),
  255. _T("MiscStatus\\1\0") _T("%5"),
  256. _T("Control\0") _T(""),
  257. _T("TypeLib\0") _T("%6"),
  258. _T("Version\0") _T("%7"),
  259. NULL
  260. };
  261. BOOL AFXAPI AfxOleRegisterControlClass(HINSTANCE hInstance,
  262. REFCLSID clsid, LPCTSTR pszProgID, UINT idTypeName, UINT idBitmap,
  263. int nRegFlags, DWORD dwMiscStatus, REFGUID tlid, WORD wVerMajor,
  264. WORD wVerMinor)
  265. {
  266. USES_CONVERSION;
  267. BOOL bSuccess = FALSE;
  268. // Format class ID as a string
  269. OLECHAR szClassID[GUID_CCH];
  270. int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
  271. LPCTSTR lpszClassID = OLE2CT(szClassID);
  272. ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
  273. if (cchGuid != GUID_CCH)
  274. return FALSE;
  275. // Format typelib guid as a string
  276. OLECHAR szTypeLibID[GUID_CCH];
  277. cchGuid = ::StringFromGUID2(tlid, szTypeLibID, GUID_CCH);
  278. ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
  279. if (cchGuid != GUID_CCH)
  280. return FALSE;
  281. CString strPathName;
  282. AfxGetModuleShortFileName(hInstance, strPathName);
  283. CString strTypeName;
  284. if (!strTypeName.LoadString(idTypeName))
  285. {
  286. ASSERT(FALSE); // Name string not present in resources
  287. strTypeName = lpszClassID; // Use Class ID instead
  288. }
  289. TCHAR szBitmapID[_MAX_PATH];
  290. _itot(idBitmap, szBitmapID, 10);
  291. TCHAR szMiscStatus[_MAX_PATH];
  292. _ltot(dwMiscStatus, szMiscStatus, 10);
  293. // Format version string as "major.minor"
  294. TCHAR szVersion[_MAX_PATH];
  295. wsprintf(szVersion, _T("%d.%d"), wVerMajor, wVerMinor);
  296. // Attempt to open registry keys.
  297. HKEY hkeyClassID = NULL;
  298. HKEY hkeyProgID = NULL;
  299. TCHAR szScratch[_MAX_PATH];
  300. wsprintf(szScratch, _T("CLSID\\%s"), lpszClassID);
  301. if (::RegCreateKey(HKEY_CLASSES_ROOT, szScratch, &hkeyClassID) !=
  302. ERROR_SUCCESS)
  303. goto Error;
  304. if (::RegCreateKey(HKEY_CLASSES_ROOT, pszProgID, &hkeyProgID) !=
  305. ERROR_SUCCESS)
  306. goto Error;
  307. ASSERT(hkeyClassID != NULL);
  308. ASSERT(hkeyProgID != NULL);
  309. LPCTSTR rglpszSymbols[7];
  310. rglpszSymbols[0] = strTypeName;
  311. rglpszSymbols[1] = lpszClassID;
  312. bSuccess = AfxOleRegisterHelper(_afxCtrlProgID, rglpszSymbols, 2,
  313. TRUE, hkeyProgID);
  314. if (!bSuccess)
  315. goto Error;
  316. rglpszSymbols[1] = pszProgID;
  317. rglpszSymbols[2] = strPathName;
  318. rglpszSymbols[3] = szBitmapID;
  319. rglpszSymbols[4] = szMiscStatus;
  320. rglpszSymbols[5] = OLE2CT(szTypeLibID);
  321. rglpszSymbols[6] = szVersion;
  322. bSuccess = AfxOleRegisterHelper(_afxCtrlClassID, rglpszSymbols, 7,
  323. TRUE, hkeyClassID);
  324. if (!bSuccess)
  325. goto Error;
  326. if (nRegFlags & afxRegInsertable)
  327. {
  328. bSuccess =
  329. (::RegSetValue(hkeyProgID, _T("Insertable"), REG_SZ, _T(""), 0) ==
  330. ERROR_SUCCESS) &&
  331. (::RegSetValue(hkeyClassID, _T("Insertable"), REG_SZ, _T(""), 0) ==
  332. ERROR_SUCCESS);
  333. }
  334. if (nRegFlags & afxRegApartmentThreading)
  335. {
  336. HKEY hkeyInprocServer32;
  337. bSuccess = (::RegOpenKey(hkeyClassID, INPROCSERVER,
  338. &hkeyInprocServer32) == ERROR_SUCCESS);
  339. if (!bSuccess)
  340. goto Error;
  341. ASSERT(hkeyInprocServer32 != NULL);
  342. static TCHAR szApartment[] = _T("Apartment");
  343. bSuccess = (::RegSetValueEx(hkeyInprocServer32, _T("ThreadingModel"), 0,
  344. REG_SZ, (const BYTE*)szApartment, (lstrlen(szApartment)+1) * sizeof(TCHAR)) ==
  345. ERROR_SUCCESS);
  346. ::RegCloseKey(hkeyInprocServer32);
  347. }
  348. Error:
  349. if (hkeyProgID != NULL)
  350. ::RegCloseKey(hkeyProgID);
  351. if (hkeyClassID != NULL)
  352. ::RegCloseKey(hkeyClassID);
  353. return bSuccess;
  354. }
  355. BOOL AFXAPI AfxOleUnregisterClass(REFCLSID clsid, LPCTSTR pszProgID)
  356. {
  357. USES_CONVERSION;
  358. // Format class ID as a string
  359. OLECHAR szClassID[GUID_CCH];
  360. int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
  361. LPCTSTR lpszClassID = OLE2CT(szClassID);
  362. ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
  363. if (cchGuid != GUID_CCH)
  364. return FALSE;
  365. TCHAR szKey[_MAX_PATH];
  366. long error;
  367. BOOL bRetCode = TRUE;
  368. // check to see if a 16-bit InprocServer key is found when unregistering
  369. // 32-bit (or vice versa).
  370. wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, INPROCSERVER_2);
  371. HKEY hkey;
  372. BOOL bSurgical = RegOpenKey(HKEY_CLASSES_ROOT, szKey, &hkey) ==
  373. ERROR_SUCCESS;
  374. if (bSurgical)
  375. {
  376. // Only remove the keys specific to this version of the control,
  377. // leaving things in tact for the other version.
  378. wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, INPROCSERVER);
  379. error = RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  380. bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
  381. wsprintf(szKey, _T("CLSID\\%s\\%s"), lpszClassID, TOOLBOXBITMAP);
  382. error = RegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  383. bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
  384. }
  385. else
  386. {
  387. // No other versions of this control were detected,
  388. // so go ahead and remove the control completely.
  389. wsprintf(szKey, _T("CLSID\\%s"), lpszClassID);
  390. error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT, szKey);
  391. bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
  392. if (pszProgID != NULL)
  393. {
  394. error = _AfxRecursiveRegDeleteKey(HKEY_CLASSES_ROOT,
  395. (LPTSTR)pszProgID);
  396. bRetCode = bRetCode && _AfxRegDeleteKeySucceeded(error);
  397. }
  398. }
  399. return bRetCode;
  400. }
  401. AFX_STATIC_DATA const LPCTSTR _afxPropPageClass[] =
  402. {
  403. _T("\0") _T("%1"),
  404. INPROCSERVER _T("\0%2"),
  405. NULL
  406. };
  407. BOOL AFXAPI AfxOleRegisterPropertyPageClass(HINSTANCE hInstance,
  408. REFCLSID clsid, UINT idTypeName)
  409. {
  410. return AfxOleRegisterPropertyPageClass(hInstance, clsid, idTypeName, 0);
  411. }
  412. BOOL AFXAPI AfxOleRegisterPropertyPageClass(HINSTANCE hInstance,
  413. REFCLSID clsid, UINT idTypeName, int nRegFlags)
  414. {
  415. ASSERT(!(nRegFlags & afxRegInsertable)); // can't be insertable
  416. USES_CONVERSION;
  417. BOOL bSuccess = FALSE;
  418. // Format class ID as a string
  419. OLECHAR szClassID[GUID_CCH];
  420. int cchGuid = ::StringFromGUID2(clsid, szClassID, GUID_CCH);
  421. LPCTSTR lpszClassID = OLE2CT(szClassID);
  422. ASSERT(cchGuid == GUID_CCH); // Did StringFromGUID2 work?
  423. if (cchGuid != GUID_CCH)
  424. return FALSE;
  425. CString strPathName;
  426. AfxGetModuleShortFileName(hInstance, strPathName);
  427. CString strTypeName;
  428. if (!strTypeName.LoadString(idTypeName))
  429. {
  430. ASSERT(FALSE); // Name string not present in resources
  431. strTypeName = lpszClassID; // Use Class ID instead
  432. }
  433. HKEY hkeyClassID = NULL;
  434. TCHAR szKey[_MAX_PATH];
  435. wsprintf(szKey, _T("CLSID\\%s"), lpszClassID);
  436. if (::RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hkeyClassID) !=
  437. ERROR_SUCCESS)
  438. goto Error;
  439. LPCTSTR rglpszSymbols[2];
  440. rglpszSymbols[0] = strTypeName;
  441. rglpszSymbols[1] = strPathName;
  442. bSuccess = AfxOleRegisterHelper(_afxPropPageClass, rglpszSymbols,
  443. 2, TRUE, hkeyClassID);
  444. if (!bSuccess)
  445. goto Error;
  446. if (nRegFlags & afxRegApartmentThreading)
  447. {
  448. HKEY hkeyInprocServer32;
  449. bSuccess = (::RegOpenKey(hkeyClassID, INPROCSERVER,
  450. &hkeyInprocServer32) == ERROR_SUCCESS);
  451. if (!bSuccess)
  452. goto Error;
  453. ASSERT(hkeyInprocServer32 != NULL);
  454. static TCHAR szApartment[] = _T("Apartment");
  455. bSuccess = (::RegSetValueEx(hkeyInprocServer32, _T("ThreadingModel"), 0,
  456. REG_SZ, (const BYTE*)szApartment, (lstrlen(szApartment)+1) * sizeof(TCHAR)) ==
  457. ERROR_SUCCESS);
  458. ::RegCloseKey(hkeyInprocServer32);
  459. }
  460. Error:
  461. if (hkeyClassID != NULL)
  462. ::RegCloseKey(hkeyClassID);
  463. return bSuccess;
  464. }
  465. /////////////////////////////////////////////////////////////////////////////
  466. // Force any extra compiler-generated code into AFX_INIT_SEG
  467. #ifdef AFX_INIT_SEG
  468. #pragma code_seg(AFX_INIT_SEG)
  469. #endif