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.

555 lines
20 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. #include "GetDcName.h"
  22. #ifdef _DEBUG
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif
  27. //////////////////////////////////////////////////////////////////////
  28. // Construction/Destruction
  29. //////////////////////////////////////////////////////////////////////
  30. #define MAX_BUF 100
  31. #define LEN_Path 255
  32. CNT4Dom::CNT4Dom()
  33. {
  34. }
  35. CNT4Dom::~CNT4Dom()
  36. {
  37. mDCMap.clear();
  38. }
  39. bool GetSamNameFromInfo( WCHAR * sInfo, WCHAR * sDomain, WCHAR * sName)
  40. {
  41. WCHAR domain[LEN_Path];
  42. DWORD dwArraySizeOfDomain = sizeof(domain)/sizeof(domain[0]);
  43. WCHAR * temp;
  44. bool rc = false;
  45. if (sInfo == NULL || wcslen(sInfo) >= dwArraySizeOfDomain)
  46. return rc;
  47. wcscpy(domain, sInfo);
  48. temp = wcschr(domain, L'\\');
  49. if ( temp )
  50. {
  51. *temp = 0;
  52. if (!_wcsicmp(domain, sDomain) || !wcsncmp(sDomain, L"\\\\", 2))
  53. {
  54. rc = true;
  55. wcscpy(sName, ++temp);
  56. }
  57. }
  58. return rc;
  59. }
  60. //-----------------------------------------------------------------------------
  61. // GetEnumeration: This function Enumerates all objects in the above specified
  62. // containers and their 6 standard values which are
  63. // 'name,comment,user/groupID,flags,FullName,description'
  64. //-----------------------------------------------------------------------------
  65. HRESULT CNT4Dom::GetEnumeration(
  66. BSTR sContainerName, //in -Container path
  67. BSTR sDomainName, //in -Domain name
  68. BSTR m_sQuery, //in -IGNORED...
  69. long attrCnt, //in -IGNORED...
  70. LPWSTR * sAttr, //in -IGNORED...
  71. ADS_SEARCHPREF_INFO prefInfo, //in -IGNORED...
  72. BOOL bMultiVal, //in -IGNORED...
  73. IEnumVARIANT **& pVarEnum //out -Pointer to the enumeration object
  74. )
  75. {
  76. // From the full LDAP path truncate to appropriate LDAP subpath
  77. // This function enumerates four types of containers
  78. // USERS, COMPUTERS, GROUPS, DOMAIN CONTROLLERS
  79. // if the container parameter specifies anything other than the three containers then
  80. // we returns UNEXPECTED.
  81. DWORD ulCount = 0;
  82. DWORD rc=0;
  83. DWORD ndx = 0;
  84. TNodeList * pNodeList = new TNodeList();
  85. WCHAR sServerName[LEN_Path];
  86. if (!pNodeList)
  87. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  88. if ( wcsncmp((WCHAR*)sDomainName, L"\\\\", 2) )
  89. {
  90. _bstr_t sDC = GetDC(sDomainName);
  91. wcscpy(sServerName, (WCHAR*)sDC);
  92. }
  93. else
  94. wcscpy((WCHAR*)sServerName, (WCHAR*) sDomainName);
  95. if ( ! rc )
  96. {
  97. for (UINT i = 0; i < wcslen(sContainerName); i++)
  98. sContainerName[i] = towupper(sContainerName[i]);
  99. if ( wcscmp(sContainerName,L"CN=USERS") &&
  100. wcscmp(sContainerName,L"CN=COMPUTERS") &&
  101. wcscmp(sContainerName,L"CN=GROUPS") &&
  102. wcscmp(sContainerName,L"CN=DOMAIN CONTROLLERS") )
  103. {
  104. // if they selected a group we enumerate the membership of that group.
  105. WCHAR * sTemp = wcstok( sContainerName, L",");
  106. WCHAR * ndx = wcstok( NULL, L",");
  107. if ((!ndx) || ( ndx && _wcsicmp(ndx, L"CN=GROUPS") ))
  108. {
  109. delete pNodeList;
  110. return E_UNEXPECTED;
  111. }
  112. else
  113. {
  114. // Get the members of the group and add them to the List,
  115. GROUP_USERS_INFO_0 * pbufNetUser;
  116. // DWORD resume=0, total=0;
  117. DWORD total=0;
  118. DWORD_PTR resume=0;
  119. // Get the first set of Members from the Group
  120. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  121. if ((rc != ERROR_SUCCESS) && (rc != NERR_GroupNotFound) && (rc != ERROR_MORE_DATA))
  122. {
  123. delete pNodeList;
  124. return HRESULT_FROM_WIN32(rc);
  125. }
  126. while ( ulCount > 0 )
  127. {
  128. // For each user construnct the array of the properties that they asked for. Then construct a node of that
  129. // array and stuff that into the List.
  130. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  131. {
  132. _variant_t varArr[6] = { pbufNetUser[dwIdx].grui0_name, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  133. TAttrNode * pNode = new TAttrNode(6, varArr);
  134. if (!pNode)
  135. {
  136. delete pNodeList;
  137. NetApiBufferFree(pbufNetUser);
  138. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  139. }
  140. pNodeList->InsertBottom(pNode);
  141. }
  142. NetApiBufferFree(pbufNetUser);
  143. // Get the next set of objects
  144. if ( rc == ERROR_MORE_DATA )
  145. {
  146. rc = NetGroupGetUsers((WCHAR*) sServerName, sTemp, 0, (LPBYTE*) &pbufNetUser, sizeof(GROUP_USERS_INFO_0) * MAX_BUF, &ulCount, &total, &resume);
  147. if ((rc != ERROR_SUCCESS) && (rc != NERR_GroupNotFound) && (rc != ERROR_MORE_DATA))
  148. {
  149. delete pNodeList;
  150. return HRESULT_FROM_WIN32(rc);
  151. }
  152. }
  153. else
  154. ulCount = 0;
  155. }
  156. // Get the members of the local group and add them to the List,
  157. LOCALGROUP_MEMBERS_INFO_3 * pbufNetInfo;
  158. resume=0;
  159. total=0;
  160. WCHAR sTempName[LEN_Path];
  161. WCHAR sName[LEN_Path];
  162. // Get the first set of Members from the Group
  163. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  164. if ((rc != ERROR_SUCCESS) && (rc != ERROR_NO_SUCH_ALIAS) && (rc != ERROR_MORE_DATA))
  165. {
  166. delete pNodeList;
  167. return HRESULT_FROM_WIN32(rc);
  168. }
  169. while ( ulCount > 0 )
  170. {
  171. // For each user create a node set the value of the node to the object name and add it to the list.
  172. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  173. {
  174. wcscpy(sTempName, pbufNetInfo[dwIdx].lgrmi3_domainandname);
  175. if (GetSamNameFromInfo(sTempName, (WCHAR*)sDomainName, sName))
  176. {
  177. _variant_t varArr[6] = { sName, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  178. TAttrNode * pNode = new TAttrNode(6, varArr);
  179. if (!pNode)
  180. {
  181. delete pNodeList;
  182. NetApiBufferFree(pbufNetInfo);
  183. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  184. }
  185. pNodeList->InsertBottom(pNode);
  186. }
  187. }
  188. NetApiBufferFree(pbufNetInfo);
  189. // Get the next set of objects
  190. if ( rc == ERROR_MORE_DATA )
  191. {
  192. rc = NetLocalGroupGetMembers((WCHAR*) sServerName, sTemp, 3, (LPBYTE*) &pbufNetInfo, sizeof(LOCALGROUP_MEMBERS_INFO_3) * MAX_BUF, &ulCount, &total, &resume);
  193. if ((rc != ERROR_SUCCESS) && (rc != ERROR_NO_SUCH_ALIAS) && (rc != ERROR_MORE_DATA))
  194. {
  195. delete pNodeList;
  196. return HRESULT_FROM_WIN32(rc);
  197. }
  198. }
  199. else
  200. ulCount = 0;
  201. }
  202. }
  203. }
  204. if (!wcscmp(sContainerName,L"CN=USERS"))
  205. {
  206. // Build User enumeration
  207. NET_DISPLAY_USER * pbufNetUser;
  208. // Get the first set of users from the domain
  209. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  210. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  211. {
  212. delete pNodeList;
  213. return HRESULT_FROM_WIN32(rc);
  214. }
  215. while ( ulCount > 0 )
  216. {
  217. // For each user create a node set the value of the node to the object name and add it to the list.
  218. TAttrNode * pNode;
  219. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  220. {
  221. {
  222. _variant_t val[6] = { pbufNetUser[dwIdx].usri1_name,
  223. pbufNetUser[dwIdx].usri1_comment,
  224. (long)0,
  225. (long)0,
  226. pbufNetUser[dwIdx].usri1_full_name,
  227. L"" };
  228. val[2].vt = VT_UI4;
  229. val[2].ulVal = pbufNetUser[dwIdx].usri1_user_id;
  230. val[3].vt = VT_UI4;
  231. val[3].ulVal = pbufNetUser[dwIdx].usri1_flags;
  232. pNode = new TAttrNode(6, val);
  233. if (!pNode)
  234. {
  235. delete pNodeList;
  236. NetApiBufferFree(pbufNetUser);
  237. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  238. }
  239. }
  240. pNodeList->InsertBottom(pNode);
  241. }
  242. // Set the index for next set of users.
  243. if ( ulCount > 0 )
  244. ndx = pbufNetUser[ulCount-1].usri1_next_index;
  245. NetApiBufferFree(pbufNetUser);
  246. // Get the next set of objects
  247. if ( rc == ERROR_MORE_DATA )
  248. {
  249. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 1, ndx, MAX_BUF, sizeof(NET_DISPLAY_USER) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  250. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  251. {
  252. delete pNodeList;
  253. return HRESULT_FROM_WIN32(rc);
  254. }
  255. }
  256. else
  257. ulCount = 0;
  258. }
  259. }
  260. else if (!wcscmp(sContainerName,L"CN=COMPUTERS"))
  261. {
  262. // Build Computers enumeration
  263. NET_DISPLAY_MACHINE * pbufNetUser;
  264. // Get the first set of users from the domain
  265. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  266. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  267. {
  268. delete pNodeList;
  269. return HRESULT_FROM_WIN32(rc);
  270. }
  271. // Build the PDC account name.
  272. WCHAR server[LEN_Path];
  273. WCHAR name[LEN_Path];
  274. BOOL bPDCFound = FALSE;
  275. wcscpy(server, (WCHAR*)(sServerName + (2*sizeof(WCHAR))));
  276. wsprintf(name, L"%s$", server);
  277. while ( ulCount > 0 )
  278. {
  279. // For each user create a node set the value of the node to the object name and add it to the list.
  280. TAttrNode * pNode;
  281. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  282. {
  283. // if we process the PDC then we need to let the function know.
  284. if ( wcscmp(pbufNetUser[dwIdx].usri2_name, name) == 0 )
  285. bPDCFound = TRUE;
  286. _variant_t val[6] = { pbufNetUser[dwIdx].usri2_name,
  287. pbufNetUser[dwIdx].usri2_comment,
  288. (long)0,
  289. (long)0,
  290. (long)0,
  291. L"" };
  292. val[2].vt = VT_UI4;
  293. val[2].ulVal = pbufNetUser[dwIdx].usri2_user_id;
  294. val[3].vt = VT_UI4;
  295. val[3].ulVal = pbufNetUser[dwIdx].usri2_flags;
  296. pNode = new TAttrNode(6, val);
  297. if (!pNode)
  298. {
  299. delete pNodeList;
  300. NetApiBufferFree(pbufNetUser);
  301. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  302. }
  303. pNodeList->InsertBottom(pNode);
  304. }
  305. // Set the index for next set of users.
  306. if ( ulCount > 0 )
  307. ndx = pbufNetUser[ulCount-1].usri2_next_index;
  308. NetApiBufferFree(pbufNetUser);
  309. // Get the next set of objects
  310. if ( rc == ERROR_MORE_DATA )
  311. {
  312. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 2, ndx, MAX_BUF, sizeof(NET_DISPLAY_MACHINE) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  313. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  314. {
  315. delete pNodeList;
  316. return HRESULT_FROM_WIN32(rc);
  317. }
  318. }
  319. else
  320. ulCount = 0;
  321. }
  322. // if pdc is already added then we dont need to do any of this.
  323. if ( !bPDCFound )
  324. {
  325. // we will fake all other attributes other than the name
  326. _variant_t val[6] = { name,
  327. L"",
  328. L"",
  329. L"",
  330. L"",
  331. L"" };
  332. val[2].vt = VT_UI4;
  333. val[2].ulVal = 0;
  334. val[3].vt = VT_UI4;
  335. val[3].ulVal = UF_SERVER_TRUST_ACCOUNT | UF_SCRIPT;
  336. TAttrNode * pNode = new TAttrNode(6, val);
  337. if (!pNode)
  338. {
  339. delete pNodeList;
  340. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  341. }
  342. pNodeList->InsertBottom(pNode);
  343. }
  344. }
  345. else if (!wcscmp(sContainerName,L"CN=GROUPS"))
  346. {
  347. // Build Groups enumeration
  348. // Build Computers enumeration
  349. NET_DISPLAY_GROUP * pbufNetUser;
  350. // Get the first set of users from the domain
  351. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  352. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  353. {
  354. delete pNodeList;
  355. return HRESULT_FROM_WIN32(rc);
  356. }
  357. while ( ulCount > 0 )
  358. {
  359. // For each user create a node set the value of the node to the object name and add it to the list.
  360. TAttrNode * pNode;
  361. for ( DWORD dwIdx = 0; dwIdx < ulCount; dwIdx++ )
  362. {
  363. _variant_t val[6] = { pbufNetUser[dwIdx].grpi3_name,
  364. pbufNetUser[dwIdx].grpi3_comment,
  365. L"",
  366. L"",
  367. L"",
  368. L"" };
  369. val[2].vt = VT_UI4;
  370. val[2].ulVal = pbufNetUser[dwIdx].grpi3_group_id;
  371. val[3].vt = VT_UI4;
  372. val[3].ulVal = pbufNetUser[dwIdx].grpi3_attributes;
  373. pNode = new TAttrNode(6, val);
  374. if (!pNode)
  375. {
  376. delete pNodeList;
  377. NetApiBufferFree(pbufNetUser);
  378. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  379. }
  380. pNodeList->InsertBottom(pNode);
  381. }
  382. // Set the index for next set of users.
  383. if ( ulCount > 0 )
  384. ndx = pbufNetUser[ulCount-1].grpi3_next_index;
  385. NetApiBufferFree(pbufNetUser);
  386. // Get the next set of objects
  387. if ( rc == ERROR_MORE_DATA )
  388. {
  389. rc = NetQueryDisplayInformation((WCHAR *)sServerName, 3, ndx, MAX_BUF, sizeof(NET_DISPLAY_GROUP) * MAX_BUF, &ulCount, (void **)&pbufNetUser);
  390. if ((rc != ERROR_SUCCESS) && (rc != ERROR_MORE_DATA))
  391. {
  392. delete pNodeList;
  393. return HRESULT_FROM_WIN32(rc);
  394. }
  395. }
  396. else
  397. ulCount = 0;
  398. }
  399. }
  400. else if (!wcscmp(sContainerName,L"CN=DOMAIN CONTROLLERS"))
  401. {
  402. // Build Domain Controller enumeration
  403. LPSERVER_INFO_101 pBuf = NULL;
  404. DWORD dwLevel = 101;
  405. DWORD dwSize = MAX_PREFERRED_LENGTH;
  406. DWORD dwEntriesRead = 0L;
  407. DWORD dwTotalEntries = 0L;
  408. DWORD dwTotalCount = 0L;
  409. DWORD dwServerType = SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_BAKCTRL; // domain controllers
  410. DWORD dwResumeHandle = 0L;
  411. NET_API_STATUS nStatus;
  412. DWORD dw;
  413. //enumerate the primary and backup domain controllers
  414. nStatus = NetServerEnum(NULL,
  415. dwLevel,
  416. (LPBYTE *) &pBuf,
  417. dwSize,
  418. &dwEntriesRead,
  419. &dwTotalEntries,
  420. dwServerType,
  421. (WCHAR*) sDomainName,
  422. &dwResumeHandle);
  423. if (nStatus == NERR_Success)
  424. {
  425. if (pBuf != NULL)
  426. {
  427. // For each DC create a node set the value of the node to the object name and add it to the list.
  428. for (dw = 0; dw < dwEntriesRead; dw++)
  429. {
  430. _variant_t varArr[6] = { pBuf[dw].sv101_name, (long)0, (long)0, (long)0, (long)0, (long)0 } ;
  431. TAttrNode * pNode = new TAttrNode(6, varArr);
  432. if (!pNode)
  433. {
  434. delete pNodeList;
  435. NetApiBufferFree(pBuf);
  436. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  437. }
  438. pNodeList->InsertBottom(pNode);
  439. }
  440. NetApiBufferFree(pBuf);
  441. }
  442. }
  443. else
  444. {
  445. delete pNodeList;
  446. return HRESULT_FROM_WIN32(nStatus);
  447. }
  448. }//end if enum DCs
  449. // Build an enumerator and return it to the caller.
  450. *pVarEnum = new CNT4Enum(pNodeList);
  451. }
  452. else
  453. delete pNodeList;
  454. return S_OK;
  455. }
  456. /*********************************************************************
  457. * *
  458. * Written by: Paul Thompson *
  459. * Date: 14 JUNE 2001 *
  460. * *
  461. * This function is responsible for getting the name of the PDC *
  462. * for the given domain. We store the domain\PDC pairs in a map *
  463. * class variable so that we only have to look up the PDC once per *
  464. * instantiations of this object. *
  465. * *
  466. *********************************************************************/
  467. //BEGIN GetDC
  468. _bstr_t CNT4Dom::GetDC(_bstr_t sDomain)
  469. {
  470. /* local variables */
  471. _bstr_t sDC;
  472. CDCMap::iterator itDCMap;
  473. /* function body */
  474. if (!sDomain.length())
  475. return L"";
  476. //look if we have already cached the naming context for this domain
  477. itDCMap = mDCMap.find(sDomain);
  478. //if found, get the cached naming context
  479. if (itDCMap != mDCMap.end())
  480. {
  481. sDC = itDCMap->second;
  482. }
  483. else //else, lookup the PDC from scratch and add that to the cache
  484. {
  485. if (GetAnyDcName5(sDomain, sDC) == ERROR_SUCCESS)
  486. {
  487. mDCMap.insert(CDCMap::value_type(sDomain, sDC));
  488. }
  489. }
  490. return sDC;
  491. }
  492. //END GetDC