diff options
author | Rob Mensching <rob@firegiant.com> | 2017-09-03 11:22:38 -0700 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2017-09-03 13:33:33 -0700 |
commit | 5d8375007754101ff2889d0e79486c8f9b7cf5ab (patch) | |
tree | a76d6fb6a38dd9f04a93ffcfd9d64e76779b3414 /src/dutil/uriutil.cpp | |
parent | 8e8da6dbc051ec884b5d439bb4f44dc027d05bbf (diff) | |
download | wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.gz wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.tar.bz2 wix-5d8375007754101ff2889d0e79486c8f9b7cf5ab.zip |
Initial commit
Diffstat (limited to 'src/dutil/uriutil.cpp')
-rw-r--r-- | src/dutil/uriutil.cpp | 538 |
1 files changed, 538 insertions, 0 deletions
diff --git a/src/dutil/uriutil.cpp b/src/dutil/uriutil.cpp new file mode 100644 index 00000000..fc192b3f --- /dev/null +++ b/src/dutil/uriutil.cpp | |||
@@ -0,0 +1,538 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | #include "precomp.h" | ||
4 | |||
5 | |||
6 | // | ||
7 | // UriCanonicalize - canonicalizes a URI. | ||
8 | // | ||
9 | extern "C" HRESULT DAPI UriCanonicalize( | ||
10 | __inout_z LPWSTR* psczUri | ||
11 | ) | ||
12 | { | ||
13 | HRESULT hr = S_OK; | ||
14 | WCHAR wz[INTERNET_MAX_URL_LENGTH] = { }; | ||
15 | DWORD cch = countof(wz); | ||
16 | |||
17 | if (!::InternetCanonicalizeUrlW(*psczUri, wz, &cch, ICU_DECODE)) | ||
18 | { | ||
19 | ExitWithLastError(hr, "Failed to canonicalize URI."); | ||
20 | } | ||
21 | |||
22 | hr = StrAllocString(psczUri, wz, cch); | ||
23 | ExitOnFailure(hr, "Failed copy canonicalized URI."); | ||
24 | |||
25 | LExit: | ||
26 | return hr; | ||
27 | } | ||
28 | |||
29 | |||
30 | // | ||
31 | // UriCrack - cracks a URI into constituent parts. | ||
32 | // | ||
33 | extern "C" HRESULT DAPI UriCrack( | ||
34 | __in_z LPCWSTR wzUri, | ||
35 | __out_opt INTERNET_SCHEME* pScheme, | ||
36 | __deref_opt_out_z LPWSTR* psczHostName, | ||
37 | __out_opt INTERNET_PORT* pPort, | ||
38 | __deref_opt_out_z LPWSTR* psczUser, | ||
39 | __deref_opt_out_z LPWSTR* psczPassword, | ||
40 | __deref_opt_out_z LPWSTR* psczPath, | ||
41 | __deref_opt_out_z LPWSTR* psczQueryString | ||
42 | ) | ||
43 | { | ||
44 | HRESULT hr = S_OK; | ||
45 | URL_COMPONENTSW components = { }; | ||
46 | WCHAR wzHostName[INTERNET_MAX_HOST_NAME_LENGTH + 1]; | ||
47 | WCHAR wzUserName[INTERNET_MAX_USER_NAME_LENGTH + 1]; | ||
48 | WCHAR wzPassword[INTERNET_MAX_PASSWORD_LENGTH + 1]; | ||
49 | WCHAR wzPath[INTERNET_MAX_PATH_LENGTH + 1]; | ||
50 | WCHAR wzQueryString[INTERNET_MAX_PATH_LENGTH + 1]; | ||
51 | |||
52 | components.dwStructSize = sizeof(URL_COMPONENTSW); | ||
53 | |||
54 | if (psczHostName) | ||
55 | { | ||
56 | components.lpszHostName = wzHostName; | ||
57 | components.dwHostNameLength = countof(wzHostName); | ||
58 | } | ||
59 | |||
60 | if (psczUser) | ||
61 | { | ||
62 | components.lpszUserName = wzUserName; | ||
63 | components.dwUserNameLength = countof(wzUserName); | ||
64 | } | ||
65 | |||
66 | if (psczPassword) | ||
67 | { | ||
68 | components.lpszPassword = wzPassword; | ||
69 | components.dwPasswordLength = countof(wzPassword); | ||
70 | } | ||
71 | |||
72 | if (psczPath) | ||
73 | { | ||
74 | components.lpszUrlPath = wzPath; | ||
75 | components.dwUrlPathLength = countof(wzPath); | ||
76 | } | ||
77 | |||
78 | if (psczQueryString) | ||
79 | { | ||
80 | components.lpszExtraInfo = wzQueryString; | ||
81 | components.dwExtraInfoLength = countof(wzQueryString); | ||
82 | } | ||
83 | |||
84 | if (!::InternetCrackUrlW(wzUri, 0, ICU_DECODE | ICU_ESCAPE, &components)) | ||
85 | { | ||
86 | ExitWithLastError(hr, "Failed to crack URI."); | ||
87 | } | ||
88 | |||
89 | if (pScheme) | ||
90 | { | ||
91 | *pScheme = components.nScheme; | ||
92 | } | ||
93 | |||
94 | if (psczHostName) | ||
95 | { | ||
96 | hr = StrAllocString(psczHostName, components.lpszHostName, components.dwHostNameLength); | ||
97 | ExitOnFailure(hr, "Failed to copy host name."); | ||
98 | } | ||
99 | |||
100 | if (pPort) | ||
101 | { | ||
102 | *pPort = components.nPort; | ||
103 | } | ||
104 | |||
105 | if (psczUser) | ||
106 | { | ||
107 | hr = StrAllocString(psczUser, components.lpszUserName, components.dwUserNameLength); | ||
108 | ExitOnFailure(hr, "Failed to copy user name."); | ||
109 | } | ||
110 | |||
111 | if (psczPassword) | ||
112 | { | ||
113 | hr = StrAllocString(psczPassword, components.lpszPassword, components.dwPasswordLength); | ||
114 | ExitOnFailure(hr, "Failed to copy password."); | ||
115 | } | ||
116 | |||
117 | if (psczPath) | ||
118 | { | ||
119 | hr = StrAllocString(psczPath, components.lpszUrlPath, components.dwUrlPathLength); | ||
120 | ExitOnFailure(hr, "Failed to copy path."); | ||
121 | } | ||
122 | |||
123 | if (psczQueryString) | ||
124 | { | ||
125 | hr = StrAllocString(psczQueryString, components.lpszExtraInfo, components.dwExtraInfoLength); | ||
126 | ExitOnFailure(hr, "Failed to copy query string."); | ||
127 | } | ||
128 | |||
129 | LExit: | ||
130 | return hr; | ||
131 | } | ||
132 | |||
133 | |||
134 | // | ||
135 | // UriCrackEx - cracks a URI into URI_INFO. | ||
136 | // | ||
137 | extern "C" HRESULT DAPI UriCrackEx( | ||
138 | __in_z LPCWSTR wzUri, | ||
139 | __in URI_INFO* pUriInfo | ||
140 | ) | ||
141 | { | ||
142 | HRESULT hr = S_OK; | ||
143 | |||
144 | hr = UriCrack(wzUri, &pUriInfo->scheme, &pUriInfo->sczHostName, &pUriInfo->port, &pUriInfo->sczUser, &pUriInfo->sczPassword, &pUriInfo->sczPath, &pUriInfo->sczQueryString); | ||
145 | ExitOnFailure(hr, "Failed to crack URI."); | ||
146 | |||
147 | LExit: | ||
148 | return hr; | ||
149 | } | ||
150 | |||
151 | |||
152 | // | ||
153 | // UriInfoUninitialize - frees the memory in a URI_INFO struct. | ||
154 | // | ||
155 | extern "C" void DAPI UriInfoUninitialize( | ||
156 | __in URI_INFO* pUriInfo | ||
157 | ) | ||
158 | { | ||
159 | ReleaseStr(pUriInfo->sczHostName); | ||
160 | ReleaseStr(pUriInfo->sczUser); | ||
161 | ReleaseStr(pUriInfo->sczPassword); | ||
162 | ReleaseStr(pUriInfo->sczPath); | ||
163 | ReleaseStr(pUriInfo->sczQueryString); | ||
164 | memset(pUriInfo, 0, sizeof(URI_INFO)); | ||
165 | } | ||
166 | |||
167 | |||
168 | // | ||
169 | // UriCreate - creates a URI from constituent parts. | ||
170 | // | ||
171 | extern "C" HRESULT DAPI UriCreate( | ||
172 | __inout_z LPWSTR* psczUri, | ||
173 | __in INTERNET_SCHEME scheme, | ||
174 | __in_z_opt LPWSTR wzHostName, | ||
175 | __in INTERNET_PORT port, | ||
176 | __in_z_opt LPWSTR wzUser, | ||
177 | __in_z_opt LPWSTR wzPassword, | ||
178 | __in_z_opt LPWSTR wzPath, | ||
179 | __in_z_opt LPWSTR wzQueryString | ||
180 | ) | ||
181 | { | ||
182 | HRESULT hr = S_OK; | ||
183 | WCHAR wz[INTERNET_MAX_URL_LENGTH] = { }; | ||
184 | DWORD cch = countof(wz); | ||
185 | URL_COMPONENTSW components = { }; | ||
186 | |||
187 | components.dwStructSize = sizeof(URL_COMPONENTSW); | ||
188 | components.nScheme = scheme; | ||
189 | components.lpszHostName = wzHostName; | ||
190 | components.nPort = port; | ||
191 | components.lpszUserName = wzUser; | ||
192 | components.lpszPassword = wzPassword; | ||
193 | components.lpszUrlPath = wzPath; | ||
194 | components.lpszExtraInfo = wzQueryString; | ||
195 | |||
196 | if (!::InternetCreateUrlW(&components, ICU_ESCAPE, wz, &cch)) | ||
197 | { | ||
198 | ExitWithLastError(hr, "Failed to create URI."); | ||
199 | } | ||
200 | |||
201 | hr = StrAllocString(psczUri, wz, cch); | ||
202 | ExitOnFailure(hr, "Failed copy created URI."); | ||
203 | |||
204 | LExit: | ||
205 | return hr; | ||
206 | } | ||
207 | |||
208 | |||
209 | // | ||
210 | // UriGetServerAndResource - gets the server and resource as independent strings from a URI. | ||
211 | // | ||
212 | // NOTE: This function is useful for the InternetConnect/HttpRequest APIs. | ||
213 | // | ||
214 | extern "C" HRESULT DAPI UriGetServerAndResource( | ||
215 | __in_z LPCWSTR wzUri, | ||
216 | __out_z LPWSTR* psczServer, | ||
217 | __out_z LPWSTR* psczResource | ||
218 | ) | ||
219 | { | ||
220 | HRESULT hr = S_OK; | ||
221 | INTERNET_SCHEME scheme = INTERNET_SCHEME_UNKNOWN; | ||
222 | LPWSTR sczHostName = NULL; | ||
223 | INTERNET_PORT port = INTERNET_INVALID_PORT_NUMBER; | ||
224 | LPWSTR sczUser = NULL; | ||
225 | LPWSTR sczPassword = NULL; | ||
226 | LPWSTR sczPath = NULL; | ||
227 | LPWSTR sczQueryString = NULL; | ||
228 | |||
229 | hr = UriCrack(wzUri, &scheme, &sczHostName, &port, &sczUser, &sczPassword, &sczPath, &sczQueryString); | ||
230 | ExitOnFailure(hr, "Failed to crack URI."); | ||
231 | |||
232 | hr = UriCreate(psczServer, scheme, sczHostName, port, sczUser, sczPassword, NULL, NULL); | ||
233 | ExitOnFailure(hr, "Failed to allocate server URI."); | ||
234 | |||
235 | hr = UriCreate(psczResource, INTERNET_SCHEME_UNKNOWN, NULL, INTERNET_INVALID_PORT_NUMBER, NULL, NULL, sczPath, sczQueryString); | ||
236 | ExitOnFailure(hr, "Failed to allocate resource URI."); | ||
237 | |||
238 | LExit: | ||
239 | ReleaseStr(sczQueryString); | ||
240 | ReleaseStr(sczPath); | ||
241 | ReleaseStr(sczPassword); | ||
242 | ReleaseStr(sczUser); | ||
243 | ReleaseStr(sczHostName); | ||
244 | |||
245 | return hr; | ||
246 | } | ||
247 | |||
248 | |||
249 | // | ||
250 | // UriFile - returns the file part of the URI. | ||
251 | // | ||
252 | extern "C" HRESULT DAPI UriFile( | ||
253 | __deref_out_z LPWSTR* psczFile, | ||
254 | __in_z LPCWSTR wzUri | ||
255 | ) | ||
256 | { | ||
257 | HRESULT hr = S_OK; | ||
258 | WCHAR wz[MAX_PATH + 1]; | ||
259 | DWORD cch = countof(wz); | ||
260 | URL_COMPONENTSW uc = { }; | ||
261 | |||
262 | uc.dwStructSize = sizeof(uc); | ||
263 | uc.lpszUrlPath = wz; | ||
264 | uc.dwUrlPathLength = cch; | ||
265 | |||
266 | if (!::InternetCrackUrlW(wzUri, 0, ICU_DECODE | ICU_ESCAPE, &uc)) | ||
267 | { | ||
268 | ExitWithLastError(hr, "Failed to crack URI."); | ||
269 | } | ||
270 | |||
271 | // Copy only the file name. Fortunately, PathFile() understands that | ||
272 | // forward slashes can be directory separators like backslashes. | ||
273 | hr = StrAllocString(psczFile, PathFile(wz), 0); | ||
274 | ExitOnFailure(hr, "Failed to copy file name"); | ||
275 | |||
276 | LExit: | ||
277 | return hr; | ||
278 | } | ||
279 | |||
280 | |||
281 | /******************************************************************* | ||
282 | UriProtocol - determines the protocol of a URI. | ||
283 | |||
284 | ********************************************************************/ | ||
285 | extern "C" HRESULT DAPI UriProtocol( | ||
286 | __in_z LPCWSTR wzUri, | ||
287 | __out URI_PROTOCOL* pProtocol | ||
288 | ) | ||
289 | { | ||
290 | Assert(wzUri && *wzUri); | ||
291 | Assert(pProtocol); | ||
292 | |||
293 | HRESULT hr = S_OK; | ||
294 | |||
295 | if ((L'h' == wzUri[0] || L'H' == wzUri[0]) && | ||
296 | (L't' == wzUri[1] || L'T' == wzUri[1]) && | ||
297 | (L't' == wzUri[2] || L'T' == wzUri[2]) && | ||
298 | (L'p' == wzUri[3] || L'P' == wzUri[3]) && | ||
299 | (L's' == wzUri[4] || L'S' == wzUri[4]) && | ||
300 | L':' == wzUri[5] && | ||
301 | L'/' == wzUri[6] && | ||
302 | L'/' == wzUri[7]) | ||
303 | { | ||
304 | *pProtocol = URI_PROTOCOL_HTTPS; | ||
305 | } | ||
306 | else if ((L'h' == wzUri[0] || L'H' == wzUri[0]) && | ||
307 | (L't' == wzUri[1] || L'T' == wzUri[1]) && | ||
308 | (L't' == wzUri[2] || L'T' == wzUri[2]) && | ||
309 | (L'p' == wzUri[3] || L'P' == wzUri[3]) && | ||
310 | L':' == wzUri[4] && | ||
311 | L'/' == wzUri[5] && | ||
312 | L'/' == wzUri[6]) | ||
313 | { | ||
314 | *pProtocol = URI_PROTOCOL_HTTP; | ||
315 | } | ||
316 | else if ((L'f' == wzUri[0] || L'F' == wzUri[0]) && | ||
317 | (L't' == wzUri[1] || L'T' == wzUri[1]) && | ||
318 | (L'p' == wzUri[2] || L'P' == wzUri[2]) && | ||
319 | L':' == wzUri[3] && | ||
320 | L'/' == wzUri[4] && | ||
321 | L'/' == wzUri[5]) | ||
322 | { | ||
323 | *pProtocol = URI_PROTOCOL_FTP; | ||
324 | } | ||
325 | else if ((L'f' == wzUri[0] || L'F' == wzUri[0]) && | ||
326 | (L'i' == wzUri[1] || L'I' == wzUri[1]) && | ||
327 | (L'l' == wzUri[2] || L'L' == wzUri[2]) && | ||
328 | (L'e' == wzUri[3] || L'E' == wzUri[3]) && | ||
329 | L':' == wzUri[4] && | ||
330 | L'/' == wzUri[5] && | ||
331 | L'/' == wzUri[6]) | ||
332 | { | ||
333 | *pProtocol = URI_PROTOCOL_FILE; | ||
334 | } | ||
335 | else | ||
336 | { | ||
337 | *pProtocol = URI_PROTOCOL_UNKNOWN; | ||
338 | } | ||
339 | |||
340 | return hr; | ||
341 | } | ||
342 | |||
343 | |||
344 | /******************************************************************* | ||
345 | UriRoot - returns the root of the path specified in the URI. | ||
346 | |||
347 | examples: | ||
348 | file:///C:\path\path -> C:\ | ||
349 | file://server/share/path/path -> \\server\share | ||
350 | http://www.example.com/path/path -> http://www.example.com/ | ||
351 | ftp://ftp.example.com/path/path -> ftp://www.example.com/ | ||
352 | |||
353 | NOTE: This function should only be used on cannonicalized URIs. | ||
354 | It does not cannonicalize itself. | ||
355 | ********************************************************************/ | ||
356 | extern "C" HRESULT DAPI UriRoot( | ||
357 | __in_z LPCWSTR wzUri, | ||
358 | __out LPWSTR* ppwzRoot, | ||
359 | __out_opt URI_PROTOCOL* pProtocol | ||
360 | ) | ||
361 | { | ||
362 | Assert(wzUri && *wzUri); | ||
363 | Assert(ppwzRoot); | ||
364 | |||
365 | HRESULT hr = S_OK; | ||
366 | URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN; | ||
367 | LPCWSTR pwcSlash = NULL; | ||
368 | |||
369 | hr = UriProtocol(wzUri, &protocol); | ||
370 | ExitOnFailure(hr, "Invalid URI."); | ||
371 | |||
372 | switch (protocol) | ||
373 | { | ||
374 | case URI_PROTOCOL_FILE: | ||
375 | if (L'/' == wzUri[7]) // file path | ||
376 | { | ||
377 | if (((L'a' <= wzUri[8] && L'z' >= wzUri[8]) || (L'A' <= wzUri[8] && L'Z' >= wzUri[8])) && L':' == wzUri[9]) | ||
378 | { | ||
379 | hr = StrAlloc(ppwzRoot, 4); | ||
380 | ExitOnFailure(hr, "Failed to allocate string for root of URI."); | ||
381 | *ppwzRoot[0] = wzUri[8]; | ||
382 | *ppwzRoot[1] = L':'; | ||
383 | *ppwzRoot[2] = L'\\'; | ||
384 | *ppwzRoot[3] = L'\0'; | ||
385 | } | ||
386 | else | ||
387 | { | ||
388 | hr = E_INVALIDARG; | ||
389 | ExitOnFailure(hr, "Invalid file path in URI."); | ||
390 | } | ||
391 | } | ||
392 | else // UNC share | ||
393 | { | ||
394 | pwcSlash = wcschr(wzUri + 8, L'/'); | ||
395 | if (!pwcSlash) | ||
396 | { | ||
397 | hr = E_INVALIDARG; | ||
398 | ExitOnFailure(hr, "Invalid server name in URI."); | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | hr = StrAllocString(ppwzRoot, L"\\\\", 64); | ||
403 | ExitOnFailure(hr, "Failed to allocate string for root of URI."); | ||
404 | |||
405 | pwcSlash = wcschr(pwcSlash + 1, L'/'); | ||
406 | if (pwcSlash) | ||
407 | { | ||
408 | hr = StrAllocConcat(ppwzRoot, wzUri + 8, pwcSlash - wzUri - 8); | ||
409 | ExitOnFailure(hr, "Failed to add server/share to root of URI."); | ||
410 | } | ||
411 | else | ||
412 | { | ||
413 | hr = StrAllocConcat(ppwzRoot, wzUri + 8, 0); | ||
414 | ExitOnFailure(hr, "Failed to add server/share to root of URI."); | ||
415 | } | ||
416 | |||
417 | // replace all slashes with backslashes to be truly UNC. | ||
418 | for (LPWSTR pwc = *ppwzRoot; pwc && *pwc; ++pwc) | ||
419 | { | ||
420 | if (L'/' == *pwc) | ||
421 | { | ||
422 | *pwc = L'\\'; | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | } | ||
427 | break; | ||
428 | |||
429 | case URI_PROTOCOL_FTP: | ||
430 | pwcSlash = wcschr(wzUri + 6, L'/'); | ||
431 | if (pwcSlash) | ||
432 | { | ||
433 | hr = StrAllocString(ppwzRoot, wzUri, pwcSlash - wzUri); | ||
434 | ExitOnFailure(hr, "Failed allocate root from URI."); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | hr = StrAllocString(ppwzRoot, wzUri, 0); | ||
439 | ExitOnFailure(hr, "Failed allocate root from URI."); | ||
440 | } | ||
441 | break; | ||
442 | |||
443 | case URI_PROTOCOL_HTTP: | ||
444 | pwcSlash = wcschr(wzUri + 7, L'/'); | ||
445 | if (pwcSlash) | ||
446 | { | ||
447 | hr = StrAllocString(ppwzRoot, wzUri, pwcSlash - wzUri); | ||
448 | ExitOnFailure(hr, "Failed allocate root from URI."); | ||
449 | } | ||
450 | else | ||
451 | { | ||
452 | hr = StrAllocString(ppwzRoot, wzUri, 0); | ||
453 | ExitOnFailure(hr, "Failed allocate root from URI."); | ||
454 | } | ||
455 | break; | ||
456 | |||
457 | default: | ||
458 | hr = E_INVALIDARG; | ||
459 | ExitOnFailure(hr, "Unknown URI protocol."); | ||
460 | } | ||
461 | |||
462 | if (pProtocol) | ||
463 | { | ||
464 | *pProtocol = protocol; | ||
465 | } | ||
466 | |||
467 | LExit: | ||
468 | return hr; | ||
469 | } | ||
470 | |||
471 | |||
472 | extern "C" HRESULT DAPI UriResolve( | ||
473 | __in_z LPCWSTR wzUri, | ||
474 | __in_opt LPCWSTR wzBaseUri, | ||
475 | __out LPWSTR* ppwzResolvedUri, | ||
476 | __out_opt const URI_PROTOCOL* pResolvedProtocol | ||
477 | ) | ||
478 | { | ||
479 | UNREFERENCED_PARAMETER(wzUri); | ||
480 | UNREFERENCED_PARAMETER(wzBaseUri); | ||
481 | UNREFERENCED_PARAMETER(ppwzResolvedUri); | ||
482 | UNREFERENCED_PARAMETER(pResolvedProtocol); | ||
483 | |||
484 | HRESULT hr = E_NOTIMPL; | ||
485 | #if 0 | ||
486 | URI_PROTOCOL protocol = URI_PROTOCOL_UNKNOWN; | ||
487 | |||
488 | hr = UriProtocol(wzUri, &protocol); | ||
489 | ExitOnFailure(hr, "Failed to determine protocol for URL: %ls", wzUri); | ||
490 | |||
491 | ExitOnNull(ppwzResolvedUri, hr, E_INVALIDARG, "Failed to resolve URI, because no method of output was provided"); | ||
492 | |||
493 | if (URI_PROTOCOL_UNKNOWN == protocol) | ||
494 | { | ||
495 | ExitOnNull(wzBaseUri, hr, E_INVALIDARG, "Failed to resolve URI - base URI provided was NULL"); | ||
496 | |||
497 | if (L'/' == *wzUri || L'\\' == *wzUri) | ||
498 | { | ||
499 | hr = UriRoot(wzBaseUri, ppwzResolvedUri, &protocol); | ||
500 | ExitOnFailure(hr, "Failed to get root from URI: %ls", wzBaseUri); | ||
501 | |||
502 | hr = StrAllocConcat(ppwzResolvedUri, wzUri, 0); | ||
503 | ExitOnFailure(hr, "Failed to concat file to base URI."); | ||
504 | } | ||
505 | else | ||
506 | { | ||
507 | hr = UriProtocol(wzBaseUri, &protocol); | ||
508 | ExitOnFailure(hr, "Failed to get protocol of base URI: %ls", wzBaseUri); | ||
509 | |||
510 | LPCWSTR pwcFile = const_cast<LPCWSTR> (UriFile(wzBaseUri)); | ||
511 | if (!pwcFile) | ||
512 | { | ||
513 | hr = E_INVALIDARG; | ||
514 | ExitOnFailure(hr, "Failed to get file from base URI: %ls", wzBaseUri); | ||
515 | } | ||
516 | |||
517 | hr = StrAllocString(ppwzResolvedUri, wzBaseUri, pwcFile - wzBaseUri); | ||
518 | ExitOnFailure(hr, "Failed to allocate string for resolved URI."); | ||
519 | |||
520 | hr = StrAllocConcat(ppwzResolvedUri, wzUri, 0); | ||
521 | ExitOnFailure(hr, "Failed to concat file to resolved URI."); | ||
522 | } | ||
523 | } | ||
524 | else | ||
525 | { | ||
526 | hr = StrAllocString(ppwzResolvedUri, wzUri, 0); | ||
527 | ExitOnFailure(hr, "Failed to copy resolved URI."); | ||
528 | } | ||
529 | |||
530 | if (pResolvedProtocol) | ||
531 | { | ||
532 | *pResolvedProtocol = protocol; | ||
533 | } | ||
534 | |||
535 | LExit: | ||
536 | #endif | ||
537 | return hr; | ||
538 | } | ||