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.

717 lines
27 KiB

  1. /*---------------------------------------------------------------------------
  2. File: NT4Dom.cpp
  3. Comments: Implementation of NT4 object enumeration. This object enumerates
  4. members in USERS,GROUPS,COMPUTERS container for NT4 domain. It
  5. returns a fixed set of columns. For more information please refer
  6. to the code below.
  7. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  8. Proprietary and confidential to Mission Critical Software, Inc.
  9. REVISION LOG ENTRY
  10. Revision By: Sham Chauthani
  11. Revised on 07/02/99 12:40:00
  12. ---------------------------------------------------------------------------
  13. */
  14. #include "stdafx.h"
  15. #include "TNode.hpp"
  16. #include "NetNode.h"
  17. #include "AttrNode.h"
  18. #include <lm.h>
  19. #include "NT4Dom.h"
  20. #include "NT4Enum.h"
  21. #ifdef _DEBUG
  22. #define new DEBUG_NEW
  23. #undef THIS_FILE
  24. static char THIS_FILE[] = __FILE__;
  25. #endif
  26. //////////////////////////////////////////////////////////////////////
  27. // Construction/Destruction
  28. //////////////////////////////////////////////////////////////////////
  29. #define MAX_BUF 100
  30. #define LEN_Path 255
  31. CNT4Dom::CNT4Dom()
  32. {
  33. }
  34. CNT4Dom::~CNT4Dom()
  35. {
  36. }
  37. bool GetSamNameFromInfo( WCHAR * sInfo, WCHAR * sDomain, WCHAR * sName)
  38. {
  39. WCHAR domain[LEN_Path];
  40. WCHAR * temp;
  41. bool rc = false;
  42. wcscpy(domain, sInfo);
  43. temp = wcschr(domain, L'\\');
  44. if ( temp )
  45. {
  46. *temp = 0;
  47. if (!_wcsicmp(domain, sDomain) || !wcsncmp(sDomain, L"\\\\", 2))
  48. {
  49. rc = true;
  50. wcscpy(sName, ++temp);
  51. }
  52. }
  53. return rc;
  54. }
  55. //---------------------------------------------------------------------------
  56. // GetContainerEnum: This function returns the enumeration for an NT4 domain
  57. // container.
  58. //---------------------------------------------------------------------------
  59. HRESULT CNT4Dom::GetContainerEnum(
  60. BSTR sContainerName, //in -Container name to enumerate
  61. BSTR sDomainName, //in -Domain name to enumerate
  62. IEnumVARIANT **& ppVarEnum //out -Pointer to the Enumaration object.
  63. )
  64. {
  65. // This function enumerates three types of containers
  66. // USERS, COMPUTERS, GROUPS
  67. // if the container parameter specifies anything other than the three containers then
  68. // we returns UNEXPECTED.
  69. DWORD ulCount;
  70. DWORD rc=0;
  71. DWORD ndx = 0;
  72. IEnumVARIANT * pEnum;
  73. TNodeList * pNodeList = new TNodeList();
  74. LPBYTE sServerName;
  75. if (!pNodeList)
  76. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  77. rc = NetGetDCName(NULL, sDomainName, &sServerName);
  78. if ( ! rc )
  79. {
  80. for (UINT i = 0; i < wcslen(sContainerName); i++)
  81. sContainerName[i] = towupper(sContainerName[i]);
  82. if ( wcscmp(sContainerName,L"CN=USERS") &&
  83. wcscmp(sContainerName,L"CN=COMPUTERS") &&
  84. wcscmp(sContainerName,L"CN=GROUPS") )
  85. {
  86. // if they selected a group we enumerate the membership of that group.
  87. WCHAR * sTemp = wcstok( sContainerName, L",");
  88. WCHAR * ndx = wcstok( NULL, L",");
  89. if ( wcscmp(ndx, L"CN=GROUPS") )
  90. {
  91. delete pNodeList;
  92. pNodeList = NULL;
  93. NetApiBufferFree(sServerName);
  94. return E_UNEXPECTED;
  95. }
  96. else
  97. {
  98. // Get the members of the global group and add them to the List,
  99. GROUP_USERS_INFO_0 * pbufNetUser;
  100. // DWORD resume=0, total=0;
  101. DWORD total=0;
  102. DWORD_PTR resume=0;
  103. // Get the first set of Members from the Group
  104. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  105. while ( ulCount > 0 )
  106. {
  107. // For each user create a node set the value of the node to the object name and add it to the list.
  108. TNetObjNode * pNode;
  109. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  110. {
  111. pNode = new TNetObjNode();
  112. if (!pNode)
  113. {
  114. delete pNodeList;
  115. NetApiBufferFree(sServerName);
  116. NetApiBufferFree(pbufNetUser);
  117. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  118. }
  119. wcscpy(pNode->m_strObjName, pbufNetUser[dwIdx].grui0_name);
  120. pNodeList->InsertBottom(pNode);
  121. }
  122. NetApiBufferFree(pbufNetUser);
  123. // Get the next set of objects
  124. if ( rc == ERROR_MORE_DATA )
  125. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  126. else
  127. ulCount = 0;
  128. }
  129. // Get the members of the local group and add them to the List,
  130. LOCALGROUP_MEMBERS_INFO_3 * pbufNetInfo;
  131. resume=0;
  132. total=0;
  133. WCHAR sTempName[LEN_Path];
  134. WCHAR sName[LEN_Path];
  135. // Get the first set of Members from the Group
  136. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  137. while ( ulCount > 0 )
  138. {
  139. // For each user create a node set the value of the node to the object name and add it to the list.
  140. TNetObjNode * pNode;
  141. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  142. {
  143. wcscpy(sTempName, pbufNetUser[dwIdx].grui0_name);
  144. if (GetSamNameFromInfo(sTempName, (WCHAR*)sDomainName, sName))
  145. {
  146. pNode = new TNetObjNode();
  147. if (!pNode)
  148. {
  149. delete pNodeList;
  150. NetApiBufferFree(sServerName);
  151. NetApiBufferFree(pbufNetInfo);
  152. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  153. }
  154. wcscpy(pNode->m_strObjName, sName);
  155. pNodeList->InsertBottom(pNode);
  156. }
  157. }
  158. NetApiBufferFree(pbufNetInfo);
  159. // Get the next set of objects
  160. if ( rc == ERROR_MORE_DATA )
  161. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  162. else
  163. ulCount = 0;
  164. }
  165. }
  166. }
  167. if (!wcscmp(sContainerName,L"CN=USERS"))
  168. {
  169. // Build User enumeration
  170. NET_DISPLAY_USER * pbufNetUser;
  171. // Get the first set of users from the domain
  172. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  173. while ( ulCount > 0 )
  174. {
  175. // For each user create a node set the value of the node to the object name and add it to the list.
  176. TNetObjNode * pNode;
  177. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  178. {
  179. pNode = new TNetObjNode();
  180. if (!pNode)
  181. {
  182. delete pNodeList;
  183. NetApiBufferFree(sServerName);
  184. NetApiBufferFree(pbufNetUser);
  185. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  186. }
  187. wcscpy(pNode->m_strObjName, pbufNetUser[dwIdx].usri1_name);
  188. pNodeList->InsertBottom(pNode);
  189. }
  190. // Set the index for next set of users.
  191. if ( ulCount > 0 )
  192. ndx = pbufNetUser[ulCount-1].usri1_next_index;
  193. NetApiBufferFree(pbufNetUser);
  194. // Get the next set of objects
  195. if ( rc == ERROR_MORE_DATA )
  196. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  197. else
  198. ulCount = 0;
  199. }
  200. }
  201. else if (!wcscmp(sContainerName,L"CN=COMPUTERS"))
  202. {
  203. // Build Computers enumeration
  204. NET_DISPLAY_MACHINE * pbufNetUser;
  205. // Get the first set of users from the domain
  206. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  207. while ( ulCount > 0 )
  208. {
  209. // For each user create a node set the value of the node to the object name and add it to the list.
  210. TNetObjNode * pNode;
  211. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  212. {
  213. pNode = new TNetObjNode();
  214. if (!pNode)
  215. {
  216. delete pNodeList;
  217. NetApiBufferFree(sServerName);
  218. NetApiBufferFree(pbufNetUser);
  219. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  220. }
  221. wcscpy(pNode->m_strObjName, pbufNetUser[dwIdx].usri2_name);
  222. pNodeList->InsertBottom(pNode);
  223. }
  224. // Set the index for next set of users.
  225. if ( ulCount > 0 )
  226. ndx = pbufNetUser[ulCount-1].usri2_next_index;
  227. NetApiBufferFree(pbufNetUser);
  228. // Get the next set of objects
  229. if ( rc == ERROR_MORE_DATA )
  230. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  231. else
  232. ulCount = 0;
  233. }
  234. }
  235. else if (!wcscmp(sContainerName,L"CN=GROUPS"))
  236. {
  237. // Build Groups enumeration
  238. // Build Computers enumeration
  239. NET_DISPLAY_GROUP * pbufNetUser;
  240. // Get the first set of users from the domain
  241. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  242. while ( ulCount > 0 )
  243. {
  244. // For each user create a node set the value of the node to the object name and add it to the list.
  245. TNetObjNode * pNode;
  246. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  247. {
  248. pNode = new TNetObjNode();
  249. if (!pNode)
  250. {
  251. delete pNodeList;
  252. NetApiBufferFree(sServerName);
  253. NetApiBufferFree(pbufNetUser);
  254. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  255. }
  256. wcscpy(pNode->m_strObjName, pbufNetUser[dwIdx].grpi3_name);
  257. pNodeList->InsertBottom(pNode);
  258. }
  259. // Set the index for next set of users.
  260. if ( ulCount > 0 )
  261. ndx = pbufNetUser[ulCount-1].grpi3_next_index;
  262. NetApiBufferFree(pbufNetUser);
  263. // Get the next set of objects
  264. if ( rc == ERROR_MORE_DATA )
  265. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  266. else
  267. ulCount = 0;
  268. }
  269. }
  270. // Build an enumerator and return it to the caller.
  271. pEnum = new CNT4Enum(pNodeList);
  272. if (!pEnum)
  273. {
  274. delete pNodeList;
  275. NetApiBufferFree(sServerName);
  276. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  277. }
  278. * ppVarEnum = pEnum;
  279. NetApiBufferFree(sServerName);
  280. }
  281. else
  282. delete pNodeList;
  283. return S_OK;
  284. }
  285. //-----------------------------------------------------------------------------
  286. // GetEnumeration: This function Enumerates all objects in the above specified
  287. // containers and their 6 standard values which are
  288. // 'name,comment,user/groupID,flags,FullName,description'
  289. //-----------------------------------------------------------------------------
  290. HRESULT CNT4Dom::GetEnumeration(
  291. BSTR sContainerName, //in -Container path
  292. BSTR sDomainName, //in -Domain name
  293. BSTR m_sQuery, //in -IGNORED...
  294. long attrCnt, //in -IGNORED...
  295. LPWSTR * sAttr, //in -IGNORED...
  296. ADS_SEARCHPREF_INFO prefInfo, //in -IGNORED...
  297. BOOL bMultiVal, //in -IGNORED...
  298. IEnumVARIANT **& pVarEnum //out -Pointer to the enumeration object
  299. )
  300. {
  301. // From the full LDAP path truncate to appropriate LDAP subpath
  302. // This function enumerates four types of containers
  303. // USERS, COMPUTERS, GROUPS, DOMAIN CONTROLLERS
  304. // if the container parameter specifies anything other than the three containers then
  305. // we returns UNEXPECTED.
  306. DWORD ulCount;
  307. DWORD rc=0;
  308. DWORD ndx = 0;
  309. TNodeList * pNodeList = new TNodeList();
  310. LPBYTE sServer = NULL;
  311. WCHAR sServerName[LEN_Path];
  312. if (!pNodeList)
  313. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  314. if ( wcsncmp((WCHAR*)sDomainName, L"\\\\", 2) )
  315. {
  316. rc = NetGetDCName(NULL, sDomainName, &sServer);
  317. if (rc == NERR_Success)
  318. {
  319. wcscpy(sServerName, (WCHAR*) sServer);
  320. NetApiBufferFree(sServer);
  321. }
  322. }
  323. else
  324. wcscpy((WCHAR*)sServerName, (WCHAR*) sDomainName);
  325. if ( ! rc )
  326. {
  327. for (UINT i = 0; i < wcslen(sContainerName); i++)
  328. sContainerName[i] = towupper(sContainerName[i]);
  329. if ( wcscmp(sContainerName,L"CN=USERS") &&
  330. wcscmp(sContainerName,L"CN=COMPUTERS") &&
  331. wcscmp(sContainerName,L"CN=GROUPS") &&
  332. wcscmp(sContainerName,L"CN=DOMAIN CONTROLLERS") )
  333. {
  334. // if they selected a group we enumerate the membership of that group.
  335. WCHAR * sTemp = wcstok( sContainerName, L",");
  336. WCHAR * ndx = wcstok( NULL, L",");
  337. if ( ndx && wcscmp(ndx, L"CN=GROUPS") )
  338. {
  339. delete pNodeList;
  340. return E_UNEXPECTED;
  341. }
  342. else
  343. {
  344. // Get the members of the group and add them to the List,
  345. GROUP_USERS_INFO_0 * pbufNetUser;
  346. // DWORD resume=0, total=0;
  347. DWORD total=0;
  348. DWORD_PTR resume=0;
  349. // Get the first set of Members from the Group
  350. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  351. while ( ulCount > 0 )
  352. {
  353. // For each user construnct the array of the properties that they asked for. Then construct a node of that
  354. // array and stuff that into the List.
  355. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  356. {
  357. _variant_t varArr[6] = { pbufNetUser[dwIdx].grui0_name, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  358. TAttrNode * pNode = new TAttrNode(6, varArr);
  359. if (!pNode)
  360. {
  361. delete pNodeList;
  362. NetApiBufferFree(pbufNetUser);
  363. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  364. }
  365. pNodeList->InsertBottom(pNode);
  366. }
  367. NetApiBufferFree(pbufNetUser);
  368. // Get the next set of objects
  369. if ( rc == ERROR_MORE_DATA )
  370. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  371. else
  372. ulCount = 0;
  373. }
  374. // Get the members of the local group and add them to the List,
  375. LOCALGROUP_MEMBERS_INFO_3 * pbufNetInfo;
  376. resume=0;
  377. total=0;
  378. WCHAR sTempName[LEN_Path];
  379. WCHAR sName[LEN_Path];
  380. // Get the first set of Members from the Group
  381. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  382. while ( ulCount > 0 )
  383. {
  384. // For each user create a node set the value of the node to the object name and add it to the list.
  385. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  386. {
  387. wcscpy(sTempName, pbufNetInfo[dwIdx].lgrmi3_domainandname);
  388. if (GetSamNameFromInfo(sTempName, (WCHAR*)sDomainName, sName))
  389. {
  390. _variant_t varArr[6] = { sName, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  391. TAttrNode * pNode = new TAttrNode(6, varArr);
  392. if (!pNode)
  393. {
  394. delete pNodeList;
  395. NetApiBufferFree(pbufNetInfo);
  396. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  397. }
  398. pNodeList->InsertBottom(pNode);
  399. }
  400. }
  401. NetApiBufferFree(pbufNetInfo);
  402. // Get the next set of objects
  403. if ( rc == ERROR_MORE_DATA )
  404. {
  405. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  406. }
  407. else
  408. ulCount = 0;
  409. }
  410. }
  411. }
  412. if (!wcscmp(sContainerName,L"CN=USERS"))
  413. {
  414. // Build User enumeration
  415. NET_DISPLAY_USER * pbufNetUser;
  416. // Get the first set of users from the domain
  417. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  418. while ( ulCount > 0 )
  419. {
  420. // For each user create a node set the value of the node to the object name and add it to the list.
  421. TAttrNode * pNode;
  422. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  423. {
  424. {
  425. _variant_t val[6] = { pbufNetUser[dwIdx].usri1_name,
  426. pbufNetUser[dwIdx].usri1_comment,
  427. (long)0,
  428. (long)0,
  429. pbufNetUser[dwIdx].usri1_full_name,
  430. L"" };
  431. val[2].vt = VT_UI4;
  432. val[2].ulVal = pbufNetUser[dwIdx].usri1_user_id;
  433. val[3].vt = VT_UI4;
  434. val[3].ulVal = pbufNetUser[dwIdx].usri1_flags;
  435. pNode = new TAttrNode(6, val);
  436. if (!pNode)
  437. {
  438. delete pNodeList;
  439. NetApiBufferFree(pbufNetUser);
  440. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  441. }
  442. }
  443. pNodeList->InsertBottom(pNode);
  444. }
  445. // Set the index for next set of users.
  446. if ( ulCount > 0 )
  447. ndx = pbufNetUser[ulCount-1].usri1_next_index;
  448. NetApiBufferFree(pbufNetUser);
  449. // Get the next set of objects
  450. if ( rc == ERROR_MORE_DATA )
  451. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  452. else
  453. ulCount = 0;
  454. }
  455. }
  456. else if (!wcscmp(sContainerName,L"CN=COMPUTERS"))
  457. {
  458. // Build Computers enumeration
  459. NET_DISPLAY_MACHINE * pbufNetUser;
  460. // Get the first set of users from the domain
  461. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  462. // Build the PDC account name.
  463. WCHAR server[LEN_Path];
  464. WCHAR name[LEN_Path];
  465. BOOL bPDCFound = FALSE;
  466. wcscpy(server, (WCHAR*)(sServerName + (2*sizeof(WCHAR))));
  467. wsprintf(name, L"%s$", server);
  468. while ( ulCount > 0 )
  469. {
  470. // For each user create a node set the value of the node to the object name and add it to the list.
  471. TAttrNode * pNode;
  472. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  473. {
  474. // if we process the PDC then we need to let the function know.
  475. if ( wcscmp(pbufNetUser[dwIdx].usri2_name, name) == 0 )
  476. bPDCFound = TRUE;
  477. _variant_t val[6] = { pbufNetUser[dwIdx].usri2_name,
  478. pbufNetUser[dwIdx].usri2_comment,
  479. (long)0,
  480. (long)0,
  481. (long)0,
  482. L"" };
  483. val[2].vt = VT_UI4;
  484. val[2].ulVal = pbufNetUser[dwIdx].usri2_user_id;
  485. val[3].vt = VT_UI4;
  486. val[3].ulVal = pbufNetUser[dwIdx].usri2_flags;
  487. pNode = new TAttrNode(6, val);
  488. if (!pNode)
  489. {
  490. delete pNodeList;
  491. NetApiBufferFree(pbufNetUser);
  492. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  493. }
  494. pNodeList->InsertBottom(pNode);
  495. }
  496. // Set the index for next set of users.
  497. if ( ulCount > 0 )
  498. ndx = pbufNetUser[ulCount-1].usri2_next_index;
  499. NetApiBufferFree(pbufNetUser);
  500. // Get the next set of objects
  501. if ( rc == ERROR_MORE_DATA )
  502. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  503. else
  504. ulCount = 0;
  505. }
  506. // if pdc is already added then we dont need to do any of this.
  507. if ( !bPDCFound )
  508. {
  509. // we will fake all other attributes other than the name
  510. _variant_t val[6] = { name,
  511. L"",
  512. L"",
  513. L"",
  514. L"",
  515. L"" };
  516. val[2].vt = VT_UI4;
  517. val[2].ulVal = 0;
  518. val[3].vt = VT_UI4;
  519. val[3].ulVal = UF_SERVER_TRUST_ACCOUNT | UF_SCRIPT;
  520. TAttrNode * pNode = new TAttrNode(6, val);
  521. if (!pNode)
  522. {
  523. delete pNodeList;
  524. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  525. }
  526. pNodeList->InsertBottom(pNode);
  527. }
  528. }
  529. else if (!wcscmp(sContainerName,L"CN=GROUPS"))
  530. {
  531. // Build Groups enumeration
  532. // Build Computers enumeration
  533. NET_DISPLAY_GROUP * pbufNetUser;
  534. // Get the first set of users from the domain
  535. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  536. while ( ulCount > 0 )
  537. {
  538. // For each user create a node set the value of the node to the object name and add it to the list.
  539. TAttrNode * pNode;
  540. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  541. {
  542. _variant_t val[6] = { pbufNetUser[dwIdx].grpi3_name,
  543. pbufNetUser[dwIdx].grpi3_comment,
  544. L"",
  545. L"",
  546. L"",
  547. L"" };
  548. val[2].vt = VT_UI4;
  549. val[2].ulVal = pbufNetUser[dwIdx].grpi3_group_id;
  550. val[3].vt = VT_UI4;
  551. val[3].ulVal = pbufNetUser[dwIdx].grpi3_attributes;
  552. pNode = new TAttrNode(6, val);
  553. if (!pNode)
  554. {
  555. delete pNodeList;
  556. NetApiBufferFree(pbufNetUser);
  557. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  558. }
  559. pNodeList->InsertBottom(pNode);
  560. }
  561. // Set the index for next set of users.
  562. if ( ulCount > 0 )
  563. ndx = pbufNetUser[ulCount-1].grpi3_next_index;
  564. NetApiBufferFree(pbufNetUser);
  565. // Get the next set of objects
  566. if ( rc == ERROR_MORE_DATA )
  567. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  568. else
  569. ulCount = 0;
  570. }
  571. }
  572. else if (!wcscmp(sContainerName,L"CN=DOMAIN CONTROLLERS"))
  573. {
  574. // Build Domain Controller enumeration
  575. LPSERVER_INFO_101 pBuf = NULL;
  576. DWORD dwLevel = 101;
  577. DWORD dwSize = MAX_PREFERRED_LENGTH;
  578. DWORD dwEntriesRead = 0L;
  579. DWORD dwTotalEntries = 0L;
  580. DWORD dwTotalCount = 0L;
  581. DWORD dwServerType = SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL; // domain controllers
  582. DWORD dwResumeHandle = 0L;
  583. NET_API_STATUS nStatus;
  584. DWORD dw;
  585. //enumerate the primary and backup domain controllers
  586. nStatus = NetServerEnum(NULL,
  587. dwLevel,
  588. (LPBYTE *) &pBuf,
  589. dwSize,
  590. &dwEntriesRead,
  591. &dwTotalEntries,
  592. dwServerType,
  593. (WCHAR*) sDomainName,
  594. &dwResumeHandle);
  595. //if we need a bigger buffer, increase it and try again
  596. if( nStatus != NERR_Success && nStatus == ERROR_MORE_DATA )
  597. {
  598. dwSize = sizeof(SERVER_INFO_100)*dwTotalEntries*MAX_PATH;
  599. NetApiBufferFree(pBuf);
  600. pBuf = NULL;
  601. dwTotalEntries = 0L;
  602. dwEntriesRead = 0L;
  603. dwResumeHandle = 0L;
  604. nStatus = NetServerEnum(NULL,
  605. dwLevel,
  606. (LPBYTE *) &pBuf,
  607. dwSize,
  608. &dwEntriesRead,
  609. &dwTotalEntries,
  610. dwServerType,
  611. (WCHAR*) sDomainName,
  612. &dwResumeHandle);
  613. }
  614. if ((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA))
  615. {
  616. if (pBuf != NULL)
  617. {
  618. // For each DC create a node set the value of the node to the object name and add it to the list.
  619. for (dw = 0; dw < dwEntriesRead; dw++)
  620. {
  621. _variant_t varArr[6] = { pBuf[dw].sv101_name, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  622. TAttrNode * pNode = new TAttrNode(6, varArr);
  623. if (!pNode)
  624. {
  625. delete pNodeList;
  626. NetApiBufferFree(pBuf);
  627. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  628. }
  629. pNodeList->InsertBottom(pNode);
  630. }
  631. NetApiBufferFree(pBuf);
  632. }
  633. }
  634. }//end if enum DCs
  635. // Build an enumerator and return it to the caller.
  636. *pVarEnum = new CNT4Enum(pNodeList);
  637. }
  638. else
  639. delete pNodeList;
  640. return S_OK;
  641. }