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.

1402 lines
39 KiB

  1. /*****************************************************************************\
  2. FILE: util.cpp
  3. DESCRIPTION:
  4. Shared stuff that operates on all classes.
  5. BryanSt 8/13/1999
  6. Copyright (C) Microsoft Corp 1999-1999. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include <atlbase.h> // USES_CONVERSION
  10. #include "util.h"
  11. #include "objctors.h"
  12. #include <comdef.h>
  13. #define DECL_CRTFREE
  14. #include <crtfree.h>
  15. #define COMPILE_MULTIMON_STUBS
  16. #include <multimon.h>
  17. /////////////////////////////////////////////////////////////////////
  18. // String Helpers
  19. /////////////////////////////////////////////////////////////////////
  20. HINSTANCE g_hinst; // My instance handle
  21. #ifdef DEBUG
  22. DWORD g_TLSliStopWatchStartHi = 0;
  23. DWORD g_TLSliStopWatchStartLo = 0;
  24. LARGE_INTEGER g_liStopWatchFreq = {0};
  25. #endif // DEBUG
  26. /////////////////////////////////////////////////////////////////////
  27. // Debug Timing Helpers
  28. /////////////////////////////////////////////////////////////////////
  29. #ifdef DEBUG
  30. void DebugStartWatch(void)
  31. {
  32. LARGE_INTEGER liStopWatchStart;
  33. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  34. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  35. // ASSERT(!liStopWatchStart.QuadPart); // If you hit this, then the stopwatch is nested.
  36. QueryPerformanceFrequency(&g_liStopWatchFreq);
  37. QueryPerformanceCounter(&liStopWatchStart);
  38. TlsSetValue(g_TLSliStopWatchStartHi, IntToPtr(liStopWatchStart.HighPart));
  39. TlsSetValue(g_TLSliStopWatchStartLo, IntToPtr(liStopWatchStart.LowPart));
  40. }
  41. DWORD DebugStopWatch(void)
  42. {
  43. LARGE_INTEGER liDiff;
  44. LARGE_INTEGER liStopWatchStart;
  45. QueryPerformanceCounter(&liDiff);
  46. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  47. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  48. liDiff.QuadPart -= liStopWatchStart.QuadPart;
  49. ASSERT(0 != g_liStopWatchFreq.QuadPart); // I don't like to fault with div 0.
  50. DWORD dwTime = (DWORD)((liDiff.QuadPart * 1000) / g_liStopWatchFreq.QuadPart);
  51. TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) 0);
  52. TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) 0);
  53. return dwTime;
  54. }
  55. #endif // DEBUG
  56. /////////////////////////////////////////////////////////////////////
  57. // String Helpers
  58. /////////////////////////////////////////////////////////////////////
  59. #undef SysAllocStringA
  60. BSTR SysAllocStringA(LPCSTR pszStr)
  61. {
  62. BSTR bstrOut = NULL;
  63. if (pszStr)
  64. {
  65. DWORD cchSize = (lstrlenA(pszStr) + 1);
  66. LPWSTR pwszThunkTemp = (LPWSTR) LocalAlloc(LPTR, (sizeof(pwszThunkTemp[0]) * cchSize)); // assumes INFOTIPSIZE number of chars max
  67. if (pwszThunkTemp)
  68. {
  69. SHAnsiToUnicode(pszStr, pwszThunkTemp, cchSize);
  70. bstrOut = SysAllocString(pwszThunkTemp);
  71. LocalFree(pwszThunkTemp);
  72. }
  73. }
  74. return bstrOut;
  75. }
  76. HRESULT HrSysAllocStringA(IN LPCSTR pszSource, OUT BSTR * pbstrDest)
  77. {
  78. HRESULT hr = S_OK;
  79. if (pbstrDest)
  80. {
  81. *pbstrDest = SysAllocStringA(pszSource);
  82. if (pszSource)
  83. {
  84. if (*pbstrDest)
  85. hr = S_OK;
  86. else
  87. hr = E_OUTOFMEMORY;
  88. }
  89. }
  90. return hr;
  91. }
  92. HRESULT HrSysAllocStringW(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  93. {
  94. HRESULT hr = S_OK;
  95. if (pbstrDest)
  96. {
  97. *pbstrDest = SysAllocString(pwzSource);
  98. if (pwzSource)
  99. {
  100. if (*pbstrDest)
  101. hr = S_OK;
  102. else
  103. hr = E_OUTOFMEMORY;
  104. }
  105. }
  106. return hr;
  107. }
  108. LPSTR AllocStringFromBStr(BSTR bstr)
  109. {
  110. USES_CONVERSION; // atlbase.h
  111. char *a = W2A((bstr ? bstr : L""));
  112. int len = 1 + lstrlenA(a);
  113. char *p = (char *)LocalAlloc(LPTR, len);
  114. if (p)
  115. {
  116. StrCpyNA(p, a, len);
  117. }
  118. return p;
  119. }
  120. HRESULT BSTRFromStream(IStream * pStream, BSTR * pbstr)
  121. {
  122. STATSTG statStg = {0};
  123. HRESULT hr = pStream->Stat(&statStg, STATFLAG_NONAME);
  124. if (S_OK == hr)
  125. {
  126. DWORD cchSize = statStg.cbSize.LowPart;
  127. *pbstr = SysAllocStringLen(NULL, cchSize + 4);
  128. if (*pbstr)
  129. {
  130. LPSTR pszTemp = (LPSTR) LocalAlloc(LPTR, sizeof(pszTemp[0]) * (cchSize + 4));
  131. if (pszTemp)
  132. {
  133. ULONG cbRead;
  134. hr = pStream->Read(pszTemp, cchSize, &cbRead);
  135. pszTemp[cchSize] = 0;
  136. SHAnsiToUnicode(pszTemp, *pbstr, (cchSize + 1));
  137. LocalFree(pszTemp);
  138. }
  139. else
  140. hr = E_OUTOFMEMORY;
  141. }
  142. else
  143. hr = E_OUTOFMEMORY;
  144. }
  145. return hr;
  146. }
  147. // --------------------------------------------------------------------------------
  148. // HrCopyStream
  149. // --------------------------------------------------------------------------------
  150. HRESULT HrCopyStream(LPSTREAM pstmIn, LPSTREAM pstmOut, ULONG *pcb)
  151. {
  152. HRESULT hr = S_OK;
  153. BYTE buf[4096];
  154. ULONG cbRead=0,
  155. cbTotal=0;
  156. do
  157. {
  158. hr = pstmIn->Read(buf, sizeof(buf), &cbRead);
  159. if (FAILED(hr) || cbRead == 0)
  160. {
  161. break;
  162. }
  163. hr = pstmOut->Write(buf, cbRead, NULL);
  164. if (FAILED(hr))
  165. {
  166. break;
  167. }
  168. cbTotal += cbRead;
  169. }
  170. while (cbRead == sizeof(buf));
  171. if (pcb && SUCCEEDED(hr))
  172. *pcb = cbTotal;
  173. return hr;
  174. }
  175. HRESULT CreateBStrVariantFromWStr(IN OUT VARIANT * pvar, IN LPCWSTR pwszString)
  176. {
  177. HRESULT hr = E_INVALIDARG;
  178. if (pvar)
  179. {
  180. pvar->bstrVal = SysAllocString(pwszString);
  181. if (pvar->bstrVal)
  182. {
  183. pvar->vt = VT_BSTR;
  184. hr = S_OK;
  185. }
  186. else
  187. {
  188. pvar->vt = VT_EMPTY;
  189. hr = E_OUTOFMEMORY;
  190. }
  191. }
  192. return hr;
  193. }
  194. HRESULT HrSysAllocString(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  195. {
  196. HRESULT hr = S_OK;
  197. if (pbstrDest)
  198. {
  199. *pbstrDest = SysAllocString(pwzSource);
  200. if (pwzSource)
  201. {
  202. if (*pbstrDest)
  203. hr = S_OK;
  204. else
  205. hr = E_OUTOFMEMORY;
  206. }
  207. }
  208. return hr;
  209. }
  210. HRESULT UnEscapeHTML(BSTR bstrEscaped, BSTR * pbstrUnEscaped)
  211. {
  212. HRESULT hr = HrSysAllocString(bstrEscaped, pbstrUnEscaped);
  213. if (SUCCEEDED(hr))
  214. {
  215. // Find %xx and replace.
  216. LPWSTR pwszEscapedSequence = StrChrW(*pbstrUnEscaped, CH_HTML_ESCAPE);
  217. WCHAR wzEscaped[5] = L"0xXX";
  218. while (pwszEscapedSequence && (3 <= lstrlenW(pwszEscapedSequence)))
  219. {
  220. int nCharCode;
  221. wzEscaped[2] = pwszEscapedSequence[1];
  222. wzEscaped[3] = pwszEscapedSequence[2];
  223. StrToIntExW(wzEscaped, STIF_SUPPORT_HEX, &nCharCode);
  224. // Replace the '%' with the real char.
  225. pwszEscapedSequence[0] = (WCHAR) nCharCode;
  226. pwszEscapedSequence = CharNextW(pwszEscapedSequence); // Skip pasted the replaced char.
  227. // Over write the 0xXX value.
  228. StrCpyNW(pwszEscapedSequence, &pwszEscapedSequence[2], lstrlen(pwszEscapedSequence)+1);
  229. // Next...
  230. pwszEscapedSequence = StrChrW(pwszEscapedSequence, CH_HTML_ESCAPE);
  231. }
  232. }
  233. return hr;
  234. }
  235. /*****************************************************************************\
  236. PARAMETERS:
  237. If fBoolean is TRUE, return "True" else "False".
  238. \*****************************************************************************/
  239. HRESULT BOOLToString(BOOL fBoolean, BSTR * pbstrValue)
  240. {
  241. HRESULT hr = E_INVALIDARG;
  242. if (pbstrValue)
  243. {
  244. LPCWSTR pwszValue;
  245. *pbstrValue = NULL;
  246. if (TRUE == fBoolean)
  247. {
  248. pwszValue = SZ_QUERYDATA_TRUE;
  249. }
  250. else
  251. {
  252. pwszValue = SZ_QUERYDATA_FALSE;
  253. }
  254. hr = HrSysAllocString(pwszValue, pbstrValue);
  255. }
  256. return hr;
  257. }
  258. #define SZ_VALID_XML L"<?xml"
  259. /////////////////////////////////////////////////////////////////////
  260. // XML Related Helpers
  261. /////////////////////////////////////////////////////////////////////
  262. HRESULT XMLDOMFromBStr(BSTR bstrXML, IXMLDOMDocument ** ppXMLDoc)
  263. {
  264. HRESULT hr = E_FAIL;
  265. // We don't even want to
  266. // bother passing it to the XML DOM because they throw exceptions. These
  267. // are caught and handled but we still don't want this to happen. We try
  268. // to get XML from the web server, but we get HTML instead if the web server
  269. // fails or the web proxy returns HTML if the site isn't found.
  270. if (!StrCmpNIW(SZ_VALID_XML, bstrXML, (ARRAYSIZE(SZ_VALID_XML) - 1)))
  271. {
  272. hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IXMLDOMDocument, ppXMLDoc));
  273. if (SUCCEEDED(hr))
  274. {
  275. VARIANT_BOOL fIsSuccessful;
  276. // NOTE: This will throw an 0xE0000001 exception in MSXML if the XML is invalid.
  277. // This is not good but there isn't much we can do about it. The problem is
  278. // that web proxies give back HTML which fails to parse.
  279. hr = (*ppXMLDoc)->loadXML(bstrXML, &fIsSuccessful);
  280. if (SUCCEEDED(hr))
  281. {
  282. if (VARIANT_TRUE != fIsSuccessful)
  283. {
  284. hr = E_FAIL;
  285. }
  286. }
  287. }
  288. if (FAILED(hr))
  289. {
  290. (*ppXMLDoc)->Release();
  291. *ppXMLDoc = NULL;
  292. }
  293. }
  294. return hr;
  295. }
  296. HRESULT XMLBStrFromDOM(IXMLDOMDocument * pXMLDoc, BSTR * pbstrXML)
  297. {
  298. IStream * pStream;
  299. HRESULT hr = pXMLDoc->QueryInterface(IID_PPV_ARG(IStream, &pStream)); // check the return value
  300. if (S_OK == hr)
  301. {
  302. hr = BSTRFromStream(pStream, pbstrXML);
  303. pStream->Release();
  304. }
  305. return hr;
  306. }
  307. HRESULT XMLAppendElement(IXMLDOMElement * pXMLElementRoot, IXMLDOMElement * pXMLElementToAppend)
  308. {
  309. IXMLDOMNode * pXMLNodeRoot;
  310. HRESULT hr = pXMLElementRoot->QueryInterface(IID_PPV_ARG(IXMLDOMNode, &pXMLNodeRoot));
  311. if (SUCCEEDED(hr))
  312. {
  313. IXMLDOMNode * pXMLNodeToAppend;
  314. hr = pXMLElementToAppend->QueryInterface(IID_PPV_ARG(IXMLDOMNode, &pXMLNodeToAppend));
  315. if (SUCCEEDED(hr))
  316. {
  317. hr = pXMLNodeRoot->appendChild(pXMLNodeToAppend, NULL);
  318. pXMLNodeToAppend->Release();
  319. }
  320. pXMLNodeRoot->Release();
  321. }
  322. return hr;
  323. }
  324. HRESULT XMLDOMFromFile(IN LPCWSTR pwzPath, OUT IXMLDOMDocument ** ppXMLDOMDoc)
  325. {
  326. HRESULT hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IXMLDOMDocument, ppXMLDOMDoc));
  327. if (SUCCEEDED(hr))
  328. {
  329. VARIANT xmlSource;
  330. xmlSource.vt = VT_BSTR;
  331. xmlSource.bstrVal = SysAllocString(pwzPath);
  332. if (xmlSource.bstrVal)
  333. {
  334. VARIANT_BOOL fIsSuccessful = VARIANT_TRUE;
  335. hr = (*ppXMLDOMDoc)->load(xmlSource, &fIsSuccessful);
  336. if ((S_FALSE == hr) || (VARIANT_FALSE == fIsSuccessful))
  337. {
  338. // This happens when the file isn't a valid XML file.
  339. hr = E_FAIL;
  340. }
  341. VariantClear(&xmlSource);
  342. }
  343. if (FAILED(hr))
  344. {
  345. ATOMICRELEASE(*ppXMLDOMDoc);
  346. }
  347. }
  348. return hr;
  349. }
  350. HRESULT XMLElem_VerifyTagName(IN IXMLDOMElement * pXMLElementMessage, IN LPCWSTR pwszTagName)
  351. {
  352. BSTR bstrTagName;
  353. HRESULT hr = pXMLElementMessage->get_tagName(&bstrTagName);
  354. if (S_FALSE == hr)
  355. {
  356. hr = E_FAIL;
  357. }
  358. else if (SUCCEEDED(hr))
  359. {
  360. if (!bstrTagName || !pwszTagName || StrCmpIW(bstrTagName, pwszTagName))
  361. {
  362. hr = E_FAIL;
  363. }
  364. SysFreeString(bstrTagName);
  365. }
  366. return hr;
  367. }
  368. HRESULT XMLElem_GetElementsByTagName(IN IXMLDOMElement * pXMLElementMessage, IN LPCWSTR pwszTagName, OUT IXMLDOMNodeList ** ppNodeList)
  369. {
  370. BSTR bstrTagName = SysAllocString(pwszTagName);
  371. HRESULT hr = E_OUTOFMEMORY;
  372. *ppNodeList = NULL;
  373. if (bstrTagName)
  374. {
  375. hr = pXMLElementMessage->getElementsByTagName(bstrTagName, ppNodeList);
  376. if (S_FALSE == hr)
  377. {
  378. hr = E_FAIL;
  379. }
  380. SysFreeString(bstrTagName);
  381. }
  382. return hr;
  383. }
  384. HRESULT XMLNode_GetAttributeValue(IN IXMLDOMNode * pXMLNode, IN LPCWSTR pwszAttributeName, OUT BSTR * pbstrValue)
  385. {
  386. BSTR bstrAttributeName = SysAllocString(pwszAttributeName);
  387. HRESULT hr = E_OUTOFMEMORY;
  388. *pbstrValue = NULL;
  389. if (bstrAttributeName)
  390. {
  391. IXMLDOMNamedNodeMap * pNodeAttributes;
  392. hr = pXMLNode->get_attributes(&pNodeAttributes);
  393. if (S_FALSE == hr) hr = E_FAIL;
  394. if (SUCCEEDED(hr))
  395. {
  396. IXMLDOMNode * pTypeAttribute;
  397. hr = pNodeAttributes->getNamedItem(bstrAttributeName, &pTypeAttribute);
  398. if (S_FALSE == hr) hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  399. if (SUCCEEDED(hr))
  400. {
  401. VARIANT varAtribValue = {0};
  402. hr = pTypeAttribute->get_nodeValue(&varAtribValue);
  403. if (S_FALSE == hr) hr = E_FAIL;
  404. if (SUCCEEDED(hr) && (VT_BSTR == varAtribValue.vt))
  405. {
  406. *pbstrValue = SysAllocString(varAtribValue.bstrVal);
  407. }
  408. VariantClear(&varAtribValue);
  409. pTypeAttribute->Release();
  410. }
  411. pNodeAttributes->Release();
  412. }
  413. SysFreeString(bstrAttributeName);
  414. }
  415. return hr;
  416. }
  417. HRESULT XMLNode_GetChildTag(IN IXMLDOMNode * pXMLNode, IN LPCWSTR pwszTagName, OUT IXMLDOMNode ** ppChildNode)
  418. {
  419. HRESULT hr = E_INVALIDARG;
  420. *ppChildNode = NULL;
  421. if (pXMLNode)
  422. {
  423. IXMLDOMElement * pXMLElement;
  424. hr = pXMLNode->QueryInterface(IID_PPV_ARG(IXMLDOMElement, &pXMLElement));
  425. if (SUCCEEDED(hr))
  426. {
  427. IXMLDOMNodeList * pNodeList;
  428. hr = XMLElem_GetElementsByTagName(pXMLElement, pwszTagName, &pNodeList);
  429. if (SUCCEEDED(hr))
  430. {
  431. hr = XMLNodeList_GetChild(pNodeList, 0, ppChildNode);
  432. pNodeList->Release();
  433. }
  434. pXMLElement->Release();
  435. }
  436. }
  437. return hr;
  438. }
  439. HRESULT XMLNode_GetTagText(IN IXMLDOMNode * pXMLNode, OUT BSTR * pbstrValue)
  440. {
  441. DOMNodeType nodeType = NODE_TEXT;
  442. HRESULT hr = pXMLNode->get_nodeType(&nodeType);
  443. *pbstrValue = NULL;
  444. if (S_FALSE == hr) hr = E_FAIL;
  445. if (SUCCEEDED(hr))
  446. {
  447. if (NODE_TEXT == nodeType)
  448. {
  449. VARIANT varAtribValue = {0};
  450. hr = pXMLNode->get_nodeValue(&varAtribValue);
  451. if (S_FALSE == hr) hr = E_FAIL;
  452. if (SUCCEEDED(hr) && (VT_BSTR == varAtribValue.vt))
  453. {
  454. *pbstrValue = SysAllocString(varAtribValue.bstrVal);
  455. }
  456. VariantClear(&varAtribValue);
  457. }
  458. else
  459. {
  460. hr = pXMLNode->get_text(pbstrValue);
  461. }
  462. }
  463. return hr;
  464. }
  465. HRESULT XMLNodeList_GetChild(IN IXMLDOMNodeList * pNodeList, IN DWORD dwIndex, OUT IXMLDOMNode ** ppXMLChildNode)
  466. {
  467. HRESULT hr = pNodeList->get_item(dwIndex, ppXMLChildNode);
  468. if (S_FALSE == hr)
  469. {
  470. hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  471. }
  472. return hr;
  473. }
  474. HRESULT XMLNode_GetChildTagTextValue(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, OUT BSTR * pbstrValue)
  475. {
  476. IXMLDOMNode * pNodeType;
  477. HRESULT hr = XMLNode_GetChildTag(pXMLNode, bstrChildTag, &pNodeType);
  478. if (SUCCEEDED(hr))
  479. {
  480. hr = XMLNode_GetTagText(pNodeType, pbstrValue);
  481. pNodeType->Release();
  482. }
  483. return hr;
  484. }
  485. HRESULT XMLNode_GetChildTagTextValueToBool(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, OUT BOOL * pfBoolean)
  486. {
  487. BSTR bstr;
  488. HRESULT hr = XMLNode_GetChildTagTextValue(pXMLNode, bstrChildTag, &bstr);
  489. if (SUCCEEDED(hr))
  490. {
  491. if (!StrCmpIW(bstr, L"on"))
  492. {
  493. *pfBoolean = TRUE;
  494. }
  495. else
  496. {
  497. *pfBoolean = FALSE;
  498. }
  499. SysFreeString(bstr);
  500. }
  501. return hr;
  502. }
  503. BOOL XML_IsChildTagTextEqual(IN IXMLDOMNode * pXMLNode, IN BSTR bstrChildTag, IN BSTR bstrText)
  504. {
  505. BOOL fIsChildTagTextEqual = FALSE;
  506. BSTR bstrChildText;
  507. HRESULT hr = XMLNode_GetChildTagTextValue(pXMLNode, bstrChildTag, &bstrChildText);
  508. if (SUCCEEDED(hr))
  509. {
  510. // Is this <TYPE>email</TYPE>?
  511. if (!StrCmpIW(bstrChildText, bstrText))
  512. {
  513. // No, so keep looking.
  514. fIsChildTagTextEqual = TRUE;
  515. }
  516. SysFreeString(bstrChildText);
  517. }
  518. return fIsChildTagTextEqual;
  519. }
  520. /////////////////////////////////////////////////////////////////////
  521. // Wininet Wrapping Helpers
  522. /////////////////////////////////////////////////////////////////////
  523. #define EMPTYSTR_FOR_NULL(str) ((!str) ? TEXT("") : (str))
  524. /*****************************************************************************\
  525. FUNCTION: InternetConnectWrap
  526. DESCRIPTION:
  527. PERF Notes:
  528. [Direct Net Connection]
  529. To: shapitst <Down the Hall>: 144ms - 250ms (Min: 2; Max: 1,667ms)
  530. To: rigel.cyberpass.net <San Diego, CA>: 717ms - 1006ms
  531. To: ftp.rz.uni-frankfurt.de <Germany>: 2609ms - 14,012ms
  532. COMMON ERROR VALUES:
  533. These are the return values in these different cases:
  534. ERROR_INTERNET_NAME_NOT_RESOLVED: No Proxy & DNS Lookup failed.
  535. ERROR_INTERNET_CANNOT_CONNECT: Some Auth Proxies and Netscape's Web/Auth Proxy
  536. ERROR_INTERNET_NAME_NOT_RESOLVED: Web Proxy
  537. ERROR_INTERNET_TIMEOUT: Invalid or Web Proxy blocked IP Address
  538. ERROR_INTERNET_INCORRECT_PASSWORD: IIS & UNIX, UserName may not exist or password for the user may be incorrect on.
  539. ERROR_INTERNET_LOGIN_FAILURE: Too many Users on IIS.
  540. ERROR_INTERNET_INCORRECT_USER_NAME: I haven't seen it.
  541. ERROR_INTERNET_EXTENDED_ERROR: yahoo.com exists, but ftp.yahoo.com doesn't.
  542. \*****************************************************************************/
  543. HRESULT InternetConnectWrap(HINTERNET hInternet, BOOL fAssertOnFailure, LPCTSTR pszServerName, INTERNET_PORT nServerPort,
  544. LPCTSTR pszUserName, LPCTSTR pszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext, HINTERNET * phFileHandle)
  545. {
  546. HRESULT hr = S_OK;
  547. DWORD dwError = 0;
  548. DEBUG_CODE(DebugStartWatch());
  549. *phFileHandle = InternetConnect(hInternet, pszServerName, nServerPort, pszUserName, pszPassword, dwService, dwFlags, dwContext);
  550. if (!*phFileHandle)
  551. {
  552. dwError = GetLastError();
  553. hr = HRESULT_FROM_WIN32(dwError);
  554. }
  555. DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetConnect(%#08lx, \"%ls\", \"%ls\", \"%ls\") returned %u. Time=%lums", hInternet, pszServerName, EMPTYSTR_FOR_NULL(pszUserName), EMPTYSTR_FOR_NULL(pszPassword), dwError, DebugStopWatch()));
  556. if (fAssertOnFailure)
  557. {
  558. }
  559. return hr;
  560. }
  561. /*****************************************************************************\
  562. FUNCTION: InternetOpenWrap
  563. DESCRIPTION:
  564. PERF Notes:
  565. [Direct Net Connection]
  566. Destination not applicable. 677-907ms
  567. \*****************************************************************************/
  568. HRESULT InternetOpenWrap(LPCTSTR pszAgent, DWORD dwAccessType, LPCTSTR pszProxy, LPCTSTR pszProxyBypass, DWORD dwFlags, HINTERNET * phFileHandle)
  569. {
  570. HRESULT hr = S_OK;
  571. DWORD dwError = 0;
  572. DEBUG_CODE(DebugStartWatch());
  573. *phFileHandle = InternetOpen(pszAgent, dwAccessType, pszProxy, pszProxyBypass, dwFlags);
  574. if (!*phFileHandle)
  575. {
  576. dwError = GetLastError();
  577. hr = HRESULT_FROM_WIN32(dwError);
  578. }
  579. DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetOpen(\"%ls\") returned %u. Time=%lums", pszAgent, dwError, DebugStopWatch()));
  580. return hr;
  581. }
  582. HRESULT InternetCloseHandleWrap(HINTERNET hInternet)
  583. {
  584. HRESULT hr = S_OK;
  585. DWORD dwError = 0;
  586. DEBUG_CODE(DebugStartWatch());
  587. if (!InternetCloseHandle(hInternet))
  588. {
  589. dwError = GetLastError();
  590. hr = HRESULT_FROM_WIN32(dwError);
  591. }
  592. DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetCloseHandle(%#08lx) returned %u. Time=%lums", hInternet, dwError, DebugStopWatch()));
  593. return hr;
  594. }
  595. /*****************************************************************************\
  596. FUNCTION: InternetOpenUrlWrap
  597. DESCRIPTION:
  598. PERF Notes:
  599. [Direct Net Connection]
  600. To: shapitst <Down the Hall>: 29ms
  601. To: rigel.cyberpass.net <San Diego, CA>: ???????
  602. To: ftp.rz.uni-frankfurt.de <Germany>: ???????
  603. \*****************************************************************************/
  604. HRESULT InternetOpenUrlWrap(HINTERNET hInternet, LPCTSTR pszUrl, LPCTSTR pszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext, HINTERNET * phFileHandle)
  605. {
  606. HRESULT hr = S_OK;
  607. DWORD dwError = 0;
  608. DEBUG_CODE(DebugStartWatch());
  609. *phFileHandle = InternetOpenUrl(hInternet, pszUrl, pszHeaders, dwHeadersLength, dwFlags, dwContext);
  610. if (!*phFileHandle)
  611. {
  612. dwError = GetLastError();
  613. hr = HRESULT_FROM_WIN32(dwError);
  614. }
  615. DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetOpenUrl(%#08lx, \"%ls\") returned %u. Time=%lums", hInternet, pszUrl, dwError, DebugStopWatch()));
  616. return hr;
  617. }
  618. HRESULT HttpOpenRequestWrap(IN HINTERNET hConnect, IN LPCSTR lpszVerb, IN LPCSTR lpszObjectName, IN LPCSTR lpszVersion,
  619. IN LPCSTR lpszReferer, IN LPCSTR FAR * lpszAcceptTypes, IN DWORD dwFlags, IN DWORD_PTR dwContext,
  620. LPDWORD pdwNumberOfBytesRead, HINTERNET * phConnectionHandle)
  621. {
  622. HRESULT hr = S_OK;
  623. DWORD dwError = 0;
  624. DEBUG_CODE(DebugStartWatch());
  625. *phConnectionHandle = HttpOpenRequestA(hConnect, lpszVerb, lpszObjectName, lpszVersion, lpszReferer, lpszAcceptTypes, dwFlags, dwContext);
  626. if (!*phConnectionHandle)
  627. {
  628. dwError = GetLastError();
  629. hr = HRESULT_FROM_WIN32(dwError);
  630. }
  631. DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "HttpOpenRequest(%#08lx, \"%ls\") returned %u. Time=%lums", *phConnectionHandle, lpszVerb, dwError, DebugStopWatch()));
  632. return hr;
  633. }
  634. HRESULT HttpSendRequestWrap(IN HINTERNET hRequest, IN LPCSTR lpszHeaders, IN DWORD dwHeadersLength, IN LPVOID lpOptional, DWORD dwOptionalLength)
  635. {
  636. HRESULT hr = S_OK;
  637. DWORD dwError = 0;
  638. if (!HttpSendRequestA(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength))
  639. {
  640. dwError = GetLastError();
  641. hr = HRESULT_FROM_WIN32(dwError);
  642. }
  643. return hr;
  644. }
  645. HRESULT InternetReadFileWrap(HINTERNET hFile, LPVOID pvBuffer, DWORD dwNumberOfBytesToRead, LPDWORD pdwNumberOfBytesRead)
  646. {
  647. HRESULT hr = S_OK;
  648. DWORD dwError = 0;
  649. // DEBUG_CODE(DebugStartWatch());
  650. if (!InternetReadFile(hFile, pvBuffer, dwNumberOfBytesToRead, pdwNumberOfBytesRead))
  651. {
  652. dwError = GetLastError();
  653. hr = HRESULT_FROM_WIN32(dwError);
  654. }
  655. // DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetReadFile(%#08lx, ToRead=%d, Read=%d) returned %u. Time=%lums", hFile, dwNumberOfBytesToRead, (pdwNumberOfBytesRead ? *pdwNumberOfBytesRead : -1), dwError, DebugStopWatch()));
  656. return hr;
  657. }
  658. HRESULT CreateUrlCacheEntryWrap(IN LPCTSTR lpszUrlName, IN DWORD dwExpectedFileSize, IN LPCTSTR lpszFileExtension, OUT LPTSTR lpszFileName, IN DWORD dwReserved)
  659. {
  660. HRESULT hr = S_OK;
  661. DWORD dwError = 0;
  662. // DEBUG_CODE(DebugStartWatch());
  663. if (!CreateUrlCacheEntry(lpszUrlName, dwExpectedFileSize, lpszFileExtension, lpszFileName, dwReserved))
  664. {
  665. dwError = GetLastError();
  666. hr = HRESULT_FROM_WIN32(dwError);
  667. }
  668. // DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetReadFile(%#08lx, ToRead=%d, Read=%d) returned %u. Time=%lums", hFile, dwNumberOfBytesToRead, (pdwNumberOfBytesRead ? *pdwNumberOfBytesRead : -1), dwError, DebugStopWatch()));
  669. return hr;
  670. }
  671. HRESULT CommitUrlCacheEntryWrap(IN LPCTSTR lpszUrlName, IN LPCTSTR lpszLocalFileName, IN FILETIME ExpireTime, IN FILETIME LastModifiedTime,
  672. IN DWORD CacheEntryType, IN LPWSTR lpHeaderInfo, IN DWORD dwHeaderSize, IN LPCTSTR lpszFileExtension, IN LPCTSTR lpszOriginalUrl)
  673. {
  674. HRESULT hr = S_OK;
  675. DWORD dwError = 0;
  676. // DEBUG_CODE(DebugStartWatch());
  677. if (!CommitUrlCacheEntryW(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime, CacheEntryType, lpHeaderInfo, dwHeaderSize, lpszFileExtension, lpszOriginalUrl))
  678. {
  679. dwError = GetLastError();
  680. hr = HRESULT_FROM_WIN32(dwError);
  681. }
  682. // DEBUG_CODE(TraceMsg(TF_WMAUTODISCOVERY, "InternetReadFile(%#08lx, ToRead=%d, Read=%d) returned %u. Time=%lums", hFile, dwNumberOfBytesToRead, (pdwNumberOfBytesRead ? *pdwNumberOfBytesRead : -1), dwError, DebugStopWatch()));
  683. return hr;
  684. }
  685. #define SIZE_COPY_BUFFER (32 * 1024) // 32k
  686. HRESULT InternetReadIntoBSTR(HINTERNET hInternetRead, OUT BSTR * pbstrXML)
  687. {
  688. BYTE byteBuffer[SIZE_COPY_BUFFER];
  689. DWORD cbRead = SIZE_COPY_BUFFER;
  690. DWORD cchSize = 0;
  691. HRESULT hr = S_OK;
  692. *pbstrXML = NULL;
  693. while (SUCCEEDED(hr) && cbRead)
  694. {
  695. hr = InternetReadFileWrap(hInternetRead, byteBuffer, sizeof(byteBuffer), &cbRead);
  696. if (SUCCEEDED(hr) && cbRead)
  697. {
  698. BSTR bstrOld = *pbstrXML;
  699. BSTR bstrEnd;
  700. // The string may not be terminated.
  701. byteBuffer[cbRead] = 0;
  702. cchSize += ARRAYSIZE(byteBuffer);
  703. *pbstrXML = SysAllocStringLen(NULL, cchSize);
  704. if (*pbstrXML)
  705. {
  706. if (bstrOld)
  707. {
  708. StrCpyN(*pbstrXML, bstrOld, cchSize);
  709. }
  710. else
  711. {
  712. (*pbstrXML)[0] = 0;
  713. }
  714. bstrEnd = *pbstrXML + lstrlenW(*pbstrXML);
  715. cchSize -= lstrlenW(*pbstrXML);
  716. SHAnsiToUnicode((LPCSTR) byteBuffer, bstrEnd, cchSize);
  717. }
  718. else
  719. {
  720. hr = E_OUTOFMEMORY;
  721. }
  722. SysFreeString(bstrOld);
  723. }
  724. }
  725. return hr;
  726. }
  727. /////////////////////////////////////////////////////////////////////
  728. // File System Wrapping Helpers
  729. /////////////////////////////////////////////////////////////////////
  730. HRESULT CreateFileHrWrap(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  731. DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile, HANDLE * phFileHandle)
  732. {
  733. HRESULT hr = S_OK;
  734. HANDLE hTemp = NULL;
  735. DWORD dwError = 0;
  736. if (!phFileHandle)
  737. phFileHandle = &hTemp;
  738. *phFileHandle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  739. if (!*phFileHandle)
  740. {
  741. dwError = GetLastError();
  742. hr = HRESULT_FROM_WIN32(dwError);
  743. }
  744. if (hTemp)
  745. CloseHandle(hTemp);
  746. return hr;
  747. }
  748. HRESULT WriteFileWrap(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
  749. {
  750. HRESULT hr = S_OK;
  751. DWORD dwError = 0;
  752. if (!WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped))
  753. {
  754. dwError = GetLastError();
  755. hr = HRESULT_FROM_WIN32(dwError);
  756. }
  757. return hr;
  758. }
  759. HRESULT DeleteFileHrWrap(LPCWSTR pszPath)
  760. {
  761. HRESULT hr = S_OK;
  762. DWORD dwError = 0;
  763. if (!DeleteFileW(pszPath))
  764. {
  765. dwError = GetLastError();
  766. hr = HRESULT_FROM_WIN32(dwError);
  767. }
  768. return hr;
  769. }
  770. HRESULT GetPrivateProfileStringHrWrap(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName)
  771. {
  772. HRESULT hr = S_OK;
  773. DWORD chGot = GetPrivateProfileStringW(lpAppName, lpKeyName, lpDefault, lpReturnedString, nSize, lpFileName);
  774. // What else can indicate an error value?
  775. if (0 == chGot)
  776. {
  777. hr = HRESULT_FROM_WIN32(GetLastError());
  778. if (SUCCEEDED(hr))
  779. hr = E_FAIL;
  780. }
  781. return hr;
  782. }
  783. /////////////////////////////////////////////////////////////////////
  784. // Other Helpers
  785. /////////////////////////////////////////////////////////////////////
  786. HRESULT HrRewindStream(IStream * pstm)
  787. {
  788. LARGE_INTEGER liOrigin = {0,0};
  789. return pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  790. }
  791. #define SET_FLAG(dwAllFlags, dwFlag) ((dwAllFlags) |= (dwFlag))
  792. #define IS_FLAG_SET(dwAllFlags, dwFlag) ((BOOL)((dwAllFlags) & (dwFlag)))
  793. // PERFPERF
  794. // This routine used to copy 512 bytes at a time, but that had a major negative perf impact.
  795. // I have measured a 2-3x speedup in copy times by increasing this buffer size to 16k.
  796. // Yes, its a lot of stack, but it is memory well spent. -saml
  797. #define STREAM_COPY_BUF_SIZE 16384
  798. #define STREAM_PROGRESS_INTERVAL (100*1024/STREAM_COPY_BUF_SIZE) // display progress after this many blocks
  799. HRESULT StreamCopyWithProgress(IStream *pstmFrom, IStream *pstmTo, ULARGE_INTEGER cb, PROGRESSINFO * ppi)
  800. {
  801. BYTE buf[STREAM_COPY_BUF_SIZE];
  802. ULONG cbRead;
  803. HRESULT hres = NOERROR;
  804. int nSection = 0; // How many buffer sizes have we copied?
  805. ULARGE_INTEGER uliNewCompleted;
  806. if (ppi)
  807. {
  808. uliNewCompleted.QuadPart = ppi->uliBytesCompleted.QuadPart;
  809. }
  810. while (cb.QuadPart)
  811. {
  812. if (ppi && ppi->ppd)
  813. {
  814. if (0 == (nSection % STREAM_PROGRESS_INTERVAL))
  815. {
  816. ppi->ppd->SetProgress64(uliNewCompleted.QuadPart, ppi->uliBytesTotal.QuadPart);
  817. if (ppi->ppd->HasUserCancelled())
  818. {
  819. hres = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  820. break;
  821. }
  822. }
  823. }
  824. hres = pstmFrom->Read(buf, min(cb.LowPart, sizeof(buf)), &cbRead);
  825. if (FAILED(hres) || (cbRead == 0))
  826. {
  827. // sometimes we are just done.
  828. if (SUCCEEDED(hres))
  829. hres = S_OK;
  830. break;
  831. }
  832. if (ppi)
  833. {
  834. uliNewCompleted.QuadPart += (ULONGLONG) cbRead;
  835. }
  836. cb.QuadPart -= cbRead;
  837. hres = pstmTo->Write(buf, cbRead, &cbRead);
  838. if (FAILED(hres) || (cbRead == 0))
  839. break;
  840. nSection++;
  841. }
  842. return hres;
  843. }
  844. /*
  845. // These are needed for COM/COM+ interop
  846. void __stdcall
  847. _com_raise_error(HRESULT hr, IErrorInfo* perrinfo) throw(_com_error)
  848. {
  849. throw _com_error(hr, perrinfo);
  850. }
  851. void __stdcall
  852. _com_issue_error(HRESULT hr) throw(_com_error)
  853. {
  854. _com_raise_error(hr, NULL);
  855. }
  856. void __stdcall
  857. _com_issue_errorex(HRESULT hr, IUnknown* punk, REFIID riid) throw(_com_error)
  858. {
  859. IErrorInfo* perrinfo = NULL;
  860. if (punk == NULL) {
  861. goto exeunt;
  862. }
  863. ISupportErrorInfo* psei;
  864. if (FAILED(punk->QueryInterface(__uuidof(ISupportErrorInfo),
  865. (void**)&psei))) {
  866. goto exeunt;
  867. }
  868. HRESULT hrSupportsErrorInfo;
  869. hrSupportsErrorInfo = psei->InterfaceSupportsErrorInfo(riid);
  870. psei->Release();
  871. if (hrSupportsErrorInfo != S_OK) {
  872. goto exeunt;
  873. }
  874. if (GetErrorInfo(0, &perrinfo) != S_OK) {
  875. perrinfo = NULL;
  876. }
  877. exeunt:
  878. _com_raise_error(hr, perrinfo);
  879. }
  880. */
  881. // needed by smtpserv:
  882. HRESULT HrByteToStream(LPSTREAM *lppstm, LPBYTE lpb, ULONG cb)
  883. {
  884. // Locals
  885. HRESULT hr=S_OK;
  886. LARGE_INTEGER liOrigin = {0,0};
  887. // Create H Global Stream
  888. hr = CreateStreamOnHGlobal (NULL, TRUE, lppstm);
  889. if (FAILED(hr))
  890. goto exit;
  891. // Write String
  892. hr = (*lppstm)->Write (lpb, cb, NULL);
  893. if (FAILED(hr))
  894. goto exit;
  895. // Rewind the steam
  896. hr = (*lppstm)->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  897. if (FAILED(hr))
  898. goto exit;
  899. exit:
  900. // Done
  901. return hr;
  902. }
  903. const char szDayOfWeekArray[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
  904. const char szMonthOfYearArray[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ;
  905. void GetDateString(char * szSentDateString, ULONG stringLen)
  906. {
  907. // Sent Date
  908. SYSTEMTIME stSentTime;
  909. CHAR szMonth[10], szWeekDay[12] ;
  910. GetSystemTime(&stSentTime);
  911. StrCpyNA(szWeekDay, szDayOfWeekArray[stSentTime.wDayOfWeek], ARRAYSIZE(szWeekDay)) ;
  912. StrCpyNA(szMonth, szMonthOfYearArray[stSentTime.wMonth-1], ARRAYSIZE(szMonth)) ;
  913. wnsprintfA(szSentDateString, stringLen, "%s, %u %s %u %2d:%02d:%02d ", (LPSTR) szWeekDay, stSentTime.wDay,
  914. (LPSTR) szMonth, stSentTime.wYear, stSentTime.wHour,
  915. stSentTime.wMinute, stSentTime.wSecond) ;
  916. }
  917. /*****************************************************************************\
  918. PARAMETERS:
  919. RETURN: Win32 HRESULT (Not Script Safe).
  920. SUCCEEDED(hr) for OK and out params filled in.
  921. FAILED(hr) for all errors.
  922. \*****************************************************************************/
  923. HRESULT GetQueryStringValue(BSTR bstrURL, LPCWSTR pwszValue, LPWSTR pwszData, int cchSizeData)
  924. {
  925. HRESULT hr = E_FAIL;
  926. LPCWSTR pwszIterate = bstrURL;
  927. pwszIterate = StrChrW(pwszIterate, L'?'); // Advance to Query part of URL.
  928. while (pwszIterate && pwszIterate[0])
  929. {
  930. pwszIterate++; // Start at first value
  931. LPCWSTR pwszEndOfValue = StrChrW(pwszIterate, L'=');
  932. if (!pwszEndOfValue)
  933. break;
  934. int cchValueSize = (INT)(UINT)(pwszEndOfValue - pwszIterate);
  935. if (0 == StrCmpNIW(pwszValue, pwszIterate, cchValueSize))
  936. {
  937. int cchSizeToCopy = cchSizeData; // Copy rest of line by default.
  938. pwszIterate = StrChrW(pwszEndOfValue, L'&');
  939. if (pwszIterate)
  940. {
  941. cchSizeToCopy = (INT)(UINT)(pwszIterate - pwszEndOfValue);
  942. }
  943. // It matches, now get the Data.
  944. StrCpyNW(pwszData, (pwszEndOfValue + 1), cchSizeToCopy);
  945. hr = S_OK;
  946. break;
  947. }
  948. else
  949. {
  950. pwszIterate = StrChrW(pwszEndOfValue, L'&');
  951. }
  952. }
  953. return hr;
  954. }
  955. // BUGBUG: This makes this object ways safe. When the MailApps security design is
  956. // complete, this needs to be removed for the permanate security solution.
  957. HRESULT MarkObjectSafe(IUnknown * punk)
  958. {
  959. HRESULT hr = S_OK;
  960. IObjectSafety * pos;
  961. hr = punk->QueryInterface(IID_PPV_ARG(IObjectSafety, &pos));
  962. if (SUCCEEDED(hr))
  963. {
  964. // BUGBUG: This makes this object ways safe. When the MailApps security design is
  965. // complete, this needs to be removed for the permanate solution.
  966. pos->SetInterfaceSafetyOptions(IID_IDispatch, (INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA), 0);
  967. pos->Release();
  968. }
  969. return hr;
  970. }
  971. BOOL _InitComCtl32()
  972. {
  973. static BOOL fInitialized = FALSE;
  974. if (!fInitialized)
  975. {
  976. INITCOMMONCONTROLSEX icc;
  977. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  978. icc.dwICC = (ICC_ANIMATE_CLASS | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_INTERNET_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES);
  979. fInitialized = InitCommonControlsEx(&icc);
  980. }
  981. return fInitialized;
  982. }
  983. HRESULT HrShellExecute(HWND hwnd, LPCTSTR lpVerb, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd)
  984. {
  985. ULARGE_INTEGER uiResult;
  986. uiResult.QuadPart = (ULONGLONG) ShellExecute(hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShowCmd);
  987. if (32 < uiResult.QuadPart)
  988. {
  989. uiResult.LowPart = ERROR_SUCCESS;
  990. }
  991. return HRESULT_FROM_WIN32(uiResult.LowPart);
  992. }
  993. HRESULT StrReplaceToken(IN LPCTSTR pszToken, IN LPCTSTR pszReplaceValue, IN LPTSTR pszString, IN DWORD cchSize)
  994. {
  995. HRESULT hr = S_OK;
  996. LPTSTR pszTempLastHalf = NULL;
  997. LPTSTR pszNextToken = pszString;
  998. while (pszNextToken = StrStrI(pszNextToken, pszToken))
  999. {
  1000. // We found one.
  1001. LPTSTR pszPastToken = pszNextToken + lstrlen(pszToken);
  1002. Str_SetPtr(&pszTempLastHalf, pszPastToken); // Keep a copy because we will overwrite it.
  1003. pszNextToken[0] = 0; // Remove the rest of the string.
  1004. StrCatBuff(pszString, pszReplaceValue, cchSize);
  1005. StrCatBuff(pszString, pszTempLastHalf, cchSize);
  1006. pszNextToken += lstrlen(pszReplaceValue);
  1007. }
  1008. Str_SetPtr(&pszTempLastHalf, NULL);
  1009. return hr;
  1010. }
  1011. BOOL IsOSNT(void)
  1012. {
  1013. OSVERSIONINFOA osVerInfoA;
  1014. osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
  1015. if (!GetVersionExA(&osVerInfoA))
  1016. return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
  1017. return (VER_PLATFORM_WIN32_NT == osVerInfoA.dwPlatformId);
  1018. }
  1019. DWORD GetOSVer(void)
  1020. {
  1021. OSVERSIONINFOA osVerInfoA;
  1022. osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
  1023. if (!GetVersionExA(&osVerInfoA))
  1024. return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
  1025. return osVerInfoA.dwMajorVersion;
  1026. }
  1027. int CALLBACK DPALocalFree_Callback(LPVOID p, LPVOID pData)
  1028. {
  1029. if (p)
  1030. {
  1031. LocalFree(p);
  1032. }
  1033. return 1;
  1034. }
  1035. // lParam can be: 0 == do a case sensitive search. 1 == do a case insensitive search.
  1036. int DPA_StringCompareCB(LPVOID pvString1, LPVOID pvString2, LPARAM lParam)
  1037. {
  1038. // return < 0 for pvPidl1 before pvPidl2.
  1039. // return == 0 for pvPidl1 equals pvPidl2.
  1040. // return > 0 for pvPidl1 after pvPidl2.
  1041. int nSort = 0; // Default to equal
  1042. if (pvString1 && pvString2)
  1043. {
  1044. nSort = StrCmp((LPCTSTR)pvString1, (LPCTSTR)pvString2);
  1045. }
  1046. return nSort;
  1047. }
  1048. HRESULT AddHDPA_StrDup(IN LPCWSTR pszString, IN HDPA * phdpa)
  1049. {
  1050. HRESULT hr = E_OUTOFMEMORY;
  1051. if (!*phdpa)
  1052. {
  1053. *phdpa = DPA_Create(2);
  1054. }
  1055. if (*phdpa)
  1056. {
  1057. LPWSTR pszStringCopy = StrDup(pszString);
  1058. if (pszStringCopy)
  1059. {
  1060. if (-1 == DPA_SortedInsertPtr(*phdpa, pszStringCopy, 0, DPA_StringCompareCB, NULL, DPAS_INSERTBEFORE, pszStringCopy))
  1061. {
  1062. // We failed so free the memory
  1063. LocalFree(pszStringCopy);
  1064. }
  1065. else
  1066. {
  1067. hr = S_OK;
  1068. }
  1069. }
  1070. }
  1071. return hr;
  1072. }