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.

300 lines
7.3 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: ncinet2.cpp
  7. //
  8. // Contents: Wrappers for some Urlmon APIs
  9. //
  10. // Notes:
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.h>
  14. #pragma hdrstop
  15. #include <wininet.h> // for ICU_NO_ENCODE
  16. #include "ncinet2.h"
  17. #include "ncstring.h" // WszAllocateAndCopyWsz
  18. // note: this uses Urlmon, where the other methods only pull in
  19. // wininet.
  20. HRESULT
  21. HrCombineUrl(LPCWSTR pszBaseUrl,
  22. LPCWSTR pszRelativeUrl,
  23. LPWSTR * ppszResult)
  24. {
  25. const DWORD dwCombineFlags = ICU_NO_ENCODE;
  26. HRESULT hr;
  27. LPWSTR pszResult;
  28. WCHAR wcharTemp;
  29. DWORD cchNeeded;
  30. pszResult = NULL;
  31. cchNeeded = 0;
  32. wcharTemp = L'\0';
  33. if (!ppszResult)
  34. {
  35. hr = E_POINTER;
  36. goto Cleanup;
  37. }
  38. if (!pszBaseUrl)
  39. {
  40. hr = E_POINTER;
  41. goto Cleanup;
  42. }
  43. if (!pszRelativeUrl)
  44. {
  45. hr = E_POINTER;
  46. goto Cleanup;
  47. }
  48. // we use this instead of InternetCombineUrl so that pluggable
  49. // protocols can do their thing.
  50. // we're assuming here that the arguments have the same semantics
  51. // as InternetCombineUrl(), as CoInternetCombineUrl is poorly
  52. // documented.
  53. // note: we don't know what the length of the combined URL is.
  54. // instead of doing two allocations, we do a dummy call to
  55. // CoInternetCombineUrl to find the needed length, allocate
  56. // the string, and then call CoInternetCombineUrl "for real".
  57. hr = CoInternetCombineUrl(pszBaseUrl,
  58. pszRelativeUrl,
  59. dwCombineFlags, // the url should already be encoded
  60. &wcharTemp,
  61. 1,
  62. &cchNeeded,
  63. 0);
  64. // note(cmr): MSDN says that CoInternetCombineUrl will return S_FALSE
  65. // if we don't have enough space in our buffer. Its implementation,
  66. // though, generally calls UrlCombineW, which is supposed to return
  67. // E_POINTER in this case.
  68. // Emperically, E_POINTER is returned here. This seems like a case of
  69. // MSDN just being wrong. We'll expect both E_POINTER and S_FALSE
  70. // as return values here, to be safe.
  71. if ((E_POINTER != hr) && FAILED(hr))
  72. {
  73. TraceError("HrCombineUrl: CoInternetCombineUrl", hr);
  74. hr = E_FAIL;
  75. goto Cleanup;
  76. }
  77. else if ((S_FALSE == hr) || (E_POINTER == hr))
  78. {
  79. Assert(cchNeeded);
  80. DWORD cchWritten;
  81. cchWritten = 0;
  82. // call CoInternetCombineUrl for real.
  83. // cchNeeded includes the room for
  84. pszResult = new WCHAR[cchNeeded];
  85. if (!pszResult)
  86. {
  87. hr = E_OUTOFMEMORY;
  88. goto Cleanup;
  89. }
  90. hr = CoInternetCombineUrl(pszBaseUrl,
  91. pszRelativeUrl,
  92. dwCombineFlags, // the url should already be encoded
  93. pszResult, // note: this is WRITTEN to...
  94. cchNeeded, // note: should THIS value include the null-terminator?
  95. &cchWritten,
  96. 0);
  97. TraceError("HrCombineUrl: CoInternetCombineUrl", hr);
  98. if (FAILED(hr))
  99. {
  100. hr = E_FAIL;
  101. goto Error;
  102. }
  103. else if (S_FALSE == hr)
  104. {
  105. // this shouldn't have happened. we had enough space.
  106. hr = E_UNEXPECTED;
  107. goto Error;
  108. }
  109. Assert(S_OK == hr);
  110. Assert((cchNeeded - 1) == cchWritten);
  111. Assert(L'\0' == pszResult[cchWritten]);
  112. }
  113. else
  114. {
  115. Assert(S_OK == hr);
  116. Assert(L'\0' == wcharTemp);
  117. // since the result needs to be null-terminated, the combined url
  118. // must be the empty string. Wacky. Let's allocate a string and
  119. // return it regardless.
  120. pszResult = new WCHAR [1];
  121. if (!pszResult)
  122. {
  123. hr = E_OUTOFMEMORY;
  124. goto Cleanup;
  125. }
  126. *pszResult = L'\0';
  127. }
  128. Cleanup:
  129. Assert(FImplies(SUCCEEDED(hr), pszResult));
  130. Assert(FImplies(FAILED(hr), !pszResult));
  131. if (ppszResult)
  132. {
  133. *ppszResult = pszResult;
  134. }
  135. TraceError("HrCombineUrl", hr);
  136. return hr;
  137. Error:
  138. if (pszResult)
  139. {
  140. delete [] pszResult;
  141. pszResult = NULL;
  142. }
  143. goto Cleanup;
  144. }
  145. // verifies that the given url is a valid url, and if it is,
  146. // copies it into a newly-allocated string at ppszResult
  147. // return values
  148. // S_OK it's a valid url. *ppszResult is a copy
  149. // S_FALSE it's not a valid url. *ppszResult is NULL
  150. HRESULT
  151. HrCopyAndValidateUrl(LPCWSTR pszUrl,
  152. LPWSTR * ppszResult)
  153. {
  154. HRESULT hr;
  155. LPWSTR pszResult;
  156. pszResult = NULL;
  157. if (!ppszResult)
  158. {
  159. hr = E_POINTER;
  160. goto Cleanup;
  161. }
  162. if (!pszUrl)
  163. {
  164. hr = E_POINTER;
  165. goto Cleanup;
  166. }
  167. // make sure the URL we're handing back is well-formed
  168. hr = IsValidURL(NULL, pszUrl, 0);
  169. TraceError("HrCopyAndValidateUrl: IsValidURL", hr);
  170. if (S_OK == hr)
  171. {
  172. // the url was valid
  173. pszResult = WszAllocateAndCopyWsz(pszUrl);
  174. if (!pszResult)
  175. {
  176. hr = E_OUTOFMEMORY;
  177. goto Cleanup;
  178. }
  179. }
  180. Cleanup:
  181. Assert(FImplies(S_OK == hr, pszResult));
  182. Assert(FImplies(S_OK != hr, !pszResult));
  183. if (ppszResult)
  184. {
  185. *ppszResult = pszResult;
  186. }
  187. TraceError("HrCopyAndValidateUrl", hr);
  188. return hr;
  189. }
  190. // this returns the security domain of the url, if one exists.
  191. // if one doesn't exist, it returns null
  192. HRESULT
  193. HrGetSecurityDomainOfUrl(LPCWSTR pszUrl,
  194. LPWSTR * ppszResult)
  195. {
  196. HRESULT hr;
  197. LPWSTR pszResult;
  198. pszResult = NULL;
  199. if (!ppszResult)
  200. {
  201. hr = E_POINTER;
  202. goto Cleanup;
  203. }
  204. *ppszResult = NULL;
  205. hr = CoInternetGetSecurityUrl(pszUrl,
  206. &pszResult,
  207. PSU_DEFAULT,
  208. 0);
  209. if (FAILED(hr))
  210. {
  211. TraceError("HrGetSecurityDomainOfUrl: CoInternetGetSecurityUrl", hr);
  212. goto Cleanup;
  213. }
  214. *ppszResult = pszResult;
  215. Cleanup:
  216. TraceError("HrGetSecurityDomainOfUrl", hr);
  217. return hr;
  218. }
  219. // Returns TRUE if the scheme of the specified URL is "http"
  220. // or "https", FALSE otherwise.
  221. // note: we do this because I really can't justify writing
  222. // a bunch of code to call a urlmon function that contains
  223. // a bunch of code to call a wininet function to do this
  224. // strcmp.
  225. BOOL
  226. FIsHttpUrl(LPCWSTR pszUrl)
  227. {
  228. Assert(pszUrl);
  229. CONST WCHAR rgchHttpScheme [] = L"http:";
  230. CONST size_t cchHttpScheme = celems(rgchHttpScheme) - 1;
  231. CONST WCHAR rgchHttpsScheme [] = L"https:";
  232. CONST size_t cchHttpsScheme = celems(rgchHttpsScheme) - 1;
  233. BOOL fResult;
  234. int result;
  235. fResult = FALSE;
  236. result = wcsncmp(rgchHttpScheme, pszUrl, cchHttpScheme);
  237. if (0 == result)
  238. {
  239. fResult = TRUE;
  240. }
  241. else
  242. {
  243. result = wcsncmp(rgchHttpsScheme, pszUrl, cchHttpsScheme);
  244. if (0 == result)
  245. {
  246. fResult = TRUE;
  247. }
  248. }
  249. return fResult;
  250. }