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.

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