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.

667 lines
14 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 "ldap.hxx"
  16. #pragma hdrstop
  17. LPCWSTR lpszTopLevel = L"SOFTWARE\\Microsoft\\ADs\\Providers\\LDAP";
  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. if (pExtensionHead)
  172. {
  173. pClassEntry->pExtensionHead = pExtensionHead;
  174. }
  175. else
  176. {
  177. //
  178. // There are no values under the key
  179. //
  180. FreeADsMem(pClassEntry);
  181. pClassEntry = NULL;
  182. }
  183. CleanupAndExit:
  184. return(pClassEntry);
  185. }
  186. PEXTENSION_ENTRY
  187. BuildExtensionEntry(
  188. LPWSTR lpszExtensionCLSID,
  189. HKEY hExtensionKey
  190. )
  191. {
  192. PEXTENSION_ENTRY pExtensionEntry = NULL;
  193. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  194. PINTERFACE_ENTRY pInterfaceHead = NULL;
  195. WCHAR lpszInterfaces[MAX_PATH];
  196. DWORD dwchInterfaces = 0;
  197. LPWSTR psz = NULL;
  198. WCHAR Interface[MAX_PATH];
  199. HRESULT hr = S_OK;
  200. pExtensionEntry = (PEXTENSION_ENTRY)AllocADsMem(sizeof(EXTENSION_ENTRY));
  201. if (!pExtensionEntry) {
  202. goto CleanupAndExit;
  203. }
  204. memset(lpszInterfaces, 0, sizeof(lpszInterfaces));
  205. dwchInterfaces = sizeof(lpszInterfaces);
  206. RegQueryValueEx(
  207. hExtensionKey,
  208. L"Interfaces",
  209. NULL,
  210. NULL,
  211. (LPBYTE) lpszInterfaces,
  212. &dwchInterfaces
  213. );
  214. psz = lpszInterfaces;
  215. while (psz && *psz) {
  216. wcscpy(Interface, psz);
  217. // skip (length) + 1
  218. // lstrlen returns length sans '\0'
  219. pInterfaceEntry = (PINTERFACE_ENTRY)AllocADsMem(sizeof(INTERFACE_ENTRY));
  220. if (pInterfaceEntry) {
  221. wcscpy(pInterfaceEntry->szInterfaceIID, Interface);
  222. hr = IIDFromString(Interface, &(pInterfaceEntry->iid));
  223. pInterfaceEntry->pNext = pInterfaceHead;
  224. pInterfaceHead = pInterfaceEntry;
  225. }
  226. psz = psz + lstrlen(psz) + 1;
  227. }
  228. wcscpy(pExtensionEntry->szExtensionCLSID, lpszExtensionCLSID);
  229. hr = CLSIDFromString(lpszExtensionCLSID, &(pExtensionEntry->ExtCLSID));
  230. pExtensionEntry->pIID = pInterfaceHead;
  231. CleanupAndExit:
  232. return(pExtensionEntry);
  233. }
  234. void
  235. FreeInterfaceEntry(
  236. PINTERFACE_ENTRY pInterfaceEntry
  237. )
  238. {
  239. if (pInterfaceEntry) {
  240. FreeADsMem(pInterfaceEntry);
  241. }
  242. }
  243. void
  244. FreeExtensionEntry(
  245. PEXTENSION_ENTRY pExtensionEntry
  246. )
  247. {
  248. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  249. PINTERFACE_ENTRY pTemp = NULL;
  250. if (pExtensionEntry) {
  251. pInterfaceEntry = pExtensionEntry->pIID;
  252. while (pInterfaceEntry) {
  253. pTemp = pInterfaceEntry->pNext;
  254. if (pInterfaceEntry) {
  255. FreeInterfaceEntry(pInterfaceEntry);
  256. }
  257. pInterfaceEntry = pTemp;
  258. }
  259. //
  260. // Now unload the Extension Object
  261. //
  262. if (pExtensionEntry->pUnknown) {
  263. //
  264. // Call non-delegating Release to release ref. count on innner
  265. // object to inner object -> inner object self destroyed.
  266. //
  267. (pExtensionEntry->pUnknown)->Release();
  268. }
  269. FreeADsMem(pExtensionEntry);
  270. }
  271. return;
  272. }
  273. void
  274. FreeClassEntry(
  275. PCLASS_ENTRY pClassEntry
  276. )
  277. {
  278. PEXTENSION_ENTRY pExtensionEntry = NULL;
  279. PEXTENSION_ENTRY pTemp = NULL;
  280. if (pClassEntry) {
  281. pExtensionEntry = pClassEntry->pExtensionHead;
  282. while (pExtensionEntry) {
  283. pTemp = pExtensionEntry->pNext;
  284. if (pExtensionEntry) {
  285. FreeExtensionEntry(pExtensionEntry);
  286. }
  287. pExtensionEntry = pTemp;
  288. }
  289. FreeADsMem(pClassEntry);
  290. }
  291. return;
  292. }
  293. PINTERFACE_ENTRY
  294. MakeCopyofInterfaceEntry(
  295. PINTERFACE_ENTRY pInterfaceEntry
  296. )
  297. {
  298. PINTERFACE_ENTRY pNewInterfaceEntry = NULL;
  299. pNewInterfaceEntry = (PINTERFACE_ENTRY)AllocADsMem(sizeof(INTERFACE_ENTRY));
  300. if (pNewInterfaceEntry) {
  301. wcscpy(pNewInterfaceEntry->szInterfaceIID, pInterfaceEntry->szInterfaceIID);
  302. memcpy(&(pNewInterfaceEntry->iid), &(pInterfaceEntry->iid), sizeof(GUID));
  303. }
  304. return(pNewInterfaceEntry);
  305. }
  306. PEXTENSION_ENTRY
  307. MakeCopyofExtensionEntry(
  308. PEXTENSION_ENTRY pExtensionEntry
  309. )
  310. {
  311. PEXTENSION_ENTRY pNewExtensionEntry = NULL;
  312. PINTERFACE_ENTRY pInterfaceEntry = NULL;
  313. PINTERFACE_ENTRY pNewInterfaceEntry = NULL;
  314. PINTERFACE_ENTRY pNewInterfaceHead = NULL;
  315. pInterfaceEntry = pExtensionEntry->pIID;
  316. while (pInterfaceEntry) {
  317. pNewInterfaceEntry = MakeCopyofInterfaceEntry(pInterfaceEntry);
  318. if (pNewInterfaceEntry) {
  319. pNewInterfaceEntry->pNext = pNewInterfaceHead;
  320. pNewInterfaceHead = pNewInterfaceEntry;
  321. }
  322. pInterfaceEntry = pInterfaceEntry->pNext;
  323. }
  324. pNewExtensionEntry = (PEXTENSION_ENTRY)AllocADsMem(sizeof(EXTENSION_ENTRY));
  325. if (pNewExtensionEntry) {
  326. wcscpy(
  327. pNewExtensionEntry->szExtensionCLSID,
  328. pExtensionEntry->szExtensionCLSID
  329. );
  330. memcpy(
  331. &(pNewExtensionEntry->ExtCLSID),
  332. &(pExtensionEntry->ExtCLSID),
  333. sizeof(GUID)
  334. );
  335. pNewExtensionEntry->pIID = pNewInterfaceHead;
  336. //
  337. // Initialize fields we won't know the values of until an instacne of
  338. // the extension is created and aggregated (loaded).
  339. //
  340. pNewExtensionEntry->pUnknown=NULL;
  341. pNewExtensionEntry->pPrivDisp=NULL;
  342. pNewExtensionEntry->pADsExt=NULL;
  343. pNewExtensionEntry->fDisp=FALSE;
  344. pNewExtensionEntry->dwExtensionID = (DWORD) -1; //invalid dwExtensionID
  345. //
  346. // let class entry handle pNext
  347. //
  348. }
  349. return(pNewExtensionEntry);
  350. }
  351. PCLASS_ENTRY
  352. MakeCopyofClassEntry(
  353. PCLASS_ENTRY pClassEntry
  354. )
  355. {
  356. PCLASS_ENTRY pNewClassEntry = NULL;
  357. PEXTENSION_ENTRY pExtensionEntry = NULL;
  358. PEXTENSION_ENTRY pNewExtensionEntry = NULL;
  359. PEXTENSION_ENTRY pNewExtensionHead = NULL;
  360. pExtensionEntry = pClassEntry->pExtensionHead;
  361. while (pExtensionEntry) {
  362. pNewExtensionEntry = MakeCopyofExtensionEntry(pExtensionEntry);
  363. if (pNewExtensionEntry) {
  364. pNewExtensionEntry->pNext = pNewExtensionHead;
  365. pNewExtensionHead = pNewExtensionEntry;
  366. }
  367. pExtensionEntry = pExtensionEntry->pNext;
  368. }
  369. pNewClassEntry = (PCLASS_ENTRY)AllocADsMem(sizeof(CLASS_ENTRY));
  370. if (pNewClassEntry) {
  371. wcscpy(pNewClassEntry->szClassName, pClassEntry->szClassName);
  372. pNewClassEntry->pExtensionHead = pNewExtensionHead;
  373. }
  374. return(pNewClassEntry);
  375. }
  376. CRITICAL_SECTION g_ExtCritSect;
  377. #define ENTER_EXTENSION_CRITSECT() EnterCriticalSection(&g_ExtCritSect)
  378. #define LEAVE_EXTENSION_CRITSECT() LeaveCriticalSection(&g_ExtCritSect)
  379. HRESULT
  380. ADSIGetExtensionList(
  381. LPWSTR pszClassName,
  382. PCLASS_ENTRY * ppClassEntry
  383. )
  384. {
  385. PCLASS_ENTRY pTempClassEntry = NULL;
  386. PCLASS_ENTRY pClassEntry = NULL;
  387. ENTER_EXTENSION_CRITSECT();
  388. //
  389. // Initialize global extensions list if not already
  390. // initialized. Note that this takes place inside the
  391. // g_ExtCritSect to protect against multiple threads trying
  392. // to simultaneously initialize it.
  393. //
  394. if (!gpClassHead) {
  395. gpClassHead = BuildClassesList();
  396. }
  397. pTempClassEntry = gpClassHead;
  398. while (pTempClassEntry) {
  399. if (!_wcsicmp(pTempClassEntry->szClassName, pszClassName)) {
  400. //
  401. // Make a copy of this entire extension and
  402. // hand it over to the calling entity.
  403. //
  404. pClassEntry = MakeCopyofClassEntry(pTempClassEntry);
  405. *ppClassEntry = pClassEntry;
  406. LEAVE_EXTENSION_CRITSECT();
  407. RRETURN(S_OK);
  408. }
  409. pTempClassEntry = pTempClassEntry->pNext;
  410. }
  411. *ppClassEntry = NULL;
  412. LEAVE_EXTENSION_CRITSECT();
  413. RRETURN(S_OK);
  414. }
  415. //+------------------------------------------------------------------------
  416. //
  417. // Function: ADSIAppendToExntesionList
  418. //
  419. // Synopsis: Adds to the end of the current class entry,
  420. // the extensions of the class pszClassName. This is
  421. // used in scenarios as follows - suppose fooUser
  422. // is derived from User, then we want to load the extensions
  423. // defined for User too apart from the extensions available
  424. // directly on fooUser.
  425. //
  426. // The first cut is not going to see if the class is already
  427. // there in the list. This optimization can be done later if
  428. // needed.
  429. //
  430. // Arguments: [pszClassName] -- name of class.
  431. // [ppClassEntry] -- class entry returned
  432. //
  433. // The class entry will be modified only if there were no
  434. // entries, if not we will append the new entry at the end.
  435. // AjayR 11-17-98 (added)
  436. //-------------------------------------------------------------------------
  437. HRESULT
  438. ADSIAppendToExtensionList(
  439. LPWSTR pszClassName,
  440. PCLASS_ENTRY * ppClassEntry
  441. )
  442. {
  443. HRESULT hr = S_OK;
  444. PEXTENSION_ENTRY pLocalExtEntry = NULL;
  445. PCLASS_ENTRY pLocClassEntry = NULL;
  446. //
  447. // Check if there are no extensions on the list
  448. //
  449. if (!*ppClassEntry) {
  450. RRETURN(ADSIGetExtensionList(pszClassName, ppClassEntry));
  451. }
  452. pLocalExtEntry = (*ppClassEntry)->pExtensionHead;
  453. while(pLocalExtEntry->pNext) {
  454. pLocalExtEntry = pLocalExtEntry->pNext;
  455. }
  456. //
  457. // Now get the extension list for the current class
  458. //
  459. hr = ADSIGetExtensionList(pszClassName, &pLocClassEntry);
  460. if (FAILED(hr)) {
  461. //
  462. // not a critical failure
  463. //
  464. hr = S_OK;
  465. }
  466. else {
  467. //
  468. // Add to the end of the current list.
  469. //
  470. if (pLocClassEntry) {
  471. pLocalExtEntry->pNext = pLocClassEntry->pExtensionHead;
  472. FreeADsMem((void*)pLocClassEntry);
  473. }
  474. }
  475. RRETURN(hr);
  476. }