Leaked source code of windows server 2003
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.

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