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.

722 lines
22 KiB

  1. #include "pch.h"
  2. #pragma hdrstop
  3. /*-----------------------------------------------------------------------------
  4. / Helper functions
  5. /----------------------------------------------------------------------------*/
  6. HRESULT _GetQueryString(LPWSTR pQuery, UINT* pLen, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls);
  7. HRESULT _GetFilterQueryString(LPWSTR pFilter, UINT* pLen, HWND hwndFilter, HDSA hdsaColumns);
  8. /*-----------------------------------------------------------------------------
  9. / Query paremeter helpers
  10. /----------------------------------------------------------------------------*/
  11. /*-----------------------------------------------------------------------------
  12. / ClassListAlloc
  13. / --------------
  14. / Construct a class list allocation based on the list of classes
  15. / we are given.
  16. /
  17. / In:
  18. / ppClassList -> receives a class list
  19. / cClassList / cClassList = array of classes to allocat from
  20. /
  21. / Out:
  22. / HRESULT
  23. /----------------------------------------------------------------------------*/
  24. STDAPI ClassListAlloc(LPDSQUERYCLASSLIST* ppDsQueryClassList, LPWSTR* aClassNames, INT cClassNames)
  25. {
  26. HRESULT hres;
  27. DWORD cbStruct, offset;
  28. LPDSQUERYCLASSLIST pDsQueryClassList = NULL;
  29. INT i;
  30. TraceEnter(TRACE_FORMS, "ClassListAlloc");
  31. if ( !ppDsQueryClassList || !aClassNames || !cClassNames )
  32. ExitGracefully(hres, E_FAIL, "Bad parameters (no class list etc)");
  33. // Walk the list of classes working out the size of the structure
  34. // we are going to generate, this consists of the array of
  35. // classes.
  36. cbStruct = SIZEOF(DSQUERYCLASSLIST)+(cClassNames*SIZEOF(DWORD));
  37. offset = cbStruct;
  38. for ( i = 0 ; i < cClassNames ; i++ )
  39. {
  40. TraceAssert(aClassNames[i]);
  41. cbStruct += StringByteSizeW(aClassNames[i]);
  42. }
  43. // Allocate the structure using the task allocator, then fill
  44. // it in copying all the strings into the data blob.
  45. Trace(TEXT("Allocating class structure %d"), cbStruct);
  46. pDsQueryClassList = (LPDSQUERYCLASSLIST)CoTaskMemAlloc(cbStruct);
  47. TraceAssert(pDsQueryClassList);
  48. if ( !pDsQueryClassList )
  49. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate class list structure");
  50. pDsQueryClassList->cbStruct = cbStruct;
  51. pDsQueryClassList->cClasses = cClassNames;
  52. for ( i = 0 ; i < cClassNames ; i++ )
  53. {
  54. Trace(TEXT("Adding class: %s"), aClassNames[i]);
  55. pDsQueryClassList->offsetClass[i] = offset;
  56. StringByteCopyW(pDsQueryClassList, offset, aClassNames[i]);
  57. offset += StringByteSizeW(aClassNames[i]);
  58. }
  59. hres = S_OK;
  60. exit_gracefully:
  61. TraceAssert(pDsQueryClassList);
  62. if (ppDsQueryClassList)
  63. *ppDsQueryClassList = pDsQueryClassList;
  64. TraceLeaveResult(hres);
  65. }
  66. /*-----------------------------------------------------------------------------
  67. / QueryParamsAlloc
  68. / ----------------
  69. / Construct a block we can pass to the DS query handler which contains
  70. / all the parameters for the query.
  71. /
  72. / In:
  73. / ppDsQueryParams -> receives the parameter block
  74. / pQuery -> LDAP query string to be used
  75. / hInstance = hInstance to write into parameter block
  76. / iColumns = number of columns
  77. / pColumnInfo -> column info structure to use
  78. /
  79. / Out:
  80. / HRESULT
  81. /----------------------------------------------------------------------------*/
  82. STDAPI QueryParamsAlloc(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery, HINSTANCE hInstance, LONG iColumns, LPCOLUMNINFO aColumnInfo)
  83. {
  84. HRESULT hres;
  85. LPDSQUERYPARAMS pDsQueryParams = NULL;
  86. LONG cbStruct;
  87. LONG i;
  88. TraceEnter(TRACE_FORMS, "QueryParamsAlloc");
  89. if ( !pQuery || !iColumns || !ppDsQueryParams )
  90. ExitGracefully(hres, E_INVALIDARG, "Failed to build query parameter block");
  91. // Compute the size of the structure we need to be using
  92. cbStruct = SIZEOF(DSQUERYPARAMS) + (SIZEOF(DSCOLUMN)*iColumns);
  93. cbStruct += StringByteSizeW(pQuery);
  94. for ( i = 0 ; i < iColumns ; i++ )
  95. {
  96. if ( aColumnInfo[i].pPropertyName )
  97. cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
  98. }
  99. pDsQueryParams = (LPDSQUERYPARAMS)CoTaskMemAlloc(cbStruct);
  100. if ( !pDsQueryParams )
  101. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate parameter block");
  102. // Structure allocated so lets fill it with data
  103. pDsQueryParams->cbStruct = cbStruct;
  104. pDsQueryParams->dwFlags = 0;
  105. pDsQueryParams->hInstance = hInstance;
  106. pDsQueryParams->iColumns = iColumns;
  107. pDsQueryParams->dwReserved = 0;
  108. cbStruct = SIZEOF(DSQUERYPARAMS) + (SIZEOF(DSCOLUMN)*iColumns);
  109. pDsQueryParams->offsetQuery = cbStruct;
  110. StringByteCopyW(pDsQueryParams, cbStruct, pQuery);
  111. cbStruct += StringByteSizeW(pQuery);
  112. for ( i = 0 ; i < iColumns ; i++ )
  113. {
  114. pDsQueryParams->aColumns[i].dwFlags = 0;
  115. pDsQueryParams->aColumns[i].fmt = aColumnInfo[i].fmt;
  116. pDsQueryParams->aColumns[i].cx = aColumnInfo[i].cx;
  117. pDsQueryParams->aColumns[i].idsName = aColumnInfo[i].idsName;
  118. pDsQueryParams->aColumns[i].dwReserved = 0;
  119. if ( aColumnInfo[i].pPropertyName )
  120. {
  121. pDsQueryParams->aColumns[i].offsetProperty = cbStruct;
  122. StringByteCopyW(pDsQueryParams, cbStruct, aColumnInfo[i].pPropertyName);
  123. cbStruct += StringByteSizeW(aColumnInfo[i].pPropertyName);
  124. }
  125. else
  126. {
  127. pDsQueryParams->aColumns[i].offsetProperty = aColumnInfo[i].iPropertyIndex;
  128. }
  129. }
  130. hres = S_OK; // success
  131. exit_gracefully:
  132. if ( FAILED(hres) && pDsQueryParams )
  133. {
  134. CoTaskMemFree(pDsQueryParams);
  135. pDsQueryParams = NULL;
  136. }
  137. if (ppDsQueryParams)
  138. *ppDsQueryParams = pDsQueryParams;
  139. TraceLeaveResult(hres);
  140. }
  141. /*-----------------------------------------------------------------------------
  142. / QueryParamsAddQueryString
  143. / -------------------------
  144. / Given an existing DS query block appened the given LDAP query string into
  145. / it. We assume that the query block has been allocated by IMalloc (or CoTaskMemAlloc).
  146. /
  147. / In:
  148. / ppDsQueryParams -> receives the parameter block
  149. / pQuery -> LDAP query string to be appended
  150. /
  151. / Out:
  152. / HRESULT
  153. /----------------------------------------------------------------------------*/
  154. STDAPI QueryParamsAddQueryString(LPDSQUERYPARAMS* ppDsQueryParams, LPWSTR pQuery)
  155. {
  156. HRESULT hres;
  157. LPWSTR pOriginalQuery = NULL;
  158. LPDSQUERYPARAMS pDsQuery = *ppDsQueryParams;
  159. INT cbQuery, i;
  160. TraceEnter(TRACE_FORMS, "QueryParamsAddQueryString");
  161. if ( pQuery )
  162. {
  163. if ( !pDsQuery )
  164. ExitGracefully(hres, E_INVALIDARG, "No query to append to");
  165. // Work out the size of the bits we are adding, take a copy of the
  166. // query string and finally re-alloc the query block (which may cause it
  167. // to move).
  168. cbQuery = StringByteSizeW(pQuery) + StringByteSizeW(L"(&)");
  169. Trace(TEXT("DSQUERYPARAMS being resized by %d bytes"), cbQuery);
  170. hres = LocalAllocStringW(&pOriginalQuery, (LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery));
  171. FailGracefully(hres, "Failed to take copy of original query string");
  172. pDsQuery = (LPDSQUERYPARAMS)CoTaskMemRealloc(pDsQuery, pDsQuery->cbStruct+cbQuery);
  173. if ( !pDsQuery )
  174. ExitGracefully(hres, E_OUTOFMEMORY, "Failed to re-alloc control block");
  175. *ppDsQueryParams = pDsQuery;
  176. // Now move everything above the query string up, and fix all the
  177. // offsets that reference those items (probably the property table),
  178. // finally adjust the size to reflect the change
  179. MoveMemory(ByteOffset(pDsQuery, pDsQuery->offsetQuery+cbQuery),
  180. ByteOffset(pDsQuery, pDsQuery->offsetQuery),
  181. (pDsQuery->cbStruct - pDsQuery->offsetQuery));
  182. for ( i = 0 ; i < pDsQuery->iColumns ; i++ )
  183. {
  184. if ( pDsQuery->aColumns[i].offsetProperty > pDsQuery->offsetQuery )
  185. {
  186. Trace(TEXT("Fixing offset of property at index %d"), i);
  187. pDsQuery->aColumns[i].offsetProperty += cbQuery;
  188. }
  189. }
  190. // We have reallocated the buffer above to include enough space for these strings
  191. StrCpyW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L"(&");
  192. StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pOriginalQuery);
  193. StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), pQuery);
  194. StrCatW((LPWSTR)ByteOffset(pDsQuery, pDsQuery->offsetQuery), L")");
  195. pDsQuery->cbStruct += cbQuery;
  196. }
  197. hres = S_OK;
  198. exit_gracefully:
  199. LocalFreeStringW(&pOriginalQuery);
  200. TraceLeaveResult(hres);
  201. }
  202. /*-----------------------------------------------------------------------------
  203. / Form to query string helper functions
  204. /----------------------------------------------------------------------------*/
  205. /*-----------------------------------------------------------------------------
  206. / GetQueryString
  207. / --------------
  208. / Build the form parmaeters into a LDAP query string using the given table.
  209. /
  210. / In:
  211. / ppQuery -> receives the string pointer
  212. / pPrefixQuery -> string placed at head of query / = NULL if none
  213. / hDlg = handle for the dialog to get the data from
  214. / aCtrls / iCtrls = control information for the window
  215. /
  216. / Out:
  217. / HRESULT
  218. /----------------------------------------------------------------------------*/
  219. STDAPI GetQueryString(LPWSTR* ppQuery, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrls, INT iCtrls)
  220. {
  221. HRESULT hres;
  222. UINT cLen = 0;
  223. TraceEnter(TRACE_FORMS, "GetQueryString");
  224. hres = _GetQueryString(NULL, &cLen, pPrefixQuery, hDlg, aCtrls, iCtrls);
  225. FailGracefully(hres, "Failed 1st pass (compute string length)");
  226. if ( cLen )
  227. {
  228. hres = LocalAllocStringLenW(ppQuery, cLen);
  229. FailGracefully(hres, "Failed to alloc buffer for query string");
  230. hres = _GetQueryString(*ppQuery, &cLen, pPrefixQuery, hDlg, aCtrls, iCtrls);
  231. FailGracefully(hres, "Failed 2nd pass (fill buffer)");
  232. }
  233. hres = cLen ? S_OK:S_FALSE;
  234. exit_gracefully:
  235. TraceLeaveResult(hres);
  236. }
  237. /*-----------------------------------------------------------------------------
  238. / _GetQueryString
  239. / ---------------
  240. / Build the string from the controls or just return the buffer size required.
  241. /
  242. / In:
  243. / pQuery -> filled with query string / = NULL
  244. / pLen = updated to reflect the required string length
  245. / pPrefixQuery -> string placed at head of query / = NULL if none
  246. / hDlg = handle for the dialog to get the data from
  247. / aCtrls / iCtrls = control information for the window
  248. /
  249. / Out:
  250. / HRESULT
  251. /----------------------------------------------------------------------------*/
  252. HRESULT _GetQueryString(LPWSTR pQuery, UINT* pLen, LPWSTR pPrefixQuery, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
  253. {
  254. HRESULT hres;
  255. INT i;
  256. TCHAR szBuffer[MAX_PATH];
  257. TraceEnter(TRACE_FORMS, "_GetQueryString");
  258. if ( !hDlg || (!aCtrl && iCtrls) )
  259. ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
  260. Trace(TEXT("Checking %d controls"), iCtrls);
  261. PutStringElementW(pQuery, pLen, pPrefixQuery);
  262. for ( i = 0 ; i < iCtrls; i++ )
  263. {
  264. if ( GetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer, ARRAYSIZE(szBuffer)) )
  265. {
  266. Trace(TEXT("Property %s, value %s"), aCtrl[i].pPropertyName, szBuffer);
  267. GetFilterString(pQuery, pLen, aCtrl[i].iFilter, aCtrl[i].pPropertyName, szBuffer);
  268. }
  269. }
  270. Trace(TEXT("Resulting query is -%s- (%d)"), pQuery ? pQuery:TEXT("<no buffer>"), pLen ? *pLen:0);
  271. hres = S_OK;
  272. exit_gracefully:
  273. TraceLeaveResult(hres);
  274. }
  275. /*-----------------------------------------------------------------------------
  276. / GetFilterString
  277. / ---------------
  278. / Given a property, a property and its filter generate a suitable filter
  279. / string that map returning it into the given buffer via PutStringElement.
  280. /
  281. / In:
  282. / pFilter, pLen = buffer information that we are returning int
  283. / iFilter = condition to be applied
  284. / pProperty -> property name
  285. / pValue -> value
  286. /
  287. / Out:
  288. / HRESULT
  289. /----------------------------------------------------------------------------*/
  290. struct
  291. {
  292. BOOL fNoValue;
  293. BOOL fFixWildcard;
  294. LPWSTR pPrefix;
  295. LPWSTR pOperator;
  296. LPWSTR pPostfix;
  297. }
  298. filter_info[] =
  299. {
  300. //
  301. // The server today does not support contains searches, therefore
  302. // for consistency map that to a STARTSWITH, NOTSTARTSWITH
  303. //
  304. #if 0
  305. 0, 1, L"(", L"=*", L"*)", // CONTAIN
  306. 0, 1, L"(!", L"=*", L"*)", // NOTCONTAINS
  307. #else
  308. 0, 1, L"(", L"=", L"*)", // CONTAINS
  309. 0, 1, L"(!", L"=", L"*)", // NOTCONTAINS
  310. #endif
  311. 0, 1, L"(", L"=", L"*)", // STARTSWITH
  312. 0, 1, L"(", L"=*", L")", // ENDSWITH
  313. 0, 0, L"(", L"=", L")", // IS
  314. 0, 0, L"(!", L"=", L")", // ISNOT
  315. 0, 0, L"(", L">=", L")", // GREATEREQUAL
  316. 0, 0, L"(", L"<=", L")", // LESSEQUAL
  317. 1, 0, L"(", L"=*)", NULL, // DEFINED
  318. 1, 0, L"(!", L"=*)", NULL, // UNDEFINED
  319. 1, 0, L"(", L"=TRUE)", NULL, // TRUE
  320. 1, 0, L"(!", L"=TRUE)", NULL, // FALSE
  321. };
  322. STDAPI GetFilterString(LPWSTR pFilter, UINT* pLen, INT iFilter, LPWSTR pProperty, LPWSTR pValue)
  323. {
  324. HRESULT hres;
  325. TraceEnter(TRACE_VIEW, "GetFilterString");
  326. // Check to see if the value we have contains a wildcard, if it does then just
  327. // make it is exact assuming the user knows what they are doing - ho ho ho!
  328. if ( pValue && filter_info[iFilter-FILTER_FIRST].fFixWildcard )
  329. {
  330. if ( wcschr(pValue, L'*') )
  331. {
  332. TraceMsg("START/ENDS contains wildcards, making is exactly");
  333. iFilter = FILTER_IS;
  334. }
  335. }
  336. // Fix the condition to index into the our array then
  337. // put the string elements down
  338. iFilter -= FILTER_FIRST; // compensate for non-zero index
  339. if ( iFilter >= ARRAYSIZE(filter_info) )
  340. ExitGracefully(hres, E_FAIL, "Bad filter value");
  341. PutStringElementW(pFilter, pLen, filter_info[iFilter].pPrefix);
  342. PutStringElementW(pFilter, pLen, pProperty);
  343. PutStringElementW(pFilter, pLen, filter_info[iFilter].pOperator);
  344. if ( !filter_info[iFilter].fNoValue )
  345. {
  346. LPWSTR pszOutput = pFilter ? (pFilter + lstrlenW(pFilter)) : NULL;
  347. for (; *pValue; pValue++)
  348. {
  349. int cchLen = 1;
  350. switch (*pValue)
  351. {
  352. // case L'*': // do no RFC encode *, if we do then the user cannot do foo* for a wildcarded string
  353. case L'(':
  354. case L')':
  355. case L'\\':
  356. {
  357. if (pszOutput)
  358. {
  359. LPCWSTR pszToHex = L"0123456789abcdef";
  360. *pszOutput++ = L'\\';
  361. *pszOutput++ = pszToHex[(*pValue & 0xf0) >> 4];
  362. *pszOutput++ = pszToHex[(*pValue & 0x0f)];
  363. }
  364. cchLen = 3;
  365. break;
  366. }
  367. default:
  368. if (pszOutput)
  369. {
  370. *pszOutput++ = *pValue;
  371. }
  372. break;
  373. }
  374. if (pLen)
  375. *pLen = (*pLen + cchLen);
  376. }
  377. if (pszOutput)
  378. *pszOutput = L'\0';
  379. }
  380. PutStringElementW(pFilter, pLen, filter_info[iFilter].pPostfix);
  381. Trace(TEXT("Filter is: %s"), pFilter ? pFilter:TEXT("<none>"));
  382. hres = S_OK;
  383. exit_gracefully:
  384. TraceLeaveResult(hres);
  385. }
  386. /*-----------------------------------------------------------------------------
  387. / GetPatternString
  388. / ----------------
  389. / Given a string wrap in suitable wildcards to do the filtering of
  390. / results.
  391. /
  392. / In:
  393. / pPattern, pLen = buffer information that we are returning int
  394. / iFilter = condition to be applied
  395. / pValue -> value
  396. /
  397. / Out:
  398. / VOID
  399. /----------------------------------------------------------------------------*/
  400. struct
  401. {
  402. LPTSTR pPrefix;
  403. LPTSTR pPostfix;
  404. }
  405. pattern_info[] =
  406. {
  407. TEXT("*"), TEXT("*"), // CONTAIN
  408. TEXT("*"), TEXT("*"), // NOTCONTAINS
  409. TEXT(""), TEXT("*"), // STARTSWITH
  410. TEXT("*"), TEXT(""), // ENDSWITH
  411. TEXT(""), TEXT(""), // IS
  412. TEXT(""), TEXT(""), // ISNOT
  413. };
  414. STDAPI GetPatternString(LPTSTR pFilter, UINT* pLen, INT iFilter, LPTSTR pValue)
  415. {
  416. HRESULT hres;
  417. TraceEnter(TRACE_VIEW, "GetFilterString");
  418. iFilter -= FILTER_FIRST; // compensate for non-zero index
  419. if ( iFilter >= ARRAYSIZE(pattern_info) )
  420. ExitGracefully(hres, E_FAIL, "Bad filter value");
  421. PutStringElement(pFilter, pLen, pattern_info[iFilter].pPrefix);
  422. PutStringElement(pFilter, pLen, pValue);
  423. PutStringElement(pFilter, pLen, pattern_info[iFilter].pPostfix);
  424. hres = S_OK;
  425. exit_gracefully:
  426. TraceLeaveResult(hres);
  427. }
  428. /*-----------------------------------------------------------------------------
  429. / Dialog helper functions
  430. /----------------------------------------------------------------------------*/
  431. /*-----------------------------------------------------------------------------
  432. / EnablePageControls
  433. / ------------------
  434. / Enable/Disable the controls on a query form.
  435. /
  436. / In:
  437. / hDlg = handle for the dialog to get the data from
  438. / aCtrls / iCtrls = control information for the window
  439. / fEnable = TRUE/FALSE to enable disable window controls
  440. /
  441. / Out:
  442. / VOID
  443. /----------------------------------------------------------------------------*/
  444. STDAPI_(VOID) EnablePageControls(HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls, BOOL fEnable)
  445. {
  446. HRESULT hres;
  447. INT i;
  448. HWND hwndCtrl;
  449. TraceEnter(TRACE_FORMS, "EnablePageControls");
  450. if ( !hDlg || (!aCtrl && iCtrls) )
  451. ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
  452. Trace(TEXT("%s %d controls"), fEnable ? TEXT("Enabling"):TEXT("Disabling"),iCtrls);
  453. for ( i = 0 ; i < iCtrls; i++ )
  454. {
  455. hwndCtrl = GetDlgItem(hDlg, aCtrl[i].nIDDlgItem);
  456. if ( hwndCtrl )
  457. EnableWindow(hwndCtrl, fEnable);
  458. }
  459. exit_gracefully:
  460. TraceLeave();
  461. }
  462. /*-----------------------------------------------------------------------------
  463. / ResetPageControls
  464. / ------------------
  465. / Reset all the form controls back to their default state.
  466. /
  467. / In:
  468. / hDlg = handle for the dialog to get the data from
  469. / aCtrls / iCtrls = control information for the window
  470. /
  471. / Out:
  472. / VOID
  473. /----------------------------------------------------------------------------*/
  474. STDAPI_(VOID) ResetPageControls(HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
  475. {
  476. HRESULT hres;
  477. INT i;
  478. TraceEnter(TRACE_FORMS, "ResetPageControls");
  479. if ( !hDlg || (!aCtrl && iCtrls) )
  480. ExitGracefully(hres, E_INVALIDARG, "No dialog or controls list");
  481. for ( i = 0 ; i < iCtrls; i++ )
  482. SetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, TEXT(""));
  483. exit_gracefully:
  484. TraceLeave();
  485. }
  486. /*-----------------------------------------------------------------------------
  487. / SetDlgItemFromProperty
  488. / ----------------------
  489. / Given an IPropertyBag interface set the control with the text for
  490. / that property. We assume the property is a string.
  491. /
  492. / In:
  493. / ppb -> IPropertyBag
  494. / pszProperty -> property to read
  495. / hwnd, id = control information
  496. / pszDefault = default text / = NULL if not important
  497. /
  498. / Out:
  499. / HRESULT
  500. /----------------------------------------------------------------------------*/
  501. STDAPI SetDlgItemFromProperty(IPropertyBag* ppb, LPCWSTR pszProperty, HWND hwnd, INT id, LPCWSTR pszDefault)
  502. {
  503. HRESULT hres;
  504. VARIANT variant;
  505. TraceEnter(TRACE_FORMS, "SetDlgItemFromProperty");
  506. VariantInit(&variant);
  507. if ( ppb && SUCCEEDED(ppb->Read(pszProperty, &variant, NULL)) )
  508. {
  509. if ( V_VT(&variant) == VT_BSTR )
  510. {
  511. pszDefault = V_BSTR(&variant);
  512. Trace(TEXT("property contained: %s"), pszDefault);
  513. }
  514. }
  515. if ( pszDefault )
  516. SetDlgItemText(hwnd, id, pszDefault);
  517. VariantClear(&variant);
  518. TraceLeaveResult(S_OK);
  519. }
  520. /*-----------------------------------------------------------------------------
  521. / Query Persistance
  522. /----------------------------------------------------------------------------*/
  523. /*-----------------------------------------------------------------------------
  524. / PersistQuery
  525. / ------------
  526. / Persist a query into a IPersistQuery object
  527. /
  528. / In:
  529. / pPersistQuery = query to persist into
  530. / fRead = read?
  531. / pSectionName = section name to use when persisting
  532. / hDlg = DLG to persist from
  533. / aCtrls / iCtrls = ctrls to be persisted
  534. /
  535. / Out:
  536. / HRESULT
  537. /----------------------------------------------------------------------------*/
  538. STDAPI PersistQuery(IPersistQuery* pPersistQuery, BOOL fRead, LPCTSTR pSection, HWND hDlg, LPPAGECTRL aCtrl, INT iCtrls)
  539. {
  540. HRESULT hres = S_OK;
  541. TCHAR szBuffer[MAX_PATH];
  542. INT i;
  543. TraceEnter(TRACE_IO, "PersistQuery");
  544. if ( !pPersistQuery || !hDlg || (!aCtrl && iCtrls) )
  545. ExitGracefully(hres, E_INVALIDARG, "No data to persist");
  546. for ( i = 0 ; i < iCtrls ; i++ )
  547. {
  548. if ( fRead )
  549. {
  550. if ( SUCCEEDED(pPersistQuery->ReadString(pSection, aCtrl[i].pPropertyName, szBuffer, ARRAYSIZE(szBuffer))) )
  551. {
  552. Trace(TEXT("Reading property: %s,%s as %s"), pSection, aCtrl[i].pPropertyName, szBuffer);
  553. SetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer);
  554. }
  555. }
  556. else
  557. {
  558. if ( GetDlgItemText(hDlg, aCtrl[i].nIDDlgItem, szBuffer, ARRAYSIZE(szBuffer)) )
  559. {
  560. Trace(TEXT("Writing property: %s,%s as %s"), pSection, aCtrl[i].pPropertyName, szBuffer);
  561. hres = pPersistQuery->WriteString(pSection, aCtrl[i].pPropertyName, szBuffer);
  562. FailGracefully(hres, "Failed to write control data");
  563. }
  564. }
  565. }
  566. hres = S_OK;
  567. exit_gracefully:
  568. TraceLeaveResult(hres);
  569. }