Source code of Windows XP (NT5)
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.

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