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.

878 lines
22 KiB

  1. #include "pch.h"
  2. #include <urlmon.h>
  3. #pragma hdrstop
  4. /*-----------------------------------------------------------------------------
  5. / Internal only string APIs
  6. /----------------------------------------------------------------------------*/
  7. /*-----------------------------------------------------------------------------
  8. / StringToDWORD
  9. / -------------
  10. / Scan the string converting it to a DWORD, cope with hex and decimal alike,
  11. / more than likely we will receive a hex number though.
  12. /
  13. / In:
  14. / pString -> string to parse
  15. /
  16. / Out:
  17. / DWORD
  18. /----------------------------------------------------------------------------*/
  19. DWORD StringToDWORD(LPWSTR pString)
  20. {
  21. DWORD dwResult = 0x0;
  22. USES_CONVERSION;
  23. TraceEnter(TRACE_COMMONAPI, "StringToDWORD");
  24. Trace(TEXT("pString %s"), W2T(pString));
  25. // Is the leading sequence 0x? If so then lets parse as hex, otherwise
  26. // we can pass to StrToInt.
  27. if ( pString[0] == L'0' && pString[1] == L'x' )
  28. {
  29. for ( pString += 2; *pString; pString++ )
  30. {
  31. WCHAR ch = *pString;
  32. if ( InRange(ch, L'0', L'9') )
  33. {
  34. dwResult = (dwResult << 4) | (ch - L'0');
  35. }
  36. else if ( InRange(ch | (L'a'-L'A'), L'a', L'f') )
  37. {
  38. dwResult = (dwResult << 4) | (ch - L'a' + 10);
  39. }
  40. else
  41. {
  42. break; // tread non 0-9, A-F as end of string
  43. }
  44. }
  45. }
  46. else
  47. {
  48. dwResult = (DWORD)StrToIntW(pString);
  49. }
  50. Trace(TEXT("DWORD result is %08x"), dwResult);
  51. TraceLeaveValue(dwResult);
  52. }
  53. /*-----------------------------------------------------------------------------
  54. / StringToURL
  55. / -----------
  56. / Convert a string to URL format, mashing the characters as required.
  57. /
  58. / In:
  59. / pString -> string to be converted
  60. / ppResult -> receives a pointer to the new string (free using LocalFreeString).
  61. /
  62. / Out:
  63. / HRESULT
  64. /----------------------------------------------------------------------------*/
  65. HRESULT StringToURL(LPCTSTR pString, LPTSTR* ppResult)
  66. {
  67. HRESULT hr;
  68. TCHAR szEncodedURL[INTERNET_MAX_URL_LENGTH];
  69. DWORD dwLen = ARRAYSIZE(szEncodedURL);
  70. int i;
  71. TraceEnter(TRACE_COMMONAPI, "StringToURL");
  72. TraceAssert(pString);
  73. TraceAssert(ppResult);
  74. *ppResult = NULL; // incase of failure
  75. if ( !InternetCanonicalizeUrl(pString, szEncodedURL, &dwLen, 0) )
  76. ExitGracefully(hr, E_FAIL, "Failed to convert URL to encoded format");
  77. hr = LocalAllocString(ppResult, szEncodedURL);
  78. FailGracefully(hr, "Failed to allocate copy of URL");
  79. hr = S_OK; // success
  80. exit_gracefully:
  81. if ( FAILED(hr) && *ppResult )
  82. LocalFreeString(ppResult);
  83. TraceLeaveResult(hr);
  84. }
  85. /*-----------------------------------------------------------------------------
  86. / Exported APIs
  87. /----------------------------------------------------------------------------*/
  88. /*-----------------------------------------------------------------------------
  89. / StringDPA_InsertString
  90. / ----------------------
  91. / Make a copy of the given string and place it into the DPA. It can then
  92. / be accessed using the StringDPA_GetString, or free'd using the
  93. / StringDPA_Destroy/StringDPA_DeleteString.
  94. /
  95. / In:
  96. / hdpa = DPA to put string into
  97. / i = index to insert at
  98. / pString -> string to be inserted
  99. /
  100. / Out:
  101. / HRESULT
  102. /----------------------------------------------------------------------------*/
  103. STDAPI StringDPA_InsertStringA(HDPA hdpa, INT i, LPCSTR pString)
  104. {
  105. if ( hdpa && pString )
  106. {
  107. LPSTR pStringCopy = NULL;
  108. HRESULT hr = LocalAllocStringA(&pStringCopy, pString);
  109. if ( FAILED(hr) )
  110. return hr;
  111. if ( -1 == DPA_InsertPtr(hdpa, i, pStringCopy) )
  112. {
  113. LocalFreeStringA(&pStringCopy);
  114. return E_OUTOFMEMORY;
  115. }
  116. }
  117. return S_OK;
  118. }
  119. STDAPI StringDPA_InsertStringW(HDPA hdpa, INT i, LPCWSTR pString)
  120. {
  121. if ( hdpa && pString )
  122. {
  123. LPWSTR pStringCopy = NULL;
  124. HRESULT hr = LocalAllocStringW(&pStringCopy, pString);
  125. if ( FAILED(hr) )
  126. return hr;
  127. if ( -1 == DPA_InsertPtr(hdpa, i, pStringCopy) )
  128. {
  129. LocalFreeStringW(&pStringCopy);
  130. return E_OUTOFMEMORY;
  131. }
  132. }
  133. return S_OK;
  134. }
  135. /*-----------------------------------------------------------------------------
  136. / StringDPA_AppendString
  137. / ----------------------
  138. / Make a copy of the given string and place it into the DPA. It can then
  139. / be accessed using the StringDPA_GetString, or free'd using the
  140. / StringDPA_Destroy/StringDPA_DeleteString.
  141. /
  142. / In:
  143. / hdpa = DPA to put string into
  144. / pString -> string to be append
  145. / pres = resulting index
  146. /
  147. / Out:
  148. / HRESULT
  149. /----------------------------------------------------------------------------*/
  150. STDAPI StringDPA_AppendStringA(HDPA hdpa, LPCSTR pString, PUINT_PTR pres)
  151. {
  152. HRESULT hr;
  153. INT ires = 0;
  154. LPSTR pStringCopy = NULL;
  155. TraceEnter(TRACE_COMMONAPI, "StringDPA_AppendStringA");
  156. TraceAssert(hdpa);
  157. TraceAssert(pString);
  158. if ( hdpa && pString )
  159. {
  160. hr = LocalAllocStringA(&pStringCopy, pString);
  161. FailGracefully(hr, "Failed to allocate string copy");
  162. ires = DPA_AppendPtr(hdpa, pStringCopy);
  163. if ( -1 == ires )
  164. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to add string to DPA");
  165. if ( pres )
  166. *pres = ires;
  167. }
  168. hr = S_OK;
  169. exit_gracefully:
  170. if ( FAILED(hr) )
  171. LocalFreeStringA(&pStringCopy);
  172. TraceLeaveResult(hr);
  173. }
  174. STDAPI StringDPA_AppendStringW(HDPA hdpa, LPCWSTR pString, PUINT_PTR pres)
  175. {
  176. HRESULT hr;
  177. INT ires = 0;
  178. LPWSTR pStringCopy = NULL;
  179. TraceEnter(TRACE_COMMONAPI, "StringDPA_AppendStringW");
  180. TraceAssert(hdpa);
  181. TraceAssert(pString);
  182. if ( hdpa && pString )
  183. {
  184. hr = LocalAllocStringW(&pStringCopy, pString);
  185. FailGracefully(hr, "Failed to allocate string copy");
  186. ires = DPA_AppendPtr(hdpa, pStringCopy);
  187. if ( -1 == ires )
  188. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to add string to DPA");
  189. if ( pres )
  190. *pres = ires;
  191. }
  192. hr = S_OK;
  193. exit_gracefully:
  194. if ( FAILED(hr) )
  195. LocalFreeStringW(&pStringCopy);
  196. TraceLeaveResult(hr);
  197. }
  198. /*-----------------------------------------------------------------------------
  199. / StringDPA_DeleteString
  200. / ----------------------
  201. / Delete the specified index from the DPA, freeing the string element
  202. / that we have dangling from the index.
  203. /
  204. / In:
  205. / hdpa -> handle to DPA to be destroyed
  206. / index = index of item to free
  207. /
  208. / Out:
  209. / -
  210. /----------------------------------------------------------------------------*/
  211. STDAPI_(VOID) StringDPA_DeleteString(HDPA hdpa, INT index)
  212. {
  213. TraceEnter(TRACE_COMMONAPI, "StringDPA_DeleteString");
  214. if ( hdpa && (index < DPA_GetPtrCount(hdpa)) )
  215. {
  216. // assumes LocalAllocString uses LocalAlloc (fair enough I guess)
  217. LocalFree((HLOCAL)DPA_FastGetPtr(hdpa, index));
  218. DPA_DeletePtr(hdpa, index);
  219. }
  220. TraceLeave();
  221. }
  222. /*-----------------------------------------------------------------------------
  223. / StringDPA_Destroy
  224. / -----------------
  225. / Take the given string DPA and destory it.
  226. /
  227. / In:
  228. / pHDPA -> handle to DPA to be destroyed
  229. /
  230. / Out:
  231. / -
  232. /----------------------------------------------------------------------------*/
  233. INT _DestroyStringDPA(LPVOID pItem, LPVOID pData)
  234. {
  235. // assumes that LocalAllocString does just that,
  236. // to store the string.
  237. LocalFree((HLOCAL)pItem);
  238. return 1;
  239. }
  240. STDAPI_(VOID) StringDPA_Destroy(HDPA* pHDPA)
  241. {
  242. TraceEnter(TRACE_COMMONAPI, "StringDPA_Destroy");
  243. if ( pHDPA && *pHDPA )
  244. {
  245. DPA_DestroyCallback(*pHDPA, _DestroyStringDPA, NULL);
  246. *pHDPA = NULL;
  247. }
  248. TraceLeave();
  249. }
  250. /*-----------------------------------------------------------------------------
  251. / LocalAllocString
  252. / ------------------
  253. / Allocate a string, and initialize it with the specified contents.
  254. /
  255. / In:
  256. / ppResult -> recieves pointer to the new string
  257. / pString -> string to initialize with
  258. /
  259. / Out:
  260. / HRESULT
  261. /----------------------------------------------------------------------------*/
  262. STDAPI LocalAllocStringA(LPSTR* ppResult, LPCSTR pString)
  263. {
  264. *ppResult = NULL;
  265. if ( pString )
  266. {
  267. *ppResult = (LPSTR)LocalAlloc(LPTR, StringByteSizeA(pString));
  268. if ( !*ppResult )
  269. return E_OUTOFMEMORY;
  270. StrCpyA(*ppResult, pString);
  271. }
  272. return S_OK;
  273. }
  274. STDAPI LocalAllocStringW(LPWSTR* ppResult, LPCWSTR pString)
  275. {
  276. *ppResult = NULL;
  277. if ( pString )
  278. {
  279. *ppResult = (LPWSTR)LocalAlloc(LPTR, StringByteSizeW(pString));
  280. if ( !*ppResult )
  281. return E_OUTOFMEMORY;
  282. StrCpyW(*ppResult, pString);
  283. }
  284. return S_OK;
  285. }
  286. /*----------------------------------------------------------------------------
  287. / LocalAllocStringLen
  288. / -------------------
  289. / Given a length return a buffer of that size.
  290. /
  291. / In:
  292. / ppResult -> receives the pointer to the string
  293. / cLen = length in characters to allocate
  294. /
  295. / Out:
  296. / HRESULT
  297. /----------------------------------------------------------------------------*/
  298. STDAPI LocalAllocStringLenA(LPSTR* ppResult, UINT cLen)
  299. {
  300. *ppResult = (LPSTR)LocalAlloc(LPTR, (cLen+1)*SIZEOF(CHAR));
  301. return (*ppResult) ? S_OK:E_OUTOFMEMORY;
  302. }
  303. STDAPI LocalAllocStringLenW(LPWSTR* ppResult, UINT cLen)
  304. {
  305. *ppResult = (LPWSTR)LocalAlloc(LPTR, (cLen+1)*SIZEOF(WCHAR));
  306. return (*ppResult) ? S_OK:E_OUTOFMEMORY;
  307. }
  308. /*-----------------------------------------------------------------------------
  309. / LocalFreeString
  310. / -----------------
  311. / Release the string pointed to be *ppString (which can be null) and
  312. / then reset the pointer back to NULL.
  313. /
  314. / In:
  315. / ppString -> pointer to string pointer to be free'd
  316. /
  317. / Out:
  318. / -
  319. /----------------------------------------------------------------------------*/
  320. VOID LocalFreeStringA(LPSTR* ppString)
  321. {
  322. LocalFreeStringW((LPWSTR*)ppString);
  323. }
  324. VOID LocalFreeStringW(LPWSTR* ppString)
  325. {
  326. if ( ppString )
  327. {
  328. if ( *ppString )
  329. LocalFree((HLOCAL)*ppString);
  330. *ppString = NULL;
  331. }
  332. }
  333. /*-----------------------------------------------------------------------------
  334. / LocalQueryString
  335. / ------------------
  336. / Hit the registry returning the wide version of the given string,
  337. / we dynamically allocate the buffer to put the result into,
  338. / this should be free'd by calling LocalFreeString.
  339. /
  340. / In:
  341. / ppString -> receives the string point
  342. / hkey = key to query from
  343. / pSubKey -> pointer to sub key identifier
  344. /
  345. /
  346. / Out:
  347. / -
  348. /----------------------------------------------------------------------------*/
  349. STDAPI _LocalQueryString(LPTSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
  350. {
  351. HRESULT hr;
  352. DWORD dwSize = NULL;
  353. TraceEnter(TRACE_COMMONAPI, "_LocalQueryString");
  354. *ppResult = NULL;
  355. if ( ERROR_SUCCESS != RegQueryValueEx(hKey, pSubKey, NULL, NULL, NULL, &dwSize) )
  356. ExitGracefully(hr, E_FAIL, "Failed when querying for key size");
  357. dwSize += SIZEOF(TCHAR);
  358. *ppResult = (LPTSTR)LocalAlloc(LPTR, dwSize);
  359. if ( !*ppResult )
  360. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate buffer for value");
  361. if ( ERROR_SUCCESS != RegQueryValueEx(hKey, pSubKey, NULL, NULL, (LPBYTE)*ppResult, &dwSize) )
  362. ExitGracefully(hr, E_FAIL, "Failed to read key value into buffer");
  363. hr = S_OK;
  364. exit_gracefully:
  365. if ( FAILED(hr) )
  366. LocalFreeString(ppResult);
  367. TraceLeaveResult(hr);
  368. }
  369. // Query string as ANSI, converting to ANSI if build UNICODE
  370. STDAPI LocalQueryStringA(LPSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
  371. {
  372. HRESULT hr;
  373. LPTSTR pResult = NULL;
  374. USES_CONVERSION;
  375. TraceEnter(TRACE_COMMONAPI, "LocalQueryStringA");
  376. *ppResult = NULL; // incase of failure
  377. #ifdef UNICODE
  378. hr = _LocalQueryString(&pResult, hKey, pSubKey);
  379. FailGracefully(hr, "Failed to read the UNICODE version of string");
  380. hr = LocalAllocStringW2A(ppResult, pResult);
  381. FailGracefully(hr, "Failed to allocate ANSI version of string");
  382. #else
  383. hr = _LocalQueryString(ppResult, hKey, pSubKey);
  384. FailGracefully(hr, "Failed to get key value");
  385. #endif
  386. exit_gracefully:
  387. if ( FAILED(hr) )
  388. LocalFreeStringA(ppResult);
  389. LocalFreeString(&pResult);
  390. TraceLeaveResult(hr);
  391. }
  392. // Query string as UNICODE, converting to UNICODE if built ANSI
  393. STDAPI LocalQueryStringW(LPWSTR* ppResult, HKEY hKey, LPCTSTR pSubKey)
  394. {
  395. HRESULT hr;
  396. LPTSTR pResult = NULL;
  397. USES_CONVERSION;
  398. TraceEnter(TRACE_COMMONAPI, "LocalQueryStringW");
  399. *ppResult = NULL; // incase of failure
  400. #ifdef UNICODE
  401. hr = _LocalQueryString(ppResult, hKey, pSubKey);
  402. FailGracefully(hr, "Falied to get key value");
  403. #else
  404. hr = _LocalQueryString(&pResult, hKey, pSubKey);
  405. FailGracefully(hr, "Failed to query key as ANSI string");
  406. hr = LocalAllocStringA2W(ppResult, pResult);
  407. FailGracefully(hr, "Failed to allocate UNICODE version of string");
  408. #endif
  409. exit_gracefully:
  410. if ( FAILED(hr) )
  411. LocalFreeStringW(ppResult);
  412. LocalFreeString(&pResult);
  413. TraceLeaveResult(hr);
  414. }
  415. /*-----------------------------------------------------------------------------
  416. / LocalAllocStringA2W / W2A
  417. / -------------------------
  418. / Alloc a string converting using MultiByteToWideChar or vice versa. This
  419. / allows in place thunking of strings without extra buffer usage.
  420. /
  421. / In:
  422. / ppResult -> receives the string point
  423. / pString -> source string
  424. /
  425. / Out:
  426. / HRESULT
  427. /----------------------------------------------------------------------------*/
  428. STDAPI LocalAllocStringA2W(LPWSTR* ppResult, LPCSTR pString)
  429. {
  430. HRESULT hr;
  431. INT iLen;
  432. TraceEnter(TRACE_COMMONAPI, "LocalAllocStringA2W");
  433. if ( !ppResult && !pString )
  434. ExitGracefully(hr, E_INVALIDARG, "Bad args for thunked allocate");
  435. iLen = MultiByteToWideChar(CP_ACP, 0, pString, -1, NULL, 0);
  436. hr = LocalAllocStringLenW(ppResult, iLen);
  437. FailGracefully(hr, "Failed to allocate buffer for string");
  438. MultiByteToWideChar(CP_ACP, 0, pString, -1, *ppResult, iLen+1);
  439. hr = S_OK;
  440. exit_gracefully:
  441. TraceLeaveResult(hr);
  442. }
  443. STDAPI LocalAllocStringW2A(LPSTR* ppResult, LPCWSTR pString)
  444. {
  445. HRESULT hr;
  446. INT iLen;
  447. TraceEnter(TRACE_COMMONAPI, "LocalAllocStringW2A");
  448. if ( !ppResult && !pString )
  449. ExitGracefully(hr, E_INVALIDARG, "Bad args for thunked allocate");
  450. iLen = WideCharToMultiByte(CP_ACP, 0, pString, -1, NULL, 0, NULL, NULL);
  451. hr = LocalAllocStringLenA(ppResult, iLen);
  452. FailGracefully(hr, "Failed to allocate buffer for string");
  453. WideCharToMultiByte(CP_ACP, 0, pString, -1, *ppResult, iLen+1, NULL, NULL);
  454. hr = S_OK;
  455. exit_gracefully:
  456. TraceLeaveResult(hr);
  457. }
  458. /*-----------------------------------------------------------------------------
  459. / PutStringElement
  460. / -----------------
  461. / Add a string to the given buffer, always updating the cLen to indicate
  462. / how many characters would have been added
  463. /
  464. / In:
  465. / pBuffer -> buffer to append to
  466. / pLen -> length value (updated)
  467. / pString -> string to add to buffer
  468. /
  469. / Out:
  470. / -
  471. /----------------------------------------------------------------------------*/
  472. STDAPI_(VOID) PutStringElementA(LPSTR pBuffer, UINT* pLen, LPCSTR pElement)
  473. {
  474. TraceEnter(TRACE_COMMONAPI, "PutStringElementA");
  475. if ( pElement )
  476. {
  477. if ( pBuffer )
  478. lstrcatA(pBuffer, pElement);
  479. if ( pLen )
  480. *pLen += lstrlenA(pElement);
  481. }
  482. TraceLeave();
  483. }
  484. STDAPI_(VOID) PutStringElementW(LPWSTR pBuffer, UINT* pLen, LPCWSTR pElement)
  485. {
  486. TraceEnter(TRACE_COMMONAPI, "PutStringElementW");
  487. if ( pElement )
  488. {
  489. if ( pBuffer )
  490. StrCatW(pBuffer, pElement);
  491. if ( pLen )
  492. *pLen += lstrlenW(pElement);
  493. }
  494. TraceLeave();
  495. }
  496. /*-----------------------------------------------------------------------------
  497. / GetStringElement
  498. / ----------------
  499. / Extract the n'th element from the given string. Each element is assumed
  500. / to be terminated with either a "," or a NULL.
  501. /
  502. / In:
  503. / pString -> string to parse
  504. / index = element to retrieve
  505. / pBuffer, cchBuffer = buffer to fill
  506. /
  507. / Out:
  508. / HRESULT
  509. /----------------------------------------------------------------------------*/
  510. STDAPI GetStringElementA(LPSTR pString, INT index, LPSTR pBuffer, INT cchBuffer)
  511. {
  512. HRESULT hr = E_FAIL;
  513. USES_CONVERSION;
  514. TraceEnter(TRACE_COMMONAPI, "GetStringElement");
  515. Trace(TEXT("pString %s, index %d"), A2T(pString), index);
  516. *pBuffer = '\0';
  517. for ( ; index > 0 ; index-- )
  518. {
  519. while ( (*pString != ',') && (*pString != '\0') )
  520. pString++;
  521. if ( *pString == ',' )
  522. pString++;
  523. }
  524. if ( !index )
  525. {
  526. while ( *pString == ' ' )
  527. pString++;
  528. while ( cchBuffer-- && (*pString != ',') && (*pString != '\0') )
  529. *pBuffer++ = *pString++;
  530. if ( cchBuffer )
  531. *pBuffer = '\0';
  532. hr = cchBuffer ? S_OK:E_FAIL;
  533. }
  534. TraceLeaveResult(hr);
  535. }
  536. STDAPI GetStringElementW(LPWSTR pString, INT index, LPWSTR pBuffer, INT cchBuffer)
  537. {
  538. HRESULT hr = E_FAIL;
  539. USES_CONVERSION;
  540. TraceEnter(TRACE_COMMONAPI, "GetStringElement");
  541. Trace(TEXT("pString %s, index %d"), W2T(pString), index);
  542. *pBuffer = L'\0';
  543. for ( ; index > 0 ; index-- )
  544. {
  545. while ( *pString != L',' && *pString != L'\0' )
  546. pString++;
  547. if ( *pString == L',' )
  548. pString++;
  549. }
  550. if ( !index )
  551. {
  552. while ( *pString == L' ' )
  553. pString++;
  554. while ( cchBuffer-- && (*pString != L',') && (*pString != L'\0') )
  555. *pBuffer++ = *pString++;
  556. if ( cchBuffer )
  557. *pBuffer = L'\0';
  558. hr = cchBuffer ? S_OK:E_FAIL;
  559. }
  560. TraceLeaveResult(hr);
  561. }
  562. /*-----------------------------------------------------------------------------
  563. / FormatMsgResource
  564. / -----------------
  565. / Load a string resource and pass it to format message, allocating a buffer
  566. / as we go.
  567. /
  568. / In:
  569. / ppString -> receives the string point
  570. / hInstance = module handle for template string
  571. / uID = template string
  572. / ... = format parameters
  573. /
  574. / Out:
  575. / HRESULT
  576. /----------------------------------------------------------------------------*/
  577. STDAPI FormatMsgResource(LPTSTR* ppString, HINSTANCE hInstance, UINT uID, ...)
  578. {
  579. HRESULT hr;
  580. TCHAR szBuffer[MAX_PATH];
  581. va_list va;
  582. TraceEnter(TRACE_COMMONAPI, "FormatMsgResource");
  583. va_start(va, uID);
  584. if ( !LoadString(hInstance, uID, szBuffer, ARRAYSIZE(szBuffer)) )
  585. ExitGracefully(hr, E_FAIL, "Failed to load template string");
  586. if ( !FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  587. (LPVOID)szBuffer, 0, 0,
  588. (LPTSTR)ppString, SIZEOF(ppString),
  589. &va) )
  590. {
  591. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to format the message");
  592. }
  593. Trace(TEXT("Resulting string: %s"), *ppString);
  594. hr = S_OK; // success
  595. exit_gracefully:
  596. va_end(va);
  597. TraceLeaveResult(hr);
  598. }
  599. /*-----------------------------------------------------------------------------
  600. / FormatMsgBox
  601. / ------------
  602. / Call FormatMessage and MessageBox together having built a suitable
  603. / string to display to the user.
  604. /
  605. / In:
  606. / ppString -> receives the string point
  607. / hInstance = module handle for template string
  608. / uID = template string
  609. / ... = format parameters
  610. /
  611. / Out:
  612. / HRESULT
  613. /----------------------------------------------------------------------------*/
  614. STDAPI_(INT) FormatMsgBox(HWND hWnd, HINSTANCE hInstance, UINT uidTitle, UINT uidPrompt, UINT uType, ...)
  615. {
  616. INT iResult = -1; // failure
  617. LPTSTR pPrompt = NULL;
  618. TCHAR szTitle[MAX_PATH];
  619. TCHAR szBuffer[MAX_PATH];
  620. va_list va;
  621. TraceEnter(TRACE_COMMONAPI, "FormatMsgBox");
  622. va_start(va, uType);
  623. LoadString(hInstance, uidTitle, szTitle, ARRAYSIZE(szTitle));
  624. LoadString(hInstance, uidPrompt, szBuffer, ARRAYSIZE(szBuffer));
  625. if ( FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  626. (LPVOID)szBuffer, 0, 0,
  627. (LPTSTR)&pPrompt, SIZEOF(pPrompt),
  628. &va) )
  629. {
  630. Trace(TEXT("Title: %s"), szTitle);
  631. Trace(TEXT("Prompt: %s"), pPrompt);
  632. iResult = MessageBox(hWnd, pPrompt, szTitle, uType);
  633. LocalFree(pPrompt);
  634. }
  635. Trace(TEXT("Result is %d"), iResult);
  636. va_end(va);
  637. TraceLeaveValue(iResult);
  638. }
  639. /*-----------------------------------------------------------------------------
  640. / FormatDirectoryName
  641. / -------------------
  642. / Collect the directory name and format it using a text resource specified.
  643. /
  644. / In:
  645. / ppString = receives the string pointer for the result
  646. / clisdNamespace = namespace instance
  647. / hInstance = instance handle to load resource from
  648. / uID = resource ID for string
  649. /
  650. / Out:
  651. / HRESULT
  652. /----------------------------------------------------------------------------*/
  653. STDAPI FormatDirectoryName(LPTSTR* ppString, HINSTANCE hInstance, UINT uID)
  654. {
  655. HRESULT hr;
  656. TCHAR szBuffer[MAX_PATH];
  657. LPTSTR pDisplayName = NULL;
  658. HKEY hKey = NULL;
  659. TraceEnter(TRACE_COMMONAPI, "FormatDirectoryName");
  660. // No IDsFolder then lets ensure that we have one
  661. hr = GetKeyForCLSID(CLSID_MicrosoftDS, NULL, &hKey);
  662. FailGracefully(hr, "Failed to open namespace's registry key");
  663. hr = LocalQueryString(&pDisplayName, hKey, NULL);
  664. FailGracefully(hr, "Failed to get the namespace display name");
  665. Trace(TEXT("Display name is: %s"), pDisplayName);
  666. if ( hInstance )
  667. {
  668. hr = FormatMsgResource(ppString, hInstance, uID, pDisplayName);
  669. FailGracefully(hr, "Failed to format from resource");
  670. }
  671. else
  672. {
  673. *ppString = pDisplayName;
  674. pDisplayName = NULL;
  675. }
  676. hr = S_OK; // success
  677. exit_gracefully:
  678. LocalFreeString(&pDisplayName);
  679. if ( hKey )
  680. RegCloseKey(hKey);
  681. TraceLeaveResult(hr);
  682. }