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.

569 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1998 - 1999
  6. //
  7. // File: qryfrm.cpp
  8. //
  9. //--------------------------------------------------------------------------
  10. // QryFrm.cpp : Implementation of CRRASQueryForm
  11. #include "stdafx.h"
  12. #include <cmnquryp.h>
  13. #include "QryFrm.h"
  14. #include "dlggen.h"
  15. #include "dlgadv.h"
  16. COLUMNINFO RRASColumn[] =
  17. {
  18. {0, 40, IDS_QRY_COL_CN, 0, ATTR_NAME_DN},
  19. {0, 30, IDS_QRY_COL_OBJECTCLASS, 1, ATTR_NAME_OBJECTCLASS},
  20. {0, 30, IDS_QRY_COL_RRASATTRIBUTE, 2, ATTR_NAME_RRASATTRIBUTE},
  21. };
  22. int cRRASColumn = 3;
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CRRASQueryForm
  25. //=========================================================================
  26. // IQueryForm methods
  27. HRESULT PageProc(LPCQPAGE pPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  28. INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  29. HRESULT GetQueryParams(HWND hWnd, LPDSQUERYPARAMS* ppDsQueryParams);
  30. STDMETHODIMP CRRASQueryForm::Initialize(HKEY hkForm)
  31. {
  32. // This method is called to initialize the query form object, it is called before
  33. // any pages are added. hkForm should be ignored, in the future however it
  34. // will be a way to persist form state.
  35. HRESULT hr = S_OK;
  36. return hr;
  37. }
  38. STDMETHODIMP CRRASQueryForm::AddForms(LPCQADDFORMSPROC pAddFormsProc, LPARAM lParam)
  39. {
  40. CQFORM cqf;
  41. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  42. // This method is called to allow the form handler to register its query form(s),
  43. // each form is identifiered by a CLSID and registered via the pAddFormProc. Here
  44. // we are going to register a test form.
  45. // When registering a form which is only applicable to a specific task, eg. Find a Domain
  46. // object, it is advised that the form be marked as hidden (CQFF_ISNEVERLISTED) which
  47. // will cause it not to appear in the form picker control. Then when the
  48. // client wants to use this form, they specify the form identifier and ask for the
  49. // picker control to be hidden.
  50. if ( !pAddFormsProc )
  51. return E_INVALIDARG;
  52. cqf.cbStruct = sizeof(cqf);
  53. cqf.dwFlags = CQFF_NOGLOBALPAGES | CQFF_ISNEVERLISTED;
  54. cqf.clsid = CLSID_RRASQueryForm;
  55. cqf.hIcon = NULL;
  56. CString title;
  57. title.LoadString(IDS_QRY_TITLE_RRASQUERYFORM);
  58. cqf.pszTitle = (LPCTSTR)title;
  59. return pAddFormsProc(lParam, &cqf);
  60. }
  61. STDMETHODIMP CRRASQueryForm::AddPages(LPCQADDPAGESPROC pAddPagesProc, LPARAM lParam)
  62. {
  63. HRESULT hr = S_OK;
  64. CQPAGE cqp;
  65. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  66. // AddPages is called after AddForms, it allows us to add the pages for the
  67. // forms we have registered. Each page is presented on a seperate tab within
  68. // the dialog. A form is a dialog with a DlgProc and a PageProc.
  69. //
  70. // When registering a page the entire structure passed to the callback is copied,
  71. // the amount of data to be copied is defined by the cbStruct field, therefore
  72. // a page implementation can grow this structure to store extra information. When
  73. // the page dialog is constructed via CreateDialog the CQPAGE strucuture is passed
  74. // as the create param.
  75. if ( !pAddPagesProc )
  76. return E_INVALIDARG;
  77. cqp.cbStruct = sizeof(cqp);
  78. cqp.dwFlags = 0x0;
  79. cqp.pPageProc = PageProc;
  80. cqp.hInstance = _Module.m_hInst;
  81. cqp.idPageName = IDS_QRY_TITLE_GENERALPAGE;
  82. cqp.idPageTemplate = IDD_QRY_GENERAL;
  83. cqp.pDlgProc = DlgProc;
  84. cqp.lParam = (LPARAM)new CDlgGeneral();
  85. hr = pAddPagesProc(lParam, CLSID_RRASQueryForm, &cqp);
  86. if(hr != S_OK)
  87. return hr;
  88. cqp.dwFlags = 0x0;
  89. cqp.pPageProc = PageProc;
  90. cqp.hInstance = _Module.m_hInst;
  91. cqp.idPageName = IDS_QRY_TITLE_ADVANCEDPAGE;
  92. cqp.idPageTemplate = IDD_QRY_ADVANCED;
  93. cqp.pDlgProc = DlgProc;
  94. cqp.lParam = (LPARAM)new CDlgAdvanced();
  95. return pAddPagesProc(lParam, CLSID_RRASQueryForm, &cqp);
  96. }
  97. /*---------------------------------------------------------------------------*/
  98. // The PageProc is used to perform general house keeping and communicate between
  99. // the frame and the page.
  100. //
  101. // All un-handled, or unknown reasons should result in an E_NOIMPL response
  102. // from the proc.
  103. //
  104. // In:
  105. // pPage -> CQPAGE structure (copied from the original passed to pAddPagesProc)
  106. // hwnd = handle of the dialog for the page
  107. // uMsg, wParam, lParam = message parameters for this event
  108. //
  109. // Out:
  110. // HRESULT
  111. //
  112. // uMsg reasons:
  113. // ------------
  114. // CQPM_INIIIALIZE
  115. // CQPM_RELEASE
  116. // These are issued as a result of the page being declared or freed, they
  117. // allow the caller to AddRef, Release or perform basic initialization
  118. // of the form object.
  119. //
  120. // CQPM_ENABLE
  121. // Enable is when the query form needs to enable or disable the controls
  122. // on its page. wParam contains TRUE/FALSE indicating the state that
  123. // is required.
  124. //
  125. // CQPM_GETPARAMETERS
  126. // To collect the parameters for the query each page on the active form
  127. // receives this event. lParam is an LPVOID* which is set to point to the
  128. // parameter block to pass to the handler, if the pointer is non-NULL
  129. // on entry the form needs to appened its query information to it. The
  130. // parameter block is handler specific.
  131. //
  132. // Returning S_FALSE from this event causes the query to be canceled.
  133. //
  134. // CQPM_CLEARFORM
  135. // When the page window is created for the first time, or the user clicks
  136. // the clear search the page receives a CQPM_CLEARFORM notification, at
  137. // which point it needs to clear out the edit controls it has and
  138. // return to a default state.
  139. //
  140. // CQPM_PERSIST:
  141. // When loading of saving a query, each page is called with an IPersistQuery
  142. // interface which allows them to read or write the configuration information
  143. // to save or restore their state. lParam is a pointer to the IPersistQuery object,
  144. // and wParam is TRUE/FALSE indicating read or write accordingly.
  145. HRESULT PageProc(LPCQPAGE pQueryPage, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  146. {
  147. HRESULT hr = S_OK;
  148. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  149. CQryDialog* pDialog = (CQryDialog*)pQueryPage->lParam;
  150. ASSERT(pDialog);
  151. switch ( uMsg )
  152. {
  153. // Initialize so AddRef the object we are associated with so that
  154. // we don't get unloaded.
  155. case CQPM_INITIALIZE:
  156. break;
  157. // Changed from qform sample to detach the hwnd, and delete the CDialog
  158. // ensure correct destruction etc.
  159. case CQPM_RELEASE:
  160. pDialog->Detach();
  161. SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)0);
  162. delete pDialog;
  163. break;
  164. // Enable so fix the state of our two controls within the window.
  165. case CQPM_ENABLE:
  166. break;
  167. // Fill out the parameter structure to return to the caller, this is
  168. // handler specific. In our case we constructure a query of the CN
  169. // and objectClass properties, and we show a columns displaying both
  170. // of these. For further information about the DSQUERYPARAMs structure
  171. // see dsquery.h
  172. case CQPM_GETPARAMETERS:
  173. hr = pDialog->GetQueryParams((LPDSQUERYPARAMS*)lParam);
  174. break;
  175. // Clear form, therefore set the window text for these two controls
  176. // to zero.
  177. case CQPM_CLEARFORM:
  178. hr = pDialog->ClearForm();
  179. break;
  180. // persistance is not currently supported by this form.
  181. case CQPM_PERSIST:
  182. {
  183. BOOL fRead = (BOOL)wParam;
  184. IPersistQuery* pPersistQuery = (IPersistQuery*)lParam;
  185. if ( !pPersistQuery )
  186. return E_INVALIDARG;
  187. hr = pDialog->Persist(pPersistQuery, fRead);
  188. break;
  189. }
  190. default:
  191. hr = E_NOTIMPL;
  192. break;
  193. }
  194. return hr;
  195. }
  196. /*---------------------------------------------------------------------------*/
  197. // The DlgProc is a standard Win32 dialog proc associated with the form
  198. // window.
  199. INT_PTR CALLBACK DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  200. {
  201. LPCQPAGE pQueryPage;
  202. CQryDialog* pDialog;
  203. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  204. if ( uMsg == WM_INITDIALOG )
  205. {
  206. // changed from qForm sample to save CDialog pointer
  207. // in the DWL_USER field of the dialog box instance.
  208. pQueryPage = (LPCQPAGE)lParam;
  209. pDialog = (CQryDialog*)pQueryPage->lParam;
  210. pDialog->Attach(hwnd);
  211. SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)pDialog);
  212. return pDialog->OnInitDialog();
  213. }
  214. else
  215. {
  216. // CDialog pointer is stored in DWL_USER
  217. // dialog structure, note however that in some cases this will
  218. // be NULL as it is set on WM_INITDIALOG.
  219. pDialog = (CQryDialog*)GetWindowLongPtr(hwnd, DWLP_USER);
  220. }
  221. if(!pDialog)
  222. return FALSE;
  223. else
  224. return AfxCallWndProc(pDialog, hwnd, uMsg, wParam, lParam);
  225. }
  226. /*---------------------------------------------------------------------------*/
  227. // Build a parameter block to pass to the query handler. Each page is called
  228. // with a pointer to a pointer which it must update with the revised query
  229. // block. For the first page this pointer is NULL, for subsequent pages
  230. // the pointer is non-zero and the page must append its data into the
  231. // allocation.
  232. //
  233. // Returning either and error or S_FALSE stops the query. An error is
  234. // reported to the user, S_FALSE stops silently.
  235. HRESULT BuildQueryParams(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
  236. {
  237. ASSERT(pQuery);
  238. if(*ppDsQueryParams)
  239. return QueryParamsAddQueryString(ppDsQueryParams, pQuery);
  240. else
  241. return QueryParamsAlloc(ppDsQueryParams, pQuery, cRRASColumn, RRASColumn);
  242. }
  243. /*-----------------------------------------------------------------------------
  244. / QueryParamsAlloc
  245. / ----------------
  246. / Construct a block we can pass to the DS query handler which contains
  247. / all the parameters for the query.
  248. /
  249. / In:
  250. / ppDsQueryParams -> receives the parameter block
  251. / pQuery -> LDAP query string to be used
  252. / iColumns = number of columns
  253. / pColumnInfo -> column info structure to use
  254. /
  255. / Out:
  256. / HRESULT
  257. /----------------------------------------------------------------------------*/
  258. HRESULT QueryParamsAlloc(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery, LONG iColumns, LPCOLUMNINFO aColumnInfo)
  259. {
  260. HRESULT hr;
  261. LPDSQUERYPARAMS pDsQueryParams = NULL;
  262. LONG cbStruct;
  263. LONG i;
  264. ASSERT(!*ppDsQueryParams);
  265. TRACE(L"QueryParamsAlloc");
  266. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  267. if ( !pQuery || !iColumns || !ppDsQueryParams )
  268. ExitGracefully(hr, E_INVALIDARG, "Failed to build query parameter block");
  269. // Compute the size of the structure we need to be using
  270. cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
  271. cbStruct += StringByteSizeW(pQuery);
  272. for ( i = 0 ; i < iColumns ; i++ )
  273. {
  274. if ( aColumnInfo[i].pPropertyName )
  275. cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
  276. }
  277. pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct);
  278. if ( !pDsQueryParams )
  279. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate parameter block");
  280. // Structure allocated so lets fill it with data
  281. pDsQueryParams->cbStruct = cbStruct;
  282. pDsQueryParams->dwFlags = 0;
  283. pDsQueryParams->hInstance = _Module.m_hInst;
  284. pDsQueryParams->iColumns = iColumns;
  285. pDsQueryParams->dwReserved = 0;
  286. cbStruct = sizeof(DSQUERYPARAMS) + (sizeof(DSCOLUMN)*iColumns);
  287. pDsQueryParams->offsetQuery = cbStruct;
  288. StringByteCopyW(pDsQueryParams, cbStruct, pQuery);
  289. cbStruct += StringByteSizeW(pQuery);
  290. for ( i = 0 ; i < iColumns ; i++ )
  291. {
  292. pDsQueryParams->aColumns[i].dwFlags = 0;
  293. pDsQueryParams->aColumns[i].fmt = aColumnInfo[i].fmt;
  294. pDsQueryParams->aColumns[i].cx = aColumnInfo[i].cx;
  295. pDsQueryParams->aColumns[i].idsName = aColumnInfo[i].idsName;
  296. pDsQueryParams->aColumns[i].dwReserved = 0;
  297. if ( aColumnInfo[i].pPropertyName )
  298. {
  299. pDsQueryParams->aColumns[i].offsetProperty = cbStruct;
  300. StringByteCopyW(pDsQueryParams, cbStruct, aColumnInfo[i].pPropertyName);
  301. cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
  302. }
  303. else
  304. {
  305. pDsQueryParams->aColumns[i].offsetProperty = aColumnInfo[i].iPropertyIndex;
  306. }
  307. }
  308. hr = S_OK; // success
  309. exit_gracefully:
  310. if ( FAILED(hr) && pDsQueryParams )
  311. {
  312. CoTaskMemFree(pDsQueryParams);
  313. pDsQueryParams = NULL;
  314. }
  315. *ppDsQueryParams = pDsQueryParams;
  316. return hr;
  317. }
  318. /*-----------------------------------------------------------------------------
  319. / QueryParamsAddQueryString
  320. / -------------------------
  321. / Given an existing DS query block appened the given LDAP query string into
  322. / it. We assume that the query block has been allocated by IMalloc (or CoTaskMemAlloc).
  323. /
  324. / In:
  325. / ppDsQueryParams -> receives the parameter block
  326. / pQuery -> LDAP query string to be appended
  327. /
  328. / Out:
  329. / HRESULT
  330. /----------------------------------------------------------------------------*/
  331. HRESULT QueryParamsAddQueryString(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
  332. {
  333. HRESULT hr;
  334. LPWSTR pOriginalQuery = NULL;
  335. LPDSQUERYPARAMS pDsQuery = *ppDsQueryParams;
  336. INT cbQuery, i;
  337. LPVOID pv;
  338. ASSERT(*ppDsQueryParams);
  339. TRACE(_T("QueryParamsAddQueryString"));
  340. if ( pQuery )
  341. {
  342. if ( !pDsQuery )
  343. ExitGracefully(hr, E_INVALIDARG, "No query to append to");
  344. // Work out the size of the bits we are adding, take a copy of the
  345. // query string and finally re-alloc the query block (which may cause it
  346. // to move).
  347. cbQuery = StringByteSizeW(pQuery) + StringByteSizeW(L"(&)");
  348. TRACE(_T("DSQUERYPARAMS being resized by %d bytes"));
  349. i = (wcslen((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery)) + 1) * sizeof(WCHAR);
  350. pOriginalQuery = (WCHAR*)_alloca(i);
  351. lstrcpyW(pOriginalQuery, (LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery));
  352. pv = CoTaskMemRealloc(*ppDsQueryParams, pDsQuery->cbStruct+cbQuery);
  353. if ( pv == NULL )
  354. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to re-alloc control block");
  355. *ppDsQueryParams = (LPDSQUERYPARAMS) pv;
  356. pDsQuery = *ppDsQueryParams; // if may have moved
  357. // Now move everything above the query string up, and fix all the
  358. // offsets that reference those items (probably the property table),
  359. // finally adjust the size to reflect the change
  360. MoveMemory(ByteOffset(pDsQuery, pDsQuery->offsetQuery+cbQuery),
  361. ByteOffset(pDsQuery, pDsQuery->offsetQuery),
  362. (pDsQuery->cbStruct - pDsQuery->offsetQuery));
  363. for ( i = 0 ; i < pDsQuery->iColumns ; i++ )
  364. {
  365. if ( pDsQuery->aColumns[i].offsetProperty > pDsQuery->offsetQuery )
  366. {
  367. pDsQuery->aColumns[i].offsetProperty += cbQuery;
  368. }
  369. }
  370. wcscpy((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L"(&");
  371. wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pOriginalQuery);
  372. wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pQuery);
  373. wcscat((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L")");
  374. pDsQuery->cbStruct += cbQuery;
  375. }
  376. hr = S_OK;
  377. exit_gracefully:
  378. return hr;
  379. }
  380. // Get the list of values in the dictionary, the variant is expected to be SARRY
  381. HRESULT QueryRRASAdminDictionary(VARIANT* pVar)
  382. {
  383. ASSERT(pVar);
  384. USES_CONVERSION;
  385. CString str, str1;
  386. IADs* pIADs = NULL;
  387. // enumerate EAP list
  388. // retieve the list of EAPTypes in the DS
  389. // get ROOTDSE
  390. HRESULT hr = S_OK;
  391. CHECK_HR(hr = ADsGetObject(L"LDAP://RootDSE", IID_IADs, (void**)&pIADs));
  392. ASSERT(pIADs);
  393. VariantClear(pVar);
  394. CHECK_HR(hr = pIADs->Get(L"configurationNamingContext", pVar));
  395. str1 = V_BSTR(pVar);
  396. pIADs->Release();
  397. pIADs = NULL;
  398. str = L"LDAP://";
  399. str += CN_DICTIONARY;
  400. str += str1;
  401. // Dictionary Object
  402. CHECK_HR(hr = ADsGetObject(T2W((LPTSTR)(LPCTSTR)str), IID_IADs, (void**)&pIADs));
  403. ASSERT(pIADs);
  404. VariantClear(pVar);
  405. CHECK_HR(hr = pIADs->GetEx(ATTR_NAME_RRASDICENTRY, pVar));
  406. goto L_EXIT;
  407. L_ERR:
  408. VariantClear(pVar);
  409. L_EXIT:
  410. if(pIADs)
  411. pIADs->Release();
  412. return hr;
  413. }
  414. HRESULT GetGeneralPageAttributes(CStrArray& array)
  415. {
  416. HRESULT hr = S_OK;
  417. CString* pStr = NULL;
  418. /*
  419. #define ATTR_VAL_LANtoLAN L"311:6:601"
  420. #define ATTR_VAL_RAS L"311:6:602"
  421. #define ATTR_VAL_DEMANDDIAL L"311:6:603"
  422. */
  423. try
  424. {
  425. pStr = new CString(ATTR_VAL_LANtoLAN);
  426. array.Add(pStr);
  427. pStr = new CString(ATTR_VAL_RAS);
  428. array.Add(pStr);
  429. pStr = new CString(ATTR_VAL_DEMANDDIAL);
  430. array.Add(pStr);
  431. }
  432. catch(CMemoryException&)
  433. {
  434. hr = E_OUTOFMEMORY;
  435. }
  436. return hr;
  437. }