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.

1576 lines
42 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. // NEWCLNT.CPP - Handle the "New Clients" IDD_PROP_NEW_CLIENTS property page
  5. //
  6. #include "pch.h"
  7. #include <dnsapi.h>
  8. #include <ntdsapi.h>
  9. #include <dsgetdc.h>
  10. #include <lm.h>
  11. #include <wininet.h>
  12. #include "newclnts.h"
  13. #include "cservice.h"
  14. DEFINE_MODULE("IMADMUI")
  15. DEFINE_THISCLASS("CNewClientsTab")
  16. #define THISCLASS CNewClientsTab
  17. #define LPTHISCLASS LPCNewClientsTab
  18. #define UNKNOWN_INVALID_TEMPLATE L"??"
  19. #include <riname.h>
  20. #include <riname.c>
  21. DWORD aNewClientsHelpMap[] = {
  22. IDC_B_BROWSE, HIDC_B_BROWSE,
  23. IDC_E_NEWMACHINEOU, HIDC_E_NEWMACHINEOU,
  24. IDC_R_SPECIFICLOCATION, HIDC_R_SPECIFICLOCATION,
  25. IDC_R_SAMEASUSER, HIDC_R_SAMEASUSER,
  26. IDC_R_DOMAINDEFAULT, HIDC_R_DOMAINDEFAULT,
  27. IDC_G_CLIENTACCOUNTLOCATION, HIDC_G_CLIENTACCOUNTLOCATION,
  28. IDC_E_SAMPLE, HIDC_E_SAMPLE,
  29. IDC_CB_NAMINGPOLICY, HIDC_CB_NAMINGPOLICY,
  30. IDC_B_ADVANCED, HIDC_B_ADVANCED,
  31. IDC_G_NAMINGFORMAT, HIDC_G_NAMINGFORMAT,
  32. NULL, NULL
  33. };
  34. DWORD aAdvancedHelpMap[] = {
  35. IDC_E_FORMAT, HIDC_E_FORMAT,
  36. IDC_E_SAMPLE, HIDC_E_SAMPLE,
  37. NULL, NULL
  38. };
  39. //
  40. // CreateInstance()
  41. //
  42. LPVOID
  43. CNewClientsTab_CreateInstance( void )
  44. {
  45. TraceFunc( "CNewClientsTab_CreateInstance()\n" );
  46. LPTHISCLASS lpcc = new THISCLASS( );
  47. if ( !lpcc ) {
  48. RETURN(lpcc);
  49. }
  50. HRESULT hr = THR( lpcc->Init( ) );
  51. if ( FAILED(hr) )
  52. {
  53. delete lpcc;
  54. RETURN(NULL);
  55. }
  56. RETURN(lpcc);
  57. }
  58. //
  59. // Constructor
  60. //
  61. THISCLASS::THISCLASS( ) :
  62. _hDlg(NULL),
  63. _punkService(NULL),
  64. _fAdmin(FALSE),
  65. _fChanged(FALSE),
  66. _iCustomId(0),
  67. _pszCustomNamingPolicy(NULL),
  68. _pszNewMachineOU(NULL),
  69. _pszServerDN(NULL),
  70. _hNotify(NULL)
  71. {
  72. TraceClsFunc( "CNewClientsTab()\n" );
  73. ZeroMemory(_szSampleName,DNS_MAX_LABEL_BUFFER_LENGTH *sizeof(WCHAR));
  74. InterlockIncrement( g_cObjects );
  75. TraceFuncExit();
  76. }
  77. //
  78. // Scratch buffer used to load strings.
  79. //
  80. WCHAR szSamples0[ SAMPLES_LIST_SIZE ];
  81. WCHAR szSamples1[ SAMPLES_LIST_SIZE ];
  82. WCHAR szSamples2[ SAMPLES_LIST_SIZE ];
  83. //
  84. // Init()
  85. //
  86. HRESULT __stdcall
  87. THISCLASS::Init( )
  88. {
  89. HRESULT hr = S_OK;
  90. TraceClsFunc( "Init()\n" );
  91. Assert( !_pszNewMachineOU );
  92. Assert( !_pszServerDN );
  93. HRETURN(hr);
  94. }
  95. //
  96. // Destructor
  97. //
  98. THISCLASS::~THISCLASS( )
  99. {
  100. TraceClsFunc( "~CNewClientsTab()\n" );
  101. if ( _punkService )
  102. _punkService->Release( );
  103. if ( _pszServerDN )
  104. TraceFree( _pszServerDN );
  105. if ( _pszCustomNamingPolicy )
  106. TraceFree( _pszCustomNamingPolicy );
  107. // tell ADS to destroy the notify object
  108. // NOTE: Another property page may do this before us. Ignore errors.
  109. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_EXIT, 0, 0 );
  110. InterlockDecrement( g_cObjects );
  111. TraceFuncExit();
  112. };
  113. // *************************************************************************
  114. //
  115. // ITab
  116. //
  117. // *************************************************************************
  118. STDMETHODIMP
  119. THISCLASS::AddPages(
  120. LPFNADDPROPSHEETPAGE lpfnAddPage,
  121. LPARAM lParam,
  122. LPUNKNOWN punk )
  123. {
  124. TraceClsFunc( "AddPages( )\n" );
  125. HRESULT hr = S_OK;
  126. PROPSHEETPAGE psp;
  127. HPROPSHEETPAGE hpage;
  128. psp.dwSize = sizeof(psp);
  129. psp.dwFlags = PSP_USEREFPARENT | PSP_USECALLBACK;
  130. psp.hInstance = (HINSTANCE) g_hInstance;
  131. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_NEW_CLIENTS);
  132. psp.pcRefParent = (UINT *) &g_cObjects;
  133. psp.pfnCallback = (LPFNPSPCALLBACK) PropSheetPageProc;
  134. psp.pfnDlgProc = PropSheetDlgProc;
  135. psp.lParam = (LPARAM) this;
  136. hpage = CreatePropertySheetPage( &psp );
  137. if ( hpage )
  138. {
  139. if ( !lpfnAddPage( hpage, lParam ) )
  140. {
  141. DestroyPropertySheetPage( hpage );
  142. hr = E_FAIL;
  143. goto Error;
  144. }
  145. }
  146. punk->AddRef( ); // matching Release in the destructor
  147. _punkService = punk;
  148. Error:
  149. HRETURN(hr);
  150. }
  151. //
  152. // ReplacePage()
  153. //
  154. STDMETHODIMP
  155. THISCLASS::ReplacePage(
  156. UINT uPageID,
  157. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  158. LPARAM lParam,
  159. LPUNKNOWN punk )
  160. {
  161. TraceClsFunc( "ReplacePage( ) *** NOT_IMPLEMENTED ***\n" );
  162. RETURN(E_NOTIMPL);
  163. }
  164. //
  165. // QueryInformation( )
  166. //
  167. STDMETHODIMP
  168. THISCLASS::QueryInformation(
  169. LPWSTR pszAttribute,
  170. LPWSTR * pszResult )
  171. {
  172. TraceClsFunc( "QueryInformation( )\n" );
  173. HRETURN(E_NOTIMPL);
  174. }
  175. //
  176. // AllowActivation( )
  177. //
  178. STDMETHODIMP
  179. THISCLASS::AllowActivation(
  180. BOOL * pfAllow )
  181. {
  182. TraceClsFunc( "AllowActivation( )\n" );
  183. HRETURN(E_NOTIMPL);
  184. }
  185. // ************************************************************************
  186. //
  187. // Property Sheet Functions
  188. //
  189. // ************************************************************************
  190. //
  191. // GenerateSample( )
  192. //
  193. DWORD
  194. GenerateSample(
  195. LPWSTR pszPolicy,
  196. LPWSTR pszSampleOut,
  197. LPDWORD maxLength )
  198. {
  199. DWORD error;
  200. GENNAME_VARIABLES variables;
  201. TraceClsFunc( "GenerateSample( )\n" );
  202. if ( !pszPolicy )
  203. HRETURN(E_POINTER);
  204. variables.UserName = L"JOHNSMI";
  205. variables.FirstName = L"John";
  206. variables.LastName = L"Smith";
  207. variables.MacAddress = L"123456789012";
  208. variables.Counter = 123456789;
  209. variables.AllowCounterTruncation = TRUE;
  210. error = GenerateNameFromTemplate(
  211. pszPolicy,
  212. &variables,
  213. pszSampleOut,
  214. DNS_MAX_LABEL_BUFFER_LENGTH,
  215. NULL,
  216. NULL,
  217. maxLength
  218. );
  219. if ( error == GENNAME_TEMPLATE_INVALID ) {
  220. wcscpy( pszSampleOut, UNKNOWN_INVALID_TEMPLATE );
  221. }
  222. RETURN(error);
  223. }
  224. //
  225. // _UpdateSheet()
  226. //
  227. HRESULT
  228. THISCLASS::_UpdateSheet( LPWSTR pszNamingPolicy )
  229. {
  230. TraceClsFunc( "_UpdateSheet( )\n" );
  231. HRESULT hr = S_FALSE;
  232. LPWSTR pszNext;
  233. DWORD dw;
  234. HWND hwndCB = GetDlgItem( _hDlg, IDC_CB_NAMINGPOLICY );
  235. if (hwndCB == NULL) {
  236. RRETURN(GetLastError());
  237. }
  238. if ( pszNamingPolicy )
  239. {
  240. BOOL fMatched = FALSE;
  241. INT iCount;
  242. INT iOldCount = ComboBox_GetCurSel( hwndCB );
  243. // Retrieve the combobox strings
  244. dw = LoadString( g_hInstance, IDS_SAMPLENAMINGPOLICY, szSamples0, ARRAYSIZE( szSamples0 ) );
  245. Assert( dw );
  246. if (!dw) {
  247. HRETURN(HRESULT_FROM_WIN32(GetLastError()));
  248. }
  249. iCount = 0;
  250. pszNext = szSamples0;
  251. while ( *pszNext )
  252. {
  253. LPWSTR pszFriendlyName = pszNext;
  254. // skip the friendly name
  255. pszNext =StrChr( pszNext, L';' );
  256. if ( !pszNext )
  257. break;
  258. *pszNext = L'\0'; // terminate
  259. pszNext++;
  260. LPWSTR pszCodedString = pszNext;
  261. pszNext = StrChr( pszNext, L';' );
  262. if ( !pszNext )
  263. break;
  264. *pszNext = L'\0'; // teminate
  265. if ( pszNamingPolicy && StrCmpI( pszNamingPolicy, pszCodedString ) == 0 )
  266. {
  267. break;
  268. }
  269. iCount++;
  270. pszNext++;
  271. }
  272. if ( iOldCount != iCount )
  273. {
  274. ComboBox_SetCurSel( hwndCB, iCount );
  275. hr = S_OK;
  276. }
  277. }
  278. else
  279. {
  280. INT iCount = ComboBox_GetCurSel( hwndCB );
  281. // Retrieve the combobox strings
  282. dw = LoadString( g_hInstance, IDS_SAMPLENAMINGPOLICY, szSamples0, ARRAYSIZE( szSamples0 ) );
  283. Assert( dw );
  284. if (!dw) {
  285. HRETURN(HRESULT_FROM_WIN32(GetLastError()));
  286. }
  287. pszNext = szSamples0;
  288. while ( *pszNext && iCount >= 0 )
  289. {
  290. LPWSTR pszFriendlyName = pszNext;
  291. // skip the friendly name
  292. pszNext =StrChr( pszNext, L';' );
  293. if ( !pszNext )
  294. break;
  295. *pszNext = L'\0'; // terminate
  296. pszNext++;
  297. pszNamingPolicy = pszNext;
  298. pszNext = StrChr( pszNext, L';' );
  299. if ( !pszNext )
  300. break;
  301. *pszNext = L'\0'; // teminate
  302. iCount--;
  303. pszNext++;
  304. }
  305. }
  306. GenerateSample( pszNamingPolicy, _szSampleName, &dw );
  307. SetDlgItemText( _hDlg, IDC_E_SAMPLE, _szSampleName );
  308. RETURN(hr);
  309. }
  310. //
  311. // _InitDialog( )
  312. //
  313. HRESULT
  314. THISCLASS::_InitDialog(
  315. HWND hDlg,
  316. LPARAM lParam )
  317. {
  318. TraceClsFunc( "_InitDialog( )\n" );
  319. HRESULT hr;
  320. HRESULT hResult = S_OK;
  321. DWORD dw;
  322. LPWSTR pszNext;
  323. HWND hwnd;
  324. LPWSTR pszNewMachineOU = NULL;
  325. IIntelliMirrorSAP * pimsap = NULL;
  326. _hDlg = hDlg;
  327. dw = LoadString( g_hInstance, IDS_SAMPLENAMINGPOLICY, szSamples1, ARRAYSIZE( szSamples1 ) );
  328. Assert( dw );
  329. if (!dw) {
  330. hr = HRESULT_FROM_WIN32(GetLastError());
  331. goto Error;
  332. }
  333. Assert( _punkService );
  334. hr = THR( _punkService->QueryInterface( IID_IIntelliMirrorSAP, (void**) &pimsap ) );
  335. if (FAILED( hr ))
  336. goto Error;
  337. hr = THR( pimsap->GetNotifyWindow( &_hNotify ) );
  338. if (FAILED( hr ))
  339. goto Error;
  340. ADsPropSetHwnd( _hNotify, _hDlg );
  341. //
  342. // Populate Naming Policy ComboBox
  343. //
  344. hwnd = GetDlgItem( _hDlg, IDC_CB_NAMINGPOLICY );
  345. ComboBox_ResetContent( hwnd );
  346. _iCustomId = 0;
  347. pszNext = szSamples1;
  348. while ( *pszNext )
  349. {
  350. // add the friendly name to the combobox
  351. LPWSTR pszFriendlyName = pszNext;
  352. pszNext = StrChr( pszNext, L';' );
  353. if ( !pszNext )
  354. break;
  355. *pszNext = L'\0'; // terminate
  356. ComboBox_AddString( hwnd, pszFriendlyName );
  357. *pszNext = L';'; // restore
  358. // skip the formatted string
  359. pszNext++;
  360. pszNext = StrChr( pszNext, L';' );
  361. if ( !pszNext )
  362. break;
  363. pszNext++;
  364. _iCustomId++;
  365. }
  366. hr = THR( pimsap->IsAdmin( &_fAdmin ) );
  367. Assert( SUCCEEDED(hr) || _fAdmin == FALSE );
  368. EnableWindow( GetDlgItem( _hDlg, IDC_CB_NAMINGPOLICY ), _fAdmin );
  369. EnableWindow( GetDlgItem( _hDlg, IDC_B_ADVANCED ), _fAdmin );
  370. EnableWindow( GetDlgItem( _hDlg, IDC_R_SAMEASUSER ), _fAdmin );
  371. EnableWindow( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ), _fAdmin );
  372. EnableWindow( GetDlgItem( _hDlg, IDD_PROP_NEW_CLIENTS ), _fAdmin );
  373. EnableWindow( GetDlgItem( _hDlg, IDC_R_SPECIFICLOCATION ), _fAdmin );
  374. hr = THR( pimsap->GetNewMachineNamingPolicy( &_pszCustomNamingPolicy ) );
  375. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND && hResult == S_OK )
  376. {
  377. hResult = hr;
  378. }
  379. Assert( SUCCEEDED(hr) || !_pszCustomNamingPolicy );
  380. _UpdateSheet( _pszCustomNamingPolicy );
  381. hr = pimsap->GetNewMachineOU( &pszNewMachineOU );
  382. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND && hResult == S_OK )
  383. {
  384. hResult = hr;
  385. }
  386. Assert( SUCCEEDED(hr) || !pszNewMachineOU );
  387. hr = THR( pimsap->GetServerDN( &_pszServerDN ) );
  388. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND && hResult == S_OK )
  389. {
  390. hResult = hr;
  391. }
  392. Assert( SUCCEEDED(hr) || !_pszServerDN );
  393. if ( pszNewMachineOU )
  394. {
  395. if( StrCmp( pszNewMachineOU, _pszServerDN ) !=0 )
  396. {
  397. hr = _MakeOUPretty( DS_FQDN_1779_NAME, DS_CANONICAL_NAME, &pszNewMachineOU );
  398. BOOLEAN temp = _fChanged;
  399. _fChanged =TRUE;// Prevent early turning on of the Apply button.
  400. SetDlgItemText( _hDlg, IDC_E_NEWMACHINEOU, pszNewMachineOU );
  401. _fChanged = temp;
  402. EnableWindow( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), _fAdmin );
  403. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), _fAdmin );
  404. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SPECIFICLOCATION ), BST_CHECKED );
  405. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ), BST_UNCHECKED );
  406. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SAMEASUSER ), BST_UNCHECKED );
  407. }
  408. else
  409. {
  410. EnableWindow( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), FALSE );
  411. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), FALSE );
  412. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SPECIFICLOCATION ), BST_UNCHECKED );
  413. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ), BST_CHECKED );
  414. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SAMEASUSER ), BST_UNCHECKED );
  415. }
  416. }
  417. else
  418. {
  419. EnableWindow( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), FALSE );
  420. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), FALSE );
  421. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SPECIFICLOCATION ), BST_UNCHECKED );
  422. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ), BST_UNCHECKED );
  423. Button_SetCheck( GetDlgItem( _hDlg, IDC_R_SAMEASUSER ), BST_CHECKED );
  424. }
  425. if ( hResult != S_OK )
  426. {
  427. MessageBoxFromHResult( _hDlg, IDS_ERROR_READINGCOMPUTERACCOUNT, hResult );
  428. }
  429. Cleanup:
  430. if ( pszNewMachineOU )
  431. TraceFree( pszNewMachineOU );
  432. if ( pimsap )
  433. pimsap->Release( );
  434. HRETURN(hr);
  435. Error:
  436. MessageBoxFromHResult( _hDlg, IDS_ERROR_READINGCOMPUTERACCOUNT, hr );
  437. goto Cleanup;
  438. }
  439. PCWSTR
  440. GetDCNameForServer(
  441. PCWSTR InputPath
  442. )
  443. /*++
  444. Routine Description:
  445. Given a server name, we retrive the name of a DC for that server's domain.
  446. We create an LDAP path of the form LDAP://DNSNAMEOFDC/DNOFDOMAIN.
  447. Arguments:
  448. ServerName - name of the server to validate
  449. Return Value:
  450. String indicating DC name. Must be freed via TraceFree().
  451. --*/
  452. {
  453. PWSTR FQDN = NULL,p,DCName = NULL,DomainDN = NULL;
  454. HRESULT hr;
  455. HANDLE hDC;
  456. DOMAIN_CONTROLLER_INFO *DomainControllerInfo;
  457. hr = DNtoFQDN( (LPWSTR)InputPath, &FQDN);
  458. if (!SUCCEEDED(hr)) {
  459. goto Exit;
  460. }
  461. hr = GetDomainDN( (LPWSTR)InputPath, &DomainDN);
  462. if (!SUCCEEDED(hr)) {
  463. goto Exit;
  464. }
  465. p = StrStrI(FQDN,L".");
  466. if (!p) {
  467. goto Exit;
  468. }
  469. p += 1;
  470. if (ERROR_SUCCESS == DsGetDcName(
  471. NULL,
  472. p,
  473. NULL,
  474. NULL,
  475. DS_IS_DNS_NAME | DS_RETURN_DNS_NAME,
  476. &DomainControllerInfo
  477. )) {
  478. //
  479. // want a string of form:
  480. //
  481. // LDAP://DNSNAMEOFDC/DNOFDOMAIN
  482. //
  483. DCName = TraceAllocString(
  484. LMEM_FIXED,
  485. sizeof(L"LDAP://") +
  486. (wcslen(DomainControllerInfo->DomainControllerName)-2)*sizeof(WCHAR) +
  487. sizeof(L"/") +
  488. wcslen(DomainDN)*sizeof(WCHAR) +
  489. 1 * sizeof (WCHAR)
  490. );
  491. if (DCName) {
  492. wcscpy(DCName,L"LDAP://");
  493. //
  494. // skip the \\ in front of the DC name
  495. //
  496. wcscat(DCName,&DomainControllerInfo->DomainControllerName[2]);
  497. wcscat(DCName,L"/");
  498. wcscat(DCName,DomainDN);
  499. }
  500. NetApiBufferFree(DomainControllerInfo);
  501. }
  502. Exit:
  503. if (FQDN) {
  504. TraceFree( FQDN );
  505. }
  506. if (DomainDN) {
  507. TraceFree( DomainDN );
  508. }
  509. return(DCName);
  510. }
  511. //
  512. // _OnCommand( )
  513. //
  514. HRESULT
  515. THISCLASS::_OnCommand( WPARAM wParam, LPARAM lParam )
  516. {
  517. TraceClsFunc( "_OnCommand( " );
  518. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  519. BOOL fReturn = TRUE;
  520. BOOL fChanged = FALSE;
  521. HWND hwndCtl = (HWND) lParam;
  522. switch( LOWORD(wParam) )
  523. {
  524. case IDC_B_ADVANCED:
  525. if ( HIWORD( wParam ) == BN_CLICKED )
  526. {
  527. LPWSTR pszNamingPolicy = _pszCustomNamingPolicy;
  528. HRESULT hr = _GetCurrentNamingPolicy( &_pszCustomNamingPolicy );
  529. if ( hr != S_FALSE )
  530. {
  531. TraceFree( pszNamingPolicy );
  532. }
  533. UINT i = (UINT) DialogBoxParam( g_hInstance,
  534. MAKEINTRESOURCE( IDD_ADVANCEDNAMIMG),
  535. _hDlg,
  536. AdvancedDlgProc,
  537. (LPARAM) this );
  538. hr = _UpdateSheet( _pszCustomNamingPolicy );
  539. if ( i == IDOK )
  540. {
  541. fChanged = TRUE;
  542. }
  543. }
  544. break;
  545. case IDC_CB_NAMINGPOLICY:
  546. if ( HIWORD( wParam ) == CBN_SELCHANGE )
  547. {
  548. INT iSelection = ComboBox_GetCurSel( hwndCtl );
  549. if ( iSelection == _iCustomId )
  550. {
  551. UINT i = (UINT) DialogBoxParam( g_hInstance,
  552. MAKEINTRESOURCE( IDD_ADVANCEDNAMIMG),
  553. _hDlg,
  554. AdvancedDlgProc,
  555. (LPARAM) this );
  556. HRESULT hr = _UpdateSheet( _pszCustomNamingPolicy );
  557. if ( i == IDOK )
  558. {
  559. fChanged = TRUE;
  560. }
  561. }
  562. else
  563. {
  564. _UpdateSheet( NULL );
  565. fChanged = TRUE;
  566. }
  567. }
  568. break;
  569. case IDC_R_SPECIFICLOCATION:
  570. if ( HIWORD( wParam ) == BN_CLICKED )
  571. {
  572. HWND hwnd = GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU );
  573. EnableWindow( hwnd, _fAdmin );
  574. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), _fAdmin );
  575. if ( GetWindowTextLength( hwnd ) != 0 )
  576. {
  577. fChanged = TRUE;
  578. }
  579. }
  580. break;
  581. case IDC_E_NEWMACHINEOU:
  582. if ( HIWORD( wParam ) == EN_CHANGE )
  583. {
  584. HWND hwnd = GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU );
  585. if ( GetWindowTextLength( hwnd ) != 0 )
  586. {
  587. fChanged = TRUE;
  588. }
  589. }
  590. break;
  591. case IDC_R_SAMEASUSER:
  592. case IDC_R_DOMAINDEFAULT:
  593. if ( HIWORD( wParam ) == BN_CLICKED )
  594. {
  595. EnableWindow( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), FALSE );
  596. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), FALSE );
  597. fChanged = TRUE;
  598. }
  599. break;
  600. case IDC_B_BROWSE:
  601. if ( HIWORD( wParam ) == BN_CLICKED )
  602. {
  603. DSBROWSEINFO info;
  604. WCHAR szCaption[ 64 ];
  605. WCHAR szTitle[ 64 ];
  606. WCHAR szPath[ INTERNET_MAX_URL_LENGTH ];
  607. DWORD dw;
  608. szCaption[0] = L'\0';
  609. dw = LoadString( g_hInstance, IDS_BROWSEFOROU_CAPTION, szCaption, ARRAYSIZE( szCaption ) );
  610. Assert( dw );
  611. szTitle[0] = L'\0';
  612. dw = LoadString( g_hInstance, IDS_BROWSEFOROU_TITLE, szTitle, ARRAYSIZE( szTitle ) );
  613. Assert( dw );
  614. ZeroMemory( &info, sizeof(info) );
  615. info.cbStruct = sizeof(info);
  616. info.hwndOwner = _hDlg;
  617. info.pszRoot = GetDCNameForServer(_pszServerDN);
  618. info.pszCaption = szCaption;
  619. info.pszTitle = szTitle;
  620. info.pszPath = szPath;
  621. info.cchPath = ARRAYSIZE(szPath);
  622. info.dwFlags = DSBI_ENTIREDIRECTORY;
  623. if ( IDOK == DsBrowseForContainer( &info ) )
  624. {
  625. // Skip the "LDAP://" part
  626. HRESULT hr = E_FAIL;
  627. LPWSTR pszOU = NULL;
  628. if (wcslen(szPath) < 8 ||
  629. !(pszOU = TraceStrDup( &szPath[7] ))) {
  630. // bail out, neither condition is valid.
  631. fChanged = FALSE;
  632. if (info.pszRoot) {
  633. TraceFree( (HGLOBAL)info.pszRoot );
  634. }
  635. RRETURN(E_FAIL);
  636. }
  637. if ( pszOU )
  638. {
  639. hr = _MakeOUPretty( DS_FQDN_1779_NAME, DS_CANONICAL_NAME, &pszOU );
  640. if (SUCCEEDED( hr ))
  641. {
  642. SetWindowText( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), pszOU );
  643. fChanged = TRUE;
  644. }
  645. TraceFree( pszOU );
  646. }
  647. if (FAILED( hr ))
  648. {
  649. SetWindowText( GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU ), &szPath[7] );
  650. fChanged = TRUE;
  651. }
  652. }
  653. if (info.pszRoot) {
  654. TraceFree( (HGLOBAL)info.pszRoot );
  655. }
  656. }
  657. break;
  658. }
  659. if ( fChanged )
  660. {
  661. if ( !_fChanged )
  662. {
  663. _fChanged = TRUE;
  664. SendMessage( GetParent( _hDlg ), PSM_CHANGED, (WPARAM)_hDlg, 0 );
  665. }
  666. }
  667. if (fReturn) {
  668. RRETURN( S_OK );
  669. }
  670. RRETURN( E_FAIL );
  671. }
  672. //
  673. // _ApplyChanges( )
  674. //
  675. HRESULT
  676. THISCLASS::_ApplyChanges( )
  677. {
  678. TraceClsFunc( "_ApplyChanges( )\n" );
  679. if ( !_fChanged )
  680. HRETURN(S_OK); // nop
  681. HRESULT hr;
  682. HRESULT hResult = S_OK;
  683. LPWSTR pszNamingPolicy = NULL;
  684. UINT iItem;
  685. IIntelliMirrorSAP * pimsap = NULL;
  686. hr = THR( _punkService->QueryInterface( IID_IIntelliMirrorSAP, (void**) &pimsap ) );
  687. if (FAILED( hr ))
  688. goto Error;
  689. if ( Button_GetCheck( GetDlgItem( _hDlg, IDC_R_SPECIFICLOCATION ) ) == BST_CHECKED )
  690. {
  691. HWND hwnd = GetDlgItem( _hDlg, IDC_E_NEWMACHINEOU );
  692. ULONG uLen = GetWindowTextLength( hwnd ) + 1;
  693. LPWSTR pszNewMachineOU = TraceAllocString( LMEM_FIXED, uLen );
  694. if ( pszNewMachineOU )
  695. {
  696. GetWindowText( hwnd, pszNewMachineOU, uLen );
  697. hr = _MakeOUPretty( DS_CANONICAL_NAME, DS_FQDN_1779_NAME, &pszNewMachineOU );
  698. if (SUCCEEDED( hr ))
  699. {
  700. hr = THR( pimsap->SetNewMachineOU( pszNewMachineOU ) );
  701. }
  702. TraceFree( pszNewMachineOU );
  703. if (FAILED(hr) && hResult == S_OK )
  704. {
  705. hResult = hr;
  706. SetFocus( hwnd );
  707. }
  708. }
  709. }
  710. else if ( Button_GetCheck( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ) ) == BST_CHECKED )
  711. {
  712. hr = THR( pimsap->SetNewMachineOU( _pszServerDN ) );
  713. if (FAILED(hr) && hResult == S_OK )
  714. {
  715. hResult = hr;
  716. SetFocus( GetDlgItem( _hDlg, IDC_R_DOMAINDEFAULT ) );
  717. }
  718. }
  719. else
  720. {
  721. hr = THR( pimsap->SetNewMachineOU( NULL ) );
  722. if (FAILED(hr) && hResult == S_OK )
  723. {
  724. hResult = hr;
  725. SetFocus( GetDlgItem( _hDlg, IDC_R_SAMEASUSER ) );
  726. }
  727. }
  728. hr = _GetCurrentNamingPolicy( &pszNamingPolicy );
  729. if (FAILED( hr ) && hResult == S_OK )
  730. {
  731. hResult = hr;
  732. }
  733. hr = THR( pimsap->SetNewMachineNamingPolicy( pszNamingPolicy ) );
  734. if (FAILED( hr ) && hResult == S_OK )
  735. {
  736. SetFocus( GetDlgItem( _hDlg, IDC_CB_NAMINGPOLICY ) );
  737. hResult = hr;
  738. }
  739. hr = THR( pimsap->CommitChanges( ) );
  740. if (FAILED( hr ))
  741. goto Error;
  742. if ( hResult != S_OK )
  743. {
  744. MessageBoxFromHResult( _hDlg, IDS_ERROR_WRITINGTOCOMPUTERACCOUNT, hResult );
  745. hr = hResult;
  746. }
  747. else
  748. {
  749. _fChanged = FALSE;
  750. }
  751. Cleanup:
  752. if ( pimsap )
  753. pimsap->Release( );
  754. if ( pszNamingPolicy )
  755. TraceFree( pszNamingPolicy );
  756. // Tell DSA that someone hit Apply
  757. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_APPLY, !!SUCCEEDED( hr ), 0 );
  758. HRETURN(hr);
  759. Error:
  760. MessageBoxFromHResult( _hDlg, IDS_ERROR_WRITINGTOCOMPUTERACCOUNT, hr );
  761. goto Cleanup;
  762. }
  763. //
  764. // _OnNotify( )
  765. //
  766. INT
  767. THISCLASS::_OnNotify(
  768. WPARAM wParam,
  769. LPARAM lParam )
  770. {
  771. TraceClsFunc( "_OnNotify( " );
  772. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  773. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  774. switch( lpnmhdr->code )
  775. {
  776. case PSN_APPLY:
  777. {
  778. HRESULT hr;
  779. TraceMsg( TF_WM, TEXT("WM_NOTIFY: PSN_APPLY\n"));
  780. hr = _ApplyChanges( );
  781. SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, ( SUCCEEDED(hr) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ));
  782. RETURN(TRUE);
  783. }
  784. break;
  785. default:
  786. break;
  787. }
  788. RETURN(FALSE);
  789. }
  790. //
  791. // PropSheetDlgProc()
  792. //
  793. INT_PTR CALLBACK
  794. THISCLASS::PropSheetDlgProc(
  795. HWND hDlg,
  796. UINT uMsg,
  797. WPARAM wParam,
  798. LPARAM lParam )
  799. {
  800. //TraceMsg( TEXT("PropSheetDlgProc(") );
  801. //TraceMsg( TF_FUNC, TEXT(" hDlg = 0x%08x, uMsg = 0x%08x, wParam = 0x%08x, lParam = 0x%08x )\n"),
  802. // hDlg, uMsg, wParam, lParam );
  803. LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
  804. if ( uMsg == WM_INITDIALOG )
  805. {
  806. TraceMsg( TF_WM, TEXT("WM_INITDIALOG\n"));
  807. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE) lParam;
  808. SetWindowLongPtr( hDlg, GWLP_USERDATA, psp->lParam );
  809. pcc = (LPTHISCLASS) psp->lParam;
  810. pcc->_InitDialog( hDlg, lParam );
  811. }
  812. if (pcc)
  813. {
  814. Assert( hDlg == pcc->_hDlg );
  815. switch ( uMsg )
  816. {
  817. case WM_NOTIFY:
  818. return pcc->_OnNotify( wParam, lParam );
  819. case WM_COMMAND:
  820. TraceMsg( TF_WM, TEXT("WM_COMMAND\n") );
  821. pcc->_OnCommand( wParam, lParam );
  822. break;
  823. case WM_HELP:// F1
  824. {
  825. LPHELPINFO phelp = (LPHELPINFO) lParam;
  826. WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aNewClientsHelpMap );
  827. }
  828. break;
  829. case WM_CONTEXTMENU: // right mouse click
  830. WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aNewClientsHelpMap );
  831. break;
  832. case WM_ADSPROP_PAGE_GET_NOTIFY:
  833. {
  834. HWND *phwnd = (HWND *) wParam;
  835. *phwnd = pcc->_hNotify;
  836. }
  837. return TRUE;
  838. }
  839. }
  840. return FALSE;
  841. }
  842. //
  843. // PropSheetPageProc()
  844. //
  845. UINT CALLBACK
  846. THISCLASS::PropSheetPageProc(
  847. HWND hwnd,
  848. UINT uMsg,
  849. LPPROPSHEETPAGE ppsp )
  850. {
  851. TraceClsFunc( "PropSheetPageProc( " );
  852. TraceMsg( TF_FUNC, TEXT("hwnd = 0x%08x, uMsg = 0x%08x, ppsp= 0x%08x )\n"),
  853. hwnd, uMsg, ppsp );
  854. switch ( uMsg )
  855. {
  856. case PSPCB_CREATE:
  857. RETURN(TRUE); // create it
  858. break;
  859. case PSPCB_RELEASE:
  860. LPTHISCLASS pcc = (LPTHISCLASS) ppsp->lParam;
  861. delete pcc;
  862. break;
  863. }
  864. RETURN(FALSE);
  865. }
  866. // ************************************************************************
  867. //
  868. // Advanced Namimg Dialog Proc
  869. //
  870. // ************************************************************************
  871. INT_PTR CALLBACK
  872. AdvancedDlgProc(
  873. HWND hDlg,
  874. UINT uMsg,
  875. WPARAM wParam,
  876. LPARAM lParam )
  877. {
  878. //TraceMsg( TEXT("AdvancedDlgProc(") );
  879. //TraceMsg( TF_FUNC, TEXT(" hDlg = 0x%08x, uMsg = 0x%08x, wParam = 0x%08x, lParam = 0x%08x )\n"),
  880. // hDlg, uMsg, wParam, lParam );
  881. WCHAR szFormat[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  882. LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
  883. if ( uMsg == WM_INITDIALOG )
  884. {
  885. TraceMsg( TF_WM, TEXT("WM_INITDIALOG\n"));
  886. pcc = (LPTHISCLASS) lParam;
  887. SetWindowLongPtr( hDlg, GWLP_USERDATA, (LPARAM) pcc );
  888. Assert( pcc != NULL );
  889. HWND hwnd = GetDlgItem( hDlg, IDC_E_FORMAT );
  890. Edit_LimitText( hwnd, ARRAYSIZE(szFormat) - 1 );
  891. LPWSTR pszNamingPolicy = NULL;
  892. HRESULT hr = pcc->_GetCurrentNamingPolicy( &pszNamingPolicy );
  893. if (SUCCEEDED( hr ) && (hr != S_FALSE))
  894. {
  895. SetWindowText( hwnd, pszNamingPolicy );
  896. TraceFree( pszNamingPolicy );
  897. }
  898. }
  899. if (pcc)
  900. {
  901. switch ( uMsg )
  902. {
  903. case WM_COMMAND:
  904. {
  905. switch( LOWORD( wParam ) )
  906. {
  907. case IDCANCEL:
  908. if ( HIWORD( wParam ) == BN_CLICKED )
  909. {
  910. EndDialog( hDlg, LOWORD( wParam ) );
  911. return TRUE;
  912. }
  913. break;
  914. case IDOK:
  915. if ( HIWORD( wParam ) == BN_CLICKED )
  916. {
  917. WCHAR szSample[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  918. DWORD maxLength;
  919. DWORD nameError;
  920. if (!GetDlgItemText( hDlg, IDC_E_FORMAT, szFormat, ARRAYSIZE(szFormat) )) {
  921. nameError = GENNAME_TEMPLATE_INVALID;
  922. } else {
  923. nameError = GenerateSample( szFormat, szSample, &maxLength );
  924. Assert( (nameError == GENNAME_NO_ERROR) ||
  925. (nameError == GENNAME_TEMPLATE_INVALID) ||
  926. (nameError == GENNAME_NAME_TOO_LONG) );
  927. }
  928. if ( nameError == GENNAME_TEMPLATE_INVALID )
  929. {
  930. MessageBoxFromStrings( hDlg,
  931. IDS_ADVANCED_NAMING_RESTRICTIONS_TITLE,
  932. IDS_ADVANCED_NAMING_RESTRICTIONS_TEXT,
  933. MB_OK );
  934. break;
  935. }
  936. else if ( nameError == GENNAME_NAME_TOO_LONG )
  937. {
  938. LRESULT lResult = MessageBoxFromStrings( hDlg,
  939. IDS_DNS_NAME_LENGTH_WARNING_TITLE,
  940. IDS_DNS_NAME_LENGTH_WARNING_TEXT,
  941. MB_YESNO );
  942. if ( lResult == IDNO )
  943. break;
  944. }
  945. pcc->_pszCustomNamingPolicy = (LPWSTR) TraceStrDup( szFormat );
  946. EndDialog( hDlg, LOWORD( wParam ) );
  947. return TRUE;
  948. }
  949. break;
  950. case IDC_E_FORMAT:
  951. if ( HIWORD( wParam ) == EN_CHANGE )
  952. {
  953. WCHAR szSample[ DNS_MAX_LABEL_BUFFER_LENGTH ] = { L"" };
  954. DWORD maxLength;
  955. DWORD nameError;
  956. if ( !GetDlgItemText( hDlg, IDC_E_FORMAT, szFormat, ARRAYSIZE(szFormat) ) )
  957. {
  958. nameError = GENNAME_TEMPLATE_INVALID;
  959. }
  960. else
  961. {
  962. nameError = GenerateSample( szFormat, szSample, &maxLength );
  963. Assert( (nameError == GENNAME_NO_ERROR) ||
  964. (nameError == GENNAME_TEMPLATE_INVALID) ||
  965. (nameError == GENNAME_NAME_TOO_LONG) );
  966. }
  967. if ( DnsValidateDnsName_W( szSample ) != NO_ERROR ) {
  968. nameError = GENNAME_TEMPLATE_INVALID;
  969. wcscpy( szSample, UNKNOWN_INVALID_TEMPLATE );
  970. }
  971. SetDlgItemText( hDlg, IDC_E_SAMPLE, szSample );
  972. EnableWindow( GetDlgItem( hDlg, IDOK ),
  973. (BOOL)(nameError != GENNAME_TEMPLATE_INVALID) );
  974. }
  975. break;
  976. }
  977. }
  978. break; // WM_COMMAND
  979. case WM_HELP:// F1
  980. {
  981. LPHELPINFO phelp = (LPHELPINFO) lParam;
  982. WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aAdvancedHelpMap );
  983. }
  984. break;
  985. case WM_CONTEXTMENU: // right mouse click
  986. WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aAdvancedHelpMap );
  987. break;
  988. }
  989. }
  990. return FALSE;
  991. }
  992. HRESULT
  993. THISCLASS::_GetCurrentNamingPolicy( LPWSTR * ppszNamingPolicy )
  994. {
  995. TraceClsFunc( "_GetCurrentNamingPolicy( )\n" );
  996. if ( !ppszNamingPolicy )
  997. HRETURN(E_POINTER);
  998. HRESULT hr = S_OK;
  999. INT iItem = ComboBox_GetCurSel( GetDlgItem( _hDlg, IDC_CB_NAMINGPOLICY ) );
  1000. if ( iItem == - 1 )
  1001. {
  1002. *ppszNamingPolicy = NULL;
  1003. HRETURN(S_FALSE);
  1004. }
  1005. else if ( iItem == _iCustomId && _pszCustomNamingPolicy )
  1006. {
  1007. if ( *ppszNamingPolicy == _pszCustomNamingPolicy )
  1008. HRETURN(S_FALSE);
  1009. *ppszNamingPolicy = TraceStrDup( _pszCustomNamingPolicy );
  1010. if (!*ppszNamingPolicy) {
  1011. HRETURN(E_OUTOFMEMORY);
  1012. }
  1013. }
  1014. else if ( iItem != _iCustomId )
  1015. {
  1016. LPWSTR pszFormat = NULL;
  1017. LPWSTR pszNext = szSamples2;
  1018. DWORD dw;
  1019. dw = LoadString( g_hInstance, IDS_SAMPLENAMINGPOLICY, szSamples2, ARRAYSIZE( szSamples2 ) );
  1020. Assert( dw );
  1021. if (!dw) {
  1022. HRETURN(E_OUTOFMEMORY);
  1023. }
  1024. for( ; *pszNext && iItem >= 0; iItem-- )
  1025. {
  1026. // find the end of the friendly name which is terminated by a ';'
  1027. pszNext = StrChr( pszNext, L';' );
  1028. if ( !pszNext )
  1029. {
  1030. pszFormat = NULL;
  1031. break;
  1032. }
  1033. pszNext++;
  1034. pszFormat = pszNext;
  1035. // skip the internal string
  1036. pszNext = StrChr( pszNext, L';' );
  1037. if ( !pszNext )
  1038. {
  1039. pszFormat = NULL;
  1040. break;
  1041. }
  1042. // next string please...
  1043. pszNext++;
  1044. }
  1045. Assert( pszFormat );
  1046. pszNext = StrChr( pszFormat, L';' );
  1047. Assert( pszNext );
  1048. *pszNext = L'\0';
  1049. *ppszNamingPolicy = TraceStrDup( pszFormat );
  1050. }
  1051. if ( !*ppszNamingPolicy )
  1052. {
  1053. hr = E_OUTOFMEMORY;
  1054. }
  1055. HRETURN(hr);
  1056. }
  1057. typedef enum {
  1058. MOUP_SYNTACTICAL,
  1059. MOUP_LOCAL_DC,
  1060. MOUP_OTHER_DC,
  1061. MOUP_GC
  1062. } CRACK_TYPE;
  1063. HRESULT
  1064. THISCLASS::_MakeOUPretty(
  1065. DS_NAME_FORMAT inFlag,
  1066. DS_NAME_FORMAT outFlag,
  1067. LPWSTR *ppszOU )
  1068. {
  1069. TraceClsFunc("_MakeOUPretty()\n");
  1070. Assert( ppszOU );
  1071. HRESULT hr;
  1072. PDS_NAME_RESULT pResults;
  1073. DWORD dw;
  1074. HANDLE hDS;
  1075. CRACK_TYPE crackType;
  1076. //
  1077. // We might need to call DsCrackNames up to four times. The logic goes like this:
  1078. //
  1079. // Call DsCrackNames to attempt a local-only syntactical mapping.
  1080. // If that fails with DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING,
  1081. // Try the local DC.
  1082. // If can't find the local DC,
  1083. // Try the GC.
  1084. // Else if local DC failed with DS_NAME_ERROR_DOMAIN_ONLY,
  1085. // Try the DC pointed to by the local DC.
  1086. // If can't find the other DC,
  1087. // Try the GC.
  1088. //
  1089. crackType = MOUP_SYNTACTICAL;
  1090. hDS = NULL;
  1091. pResults = NULL;
  1092. while ( TRUE ) {
  1093. //
  1094. // If we have a bind handle left over from the previous pass, unbind it now.
  1095. //
  1096. if ( hDS != NULL ) {
  1097. DsUnBind( &hDS );
  1098. hDS = NULL;
  1099. }
  1100. //
  1101. // Bind to the DC or GC.
  1102. //
  1103. if ( crackType == MOUP_SYNTACTICAL ) {
  1104. hDS = NULL;
  1105. } else if ( crackType == MOUP_LOCAL_DC ) {
  1106. //
  1107. // Find a local DC.
  1108. //
  1109. PDOMAIN_CONTROLLER_INFOW pDCInfo = NULL;
  1110. dw = DsGetDcName(
  1111. NULL,
  1112. NULL,
  1113. NULL,
  1114. NULL,
  1115. DS_DIRECTORY_SERVICE_REQUIRED | DS_IP_REQUIRED,
  1116. &pDCInfo
  1117. );
  1118. if ( dw != NO_ERROR ) {
  1119. //
  1120. // Couldn't find a DC. Try the GC.
  1121. //
  1122. crackType = MOUP_GC;
  1123. continue;
  1124. }
  1125. Assert( pDCInfo != NULL );
  1126. dw = DsBind( pDCInfo->DomainControllerName, NULL, &hDS );
  1127. NetApiBufferFree( pDCInfo );
  1128. if ( dw != NO_ERROR ) {
  1129. //
  1130. // Couldn't bind to the DC. Try the GC.
  1131. //
  1132. crackType = MOUP_GC;
  1133. continue;
  1134. }
  1135. } else if ( crackType == MOUP_OTHER_DC ) {
  1136. //
  1137. // We need to talk to the DC that the local DC referred us to.
  1138. //
  1139. dw = DsBind( NULL, pResults->rItems[0].pDomain, &hDS );
  1140. if ( dw != NO_ERROR ) {
  1141. //
  1142. // Couldn't bind to the DC. Try the GC.
  1143. //
  1144. crackType = MOUP_GC;
  1145. continue;
  1146. }
  1147. } else {
  1148. //
  1149. // Bind to the GC.
  1150. //
  1151. dw = DsBind( NULL, NULL, &hDS );
  1152. if ( dw != NO_ERROR ) {
  1153. //
  1154. // Couldn't bind to the GC. Give up.
  1155. //
  1156. hr = HRESULT_FROM_WIN32( dw );
  1157. break;
  1158. }
  1159. }
  1160. //
  1161. // If we have pResults left over from a previous call, free it now.
  1162. //
  1163. if ( pResults != NULL ) {
  1164. DsFreeNameResult( pResults );
  1165. pResults = NULL;
  1166. }
  1167. //
  1168. // Try to crack the name.
  1169. //
  1170. dw = DsCrackNames( hDS,
  1171. (crackType == MOUP_SYNTACTICAL) ?
  1172. DS_NAME_FLAG_SYNTACTICAL_ONLY : DS_NAME_NO_FLAGS,
  1173. inFlag,
  1174. outFlag,
  1175. 1,
  1176. ppszOU,
  1177. &pResults );
  1178. if ( dw != NO_ERROR ) {
  1179. if ( crackType == MOUP_SYNTACTICAL ) {
  1180. //
  1181. // We were doing a syntactical check. We don't expect this to fail.
  1182. //
  1183. hr = HRESULT_FROM_WIN32( dw );
  1184. break;
  1185. } else if ( crackType == MOUP_LOCAL_DC ) {
  1186. //
  1187. // We had trouble getting to the local DC. Try the GC.
  1188. //
  1189. crackType = MOUP_GC;
  1190. continue;
  1191. } else if ( crackType == MOUP_OTHER_DC ) {
  1192. //
  1193. // We had trouble getting to the other DC. Try the GC.
  1194. //
  1195. crackType = MOUP_GC;
  1196. continue;
  1197. } else {
  1198. //
  1199. // We had trouble getting to the GC. Give up.
  1200. //
  1201. hr = HRESULT_FROM_WIN32( dw );
  1202. break;
  1203. }
  1204. } else {
  1205. Assert( pResults != NULL );
  1206. Assert( pResults->cItems == 1 );
  1207. if ( pResults->rItems[0].status == DS_NAME_NO_ERROR ) {
  1208. //
  1209. // We've got what we wanted.
  1210. //
  1211. hr = S_OK;
  1212. break;
  1213. }
  1214. if ( crackType == MOUP_SYNTACTICAL ) {
  1215. if ( pResults->rItems[0].status != DS_NAME_ERROR_NO_SYNTACTICAL_MAPPING ) {
  1216. //
  1217. // Unexpected error. Give up.
  1218. //
  1219. hr = HRESULT_FROM_WIN32( ERROR_DS_GENERIC_ERROR );
  1220. break;
  1221. }
  1222. //
  1223. // Try the local DC next.
  1224. //
  1225. crackType = MOUP_LOCAL_DC;
  1226. continue;
  1227. } else if ( crackType == MOUP_LOCAL_DC ) {
  1228. if ( pResults->rItems[0].status != DS_NAME_ERROR_DOMAIN_ONLY ) {
  1229. //
  1230. // Unexpected error. Give up.
  1231. //
  1232. hr = HRESULT_FROM_WIN32( ERROR_DS_GENERIC_ERROR );
  1233. break;
  1234. }
  1235. //
  1236. // Try the other DC next.
  1237. //
  1238. crackType = MOUP_OTHER_DC;
  1239. continue;
  1240. } else if ( crackType == MOUP_OTHER_DC ) {
  1241. //
  1242. // Unexpected error. Give up.
  1243. //
  1244. hr = HRESULT_FROM_WIN32( ERROR_DS_GENERIC_ERROR );
  1245. break;
  1246. } else {
  1247. //
  1248. // Couldn't get what we need from the GC. Give up.
  1249. //
  1250. hr = HRESULT_FROM_WIN32( ERROR_DS_GENERIC_ERROR );
  1251. break;
  1252. }
  1253. }
  1254. }
  1255. if ( hr == S_OK ) {
  1256. Assert( pResults != NULL );
  1257. Assert( pResults->cItems == 1 );
  1258. Assert( pResults->rItems[0].status == DS_NAME_NO_ERROR );
  1259. Assert( pResults->rItems[0].pName );
  1260. LPWSTR psz = TraceStrDup( pResults->rItems[0].pName );
  1261. if ( psz != NULL ) {
  1262. if (*ppszOU) {
  1263. TraceFree( *ppszOU );
  1264. *ppszOU = NULL;
  1265. }
  1266. *ppszOU = psz;
  1267. } else {
  1268. hr = E_OUTOFMEMORY;
  1269. }
  1270. }
  1271. if ( hDS != NULL ) {
  1272. DsUnBind( &hDS );
  1273. }
  1274. if ( pResults != NULL ) {
  1275. DsFreeNameResult( pResults );
  1276. }
  1277. HRETURN(hr);
  1278. }