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.

1219 lines
39 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000
  5. //
  6. // File: dsget.cpp
  7. //
  8. // Contents: Defines the main function DSGET
  9. // command line utility
  10. //
  11. // History: 13-Oct-2000 JeffJon Created
  12. //
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "pch.h"
  16. #include "cstrings.h"
  17. #include "usage.h"
  18. #include "gettable.h"
  19. #include "query.h"
  20. #include "resource.h"
  21. #include "output.h"
  22. //
  23. // Forward Function Declarations
  24. //
  25. HRESULT DoGetValidation(PARG_RECORD pCommandArgs,
  26. PDSGetObjectTableEntry pObjectEntry,
  27. BOOL& bErrorShown);
  28. HRESULT DoGet(PARG_RECORD pCommandArgs,
  29. PDSGetObjectTableEntry pObjectEntry);
  30. HRESULT GetAttributesToFetch(IN PARG_RECORD pCommandArgs,
  31. IN PDSGetObjectTableEntry pObjectEntry,
  32. OUT LPWSTR **ppszAttributes,
  33. OUT DWORD * pCount);
  34. VOID FreeAttributesToFetch( IN LPWSTR *ppszAttributes,
  35. IN DWORD dwCount);
  36. HRESULT SetRange(IN LPCWSTR pszAttrName,
  37. IN DWORD dwRangeUBound,
  38. OUT LPWSTR* pszAttrs);
  39. // NTRAID#NTBUG9-717576-2002/10/10-JeffJon
  40. // set this global so that we don't show the success message
  41. // when displaying members of a group or memberof or manager
  42. bool bDontDisplaySuccess = false;
  43. //
  44. //Main Function
  45. //
  46. int __cdecl _tmain( VOID )
  47. {
  48. int argc = 0;
  49. LPTOKEN pToken = NULL;
  50. HRESULT hr = S_OK;
  51. PARG_RECORD pNewCommandArgs = 0;
  52. //
  53. // False loop
  54. //
  55. do
  56. {
  57. //
  58. // Initialize COM
  59. //
  60. hr = ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  61. if (FAILED(hr))
  62. break;
  63. //Get CommandLine Input
  64. DWORD _dwErr = GetCommandInput(&argc,&pToken);
  65. hr = HRESULT_FROM_WIN32(_dwErr);
  66. if(FAILED(hr))
  67. break;
  68. if(argc == 1)
  69. {
  70. //
  71. // Display the error message and then break out of the false loop
  72. //
  73. DisplayMessage(USAGE_DSGET,TRUE);
  74. hr = E_INVALIDARG;
  75. break;
  76. }
  77. if(argc == 2)
  78. {
  79. if(IsTokenHelpSwitch(pToken + 1))
  80. {
  81. hr = S_OK;
  82. DisplayMessage(USAGE_DSGET,TRUE);
  83. break;
  84. }
  85. }
  86. //
  87. // Find which object table entry to use from
  88. // the second command line argument
  89. //
  90. PDSGetObjectTableEntry pObjectEntry = NULL;
  91. UINT idx = 0;
  92. PWSTR pszObjectType = (pToken+1)->GetToken();
  93. while (true)
  94. {
  95. pObjectEntry = g_DSObjectTable[idx++];
  96. if (!pObjectEntry)
  97. {
  98. break;
  99. }
  100. //Security Review:Both are null terminated.
  101. if (0 == _wcsicmp(pObjectEntry->pszCommandLineObjectType, pszObjectType))
  102. {
  103. break;
  104. }
  105. }
  106. if (!pObjectEntry)
  107. {
  108. //
  109. // Display the error message and then break out of the false loop
  110. //
  111. DisplayMessage(USAGE_DSGET);
  112. hr = E_INVALIDARG;
  113. break;
  114. }
  115. //
  116. // Now that we have the correct table entry, merge the command line table
  117. // for this object with the common commands
  118. //
  119. hr = MergeArgCommand(DSGET_COMMON_COMMANDS,
  120. pObjectEntry->pParserTable,
  121. &pNewCommandArgs);
  122. if (FAILED(hr))
  123. break;
  124. //
  125. //Parse the Input
  126. //
  127. PARSE_ERROR Error;
  128. if(!ParseCmd(g_pszDSCommandName,
  129. pNewCommandArgs,
  130. argc-1,
  131. pToken+1,
  132. pObjectEntry->nUsageID,
  133. &Error,
  134. TRUE))
  135. {
  136. //ParseCmd did not display any error. Error should
  137. //be handled here. Check DisplayParseError for the
  138. //cases where Error is not shown by ParseCmd
  139. if(!Error.MessageShown)
  140. {
  141. hr = E_INVALIDARG;
  142. DisplayErrorMessage(g_pszDSCommandName,
  143. NULL,
  144. hr);
  145. break;
  146. }
  147. if(Error.ErrorSource == ERROR_FROM_PARSER
  148. && Error.Error == PARSE_ERROR_HELP_SWITCH)
  149. {
  150. hr = S_OK;
  151. break;
  152. }
  153. hr = E_INVALIDARG;
  154. break;
  155. }
  156. //
  157. // Check to see if we are doing debug spew
  158. //
  159. #ifdef DBG
  160. bool bDebugging = pNewCommandArgs[eCommDebug].bDefined &&
  161. pNewCommandArgs[eCommDebug].nValue;
  162. if (bDebugging)
  163. {
  164. ENABLE_DEBUG_OUTPUT(pNewCommandArgs[eCommDebug].nValue);
  165. }
  166. #else
  167. DISABLE_DEBUG_OUTPUT();
  168. #endif
  169. //
  170. // Do extra validation like switch dependency check etc.
  171. //
  172. BOOL bErrorShown = FALSE;
  173. hr = DoGetValidation(pNewCommandArgs,
  174. pObjectEntry,
  175. bErrorShown);
  176. if (FAILED(hr))
  177. {
  178. if (!bErrorShown)
  179. {
  180. DisplayErrorMessage(g_pszDSCommandName, 0, hr);
  181. }
  182. break;
  183. }
  184. //
  185. // Command line parsing succeeded
  186. //
  187. hr = DoGet(pNewCommandArgs,
  188. pObjectEntry);
  189. if(FAILED(hr))
  190. break;
  191. } while (false); //False Loop
  192. //
  193. //Do the CleanUp
  194. //
  195. //
  196. // Free the memory associated with the command values
  197. //
  198. if (pNewCommandArgs)
  199. {
  200. FreeCmd(pNewCommandArgs);
  201. }
  202. //
  203. // Free the tokens
  204. //
  205. if (pToken)
  206. {
  207. delete[] pToken;
  208. pToken = 0;
  209. }
  210. //
  211. //Display Failure or Success Message
  212. //
  213. // NTRAID#NTBUG9-717576-2002/10/10-JeffJon
  214. // don't show the success message when displaying members
  215. // of a group or memberof
  216. if(SUCCEEDED(hr) && !bDontDisplaySuccess)
  217. {
  218. DisplaySuccessMessage(g_pszDSCommandName,
  219. NULL);
  220. }
  221. //
  222. // Uninitialize COM
  223. //
  224. CoUninitialize();
  225. return hr;
  226. }
  227. //+--------------------------------------------------------------------------
  228. //
  229. // Function: DoGetValidation
  230. //
  231. // Synopsis: Checks to be sure that command line switches that are mutually
  232. // exclusive are not both present and those that are dependent are
  233. // both present, and other validations which cannot be done by parser.
  234. //
  235. // Arguments: [pCommandArgs - IN] : the command line argument structure used
  236. // to retrieve the values for each switch
  237. // [pObjectEntry - IN] : pointer to the object table entry for the
  238. // object type that will be queryied
  239. // [bErrorShown - OUT] : this is set to true if the error is
  240. // displayed within this function
  241. //
  242. // Returns: HRESULT : S_OK if everything succeeded
  243. // E_INVALIDARG if the object entry wasn't found
  244. //
  245. // History: 13-Oct-2000 JeffJon Created
  246. // 15-Jan-2002 JeffJon Added the bErrorShown out parameter
  247. // and a special error message for server/domain
  248. //
  249. //---------------------------------------------------------------------------
  250. HRESULT DoGetValidation(IN PARG_RECORD pCommandArgs,
  251. IN PDSGetObjectTableEntry pObjectEntry,
  252. OUT BOOL& bErrorShown)
  253. {
  254. ENTER_FUNCTION_HR(MINIMAL_LOGGING, DoGetValidation, hr);
  255. do // false loop
  256. {
  257. if (!pCommandArgs ||
  258. !pObjectEntry)
  259. {
  260. ASSERT(pCommandArgs);
  261. ASSERT(pObjectEntry);
  262. hr = E_INVALIDARG;
  263. break;
  264. }
  265. // Check to be sure the server and domain switches
  266. // are mutually exclusive
  267. if (pCommandArgs[eCommServer].bDefined &&
  268. pCommandArgs[eCommDomain].bDefined)
  269. {
  270. hr = E_INVALIDARG;
  271. DisplayErrorMessage(g_pszDSCommandName, 0, hr, IDS_NO_SERVER_AND_DOMAIN);
  272. bErrorShown = TRUE;
  273. break;
  274. }
  275. //
  276. // Check the object type specific switches
  277. //
  278. PWSTR pszObjectType = NULL;
  279. if (!pCommandArgs[eCommObjectType].bDefined &&
  280. !pCommandArgs[eCommObjectType].strValue)
  281. {
  282. hr = E_INVALIDARG;
  283. break;
  284. }
  285. pszObjectType = pCommandArgs[eCommObjectType].strValue;
  286. UINT nMemberOfIdx = 0;
  287. UINT nExpandIdx = 0;
  288. UINT nIdxLast = 0;
  289. UINT nMembersIdx = 0;
  290. bool bMembersDefined = false;
  291. bool bMemberOfDefined = false;
  292. UINT nPartIdx = 0;
  293. bool bServerPartDefined = false;
  294. bool bPartitionTopObjDefined = false;
  295. bool bServerTopObjDefined = false;
  296. //Security Review:Both are null terminated.
  297. if (0 == _wcsicmp(g_pszUser, pszObjectType) )
  298. {
  299. nMemberOfIdx = eUserMemberOf;
  300. nExpandIdx = eUserExpand;
  301. nIdxLast = eUserLast;
  302. if (pCommandArgs[eUserMemberOf].bDefined)
  303. {
  304. bMemberOfDefined = true;
  305. }
  306. //
  307. // If nothing is defined, then define DN, SAMAccountName, and Description
  308. //
  309. bool bSomethingDefined = false;
  310. for (UINT nIdx = eCommDN; nIdx <= eUserLast; nIdx++)
  311. {
  312. if (pCommandArgs[nIdx].bDefined)
  313. {
  314. bSomethingDefined = true;
  315. break;
  316. }
  317. }
  318. if (!bSomethingDefined)
  319. {
  320. pCommandArgs[eCommDN].bDefined = TRUE;
  321. pCommandArgs[eCommDN].bValue = TRUE;
  322. pCommandArgs[eUserSamID].bDefined = TRUE;
  323. pCommandArgs[eUserSamID].bValue = TRUE;
  324. pCommandArgs[eCommDescription].bDefined = TRUE;
  325. pCommandArgs[eCommDescription].bValue = TRUE;
  326. }
  327. if (pCommandArgs[eUserManager].bDefined)
  328. {
  329. bDontDisplaySuccess = true;
  330. }
  331. }
  332. //Security Review:Both are null terminated.
  333. else if (0 == _wcsicmp(g_pszComputer, pszObjectType) )
  334. {
  335. nMemberOfIdx = eComputerMemberOf;
  336. nExpandIdx = eComputerExpand;
  337. nIdxLast = eComputerLast;
  338. if (pCommandArgs[eComputerMemberOf].bDefined)
  339. {
  340. bMemberOfDefined = true;
  341. }
  342. //
  343. // If nothing is defined, then define DN, and Description
  344. //
  345. bool bSomethingDefined = false;
  346. for (UINT nIdx = eCommDN; nIdx <= eComputerLast; nIdx++)
  347. {
  348. if (pCommandArgs[nIdx].bDefined)
  349. {
  350. bSomethingDefined = true;
  351. break;
  352. }
  353. }
  354. if (!bSomethingDefined)
  355. {
  356. pCommandArgs[eCommDN].bDefined = TRUE;
  357. pCommandArgs[eCommDN].bValue = TRUE;
  358. pCommandArgs[eCommDescription].bDefined = TRUE;
  359. pCommandArgs[eCommDescription].bValue = TRUE;
  360. }
  361. }
  362. // Both are null terminated.
  363. else if (0 == _wcsicmp(g_pszPartition, pszObjectType) )
  364. {
  365. if (pCommandArgs[ePartitionTopObjOwner].bDefined)
  366. {
  367. nPartIdx = ePartitionTopObjOwner;
  368. nIdxLast = ePartitionLast;
  369. bPartitionTopObjDefined = true;
  370. }
  371. }
  372. // Both are null terminated.
  373. else if (0 == _wcsicmp(g_pszServer, pszObjectType) )
  374. {
  375. if (pCommandArgs[eServerPart].bDefined)
  376. {
  377. nPartIdx = eServerPart;
  378. nIdxLast = eServerLast;
  379. bServerPartDefined = true;
  380. }
  381. else if(pCommandArgs[eServerTopObjOwner].bDefined)
  382. {
  383. nPartIdx = eServerTopObjOwner;
  384. nIdxLast = eServerLast;
  385. bServerTopObjDefined = true;
  386. }
  387. }
  388. //Security Review:Both are null terminated.
  389. else if (0 == _wcsicmp(g_pszGroup, pszObjectType) )
  390. {
  391. nMemberOfIdx = eGroupMemberOf;
  392. nExpandIdx = eGroupExpand;
  393. nIdxLast = eGroupLast;
  394. nMembersIdx = eGroupMembers;
  395. if (pCommandArgs[eGroupMemberOf].bDefined)
  396. {
  397. bMemberOfDefined = true;
  398. }
  399. if (pCommandArgs[eGroupMembers].bDefined)
  400. {
  401. bMembersDefined = true;
  402. }
  403. //
  404. // If nothing is defined, then define DN, and Description
  405. //
  406. bool bSomethingDefined = false;
  407. for (UINT nIdx = eCommDN; nIdx <= eGroupLast; nIdx++)
  408. {
  409. if (pCommandArgs[nIdx].bDefined)
  410. {
  411. bSomethingDefined = true;
  412. break;
  413. }
  414. }
  415. if (!bSomethingDefined)
  416. {
  417. pCommandArgs[eCommDN].bDefined = TRUE;
  418. pCommandArgs[eCommDN].bValue = TRUE;
  419. pCommandArgs[eCommDescription].bDefined = TRUE;
  420. pCommandArgs[eCommDescription].bValue = TRUE;
  421. }
  422. }
  423. //Security Review:Both are null terminated.
  424. else if (0 == _wcsicmp(g_pszOU, pszObjectType))
  425. {
  426. //
  427. // If nothing is defined, then define DN, and Description
  428. //
  429. bool bSomethingDefined = false;
  430. for (UINT nIdx = eCommDN; nIdx <= eCommDescription; nIdx++)
  431. {
  432. if (pCommandArgs[nIdx].bDefined)
  433. {
  434. bSomethingDefined = true;
  435. break;
  436. }
  437. }
  438. if (!bSomethingDefined)
  439. {
  440. pCommandArgs[eCommDN].bDefined = TRUE;
  441. pCommandArgs[eCommDN].bValue = TRUE;
  442. pCommandArgs[eCommDescription].bDefined = TRUE;
  443. pCommandArgs[eCommDescription].bValue = TRUE;
  444. }
  445. }
  446. //Security Review:Both are null terminated.
  447. else if(0 == _wcsicmp(g_pszContact, pszObjectType))
  448. {
  449. //
  450. // If nothing is defined, then define DN, and Description
  451. //
  452. bool bSomethingDefined = false;
  453. for (UINT nIdx = eCommDN; nIdx <= eContactLast; nIdx++)
  454. {
  455. if (pCommandArgs[nIdx].bDefined)
  456. {
  457. bSomethingDefined = true;
  458. break;
  459. }
  460. }
  461. if (!bSomethingDefined)
  462. {
  463. pCommandArgs[eCommDN].bDefined = TRUE;
  464. pCommandArgs[eCommDN].bValue = TRUE;
  465. pCommandArgs[eCommDescription].bDefined = TRUE;
  466. pCommandArgs[eCommDescription].bValue = TRUE;
  467. }
  468. }
  469. //Security Review:Both are null terminated.
  470. else if(0 == _wcsicmp(g_pszServer, pszObjectType))
  471. {
  472. //
  473. // If nothing is defined, then define DN, and Description
  474. //
  475. bool bSomethingDefined = false;
  476. for (UINT nIdx = eCommDN; nIdx <= eServerLast; nIdx++)
  477. {
  478. if (pCommandArgs[nIdx].bDefined)
  479. {
  480. bSomethingDefined = true;
  481. break;
  482. }
  483. }
  484. if (!bSomethingDefined)
  485. {
  486. pCommandArgs[eCommDN].bDefined = TRUE;
  487. pCommandArgs[eCommDN].bValue = TRUE;
  488. pCommandArgs[eServerDnsName].bDefined = TRUE;
  489. pCommandArgs[eServerDnsName].bValue = TRUE;
  490. }
  491. }
  492. //Security Review:Both are null terminated.
  493. else if(0 == _wcsicmp(g_pszSite, pszObjectType))
  494. {
  495. //
  496. // If nothing is defined, then define DN, and Description
  497. //
  498. bool bSomethingDefined = false;
  499. for (UINT nIdx = eCommDN; nIdx <= eSiteLast; nIdx++)
  500. {
  501. if (pCommandArgs[nIdx].bDefined)
  502. {
  503. bSomethingDefined = true;
  504. break;
  505. }
  506. }
  507. if (!bSomethingDefined)
  508. {
  509. pCommandArgs[eCommDN].bDefined = TRUE;
  510. pCommandArgs[eCommDN].bValue = TRUE;
  511. pCommandArgs[eCommDescription].bDefined = TRUE;
  512. pCommandArgs[eCommDescription].bValue = TRUE;
  513. }
  514. }
  515. //Security Review:Both are null terminated.
  516. else if(0 == _wcsicmp(g_pszSubnet, pszObjectType))
  517. {
  518. //
  519. // If nothing is defined, then define DN, and Description
  520. //
  521. bool bSomethingDefined = false;
  522. for (UINT nIdx = eCommDN; nIdx <= eSubnetLast; nIdx++)
  523. {
  524. if (pCommandArgs[nIdx].bDefined)
  525. {
  526. bSomethingDefined = true;
  527. break;
  528. }
  529. }
  530. if (!bSomethingDefined)
  531. {
  532. pCommandArgs[eCommDN].bDefined = TRUE;
  533. pCommandArgs[eCommDN].bValue = TRUE;
  534. pCommandArgs[eCommDescription].bDefined = TRUE;
  535. pCommandArgs[eCommDescription].bValue = TRUE;
  536. pCommandArgs[eSubnetSite].bDefined = TRUE;
  537. pCommandArgs[eSubnetSite].bValue = TRUE;
  538. }
  539. }
  540. //
  541. // if the -members or the -memberof switch is defined
  542. //
  543. if (bMemberOfDefined ||
  544. bMembersDefined)
  545. {
  546. // NTRAID#NTBUG9-717576-2002/10/10-JeffJon
  547. // set this global so that we don't show the success message
  548. // when displaying members of a group or memberof
  549. bDontDisplaySuccess = true;
  550. // 476206-2002/04/23-JonN
  551. if (bMemberOfDefined && bMembersDefined)
  552. {
  553. hr = E_INVALIDARG;
  554. break;
  555. }
  556. //
  557. // If either the -members or -memberof switch is defined,
  558. // no other switches may be defined
  559. //
  560. for (UINT nIdx = eCommDN; nIdx < nIdxLast; nIdx++)
  561. {
  562. // 476206-2002/04/23-JonN
  563. if (pCommandArgs[nIdx].bDefined &&
  564. nIdx != nMemberOfIdx &&
  565. nIdx != nMembersIdx &&
  566. nIdx != nExpandIdx)
  567. {
  568. hr = E_INVALIDARG;
  569. break;
  570. }
  571. }
  572. //
  573. // MemberOf should always be seen in list view
  574. //
  575. pCommandArgs[eCommList].bDefined = TRUE;
  576. pCommandArgs[eCommList].bValue = TRUE;
  577. }
  578. //
  579. // if the [server -part], [partition -topobjowner]
  580. // or [server -topobjowner] switch is defined
  581. //
  582. if (bServerPartDefined || bPartitionTopObjDefined || bServerTopObjDefined)
  583. {
  584. // Server and Partition are mutually exclusive objects types so
  585. // the parser will ensure that these two flags can never be true
  586. // at the same time. The following check ensures that both values
  587. // weren't passed at the same time
  588. if (bServerPartDefined && bServerTopObjDefined)
  589. {
  590. DEBUG_OUTPUT(MINIMAL_LOGGING,
  591. L"Server -part and server -topobjowner can not be defined at the same time");
  592. hr = E_INVALIDARG;
  593. break;
  594. }
  595. // If one of these switches is defined,
  596. // then no other switches may be defined
  597. for (UINT nIdx = eCommDN; nIdx < nIdxLast; nIdx++)
  598. {
  599. if (pCommandArgs[nIdx].bDefined && nIdx != nPartIdx)
  600. {
  601. hr = E_INVALIDARG;
  602. break;
  603. }
  604. }
  605. //
  606. // should always be seen in a list view
  607. //
  608. pCommandArgs[eCommList].bDefined = TRUE;
  609. pCommandArgs[eCommList].bValue = TRUE;
  610. }
  611. } while (false);
  612. return hr;
  613. }
  614. //+--------------------------------------------------------------------------
  615. //
  616. // Function: DoGet
  617. //
  618. // Synopsis: Does the get
  619. // Arguments: [pCommandArgs - IN] : the command line argument structure used
  620. // to retrieve the values for each switch
  621. // [pObjectEntry - IN] : pointer to the object table entry for the
  622. // object type that will be modified
  623. //
  624. // Returns: HRESULT : S_OK if everything succeeded
  625. // E_INVALIDARG if the object entry wasn't found
  626. // Anything else is a failure code from an ADSI call
  627. //
  628. // History: 13-Oct-2000 JeffJon Created
  629. //
  630. //---------------------------------------------------------------------------
  631. HRESULT DoGet(PARG_RECORD pCommandArgs,
  632. PDSGetObjectTableEntry pObjectEntry)
  633. {
  634. ENTER_FUNCTION_HR(MINIMAL_LOGGING, DoGet, hr);
  635. PWSTR pszPartitionDN = NULL;
  636. do // false loop
  637. {
  638. if (!pCommandArgs ||
  639. !pObjectEntry)
  640. {
  641. ASSERT(pCommandArgs);
  642. ASSERT(pObjectEntry);
  643. hr = E_INVALIDARG;
  644. break;
  645. }
  646. //
  647. // The DNs or Names should be given as a \0 separated list
  648. // So parse it and loop through each object
  649. //
  650. UINT nStrings = 0;
  651. PWSTR* ppszArray = NULL;
  652. ParseNullSeparatedString(pCommandArgs[eCommObjectDNorName].strValue,
  653. &ppszArray,
  654. &nStrings);
  655. if (nStrings < 1 ||
  656. !ppszArray)
  657. {
  658. //
  659. // Display an error message and then fail
  660. //
  661. hr = E_INVALIDARG;
  662. DisplayErrorMessage(g_pszDSCommandName, 0, hr);
  663. break;
  664. }
  665. // Make sure all the DNs actually have DN syntax
  666. bool bContinue = pCommandArgs[eCommContinue].bDefined &&
  667. pCommandArgs[eCommContinue].bValue;
  668. UINT nValidDNs = ValidateDNSyntax(ppszArray, nStrings);
  669. if (nValidDNs < nStrings && !bContinue)
  670. {
  671. hr = E_ADS_BAD_PATHNAME;
  672. DisplayErrorMessage(g_pszDSCommandName, 0, hr);
  673. break;
  674. }
  675. CDSCmdCredentialObject credentialObject;
  676. if (pCommandArgs[eCommUserName].bDefined)
  677. {
  678. credentialObject.SetUsername(pCommandArgs[eCommUserName].strValue);
  679. credentialObject.SetUsingCredentials(true);
  680. }
  681. if (pCommandArgs[eCommPassword].bDefined)
  682. {
  683. //Security Review:pCommandArgs[eCommPassword].strValue is encrypted.
  684. //Decrypt pCommandArgs[eCommPassword].strValue and then pass it to the
  685. //credentialObject.SetPassword.
  686. //See NTRAID#NTBUG9-571544-2000/11/13-hiteshr
  687. credentialObject.SetEncryptedPassword(&pCommandArgs[eCommPassword].encryptedDataBlob);
  688. credentialObject.SetUsingCredentials(true);
  689. }
  690. //
  691. // Initialize the base paths info from the command line args
  692. //
  693. CDSCmdBasePathsInfo basePathsInfo;
  694. if (pCommandArgs[eCommServer].bDefined)
  695. {
  696. hr = basePathsInfo.InitializeFromName(credentialObject,
  697. pCommandArgs[eCommServer].strValue,
  698. true);
  699. }
  700. else if (pCommandArgs[eCommDomain].bDefined)
  701. {
  702. hr = basePathsInfo.InitializeFromName(credentialObject,
  703. pCommandArgs[eCommDomain].strValue,
  704. false);
  705. }
  706. else
  707. {
  708. hr = basePathsInfo.InitializeFromName(credentialObject, NULL, false);
  709. }
  710. if (FAILED(hr))
  711. {
  712. break;
  713. }
  714. //
  715. // Create the formatting object and initialize it
  716. //
  717. CFormatInfo formatInfo;
  718. hr = formatInfo.Initialize(nStrings,
  719. pCommandArgs[eCommList].bDefined != 0,
  720. pCommandArgs[eCommQuiet].bDefined != 0);
  721. if (FAILED(hr))
  722. {
  723. break;
  724. }
  725. //
  726. // Loop through each of the objects
  727. //
  728. for (UINT nNameIdx = 0; nNameIdx < nStrings; nNameIdx++)
  729. {
  730. //
  731. // Use a false do loop here so that we can break on an
  732. // error but still have the chance to determine if we
  733. // should continue the for loop if the -c option was provided
  734. //
  735. bool fDisplayedMessage = false; // 662519-2002/07/11-JonN double-display
  736. do // false loop
  737. {
  738. PWSTR pszObjectDN = ppszArray[nNameIdx];
  739. if (!pszObjectDN)
  740. {
  741. //
  742. // Display an error message and then fail
  743. //
  744. hr = E_INVALIDARG;
  745. break;
  746. }
  747. // If partition object then look at first DN and then munge it
  748. if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition))
  749. {
  750. // Validate the partition and get the DN to the NTDS Quotas Container
  751. hr = GetQuotaContainerDN(basePathsInfo, credentialObject,
  752. pszObjectDN, &pszPartitionDN);
  753. if(FAILED(hr))
  754. {
  755. hr = E_INVALIDARG;
  756. DisplayErrorMessage(g_pszDSCommandName,
  757. NULL,
  758. hr,
  759. IDS_ERRMSG_NO_QUOTAS_CONTAINER);
  760. fDisplayedMessage = true;
  761. break;
  762. }
  763. // Replace the object pointer with the new partition container DN
  764. pszObjectDN = pszPartitionDN;
  765. }
  766. DEBUG_OUTPUT(MINIMAL_LOGGING, L"Object DN = %s", pszObjectDN);
  767. CComBSTR sbstrObjectPath;
  768. basePathsInfo.ComposePathFromDN(pszObjectDN, sbstrObjectPath);
  769. CComPtr<IDirectoryObject> spObject;
  770. hr = DSCmdOpenObject(credentialObject,
  771. sbstrObjectPath,
  772. IID_IDirectoryObject,
  773. (void**)&spObject,
  774. true);
  775. if(FAILED(hr))
  776. {
  777. break;
  778. }
  779. // 602981-2002/04/25-JonN check object class
  780. CComQIPtr<IADs> spADs(spObject);
  781. if (!spADs)
  782. {
  783. ASSERT(spADs);
  784. hr = E_INVALIDARG;
  785. DisplayErrorMessage(g_pszDSCommandName,
  786. pszObjectDN,
  787. hr);
  788. fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display
  789. break;
  790. }
  791. CComBSTR sbstrClass;
  792. hr = spADs->get_Class( &sbstrClass );
  793. if (FAILED(hr))
  794. {
  795. DEBUG_OUTPUT(MINIMAL_LOGGING,
  796. L"get_Class failed: hr = 0x%x",
  797. hr);
  798. DisplayErrorMessage(g_pszDSCommandName,
  799. pszObjectDN,
  800. hr);
  801. fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display
  802. break;
  803. }
  804. if (_wcsicmp(sbstrClass, pObjectEntry->pszObjectClass)
  805. && ( _wcsicmp(pObjectEntry->pszObjectClass,L"user")
  806. || _wcsicmp(sbstrClass,L"inetorgperson"))
  807. // 662519-2002/07/11-JonN fix OU bug
  808. && ( _wcsicmp(pObjectEntry->pszObjectClass,L"ou")
  809. || _wcsicmp(sbstrClass,L"organizationalUnit"))
  810. )
  811. {
  812. //
  813. // Display error message and return
  814. //
  815. DEBUG_OUTPUT(MINIMAL_LOGGING, L"Command line type does not match object class");
  816. DEBUG_OUTPUT(MINIMAL_LOGGING, L"command line type = %s", pCommandArgs[eCommObjectType].strValue);
  817. DEBUG_OUTPUT(MINIMAL_LOGGING, L"object class = %s", sbstrClass);
  818. DisplayErrorMessage(g_pszDSCommandName,
  819. pszObjectDN,
  820. hr,
  821. IDS_ERRMSG_CLASS_NOT_EQUAL);
  822. hr = E_INVALIDARG;
  823. fDisplayedMessage = true; // 662519-2002/07/11-JonN double-display
  824. break;
  825. }
  826. //
  827. //Get the attributes to fetch
  828. //
  829. LPWSTR *ppszAttributes = NULL;
  830. DWORD dwCountAttr = 0;
  831. hr = GetAttributesToFetch(pCommandArgs,
  832. pObjectEntry,
  833. &ppszAttributes,
  834. &dwCountAttr);
  835. if (FAILED(hr))
  836. {
  837. break;
  838. }
  839. DEBUG_OUTPUT(MINIMAL_LOGGING,
  840. L"Calling GetObjectAttributes for %d attributes.",
  841. dwCountAttr);
  842. DWORD dwAttrsReturned = 0;
  843. PADS_ATTR_INFO pAttrInfo = NULL;
  844. if(dwCountAttr > 0)
  845. {
  846. hr = spObject->GetObjectAttributes(ppszAttributes,
  847. dwCountAttr,
  848. &pAttrInfo,
  849. &dwAttrsReturned);
  850. if(FAILED(hr))
  851. {
  852. DEBUG_OUTPUT(MINIMAL_LOGGING,
  853. L"GetObjectAttributes failed: hr = 0x%x",
  854. hr);
  855. FreeAttributesToFetch(ppszAttributes,dwCountAttr);
  856. break;
  857. }
  858. DEBUG_OUTPUT(LEVEL5_LOGGING,
  859. L"GetObjectAttributes succeeded: dwAttrsReturned = %d",
  860. dwAttrsReturned);
  861. }
  862. //
  863. // NOTE: there may be other items to display that are not
  864. // part of the attributes fetched
  865. //
  866. /*
  867. if (dwAttrsReturned == 0 || !pAttrInfo)
  868. {
  869. break;
  870. }
  871. */
  872. //
  873. // Output the result of search
  874. //
  875. hr = DsGetOutputValuesList(pszObjectDN,
  876. basePathsInfo,
  877. credentialObject,
  878. pCommandArgs,
  879. pObjectEntry,
  880. dwAttrsReturned,
  881. pAttrInfo,
  882. spObject,
  883. formatInfo);
  884. } while (false);
  885. //
  886. // If there was a failure and the -c (continue) flag wasn't given
  887. // then stop processing names
  888. //
  889. if (FAILED(hr))
  890. {
  891. if (!fDisplayedMessage) // 662519-2002/07/11-JonN double-display
  892. {
  893. DisplayErrorMessage(g_pszDSCommandName, 0, hr);
  894. }
  895. if (!pCommandArgs[eCommContinue].bDefined)
  896. {
  897. break;
  898. }
  899. }
  900. // If we alloc'd a partition DN, then free it
  901. if(pszPartitionDN)
  902. {
  903. LocalFree(pszPartitionDN);
  904. pszPartitionDN = NULL;
  905. }
  906. } // Names for loop
  907. //
  908. // Now display the results
  909. //
  910. formatInfo.Display();
  911. } while (false);
  912. // If we alloc'd a partition DN, then free it
  913. if(pszPartitionDN)
  914. {
  915. LocalFree(pszPartitionDN);
  916. pszPartitionDN = NULL;
  917. }
  918. return hr;
  919. }
  920. //+--------------------------------------------------------------------------
  921. //
  922. // Function: GetAttributesToFetch
  923. //
  924. // Synopsis: Make an array of attributes to fetch.
  925. // Arguments: [ppszAttributes - OUT] : array of attributes to fetch
  926. // [pCount - OUT] : count of attributes in array
  927. //
  928. // Returns: HRESULT : S_OK if everything succeeded
  929. // E_INVALIDARG if the object entry wasn't found
  930. // Anything else is a failure code from an ADSI call
  931. //
  932. // History: 25-Sep-2000 hiteshr Created
  933. //
  934. //---------------------------------------------------------------------------
  935. HRESULT GetAttributesToFetch(IN PARG_RECORD pCommandArgs,
  936. IN PDSGetObjectTableEntry pObjectEntry,
  937. OUT LPWSTR **ppszAttributes,
  938. OUT DWORD * pCount)
  939. {
  940. ENTER_FUNCTION_HR(LEVEL8_LOGGING, GetAttributesToFetch, hr);
  941. do // false loop
  942. {
  943. if(!pCommandArgs ||
  944. !pObjectEntry)
  945. {
  946. ASSERT(pCommandArgs);
  947. ASSERT(pObjectEntry);
  948. hr = E_INVALIDARG;
  949. break;
  950. }
  951. LPWSTR *ppszAttr = (LPWSTR *)LocalAlloc(LPTR,pObjectEntry->dwAttributeCount *sizeof(LPCTSTR));
  952. if(!ppszAttr)
  953. {
  954. hr = E_OUTOFMEMORY;
  955. break;
  956. }
  957. //
  958. // Loop through the attributes that are needed and copy
  959. // them into the array.
  960. //
  961. // REVIEW_JEFFON : what if there are duplicates?
  962. //
  963. DEBUG_OUTPUT(FULL_LOGGING, L"Adding attributes to list:");
  964. DWORD dwAttrCount = 0;
  965. for(DWORD i = 0; i < pObjectEntry->dwAttributeCount; i++)
  966. {
  967. if (pObjectEntry->pAttributeTable[i])
  968. {
  969. UINT nCommandEntry = pObjectEntry->pAttributeTable[i]->nAttributeID;
  970. if (pCommandArgs[nCommandEntry].bDefined)
  971. {
  972. LPWSTR pszAttr = pObjectEntry->pAttributeTable[i]->pszName;
  973. if (pszAttr)
  974. {
  975. // 702724 ronmart 2002/09/18 If looking for top
  976. // object owner then specify a range
  977. if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszPartition)
  978. && pCommandArgs[ePartitionTopObjOwner].bDefined)
  979. {
  980. hr = SetRange(pszAttr, pCommandArgs[ePartitionTopObjOwner].nValue,
  981. ppszAttr+dwAttrCount);
  982. }
  983. else if(0 == lstrcmpi(pObjectEntry->pszCommandLineObjectType, g_pszServer)
  984. && pCommandArgs[eServerTopObjOwner].bDefined)
  985. {
  986. hr = SetRange(pszAttr, pCommandArgs[eServerTopObjOwner].nValue,
  987. ppszAttr+dwAttrCount);
  988. }
  989. // NTRAID#NTBUG9-765440-2003/01/17-ronmart-dsget user/group -qlimit -qused
  990. // not returning values
  991. // These do not appear on the user object so GetObjectAttributes
  992. // will fail if these are included in the fetch array
  993. else if(0 == lstrcmpi(pszAttr,g_pszAttrmsDSQuotaEffective) ||
  994. 0 == lstrcmpi(pszAttr,g_pszAttrmsDSQuotaUsed))
  995. {
  996. continue; // ignore
  997. }
  998. else
  999. {
  1000. hr = LocalCopyString(ppszAttr+dwAttrCount, pszAttr);
  1001. }
  1002. if (FAILED(hr))
  1003. {
  1004. LocalFree(ppszAttr);
  1005. hr = E_OUTOFMEMORY;
  1006. break;
  1007. }
  1008. // 702724 ronmart 2002/09/18 Use the array value that has
  1009. // be created (and possibly modified to include the range)
  1010. // rather than the attribute name when spewing attrs
  1011. DEBUG_OUTPUT(FULL_LOGGING, L"\t%s", *(ppszAttr+dwAttrCount));
  1012. dwAttrCount++;
  1013. }
  1014. }
  1015. }
  1016. }
  1017. if (SUCCEEDED(hr))
  1018. {
  1019. DEBUG_OUTPUT(FULL_LOGGING, L"Done adding %d attributes to list.", dwAttrCount);
  1020. }
  1021. *ppszAttributes = ppszAttr;
  1022. *pCount = dwAttrCount;
  1023. } while (false);
  1024. return hr;
  1025. }
  1026. //+--------------------------------------------------------------------------
  1027. //
  1028. // Function: FreeAttributesToFetch
  1029. //
  1030. // Synopsis: Function to free memory allocated by GetAttributesToFetch
  1031. // Arguments: [dwszAttributes - in] : array of attributes to fetch
  1032. // [dwCount - in] : count of attributes in array
  1033. //
  1034. // Returns: HRESULT : S_OK if everything succeeded
  1035. // E_INVALIDARG if the object entry wasn't found
  1036. // Anything else is a failure code from an ADSI call
  1037. //
  1038. // History: 25-Sep-2000 hiteshr Created
  1039. //
  1040. //---------------------------------------------------------------------------
  1041. VOID FreeAttributesToFetch( IN LPWSTR *ppszAttributes,
  1042. IN DWORD dwCount)
  1043. {
  1044. while(dwCount)
  1045. {
  1046. LocalFree(ppszAttributes[--dwCount]);
  1047. }
  1048. LocalFree(ppszAttributes);
  1049. }
  1050. //+--------------------------------------------------------------------------
  1051. //
  1052. // Function: SetRange
  1053. //
  1054. // Synopsis: Set's the range qualifier for an attribute
  1055. // Arguments: [pszAttrName - IN] : attribute name to append the range to
  1056. // [dwRangeUBound - IN]: one based upper bound of the range
  1057. // [pszAttrs - OUT] : attr array entry that should be allocated
  1058. //
  1059. // Returns: HRESULT : S_OK if everything succeeded
  1060. // E_INVALIDARG if the object entry wasn't found
  1061. // Anything else is a failure code from an ADSI call
  1062. //
  1063. // History: 18-Sep-2002 ronmart Created for 702724 fix
  1064. //
  1065. //---------------------------------------------------------------------------
  1066. HRESULT SetRange(IN LPCWSTR pszAttrName,
  1067. IN DWORD dwRangeUBound,
  1068. OUT LPWSTR* pszAttrs)
  1069. {
  1070. ENTER_FUNCTION_HR(MINIMAL_LOGGING, SetRange, hr);
  1071. do // false loop
  1072. {
  1073. // Validate params
  1074. if(!pszAttrName ||
  1075. !pszAttrs )
  1076. {
  1077. hr = E_INVALIDARG;
  1078. break;
  1079. }
  1080. // Get the size of the base attribute name
  1081. size_t cbSize = lstrlen(pszAttrName);
  1082. if(cbSize == 0)
  1083. break;
  1084. cbSize += 64; // leave room for null term, range string and int value
  1085. cbSize *= sizeof(WCHAR);
  1086. // Allocate the buffer to hold the range
  1087. *pszAttrs = (LPWSTR) LocalAlloc(LPTR, cbSize);
  1088. if(NULL == *pszAttrs)
  1089. {
  1090. hr = E_OUTOFMEMORY;
  1091. break;
  1092. }
  1093. // If zero then show all
  1094. if(dwRangeUBound == 0)
  1095. {
  1096. hr = StringCbPrintf(*pszAttrs, cbSize, L"%s%s=0-*", pszAttrName, g_pszRange);
  1097. }
  1098. // Otherwise show the value specified
  1099. else
  1100. {
  1101. hr = StringCbPrintf(*pszAttrs, cbSize, L"%s%s=0-%d",
  1102. pszAttrName, // Name of the attribute to append the range to
  1103. g_pszRange, // The range qualifer ;range
  1104. dwRangeUBound - 1); // Range is 0 based, and input is 1 based so adjust
  1105. }
  1106. if(FAILED(hr))
  1107. break;
  1108. } while(false);
  1109. return hr;
  1110. }