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.

626 lines
15 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. //
  5. // SERVERQY.CPP - The RIS server query form
  6. //
  7. #include "pch.h"
  8. #include "serverqy.h"
  9. #include "mangdlg.h"
  10. DEFINE_MODULE("IMADMUI")
  11. DEFINE_THISCLASS("CRISrvQueryForm")
  12. #define THISCLASS CRISrvQueryForm
  13. #define LPTHISCLASS LPCRISrvQueryForm
  14. #define FILTER_QUERY_SERVER L"(&(objectClass=computer)(netbootSCPBL=*)(CN=%s))"
  15. #define StringByteCopy(pDest, iOffset, sz) \
  16. { memcpy(&(((LPBYTE)pDest)[iOffset]), sz, StringByteSize(sz)); }
  17. #define StringByteSize(sz) \
  18. ((lstrlen(sz)+1)*sizeof(TCHAR))
  19. DWORD aSrvQueryHelpMap[] = {
  20. IDC_E_SERVER, HIDC_E_SERVER,
  21. NULL, NULL
  22. };
  23. //
  24. // CRISrvQueryForm_CreateInstance( )
  25. //
  26. LPVOID
  27. CRISrvQueryForm_CreateInstance( void )
  28. {
  29. TraceFunc( "CRISrvQueryForm_CreateInstance()\n" );
  30. LPTHISCLASS lpcc = new THISCLASS( );
  31. if ( !lpcc ) {
  32. RETURN(lpcc);
  33. }
  34. HRESULT hr = THR( lpcc->Init( ) );
  35. if ( hr )
  36. {
  37. delete lpcc;
  38. RETURN(NULL);
  39. }
  40. RETURN(lpcc);
  41. }
  42. //
  43. // Constructor
  44. //
  45. THISCLASS::THISCLASS( )
  46. {
  47. TraceClsFunc( "CRISrvQueryForm( )\n" );
  48. InterlockIncrement( g_cObjects );
  49. TraceFuncExit();
  50. }
  51. //
  52. // Init( )
  53. //
  54. HRESULT
  55. THISCLASS::Init( )
  56. {
  57. TraceClsFunc( "Init( )\n" );
  58. HRESULT hr;
  59. // IUnknown stuff
  60. BEGIN_QITABLE_IMP( CRISrvQueryForm, IQueryForm );
  61. QITABLE_IMP( IQueryForm );
  62. END_QITABLE_IMP( CRISrvQueryForm );
  63. Assert( _cRef == 0);
  64. AddRef( );
  65. hr = CheckClipboardFormats( );
  66. HRETURN(hr);
  67. }
  68. //
  69. // Destructor
  70. //
  71. THISCLASS::~THISCLASS( )
  72. {
  73. TraceClsFunc( "~CRISrvQueryForm( )\n" );
  74. InterlockDecrement( g_cObjects );
  75. TraceFuncExit();
  76. }
  77. // ************************************************************************
  78. //
  79. // IUnknown
  80. //
  81. // ************************************************************************
  82. //
  83. // QueryInterface()
  84. //
  85. STDMETHODIMP
  86. THISCLASS::QueryInterface(
  87. REFIID riid,
  88. LPVOID *ppv )
  89. {
  90. TraceClsFunc( "" );
  91. HRESULT hr = ::QueryInterface( this, _QITable, riid, ppv );
  92. QIRETURN( hr, riid );
  93. }
  94. //
  95. // AddRef()
  96. //
  97. STDMETHODIMP_(ULONG)
  98. THISCLASS::AddRef( void )
  99. {
  100. TraceClsFunc( "[IUnknown] AddRef( )\n" );
  101. InterlockIncrement( _cRef );
  102. RETURN(_cRef);
  103. }
  104. //
  105. // Release()
  106. //
  107. STDMETHODIMP_(ULONG)
  108. THISCLASS::Release( void )
  109. {
  110. TraceClsFunc( "[IUnknown] Release( )\n" );
  111. InterlockDecrement( _cRef );
  112. if ( _cRef )
  113. RETURN(_cRef);
  114. TraceDo( delete this );
  115. RETURN(0);
  116. }
  117. // ************************************************************************
  118. //
  119. // IQueryForm
  120. //
  121. // ************************************************************************
  122. //
  123. // Initialize( )
  124. //
  125. STDMETHODIMP
  126. THISCLASS::Initialize(
  127. HKEY hkForm)
  128. {
  129. TraceClsFunc( "[IQueryForm] Initialize( )\n" );
  130. HRETURN(S_OK);
  131. }
  132. //
  133. // SetObject( )
  134. //
  135. STDMETHODIMP
  136. THISCLASS::AddForms(
  137. LPCQADDFORMSPROC pAddFormsProc,
  138. LPARAM lParam )
  139. {
  140. TraceClsFunc( "[IQueryForm] AddForms(" );
  141. TraceMsg( TF_FUNC, " pAddFormsProc = 0x%p, lParam = 0x%p )\n", pAddFormsProc, lParam );
  142. if ( !pAddFormsProc )
  143. HRETURN(E_INVALIDARG);
  144. HRESULT hr = S_OK;
  145. CQFORM cqf;
  146. WCHAR szTitle[ 255 ];
  147. DWORD dw;
  148. dw = LoadString( g_hInstance, IDS_REMOTE_INSTALL_SERVERS, szTitle, ARRAYSIZE(szTitle) );
  149. Assert(dw);
  150. ZeroMemory( &cqf, sizeof(cqf) );
  151. cqf.cbStruct = sizeof(cqf);
  152. cqf.dwFlags = CQFF_ISOPTIONAL;
  153. cqf.clsid = CLSID_RISrvQueryForm;
  154. cqf.pszTitle = szTitle;
  155. hr = THR( pAddFormsProc(lParam, &cqf) );
  156. HRETURN(hr);
  157. }
  158. //
  159. // AddPages( )
  160. //
  161. STDMETHODIMP
  162. THISCLASS::AddPages(
  163. LPCQADDPAGESPROC pAddPagesProc,
  164. LPARAM lParam)
  165. {
  166. TraceClsFunc( "[IQueryForm] AddPages(" );
  167. TraceMsg( TF_FUNC, " pAddPagesProc = 0x%p, lParam = 0x%p )\n", pAddPagesProc, lParam );
  168. if ( !pAddPagesProc )
  169. HRETURN(E_INVALIDARG);
  170. HRESULT hr = S_OK;
  171. CQPAGE cqp;
  172. cqp.cbStruct = sizeof(cqp);
  173. cqp.dwFlags = 0x0;
  174. cqp.pPageProc = (LPCQPAGEPROC) PropSheetPageProc;
  175. cqp.hInstance = g_hInstance;
  176. cqp.idPageName = IDS_REMOTE_INSTALL_SERVERS;
  177. cqp.idPageTemplate = IDD_SERVER_QUERY_FORM;
  178. cqp.pDlgProc = PropSheetDlgProc;
  179. cqp.lParam = (LPARAM)this;
  180. hr = THR( pAddPagesProc(lParam, CLSID_RISrvQueryForm, &cqp) );
  181. HRETURN(hr);
  182. }
  183. // ************************************************************************
  184. //
  185. // Property Sheet Functions
  186. //
  187. // ************************************************************************
  188. //
  189. // PropSheetDlgProc()
  190. //
  191. INT_PTR CALLBACK
  192. THISCLASS::PropSheetDlgProc(
  193. HWND hDlg,
  194. UINT uMsg,
  195. WPARAM wParam,
  196. LPARAM lParam )
  197. {
  198. //TraceMsg( TEXT("PropSheetDlgProc(") );
  199. //TraceMsg( TF_FUNC, TEXT(" hDlg = 0x%p, uMsg = 0x%p, wParam = 0x%p, lParam = 0x%p )\n"),
  200. // hDlg, uMsg, wParam, lParam );
  201. LPTHISCLASS pcc = (LPTHISCLASS) GetWindowLongPtr( hDlg, GWLP_USERDATA );
  202. if ( uMsg == WM_INITDIALOG )
  203. {
  204. TraceMsg( TF_WM, TEXT("WM_INITDIALOG\n"));
  205. CQPAGE * pcqp = (CQPAGE *) lParam;
  206. SetWindowLongPtr( hDlg, GWLP_USERDATA, pcqp->lParam );
  207. pcc = (LPTHISCLASS) pcqp->lParam;
  208. pcc->_InitDialog( hDlg, lParam );
  209. }
  210. if (pcc)
  211. {
  212. Assert( hDlg == pcc->_hDlg );
  213. switch ( uMsg )
  214. {
  215. case WM_NOTIFY:
  216. TraceMsg( TF_WM, TEXT("WM_NOTIFY\n") );
  217. return pcc->_OnNotify( wParam, lParam );
  218. case WM_COMMAND:
  219. TraceMsg( TF_WM, TEXT("WM_COMMAND\n") );
  220. return pcc->_OnCommand( wParam, lParam );
  221. case WM_HELP:// F1
  222. {
  223. LPHELPINFO phelp = (LPHELPINFO) lParam;
  224. WinHelp( (HWND) phelp->hItemHandle, g_cszHelpFile, HELP_WM_HELP, (DWORD_PTR) &aSrvQueryHelpMap );
  225. }
  226. break;
  227. case WM_CONTEXTMENU: // right mouse click
  228. WinHelp((HWND) wParam, g_cszHelpFile, HELP_CONTEXTMENU, (DWORD_PTR) &aSrvQueryHelpMap );
  229. break;
  230. }
  231. }
  232. return FALSE;
  233. }
  234. //
  235. // PropSheetPageProc()
  236. //
  237. HRESULT CALLBACK
  238. THISCLASS::PropSheetPageProc(
  239. LPCQPAGE pQueryPage,
  240. HWND hwnd,
  241. UINT uMsg,
  242. WPARAM wParam,
  243. LPARAM lParam)
  244. {
  245. TraceClsFunc( "PropSheetPageProc( " );
  246. TraceMsg( TF_FUNC, TEXT("pQueryPage = 0x%p, hwnd = 0x%p, uMsg = 0x%p, wParam= 0x%p, lParam = 0x%p )\n"),
  247. pQueryPage, hwnd, uMsg, wParam, lParam );
  248. HRESULT hr = E_NOTIMPL;
  249. Assert( pQueryPage );
  250. LPTHISCLASS pQueryForm = (LPTHISCLASS )pQueryPage->lParam;
  251. Assert( pQueryForm );
  252. switch ( uMsg )
  253. {
  254. // Initialize so AddRef the object we are associated with so that
  255. // we don't get unloaded.
  256. case CQPM_INITIALIZE:
  257. TraceMsg( TF_WM, "CQPM_INITIALIZE\n" );
  258. pQueryForm->AddRef();
  259. hr = S_OK;
  260. break;
  261. // Release, therefore Release the object we are associated with to
  262. // ensure correct destruction etc.
  263. case CQPM_RELEASE:
  264. TraceMsg( TF_WM, "CQPM_RELEASE\n" );
  265. SetWindowLongPtr( pQueryForm->_hDlg, GWLP_USERDATA, NULL );
  266. pQueryForm->Release();
  267. hr = S_OK;
  268. break;
  269. // Enable so fix the state of our two controls within the window.
  270. case CQPM_ENABLE:
  271. TraceMsg( TF_WM, "CQPM_ENABLE\n" );
  272. EnableWindow( GetDlgItem( hwnd, IDC_E_SERVER ), (BOOL)wParam );
  273. hr = S_OK;
  274. break;
  275. // Fill out the parameter structure to return to the caller, this is
  276. // handler specific. In our case we constructure a query of the CN
  277. // and objectClass properties, and we show a columns displaying both
  278. // of these. For further information about the DSQUERYPARAMs structure
  279. // see dsquery.h
  280. case CQPM_GETPARAMETERS:
  281. TraceMsg( TF_WM, "CQPM_GETPARAMETERS\n" );
  282. hr = pQueryForm->_GetQueryParams( hwnd, (LPDSQUERYPARAMS*)lParam );
  283. break;
  284. // Clear form, therefore set the window text for these two controls
  285. // to zero.
  286. case CQPM_CLEARFORM:
  287. TraceMsg( TF_WM, "CQPM_CLEARFORM\n" );
  288. SetDlgItemText( hwnd, IDC_E_SERVER, L"" );
  289. hr = S_OK;
  290. break;
  291. case CQPM_SETDEFAULTPARAMETERS:
  292. TraceMsg( TF_WM, "CQPM_SETDEFAULTPARAMETERS: wParam = %s lParam = 0x%p\n", BOOLTOSTRING(wParam), lParam );
  293. SetDlgItemText( hwnd, IDC_E_SERVER, L"*" );
  294. hr = S_OK;
  295. break;
  296. default:
  297. TraceMsg( TF_WM, "CQPM_message 0x%08x *** NOT IMPL ***\n", uMsg );
  298. hr = E_NOTIMPL;
  299. break;
  300. }
  301. RETURN(hr);
  302. }
  303. //
  304. // _OnPSPCB_Create( )
  305. //
  306. HRESULT
  307. THISCLASS::_OnPSPCB_Create( )
  308. {
  309. TraceClsFunc( "_OnPSPCB_Create( )\n" );
  310. HRETURN(S_OK);
  311. }
  312. //
  313. // _InitDialog( )
  314. //
  315. HRESULT
  316. THISCLASS::_InitDialog(
  317. HWND hDlg,
  318. LPARAM lParam )
  319. {
  320. TraceClsFunc( "_InitDialog( )\n" );
  321. _hDlg = hDlg;
  322. Edit_LimitText( GetDlgItem( _hDlg, IDC_E_SERVER), DNS_MAX_NAME_LENGTH );
  323. HRETURN(S_OK);
  324. }
  325. //
  326. // _OnCommand( )
  327. //
  328. INT
  329. THISCLASS::_OnCommand( WPARAM wParam, LPARAM lParam )
  330. {
  331. TraceClsFunc( "_OnCommand( " );
  332. TraceMsg( TF_FUNC, "wParam = 0x%p, lParam = 0x%p )\n", wParam, lParam );
  333. #if 0
  334. switch ( LOWORD(wParam) )
  335. {
  336. }
  337. #endif
  338. RETURN(FALSE);
  339. }
  340. //
  341. // _OnNotify( )
  342. //
  343. INT
  344. THISCLASS::_OnNotify(
  345. WPARAM wParam,
  346. LPARAM lParam )
  347. {
  348. TraceClsFunc( "_OnNotify( " );
  349. TraceMsg( TF_FUNC, "wParam = 0x%p, lParam = 0x%p )\n", wParam, lParam );
  350. LPNMHDR lpnmhdr = (LPNMHDR) lParam;
  351. TraceMsg( TF_WM, "NMHDR: HWND = 0x%p, idFrom = 0x%08x, code = 0x%08x\n",
  352. lpnmhdr->hwndFrom, lpnmhdr->idFrom, lpnmhdr->code );
  353. #if 0
  354. switch( lpnmhdr->code )
  355. {
  356. }
  357. #endif
  358. RETURN(FALSE);
  359. }
  360. struct
  361. {
  362. INT fmt;
  363. INT cx;
  364. INT uID;
  365. LPCTSTR pDisplayProperty;
  366. }
  367. srvcolumns[] =
  368. {
  369. 0, 20, IDS_NAME, TEXT("cn"),
  370. };
  371. //
  372. // _GetQueryParams( )
  373. //
  374. HRESULT
  375. THISCLASS::_GetQueryParams(
  376. HWND hWnd,
  377. LPDSQUERYPARAMS* ppdsqp )
  378. {
  379. TraceClsFunc( "_GetQueryParams( )\n" );
  380. if ( !ppdsqp )
  381. HRETURN(E_POINTER);
  382. HRESULT hr = S_OK;
  383. INT i;
  384. WCHAR szServer[DNS_MAX_NAME_BUFFER_LENGTH];
  385. WCHAR szFilter[ARRAYSIZE(FILTER_QUERY_SERVER)+ARRAYSIZE(szServer)];
  386. ULONG offset;
  387. ULONG cbStruct = 0;
  388. LPDSQUERYPARAMS pDsQueryParams = NULL;
  389. #if 0
  390. if ( *ppdsqp )
  391. {
  392. // This page doesn't support appending its query data to an
  393. // existing DSQUERYPARAMS strucuture, only creating a new block,
  394. // therefore bail if we see the pointer is not NULL.
  395. hr = THR(E_INVALIDARG);
  396. goto Error;
  397. }
  398. #endif
  399. if (!GetDlgItemText( hWnd, IDC_E_SERVER, szServer, ARRAYSIZE(szServer))) {
  400. wcscpy( szServer, L"*");
  401. }
  402. wsprintf( szFilter, FILTER_QUERY_SERVER, szServer );
  403. DebugMsg( "RI Filter: %s\n", szFilter );
  404. // compute the size of the new query block
  405. if ( !*ppdsqp )
  406. {
  407. offset = cbStruct = sizeof(DSQUERYPARAMS) + ((ARRAYSIZE(srvcolumns)-1)*sizeof(DSCOLUMN));
  408. cbStruct += StringByteSize(szFilter);
  409. for ( i = 0; i < ARRAYSIZE(srvcolumns); i++ )
  410. {
  411. cbStruct += StringByteSize(srvcolumns[i].pDisplayProperty);
  412. }
  413. }
  414. else
  415. {
  416. LPWSTR pszQuery;
  417. pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery);
  418. offset = (*ppdsqp)->cbStruct;
  419. cbStruct = (*ppdsqp)->cbStruct + StringByteSize( pszQuery ) + StringByteSize( szFilter );
  420. }
  421. // Allocate it and populate it with the data, the header is fixed
  422. // but the strings are referenced by offset.
  423. pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct);
  424. if ( !pDsQueryParams )
  425. {
  426. hr = E_OUTOFMEMORY;
  427. goto Error;
  428. }
  429. // Did they hand in a query that we need to modify?
  430. if ( !*ppdsqp)
  431. { // no... create our own query
  432. pDsQueryParams->cbStruct = cbStruct;
  433. pDsQueryParams->dwFlags = 0;
  434. pDsQueryParams->hInstance = g_hInstance;
  435. pDsQueryParams->offsetQuery = offset;
  436. pDsQueryParams->iColumns = ARRAYSIZE(srvcolumns);
  437. // Copy the filter string and bump the offset
  438. StringByteCopy(pDsQueryParams, offset, szFilter);
  439. offset += StringByteSize(szFilter);
  440. // Fill in the array of columns to dispaly, the cx is a percentage of the
  441. // current view, the propertie names to display are UNICODE strings and
  442. // are referenced by offset, therefore we bump the offset as we copy
  443. // each one.
  444. for ( i = 0 ; i < ARRAYSIZE(srvcolumns); i++ )
  445. {
  446. pDsQueryParams->aColumns[i].fmt = srvcolumns[i].fmt;
  447. pDsQueryParams->aColumns[i].cx = srvcolumns[i].cx;
  448. pDsQueryParams->aColumns[i].idsName = srvcolumns[i].uID;
  449. pDsQueryParams->aColumns[i].offsetProperty = offset;
  450. StringByteCopy(pDsQueryParams, offset, srvcolumns[i].pDisplayProperty);
  451. offset += StringByteSize(srvcolumns[i].pDisplayProperty);
  452. }
  453. }
  454. else
  455. { // yes... add our parameters to the query
  456. LPWSTR pszQuery;
  457. LPWSTR pszNewQuery;
  458. INT n;
  459. // duplicate the existing query
  460. Assert( offset == (*ppdsqp)->cbStruct );
  461. CopyMemory( pDsQueryParams, *ppdsqp, offset );
  462. pDsQueryParams->cbStruct = cbStruct;
  463. #if 0
  464. // add our columns
  465. for ( i = 0 ; i < ARRAYSIZE(srvcolumns); i++ )
  466. {
  467. pDsQueryParams->aColumns[n+i].fmt = srvcolumns[i].fmt;
  468. pDsQueryParams->aColumns[n+i].cx = srvcolumns[i].cx;
  469. pDsQueryParams->aColumns[n+i].idsName = srvcolumns[i].uID;
  470. pDsQueryParams->aColumns[n+i].offsetProperty = offset;
  471. StringByteCopy(pDsQueryParams, offset, srvcolumns[i].pDisplayProperty);
  472. offset += StringByteSize(srvcolumns[i].pDisplayProperty);
  473. }
  474. #endif
  475. // new query location
  476. pDsQueryParams->offsetQuery = offset;
  477. pszQuery = (LPWSTR) ((LPBYTE)(*ppdsqp) + (*ppdsqp)->offsetQuery);
  478. pszNewQuery = (LPWSTR) ((LPBYTE)pDsQueryParams + offset);
  479. Assert( pszQuery );
  480. // append to their query
  481. if ( StrCmpN( pszQuery, L"(&", 2 ) == 0 )
  482. {
  483. pszQuery[ wcslen( pszQuery ) - 1 ] = L'\0'; // remove ")"
  484. }
  485. else
  486. {
  487. wcscpy( pszNewQuery, L"(&" ); // add "(&" to begining of query
  488. }
  489. wcscat( pszNewQuery, pszQuery ); // add their query
  490. wcscat( pszNewQuery, &szFilter[2] ); // add our query starting after the "(&"
  491. offset += StringByteSize( pszNewQuery ); // compute new offset
  492. DebugMsg( "New Query String: %s\n", pszNewQuery );
  493. // Cleanup
  494. CoTaskMemFree( *ppdsqp );
  495. }
  496. // Success
  497. *ppdsqp = pDsQueryParams;
  498. Assert( hr == S_OK );
  499. Cleanup:
  500. HRETURN(hr);
  501. Error:
  502. if ( pDsQueryParams )
  503. CoTaskMemFree( pDsQueryParams );
  504. // If we aren't modifying the query and there wasn't
  505. // a query handed into us, indicate failure instead.
  506. if ( hr == S_FALSE && !*ppdsqp )
  507. {
  508. hr = E_FAIL;
  509. }
  510. goto Cleanup;
  511. }