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.

1234 lines
32 KiB

  1. /*****************************************************************************\
  2. FILE: util.cpp
  3. DESCRIPTION:
  4. Shared stuff that operates on all classes.
  5. BryanSt 5/30/2000
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #include "util.h"
  11. #include <comdef.h>
  12. /////////////////////////////////////////////////////////////////////
  13. // String Helpers
  14. /////////////////////////////////////////////////////////////////////
  15. HINSTANCE g_hinst; // My instance handle
  16. #ifdef DEBUG
  17. DWORD g_TLSliStopWatchStartHi = 0;
  18. DWORD g_TLSliStopWatchStartLo = 0;
  19. LARGE_INTEGER g_liStopWatchFreq = {0};
  20. #endif // DEBUG
  21. /////////////////////////////////////////////////////////////////////
  22. // Debug Timing Helpers
  23. /////////////////////////////////////////////////////////////////////
  24. #ifdef DEBUG
  25. void DebugStartWatch(void)
  26. {
  27. LARGE_INTEGER liStopWatchStart;
  28. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  29. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  30. // ASSERT(!liStopWatchStart.QuadPart); // If you hit this, then the stopwatch is nested.
  31. QueryPerformanceFrequency(&g_liStopWatchFreq);
  32. QueryPerformanceCounter(&liStopWatchStart);
  33. TlsSetValue(g_TLSliStopWatchStartHi, IntToPtr(liStopWatchStart.HighPart));
  34. TlsSetValue(g_TLSliStopWatchStartLo, IntToPtr(liStopWatchStart.LowPart));
  35. }
  36. DWORD DebugStopWatch(void)
  37. {
  38. LARGE_INTEGER liDiff;
  39. LARGE_INTEGER liStopWatchStart;
  40. QueryPerformanceCounter(&liDiff);
  41. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  42. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  43. liDiff.QuadPart -= liStopWatchStart.QuadPart;
  44. ASSERT(0 != g_liStopWatchFreq.QuadPart); // I don't like to fault with div 0.
  45. DWORD dwTime = (DWORD)((liDiff.QuadPart * 1000) / g_liStopWatchFreq.QuadPart);
  46. TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) 0);
  47. TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) 0);
  48. return dwTime;
  49. }
  50. #endif // DEBUG
  51. /////////////////////////////////////////////////////////////////////
  52. // String Helpers
  53. /////////////////////////////////////////////////////////////////////
  54. #undef SysAllocStringA
  55. BSTR SysAllocStringA(LPCSTR pszStr)
  56. {
  57. BSTR bstrOut = NULL;
  58. if (pszStr)
  59. {
  60. DWORD cchSize = (lstrlenA(pszStr) + 1);
  61. LPWSTR pwszThunkTemp = (LPWSTR) LocalAlloc(LPTR, (sizeof(pwszThunkTemp[0]) * cchSize)); // assumes INFOTIPSIZE number of chars max
  62. if (pwszThunkTemp)
  63. {
  64. SHAnsiToUnicode(pszStr, pwszThunkTemp, cchSize);
  65. bstrOut = SysAllocString(pwszThunkTemp);
  66. LocalFree(pwszThunkTemp);
  67. }
  68. }
  69. return bstrOut;
  70. }
  71. HRESULT HrSysAllocStringA(IN LPCSTR pszSource, OUT BSTR * pbstrDest)
  72. {
  73. HRESULT hr = S_OK;
  74. if (pbstrDest)
  75. {
  76. *pbstrDest = SysAllocStringA(pszSource);
  77. if (pszSource)
  78. {
  79. if (*pbstrDest)
  80. hr = S_OK;
  81. else
  82. hr = E_OUTOFMEMORY;
  83. }
  84. }
  85. return hr;
  86. }
  87. HRESULT HrSysAllocStringW(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  88. {
  89. HRESULT hr = S_OK;
  90. if (pbstrDest)
  91. {
  92. *pbstrDest = SysAllocString(pwzSource);
  93. if (pwzSource)
  94. {
  95. if (*pbstrDest)
  96. hr = S_OK;
  97. else
  98. hr = E_OUTOFMEMORY;
  99. }
  100. }
  101. return hr;
  102. }
  103. HRESULT BSTRFromStream(IStream * pStream, BSTR * pbstr)
  104. {
  105. STATSTG statStg = {0};
  106. HRESULT hr = pStream->Stat(&statStg, STATFLAG_NONAME);
  107. if (S_OK == hr)
  108. {
  109. DWORD cchSize = statStg.cbSize.LowPart;
  110. *pbstr = SysAllocStringLen(NULL, cchSize + 4);
  111. if (*pbstr)
  112. {
  113. LPSTR pszTemp = (LPSTR) LocalAlloc(LPTR, sizeof(pszTemp[0]) * (cchSize + 4));
  114. if (pszTemp)
  115. {
  116. ULONG cbRead;
  117. hr = pStream->Read(pszTemp, cchSize, &cbRead);
  118. pszTemp[cchSize] = 0;
  119. SHAnsiToUnicode(pszTemp, *pbstr, (cchSize + 1));
  120. LocalFree(pszTemp);
  121. }
  122. else
  123. hr = E_OUTOFMEMORY;
  124. }
  125. else
  126. hr = E_OUTOFMEMORY;
  127. }
  128. return hr;
  129. }
  130. // --------------------------------------------------------------------------------
  131. // HrCopyStream
  132. // --------------------------------------------------------------------------------
  133. HRESULT HrCopyStream(LPSTREAM pstmIn, LPSTREAM pstmOut, ULONG *pcb)
  134. {
  135. HRESULT hr = S_OK;
  136. BYTE buf[4096];
  137. ULONG cbRead=0,
  138. cbTotal=0;
  139. do
  140. {
  141. hr = pstmIn->Read(buf, sizeof(buf), &cbRead);
  142. if (FAILED(hr) || cbRead == 0)
  143. {
  144. break;
  145. }
  146. hr = pstmOut->Write(buf, cbRead, NULL);
  147. if (FAILED(hr))
  148. {
  149. break;
  150. }
  151. cbTotal += cbRead;
  152. }
  153. while (cbRead == sizeof (buf));
  154. if (pcb && SUCCEEDED(hr))
  155. *pcb = cbTotal;
  156. return hr;
  157. }
  158. HRESULT CreateBStrVariantFromWStr(IN OUT VARIANT * pvar, IN LPCWSTR pwszString)
  159. {
  160. HRESULT hr = E_INVALIDARG;
  161. if (pvar)
  162. {
  163. pvar->bstrVal = SysAllocString(pwszString);
  164. if (pvar->bstrVal)
  165. {
  166. pvar->vt = VT_BSTR;
  167. hr = S_OK;
  168. }
  169. else
  170. {
  171. pvar->vt = VT_EMPTY;
  172. hr = E_OUTOFMEMORY;
  173. }
  174. }
  175. return hr;
  176. }
  177. HRESULT HrSysAllocString(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  178. {
  179. HRESULT hr = S_OK;
  180. if (pbstrDest)
  181. {
  182. *pbstrDest = SysAllocString(pwzSource);
  183. if (pwzSource)
  184. {
  185. if (*pbstrDest)
  186. hr = S_OK;
  187. else
  188. hr = E_OUTOFMEMORY;
  189. }
  190. }
  191. return hr;
  192. }
  193. HRESULT UnEscapeHTML(BSTR bstrEscaped, BSTR * pbstrUnEscaped)
  194. {
  195. HRESULT hr = HrSysAllocString(bstrEscaped, pbstrUnEscaped);
  196. if (SUCCEEDED(hr))
  197. {
  198. // Find %xx and replace.
  199. LPWSTR pwszEscapedSequence = StrChrW(*pbstrUnEscaped, CH_HTML_ESCAPE);
  200. WCHAR wzEscaped[5] = L"0xXX";
  201. while (pwszEscapedSequence && (3 <= lstrlenW(pwszEscapedSequence)))
  202. {
  203. int nCharCode;
  204. wzEscaped[2] = pwszEscapedSequence[1];
  205. wzEscaped[3] = pwszEscapedSequence[2];
  206. StrToIntExW(wzEscaped, STIF_SUPPORT_HEX, &nCharCode);
  207. // Replace the '%' with the real char.
  208. pwszEscapedSequence[0] = (WCHAR) nCharCode;
  209. pwszEscapedSequence = CharNextW(pwszEscapedSequence); // Skip pasted the replaced char.
  210. // Over write the 0xXX value.
  211. StrCpyW(pwszEscapedSequence, &pwszEscapedSequence[2]);
  212. // Next...
  213. pwszEscapedSequence = StrChrW(pwszEscapedSequence, CH_HTML_ESCAPE);
  214. }
  215. }
  216. return hr;
  217. }
  218. /*****************************************************************************\
  219. PARAMETERS:
  220. If fBoolean is TRUE, return "True" else "False".
  221. HRESULT BOOLToString(BOOL fBoolean, BSTR * pbstrValue)
  222. {
  223. HRESULT hr = E_INVALIDARG;
  224. if (pbstrValue)
  225. {
  226. LPCWSTR pwszValue;
  227. *pbstrValue = NULL;
  228. if (TRUE == fBoolean)
  229. {
  230. pwszValue = SZ_QUERYDATA_TRUE;
  231. }
  232. else
  233. {
  234. pwszValue = SZ_QUERYDATA_FALSE;
  235. }
  236. hr = HrSysAllocString(pwszValue, pbstrValue);
  237. }
  238. return hr;
  239. }
  240. \*****************************************************************************/
  241. #define SZ_VALID_XML L"<?xml"
  242. /////////////////////////////////////////////////////////////////////
  243. // XML Related Helpers
  244. /////////////////////////////////////////////////////////////////////
  245. HRESULT XMLDOMFromBStr(BSTR bstrXML, IXMLDOMDocument ** ppXMLDoc)
  246. {
  247. HRESULT hr = E_FAIL;
  248. // We don't even want to
  249. // bother passing it to the XML DOM because they throw exceptions. These
  250. // are caught and handled but we still don't want this to happen. We try
  251. // to get XML from the web server, but we get HTML instead if the web server
  252. // fails or the web proxy returns HTML if the site isn't found.
  253. if (!StrCmpNIW(SZ_VALID_XML, bstrXML, (ARRAYSIZE(SZ_VALID_XML) - 1)))
  254. {
  255. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IXMLDOMDocument, ppXMLDoc));
  256. if (SUCCEEDED(hr))
  257. {
  258. VARIANT_BOOL fIsSuccessful;
  259. // NOTE: This will throw an 0xE0000001 exception in MSXML if the XML is invalid.
  260. // This is not good but there isn't much we can do about it. The problem is
  261. // that web proxies give back HTML which fails to parse.
  262. hr = (*ppXMLDoc)->loadXML(bstrXML, &fIsSuccessful);
  263. if (SUCCEEDED(hr))
  264. {
  265. if (VARIANT_TRUE != fIsSuccessful)
  266. {
  267. hr = E_FAIL;
  268. }
  269. }
  270. }
  271. if (FAILED(hr))
  272. {
  273. (*ppXMLDoc)->Release();
  274. *ppXMLDoc = NULL;
  275. }
  276. }
  277. return hr;
  278. }
  279. HRESULT XMLBStrFromDOM(IXMLDOMDocument * pXMLDoc, BSTR * pbstrXML)
  280. {
  281. IStream * pStream;
  282. HRESULT hr = pXMLDoc->QueryInterface(IID_PPV_ARG(IStream, &pStream)); // check the return value
  283. if (S_OK == hr)
  284. {
  285. hr = BSTRFromStream(pStream, pbstrXML);
  286. pStream->Release();
  287. }
  288. return hr;
  289. }
  290. HRESULT XMLAppendElement(IXMLDOMElement * pXMLElementRoot, IXMLDOMElement * pXMLElementToAppend)
  291. {
  292. IXMLDOMNode * pXMLNodeRoot;
  293. HRESULT hr = pXMLElementRoot->QueryInterface(IID_PPV_ARG(IXMLDOMNode, &pXMLNodeRoot));
  294. if (EVAL(SUCCEEDED(hr)))
  295. {
  296. IXMLDOMNode * pXMLNodeToAppend;
  297. hr = pXMLElementToAppend->QueryInterface(IID_PPV_ARG(IXMLDOMNode, &pXMLNodeToAppend));
  298. if (EVAL(SUCCEEDED(hr)))
  299. {
  300. hr = pXMLNodeRoot->appendChild(pXMLNodeToAppend, NULL);
  301. pXMLNodeToAppend->Release();
  302. }
  303. pXMLNodeRoot->Release();
  304. }
  305. return hr;
  306. }
  307. HRESULT XMLDOMFromFile(IN LPCWSTR pwzPath, OUT IXMLDOMDocument ** ppXMLDOMDoc)
  308. {
  309. HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IXMLDOMDocument, ppXMLDOMDoc));
  310. if (SUCCEEDED(hr))
  311. {
  312. VARIANT xmlSource;
  313. xmlSource.vt = VT_BSTR;
  314. xmlSource.bstrVal = SysAllocString(pwzPath);
  315. if (xmlSource.bstrVal)
  316. {
  317. VARIANT_BOOL fIsSuccessful = VARIANT_TRUE;
  318. hr = (*ppXMLDOMDoc)->load(xmlSource, &fIsSuccessful);
  319. if ((S_FALSE == hr) || (VARIANT_FALSE == fIsSuccessful))
  320. {
  321. // This happens when the file isn't a valid XML file.
  322. hr = E_FAIL;
  323. }
  324. VariantClear(&xmlSource);
  325. }
  326. if (FAILED(hr))
  327. {
  328. ATOMICRELEASE(*ppXMLDOMDoc);
  329. }
  330. }
  331. return hr;
  332. }
  333. HRESULT XMLElem_VerifyTagName(IN IXMLDOMElement * pXMLElementMessage, IN LPCWSTR pwszTagName)
  334. {
  335. BSTR bstrTagName;
  336. HRESULT hr = pXMLElementMessage->get_tagName(&bstrTagName);
  337. if (S_FALSE == hr)
  338. {
  339. hr = E_FAIL;
  340. }
  341. else if (SUCCEEDED(hr))
  342. {
  343. if (!bstrTagName || !pwszTagName || StrCmpIW(bstrTagName, pwszTagName))
  344. {
  345. hr = E_FAIL;
  346. }
  347. SysFreeString(bstrTagName);
  348. }
  349. return hr;
  350. }
  351. HRESULT XMLElem_GetElementsByTagName(IN IXMLDOMElement * pXMLElementMessage, IN LPCWSTR pwszTagName, OUT IXMLDOMNodeList ** ppNodeList)
  352. {
  353. BSTR bstrTagName = SysAllocString(pwszTagName);
  354. HRESULT hr = E_OUTOFMEMORY;
  355. *ppNodeList = NULL;
  356. if (bstrTagName)
  357. {
  358. hr = pXMLElementMessage->getElementsByTagName(bstrTagName, ppNodeList);
  359. if (S_FALSE == hr)
  360. {
  361. hr = E_FAIL;
  362. }
  363. SysFreeString(bstrTagName);
  364. }
  365. return hr;
  366. }
  367. HRESULT XMLNode_GetAttributeValue(IN IXMLDOMNode * pXMLNode, IN LPCWSTR pwszAttributeName, OUT BSTR * pbstrValue)
  368. {
  369. BSTR bstrAttributeName = SysAllocString(pwszAttributeName);
  370. HRESULT hr = E_OUTOFMEMORY;
  371. *pbstrValue = NULL;
  372. if (bstrAttributeName)
  373. {
  374. IXMLDOMNamedNodeMap * pNodeAttributes;
  375. hr = pXMLNode->get_attributes(&pNodeAttributes);
  376. if (S_FALSE == hr) hr = E_FAIL;
  377. if (SUCCEEDED(hr))
  378. {
  379. IXMLDOMNode * pTypeAttribute;
  380. hr = pNodeAttributes->getNamedItem(bstrAttributeName, &pTypeAttribute);
  381. if (S_FALSE == hr) hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  382. if (SUCCEEDED(hr))
  383. {
  384. VARIANT varAtribValue = {0};
  385. hr = pTypeAttribute->get_nodeValue(&varAtribValue);
  386. if (S_FALSE == hr) hr = E_FAIL;
  387. if (SUCCEEDED(hr) && (VT_BSTR == varAtribValue.vt))
  388. {
  389. *pbstrValue = SysAllocString(varAtribValue.bstrVal);
  390. }
  391. VariantClear(&varAtribValue);
  392. pTypeAttribute->Release();
  393. }
  394. pNodeAttributes->Release();
  395. }
  396. SysFreeString(bstrAttributeName);
  397. }
  398. return hr;
  399. }
  400. HRESULT XMLNode_GetChildTag(IN IXMLDOMNode * pXMLNode, IN LPCWSTR pwszTagName, OUT IXMLDOMNode ** ppChildNode)
  401. {
  402. HRESULT hr = E_INVALIDARG;
  403. *ppChildNode = NULL;
  404. if (pXMLNode)
  405. {
  406. IXMLDOMElement * pXMLElement;
  407. hr = pXMLNode->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pXMLElement));
  408. if (SUCCEEDED(hr))
  409. {
  410. IXMLDOMNodeList * pNodeList;
  411. hr = XMLElem_GetElementsByTagName(pXMLElement, pwszTagName, &pNodeList);
  412. if (SUCCEEDED(hr))
  413. {
  414. hr = XMLNodeList_GetChild(pNodeList, 0, ppChildNode);
  415. pNodeList->Release();
  416. }
  417. pXMLElement->Release();
  418. }
  419. }
  420. return hr;
  421. }
  422. HRESULT XMLNode_GetTagText(IN IXMLDOMNode * pXMLNode, OUT BSTR * pbstrValue)
  423. {
  424. DOMNodeType nodeType = NODE_TEXT;
  425. HRESULT hr = pXMLNode->get_nodeType(&nodeType);
  426. *pbstrValue = NULL;
  427. if (S_FALSE == hr) hr = E_FAIL;
  428. if (SUCCEEDED(hr))
  429. {
  430. if (NODE_TEXT == nodeType)
  431. {
  432. VARIANT varAtribValue = {0};
  433. hr = pXMLNode->get_nodeValue(&varAtribValue);
  434. if (S_FALSE == hr) hr = E_FAIL;
  435. if (SUCCEEDED(hr) && (VT_BSTR == varAtribValue.vt))
  436. {
  437. *pbstrValue = SysAllocString(varAtribValue.bstrVal);
  438. }
  439. VariantClear(&varAtribValue);
  440. }
  441. else
  442. {
  443. hr = pXMLNode->get_text(pbstrValue);
  444. }
  445. }
  446. return hr;
  447. }
  448. HRESULT XMLNodeList_GetChild(IN IXMLDOMNodeList * pNodeList, IN DWORD dwIndex, OUT IXMLDOMNode ** ppXMLChildNode)
  449. {
  450. HRESULT hr = pNodeList->get_item(dwIndex, ppXMLChildNode);
  451. if (S_FALSE == hr)
  452. {
  453. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  454. }
  455. return hr;
  456. }
  457. HRESULT XMLNode_GetChildTagTextValue(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, OUT BSTR * pbstrValue)
  458. {
  459. IXMLDOMNode * pNodeType;
  460. HRESULT hr = XMLNode_GetChildTag(pXMLNode, bstrChildTag, &pNodeType);
  461. if (SUCCEEDED(hr))
  462. {
  463. hr = XMLNode_GetTagText(pNodeType, pbstrValue);
  464. pNodeType->Release();
  465. }
  466. return hr;
  467. }
  468. HRESULT XMLNode_GetChildTagTextValueToBool(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, OUT BOOL * pfBoolean)
  469. {
  470. BSTR bstr;
  471. HRESULT hr = XMLNode_GetChildTagTextValue(pXMLNode, bstrChildTag, &bstr);
  472. if (SUCCEEDED(hr))
  473. {
  474. if (!StrCmpIW(bstr, L"on"))
  475. {
  476. *pfBoolean = TRUE;
  477. }
  478. else
  479. {
  480. *pfBoolean = FALSE;
  481. }
  482. SysFreeString(bstr);
  483. }
  484. return hr;
  485. }
  486. BOOL XML_IsChildTagTextEqual(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, IN BSTR bstrText)
  487. {
  488. BOOL fIsChildTagTextEqual = FALSE;
  489. BSTR bstrChildText;
  490. HRESULT hr = XMLNode_GetChildTagTextValue(pXMLNode, bstrChildTag, &bstrChildText);
  491. if (SUCCEEDED(hr))
  492. {
  493. // Is this <TYPE>email</TYPE>?
  494. if (!StrCmpIW(bstrChildText, bstrText))
  495. {
  496. // No, so keep looking.
  497. fIsChildTagTextEqual = TRUE;
  498. }
  499. SysFreeString(bstrChildText);
  500. }
  501. return fIsChildTagTextEqual;
  502. }
  503. #define EMPTYSTR_FOR_NULL(str) ((!str) ? TEXT("") : (str))
  504. /////////////////////////////////////////////////////////////////////
  505. // File System Wrapping Helpers
  506. /////////////////////////////////////////////////////////////////////
  507. HRESULT CreateFileHrWrap(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  508. DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, HANDLE * phFileHandle)
  509. {
  510. HRESULT hr = S_OK;
  511. HANDLE hTemp = NULL;
  512. DWORD dwError = 0;
  513. if (!phFileHandle)
  514. phFileHandle = &hTemp;
  515. *phFileHandle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  516. if (INVALID_HANDLE_VALUE == *phFileHandle)
  517. {
  518. dwError = GetLastError();
  519. hr = HRESULT_FROM_WIN32(dwError);
  520. }
  521. if (hTemp)
  522. CloseHandle(hTemp);
  523. return hr;
  524. }
  525. HRESULT WriteFileWrap(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  526. {
  527. HRESULT hr = S_OK;
  528. DWORD dwError = 0;
  529. if (!WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped))
  530. {
  531. dwError = GetLastError();
  532. hr = HRESULT_FROM_WIN32(dwError);
  533. }
  534. return hr;
  535. }
  536. HRESULT DeleteFileHrWrap(LPCWSTR pszPath)
  537. {
  538. HRESULT hr = S_OK;
  539. DWORD dwError = 0;
  540. if (!DeleteFileW(pszPath))
  541. {
  542. dwError = GetLastError();
  543. hr = HRESULT_FROM_WIN32(dwError);
  544. }
  545. return hr;
  546. }
  547. HRESULT GetPrivateProfileStringHrWrap(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName)
  548. {
  549. HRESULT hr = S_OK;
  550. DWORD chGot = GetPrivateProfileStringW(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, lpFileName);
  551. // What else can indicate an error value?
  552. if (0 == chGot)
  553. {
  554. hr = HRESULT_FROM_WIN32(GetLastError());
  555. if (SUCCEEDED(hr))
  556. hr = E_FAIL;
  557. }
  558. return hr;
  559. }
  560. /////////////////////////////////////////////////////////////////////
  561. // Registry Helpers
  562. /////////////////////////////////////////////////////////////////////
  563. HRESULT HrRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
  564. {
  565. DWORD dwError = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  566. return HRESULT_FROM_WIN32(dwError);
  567. }
  568. HRESULT HrRegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions,
  569. REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
  570. {
  571. DWORD dwError = RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  572. return HRESULT_FROM_WIN32(dwError);
  573. }
  574. HRESULT HrRegQueryValueEx(IN HKEY hKey, IN LPCTSTR lpValueName, IN LPDWORD lpReserved, IN LPDWORD lpType, IN LPBYTE lpData, IN LPDWORD lpcbData)
  575. {
  576. DWORD dwError = RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
  577. return HRESULT_FROM_WIN32(dwError);
  578. }
  579. HRESULT HrRegSetValueEx(IN HKEY hKey, IN LPCTSTR lpValueName, IN DWORD dwReserved, IN DWORD dwType, IN CONST BYTE *lpData, IN DWORD cbData)
  580. {
  581. DWORD dwError = RegSetValueEx(hKey, lpValueName, dwReserved, dwType, lpData, cbData);
  582. return HRESULT_FROM_WIN32(dwError);
  583. }
  584. HRESULT HrRegEnumKey(HKEY hKey, DWORD dwIndex, LPTSTR lpName, DWORD cbName)
  585. {
  586. DWORD dwError = RegEnumKey(hKey, dwIndex, lpName, cbName);
  587. return HRESULT_FROM_WIN32(dwError);
  588. }
  589. HRESULT HrRegEnumValue(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, LPDWORD lpcValueName, LPDWORD lpReserved,
  590. LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
  591. {
  592. DWORD dwError = RegEnumValue(hKey, dwIndex, lpValueName, lpcValueName, lpReserved, lpType, lpData, lpcbData);
  593. return HRESULT_FROM_WIN32(dwError);
  594. }
  595. HRESULT HrRegQueryInfoKey(HKEY hKey, LPTSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen,
  596. LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
  597. {
  598. DWORD dwError = RegQueryInfoKey(hKey, lpClass, lpcClass, lpReserved, lpcSubKeys, lpcMaxSubKeyLen,
  599. lpcMaxClassLen, lpcValues, lpcMaxValueNameLen, lpcMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime);
  600. return HRESULT_FROM_WIN32(dwError);
  601. }
  602. HRESULT HrBStrRegQueryValue(IN HKEY hKey, IN LPCTSTR lpValueName, OUT BSTR * pbstr)
  603. {
  604. TCHAR szValue[MAX_PATH];
  605. DWORD dwType;
  606. DWORD cbSize = sizeof(szValue);
  607. HRESULT hr = HrRegQueryValueEx(hKey, lpValueName, 0, &dwType, (BYTE *)szValue, &cbSize);
  608. *pbstr = NULL;
  609. if (SUCCEEDED(hr))
  610. {
  611. hr = HrSysAllocStringW(szValue, pbstr);
  612. }
  613. return hr;
  614. }
  615. HRESULT HrSHGetValue(IN HKEY hKey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, OPTIONAL OUT LPDWORD pdwType,
  616. OPTIONAL OUT LPVOID pvData, OPTIONAL OUT LPDWORD pcbData)
  617. {
  618. DWORD dwError = SHGetValue(hKey, pszSubKey, pszValue, pdwType, pvData, pcbData);
  619. return HRESULT_FROM_WIN32(dwError);
  620. }
  621. HRESULT HrSHSetValue(IN HKEY hkey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, DWORD dwType, OPTIONAL OUT LPVOID pvData, IN DWORD cbData)
  622. {
  623. DWORD dwError = SHSetValue(hkey, pszSubKey, pszValue, dwType, pvData, cbData);
  624. return HRESULT_FROM_WIN32(dwError);
  625. }
  626. HRESULT HrBStrRegSetValue(IN HKEY hKey, IN LPCTSTR lpValueName, OUT BSTR bstr)
  627. {
  628. DWORD cbSize = ((lstrlenW(bstr) + 1) * sizeof(bstr[0]));
  629. return HrRegSetValueEx(hKey, lpValueName, 0, REG_SZ, (BYTE *)bstr, cbSize);
  630. }
  631. /////////////////////////////////////////////////////////////////////
  632. // Palette Helpers
  633. /////////////////////////////////////////////////////////////////////
  634. COLORREF GetNearestPaletteColor(HPALETTE hpal, COLORREF rgb)
  635. {
  636. PALETTEENTRY pe;
  637. GetPaletteEntries(hpal, GetNearestPaletteIndex(hpal, rgb & 0x00FFFFFF), 1, &pe);
  638. return RGB(pe.peRed, pe.peGreen, pe.peBlue);
  639. }
  640. BOOL IsPaletteColor(HPALETTE hpal, COLORREF rgb)
  641. {
  642. return GetNearestPaletteColor(hpal, rgb) == (rgb & 0xFFFFFF);
  643. }
  644. /////////////////////////////////////////////////////////////////////
  645. // Other Helpers
  646. /////////////////////////////////////////////////////////////////////
  647. HRESULT HrRewindStream(IStream * pstm)
  648. {
  649. LARGE_INTEGER liOrigin = {0,0};
  650. return pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  651. }
  652. #define SET_FLAG(dwAllFlags, dwFlag) ((dwAllFlags) |= (dwFlag))
  653. #define IS_FLAG_SET(dwAllFlags, dwFlag) ((BOOL)((dwAllFlags) & (dwFlag)))
  654. // PERFPERF
  655. // This routine used to copy 512 bytes at a time, but that had a major negative perf impact.
  656. // I have measured a 2-3x speedup in copy times by increasing this buffer size to 16k.
  657. // Yes, its a lot of stack, but it is memory well spent. -saml
  658. #define STREAM_COPY_BUF_SIZE 16384
  659. #define STREAM_PROGRESS_INTERVAL (100*1024/STREAM_COPY_BUF_SIZE) // display progress after this many blocks
  660. HRESULT StreamCopyWithProgress(IStream *pstmFrom, IStream *pstmTo, ULARGE_INTEGER cb, PROGRESSINFO * ppi)
  661. {
  662. BYTE buf[STREAM_COPY_BUF_SIZE];
  663. ULONG cbRead;
  664. HRESULT hres = NOERROR;
  665. int nSection = 0; // How many buffer sizes have we copied?
  666. ULARGE_INTEGER uliNewCompleted;
  667. if (ppi)
  668. {
  669. uliNewCompleted.QuadPart = ppi->uliBytesCompleted.QuadPart;
  670. }
  671. while (cb.QuadPart)
  672. {
  673. if (ppi && ppi->ppd)
  674. {
  675. if (0 == (nSection % STREAM_PROGRESS_INTERVAL))
  676. {
  677. EVAL(SUCCEEDED(ppi->ppd->SetProgress64(uliNewCompleted.QuadPart, ppi->uliBytesTotal.QuadPart)));
  678. if (ppi->ppd->HasUserCancelled())
  679. {
  680. hres = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  681. break;
  682. }
  683. }
  684. }
  685. hres = pstmFrom->Read(buf, min(cb.LowPart, SIZEOF(buf)), &cbRead);
  686. if (FAILED(hres) || (cbRead == 0))
  687. {
  688. // sometimes we are just done.
  689. if (SUCCEEDED(hres))
  690. hres = S_OK;
  691. break;
  692. }
  693. if (ppi)
  694. {
  695. uliNewCompleted.QuadPart += (ULONGLONG) cbRead;
  696. }
  697. cb.QuadPart -= cbRead;
  698. hres = pstmTo->Write(buf, cbRead, &cbRead);
  699. if (FAILED(hres) || (cbRead == 0))
  700. break;
  701. nSection++;
  702. }
  703. return hres;
  704. }
  705. /*
  706. // These are needed for COM/COM+ interop
  707. void __stdcall
  708. _com_raise_error(HRESULT hr, IErrorInfo* perrinfo) throw(_com_error)
  709. {
  710. throw _com_error(hr, perrinfo);
  711. }
  712. void __stdcall
  713. _com_issue_error(HRESULT hr) throw(_com_error)
  714. {
  715. _com_raise_error(hr, NULL);
  716. }
  717. void __stdcall
  718. _com_issue_errorex(HRESULT hr, IUnknown* punk, REFIID riid) throw(_com_error)
  719. {
  720. IErrorInfo* perrinfo = NULL;
  721. if (punk == NULL) {
  722. goto exeunt;
  723. }
  724. ISupportErrorInfo* psei;
  725. if (FAILED(punk->QueryInterface(__uuidof(ISupportErrorInfo),
  726. (void**)&psei))) {
  727. goto exeunt;
  728. }
  729. HRESULT hrSupportsErrorInfo;
  730. hrSupportsErrorInfo = psei->InterfaceSupportsErrorInfo(riid);
  731. psei->Release();
  732. if (hrSupportsErrorInfo != S_OK) {
  733. goto exeunt;
  734. }
  735. if (GetErrorInfo(0, &perrinfo) != S_OK) {
  736. perrinfo = NULL;
  737. }
  738. exeunt:
  739. _com_raise_error(hr, perrinfo);
  740. }
  741. */
  742. // needed by smtpserv:
  743. HRESULT HrByteToStream(LPSTREAM *lppstm, LPBYTE lpb, ULONG cb)
  744. {
  745. // Locals
  746. HRESULT hr=S_OK;
  747. LARGE_INTEGER liOrigin = {0,0};
  748. // Create H Global Stream
  749. hr = CreateStreamOnHGlobal (NULL, TRUE, lppstm);
  750. if (FAILED(hr))
  751. goto exit;
  752. // Write String
  753. hr = (*lppstm)->Write (lpb, cb, NULL);
  754. if (FAILED(hr))
  755. goto exit;
  756. // Rewind the steam
  757. hr = (*lppstm)->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  758. if (FAILED(hr))
  759. goto exit;
  760. exit:
  761. // Done
  762. return hr;
  763. }
  764. const char szDayOfWeekArray[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
  765. const char szMonthOfYearArray[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ;
  766. void GetDateString(char * szSentDateString, ULONG stringLen)
  767. {
  768. // Sent Date
  769. SYSTEMTIME stSentTime;
  770. CHAR szMonth[10], szWeekDay[12] ;
  771. GetSystemTime(&stSentTime);
  772. lstrcpynA(szWeekDay, szDayOfWeekArray[stSentTime.wDayOfWeek], ARRAYSIZE(szWeekDay)) ;
  773. lstrcpynA(szMonth, szMonthOfYearArray[stSentTime.wMonth-1], ARRAYSIZE(szMonth)) ;
  774. wnsprintfA(szSentDateString, stringLen, "%s, %u %s %u %2d:%02d:%02d ", (LPSTR) szWeekDay, stSentTime.wDay,
  775. (LPSTR) szMonth, stSentTime.wYear, stSentTime.wHour,
  776. stSentTime.wMinute, stSentTime.wSecond) ;
  777. }
  778. /*****************************************************************************\
  779. PARAMETERS:
  780. RETURN: Win32 HRESULT (Not Script Safe).
  781. SUCCEEDED(hr) for OK and out params filled in.
  782. FAILED(hr) for all errors.
  783. \*****************************************************************************/
  784. HRESULT GetQueryStringValue(BSTR bstrURL, LPCWSTR pwszValue, LPWSTR pwszData, int cchSizeData)
  785. {
  786. HRESULT hr = E_FAIL;
  787. LPCWSTR pwszIterate = bstrURL;
  788. pwszIterate = StrChrW(pwszIterate, L'?'); // Advance to Query part of URL.
  789. while (pwszIterate && pwszIterate[0])
  790. {
  791. pwszIterate++; // Start at first value
  792. LPCWSTR pwszEndOfValue = StrChrW(pwszIterate, L'=');
  793. if (!pwszEndOfValue)
  794. break;
  795. int cchValueSize = (INT)(UINT)(pwszEndOfValue - pwszIterate);
  796. if (0 == StrCmpNIW(pwszValue, pwszIterate, cchValueSize))
  797. {
  798. int cchSizeToCopy = cchSizeData; // Copy rest of line by default.
  799. pwszIterate = StrChrW(pwszEndOfValue, L'&');
  800. if (pwszIterate)
  801. {
  802. cchSizeToCopy = (INT)(UINT)(pwszIterate - pwszEndOfValue);
  803. }
  804. // It matches, now get the Data.
  805. StrCpyNW(pwszData, (pwszEndOfValue + 1), cchSizeToCopy);
  806. hr = S_OK;
  807. break;
  808. }
  809. else
  810. {
  811. pwszIterate = StrChrW(pwszEndOfValue, L'&');
  812. }
  813. }
  814. return hr;
  815. }
  816. BOOL _InitComCtl32()
  817. {
  818. static BOOL fInitialized = FALSE;
  819. if (!fInitialized)
  820. {
  821. INITCOMMONCONTROLSEX icc;
  822. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  823. icc.dwICC = (ICC_ANIMATE_CLASS | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_INTERNET_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES);
  824. fInitialized = InitCommonControlsEx(&icc);
  825. }
  826. return fInitialized;
  827. }
  828. HRESULT HrShellExecute(HWND hwnd, LPCTSTR lpVerb, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd)
  829. {
  830. ULARGE_INTEGER uiResult;
  831. uiResult.QuadPart = (ULONGLONG) ShellExecute(hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShowCmd);
  832. if (32 < uiResult.QuadPart)
  833. {
  834. uiResult.LowPart = ERROR_SUCCESS;
  835. }
  836. return HRESULT_FROM_WIN32(uiResult.LowPart);
  837. }
  838. HRESULT StrReplaceToken(IN LPCTSTR pszToken, IN LPCTSTR pszReplaceValue, IN LPTSTR pszString, IN DWORD cchSize)
  839. {
  840. HRESULT hr = S_OK;
  841. LPTSTR pszTempLastHalf = NULL;
  842. LPTSTR pszNextToken = pszString;
  843. while (pszNextToken = StrStrI(pszNextToken, pszToken))
  844. {
  845. // We found one.
  846. LPTSTR pszPastToken = pszNextToken + lstrlen(pszToken);
  847. Str_SetPtr(&pszTempLastHalf, pszPastToken); // Keep a copy because we will overwrite it.
  848. pszNextToken[0] = 0; // Remove the rest of the string.
  849. StrCatBuff(pszString, pszReplaceValue, cchSize);
  850. StrCatBuff(pszString, pszTempLastHalf, cchSize);
  851. pszNextToken += lstrlen(pszReplaceValue);
  852. }
  853. Str_SetPtr(&pszTempLastHalf, NULL);
  854. return hr;
  855. }
  856. BOOL IUnknown_CompareCLSID(IN IUnknown * punk, IN CLSID clsid)
  857. {
  858. BOOL fIsEqual = FALSE;
  859. if (punk)
  860. {
  861. CLSID clsidPageID;
  862. HRESULT hr = IUnknown_GetClassID(punk, &clsidPageID);
  863. if (SUCCEEDED(hr) && IsEqualCLSID(clsidPageID, clsid))
  864. {
  865. fIsEqual = TRUE;
  866. }
  867. }
  868. return fIsEqual;
  869. }
  870. HRESULT IEnumUnknown_FindCLSID(IN IUnknown * punk, IN CLSID clsid, OUT IUnknown ** ppunkFound)
  871. {
  872. HRESULT hr = E_INVALIDARG;
  873. if (punk && ppunkFound)
  874. {
  875. IEnumUnknown * pEnum;
  876. *ppunkFound = NULL;
  877. hr = punk->QueryInterface(IID_PPV_ARG(IEnumUnknown, &pEnum));
  878. if (SUCCEEDED(hr))
  879. {
  880. IUnknown * punkToTry;
  881. ULONG ulFetched;
  882. while (SUCCEEDED(pEnum->Next(1, &punkToTry, &ulFetched)) &&
  883. (1 == ulFetched))
  884. {
  885. if (IUnknown_CompareCLSID(punkToTry, clsid))
  886. {
  887. *ppunkFound = punkToTry;
  888. break;
  889. }
  890. punkToTry->Release();
  891. }
  892. pEnum->Release();
  893. }
  894. }
  895. return hr;
  896. }
  897. HRESULT GetPageByCLSID(IUnknown * punkSite, const GUID * pClsid, IPropertyBag ** ppPropertyBag)
  898. {
  899. HRESULT hr = E_FAIL;
  900. *ppPropertyBag = NULL;
  901. if (punkSite)
  902. {
  903. IThemeUIPages * pThemeUI;
  904. hr = punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUI));
  905. if (SUCCEEDED(hr))
  906. {
  907. IEnumUnknown * pEnumUnknown;
  908. hr = pThemeUI->GetBasePagesEnum(&pEnumUnknown);
  909. if (SUCCEEDED(hr))
  910. {
  911. IUnknown * punk;
  912. // This may not exit due to policy
  913. hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
  914. if (SUCCEEDED(hr))
  915. {
  916. hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
  917. punk->Release();
  918. }
  919. pEnumUnknown->Release();
  920. }
  921. pThemeUI->Release();
  922. }
  923. }
  924. return hr;
  925. }