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.

614 lines
17 KiB

  1. #include "oleds.hxx"
  2. #include "bindercf.hxx"
  3. #include "atlbase.h"
  4. #pragma hdrstop
  5. //+---------------------------------------------------------------------------
  6. //
  7. // Microsoft Windows
  8. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  9. //
  10. // File: libmain.cxx
  11. //
  12. // Contents: LibMain for ADs.dll
  13. //
  14. // Functions: LibMain, DllGetClassObject
  15. //
  16. // History: 25-Oct-94 KrishnaG Created.
  17. //
  18. //----------------------------------------------------------------------------
  19. HINSTANCE g_hInst = NULL;
  20. PROUTER_ENTRY g_pRouterHead = NULL;
  21. CRITICAL_SECTION g_csRouterHeadCritSect;
  22. //
  23. // Dll's we load dynamically.
  24. //
  25. extern HANDLE g_hDllAdvapi32;
  26. extern const GUID DBGUID_ROOTBINDER =
  27. {0xFF151822, 0xB0BF, 0x11D1, {0xA8, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
  28. //---------------------------------------------------------------------------
  29. // ADs debug print, mem leak and object tracking-related stuff
  30. //---------------------------------------------------------------------------
  31. DECLARE_INFOLEVEL(ADs)
  32. //+---------------------------------------------------------------------------
  33. //
  34. // Function: ShutDown
  35. //
  36. // Synopsis: Function to handle printing out heap debugging display
  37. //
  38. //----------------------------------------------------------------------------
  39. inline VOID ShutDown()
  40. {
  41. #if DBG==1
  42. #ifndef MSVC
  43. DUMP_TRACKING_INFO_DELETE();
  44. AllocArenaDump( NULL );
  45. DeleteCriticalSection(&g_csOT);
  46. #endif // ifndef MSVC
  47. DeleteCriticalSection(&g_csDP);
  48. #endif
  49. }
  50. extern "C" DWORD heapInfoLevel;
  51. extern "C" DWORD OtInfoLevel;
  52. extern "C" DWORD ADsInfoLevel;
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Function: GetINIHeapInfoLevel
  56. //
  57. // Synopsis: Gets various infolevel values from win.ini
  58. //
  59. //----------------------------------------------------------------------------
  60. inline VOID GetINIHeapInfoLevel()
  61. {
  62. #if DBG==1
  63. const INT MAXINFOLEN=11;
  64. WCHAR awcs[MAXINFOLEN];
  65. #ifndef MSVC
  66. if (GetProfileString(L"ADs",L"heapInfoLevel", L"00000003", awcs,MAXINFOLEN))
  67. heapInfoLevel = wcstoul(awcs, NULL, 16);
  68. if (GetProfileString(L"ADs",L"Ot", L"00000003", awcs, MAXINFOLEN))
  69. OtInfoLevel = wcstoul(awcs, NULL, 16);
  70. #endif // MSVC
  71. if (GetProfileString(L"ADs",L"ADsInfoLevel", L"00000003", awcs,MAXINFOLEN))
  72. ADsInfoLevel = wcstoul(awcs, NULL, 16);
  73. #endif
  74. }
  75. // Globals
  76. ULONG g_ulObjCount = 0; // Number of objects alivein ADs.dll
  77. //+------------------------------------------------------------------------
  78. //
  79. // Macro that calculates the number of elements in a statically-defined
  80. // array.
  81. //
  82. // Note - I swiped this from formsary.cxx - A type-safe array class. Remember
  83. // to swipe the whole thing as required.
  84. //-------------------------------------------------------------------------
  85. #define ARRAY_SIZE(_a) (sizeof(_a) / sizeof(_a[0]))
  86. //+------------------------------------------------------------------------
  87. //
  88. // ADs class factories
  89. //
  90. //-------------------------------------------------------------------------
  91. CADsNamespacesCF g_cfNamespaces;
  92. CADsProviderCF g_cfProvider;
  93. CDSOCF g_cfDSO;
  94. CADsSecurityDescriptorCF g_cfSed;
  95. CADsAccessControlListCF g_cfAcl;
  96. CADsAccessControlEntryCF g_cfAce;
  97. CADsPropertyEntryCF g_cfPropEntry;
  98. CADsPropertyValueCF g_cfPropertyValue;
  99. CADsLargeIntegerCF g_cfLargeInteger;
  100. CADsBinderCF g_cfBinder;
  101. CPathnameCF g_cfPathname;
  102. CADsDNWithBinaryCF g_cfDNWithBinary;
  103. CADsDNWithStringCF g_cfDNWithString;
  104. CADsSecurityUtilityCF g_cfADsSecurityUtility;
  105. extern CRITICAL_SECTION g_DispTypeInfoCritSect;
  106. extern CRITICAL_SECTION g_StringsCriticalSection;
  107. struct CLSCACHE
  108. {
  109. const CLSID * pclsid;
  110. IClassFactory * pCF;
  111. };
  112. CLSCACHE g_aclscache[] =
  113. {
  114. &CLSID_ADsNamespaces, &g_cfNamespaces,
  115. &CLSID_ADsProvider, &g_cfProvider,
  116. &CLSID_ADsDSOObject, &g_cfDSO,
  117. &CLSID_SecurityDescriptor, &g_cfSed,
  118. &CLSID_AccessControlList, &g_cfAcl,
  119. &CLSID_AccessControlEntry, &g_cfAce,
  120. &CLSID_PropertyEntry, &g_cfPropEntry,
  121. &CLSID_PropertyValue, &g_cfPropertyValue,
  122. &CLSID_LargeInteger, &g_cfLargeInteger,
  123. &CLSID_ADSI_BINDER, &g_cfBinder,
  124. &CLSID_Pathname, &g_cfPathname,
  125. &CLSID_DNWithBinary, &g_cfDNWithBinary,
  126. &CLSID_DNWithString, &g_cfDNWithString,
  127. &CLSID_ADsSecurityUtility, &g_cfADsSecurityUtility
  128. };
  129. //------------------------------------------------------------------------
  130. // ATL Module definition
  131. //------------------------------------------------------------------------
  132. CComModule _Module;
  133. //+---------------------------------------------------------------
  134. //
  135. // Function: DllGetClassObject
  136. //
  137. // Synopsis: Standard DLL entrypoint for locating class factories
  138. //
  139. //----------------------------------------------------------------
  140. STDAPI
  141. DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID FAR* ppv)
  142. {
  143. HRESULT hr;
  144. size_t i;
  145. if( ppv == NULL )
  146. RRETURN( E_INVALIDARG );
  147. *ppv = NULL;
  148. for (i = 0; i < ARRAY_SIZE(g_aclscache); i++)
  149. {
  150. if (IsEqualCLSID(clsid, *g_aclscache[i].pclsid))
  151. {
  152. hr = g_aclscache[i].pCF->QueryInterface(iid, ppv);
  153. RRETURN(hr);
  154. }
  155. }
  156. *ppv = NULL;
  157. //
  158. // Add Debugging Code to indicate that the ADs.DllGetClassObject
  159. // has been called with an unknown CLSID.
  160. //
  161. return CLASS_E_CLASSNOTAVAILABLE;
  162. }
  163. //+---------------------------------------------------------------
  164. //
  165. // Function: DllCanUnloadNow
  166. //
  167. // Synopsis: Standard DLL entrypoint to determine if DLL can be unloaded
  168. //
  169. //---------------------------------------------------------------
  170. STDAPI
  171. DllCanUnloadNow(void)
  172. {
  173. HRESULT hr;
  174. hr = S_FALSE;
  175. if (DllReadyToUnload())
  176. hr = S_OK;
  177. return hr;
  178. }
  179. //+---------------------------------------------------------------
  180. //
  181. // Function: LibMain
  182. //
  183. // Synopsis: Standard DLL initialization entrypoint
  184. //
  185. //---------------------------------------------------------------
  186. EXTERN_C BOOL __cdecl
  187. LibMain(HINSTANCE hInst, ULONG ulReason, LPVOID pvReserved)
  188. {
  189. HRESULT hr;
  190. switch (ulReason)
  191. {
  192. case DLL_PROCESS_ATTACH:
  193. //
  194. // Need to put in try catch block as init crit sects can fail.
  195. //
  196. __try {
  197. DisableThreadLibraryCalls(hInst);
  198. g_hInst = hInst;
  199. #if DBG==1
  200. #ifndef MSVC
  201. InitializeCriticalSection(&g_csOT); // Used by Object Tracker
  202. InitializeCriticalSection(&g_csMem); // Used by Object Tracker
  203. #endif
  204. InitializeCriticalSection(&g_csDP); // Used by ADsDebug
  205. #endif
  206. InitializeCriticalSection(&g_DispTypeInfoCritSect);
  207. InitializeCriticalSection(&g_StringsCriticalSection);
  208. InitializeCriticalSection(&g_csRouterHeadCritSect); // router initialization
  209. }
  210. __except (EXCEPTION_EXECUTE_HANDLER) {
  211. //
  212. // Critical failure
  213. //
  214. return FALSE;
  215. }
  216. break;
  217. case DLL_PROCESS_DETACH:
  218. if (g_pRouterHead) {
  219. CleanupRouter(g_pRouterHead);
  220. }
  221. FreeTypeInfoTable();
  222. //
  223. // Delete the cs we inited.
  224. //
  225. #if DBG==1
  226. #ifndef MSVC
  227. DeleteCriticalSection(&g_csOT); // Used by Object Tracker
  228. DeleteCriticalSection(&g_csMem); // Used by Object Tracker
  229. #endif
  230. DeleteCriticalSection(&g_csDP); // Used by ADsDebug
  231. #endif
  232. DeleteCriticalSection(&g_DispTypeInfoCritSect);
  233. DeleteCriticalSection(&g_StringsCriticalSection);
  234. DeleteCriticalSection(&g_csRouterHeadCritSect);
  235. //
  236. // Free any libs we loaded using loadlibrary
  237. //
  238. if (g_hDllAdvapi32) {
  239. FreeLibrary((HMODULE) g_hDllAdvapi32);
  240. g_hDllAdvapi32 = NULL;
  241. }
  242. break;
  243. default:
  244. break;
  245. }
  246. return TRUE;
  247. }
  248. //+---------------------------------------------------------------------------
  249. //
  250. // Function: DllMain
  251. //
  252. // Synopsis: entry point for NT - post .546
  253. //
  254. //----------------------------------------------------------------------------
  255. BOOL
  256. DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
  257. {
  258. return LibMain((HINSTANCE)hDll, dwReason, lpReserved);
  259. }
  260. //+------------------------------------------------------------------------
  261. //
  262. // Function: GetCachedClsidIndex
  263. //
  264. // Synopsis: Returns the index of the given CLSID in the cache, or
  265. // -1 if the CLSID is not present in the cache
  266. //
  267. // Arguments: [clsid]
  268. //
  269. // Returns: int
  270. //
  271. //-------------------------------------------------------------------------
  272. int
  273. GetCachedClsidIndex(REFCLSID clsid)
  274. {
  275. int i;
  276. CLSCACHE * pclscache;
  277. for (i = 0, pclscache = g_aclscache;
  278. i < ARRAY_SIZE(g_aclscache);
  279. i ++, pclscache++)
  280. {
  281. if (IsEqualCLSID(*pclscache->pclsid, clsid))
  282. return i;
  283. }
  284. return -1;
  285. }
  286. //+------------------------------------------------------------------------
  287. //
  288. // Function: GetCachedClassFactory
  289. //
  290. // Synopsis: Returns the cached class factory with the given index.
  291. // The pointer returned has been AddRef'd.
  292. //
  293. // Arguments: [iclsid]
  294. //
  295. // Returns: IClassFactory *
  296. //
  297. //-------------------------------------------------------------------------
  298. IClassFactory *
  299. GetCachedClassFactory(int iclsid)
  300. {
  301. IClassFactory * pCF;
  302. // Assert(iclsid >= 0);
  303. // Assert(iclsid < ARRAY_SIZE(g_aclscache));
  304. pCF = g_aclscache[iclsid].pCF;
  305. pCF->AddRef();
  306. return pCF;
  307. }
  308. //+------------------------------------------------------------------------
  309. //
  310. // Function: GetCachedClsid
  311. //
  312. // Synopsis: Returns the CLSID corresponding to the given index.
  313. // Normally, code should call GetCachedClassFactory to get
  314. // the class factory directly.
  315. //
  316. // Arguments: [iclsid] -- Clsid index
  317. // [pclsid] -- Matching clsid returned in *pclsid
  318. //
  319. //-------------------------------------------------------------------------
  320. void
  321. GetCachedClsid(int iclsid, CLSID * pclsid)
  322. {
  323. // Assert(iclsid >= 0);
  324. // Assert(iclsid < ARRAY_SIZE(g_aclscache));
  325. *pclsid = *g_aclscache[iclsid].pclsid;
  326. }
  327. STDAPI DllRegisterServer()
  328. {
  329. PWCHAR pwszClsid = NULL;
  330. WCHAR pwszSubKey[256];
  331. HRESULT hr = S_OK;
  332. #if (!defined(BUILD_FOR_NT40))
  333. auto_rel<IRegisterProvider> pRegisterProvider;
  334. wcscpy(pwszSubKey, L"SOFTWARE\\Classes\\CLSID\\");
  335. hr = StringFromCLSID(CLSID_ADSI_BINDER, &pwszClsid);
  336. if (FAILED(hr))
  337. return hr;
  338. wcscat(pwszSubKey, pwszClsid);
  339. HKEY hKeyClsid = NULL, hKeyDll = NULL;
  340. DWORD dwDisposition;
  341. LONG lRetVal;
  342. //
  343. // Make sure the router has been initialized
  344. //
  345. EnterCriticalSection(&g_csRouterHeadCritSect);
  346. if (!g_pRouterHead) {
  347. g_pRouterHead = InitializeRouter();
  348. }
  349. LeaveCriticalSection(&g_csRouterHeadCritSect);
  350. //Create CLSID entry
  351. lRetVal = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  352. pwszSubKey,
  353. 0,
  354. L"",
  355. 0,
  356. KEY_ALL_ACCESS,
  357. NULL,
  358. &hKeyClsid,
  359. &dwDisposition);
  360. if (lRetVal != ERROR_SUCCESS)
  361. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  362. //set the value
  363. lRetVal = RegSetValueEx(hKeyClsid,
  364. NULL,
  365. 0,
  366. REG_SZ,
  367. (CONST BYTE *)L"Provider Binder for DS OLE DB Provider",
  368. 78);
  369. if (lRetVal != ERROR_SUCCESS)
  370. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  371. //Create InprocServer32 entry
  372. lRetVal = RegCreateKeyEx(hKeyClsid,
  373. L"InprocServer32",
  374. 0,
  375. L"activeds.dll",
  376. 0,
  377. KEY_ALL_ACCESS,
  378. NULL,
  379. &hKeyDll,
  380. &dwDisposition);
  381. if (lRetVal != ERROR_SUCCESS)
  382. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  383. //set the value
  384. lRetVal = RegSetValueEx(hKeyDll,
  385. NULL,
  386. 0,
  387. REG_SZ,
  388. (CONST BYTE *)L"activeds.dll",
  389. 26);
  390. if (lRetVal != ERROR_SUCCESS)
  391. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  392. //Now set the threadingModel value for the dll key
  393. lRetVal = RegSetValueEx(hKeyDll,
  394. L"ThreadingModel",
  395. 0,
  396. REG_SZ,
  397. (CONST BYTE *)L"Both",
  398. 10);
  399. if (lRetVal != ERROR_SUCCESS)
  400. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  401. //Now register the provider with the root binder.
  402. //Cocreate Root Binder and get IRegisterProvider interface.
  403. hr = CoCreateInstance ( DBGUID_ROOTBINDER,
  404. NULL,
  405. CLSCTX_ALL,
  406. __uuidof(IRegisterProvider),
  407. (void **) &pRegisterProvider
  408. );
  409. if (SUCCEEDED(hr))
  410. {
  411. // Go through list of ADS providers and register each of them
  412. // with the root binder.
  413. for ( PROUTER_ENTRY pProvider = g_pRouterHead;
  414. pProvider != NULL;
  415. pProvider=pProvider->pNext)
  416. {
  417. // Invalid provider ProgID? If so, continue with next provider
  418. if (NULL == pProvider->szProviderProgId)
  419. continue;
  420. hr = pRegisterProvider->SetURLMapping(
  421. pProvider->szProviderProgId,
  422. 0,
  423. CLSID_ADSI_BINDER);
  424. if (FAILED(hr))
  425. AtlTrace(_T("Failed to register %s mapping hr = %x\n"),
  426. pProvider->szProviderProgId, hr);
  427. // Ignore error and continue with next provider
  428. hr = S_OK;
  429. }
  430. }
  431. else
  432. {
  433. AtlTrace(_T("Creation of Root Binder failed! hr = %x\n"), hr);
  434. }
  435. error:
  436. CoTaskMemFree(pwszClsid);
  437. if (hKeyClsid) {
  438. RegCloseKey(hKeyClsid);
  439. }
  440. if (hKeyDll) {
  441. RegCloseKey(hKeyDll);
  442. }
  443. #endif
  444. return hr;
  445. }
  446. STDAPI DllUnregisterServer()
  447. {
  448. PWCHAR pwszClsid = NULL;
  449. WCHAR pwszClsidKey[256];
  450. WCHAR pwszDllKey[256];
  451. HRESULT hr = S_OK;
  452. LONG lRetVal;
  453. #if (!defined(BUILD_FOR_NT40))
  454. auto_rel<IRegisterProvider> pRegisterProvider;
  455. wcscpy(pwszClsidKey, L"SOFTWARE\\Classes\\CLSID\\");
  456. hr = StringFromCLSID(CLSID_ADSI_BINDER, &pwszClsid);
  457. if (FAILED(hr))
  458. return hr;
  459. wcscat(pwszClsidKey, pwszClsid);
  460. wcscpy(pwszDllKey, pwszClsidKey);
  461. wcscat(pwszDllKey, L"\\InprocServer32");
  462. //
  463. // Make sure the router has been initialized
  464. //
  465. EnterCriticalSection(&g_csRouterHeadCritSect);
  466. if (!g_pRouterHead) {
  467. g_pRouterHead = InitializeRouter();
  468. }
  469. LeaveCriticalSection(&g_csRouterHeadCritSect);
  470. //Delete InprocServer32 key
  471. lRetVal = RegDeleteKey(HKEY_LOCAL_MACHINE, pwszDllKey);
  472. if (lRetVal != ERROR_SUCCESS)
  473. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  474. //Delete key and all its subkeys.
  475. lRetVal = RegDeleteKey(HKEY_LOCAL_MACHINE, pwszClsidKey);
  476. if (lRetVal != ERROR_SUCCESS)
  477. BAIL_ON_FAILURE(HRESULT_FROM_WIN32(lRetVal));
  478. //Now unregister provider binder from Root Binder.
  479. //Cocreate Root Binder and get IRegisterProvider interface.
  480. hr = CoCreateInstance ( DBGUID_ROOTBINDER,
  481. NULL,
  482. CLSCTX_ALL,
  483. __uuidof(IRegisterProvider),
  484. (void **) &pRegisterProvider
  485. );
  486. if (SUCCEEDED(hr))
  487. {
  488. // Unregister each provider with the root binder
  489. for ( PROUTER_ENTRY pProvider = g_pRouterHead;
  490. pProvider != NULL;
  491. pProvider=pProvider->pNext)
  492. {
  493. // Invalid provider ProgID? If so, continue with next provider
  494. if (NULL == pProvider->szProviderProgId)
  495. continue;
  496. pRegisterProvider->UnregisterProvider(
  497. pProvider->szProviderProgId,
  498. 0,
  499. CLSID_ADSI_BINDER);
  500. }
  501. }
  502. error:
  503. CoTaskMemFree(pwszClsid);
  504. #endif
  505. return hr;
  506. }