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.

1301 lines
31 KiB

  1. #include "headers.hxx"
  2. #pragma hdrstop
  3. #include <compobj.h>
  4. #include <initguid.h>
  5. //
  6. // Helpful debug macros
  7. //
  8. #define DBG_OUT_HRESULT(hr) printf("error 0x%x at line %u\n", hr, __LINE__)
  9. #define BREAK_ON_FAIL_HRESULT(hr) \
  10. if (FAILED(hr)) \
  11. { \
  12. DBG_OUT_HRESULT(hr); \
  13. break; \
  14. }
  15. //
  16. // Forward references
  17. //
  18. VOID
  19. DumpDsSelectedItemList(
  20. PDSSELECTIONLIST pDsSelList,
  21. ULONG cRequestedAttributes,
  22. LPCTSTR *aptzRequestedAttributes);
  23. VOID
  24. Usage();
  25. HRESULT
  26. AnsiToUnicode(
  27. LPWSTR pwszTo,
  28. LPCSTR szFrom,
  29. LONG cchTo);
  30. BOOL
  31. ParseFetchSwitch(
  32. char *pzFetchSwitch,
  33. PULONG pcRequestedAttributes,
  34. LPCTSTR **paptzRequestedAttributes);
  35. BOOL
  36. ParseGroupSwitch(
  37. char *pzGroupSwitch,
  38. ULONG *pulFlags);
  39. BOOL
  40. ParseUserSwitch(
  41. char *pzUserSwitch,
  42. ULONG *pulFlags);
  43. BOOL
  44. ParseInitialScope(
  45. char *pzScopeSwitch,
  46. ULONG *pulFlags);
  47. BOOL
  48. ParseScope(
  49. char *pzScopeSwitch,
  50. ULONG *pulFlags,
  51. PWSTR wzComputer,
  52. PWSTR wzDomain);
  53. BOOL
  54. ParseProviders(
  55. char *pzProviderSwitch,
  56. PULONG cAcceptableProviders,
  57. LPCWSTR **paptzAcceptableProviders);
  58. BOOL
  59. ParseRunCount(
  60. char *pzRunCountSwitch,
  61. PULONG pcRunCount);
  62. LPWSTR
  63. VariantString(
  64. VARIANT *pvar);
  65. void
  66. VarArrayToStr(
  67. VARIANT *pvar,
  68. LPWSTR wzBuf,
  69. ULONG cchbuf);
  70. //
  71. // Entry point
  72. //
  73. enum API_TO_CALL
  74. {
  75. NONE,
  76. COMPUTER,
  77. USER_GROUP
  78. };
  79. void _cdecl
  80. main(int argc, char * argv[])
  81. {
  82. HRESULT hr;
  83. BOOL fBadArg = FALSE;
  84. API_TO_CALL api = NONE;
  85. ULONG flObjectPicker = 0;
  86. ULONG flDsObjectPicker = 0;
  87. ULONG flUserGroupObjectPickerSpecifiedDomain = 0;
  88. ULONG flUserGroupObjectPickerOtherDomains = 0;
  89. ULONG *pflUserGroup = &flUserGroupObjectPickerOtherDomains;
  90. ULONG flComputerObjectPicker = 0;
  91. ULONG flInitialScope = 0;
  92. WCHAR wzComputer[MAX_PATH] = L"";
  93. WCHAR wzDomain[MAX_PATH] = L"";
  94. ULONG cAcceptableProviders = 0;
  95. LPCWSTR *aptzAcceptableProviders = NULL;
  96. ULONG cInvocations = 1;
  97. ULONG cRequestedAttributes = 0;
  98. LPCTSTR *aptzRequestedAttributes = NULL;
  99. for (int idxArg = 1; idxArg < argc && !fBadArg; idxArg++)
  100. {
  101. switch (argv[idxArg][1])
  102. {
  103. case 'c':
  104. case 'C':
  105. if (argv[idxArg][2] == ':' &&
  106. tolower(argv[idxArg][3]) == 'a')
  107. {
  108. if (api == USER_GROUP)
  109. {
  110. fBadArg = TRUE;
  111. printf("Can't specify /C:Api with user/group switches\n");
  112. }
  113. api = COMPUTER;
  114. }
  115. else
  116. {
  117. if (api == COMPUTER)
  118. {
  119. fBadArg = TRUE;
  120. printf("Can't specify both /C and /C:Api\n");
  121. }
  122. api = USER_GROUP;
  123. *pflUserGroup |= UGOP_COMPUTERS;
  124. }
  125. break;
  126. case 'd':
  127. case 'D':
  128. if (argv[idxArg][2] != ':')
  129. {
  130. printf("Expected ':' after /D\n");
  131. fBadArg = TRUE;
  132. break;
  133. }
  134. switch (argv[idxArg][3])
  135. {
  136. case 's':
  137. case 'S':
  138. pflUserGroup = &flUserGroupObjectPickerSpecifiedDomain;
  139. break;
  140. case 'o':
  141. case 'O':
  142. case '0': // allow a typo
  143. pflUserGroup = &flUserGroupObjectPickerOtherDomains;
  144. break;
  145. default:
  146. fBadArg = TRUE;
  147. printf("Expected S or O after /D:\n");
  148. break;
  149. }
  150. break;
  151. case 'f':
  152. case 'F':
  153. fBadArg = !ParseFetchSwitch(argv[idxArg], &cRequestedAttributes, &aptzRequestedAttributes);
  154. break;
  155. case 'g':
  156. case 'G':
  157. if (api != NONE && api != USER_GROUP)
  158. {
  159. fBadArg = TRUE;
  160. break;
  161. }
  162. api = USER_GROUP;
  163. fBadArg = !ParseGroupSwitch(argv[idxArg], pflUserGroup);
  164. break;
  165. case 'h':
  166. case 'H':
  167. if (api != NONE && api != USER_GROUP)
  168. {
  169. fBadArg = TRUE;
  170. break;
  171. }
  172. api = USER_GROUP;
  173. *pflUserGroup |= UGOP_INCLUDE_HIDDEN;
  174. break;
  175. case 'i':
  176. case 'I':
  177. fBadArg = !ParseInitialScope(argv[idxArg], &flInitialScope);
  178. break;
  179. case 'm':
  180. case 'M':
  181. flObjectPicker |= OP_MULTISELECT;
  182. break;
  183. case 'n':
  184. case 'N':
  185. flDsObjectPicker |= DSOP_RESTRICT_NAMES_TO_KNOWN_DOMAINS;
  186. break;
  187. case 'p':
  188. case 'P':
  189. fBadArg = !ParseProviders(argv[idxArg],
  190. &cAcceptableProviders,
  191. &aptzAcceptableProviders);
  192. break;
  193. case 'r':
  194. case 'R':
  195. fBadArg = !ParseRunCount(argv[idxArg], &cInvocations);
  196. break;
  197. case 's':
  198. case 'S':
  199. fBadArg = !ParseScope(argv[idxArg],
  200. &flDsObjectPicker,
  201. wzComputer,
  202. wzDomain);
  203. break;
  204. case 'u':
  205. case 'U':
  206. if (api == COMPUTER)
  207. {
  208. fBadArg = TRUE;
  209. break;
  210. }
  211. api = USER_GROUP;
  212. fBadArg = !ParseUserSwitch(argv[idxArg], pflUserGroup);
  213. break;
  214. case 'x':
  215. case 'X':
  216. flDsObjectPicker |= DSOP_CONVERT_EXTERNAL_PATHS_TO_SID;
  217. break;
  218. default:
  219. fBadArg = TRUE;
  220. break;
  221. }
  222. }
  223. if (fBadArg || api == NONE)
  224. {
  225. Usage();
  226. return;
  227. }
  228. hr = CoInitialize(NULL);
  229. if (FAILED(hr))
  230. {
  231. printf("CoInitializeEx - 0x%x\n", hr);
  232. return;
  233. }
  234. //
  235. // Call the API
  236. //
  237. PDSSELECTIONLIST pDsSelList = NULL;
  238. if (api == USER_GROUP)
  239. {
  240. GETUSERGROUPSELECTIONINFO ugsi;
  241. ZeroMemory(&ugsi, sizeof ugsi);
  242. ugsi.cbSize = sizeof(ugsi);
  243. ugsi.ptzComputerName = *wzComputer ? wzComputer : NULL;
  244. ugsi.ptzDomainName = *wzDomain ? wzDomain : NULL;
  245. ugsi.flObjectPicker = flObjectPicker;
  246. ugsi.flDsObjectPicker = flDsObjectPicker;
  247. ugsi.flStartingScope = flInitialScope;
  248. ugsi.flUserGroupObjectPickerSpecifiedDomain =
  249. flUserGroupObjectPickerSpecifiedDomain;
  250. ugsi.flUserGroupObjectPickerOtherDomains =
  251. flUserGroupObjectPickerOtherDomains;
  252. ugsi.ppDsSelList = &pDsSelList;
  253. ugsi.cAcceptableProviders = cAcceptableProviders;
  254. ugsi.aptzAcceptableProviders = aptzAcceptableProviders;
  255. ugsi.cRequestedAttributes = cRequestedAttributes;
  256. ugsi.aptzRequestedAttributes = aptzRequestedAttributes;
  257. for (ULONG i = 0; i < cInvocations; i++)
  258. {
  259. hr = GetUserGroupSelection(&ugsi);
  260. if (hr == S_FALSE)
  261. {
  262. printf("Invocation %u: User/Group picker dialog cancelled\n", i);
  263. }
  264. else if (SUCCEEDED(hr))
  265. {
  266. DumpDsSelectedItemList(pDsSelList,
  267. cRequestedAttributes,
  268. aptzRequestedAttributes);
  269. }
  270. else
  271. {
  272. printf("Invocation %u: User/Group picker dialog failed 0x%x\n", i, hr);
  273. }
  274. FreeDsSelectionList(pDsSelList);
  275. pDsSelList = NULL;
  276. }
  277. }
  278. else if (api == COMPUTER)
  279. {
  280. GETCOMPUTERSELECTIONINFO csi;
  281. ZeroMemory(&csi, sizeof csi);
  282. csi.cbSize = sizeof(csi);
  283. csi.ptzComputerName = *wzComputer ? wzComputer : NULL;
  284. csi.ptzDomainName = *wzDomain ? wzDomain : NULL;
  285. csi.flObjectPicker = flObjectPicker;
  286. csi.flDsObjectPicker = flDsObjectPicker;
  287. csi.flStartingScope = flInitialScope;
  288. csi.flComputerObjectPicker = flComputerObjectPicker;
  289. csi.ppDsSelList = &pDsSelList;
  290. csi.cAcceptableProviders = cAcceptableProviders;
  291. csi.aptzAcceptableProviders = aptzAcceptableProviders;
  292. csi.cRequestedAttributes = cRequestedAttributes;
  293. csi.aptzRequestedAttributes = aptzRequestedAttributes;
  294. for (ULONG i = 0; i < cInvocations; i++)
  295. {
  296. hr = GetComputerSelection(&csi);
  297. if (hr == S_FALSE)
  298. {
  299. printf("Invocation %u: Computer picker dialog cancelled\n", i);
  300. }
  301. else if (SUCCEEDED(hr))
  302. {
  303. DumpDsSelectedItemList(pDsSelList,
  304. cRequestedAttributes,
  305. aptzRequestedAttributes);
  306. }
  307. else
  308. {
  309. printf("Invocation %u: Computer picker dialog failed 0x%x\n", i, hr);
  310. }
  311. FreeDsSelectionList(pDsSelList);
  312. pDsSelList = NULL;
  313. }
  314. }
  315. else
  316. {
  317. printf("unexpected api setting\n");
  318. }
  319. CoUninitialize();
  320. }
  321. LPWSTR apwzAttr[100];
  322. BOOL
  323. ParseFetchSwitch(
  324. char *pzFetchSwitch,
  325. PULONG pcRequestedAttributes,
  326. LPCTSTR **paptzRequestedAttributes)
  327. {
  328. BOOL fOk = TRUE;
  329. pzFetchSwitch += 2; // advance past '/' (or '-') and 'G'
  330. if (*pzFetchSwitch != ':')
  331. {
  332. printf("expected : after /Fetch\n");
  333. return FALSE;
  334. }
  335. *pcRequestedAttributes = 0;
  336. *paptzRequestedAttributes = NULL;
  337. ULONG cRequestedAttributes = 0;
  338. for (pzFetchSwitch++; *pzFetchSwitch && fOk; pzFetchSwitch++)
  339. {
  340. if (*pzFetchSwitch == ',')
  341. {
  342. continue;
  343. }
  344. PSTR pzComma = strchr(pzFetchSwitch, ',');
  345. if (pzComma)
  346. {
  347. *pzComma = '\0';
  348. }
  349. ULONG cchFetchSwitch = strlen(pzFetchSwitch) + 1;
  350. // BUGBUG this is leaked. (who cares?)
  351. apwzAttr[cRequestedAttributes] = new WCHAR[cchFetchSwitch];
  352. if (!apwzAttr[cRequestedAttributes])
  353. {
  354. printf("out of memory\n");
  355. return FALSE;
  356. }
  357. AnsiToUnicode(apwzAttr[cRequestedAttributes],
  358. pzFetchSwitch,
  359. cchFetchSwitch);
  360. cRequestedAttributes++;
  361. if (pzComma)
  362. {
  363. *pzComma = ',';
  364. pzFetchSwitch = pzComma;
  365. }
  366. else
  367. {
  368. pzFetchSwitch += strlen(pzFetchSwitch) - 1;
  369. }
  370. }
  371. if (cRequestedAttributes && fOk)
  372. {
  373. *pcRequestedAttributes = cRequestedAttributes;
  374. *paptzRequestedAttributes = (LPCTSTR *)apwzAttr;
  375. }
  376. return fOk;
  377. }
  378. BOOL
  379. ParseGroupSwitch(
  380. char *pzGroupSwitch,
  381. ULONG *pulFlags)
  382. {
  383. BOOL fOk = TRUE;
  384. pzGroupSwitch += 2; // advance past '/' (or '-') and 'G'
  385. if (*pzGroupSwitch != ':')
  386. {
  387. printf("expected : after /Groups\n");
  388. return FALSE;
  389. }
  390. for (pzGroupSwitch++; *pzGroupSwitch && fOk; pzGroupSwitch++)
  391. {
  392. if (*pzGroupSwitch == ',')
  393. {
  394. continue;
  395. }
  396. PSTR pzComma = strchr(pzGroupSwitch, ',');
  397. if (pzComma)
  398. {
  399. *pzComma = '\0';
  400. }
  401. BOOL fMatch = FALSE;
  402. if (!lstrcmpiA(pzGroupSwitch, "all"))
  403. {
  404. fMatch = TRUE;
  405. *pulFlags |= UGOP_ALL_GROUPS;
  406. }
  407. if (pzComma)
  408. {
  409. *pzComma = ',';
  410. }
  411. if (fMatch)
  412. {
  413. if (pzComma)
  414. {
  415. pzGroupSwitch = pzComma;
  416. }
  417. else
  418. {
  419. pzGroupSwitch += strlen(pzGroupSwitch) - 1;
  420. }
  421. continue;
  422. }
  423. switch (tolower(*pzGroupSwitch))
  424. {
  425. case 'u':
  426. if (tolower(pzGroupSwitch[1]) == 's')
  427. {
  428. *pulFlags |= UGOP_UNIVERSAL_GROUPS_SE;
  429. pzGroupSwitch++;
  430. }
  431. else
  432. {
  433. *pulFlags |= UGOP_UNIVERSAL_GROUPS;
  434. }
  435. break;
  436. case 'a':
  437. if (tolower(pzGroupSwitch[1]) == 's')
  438. {
  439. *pulFlags |= UGOP_ACCOUNT_GROUPS_SE;
  440. pzGroupSwitch++;
  441. }
  442. else
  443. {
  444. *pulFlags |= UGOP_ACCOUNT_GROUPS;
  445. }
  446. break;
  447. case 'r':
  448. if (tolower(pzGroupSwitch[1]) == 's')
  449. {
  450. *pulFlags |= UGOP_RESOURCE_GROUPS_SE;
  451. pzGroupSwitch++;
  452. }
  453. else
  454. {
  455. *pulFlags |= UGOP_RESOURCE_GROUPS;
  456. }
  457. break;
  458. case 'l':
  459. *pulFlags |= UGOP_LOCAL_GROUPS;
  460. break;
  461. case 'g':
  462. *pulFlags |= UGOP_GLOBAL_GROUPS;
  463. break;
  464. case 'b':
  465. *pulFlags |= UGOP_BUILTIN_GROUPS;
  466. break;
  467. case 'w':
  468. *pulFlags |= UGOP_WELL_KNOWN_PRINCIPALS_USERS;
  469. break;
  470. default:
  471. fOk = FALSE;
  472. printf("unexpected character '%c' in group type switch\n",
  473. *pzGroupSwitch);
  474. break;
  475. }
  476. }
  477. printf("flags = 0x%x\n", *pulFlags);
  478. return fOk;
  479. }
  480. BOOL
  481. ParseUserSwitch(
  482. char *pzUserSwitch,
  483. ULONG *pulFlags)
  484. {
  485. BOOL fOk = TRUE;
  486. pzUserSwitch += 2; // advance past '/' (or '-') and 'U'
  487. if (*pzUserSwitch != ':')
  488. {
  489. printf("expected : after /Users\n");
  490. return FALSE;
  491. }
  492. for (pzUserSwitch++; *pzUserSwitch && fOk; pzUserSwitch++)
  493. {
  494. if (*pzUserSwitch == ',')
  495. {
  496. continue;
  497. }
  498. PSTR pzComma = strchr(pzUserSwitch, ',');
  499. if (pzComma)
  500. {
  501. *pzComma = '\0';
  502. }
  503. BOOL fMatch = FALSE;
  504. if (!lstrcmpiA(pzUserSwitch, "all"))
  505. {
  506. fMatch = TRUE;
  507. *pulFlags |= UGOP_ALL_USERS;
  508. }
  509. else if (!lstrcmpiA(pzUserSwitch, "world"))
  510. {
  511. fMatch = TRUE;
  512. *pulFlags |= UGOP_USER_WORLD;
  513. }
  514. else if (!lstrcmpiA(pzUserSwitch, "authenticated"))
  515. {
  516. fMatch = TRUE;
  517. *pulFlags |= UGOP_USER_AUTHENTICATED_USER;
  518. }
  519. else if (!lstrcmpiA(pzUserSwitch, "anonymous"))
  520. {
  521. fMatch = TRUE;
  522. *pulFlags |= UGOP_USER_ANONYMOUS;
  523. }
  524. else if (!lstrcmpiA(pzUserSwitch, "dialup"))
  525. {
  526. fMatch = TRUE;
  527. *pulFlags |= UGOP_USER_DIALUP;
  528. }
  529. else if (!lstrcmpiA(pzUserSwitch, "network"))
  530. {
  531. fMatch = TRUE;
  532. *pulFlags |= UGOP_USER_NETWORK;
  533. }
  534. else if (!lstrcmpiA(pzUserSwitch, "Batch"))
  535. {
  536. fMatch = TRUE;
  537. *pulFlags |= UGOP_USER_BATCH;
  538. }
  539. else if (!lstrcmpiA(pzUserSwitch, "Interactive"))
  540. {
  541. fMatch = TRUE;
  542. *pulFlags |= UGOP_USER_INTERACTIVE;
  543. }
  544. else if (!lstrcmpiA(pzUserSwitch, "Service"))
  545. {
  546. fMatch = TRUE;
  547. *pulFlags |= UGOP_USER_SERVICE;
  548. }
  549. else if (!lstrcmpiA(pzUserSwitch, "System"))
  550. {
  551. fMatch = TRUE;
  552. *pulFlags |= UGOP_USER_SYSTEM;
  553. }
  554. if (pzComma)
  555. {
  556. *pzComma = ',';
  557. }
  558. if (fMatch)
  559. {
  560. if (pzComma)
  561. {
  562. pzUserSwitch = pzComma;
  563. }
  564. else
  565. {
  566. pzUserSwitch += strlen(pzUserSwitch) - 1;
  567. }
  568. continue;
  569. }
  570. switch (tolower(*pzUserSwitch))
  571. {
  572. case 'u':
  573. *pulFlags |= UGOP_USERS;
  574. break;
  575. case 'c':
  576. *pulFlags |= UGOP_CONTACTS;
  577. break;
  578. default:
  579. fOk = FALSE;
  580. printf("unexpected character '%c' in user type switch\n",
  581. *pzUserSwitch);
  582. break;
  583. }
  584. if (pzComma)
  585. {
  586. pzUserSwitch = pzComma;
  587. }
  588. }
  589. return fOk;
  590. }
  591. BOOL
  592. ParseInitialScope(
  593. char *pzScopeSwitch,
  594. ULONG *pulFlags)
  595. {
  596. PSTR pzCur = strchr(pzScopeSwitch, ':');
  597. if (!pzCur)
  598. {
  599. printf("expected : after /InitialScope switch\n");
  600. return FALSE;
  601. }
  602. // advance past colon
  603. pzCur++;
  604. switch (tolower(*pzCur))
  605. {
  606. case 'c':
  607. *pulFlags |= DSOP_SCOPE_SPECIFIED_MACHINE;
  608. break;
  609. case 'd':
  610. *pulFlags |= DSOP_SCOPE_SPECIFIED_DOMAIN;
  611. break;
  612. case 'g':
  613. *pulFlags |= DSOP_SCOPE_DIRECTORY;
  614. break;
  615. case 't':
  616. *pulFlags |= DSOP_SCOPE_DOMAIN_TREE;
  617. break;
  618. case 'x':
  619. *pulFlags |= DSOP_SCOPE_EXTERNAL_TRUSTED_DOMAINS;
  620. break;
  621. default:
  622. printf("invalid /InitialScope switch\n");
  623. return FALSE;
  624. }
  625. return TRUE;
  626. }
  627. BOOL
  628. ParseProviders(
  629. char *pzProviderSwitch,
  630. PULONG pcAcceptableProviders,
  631. LPCWSTR **paptzAcceptableProviders)
  632. {
  633. BOOL fOk = TRUE;
  634. PSTR pzCur = strchr(pzProviderSwitch, ':');
  635. static LPCWSTR apwzProviders[3];
  636. *paptzAcceptableProviders = apwzProviders;
  637. if (!pzCur)
  638. {
  639. printf("expected : after /Providers switch\n");
  640. return FALSE;
  641. }
  642. ZeroMemory(apwzProviders, sizeof apwzProviders);
  643. // advance past colon
  644. pzCur++;
  645. while (*pzCur)
  646. {
  647. switch (tolower(*pzCur))
  648. {
  649. case 'w':
  650. apwzProviders[(*pcAcceptableProviders)++] = L"WinNT";
  651. break;
  652. case 'l':
  653. apwzProviders[(*pcAcceptableProviders)++] = L"LDAP";
  654. break;
  655. case 'g':
  656. apwzProviders[(*pcAcceptableProviders)++] = L"GC";
  657. break;
  658. default:
  659. printf("invalid provider switch\n");
  660. return FALSE;
  661. }
  662. for (; *pzCur && *pzCur != ','; pzCur++)
  663. {
  664. }
  665. if (*pzCur == ',')
  666. {
  667. pzCur++;
  668. }
  669. // ignore extras
  670. if (*pcAcceptableProviders == 3)
  671. {
  672. break;
  673. }
  674. }
  675. return fOk;
  676. }
  677. BOOL
  678. ParseRunCount(
  679. char *pzRunCountSwitch,
  680. PULONG pcRunCount)
  681. {
  682. PSTR pzCur = strchr(pzRunCountSwitch, ':');
  683. if (!pzCur)
  684. {
  685. printf("expected : after /Runcount switch\n");
  686. return FALSE;
  687. }
  688. *pcRunCount = (ULONG) atol(pzCur + 1);
  689. if (!*pcRunCount || *pcRunCount > 10)
  690. {
  691. printf("Invalid run count %u\n", *pcRunCount);
  692. }
  693. return TRUE;
  694. }
  695. BOOL
  696. ParseScope(
  697. char *pzScopeSwitch,
  698. ULONG *pulFlags,
  699. PWSTR wzComputer,
  700. PWSTR wzDomain)
  701. {
  702. PSTR pzCur = strchr(pzScopeSwitch, ':');
  703. if (!pzCur)
  704. {
  705. printf("expected : after /Scope switch\n");
  706. return FALSE;
  707. }
  708. // advance past colon
  709. pzCur++;
  710. while (*pzCur)
  711. {
  712. switch (tolower(*pzCur))
  713. {
  714. case 'c':
  715. {
  716. *pulFlags |= DSOP_SCOPE_SPECIFIED_MACHINE;
  717. // find '='
  718. for (PSTR pzEqual = pzCur;
  719. *pzEqual && *pzEqual != ',' && *pzEqual != '=';
  720. pzEqual++)
  721. {
  722. }
  723. if (*pzEqual == '=')
  724. {
  725. CHAR szTemp[MAX_PATH];
  726. strcpy(szTemp, pzEqual + 1);
  727. LPSTR pzComma = strchr(szTemp, ',');
  728. if (pzComma)
  729. {
  730. *pzComma = '\0';
  731. }
  732. AnsiToUnicode(wzComputer, szTemp, MAX_PATH);
  733. pzCur = pzEqual + 1;
  734. }
  735. break;
  736. }
  737. case 'd':
  738. {
  739. *pulFlags |= DSOP_SCOPE_SPECIFIED_DOMAIN;
  740. for (PSTR pzEqual = pzCur;
  741. *pzEqual && *pzEqual != ',' && *pzEqual != '=';
  742. pzEqual++)
  743. {
  744. }
  745. if (*pzEqual == '=')
  746. {
  747. CHAR szTemp[MAX_PATH];
  748. LPSTR pzOpenQuote = strchr(pzEqual, '\'');
  749. if (!pzOpenQuote)
  750. {
  751. printf("Expected single quote after = in domain spec\n");
  752. return FALSE;
  753. }
  754. LPSTR pzCloseQuote = strchr(pzOpenQuote + 1, '\'');
  755. if (!pzCloseQuote)
  756. {
  757. printf("Expected closing single quote after = in domain spec\n");
  758. return FALSE;
  759. }
  760. CopyMemory(szTemp, pzOpenQuote + 1, pzCloseQuote - pzOpenQuote - 1);
  761. szTemp[pzCloseQuote - pzOpenQuote - 1] = '\0';
  762. AnsiToUnicode(wzDomain, szTemp, MAX_PATH);
  763. pzCur = pzCloseQuote + 1;
  764. }
  765. break;
  766. }
  767. case 'g':
  768. *pulFlags |= DSOP_SCOPE_DIRECTORY;
  769. break;
  770. case 't':
  771. *pulFlags |= DSOP_SCOPE_DOMAIN_TREE;
  772. break;
  773. case 'x':
  774. *pulFlags |= DSOP_SCOPE_EXTERNAL_TRUSTED_DOMAINS;
  775. break;
  776. default:
  777. printf("invalid scope switch\n");
  778. return FALSE;
  779. }
  780. for (; *pzCur && *pzCur != ','; pzCur++)
  781. {
  782. }
  783. if (*pzCur == ',')
  784. {
  785. pzCur++;
  786. }
  787. }
  788. return TRUE;
  789. }
  790. //+--------------------------------------------------------------------------
  791. //
  792. // Function: DumpDsSelectedItemList
  793. //
  794. // Synopsis: Dump the contents of the list of DS items the user selected
  795. // to the console.
  796. //
  797. // Arguments: [pDsSelList] - list of Ds items
  798. //
  799. // History: 11-04-1997 DavidMun Created
  800. //
  801. //---------------------------------------------------------------------------
  802. VOID
  803. DumpDsSelectedItemList(
  804. PDSSELECTIONLIST pDsSelList,
  805. ULONG cRequestedAttributes,
  806. LPCTSTR *aptzRequestedAttributes)
  807. {
  808. if (!pDsSelList)
  809. {
  810. printf("List is empty\n");
  811. return;
  812. }
  813. ULONG i;
  814. PDSSELECTION pCur = &pDsSelList->aDsSelection[0];
  815. for (i = 0; i < pDsSelList->cItems; i++, pCur++)
  816. {
  817. printf("Name: %ws\n", pCur->pwzName);
  818. printf("Class: %ws\n", pCur->pwzClass);
  819. printf("Path: %ws\n", pCur->pwzADsPath);
  820. printf("UPN: %ws\n", pCur->pwzUPN);
  821. for (ULONG j = 0; j < cRequestedAttributes; j++)
  822. {
  823. printf("Attr %02u: %ws = %ws\n",
  824. j,
  825. aptzRequestedAttributes[j],
  826. VariantString(&pCur->pvarOtherAttributes[j]));
  827. }
  828. printf("\n");
  829. }
  830. }
  831. LPWSTR
  832. VariantString(
  833. VARIANT *pvar)
  834. {
  835. static WCHAR wzBuf[1024];
  836. wzBuf[0] = L'\0';
  837. switch (pvar->vt)
  838. {
  839. case VT_EMPTY:
  840. lstrcpy(wzBuf, L"VT_EMPTY");
  841. break;
  842. case VT_NULL:
  843. lstrcpy(wzBuf, L"VT_NULL");
  844. break;
  845. case VT_I2:
  846. wsprintf(wzBuf, L"%d", V_I2(pvar));
  847. break;
  848. case VT_I4:
  849. wsprintf(wzBuf, L"%d", V_I4(pvar));
  850. break;
  851. case VT_R4:
  852. wsprintf(wzBuf, L"%f", V_R4(pvar));
  853. break;
  854. case VT_R8:
  855. wsprintf(wzBuf, L"%f", V_R8(pvar));
  856. break;
  857. case VT_CY:
  858. wsprintf(wzBuf, L"$%f", V_CY(pvar));
  859. break;
  860. case VT_DATE:
  861. wsprintf(wzBuf, L"date %f", V_DATE(pvar));
  862. break;
  863. case VT_BSTR:
  864. if (V_BSTR(pvar))
  865. {
  866. wsprintf(wzBuf, L"'%ws'", V_BSTR(pvar));
  867. }
  868. else
  869. {
  870. lstrcpy(wzBuf, L"VT_BSTR NULL");
  871. }
  872. break;
  873. case VT_DISPATCH:
  874. wsprintf(wzBuf, L"VT_DISPATCH 0x%x", V_DISPATCH(pvar));
  875. break;
  876. case VT_UNKNOWN:
  877. wsprintf(wzBuf, L"VT_UNKNOWN 0x%x", V_UNKNOWN(pvar));
  878. break;
  879. case VT_ERROR:
  880. case VT_HRESULT:
  881. wsprintf(wzBuf, L"hr 0x%x", V_ERROR(pvar));
  882. break;
  883. case VT_BOOL:
  884. wsprintf(wzBuf, L"%s", V_BOOL(pvar) ? "TRUE" : "FALSE");
  885. break;
  886. case VT_VARIANT:
  887. wsprintf(wzBuf, L"variant 0x%x", V_VARIANTREF(pvar));
  888. break;
  889. case VT_DECIMAL:
  890. lstrcpy(wzBuf, L"VT_DECIMAL");
  891. break;
  892. case VT_I1:
  893. wsprintf(wzBuf, L"%d", V_I1(pvar));
  894. break;
  895. case VT_UI1:
  896. wsprintf(wzBuf, L"%u", V_UI1(pvar));
  897. break;
  898. case VT_UI2:
  899. wsprintf(wzBuf, L"%u", V_UI2(pvar));
  900. break;
  901. case VT_UI4:
  902. wsprintf(wzBuf, L"%u", V_UI4(pvar));
  903. break;
  904. case VT_I8:
  905. lstrcpy(wzBuf, L"VT_I8");
  906. break;
  907. case VT_UI8:
  908. lstrcpy(wzBuf, L"VT_UI8");
  909. break;
  910. case VT_INT:
  911. wsprintf(wzBuf, L"%d", V_INT(pvar));
  912. break;
  913. case VT_UINT:
  914. wsprintf(wzBuf, L"%u", V_UINT(pvar));
  915. break;
  916. case VT_VOID:
  917. lstrcpy(wzBuf, L"VT_VOID");
  918. break;
  919. case VT_UI1 | VT_ARRAY:
  920. VarArrayToStr(pvar, wzBuf, ARRAYLEN(wzBuf));
  921. break;
  922. case VT_PTR:
  923. case VT_SAFEARRAY:
  924. case VT_CARRAY:
  925. case VT_USERDEFINED:
  926. case VT_LPSTR:
  927. case VT_LPWSTR:
  928. case VT_RECORD:
  929. case VT_FILETIME:
  930. case VT_BLOB:
  931. case VT_STREAM:
  932. case VT_STORAGE:
  933. case VT_STREAMED_OBJECT:
  934. case VT_STORED_OBJECT:
  935. case VT_BLOB_OBJECT:
  936. case VT_CF:
  937. case VT_CLSID:
  938. case VT_BSTR_BLOB:
  939. default:
  940. wsprintf(wzBuf, L"VT 0x%x", V_VT(pvar));
  941. break;
  942. }
  943. return wzBuf;
  944. }
  945. void
  946. VarArrayToStr(
  947. VARIANT *pvar,
  948. LPWSTR wzBuf,
  949. ULONG cchBuf)
  950. {
  951. ULONG i;
  952. LPWSTR pwzNext = wzBuf;
  953. LPWSTR pwzEnd = wzBuf + cchBuf;
  954. for (i = 0; i < pvar->parray->rgsabound[0].cElements && pwzNext < pwzEnd + 6; i++)
  955. {
  956. wsprintf(pwzNext, L"x%02x ", ((LPBYTE)(pvar->parray->pvData))[i]);
  957. pwzNext += lstrlen(pwzNext);
  958. }
  959. }
  960. VOID
  961. Usage()
  962. {
  963. printf("\n");
  964. printf("Usage: opt <switches>\n");
  965. printf("\n");
  966. printf("Switches are:\n");
  967. printf(" /Computers[:Api]\n");
  968. printf(" If API is specified, GetComputerSelection is called, otherwise\n");
  969. printf(" this means include computer objects in the query\n");
  970. printf(" /Domain:{S|O}\n");
  971. printf(" If S is specified, then any following /Users, /Groups, or\n");
  972. printf(" /Computers switches apply only to the specified domain scope.\n");
  973. printf(" Otherwise, those switches apply to all other scopes\n");
  974. printf(" /Fetch:<attr>[,<attr>]...\n");
  975. printf(" <attr> is the name of an attribute to retrieve\n");
  976. printf(" /Groups:<group-type>[,<group-type>]...\n");
  977. printf(" <group-type> is one of:\n");
  978. printf(" ALL - same as specifiying each of the following\n");
  979. printf(" U - Universal\n");
  980. printf(" A - Account\n");
  981. printf(" R - Resource\n");
  982. printf(" US - Universal Security Enabled\n");
  983. printf(" AS - Account Security Enabled\n");
  984. printf(" RS - Resource Security Enabled\n");
  985. printf(" L - Local\n");
  986. printf(" G - Global\n");
  987. printf(" B - Builtin\n");
  988. printf(" W - Well-Known Security Principals\n");
  989. printf(" /Hidden\n");
  990. printf(" Include objects hidden from address book.\n");
  991. printf(" /Initialscope:{Computer|Domain|Gc|Tree|Xternal}\n");
  992. printf(" /Multiselect\n");
  993. printf(" /Namerestrict - reject names in unknown domains\n");
  994. printf(" /Providers:<provider>[,<provider>]\n");
  995. printf(" <provider> is one of:\n");
  996. printf(" WINNT\n");
  997. printf(" LDAP\n");
  998. printf(" GC\n");
  999. printf(" /Runcount:<n>\n");
  1000. printf(" <n> is number of times to invoke object picker\n");
  1001. printf(" /Scopes:<scope-spec>[,<scope-spec>]...\n");
  1002. printf(" <scope-spec> is one of:\n");
  1003. printf(" Computer[=name]\n");
  1004. printf(" Domain[='<domain-spec>']\n");
  1005. printf(" Gc\n");
  1006. printf(" Tree\n");
  1007. printf(" Xternal\n");
  1008. printf(" <domain-spec> is one of:\n");
  1009. printf(" <path> - the ADs path of a DS namespace\n");
  1010. printf(" <name> - the flat name of a downlevel domain\n");
  1011. printf(" /Users:<user-type>[,<user-type>]...\n");
  1012. printf(" <user-type> is one of:\n");
  1013. printf(" ALL - same as specifying each of the following\n");
  1014. printf(" U - User\n");
  1015. printf(" C - Contact\n");
  1016. printf(" WORLD\n");
  1017. printf(" AUTHENTICATED\n");
  1018. printf(" ANONYMOUS\n");
  1019. printf(" DIALUP\n");
  1020. printf(" NETWORK\n");
  1021. printf(" BATCH\n");
  1022. printf(" INTERACTIVE\n");
  1023. printf(" SERVICE\n");
  1024. printf(" SYSTEM\n");
  1025. printf(" /Xternal - force conversion of external paths to SIDs\n");
  1026. printf("\n");
  1027. printf("You must specify the Scope switch and at least one of the Computers,\n");
  1028. printf("Groups, or Users switches.\n");
  1029. printf("The significant characters in the switches are shown in upper case.\n");
  1030. }
  1031. //+---------------------------------------------------------------------------
  1032. //
  1033. // Function: AnsiToUnicode
  1034. //
  1035. // Synopsis: Convert ANSI string [szFrom] to Unicode string in buffer
  1036. // [pwszTo].
  1037. //
  1038. // Arguments: [pwszTo] - destination buffer
  1039. // [szFrom] - source string
  1040. // [cchTo] - size of destination buffer, in WCHARS
  1041. //
  1042. // Returns: S_OK - conversion succeeded
  1043. // HRESULT_FROM_WIN32 - MultiByteToWideChar failed
  1044. //
  1045. // Modifies: *[pwszTo]
  1046. //
  1047. // History: 10-29-96 DavidMun Created
  1048. //
  1049. // Notes: The string in [pwszTo] will be NULL terminated even on
  1050. // failure.
  1051. //
  1052. //----------------------------------------------------------------------------
  1053. HRESULT
  1054. AnsiToUnicode(
  1055. LPWSTR pwszTo,
  1056. LPCSTR szFrom,
  1057. LONG cchTo)
  1058. {
  1059. HRESULT hr = S_OK;
  1060. ULONG cchWritten;
  1061. cchWritten = MultiByteToWideChar(CP_ACP, 0, szFrom, -1, pwszTo, cchTo);
  1062. if (!cchWritten)
  1063. {
  1064. pwszTo[cchTo - 1] = L'\0'; // ensure NULL termination
  1065. hr = HRESULT_FROM_WIN32(GetLastError());
  1066. printf("AnsiToUnicode: MultiByteToWideChar hr=0x%x\n", hr);
  1067. }
  1068. return hr;
  1069. }