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.

982 lines
25 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. // CLIENT.CPP - Handles the "IntelliMirror" IDD_PROP_INTELLIMIRROR_CLIENT tab
  5. //
  6. #include "pch.h"
  7. #include "client.h"
  8. #include "ccomputr.h"
  9. #include "winsock2.h"
  10. DEFINE_MODULE("IMADMUI")
  11. DEFINE_THISCLASS("CClientTab")
  12. #define THISCLASS CClientTab
  13. #define LPTHISCLASS LPCClientTab
  14. #define LDAPSTRINGNOWACKS L"LDAP://"
  15. DWORD aClientHelpMap[] = {
  16. IDC_E_GUID, HIDC_E_GUID,
  17. IDC_E_SERVERNAME, HIDC_E_SERVERNAME,
  18. IDC_B_BROWSE, HIDC_B_BROWSE,
  19. IDC_B_SERVER, HIDC_B_SERVER,
  20. NULL, NULL
  21. };
  22. //
  23. // CreateInstance()
  24. //
  25. LPVOID
  26. CClientTab_CreateInstance( void )
  27. {
  28. TraceFunc( "CClientTab_CreateInstance()\n" );
  29. LPTHISCLASS lpcc = new THISCLASS( );
  30. HRESULT hr = THR( lpcc->Init( ) );
  31. if (FAILED( hr ))
  32. {
  33. delete lpcc;
  34. RETURN(NULL);
  35. }
  36. RETURN((LPVOID) lpcc);
  37. }
  38. //
  39. // Constructor
  40. //
  41. THISCLASS::THISCLASS( ) :
  42. _hDlg(NULL),
  43. _punkComputer(NULL),
  44. _fChanged(FALSE),
  45. _hNotify(NULL)
  46. {
  47. TraceClsFunc( "CClientTab()\n" );
  48. InterlockIncrement( g_cObjects );
  49. Assert( !_punkComputer );
  50. TraceFuncExit();
  51. }
  52. //
  53. // Init()
  54. //
  55. STDMETHODIMP
  56. THISCLASS::Init( )
  57. {
  58. HRESULT hr = S_OK;
  59. TraceClsFunc( "Init()\n" );
  60. HRETURN(hr);
  61. }
  62. //
  63. // Destructor
  64. //
  65. THISCLASS::~THISCLASS( )
  66. {
  67. TraceClsFunc( "~CClientTab()\n" );
  68. // Private Members
  69. if ( _punkComputer )
  70. _punkComputer->Release( ); // matching AddRef() in AddPages()
  71. // tell ADS to destroy the notify object
  72. // NOTE: Another property page may do this before us. Ignore the error.
  73. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_EXIT, 0, 0 );
  74. InterlockDecrement( g_cObjects );
  75. TraceFuncExit();
  76. };
  77. // *************************************************************************
  78. //
  79. // ITab
  80. //
  81. // *************************************************************************
  82. //
  83. // AddPages( )
  84. //
  85. STDMETHODIMP
  86. THISCLASS::AddPages(
  87. LPFNADDPROPSHEETPAGE lpfnAddPage,
  88. LPARAM lParam,
  89. LPUNKNOWN punk )
  90. {
  91. TraceClsFunc( "AddPages( )\n" );
  92. HRESULT hr = S_OK;
  93. PROPSHEETPAGE psp;
  94. HPROPSHEETPAGE hpage;
  95. psp.dwSize = sizeof(psp);
  96. psp.dwFlags = PSP_USEREFPARENT | PSP_USECALLBACK;
  97. psp.hInstance = (HINSTANCE) g_hInstance;
  98. psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_INTELLIMIRROR_CLIENT);
  99. psp.pcRefParent = (UINT *) &g_cObjects;
  100. psp.pfnCallback = (LPFNPSPCALLBACK) PropSheetPageProc;
  101. psp.pfnDlgProc = PropSheetDlgProc;
  102. psp.lParam = (LPARAM) this;
  103. hpage = CreatePropertySheetPage( &psp );
  104. if ( hpage )
  105. {
  106. if ( !lpfnAddPage( hpage, lParam ) )
  107. {
  108. DestroyPropertySheetPage( hpage );
  109. hr = THR(E_FAIL);
  110. goto Error;
  111. }
  112. }
  113. punk->AddRef( ); // matching Release in the destructor
  114. _punkComputer = punk;
  115. Error:
  116. HRETURN(hr);
  117. }
  118. //
  119. // ReplacePage()
  120. //
  121. STDMETHODIMP
  122. THISCLASS::ReplacePage(
  123. UINT uPageID,
  124. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  125. LPARAM lParam,
  126. LPUNKNOWN punk )
  127. {
  128. TraceClsFunc( "ReplacePage( ) *** NOT_IMPLEMENTED ***\n" );
  129. RETURN(E_NOTIMPL);
  130. }
  131. //
  132. // QueryInformation( )
  133. //
  134. STDMETHODIMP
  135. THISCLASS::QueryInformation(
  136. LPWSTR pszAttribute,
  137. LPWSTR * pszResult )
  138. {
  139. TraceClsFunc( "QueryInformation( )\n" );
  140. HRETURN(E_NOTIMPL);
  141. }
  142. //
  143. // AllowActivation( )
  144. //
  145. STDMETHODIMP
  146. THISCLASS::AllowActivation(
  147. BOOL * pfAllow )
  148. {
  149. TraceClsFunc( "AllowActivation( )\n" );
  150. HRETURN(E_NOTIMPL);
  151. }
  152. // ************************************************************************
  153. //
  154. // Property Sheet Functions
  155. //
  156. // ************************************************************************
  157. //
  158. // PropSheetDlgProc()
  159. //
  160. INT_PTR CALLBACK
  161. THISCLASS::PropSheetDlgProc(
  162. HWND hDlg,
  163. UINT uMsg,
  164. WPARAM wParam,
  165. LPARAM lParam )
  166. {
  167. //TraceMsg( TEXT("PropSheetDlgProc(") );
  168. //TraceMsg( TF_FUNC, TEXT(" hDlg = 0x%08x, uMsg = 0x%08x, wParam = 0x%08x, lParam = 0x%08x )\n"),
  169. // hDlg, uMsg, wParam, lParam );
  170. LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
  171. if ( uMsg == WM_INITDIALOG )
  172. {
  173. TraceMsg( TF_WM, TEXT("WM_INITDIALOG\n"));
  174. LPPROPSHEETPAGE psp = (LPPROPSHEETPAGE) lParam;
  175. SetWindowLongPtr( hDlg, GWLP_USERDATA, psp->lParam );
  176. pcc = (LPTHISCLASS) psp->lParam;
  177. pcc->_InitDialog( hDlg, lParam );
  178. }
  179. if (pcc)
  180. {
  181. Assert( hDlg == pcc->_hDlg );
  182. switch ( uMsg )
  183. {
  184. case WM_NOTIFY:
  185. return pcc->_OnNotify( wParam, lParam );
  186. case WM_COMMAND:
  187. TraceMsg( TF_WM, TEXT("WM_COMMAND\n") );
  188. pcc->_OnCommand( wParam, lParam );
  189. break;
  190. case WM_HELP:// F1
  191. {
  192. LPHELPINFO phelp = (LPHELPINFO) lParam;
  193. WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aClientHelpMap );
  194. }
  195. break;
  196. case WM_CONTEXTMENU: // right mouse click
  197. WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aClientHelpMap );
  198. break;
  199. case WM_ADSPROP_PAGE_GET_NOTIFY:
  200. HWND *phwnd = (HWND *) wParam;
  201. *phwnd = pcc->_hNotify;
  202. return TRUE;
  203. }
  204. }
  205. return FALSE;
  206. }
  207. //
  208. // PropSheetPageProc()
  209. //
  210. UINT CALLBACK
  211. THISCLASS::PropSheetPageProc(
  212. HWND hwnd,
  213. UINT uMsg,
  214. LPPROPSHEETPAGE ppsp )
  215. {
  216. TraceClsFunc( "PropSheetPageProc( " );
  217. TraceMsg( TF_FUNC, TEXT("hwnd = 0x%08x, uMsg = 0x%08x, ppsp= 0x%08x )\n"),
  218. hwnd, uMsg, ppsp );
  219. switch ( uMsg )
  220. {
  221. case PSPCB_CREATE:
  222. RETURN(TRUE); // create it
  223. break;
  224. case PSPCB_RELEASE:
  225. LPTHISCLASS pcc = (LPTHISCLASS) ppsp->lParam;
  226. delete pcc;
  227. break;
  228. }
  229. RETURN(FALSE);
  230. }
  231. //
  232. // _InitDialog( )
  233. //
  234. HRESULT
  235. THISCLASS::_InitDialog(
  236. HWND hDlg,
  237. LPARAM lParam )
  238. {
  239. TraceClsFunc( "_InitDialog( )\n" );
  240. HRESULT hr;
  241. IMAO * pmao;
  242. BOOL fAdmin;
  243. HWND hwndGuid;
  244. HWND hwndServer;
  245. LPWSTR pszServerName = NULL;
  246. LPWSTR pszGUID = NULL;
  247. CWaitCursor Wait;
  248. _hDlg = hDlg;
  249. _fChanged = TRUE; // prevent turning on the Apply button early
  250. hwndGuid = GetDlgItem( _hDlg, IDC_E_GUID );
  251. hwndServer = GetDlgItem( _hDlg, IDC_E_SERVERNAME );
  252. Edit_LimitText( hwndGuid, MAX_INPUT_GUID_STRING - 1 );
  253. Edit_LimitText( hwndServer, DNS_MAX_NAME_BUFFER_LENGTH - 1 );
  254. // retrieve values
  255. hr = THR( _punkComputer->QueryInterface( IID_IMAO, (void**) &pmao ) );
  256. if (FAILED( hr ))
  257. goto Error;
  258. hr = THR( pmao->GetNotifyWindow( &_hNotify ) );
  259. if (FAILED( hr ))
  260. goto Error;
  261. ADsPropSetHwnd( _hNotify, _hDlg );
  262. hr = THR( pmao->IsAdmin( &fAdmin ) );
  263. EnableWindow( hwndGuid, fAdmin );
  264. EnableWindow( hwndServer, fAdmin );
  265. EnableWindow( GetDlgItem( _hDlg, IDC_B_BROWSE ), fAdmin );
  266. hr = pmao->GetServerName( &pszServerName );
  267. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  268. goto Error;
  269. Assert( SUCCEEDED(hr) || pszServerName == NULL );
  270. hr = THR( pmao->GetGUID( &pszGUID, NULL ) );
  271. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  272. goto Error;
  273. Assert( SUCCEEDED(hr) || pszGUID == NULL );
  274. if ( pszGUID )
  275. {
  276. SetWindowText( hwndGuid, pszGUID );
  277. }
  278. else
  279. {
  280. SetWindowText( hwndGuid, L"" );
  281. }
  282. if ( pszServerName )
  283. {
  284. SetWindowText( hwndServer, pszServerName );
  285. EnableWindow( GetDlgItem( _hDlg, IDC_B_SERVER ), fAdmin );
  286. }
  287. else
  288. {
  289. SetWindowText( hwndServer, L"" );
  290. }
  291. hr = S_OK;
  292. Cleanup:
  293. if ( pmao )
  294. pmao->Release( );
  295. if ( pszGUID )
  296. TraceFree( pszGUID );
  297. if ( pszServerName )
  298. TraceFree( pszServerName );
  299. _fChanged = FALSE;
  300. HRETURN(hr);
  301. Error:
  302. MessageBoxFromHResult( _hDlg, IDS_ERROR_READINGCOMPUTERACCOUNT, hr );
  303. goto Cleanup;
  304. }
  305. //
  306. // _OnCommand( )
  307. //
  308. HRESULT
  309. THISCLASS::_OnCommand( WPARAM wParam, LPARAM lParam )
  310. {
  311. TraceClsFunc( "_OnCommand( " );
  312. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  313. HRESULT hr;
  314. BOOL fAdmin;
  315. BOOL fChanged = FALSE;
  316. IMAO * pmao;
  317. HWND hwnd = (HWND) lParam;
  318. hr = THR( _punkComputer->QueryInterface( IID_IMAO, (void**) &pmao ) );
  319. if (FAILED( hr ))
  320. goto Error;
  321. switch( LOWORD(wParam) )
  322. {
  323. case IDC_E_SERVERNAME:
  324. if ( HIWORD(wParam) == EN_CHANGE )
  325. {
  326. LRESULT iLength = GetWindowTextLength( (HWND) lParam );
  327. EnableWindow( GetDlgItem( _hDlg, IDC_B_SERVER ), !!iLength );
  328. fChanged = TRUE;
  329. }
  330. break;
  331. case IDC_E_GUID:
  332. if ( HIWORD(wParam) == EN_CHANGE )
  333. {
  334. fChanged = TRUE;
  335. }
  336. break;
  337. case IDC_B_SERVER:
  338. if ( HIWORD( wParam ) == BN_CLICKED )
  339. {
  340. _JumpToServer( TRUE );
  341. }
  342. break;
  343. case IDC_B_BROWSE:
  344. if ( HIWORD( wParam ) == BN_CLICKED )
  345. {
  346. hr = _OnSearch( _hDlg );
  347. }
  348. break;
  349. }
  350. //
  351. // Update apply button as needed
  352. //
  353. if ( fChanged )
  354. {
  355. if ( !_fChanged )
  356. {
  357. _fChanged = TRUE; // indicates we need to save changes
  358. PropSheet_Changed( GetParent( _hDlg ), _hDlg );
  359. }
  360. }
  361. Error:
  362. HRETURN(hr);
  363. }
  364. HRESULT
  365. THISCLASS::_OnSearch(
  366. HWND hDlg )
  367. {
  368. TraceClsFunc( "_OnSearch( )\n" );
  369. HRESULT hr = E_FAIL;
  370. DSQUERYINITPARAMS dqip;
  371. OPENQUERYWINDOW oqw;
  372. LPDSOBJECTNAMES pDsObjects;
  373. VARIANT var;
  374. ICommonQuery * pCommonQuery = NULL;
  375. IDataObject *pdo;
  376. VariantInit( &var );
  377. hr = THR( CoCreateInstance( CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_ICommonQuery, (PVOID *)&pCommonQuery) );
  378. if (FAILED(hr)) {
  379. goto Error;
  380. }
  381. ZeroMemory( &dqip, sizeof(dqip) );
  382. dqip.cbStruct = sizeof(dqip);
  383. dqip.dwFlags = DSQPF_NOSAVE | DSQPF_SHOWHIDDENOBJECTS | DSQPF_ENABLEADMINFEATURES;
  384. dqip.dwFlags |= DSQPF_ENABLEADVANCEDFEATURES;
  385. ZeroMemory( &oqw, sizeof(oqw) );
  386. oqw.cbStruct = sizeof(oqw);
  387. oqw.dwFlags = OQWF_SHOWOPTIONAL | OQWF_ISSUEONOPEN
  388. | OQWF_REMOVESCOPES | OQWF_REMOVEFORMS
  389. | OQWF_DEFAULTFORM | OQWF_OKCANCEL | OQWF_SINGLESELECT;
  390. oqw.clsidHandler = CLSID_DsQuery;
  391. oqw.pHandlerParameters = &dqip;
  392. oqw.clsidDefaultForm = CLSID_RISrvQueryForm;
  393. hr = pCommonQuery->OpenQueryWindow( hDlg, &oqw, &pdo);
  394. if ( SUCCEEDED(hr) && pdo) {
  395. FORMATETC fmte = {
  396. (CLIPFORMAT)g_cfDsObjectNames,
  397. NULL,
  398. DVASPECT_CONTENT,
  399. -1,
  400. TYMED_HGLOBAL};
  401. STGMEDIUM medium = { TYMED_HGLOBAL, NULL, NULL };
  402. //
  403. // Retrieve the result from the IDataObject,
  404. // in this case CF_DSOBJECTNAMES (dsclient.h)
  405. // is needed because it describes
  406. // the objects which were selected by the user.
  407. //
  408. hr = pdo->GetData(&fmte, &medium);
  409. if ( SUCCEEDED(hr) ) {
  410. DSOBJECTNAMES *pdon = (DSOBJECTNAMES*)GlobalLock(medium.hGlobal);
  411. PWSTR p,FQDN;
  412. //
  413. // we want the name of the computer object that was selected.
  414. // crack the DSOBJECTNAMES structure to get this data,
  415. // convert it into a version that the user can view, and set the
  416. // dialog text to this data.
  417. //
  418. if ( pdon ) {
  419. Assert( pdon->cItems == 1);
  420. p = (PWSTR)((ULONG_PTR)pdon + (ULONG_PTR)pdon->aObjects[0].offsetName);
  421. if (p && (p = wcsstr(p, L"LDAP://"))) {
  422. p += 6;
  423. if ((p = wcsstr(p, L"/CN="))) {
  424. p += 1;
  425. hr = DNtoFQDNEx( p, &FQDN);
  426. if (SUCCEEDED(hr)) {
  427. SetDlgItemText( hDlg, IDC_E_SERVERNAME, FQDN );
  428. TraceFree( FQDN );
  429. }
  430. }
  431. }
  432. GlobalUnlock(medium.hGlobal);
  433. }
  434. }
  435. ReleaseStgMedium(&medium);
  436. pdo->Release();
  437. }
  438. Error:
  439. if ( pCommonQuery )
  440. pCommonQuery->Release();
  441. if (FAILED(hr)) {
  442. MessageBoxFromStrings(
  443. hDlg,
  444. IDS_PROBLEM_SEARCHING_TITLE,
  445. IDS_PROBLEM_SEARCHING_TEXT,
  446. MB_ICONEXCLAMATION );
  447. }
  448. HRETURN(hr);
  449. }
  450. //
  451. // _ApplyChanges( )
  452. //
  453. HRESULT
  454. THISCLASS::_ApplyChanges( )
  455. {
  456. TraceClsFunc( "_ApplyChanges( )\n" );
  457. if ( !_fChanged )
  458. HRESULT(S_OK); // nothing to do
  459. HRESULT hr = S_OK;
  460. IMAO *pmao = NULL;
  461. WCHAR szGuid[ MAX_INPUT_GUID_STRING ];
  462. WCHAR szServerName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  463. INT iLength;
  464. HWND hwndServer = GetDlgItem( _hDlg, IDC_E_SERVERNAME );
  465. HWND hwndGuid = GetDlgItem( _hDlg, IDC_E_GUID );
  466. HWND eWnd;
  467. LPWSTR pszGuid = NULL;
  468. CWaitCursor Wait;
  469. eWnd = hwndGuid;
  470. hr = THR( _punkComputer->QueryInterface( IID_IMAO, (void**) &pmao ) );
  471. if (FAILED( hr ))
  472. goto Error;
  473. iLength = GetWindowText( hwndGuid, szGuid, ARRAYSIZE( szGuid ) );
  474. Assert( iLength <= ARRAYSIZE( szGuid ) );
  475. if ( iLength == 0 )
  476. {
  477. hr = THR( pmao->GetGUID( &pszGuid, NULL ) );
  478. if (FAILED( hr ) && hr != E_ADS_PROPERTY_NOT_FOUND )
  479. goto Error;
  480. Assert( SUCCEEDED(hr) || pszGuid == NULL );
  481. if ( pszGuid != NULL )
  482. {
  483. LRESULT iResult = MessageBoxFromStrings( _hDlg, IDS_REMOVING_GUID_TITLE, IDS_REMOVING_GUID_TEXT, MB_YESNO );
  484. if ( iResult == IDYES )
  485. {
  486. hr = THR( pmao->SetGUID( NULL ) );
  487. if (FAILED( hr ))
  488. goto Error;
  489. }
  490. else
  491. { // reset the GUID
  492. SetWindowText( hwndGuid, pszGuid );
  493. hr = E_FAIL;
  494. goto Cleanup;
  495. }
  496. }
  497. }
  498. else
  499. {
  500. hr = ValidateGuid( szGuid, NULL, NULL );
  501. if ( hr != S_OK )
  502. {
  503. hr = HRESULT_FROM_WIN32( ERROR_INVALID_DATA );
  504. goto InvalidGuid;
  505. }
  506. hr = THR( pmao->SetGUID( szGuid ) );
  507. if (FAILED( hr ))
  508. goto Error;
  509. }
  510. iLength = GetWindowText( hwndServer, szServerName, ARRAYSIZE( szServerName ) );
  511. Assert( iLength <= ARRAYSIZE( szServerName ) );
  512. if (iLength != 0) {
  513. hr = _JumpToServer( FALSE );
  514. if( FAILED(hr) ){
  515. // Well, server name invalid. Stop and return false.
  516. eWnd = hwndServer;
  517. goto Error;
  518. }
  519. hr = THR( pmao->SetServerName( szServerName ) );
  520. if (FAILED( hr ))
  521. goto Error;
  522. } else {
  523. hr = THR( pmao->SetServerName( NULL ) );
  524. if (FAILED( hr ))
  525. goto Error;
  526. }
  527. hr = THR( pmao->CommitChanges( ) );
  528. if (FAILED( hr ))
  529. goto Error;
  530. _fChanged = FALSE; // reset
  531. hr = S_OK;
  532. Cleanup:
  533. if ( pszGuid )
  534. TraceFree( pszGuid );
  535. if ( pmao )
  536. pmao->Release( );
  537. // Tell DSA that someone hit the Apply
  538. SendMessage( _hNotify, WM_ADSPROP_NOTIFY_APPLY, !!SUCCEEDED( hr ), 0 );
  539. HRETURN(hr);
  540. Error:
  541. SetFocus( eWnd );
  542. if ( eWnd == hwndGuid ) {
  543. MessageBoxFromHResult( _hDlg, IDS_ERROR_WRITINGTOCOMPUTERACCOUNT, hr );
  544. }
  545. goto Cleanup;
  546. InvalidGuid:
  547. SetFocus( hwndGuid );
  548. MessageBoxFromStrings( NULL, IDS_INVALID_GUID_CAPTION, IDS_INVALID_GUID_TEXT, MB_OK );
  549. goto Cleanup;
  550. }
  551. //
  552. // _OnNotify( )
  553. //
  554. INT
  555. THISCLASS::_OnNotify(
  556. WPARAM wParam,
  557. LPARAM lParam )
  558. {
  559. TraceClsFunc( "_OnNotify( " );
  560. TraceMsg( TF_FUNC, "wParam = 0x%08x, lParam = 0x%08x )\n", wParam, lParam );
  561. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  562. switch( lpnmhdr->code )
  563. {
  564. case PSN_APPLY:
  565. {
  566. HRESULT hr;
  567. CWaitCursor *Wait;
  568. Wait = new CWaitCursor();
  569. TraceMsg( TF_WM, TEXT("WM_NOTIFY: PSN_APPLY\n"));
  570. hr = _ApplyChanges( );
  571. if (Wait) {
  572. delete Wait;
  573. Wait = NULL;
  574. }
  575. SetWindowLongPtr( _hDlg, DWLP_MSGRESULT, ( SUCCEEDED(hr) ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE ));
  576. RETURN(TRUE);
  577. }
  578. break;
  579. default:
  580. break;
  581. }
  582. RETURN(FALSE);
  583. }
  584. HRESULT
  585. THISCLASS::_JumpToServer(
  586. BOOLEAN ShowProperties
  587. )
  588. {
  589. HRESULT hr = E_FAIL;
  590. WCHAR szServerName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  591. IDataObject *pido = NULL;
  592. ULONG ulSize = 0;
  593. CWaitCursor *Wait;
  594. const WCHAR cszFilter[] = L"(&(objectCategory=computer)(servicePrincipalName=host/%s%s))";
  595. const WCHAR samname[] = L"samaccountname";
  596. LPCWSTR patterns[] = {L""};
  597. CHAR mbszServerName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  598. // Later to do pattern matching searches on the dnsHostName or Netbios name
  599. // expand the above arrays. See the for loop for details.
  600. ULONG index;
  601. WCHAR *pStart;
  602. WCHAR *pEnd;
  603. LPWSTR pszFilter = NULL;
  604. IADsContainer *pads = NULL;
  605. IEnumVARIANT *penum = NULL;
  606. ADS_SEARCH_COLUMN adsColumn; // this needs to be freed
  607. ADS_SEARCH_HANDLE adsHandle = NULL;
  608. IDirectorySearch *pds = NULL;
  609. LPWSTR ComputerAttrs[] = { DISTINGUISHEDNAME, NETBOOTSAP };
  610. BOOL badsColumnValid = FALSE;
  611. ULONG uFetched;
  612. VARIANT varEnum;
  613. size_t len;
  614. HOSTENT *hent;
  615. TraceClsFunc("_JumpToServer( )\n");
  616. Wait = new CWaitCursor();
  617. if (!GetDlgItemText( _hDlg, IDC_E_SERVERNAME, szServerName, ARRAYSIZE(szServerName) )) {
  618. hr = E_INVALIDARG;
  619. goto Error;
  620. }
  621. hr = _IsValidRISServer( szServerName );
  622. if ( FAILED( hr )) {
  623. goto Error;
  624. }
  625. if (ShowProperties) {
  626. VariantInit( &varEnum );
  627. //
  628. // get the full DN of the machine.
  629. //
  630. len = wcstombs( mbszServerName, szServerName, ARRAYSIZE( mbszServerName ) );
  631. if ( !len ) {
  632. goto Error;
  633. }
  634. hent = gethostbyname( mbszServerName );
  635. if (!hent) {
  636. goto Error;
  637. }
  638. len = mbstowcs( szServerName, hent->h_name, strlen( hent->h_name ) );
  639. if ( !len ) {
  640. goto Error;
  641. }
  642. szServerName[len] = L'\0';
  643. // Build the filter
  644. pszFilter = (LPWSTR) TraceAllocString( LPTR, ARRAYSIZE(cszFilter) + wcslen(szServerName)
  645. + ARRAYSIZE(samname) + 2 ); // size of the longest
  646. if ( !pszFilter ) {
  647. hr = E_OUTOFMEMORY;
  648. goto Error;
  649. }
  650. hr = THR( ADsOpenObject( L"LDAP:", NULL, NULL, ADS_SECURE_AUTHENTICATION, IID_IADsContainer, (LPVOID *) &pads ) );
  651. if (FAILED( hr ))
  652. goto Error;
  653. hr = THR( ADsBuildEnumerator( pads, &penum ) );
  654. if (FAILED( hr ))
  655. goto Error;
  656. hr = THR( ADsEnumerateNext( penum, 1, &varEnum, &uFetched ) );
  657. if (FAILED( hr ))
  658. goto Error;
  659. if ( hr == S_FALSE )
  660. goto Cleanup; // hum...
  661. Assert( uFetched == 1 || varEnum.vt == VT_DISPATCH || varEnum.pdispVal != NULL );
  662. hr = THR( varEnum.pdispVal->QueryInterface( IID_IDirectorySearch, (void**)&pds) );
  663. if (FAILED( hr ))
  664. goto Error;
  665. for ( index = 0; index < ARRAYSIZE(patterns); index ++ ) {
  666. wsprintf( pszFilter, cszFilter, szServerName,patterns[index] );
  667. DebugMsg( "Filter = '%s'\n", pszFilter );
  668. hr = THR( pds->ExecuteSearch( pszFilter, ComputerAttrs, ARRAYSIZE(ComputerAttrs), &adsHandle ) );
  669. if (FAILED( hr ))
  670. continue;
  671. do{
  672. hr = THR( pds->GetNextRow( adsHandle ) );
  673. if (FAILED( hr ) || ( hr == S_ADS_NOMORE_ROWS ) ) {
  674. if ( adsHandle )
  675. pds->CloseSearchHandle( adsHandle );
  676. adsHandle = NULL;
  677. break;
  678. }
  679. hr = THR( pds->GetColumn( adsHandle, ComputerAttrs[1], &adsColumn ) );
  680. if (FAILED( hr )){
  681. continue;
  682. }
  683. if ( pds ) {
  684. hr = THR( pds->FreeColumn( &adsColumn ) );
  685. }
  686. hr = THR( pds->GetColumn( adsHandle, ComputerAttrs[0], &adsColumn ) );
  687. if (FAILED( hr )){
  688. continue;
  689. }
  690. Assert( adsColumn.dwADsType == ADSTYPE_DN_STRING );
  691. Assert( adsColumn.pADsValues->dwType == ADSTYPE_DN_STRING );
  692. Assert( adsColumn.pADsValues->DNString );
  693. badsColumnValid = TRUE;
  694. break;
  695. } while ( TRUE );
  696. if ( badsColumnValid ) {
  697. break;
  698. }
  699. }
  700. if (index == ARRAYSIZE( patterns ) ) {
  701. goto Error;
  702. }
  703. hr = THR( _punkComputer->QueryInterface( IID_IDataObject, (LPVOID *) &pido ) );
  704. if (FAILED( hr ))
  705. goto Error;
  706. if (Wait) {
  707. delete Wait;
  708. Wait = NULL;
  709. }
  710. hr = THR( PostADsPropSheet( adsColumn.pADsValues->DNString, pido, _hDlg, FALSE) );
  711. // PostADsPropSheet should put up its own errors
  712. }
  713. Cleanup:
  714. if (Wait) {
  715. delete Wait;
  716. Wait = NULL;
  717. }
  718. if ( pido )
  719. pido->Release( );
  720. if ( pszFilter )
  721. TraceFree( pszFilter );
  722. if ( pads )
  723. pads->Release( );
  724. if ( penum )
  725. ADsFreeEnumerator( penum );
  726. if ( pds && badsColumnValid ) {
  727. hr = THR( pds->FreeColumn( &adsColumn ) );
  728. }
  729. if ( pds && adsHandle ) {
  730. hr = THR( pds->CloseSearchHandle( adsHandle ) );
  731. }
  732. if ( pds )
  733. pds->Release();
  734. HRETURN(hr);
  735. Error:
  736. if (Wait) {
  737. delete Wait;
  738. Wait = NULL;
  739. }
  740. if ( ShowProperties ){
  741. MessageBoxFromStrings(
  742. _hDlg,
  743. IDS_PROBLEM_FINDING_SERVER_TITLE,
  744. IDS_PROBLEM_FINDING_SERVER_TEXT,
  745. MB_OK | MB_ICONWARNING );
  746. } else {
  747. int retVal = MessageBoxFromStrings(
  748. _hDlg,
  749. IDS_PROBLEM_FINDING_SERVER_TITLE,
  750. IDS_PROBLEM_FINDING_SERVER_CONFIRM_TEXT,
  751. MB_YESNO | MB_ICONWARNING);
  752. hr = (retVal == IDYES)?S_OK:E_ADS_BAD_PARAMETER;
  753. }
  754. goto Cleanup;
  755. }
  756. HRESULT
  757. THISCLASS::_IsValidRISServer(
  758. IN LPCWSTR ServerName
  759. )
  760. /*++
  761. Routine Description:
  762. Validates if the specified server name points to a valid RIS server.
  763. Arguments:
  764. ServerName - name of the server to validate
  765. Return Value:
  766. HRESULT indicating outcome.
  767. (S_OK indicates that the server is a valid RIS server).
  768. --*/
  769. {
  770. HRESULT hr = E_FAIL;
  771. CHAR mbszServerName[ DNS_MAX_NAME_BUFFER_LENGTH +1];
  772. size_t len;
  773. PHOSTENT hent;
  774. WCHAR ServerShare[MAX_PATH];
  775. TraceClsFunc("_IsValidRISServer( )\n");
  776. Assert( wcslen(ServerName) <= DNS_MAX_NAME_BUFFER_LENGTH );
  777. //
  778. // Do a DNS Lookup of the server as a first check to ensure it's a
  779. // valid name.
  780. //
  781. len = wcstombs( mbszServerName, ServerName, ARRAYSIZE( mbszServerName ) );
  782. if ( !len ) {
  783. goto e0;
  784. }
  785. hent = gethostbyname( mbszServerName );
  786. if (!hent) {
  787. goto e0;
  788. }
  789. //
  790. // OK, we know the server actually resolves to a computer name. Let's search
  791. // for \\servername\reminst share. If this succeeds, we assume the server
  792. // is a valid remote install server
  793. //
  794. if (_snwprintf(
  795. ServerShare,
  796. ARRAYSIZE(ServerShare),
  797. L"\\\\%s\\reminst\\oschooser",
  798. ServerName) < 0 ||
  799. GetFileAttributes(ServerShare) == -1) {
  800. goto e0;
  801. }
  802. hr = S_OK;
  803. e0:
  804. HRETURN(hr);
  805. }