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.

649 lines
19 KiB

  1. //--------------------------------------------------------------------------
  2. #ifndef _WIN32_WINNT
  3. #define _WIN32_WINNT 0x0510
  4. #endif
  5. #ifndef WIN32_LEAN_AND_MEAN
  6. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
  7. #endif
  8. #define SECURITY_WIN32
  9. #include <windows.h>
  10. #include <tchar.h>
  11. #include <assert.h>
  12. #include <objbase.h>
  13. #include <objsel.h>
  14. #include <Security.h>
  15. #include <Secext.h>
  16. #include "objectpicker.h"
  17. #define OP_GENERIC_EXCEPTION ( ( DWORD ) 1 )
  18. //--------------------------------------------------------------------------
  19. extern HINSTANCE g_hInstance;
  20. UINT g_cfDsObjectPicker = RegisterClipboardFormat( CFSTR_DSOP_DS_SELECTION_LIST );
  21. static HRESULT InitObjectPicker( UINT uObjectType, IDsObjectPicker *pDsObjectPicker );
  22. static HRESULT InitObjectPickerForComputers( IDsObjectPicker *pDsObjectPicker );
  23. static HRESULT InitObjectPickerForGroups( IDsObjectPicker *pDsObjectPicker,
  24. BOOL fMultiselect,
  25. BOOL fWantSidPath );
  26. static HRESULT InitObjectPickerForUsers( IDsObjectPicker *pDsObjectPicker,
  27. BOOL fMultiselect );
  28. static bool ProcessSelectedObjects( IDataObject *pdo, PTCHAR szObjectName, ULONG uBufSize );
  29. //--------------------------------------------------------------------------
  30. // returns true if no errors, false otherwise
  31. // use GetLastError() to get error code
  32. //
  33. bool ObjectPicker( HWND hwndParent, UINT uObjectType, PTCHAR szObjectName, ULONG uBufSize )
  34. {
  35. IDsObjectPicker *pDsObjectPicker = NULL;
  36. IDataObject *pdo = NULL;
  37. bool bRet = true; // assume no errors
  38. try
  39. {
  40. HRESULT hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  41. if( FAILED( hr ) )
  42. throw HRESULT_CODE( hr );
  43. //
  44. // Create an instance of the object picker.
  45. //
  46. hr = CoCreateInstance(
  47. CLSID_DsObjectPicker,
  48. NULL,
  49. CLSCTX_INPROC_SERVER,
  50. IID_IDsObjectPicker,
  51. ( void ** ) &pDsObjectPicker );
  52. if( FAILED( hr ) )
  53. throw HRESULT_CODE( hr );
  54. //
  55. // Initialize the object picker instance.
  56. //
  57. hr = InitObjectPicker( uObjectType, pDsObjectPicker );
  58. if( FAILED( hr ) )
  59. throw HRESULT_CODE( hr );
  60. //
  61. // Invoke the modal dialog.
  62. //
  63. hr = pDsObjectPicker->InvokeDialog( hwndParent, &pdo );
  64. if( S_OK == hr )
  65. {
  66. if( !ProcessSelectedObjects( pdo, szObjectName, uBufSize ))
  67. throw GetLastError();
  68. }
  69. else if( S_FALSE == hr ) // user pressed cancel
  70. {
  71. throw OP_GENERIC_EXCEPTION;
  72. }
  73. else
  74. {
  75. throw HRESULT_CODE( hr );
  76. }
  77. }
  78. catch( HRESULT hrErr )
  79. {
  80. SetLastError( hrErr );
  81. bRet = false;
  82. }
  83. catch( DWORD dwErr )
  84. {
  85. SetLastError( dwErr );
  86. bRet = false;
  87. }
  88. if( pdo )
  89. pdo->Release();
  90. if( pDsObjectPicker )
  91. pDsObjectPicker->Release();
  92. CoUninitialize();
  93. return bRet;
  94. }
  95. //--------------------------------------------------------------------------
  96. static HRESULT InitObjectPicker( UINT uObjectType, IDsObjectPicker *pDsObjectPicker )
  97. {
  98. if( NULL == pDsObjectPicker )
  99. {
  100. return E_INVALIDARG;
  101. }
  102. HRESULT hr = E_FAIL;
  103. if( OP_COMPUTER == uObjectType )
  104. {
  105. hr = InitObjectPickerForComputers( pDsObjectPicker );
  106. }
  107. else if( OP_USER == uObjectType )
  108. {
  109. hr = InitObjectPickerForUsers( pDsObjectPicker, FALSE );
  110. }
  111. else if( OP_GROUP == uObjectType )
  112. {
  113. hr = InitObjectPickerForGroups( pDsObjectPicker, FALSE, TRUE );
  114. }
  115. return hr;
  116. }
  117. //--------------------------------------------------------------------------
  118. static bool ProcessSelectedObjects( IDataObject *pdo, PTCHAR szObjectName, ULONG uBufSize )
  119. {
  120. PDS_SELECTION_LIST pDsSelList = NULL;
  121. bool dwRet = true; // assume ok
  122. STGMEDIUM stgmedium =
  123. {
  124. TYMED_HGLOBAL,
  125. NULL,
  126. NULL
  127. };
  128. FORMATETC formatetc =
  129. {
  130. ( CLIPFORMAT ) g_cfDsObjectPicker,
  131. NULL,
  132. DVASPECT_CONTENT,
  133. -1,
  134. TYMED_HGLOBAL
  135. };
  136. try
  137. {
  138. //
  139. // Get the global memory block containing a user's selections.
  140. //
  141. HRESULT hr = pdo->GetData( &formatetc, &stgmedium );
  142. if( FAILED( hr ) )
  143. throw HRESULT_CODE( hr );
  144. //
  145. // Retrieve pointer to DS_SELECTION_LIST structure.
  146. //
  147. pDsSelList = ( PDS_SELECTION_LIST ) GlobalLock( stgmedium.hGlobal );
  148. if( !pDsSelList )
  149. {
  150. throw GetLastError();
  151. }
  152. //
  153. // assume there is only 1 item returned because
  154. // we have multi-select turned off
  155. //
  156. if( pDsSelList->cItems != 1 )
  157. {
  158. assert( false );
  159. throw OP_GENERIC_EXCEPTION;
  160. }
  161. UINT i = 0;
  162. //_tprintf( TEXT( "Object '%u'\n" ), i );
  163. //_tprintf( TEXT( " Name '%ws'\n" ), pDsSelList->aDsSelection[i].pwzName );
  164. //_tprintf( TEXT( " Class '%ws'\n" ), pDsSelList->aDsSelection[i].pwzClass );
  165. //_tprintf( TEXT( " Path '%ws'\n" ), pDsSelList->aDsSelection[i].pwzADsPath );
  166. //_tprintf( TEXT( " UPN '%ws'\n" ), pDsSelList->aDsSelection[i].pwzUPN );
  167. //
  168. // did we request a computer name? If so, we get it directly in the pwzName field
  169. //
  170. if( 0 == _tcsicmp( pDsSelList->aDsSelection[i].pwzClass, TEXT( "computer" )) )
  171. {
  172. assert( uBufSize > _tcslen( pDsSelList->aDsSelection[i].pwzName ) );
  173. _tcsncpy( szObjectName, pDsSelList->aDsSelection[i].pwzName, uBufSize - 1 );
  174. szObjectName[ uBufSize - 1 ] = NULL;
  175. }
  176. //
  177. // user name or group takes some post-processsing...
  178. //
  179. else if( 0 == _tcsicmp( pDsSelList->aDsSelection[i].pwzClass, TEXT( "user" ) ) ||
  180. 0 == _tcsicmp( pDsSelList->aDsSelection[i].pwzClass, TEXT( "group" ) ) )
  181. {
  182. //
  183. // user names from the domain begin with "LDAP:"
  184. // strip off the prefix info, up to the first "cn="
  185. // then use the TranslateName API to get the form "domain\user" or "domain\group"
  186. //
  187. if( 0 == _tcsnicmp( pDsSelList->aDsSelection[i].pwzADsPath, TEXT( "LDAP:" ), 5 ) )
  188. {
  189. PTCHAR p = _tcsstr( pDsSelList->aDsSelection[i].pwzADsPath, TEXT( "CN=" ) );
  190. if( NULL == p )
  191. p = _tcsstr( pDsSelList->aDsSelection[i].pwzADsPath, TEXT( "cn=" ) );
  192. if( NULL == p )
  193. {
  194. assert( false );
  195. throw OP_GENERIC_EXCEPTION;
  196. }
  197. if( !TranslateName( p, NameFullyQualifiedDN, NameSamCompatible, szObjectName, &uBufSize ) )
  198. throw GetLastError();
  199. }
  200. //
  201. // otherwise, names on the local box begin with "winnt:"
  202. // and we are only interested in the last two sections of the string,
  203. // delimited by "/"
  204. //
  205. else if( 0 == _tcsnicmp( pDsSelList->aDsSelection[i].pwzADsPath, TEXT( "WINNT:" ), 6 ) )
  206. {
  207. PTCHAR p = pDsSelList->aDsSelection[i].pwzADsPath;
  208. PTCHAR pend = p + _tcslen( p );
  209. UINT uCount = 0;
  210. while( pend > p )
  211. {
  212. if( '/' == *pend )
  213. {
  214. *pend = '\\';
  215. uCount++;
  216. if( uCount == 2 )
  217. {
  218. p = pend + 1;
  219. break;
  220. }
  221. }
  222. pend--;
  223. }
  224. //
  225. // if this fails, assert during debug but do not stop
  226. //
  227. if( p == pend )
  228. assert( false );
  229. assert( uBufSize > _tcslen( p ) );
  230. _tcsncpy( szObjectName, p, uBufSize - 1 );
  231. szObjectName[ uBufSize - 1 ] = NULL;
  232. }
  233. else
  234. {
  235. assert( false );
  236. throw OP_GENERIC_EXCEPTION;
  237. }
  238. }
  239. else
  240. {
  241. assert( false );
  242. throw OP_GENERIC_EXCEPTION;
  243. }
  244. }
  245. catch( DWORD dwErr )
  246. {
  247. SetLastError( dwErr );
  248. dwRet = false;
  249. }
  250. if( pDsSelList )
  251. GlobalUnlock( stgmedium.hGlobal );
  252. ReleaseStgMedium( &stgmedium );
  253. return dwRet;
  254. }
  255. //+--------------------------------------------------------------------------
  256. //
  257. // Function: InitObjectPickerForGroups
  258. //
  259. // Synopsis: Call IDsObjectPicker::Initialize with arguments that will
  260. // set it to allow the user to pick one or more groups.
  261. //
  262. // Arguments: [pDsObjectPicker] - object picker interface instance
  263. //
  264. // Returns: Result of calling IDsObjectPicker::Initialize.
  265. //
  266. // History: 10-14-1998 DavidMun Created
  267. // 1-8-2000 SergeiA Adapted for IIS
  268. // 9-6-2002 a-dsebes Adapted for UDDI
  269. //
  270. //---------------------------------------------------------------------------
  271. HRESULT
  272. InitObjectPickerForGroups( IDsObjectPicker *pDsObjectPicker,
  273. BOOL fMultiselect,
  274. BOOL fWantSidPath )
  275. {
  276. //
  277. // Prepare to initialize the object picker.
  278. // Set up the array of scope initializer structures.
  279. //
  280. static const int SCOPE_INIT_COUNT = 5;
  281. DSOP_SCOPE_INIT_INFO aScopeInit[ SCOPE_INIT_COUNT ];
  282. ZeroMemory( aScopeInit, sizeof( DSOP_SCOPE_INIT_INFO ) * SCOPE_INIT_COUNT );
  283. //
  284. // Target computer scope. This adds a "Look In" entry for the
  285. // target computer. Computer scopes are always treated as
  286. // downlevel (i.e., they use the WinNT provider).
  287. //
  288. aScopeInit[ 0 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  289. aScopeInit[ 0 ].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
  290. aScopeInit[ 0 ].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
  291. aScopeInit[ 0 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_BUILTIN_GROUPS;
  292. aScopeInit[ 0 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_LOCAL_GROUPS;
  293. if( fWantSidPath )
  294. {
  295. aScopeInit[ 0 ].flScope |= DSOP_SCOPE_FLAG_WANT_SID_PATH;
  296. }
  297. //
  298. // The domain to which the target computer is joined. Note we're
  299. // combining two scope types into flType here for convenience.
  300. //
  301. aScopeInit[ 1 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  302. aScopeInit[ 1 ].flScope = 0;
  303. aScopeInit[ 1 ].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN |
  304. DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  305. aScopeInit[ 1 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_GLOBAL_GROUPS_SE |
  306. DSOP_FILTER_UNIVERSAL_GROUPS_SE |
  307. DSOP_FILTER_DOMAIN_LOCAL_GROUPS_SE;
  308. aScopeInit[ 1 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
  309. if( fWantSidPath )
  310. {
  311. aScopeInit[ 1 ].flScope |= DSOP_SCOPE_FLAG_WANT_SID_PATH;
  312. }
  313. //
  314. // The domains in the same forest (enterprise) as the domain to which
  315. // the target machine is joined. Note these can only be DS-aware
  316. //
  317. aScopeInit[ 2 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  318. aScopeInit[ 2 ].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
  319. aScopeInit[ 2 ].flScope = 0;
  320. aScopeInit[ 2 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_GLOBAL_GROUPS_SE |
  321. DSOP_FILTER_UNIVERSAL_GROUPS_SE;
  322. if( fWantSidPath )
  323. {
  324. aScopeInit[ 2 ].flScope |= DSOP_SCOPE_FLAG_WANT_SID_PATH;
  325. }
  326. //
  327. // Domains external to the enterprise but trusted directly by the
  328. // domain to which the target machine is joined.
  329. //
  330. // If the target machine is joined to an NT4 domain, only the
  331. // external downlevel domain scope applies, and it will cause
  332. // all domains trusted by the joined domain to appear.
  333. //
  334. aScopeInit[ 3 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  335. aScopeInit[ 3 ].flScope = 0;
  336. aScopeInit[ 3 ].flType = DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
  337. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN;
  338. aScopeInit[ 3 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_GLOBAL_GROUPS_SE |
  339. DSOP_FILTER_UNIVERSAL_GROUPS_SE;
  340. aScopeInit[ 3 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_GLOBAL_GROUPS;
  341. if( fWantSidPath )
  342. {
  343. aScopeInit[ 3 ].flScope |= DSOP_SCOPE_FLAG_WANT_SID_PATH;
  344. }
  345. //
  346. // The Global Catalog
  347. //
  348. aScopeInit[ 4 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  349. aScopeInit[ 4 ].flScope = 0;
  350. aScopeInit[ 4 ].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  351. //
  352. // Only native mode applies to gc scope.
  353. //
  354. aScopeInit[ 4 ].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_GLOBAL_GROUPS_SE |
  355. DSOP_FILTER_UNIVERSAL_GROUPS_SE;
  356. if( fWantSidPath )
  357. {
  358. aScopeInit[ 4 ].flScope |= DSOP_SCOPE_FLAG_WANT_SID_PATH;
  359. }
  360. //
  361. // Put the scope init array into the object picker init array
  362. //
  363. DSOP_INIT_INFO InitInfo;
  364. ZeroMemory( &InitInfo, sizeof( InitInfo ) );
  365. InitInfo.cbSize = sizeof( InitInfo );
  366. //
  367. // The pwzTargetComputer member allows the object picker to be
  368. // retargetted to a different computer. It will behave as if it
  369. // were being run ON THAT COMPUTER.
  370. //
  371. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  372. InitInfo.aDsScopeInfos = aScopeInit;
  373. InitInfo.flOptions = fMultiselect ? DSOP_FLAG_MULTISELECT : 0;
  374. //
  375. // Note object picker makes its own copy of InitInfo. Also note
  376. // that Initialize may be called multiple times, last call wins.
  377. //
  378. HRESULT hr = pDsObjectPicker->Initialize( &InitInfo );
  379. return hr;
  380. }
  381. //+--------------------------------------------------------------------------
  382. //
  383. // Function: InitObjectPickerForUsers
  384. //
  385. // Synopsis: Call IDsObjectPicker::Initialize with arguments that will
  386. // set it to allow the user to pick one or more groups.
  387. //
  388. // Arguments: [pDsObjectPicker] - object picker interface instance
  389. //
  390. // Returns: Result of calling IDsObjectPicker::Initialize.
  391. //
  392. // History: 9-6-2002 a-dsebes Created.
  393. //
  394. //
  395. //---------------------------------------------------------------------------
  396. HRESULT
  397. InitObjectPickerForUsers( IDsObjectPicker *pDsObjectPicker,
  398. BOOL fMultiselect )
  399. {
  400. //
  401. // Prepare to initialize the object picker.
  402. // Set up the array of scope initializer structures.
  403. //
  404. static const int SCOPE_INIT_COUNT = 5;
  405. DSOP_SCOPE_INIT_INFO aScopeInit[ SCOPE_INIT_COUNT ];
  406. ZeroMemory( aScopeInit, sizeof( DSOP_SCOPE_INIT_INFO ) * SCOPE_INIT_COUNT );
  407. //
  408. // Target computer scope. This adds a "Look In" entry for the
  409. // target computer. Computer scopes are always treated as
  410. // downlevel (i.e., they use the WinNT provider).
  411. //
  412. aScopeInit[ 0 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  413. aScopeInit[ 0 ].flType = DSOP_SCOPE_TYPE_TARGET_COMPUTER;
  414. aScopeInit[ 0 ].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
  415. aScopeInit[ 0 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  416. aScopeInit[ 0 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  417. //
  418. // The domain to which the target computer is joined. Note we're
  419. // combining two scope types into flType here for convenience.
  420. //
  421. aScopeInit[ 1 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  422. aScopeInit[ 1 ].flScope = 0;
  423. aScopeInit[ 1 ].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN |
  424. DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  425. aScopeInit[ 1 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  426. aScopeInit[ 1 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  427. //
  428. // The domains in the same forest (enterprise) as the domain to which
  429. // the target machine is joined. Note these can only be DS-aware
  430. //
  431. aScopeInit[ 2 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  432. aScopeInit[ 2 ].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN;
  433. aScopeInit[ 2 ].flScope = 0;
  434. aScopeInit[ 2 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  435. //
  436. // Domains external to the enterprise but trusted directly by the
  437. // domain to which the target machine is joined.
  438. //
  439. // If the target machine is joined to an NT4 domain, only the
  440. // external downlevel domain scope applies, and it will cause
  441. // all domains trusted by the joined domain to appear.
  442. //
  443. aScopeInit[ 3 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  444. aScopeInit[ 3 ].flScope = 0;
  445. aScopeInit[ 3 ].flType = DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN |
  446. DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN;
  447. aScopeInit[ 3 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_USERS;
  448. aScopeInit[ 3 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_USERS;
  449. //
  450. // The Global Catalog
  451. //
  452. aScopeInit[ 4 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  453. aScopeInit[ 4 ].flScope = 0;
  454. aScopeInit[ 4 ].flType = DSOP_SCOPE_TYPE_GLOBAL_CATALOG;
  455. //
  456. // Only native mode applies to gc scope.
  457. //
  458. aScopeInit[ 4 ].FilterFlags.Uplevel.flNativeModeOnly = DSOP_FILTER_USERS;
  459. //
  460. // Put the scope init array into the object picker init array
  461. //
  462. DSOP_INIT_INFO InitInfo;
  463. ZeroMemory( &InitInfo, sizeof( InitInfo ) );
  464. InitInfo.cbSize = sizeof( InitInfo );
  465. //
  466. // The pwzTargetComputer member allows the object picker to be
  467. // retargetted to a different computer. It will behave as if it
  468. // were being run ON THAT COMPUTER.
  469. //
  470. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  471. InitInfo.aDsScopeInfos = aScopeInit;
  472. InitInfo.flOptions = fMultiselect ? DSOP_FLAG_MULTISELECT : 0;
  473. //
  474. // Note object picker makes its own copy of InitInfo. Also note
  475. // that Initialize may be called multiple times, last call wins.
  476. //
  477. HRESULT hr = pDsObjectPicker->Initialize( &InitInfo );
  478. return hr;
  479. }
  480. //+--------------------------------------------------------------------------
  481. //
  482. // Function: InitObjectPickerForComputers
  483. //
  484. // Synopsis: Call IDsObjectPicker::Initialize with arguments that will
  485. // set it to allow the user to pick a single computer object.
  486. //
  487. // Arguments: [pDsObjectPicker] - object picker interface instance
  488. //
  489. // Returns: Result of calling IDsObjectPicker::Initialize.
  490. //
  491. // History: 10-14-1998 DavidMun Created
  492. // 08-06-2002 a-dsebes Adapted for UDDI.
  493. //
  494. //---------------------------------------------------------------------------
  495. HRESULT
  496. InitObjectPickerForComputers( IDsObjectPicker *pDsObjectPicker )
  497. {
  498. //
  499. // Prepare to initialize the object picker.
  500. // Set up the array of scope initializer structures.
  501. //
  502. static const int SCOPE_INIT_COUNT = 2;
  503. DSOP_SCOPE_INIT_INFO aScopeInit[ SCOPE_INIT_COUNT ];
  504. ZeroMemory( aScopeInit, sizeof( DSOP_SCOPE_INIT_INFO ) * SCOPE_INIT_COUNT );
  505. //
  506. // Build a scope init struct for everything except the joined domain.
  507. //
  508. aScopeInit[ 0 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  509. aScopeInit[ 0 ].flType = DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN
  510. | DSOP_SCOPE_TYPE_GLOBAL_CATALOG
  511. | DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN
  512. | DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN
  513. | DSOP_SCOPE_TYPE_WORKGROUP
  514. | DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE
  515. | DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE;
  516. aScopeInit[ 0 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_COMPUTERS;
  517. aScopeInit[ 0 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  518. //
  519. // scope for the joined domain, make it the default
  520. //
  521. aScopeInit[ 1 ].cbSize = sizeof( DSOP_SCOPE_INIT_INFO );
  522. aScopeInit[ 1 ].flType = DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN
  523. | DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN;
  524. aScopeInit[ 1 ].FilterFlags.Uplevel.flBothModes = DSOP_FILTER_COMPUTERS;
  525. aScopeInit[ 1 ].FilterFlags.flDownlevel = DSOP_DOWNLEVEL_FILTER_COMPUTERS;
  526. aScopeInit[ 1 ].flScope = DSOP_SCOPE_FLAG_STARTING_SCOPE;
  527. //
  528. // Put the scope init array into the object picker init array
  529. //
  530. DSOP_INIT_INFO InitInfo;
  531. ZeroMemory( &InitInfo, sizeof( InitInfo ) );
  532. InitInfo.cbSize = sizeof( InitInfo );
  533. InitInfo.pwzTargetComputer = NULL; // NULL == local machine
  534. InitInfo.cDsScopeInfos = SCOPE_INIT_COUNT;
  535. InitInfo.aDsScopeInfos = aScopeInit;
  536. //
  537. // Note object picker makes its own copy of InitInfo. Also note
  538. // that Initialize may be called multiple times, last call wins.
  539. //
  540. return pDsObjectPicker->Initialize(&InitInfo);
  541. }