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.

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