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.

822 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: libmain.cxx
  7. //
  8. // Contents: LibMain for ADs.dll
  9. //
  10. // Functions: LibMain, DllGetClassObject
  11. //
  12. // History: 25-Oct-94 KrishnaG Created.
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "nwcompat.hxx"
  16. #pragma hdrstop
  17. LPCWSTR lpszTopLevel = L"SOFTWARE\\Microsoft\\ADs\\Providers\\NWCOMPAT";
  18. LPCWSTR lpszExtensions = L"Extensions";
  19. PCLASS_ENTRY gpClassHead = NULL;
  20. PCLASS_ENTRY
  21. BuildClassesList()
  22. {
  23. HKEY hTopLevelKey = NULL;
  24. HKEY hExtensionKey = NULL;
  25. HKEY hExtensionRootKey = NULL;
  26. HKEY hClassKey = NULL;
  27. DWORD dwIndex = 0;
  28. WCHAR lpszClassName[MAX_PATH];
  29. DWORD dwchClassName = 0;
  30. PCLASS_ENTRY pClassHead = NULL;
  31. PCLASS_ENTRY pClassEntry = NULL;
  32. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  33. lpszTopLevel,
  34. 0,
  35. KEY_READ,
  36. &hTopLevelKey
  37. ) != ERROR_SUCCESS)
  38. {
  39. goto CleanupAndExit;
  40. }
  41. if (RegOpenKeyEx(hTopLevelKey,
  42. lpszExtensions,
  43. 0,
  44. KEY_READ,
  45. &hExtensionRootKey
  46. ) != ERROR_SUCCESS)
  47. {
  48. goto CleanupAndExit;
  49. }
  50. memset(lpszClassName, 0, sizeof(lpszClassName));
  51. dwchClassName = sizeof(lpszClassName)/sizeof(WCHAR);
  52. while(RegEnumKeyEx(hExtensionRootKey,
  53. dwIndex,
  54. lpszClassName,
  55. &dwchClassName,
  56. NULL,
  57. NULL,
  58. NULL,
  59. NULL
  60. ) == ERROR_SUCCESS)
  61. {
  62. //
  63. // Read namespace
  64. //
  65. if (RegOpenKeyEx(hExtensionRootKey,
  66. lpszClassName,
  67. 0,
  68. KEY_READ,
  69. &hClassKey
  70. ) != ERROR_SUCCESS){
  71. goto CleanupAndExit;
  72. }
  73. pClassEntry = BuildClassEntry(
  74. lpszClassName,
  75. hClassKey
  76. );
  77. if (pClassEntry) {
  78. pClassEntry->pNext = pClassHead;
  79. pClassHead = pClassEntry;
  80. }
  81. if (hClassKey) {
  82. CloseHandle(hClassKey);
  83. }
  84. memset(lpszClassName, 0, sizeof(lpszClassName));
  85. dwchClassName = sizeof(lpszClassName)/sizeof(WCHAR);
  86. dwIndex++;
  87. }
  88. CleanupAndExit:
  89. if (hExtensionRootKey) {
  90. RegCloseKey(hExtensionRootKey);
  91. }
  92. if (hTopLevelKey) {
  93. RegCloseKey(hTopLevelKey);
  94. }
  95. return(pClassHead);
  96. }
  97. VOID
  98. FreeClassesList(
  99. PCLASS_ENTRY pClassHead
  100. )
  101. {
  102. PCLASS_ENTRY pDelete;
  103. while (pClassHead) {
  104. pDelete = pClassHead;
  105. pClassHead = pClassHead->pNext;
  106. FreeClassEntry(pDelete);
  107. }
  108. return;
  109. }
  110. PCLASS_ENTRY
  111. BuildClassEntry(
  112. LPWSTR lpszClassName,
  113. HKEY hClassKey
  114. )
  115. {
  116. HKEY hTopLevelKey = NULL;
  117. HKEY hExtensionKey = NULL;
  118. DWORD dwIndex = 0;
  119. DWORD dwchExtensionCLSID = 0;
  120. WCHAR lpszExtensionCLSID[MAX_PATH];
  121. PCLASS_ENTRY pClassEntry = NULL;
  122. PEXTENSION_ENTRY pExtensionHead = NULL;
  123. PEXTENSION_ENTRY pExtensionEntry = NULL;
  124. pClassEntry = (PCLASS_ENTRY)AllocADsMem(sizeof(CLASS_ENTRY));
  125. if (!pClassEntry) {
  126. goto CleanupAndExit;
  127. }
  128. wcscpy(pClassEntry->szClassName, lpszClassName);
  129. memset(lpszExtensionCLSID, 0, sizeof(lpszExtensionCLSID));
  130. dwchExtensionCLSID = sizeof(lpszExtensionCLSID)/sizeof(WCHAR);
  131. while(RegEnumKeyEx(hClassKey,
  132. dwIndex,
  133. lpszExtensionCLSID,
  134. &dwchExtensionCLSID,
  135. NULL,
  136. NULL,
  137. NULL,
  138. NULL
  139. ) == ERROR_SUCCESS)
  140. {
  141. //
  142. // Read namespace
  143. //
  144. if (RegOpenKeyEx(hClassKey,
  145. lpszExtensionCLSID,
  146. 0,
  147. KEY_READ,
  148. &hExtensionKey
  149. ) != ERROR_SUCCESS){
  150. goto CleanupAndExit;
  151. }
  152. //
  153. // Read the Interfaces that this Extension supports
  154. //
  155. pExtensionEntry = BuildExtensionEntry(
  156. lpszExtensionCLSID,
  157. hExtensionKey
  158. );
  159. if (pExtensionEntry) {
  160. wcscpy(pExtensionEntry->szExtensionCLSID, lpszExtensionCLSID);
  161. pExtensionEntry->pNext = pExtensionHead;
  162. pExtensionHead = pExtensionEntry;
  163. }
  164. if (hExtensionKey) {
  165. CloseHandle(hExtensionKey);
  166. }
  167. memset(lpszExtensionCLSID, 0, sizeof(lpszExtensionCLSID));
  168. dwchExtensionCLSID = sizeof(lpszExtensionCLSID)/sizeof(WCHAR);
  169. dwIndex++;
  170. }
  171. pClassEntry->pExtensionHead = pExtensionHead;
  172. CleanupAndExit:
  173. return(pClassEntry);
  174. }
  175. PEXTENSION_ENTRY
  176. BuildExtensionEntry(
  177. LPWSTR lpszExtensionCLSID,
  178. HKEY hExtensionKey
  179. )
  180. {
  181. PEXTENSION_ENTRY pExtensionEntry = NULL;
  182. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  183. PINTERFACE_ENTRY pInterfaceHead = NULL;
  184. WCHAR lpszInterfaces[MAX_PATH];
  185. DWORD dwchInterfaces = 0;
  186. LPWSTR psz = NULL;
  187. WCHAR Interface[MAX_PATH];
  188. HRESULT hr = S_OK;
  189. pExtensionEntry = (PEXTENSION_ENTRY)AllocADsMem(sizeof(EXTENSION_ENTRY));
  190. if (!pExtensionEntry) {
  191. goto CleanupAndExit;
  192. }
  193. memset(lpszInterfaces, 0, sizeof(lpszInterfaces));
  194. dwchInterfaces = sizeof(lpszInterfaces);
  195. RegQueryValueEx(
  196. hExtensionKey,
  197. L"Interfaces",
  198. NULL,
  199. NULL,
  200. (LPBYTE) lpszInterfaces,
  201. &dwchInterfaces
  202. );
  203. psz = lpszInterfaces;
  204. while (psz && *psz) {
  205. wcscpy(Interface, psz);
  206. // skip (length) + 1
  207. // lstrlen returns length sans '\0'
  208. pInterfaceEntry = (PINTERFACE_ENTRY)AllocADsMem(sizeof(INTERFACE_ENTRY));
  209. if (pInterfaceEntry) {
  210. wcscpy(pInterfaceEntry->szInterfaceIID, Interface);
  211. hr = IIDFromString(Interface, &(pInterfaceEntry->iid));
  212. pInterfaceEntry->pNext = pInterfaceHead;
  213. pInterfaceHead = pInterfaceEntry;
  214. }
  215. psz = psz + lstrlen(psz) + 1;
  216. }
  217. wcscpy(pExtensionEntry->szExtensionCLSID, lpszExtensionCLSID);
  218. hr = CLSIDFromString(lpszExtensionCLSID, &(pExtensionEntry->ExtCLSID));
  219. pExtensionEntry->pIID = pInterfaceHead;
  220. CleanupAndExit:
  221. return(pExtensionEntry);
  222. }
  223. void
  224. FreeInterfaceEntry(
  225. PINTERFACE_ENTRY pInterfaceEntry
  226. )
  227. {
  228. if (pInterfaceEntry) {
  229. FreeADsMem(pInterfaceEntry);
  230. }
  231. }
  232. void
  233. FreeExtensionEntry(
  234. PEXTENSION_ENTRY pExtensionEntry
  235. )
  236. {
  237. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  238. PINTERFACE_ENTRY pTemp = NULL;
  239. if (pExtensionEntry) {
  240. pInterfaceEntry = pExtensionEntry->pIID;
  241. while (pInterfaceEntry) {
  242. pTemp = pInterfaceEntry->pNext;
  243. if (pInterfaceEntry) {
  244. FreeInterfaceEntry(pInterfaceEntry);
  245. }
  246. pInterfaceEntry = pTemp;
  247. }
  248. //
  249. // Now unload the Extension Object
  250. //
  251. if (pExtensionEntry->pUnknown) {
  252. //
  253. // Call non-delegating Release to release ref. count on innner
  254. // object (for pUnkown) -> inner object self destroy
  255. //
  256. (pExtensionEntry->pUnknown)->Release();
  257. }
  258. FreeADsMem(pExtensionEntry);
  259. }
  260. return;
  261. }
  262. void
  263. FreeClassEntry(
  264. PCLASS_ENTRY pClassEntry
  265. )
  266. {
  267. PEXTENSION_ENTRY pExtensionEntry = NULL;
  268. PEXTENSION_ENTRY pTemp = NULL;
  269. if (pClassEntry) {
  270. pExtensionEntry = pClassEntry->pExtensionHead;
  271. while (pExtensionEntry) {
  272. pTemp = pExtensionEntry->pNext;
  273. if (pExtensionEntry) {
  274. FreeExtensionEntry(pExtensionEntry);
  275. }
  276. pExtensionEntry = pTemp;
  277. }
  278. FreeADsMem(pClassEntry);
  279. }
  280. return;
  281. }
  282. PINTERFACE_ENTRY
  283. MakeCopyofInterfaceEntry(
  284. PINTERFACE_ENTRY pInterfaceEntry
  285. )
  286. {
  287. PINTERFACE_ENTRY pNewInterfaceEntry = NULL;
  288. pNewInterfaceEntry = (PINTERFACE_ENTRY)AllocADsMem(sizeof(INTERFACE_ENTRY));
  289. if (pNewInterfaceEntry) {
  290. wcscpy(pNewInterfaceEntry->szInterfaceIID, pInterfaceEntry->szInterfaceIID);
  291. memcpy(&(pNewInterfaceEntry->iid), &(pInterfaceEntry->iid), sizeof(GUID));
  292. }
  293. return(pNewInterfaceEntry);
  294. }
  295. PEXTENSION_ENTRY
  296. MakeCopyofExtensionEntry(
  297. PEXTENSION_ENTRY pExtensionEntry
  298. )
  299. {
  300. PEXTENSION_ENTRY pNewExtensionEntry = NULL;
  301. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  302. PINTERFACE_ENTRY pNewInterfaceEntry = NULL;
  303. PINTERFACE_ENTRY pNewInterfaceHead = NULL;
  304. pInterfaceEntry = pExtensionEntry->pIID;
  305. while (pInterfaceEntry) {
  306. pNewInterfaceEntry = MakeCopyofInterfaceEntry(pInterfaceEntry);
  307. if (pNewInterfaceEntry) {
  308. pNewInterfaceEntry->pNext = pNewInterfaceHead;
  309. pNewInterfaceHead = pNewInterfaceEntry;
  310. }
  311. pInterfaceEntry = pInterfaceEntry->pNext;
  312. }
  313. pNewExtensionEntry = (PEXTENSION_ENTRY)AllocADsMem(sizeof(EXTENSION_ENTRY));
  314. if (pNewExtensionEntry) {
  315. wcscpy(
  316. pNewExtensionEntry->szExtensionCLSID,
  317. pExtensionEntry->szExtensionCLSID
  318. );
  319. memcpy(
  320. &(pNewExtensionEntry->ExtCLSID),
  321. &(pExtensionEntry->ExtCLSID),
  322. sizeof(GUID)
  323. );
  324. pNewExtensionEntry->pIID = pNewInterfaceHead;
  325. //
  326. // Initialize fields we won't know the values of until an instacne of
  327. // the extension is created and aggregated (loaded).
  328. //
  329. pNewExtensionEntry->pUnknown=NULL;
  330. pNewExtensionEntry->pPrivDisp=NULL;
  331. pNewExtensionEntry->pADsExt=NULL;
  332. pNewExtensionEntry->fDisp=FALSE;
  333. pNewExtensionEntry->dwExtensionID = (DWORD) -1; //invalid dwExtensionID
  334. //
  335. // let class entry handle pNext
  336. //
  337. }
  338. return(pNewExtensionEntry);
  339. }
  340. PCLASS_ENTRY
  341. MakeCopyofClassEntry(
  342. PCLASS_ENTRY pClassEntry
  343. )
  344. {
  345. PCLASS_ENTRY pNewClassEntry = NULL;
  346. PEXTENSION_ENTRY pExtensionEntry = NULL;
  347. PEXTENSION_ENTRY pNewExtensionEntry = NULL;
  348. PEXTENSION_ENTRY pNewExtensionHead = NULL;
  349. pExtensionEntry = pClassEntry->pExtensionHead;
  350. while (pExtensionEntry) {
  351. pNewExtensionEntry = MakeCopyofExtensionEntry(pExtensionEntry);
  352. if (pNewExtensionEntry) {
  353. pNewExtensionEntry->pNext = pNewExtensionHead;
  354. pNewExtensionHead = pNewExtensionEntry;
  355. }
  356. pExtensionEntry = pExtensionEntry->pNext;
  357. }
  358. pNewClassEntry = (PCLASS_ENTRY)AllocADsMem(sizeof(CLASS_ENTRY));
  359. if (pNewClassEntry) {
  360. wcscpy(pNewClassEntry->szClassName, pClassEntry->szClassName);
  361. pNewClassEntry->pExtensionHead = pNewExtensionHead;
  362. }
  363. return(pNewClassEntry);
  364. }
  365. CRITICAL_SECTION g_ExtCritSect;
  366. #define ENTER_EXTENSION_CRITSECT() EnterCriticalSection(&g_ExtCritSect)
  367. #define LEAVE_EXTENSION_CRITSECT() LeaveCriticalSection(&g_ExtCritSect)
  368. HRESULT
  369. ADSIGetExtensionList(
  370. LPWSTR pszClassName,
  371. PCLASS_ENTRY * ppClassEntry
  372. )
  373. {
  374. PCLASS_ENTRY pTempClassEntry = NULL;
  375. PCLASS_ENTRY pClassEntry = NULL;
  376. ENTER_EXTENSION_CRITSECT();
  377. pTempClassEntry = gpClassHead;
  378. while (pTempClassEntry) {
  379. if (!_wcsicmp(pTempClassEntry->szClassName, pszClassName)) {
  380. //
  381. // Make a copy of this entire extension and
  382. // hand it over to the calling entity.
  383. //
  384. pClassEntry = MakeCopyofClassEntry(pTempClassEntry);
  385. *ppClassEntry = pClassEntry;
  386. LEAVE_EXTENSION_CRITSECT();
  387. RRETURN(S_OK);
  388. }
  389. pTempClassEntry = pTempClassEntry->pNext;
  390. }
  391. *ppClassEntry = NULL;
  392. LEAVE_EXTENSION_CRITSECT();
  393. RRETURN(S_OK);
  394. }
  395. //
  396. //
  397. // Instantiate extension objects listed in <pClassEntry> as aggregatees of
  398. // aggregator <pUnkOuter>.
  399. //
  400. // Max Load 127 extensions. Return S_FALSE if more extension in <pClassEntry>
  401. HRESULT
  402. ADSILoadExtensions(
  403. IUnknown FAR * pUnkOuter,
  404. PCLASS_ENTRY pClassEntry
  405. )
  406. {
  407. HRESULT hr = S_OK;
  408. PEXTENSION_ENTRY pExtEntry = NULL;
  409. DWORD dwExtensionID = MIN_EXTENSION_ID;
  410. IPrivateDispatch * pPrivDisp = NULL;
  411. BOOL fReturnError = FALSE;
  412. VARIANT varUserName, varPassword, varAuthFlags;
  413. VariantInit(&varUserName);
  414. VariantInit(&varPassword);
  415. VariantInit(&varAuthFlags);
  416. varUserName.vt = VT_BSTR;
  417. varUserName.bstrVal = NULL;
  418. varPassword.vt = VT_BSTR;
  419. varPassword.bstrVal = NULL;
  420. varAuthFlags.vt = VT_I4;
  421. varAuthFlags.lVal = 0;
  422. ASSERT(pUnkOuter);
  423. if (!pClassEntry || !(pExtEntry=pClassEntry->pExtensionHead) ) {
  424. RRETURN(S_OK);
  425. }
  426. while (pExtEntry) {
  427. //
  428. // Max # of extension have been loaded, cannot load more
  429. //
  430. if (dwExtensionID>MAX_EXTENSION_ID) {
  431. hr = S_FALSE;
  432. fReturnError = TRUE;
  433. break;
  434. }
  435. //
  436. // create extension object (aggregatee) and ask for Non-delegating
  437. // IUnknown. Ref count on extension object = 1.
  438. //
  439. hr = CoCreateInstance(
  440. pExtEntry->ExtCLSID,
  441. pUnkOuter,
  442. CLSCTX_INPROC_SERVER,
  443. IID_IUnknown,
  444. (void **)&(pExtEntry->pUnknown)
  445. );
  446. //
  447. // if fail, go to next extesion entry s.t. bad individual extension
  448. // cannot block other extensions from loading (no clean up needed)
  449. //
  450. // The user receives no warning about the failure to load a particular
  451. // extension (we really don't have any way to do so specified), other
  452. // than the fact that their extension doesn't work when they try to
  453. // use it (e.g., they'll probably get back something like
  454. // DISP_E_UNKNOWNNAME when they try to use GetIDsOfNames to find its
  455. // methods).
  456. //
  457. if (SUCCEEDED(hr)) {
  458. pExtEntry->dwExtensionID = dwExtensionID;
  459. hr = (pExtEntry->pUnknown)->QueryInterface(
  460. IID_IADsExtension,
  461. (void **) &(pExtEntry->pADsExt)
  462. );
  463. if (FAILED(hr)) {
  464. //
  465. // extension does not support the optioanl IADsExtension -> OK.
  466. // (no clean up needed)
  467. //
  468. pExtEntry->pADsExt=NULL;
  469. pExtEntry->fDisp = FALSE;
  470. } else {
  471. //
  472. // Cache the interface ptr but call Release() immediately to
  473. // avoid aggregator having a ref count on itself
  474. // since IADsExtension inherits from delegating IUnknown.
  475. //
  476. // Note: codes still works if inherit from NonDelegatingIUknown
  477. //
  478. (pExtEntry->pADsExt)->Release() ;
  479. //
  480. // For efficiency, set this flag to FALSE on FIRST encounter of
  481. // pADsExt->PrivateGetIDsOfNames()/Invoke() returning E_NOTIMPL.
  482. // Set as TRUE now s.t. at least first encounter will happen.
  483. //
  484. pExtEntry->fDisp = TRUE;
  485. pExtEntry->pADsExt->Operate(
  486. ADS_EXT_INITCREDENTIALS,
  487. varUserName,
  488. varPassword,
  489. varAuthFlags
  490. );
  491. }
  492. } // end if CoCreateInstance() succeeded
  493. pExtEntry = pExtEntry->pNext;
  494. //
  495. // ++ extension ID even if creat'n of extension fails just to be safe
  496. // - chuck's stuff :)
  497. //
  498. dwExtensionID++;
  499. } // end while
  500. if (fReturnError) {
  501. RRETURN(hr); // fetal error,
  502. }
  503. else {
  504. RRETURN(S_OK); // "okay" error if any, optional support
  505. }
  506. }
  507. #if 0
  508. HRESULT
  509. ADSILoadExtensions(
  510. IUnknown FAR * pUnkOuter,
  511. PCLASS_ENTRY pClassEntry,
  512. LPTSTR pszClassName
  513. )
  514. {
  515. HRESULT hr = S_OK;
  516. PEXTENSION_ENTRY pExtensionEntry = NULL;
  517. DWORD dwExtensionID = 1;
  518. IPrivateDispatch * pPrivDisp = NULL;
  519. pExtensionEntry = pClassEntry->pExtensionHead;
  520. while (pExtensionEntry) {
  521. hr = CoCreateInstance(
  522. pExtensionEntry->ExtCLSID,
  523. pUnkOuter,
  524. CLSCTX_INPROC_SERVER,
  525. IID_IPrivateUnknown,
  526. (void **)&(pExtensionEntry->pUnknown)
  527. );
  528. if (SUCCEEDED(hr)) {
  529. hr = (pExtensionEntry->pUnknown)->ADSIInitializeObject(
  530. NULL,
  531. NULL,
  532. 0
  533. );
  534. pExtensionEntry->dwExtensionID = dwExtensionID;
  535. hr = (pExtensionEntry->pUnknown)->QueryInterface(
  536. IID_IPrivateDispatch,
  537. (void **)&pPrivDisp
  538. );
  539. if (SUCCEEDED(hr)) {
  540. hr = pPrivDisp->ADSIInitializeDispatchManager(dwExtensionID);
  541. if (FAILED(hr)) {
  542. //
  543. // Remember NOT to do a Release here for IPrivateDispatch
  544. //
  545. pExtensionEntry->fDisp = FALSE;
  546. (pExtensionEntry->pUnknown)->Release();
  547. }else {
  548. pExtensionEntry->fDisp = TRUE;
  549. pExtensionEntry->pPrivDisp = pPrivDisp;
  550. //
  551. // Now release both pointers because we don't want to
  552. // have a cyclic reference count
  553. //
  554. (pExtensionEntry->pPrivDisp)->Release();
  555. (pExtensionEntry->pUnknown)->Release();
  556. }
  557. }else {
  558. pExtensionEntry->fDisp = FALSE;
  559. (pExtensionEntry->pUnknown)->Release();
  560. }
  561. }
  562. pExtensionEntry = pExtensionEntry->pNext;
  563. dwExtensionID++;
  564. }
  565. RRETURN(S_OK);
  566. }
  567. #endif