Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

804 lines
21 KiB

  1. //=--------------------------------------------------------------------------=
  2. // InProcServer.Cpp
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // implements all exported DLL functions for the program, as well as a few
  13. // others that will be used by same
  14. //
  15. #include "pch.h"
  16. #include "LocalSrv.H"
  17. #include "AutoObj.H"
  18. #include "ClassF.H"
  19. #include "CtrlObj.H"
  20. #include "Unknown.H"
  21. #include "ComCat.H"
  22. #ifdef DEBUG
  23. #include "debug.h"
  24. #include <winbase.h>
  25. #endif // DEBUG
  26. // for ASSERT and FAIL
  27. //
  28. SZTHISFILE
  29. #ifdef VS_HELP
  30. #include "vshelp.h"
  31. extern IVsHelpSystem *g_pIVsHelpSystem;
  32. #endif
  33. //=--------------------------------------------------------------------------=
  34. // Private module level data
  35. //
  36. //=--------------------------------------------------------------------------=
  37. // These are used for reflection in OLE Controls. Not that big of a hit that
  38. // we mind defining them for all servers, including automation or generic
  39. // COM.
  40. //
  41. // Make this a constant.
  42. extern const char g_szReflectClassName [] = "CtlFrameWork_ReflectWindow";
  43. BYTE g_fRegisteredReflect = FALSE;
  44. BOOL g_fDBCSEnabled = FALSE;
  45. extern HINSTANCE g_hInstResources;
  46. extern HINSTANCE g_hinstVersion;
  47. #ifdef MDAC_BUILD
  48. extern HINSTANCE g_hOleAutHandle;
  49. #else
  50. extern HANDLE g_hOleAutHandle;
  51. #endif
  52. extern const int g_ctCATIDImplemented;
  53. extern const CATID* g_rgCATIDImplemented[];
  54. // ref count for LockServer
  55. //
  56. LONG g_cLocks;
  57. // private routines for this file.
  58. //
  59. int IndexOfOleObject(REFCLSID);
  60. HRESULT RegisterAllObjects(void);
  61. HRESULT UnregisterAllObjects(void);
  62. void CleanupGlobalObjects(void);
  63. //=--------------------------------------------------------------------------=
  64. // DllMain
  65. //=--------------------------------------------------------------------------=
  66. // yon standard LibMain.
  67. //
  68. // Parameters and Output:
  69. // - see SDK Docs on DllMain
  70. //
  71. // Notes:
  72. //
  73. BOOL WINAPI DllMain
  74. (
  75. HANDLE hInstance,
  76. DWORD dwReason,
  77. void *pvReserved
  78. )
  79. {
  80. // int i;
  81. switch (dwReason) {
  82. // set up some global variables, and get some OS/Version information
  83. // set up.
  84. //
  85. case DLL_PROCESS_ATTACH:
  86. {
  87. DWORD dwVer = GetVersion();
  88. DWORD dwWinVer;
  89. // swap the two lowest bytes of dwVer so that the major and minor version
  90. // numbers are in a usable order.
  91. // for dwWinVer: high byte = major version, low byte = minor version
  92. // OS Sys_WinVersion (as of 5/2/95)
  93. // =-------------= =-------------=
  94. // Win95 0x035F (3.95)
  95. // WinNT ProgMan 0x0333 (3.51)
  96. // WinNT Win95 UI 0x0400 (4.00)
  97. //
  98. dwWinVer = (UINT)(((dwVer & 0xFF) << 8) | ((dwVer >> 8) & 0xFF));
  99. g_fSysWinNT = FALSE;
  100. g_fSysWin95 = FALSE;
  101. g_fSysWin95Shell = FALSE;
  102. if (dwVer < 0x80000000) {
  103. g_fSysWinNT = TRUE;
  104. g_fSysWin95Shell = (dwWinVer >= 0x0334);
  105. } else {
  106. g_fSysWin95 = TRUE;
  107. g_fSysWin95Shell = TRUE;
  108. }
  109. // initialize a critical seciton for our apartment threading support
  110. //
  111. InitializeCriticalSection(&g_CriticalSection);
  112. // create an initial heap for everybody to use.
  113. // currently, we're going to let the system make things thread-safe,
  114. // which will make them a little slower, but hopefully not enough
  115. // to notice
  116. //
  117. if (!g_hHeap)
  118. g_hHeap = GetProcessHeap();
  119. if (!g_hHeap) {
  120. FAIL("Couldn't get Process Heap. Not good!");
  121. return FALSE;
  122. }
  123. g_hInstance = (HINSTANCE)hInstance;
  124. // this causes DllMain to NOT get called for DLL_THREAD_ATTACH and DETACH.
  125. // if you are interested in these notifications, please remove this line.
  126. //
  127. DisableThreadLibraryCalls(g_hInstance);
  128. g_fDBCSEnabled = GetSystemMetrics(SM_DBCSENABLED);
  129. // Initialize OleAut
  130. //
  131. g_hOleAutHandle = LoadLibrary("oleaut32.dll");
  132. // give the user a chance to initialize whatever
  133. //
  134. InitializeLibrary();
  135. #ifdef DEBUG
  136. TCHAR lpCtlName[255];
  137. DWORD nSize = 255;
  138. DWORD fValidPath;
  139. // set all ctl debug switches
  140. //
  141. fValidPath = GetModuleFileName(g_hInstance, (LPTSTR)lpCtlName, nSize);
  142. if (fValidPath != 0)
  143. SetCtlSwitches((LPSTR)lpCtlName);
  144. // initialize a critical seciton for our heap memory leak detection
  145. //
  146. InitializeCriticalSection(&g_csHeap);
  147. g_fInitCrit = TRUE;
  148. #endif // DEBUG
  149. return TRUE;
  150. }
  151. // do a little cleaning up!
  152. //
  153. case DLL_PROCESS_DETACH:
  154. #ifdef VS_HELP
  155. ASSERT(g_pIVsHelpSystem == NULL, "IVsHelpSystem didn't get released");
  156. #endif
  157. // clean up some stuff
  158. //
  159. DeleteCriticalSection(&g_CriticalSection);
  160. CleanupGlobalObjects();
  161. // give the user a chance to do some cleaning up
  162. //
  163. UninitializeLibrary();
  164. // Deinitialize OleAut, But not in Win95.
  165. // Calling FreeLibrary under Win95 for OleAut
  166. // will sometimes cause a crash (It seems that
  167. // there can be a rpoblem in which OleAut is called
  168. // from OleUnitnitialize and causes a problem with FreeLibrary.
  169. //
  170. if (g_hOleAutHandle && !g_fSysWin95)
  171. {
  172. FreeLibrary((HINSTANCE)g_hOleAutHandle);
  173. g_hOleAutHandle = NULL;
  174. }
  175. // Make sure we free up our cached resource handle for localized resources
  176. //
  177. if (g_hInstResources && g_hInstResources != g_hInstance)
  178. FreeLibrary(g_hInstResources);
  179. // Free up VERSION.DLL
  180. //
  181. if (g_hinstVersion)
  182. {
  183. FreeLibrary(g_hinstVersion);
  184. g_hinstVersion = NULL;
  185. }
  186. #ifdef DEBUG
  187. // check for memory leaks
  188. //
  189. CheckForLeaks();
  190. // free critical section used for leak checking
  191. //
  192. DeleteCriticalSection(&g_csHeap);
  193. g_fInitCrit = FALSE;
  194. #endif // DEBUG
  195. return TRUE;
  196. }
  197. return TRUE;
  198. }
  199. //=--------------------------------------------------------------------------=
  200. // CleanupGlobalObjects
  201. //=--------------------------------------------------------------------------=
  202. // duh
  203. //
  204. // Notes:
  205. //
  206. void CleanupGlobalObjects(void)
  207. {
  208. int i = 0;
  209. while (!ISEMPTYOBJECT(i)) {
  210. if (g_ObjectInfo[i].usType == OI_CONTROL) {
  211. if (CTLWNDCLASSREGISTERED(i))
  212. UnregisterClass(WNDCLASSNAMEOFCONTROL(i), g_hInstance);
  213. }
  214. i++;
  215. }
  216. // clean up our parking window.
  217. //
  218. if (g_hwndParking) {
  219. DestroyWindow(g_hwndParking);
  220. g_hwndParking = NULL;
  221. UnregisterClass("CtlFrameWork_Parking", g_hInstance);
  222. }
  223. // clean up after reflection, if appropriate.
  224. //
  225. if (g_fRegisteredReflect) {
  226. UnregisterClass(g_szReflectClassName, g_hInstance);
  227. g_fRegisteredReflect = FALSE;
  228. }
  229. }
  230. //=--------------------------------------------------------------------------=
  231. // DllRegisterServer
  232. //=--------------------------------------------------------------------------=
  233. // registers the Automation server
  234. //
  235. // Output:
  236. // HRESULT
  237. //
  238. // Notes:
  239. //
  240. STDAPI DllRegisterServer
  241. (
  242. void
  243. )
  244. {
  245. HRESULT hr;
  246. hr = RegisterAllObjects();
  247. RETURN_ON_FAILURE(hr);
  248. // call user registration function.
  249. //
  250. return (RegisterData())? S_OK : E_FAIL;
  251. }
  252. //=--------------------------------------------------------------------------=
  253. // DllUnregisterServer
  254. //=--------------------------------------------------------------------------=
  255. // unregister's the Automation server
  256. //
  257. // Output:
  258. // HRESULT
  259. //
  260. // Notes:
  261. //
  262. STDAPI DllUnregisterServer
  263. (
  264. void
  265. )
  266. {
  267. HRESULT hr;
  268. hr = UnregisterAllObjects();
  269. RETURN_ON_FAILURE(hr);
  270. // call user unregistration function
  271. //
  272. return (UnregisterData()) ? S_OK : E_FAIL;
  273. }
  274. //=--------------------------------------------------------------------------=
  275. // DllCanUnloadNow
  276. //=--------------------------------------------------------------------------=
  277. // we are being asked whether or not it's okay to unload the DLL. just check
  278. // the lock counts on remaining objects ...
  279. //
  280. // Output:
  281. // HRESULT - S_OK, can unload now, S_FALSE, can't.
  282. //
  283. // Notes:
  284. //
  285. STDAPI DllCanUnloadNow
  286. (
  287. void
  288. )
  289. {
  290. #ifdef VS_HELP
  291. if (g_pIVsHelpSystem)
  292. {
  293. g_pIVsHelpSystem->Release();
  294. g_pIVsHelpSystem = NULL;
  295. }
  296. #endif
  297. // if there are any objects lying around, then we can't unload. The
  298. // controlling CUnknownObject class that people should be inheriting from
  299. // takes care of this
  300. //
  301. #ifdef MDAC_BUILD
  302. return (g_cLocks || !CanUnloadLibraryNow()) ? S_FALSE : S_OK;
  303. #else
  304. return (g_cLocks) ? S_FALSE : S_OK;
  305. #endif
  306. }
  307. //=--------------------------------------------------------------------------=
  308. // DllGetClassObject
  309. //=--------------------------------------------------------------------------=
  310. // creates a ClassFactory object, and returns it.
  311. //
  312. // Parameters:
  313. // REFCLSID - CLSID for the class object
  314. // REFIID - interface we want class object to be.
  315. // void ** - pointer to where we should ptr to new object.
  316. //
  317. // Output:
  318. // HRESULT - S_OK, CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY,
  319. // E_INVALIDARG, E_UNEXPECTED
  320. //
  321. // Notes:
  322. //
  323. STDAPI DllGetClassObject
  324. (
  325. REFCLSID rclsid,
  326. REFIID riid,
  327. void **ppvObjOut
  328. )
  329. {
  330. HRESULT hr;
  331. void *pv;
  332. int iIndex;
  333. // arg checking
  334. //
  335. if (!ppvObjOut)
  336. return E_INVALIDARG;
  337. // first of all, make sure they're asking for something we work with.
  338. //
  339. iIndex = IndexOfOleObject(rclsid);
  340. if (iIndex == -1)
  341. #ifdef MDAC_BUILD
  342. // NOTE: LibraryGetClassObject() hook for ATL/VS98 support, added by markash
  343. return LibraryGetClassObject(rclsid, riid, ppvObjOut);
  344. #else
  345. return CLASS_E_CLASSNOTAVAILABLE;
  346. #endif
  347. // create the blank object.
  348. //
  349. pv = (void *)new CClassFactory(iIndex);
  350. if (!pv)
  351. return E_OUTOFMEMORY;
  352. // QI for whatever the user has asked for.
  353. //
  354. hr = ((IUnknown *)pv)->QueryInterface(riid, ppvObjOut);
  355. ((IUnknown *)pv)->Release();
  356. return hr;
  357. }
  358. //=--------------------------------------------------------------------------=
  359. // IndexOfOleObject
  360. //=--------------------------------------------------------------------------=
  361. // returns the index in our global table of objects of the given CLSID. if
  362. // it's not a supported object, then we return -1
  363. //
  364. // Parameters:
  365. // REFCLSID - [in] duh.
  366. //
  367. // Output:
  368. // int - >= 0 is index into global table, -1 means not supported
  369. //
  370. // Notes:
  371. //
  372. int IndexOfOleObject
  373. (
  374. REFCLSID rclsid
  375. )
  376. {
  377. int x = 0;
  378. // an object is creatable if it's CLSID is in the table of all allowable object
  379. // types.
  380. //
  381. while (!ISEMPTYOBJECT(x)) {
  382. if (OBJECTISCREATABLE(x)) {
  383. if (rclsid == CLSIDOFOBJECT(x))
  384. return x;
  385. }
  386. x++;
  387. }
  388. return -1;
  389. }
  390. //=--------------------------------------------------------------------------=
  391. // RegisterAllObjects
  392. //=--------------------------------------------------------------------------=
  393. // registers all the objects for the given automation server.
  394. //
  395. // Parameters:
  396. // none
  397. //
  398. // Output:
  399. // HERSULT - S_OK, E_FAIL
  400. //
  401. // Notes:
  402. //
  403. HRESULT RegisterAllObjects
  404. (
  405. void
  406. )
  407. {
  408. ITypeLib *pTypeLib = NULL;
  409. HRESULT hr;
  410. DWORD dwPathLen;
  411. char szTmp[MAX_PATH];
  412. char szHelpPath[MAX_PATH];
  413. int x = 0;
  414. BOOL fHelpFile = FALSE;
  415. long lMajor = -1, lMinor = -1;
  416. UINT cbWinHelpPath = 0;
  417. OLECHAR *pwszHelpPath;
  418. BSTR bstrTypeLibName = NULL;
  419. WORD wFlags = 0;
  420. #if DEBUG
  421. BOOL fCtlFlagFound = FALSE;
  422. BOOL fCtlTypeLib = FALSE;
  423. int iCatID;
  424. BOOL fCatIDFound = FALSE;
  425. #endif
  426. // Load and register our type library.
  427. //
  428. if (g_fServerHasTypeLibrary) {
  429. TLIBATTR *ptlattr;
  430. dwPathLen = GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  431. bstrTypeLibName = BSTRFROMANSI(szTmp);
  432. hr = LoadTypeLib(bstrTypeLibName, &pTypeLib);
  433. if (FAILED(hr)) goto CleanUp;
  434. pTypeLib->GetLibAttr(&ptlattr);
  435. lMajor = ptlattr->wMajorVerNum;
  436. lMinor = ptlattr->wMinorVerNum;
  437. #if DEBUG
  438. fCtlTypeLib = ptlattr->wLibFlags & LIBFLAG_FCONTROL;
  439. #endif
  440. pTypeLib->ReleaseTLibAttr(ptlattr);
  441. }
  442. // loop through all of our creatable objects [those that have a clsid in
  443. // our global table] and register them.
  444. //
  445. while (!ISEMPTYOBJECT(x)) {
  446. if (!OBJECTISCREATABLE(x)) {
  447. x++;
  448. continue;
  449. }
  450. // Check to see if there is a help file for the object
  451. // If so, look for it in the Windows\Help directory. If a help file is
  452. // found for any object in the Windows\Help directory, then we'll register it with
  453. // the typelib. Once we find the first help file we stop looking.
  454. //
  455. if (!fHelpFile) {
  456. if (cbWinHelpPath == 0) {
  457. cbWinHelpPath = GetHelpFilePath(szHelpPath, MAX_PATH);
  458. lstrcat(szHelpPath, "\\");
  459. cbWinHelpPath++;
  460. }
  461. ASSERT(cbWinHelpPath > 0, "Help path is zero length");
  462. ASSERT(cbWinHelpPath + ((HELPFILEOFOBJECT(x)) ? lstrlen(HELPFILEOFOBJECT(x)) : 0) < MAX_PATH, "Help file path exceeds maxiumu path");
  463. // Make sure we have a non-NULL pointer before calling lstrlen
  464. // and check that the helpfile exists and isn't a directory
  465. //
  466. if (HELPFILEOFOBJECT(x) && lstrlen(HELPFILEOFOBJECT(x)) > 0) {
  467. lstrcpyn(szHelpPath + cbWinHelpPath, HELPFILEOFOBJECT(x), lstrlen(HELPFILEOFOBJECT(x)) + 1);
  468. fHelpFile = ((GetFileAttributes(szHelpPath) & FILE_ATTRIBUTE_DIRECTORY) == 0);
  469. }
  470. // Once we've determined the help file exists, terminate after the filename
  471. // since all we care to register is the path. Not the path and filename. We also
  472. // don't want the terminating '\', so subtract 1 from cbWinHelpPath.
  473. //
  474. if (fHelpFile)
  475. szHelpPath[cbWinHelpPath - 1] = '\0';
  476. else
  477. szHelpPath[cbWinHelpPath] = '\0';
  478. }
  479. // depending on the object type, register different pieces of information
  480. //
  481. switch (g_ObjectInfo[x].usType) {
  482. // for both simple co-creatable objects and proeprty pages, do the same
  483. // thing
  484. //
  485. case OI_UNKNOWN:
  486. case OI_PROPERTYPAGE:
  487. #if DEBUG
  488. // For debug builds, verify that the cached object data matches the typeinfo attributes for that object
  489. //
  490. hr = GetTypeFlagsForGuid(pTypeLib, CLSIDOFOBJECT(x), &wFlags);
  491. if (SUCCEEDED(hr))
  492. {
  493. if (NULL != CREATEFNOFOBJECT(x))
  494. {
  495. ASSERT(wFlags & TYPEFLAG_FCANCREATE, "Create flag not found on creatable object");
  496. }
  497. else
  498. {
  499. ASSERT(!(wFlags & TYPEFLAG_FCANCREATE), "Create flag found on non-creatable object");
  500. }
  501. }
  502. #endif
  503. RegisterUnknownObject(NAMEOFOBJECT(x), LABELOFOBJECT(x), CLSIDOFOBJECT(x), ISAPARTMENTMODELTHREADED(x));
  504. break;
  505. case OI_AUTOMATION:
  506. #if DEBUG
  507. // For debug builds, verify that the cached object data matches the typeinfo attributes for that object
  508. //
  509. hr = GetTypeFlagsForGuid(pTypeLib, CLSIDOFOBJECT(x), &wFlags);
  510. if (SUCCEEDED(hr))
  511. {
  512. if (NULL != CREATEFNOFOBJECT(x))
  513. {
  514. ASSERT(wFlags & TYPEFLAG_FCANCREATE, "Create flag not found on creatable object");
  515. }
  516. else
  517. {
  518. ASSERT(!(wFlags & TYPEFLAG_FCANCREATE), "Create flag found on non-creatable object");
  519. }
  520. }
  521. #endif
  522. RegisterAutomationObject(g_szLibName, NAMEOFOBJECT(x), LABELOFOBJECT(x), VERSIONOFOBJECT(x),
  523. lMajor, lMinor, *g_pLibid, CLSIDOFOBJECT(x), ISAPARTMENTMODELTHREADED(x));
  524. break;
  525. case OI_CONTROL:
  526. {
  527. BOOL fControl = TRUE;
  528. // Go to the TypeInfo for the object and see if it has the control bit set
  529. // We should only add the Control and ToolboxBitmap32 registry key for objects
  530. // that have the Control bit set in their typelib.
  531. //
  532. // Note: If the TypeLib can't be found or there is an error attempting to
  533. // retrieve the control flag, we default to setting the Control bit.
  534. // Since we're attempting to register the object as a control our
  535. // default assumption will be that it is a control.
  536. //
  537. hr = GetTypeFlagsForGuid(pTypeLib, CLSIDOFOBJECT(x), &wFlags);
  538. if (SUCCEEDED(hr))
  539. {
  540. fControl = wFlags & TYPEFLAG_FCONTROL;
  541. #if DEBUG
  542. fCtlFlagFound |= fControl;
  543. // For debug builds, verify that the cached object data matches the typeinfo attributes for that object
  544. //
  545. if (NULL != CREATEFNOFOBJECT(x))
  546. {
  547. ASSERT(wFlags & TYPEFLAG_FCANCREATE, "Create flag not found on creatable object");
  548. }
  549. else
  550. {
  551. ASSERT(!(wFlags & TYPEFLAG_FCANCREATE), "Create flag found on non-creatable object");
  552. }
  553. #endif
  554. }
  555. RegisterControlObject(g_szLibName, NAMEOFOBJECT(x), LABELOFOBJECT(x),
  556. VERSIONOFOBJECT(x), VERSIONMINOROFOBJECT(x),
  557. lMajor, lMinor,
  558. *g_pLibid, CLSIDOFOBJECT(x), OLEMISCFLAGSOFCONTROL(x),
  559. BITMAPIDOFCONTROL(x), ISAPARTMENTMODELTHREADED(x),
  560. fControl);
  561. }
  562. break;
  563. }
  564. x++;
  565. }
  566. // Make sure the if a TypeLib control attribute was found, a coclass control attribute is also found;
  567. // or neither is found. You can't have one without the other.
  568. //
  569. ASSERT((fCtlTypeLib && fCtlFlagFound) ||
  570. (!fCtlTypeLib && !fCtlFlagFound), "TypeLib and coclass control attributes not set consistently");
  571. if (g_fServerHasTypeLibrary)
  572. {
  573. ASSERT(pTypeLib, "TypeLib pointer is NULL");
  574. ASSERT(SysStringLen(bstrTypeLibName) > 0, "TypeLib name is invalid");
  575. if (fHelpFile)
  576. pwszHelpPath = OLESTRFROMANSI(szHelpPath);
  577. // Note: we have to pass in an empty string instead of NULL if fHelpFile==FALSE, because
  578. // otherwise OLEAUT leaves the old value of the HELPDIR key there (stephwe 9/97)
  579. hr = RegisterTypeLib(pTypeLib, bstrTypeLibName, fHelpFile ? pwszHelpPath : L"");
  580. if (fHelpFile)
  581. CoTaskMemFree(pwszHelpPath);
  582. pTypeLib->Release();
  583. if (FAILED(hr)) goto CleanUp;
  584. }
  585. #if DEBUG
  586. // Make sure there is consistency between the Control flags set in the typelib
  587. // versus the CATID_Control attribute.
  588. //
  589. for (iCatID=0; iCatID < g_ctCATIDImplemented; iCatID++)
  590. {
  591. if (IsEqualGUID((REFGUID) *g_rgCATIDImplemented[iCatID], (REFGUID) CATID_Control))
  592. {
  593. fCatIDFound = TRUE;
  594. break;
  595. }
  596. }
  597. ASSERT((fCatIDFound && fCtlFlagFound) ||
  598. (!fCatIDFound && !fCtlFlagFound), "Typelib control attribute not in sync with CATID_Control setting");
  599. #endif
  600. hr = S_OK;
  601. CleanUp:
  602. SysFreeString(bstrTypeLibName);
  603. return hr;
  604. }
  605. //=--------------------------------------------------------------------------=
  606. // UnregisterAllObjects
  607. //=--------------------------------------------------------------------------=
  608. // un-registers all the objects for the given automation server.
  609. //
  610. // Parameters:
  611. // none
  612. //
  613. // Output:
  614. // HRESULT - S_OK
  615. //
  616. // Notes:
  617. // WARNING! You must link with the new version of OLEAUT shipping with
  618. // Visual Basic version 5.0 in order for this function to
  619. // work correctly.
  620. //
  621. HRESULT UnregisterAllObjects
  622. (
  623. void
  624. )
  625. {
  626. HRESULT hr;
  627. int x = 0;
  628. char szTmp[MAX_PATH];
  629. TLIBATTR *ptlibattr = NULL;
  630. ITypeLib *pTypeLib = NULL;
  631. // loop through all of our creatable objects [those that have a clsid in
  632. // our global table] and register them.
  633. //
  634. while (!ISEMPTYOBJECT(x)) {
  635. if (!OBJECTISCREATABLE(x)) {
  636. x++;
  637. continue;
  638. }
  639. switch (g_ObjectInfo[x].usType) {
  640. case OI_UNKNOWN:
  641. case OI_PROPERTYPAGE:
  642. UnregisterUnknownObject(CLSIDOFOBJECT(x), NULL);
  643. break;
  644. case OI_CONTROL:
  645. UnregisterControlObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x),
  646. CLSIDOFOBJECT(x));
  647. break;
  648. case OI_AUTOMATION:
  649. UnregisterAutomationObject(g_szLibName, NAMEOFOBJECT(x), VERSIONOFOBJECT(x),
  650. CLSIDOFOBJECT(x));
  651. break;
  652. }
  653. x++;
  654. }
  655. // if we've got one, unregister our type library
  656. if (g_pLibid)
  657. {
  658. GetModuleFileName(g_hInstance, szTmp, MAX_PATH);
  659. MAKE_WIDEPTR_FROMANSI(pwsz, szTmp);
  660. hr = LoadTypeLibEx(pwsz, REGKIND_NONE, &pTypeLib);
  661. if (FAILED(hr)) goto CleanUp;
  662. hr = pTypeLib->GetLibAttr(&ptlibattr);
  663. if (FAILED(hr)) goto CleanUp;
  664. // Call OLEAUT to have it unregister our type library. It will handle
  665. // the case where there is a 16-bit version of the control's typelib
  666. // registered and will only blow away the 32-bit related keys in this case.
  667. //
  668. UnRegisterTypeLib(*g_pLibid, ptlibattr->wMajorVerNum, ptlibattr->wMinorVerNum, ptlibattr->lcid, ptlibattr->syskind);
  669. }
  670. CleanUp:
  671. if (ptlibattr)
  672. pTypeLib->ReleaseTLibAttr(ptlibattr);
  673. RELEASE_OBJECT(pTypeLib);
  674. return S_OK;
  675. }