ReactOS  0.4.13-dev-235-g7373cb3
url.c
Go to the documentation of this file.
1 /*
2  * Url functions
3  *
4  * Copyright 2000 Huw D M Davies for CodeWeavers.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 #include "wine/port.h"
23 #include <stdarg.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnls.h"
29 #include "winerror.h"
30 #include "wine/unicode.h"
31 #include "wininet.h"
32 #include "winreg.h"
33 #include "winternl.h"
34 #define NO_SHLWAPI_STREAM
35 #include "shlwapi.h"
36 #include "intshcut.h"
37 #include "wine/debug.h"
38 
42 
44 
45 static inline WCHAR *heap_strdupAtoW(const char *str)
46 {
47  LPWSTR ret = NULL;
48 
49  if(str) {
50  DWORD len;
51 
52  len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
53  ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
55  }
56 
57  return ret;
58 }
59 
60 /* The following schemes were identified in the native version of
61  * SHLWAPI.DLL version 5.50
62  */
63 static const struct {
66 } shlwapi_schemes[] = {
67  {URL_SCHEME_FTP, {'f','t','p',0}},
68  {URL_SCHEME_HTTP, {'h','t','t','p',0}},
69  {URL_SCHEME_GOPHER, {'g','o','p','h','e','r',0}},
70  {URL_SCHEME_MAILTO, {'m','a','i','l','t','o',0}},
71  {URL_SCHEME_NEWS, {'n','e','w','s',0}},
72  {URL_SCHEME_NNTP, {'n','n','t','p',0}},
73  {URL_SCHEME_TELNET, {'t','e','l','n','e','t',0}},
74  {URL_SCHEME_WAIS, {'w','a','i','s',0}},
75  {URL_SCHEME_FILE, {'f','i','l','e',0}},
76  {URL_SCHEME_MK, {'m','k',0}},
77  {URL_SCHEME_HTTPS, {'h','t','t','p','s',0}},
78  {URL_SCHEME_SHELL, {'s','h','e','l','l',0}},
79  {URL_SCHEME_SNEWS, {'s','n','e','w','s',0}},
80  {URL_SCHEME_LOCAL, {'l','o','c','a','l',0}},
81  {URL_SCHEME_JAVASCRIPT, {'j','a','v','a','s','c','r','i','p','t',0}},
82  {URL_SCHEME_VBSCRIPT, {'v','b','s','c','r','i','p','t',0}},
83  {URL_SCHEME_ABOUT, {'a','b','o','u','t',0}},
84  {URL_SCHEME_RES, {'r','e','s',0}},
85 };
86 
87 typedef struct {
88  LPCWSTR pScheme; /* [out] start of scheme */
89  DWORD szScheme; /* [out] size of scheme (until colon) */
90  LPCWSTR pUserName; /* [out] start of Username */
91  DWORD szUserName; /* [out] size of Username (until ":" or "@") */
92  LPCWSTR pPassword; /* [out] start of Password */
93  DWORD szPassword; /* [out] size of Password (until "@") */
94  LPCWSTR pHostName; /* [out] start of Hostname */
95  DWORD szHostName; /* [out] size of Hostname (until ":" or "/") */
96  LPCWSTR pPort; /* [out] start of Port */
97  DWORD szPort; /* [out] size of Port (until "/" or eos) */
98  LPCWSTR pQuery; /* [out] start of Query */
99  DWORD szQuery; /* [out] size of Query (until eos) */
101 
102 typedef enum {
108 
109 static const CHAR hexDigits[] = "0123456789ABCDEF";
110 
111 static const WCHAR fileW[] = {'f','i','l','e','\0'};
112 
113 static const unsigned char HashDataLookup[256] = {
114  0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77, 0x8A, 0xAA, 0x7D, 0x76, 0x1B,
115  0xE9, 0x8C, 0x33, 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44, 0x1E, 0x07,
116  0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41, 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94,
117  0xDF, 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C, 0x0C, 0xB5, 0x67, 0x46,
118  0x16, 0x3A, 0x4B, 0x4E, 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90, 0xB0,
119  0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53, 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6,
120  0x29, 0xFE, 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58, 0x23, 0xCE, 0x5F,
121  0x74, 0xFC, 0xC0, 0x36, 0xDD, 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
122  0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D, 0xA6, 0x50, 0x32, 0x22, 0xAF,
123  0xC3, 0x64, 0x63, 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD, 0x79, 0x40,
124  0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A, 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9,
125  0xC2, 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B, 0x4A, 0x3B, 0x89, 0xE4,
126  0x6C, 0xBF, 0xE8, 0x8B, 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C, 0xFB,
127  0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70, 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB,
128  0x0D, 0x20, 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B, 0xF9, 0xEC, 0x2D,
129  0xF4, 0x6F, 0xB6, 0x99, 0x88, 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
130  0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72, 0xA2, 0x35, 0xA0, 0xD7, 0xCD,
131  0xB4, 0x2F, 0x6D, 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34, 0x3F, 0x17,
132  0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB,
133  0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
134 
136 {
137  unsigned int i;
138 
139  for(i=0; i < sizeof(shlwapi_schemes)/sizeof(shlwapi_schemes[0]); i++) {
140  if(scheme_len == strlenW(shlwapi_schemes[i].scheme_name)
141  && !memicmpW(scheme, shlwapi_schemes[i].scheme_name, scheme_len))
143  }
144 
145  return URL_SCHEME_UNKNOWN;
146 }
147 
148 /*************************************************************************
149  * @ [SHLWAPI.1]
150  *
151  * Parse a Url into its constituent parts.
152  *
153  * PARAMS
154  * x [I] Url to parse
155  * y [O] Undocumented structure holding the parsed information
156  *
157  * RETURNS
158  * Success: S_OK. y contains the parsed Url details.
159  * Failure: An HRESULT error code.
160  */
162 {
164  const char *ptr = x;
165  int len;
166 
167  TRACE("%s %p\n", debugstr_a(x), y);
168 
169  if(y->cbSize != sizeof(*y))
170  return E_INVALIDARG;
171 
172  while(*ptr && (isalnum(*ptr) || *ptr == '-' || *ptr == '+' || *ptr == '.'))
173  ptr++;
174 
175  if (*ptr != ':' || ptr <= x+1) {
176  y->pszProtocol = NULL;
177  return URL_E_INVALID_SYNTAX;
178  }
179 
180  y->pszProtocol = x;
181  y->cchProtocol = ptr-x;
182  y->pszSuffix = ptr+1;
183  y->cchSuffix = strlen(y->pszSuffix);
184 
186  scheme, sizeof(scheme)/sizeof(WCHAR));
187  y->nScheme = get_scheme_code(scheme, len);
188 
189  return S_OK;
190 }
191 
192 /*************************************************************************
193  * @ [SHLWAPI.2]
194  *
195  * Unicode version of ParseURLA.
196  */
198 {
199  const WCHAR *ptr = x;
200 
201  TRACE("%s %p\n", debugstr_w(x), y);
202 
203  if(y->cbSize != sizeof(*y))
204  return E_INVALIDARG;
205 
206  while(*ptr && (isalnumW(*ptr) || *ptr == '-' || *ptr == '+' || *ptr == '.'))
207  ptr++;
208 
209  if (*ptr != ':' || ptr <= x+1) {
210  y->pszProtocol = NULL;
211  return URL_E_INVALID_SYNTAX;
212  }
213 
214  y->pszProtocol = x;
215  y->cchProtocol = ptr-x;
216  y->pszSuffix = ptr+1;
217  y->cchSuffix = strlenW(y->pszSuffix);
218  y->nScheme = get_scheme_code(x, ptr-x);
219 
220  return S_OK;
221 }
222 
223 /*************************************************************************
224  * UrlCanonicalizeA [SHLWAPI.@]
225  *
226  * Canonicalize a Url.
227  *
228  * PARAMS
229  * pszUrl [I] Url to cCanonicalize
230  * pszCanonicalized [O] Destination for converted Url.
231  * pcchCanonicalized [I/O] Length of pszUrl, destination for length of pszCanonicalized
232  * dwFlags [I] Flags controlling the conversion.
233  *
234  * RETURNS
235  * Success: S_OK. The pszCanonicalized contains the converted Url.
236  * Failure: E_POINTER, if *pcchCanonicalized is too small.
237  *
238  * MSDN incorrectly describes the flags for this function. They should be:
239  *| URL_DONT_ESCAPE_EXTRA_INFO 0x02000000
240  *| URL_ESCAPE_SPACES_ONLY 0x04000000
241  *| URL_ESCAPE_PERCENT 0x00001000
242  *| URL_ESCAPE_UNSAFE 0x10000000
243  *| URL_UNESCAPE 0x10000000
244  *| URL_DONT_SIMPLIFY 0x08000000
245  *| URL_ESCAPE_SEGMENT_ONLY 0x00002000
246  */
247 HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
248  LPDWORD pcchCanonicalized, DWORD dwFlags)
249 {
250  LPWSTR url, canonical;
251  HRESULT ret;
252 
253  TRACE("(%s, %p, %p, 0x%08x) *pcchCanonicalized: %d\n", debugstr_a(pszUrl), pszCanonicalized,
254  pcchCanonicalized, dwFlags, pcchCanonicalized ? *pcchCanonicalized : -1);
255 
256  if(!pszUrl || !pszCanonicalized || !pcchCanonicalized || !*pcchCanonicalized)
257  return E_INVALIDARG;
258 
259  url = heap_strdupAtoW(pszUrl);
260  canonical = HeapAlloc(GetProcessHeap(), 0, *pcchCanonicalized*sizeof(WCHAR));
261  if(!url || !canonical) {
262  HeapFree(GetProcessHeap(), 0, url);
263  HeapFree(GetProcessHeap(), 0, canonical);
264  return E_OUTOFMEMORY;
265  }
266 
267  ret = UrlCanonicalizeW(url, canonical, pcchCanonicalized, dwFlags);
268  if(ret == S_OK)
269  WideCharToMultiByte(CP_ACP, 0, canonical, -1, pszCanonicalized,
270  *pcchCanonicalized+1, NULL, NULL);
271 
272  HeapFree(GetProcessHeap(), 0, url);
273  HeapFree(GetProcessHeap(), 0, canonical);
274  return ret;
275 }
276 
277 /*************************************************************************
278  * UrlCanonicalizeW [SHLWAPI.@]
279  *
280  * See UrlCanonicalizeA.
281  */
282 HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
283  LPDWORD pcchCanonicalized, DWORD dwFlags)
284 {
285  HRESULT hr = S_OK;
286  DWORD EscapeFlags;
287  LPCWSTR wk1, root;
288  LPWSTR lpszUrlCpy, url, wk2, mp, mp2;
289  INT state;
290  DWORD nByteLen, nLen, nWkLen;
291  BOOL is_file_url;
292  WCHAR slash = '\0';
293 
294  static const WCHAR wszFile[] = {'f','i','l','e',':'};
295  static const WCHAR wszRes[] = {'r','e','s',':'};
296  static const WCHAR wszHttp[] = {'h','t','t','p',':'};
297  static const WCHAR wszLocalhost[] = {'l','o','c','a','l','h','o','s','t'};
298  static const WCHAR wszFilePrefix[] = {'f','i','l','e',':','/','/','/'};
299 
300  TRACE("(%s, %p, %p, 0x%08x) *pcchCanonicalized: %d\n", debugstr_w(pszUrl), pszCanonicalized,
301  pcchCanonicalized, dwFlags, pcchCanonicalized ? *pcchCanonicalized : -1);
302 
303  if(!pszUrl || !pszCanonicalized || !pcchCanonicalized || !*pcchCanonicalized)
304  return E_INVALIDARG;
305 
306  if(!*pszUrl) {
307  *pszCanonicalized = 0;
308  return S_OK;
309  }
310 
311  /* Remove '\t' characters from URL */
312  nByteLen = (strlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
313  url = HeapAlloc(GetProcessHeap(), 0, nByteLen);
314  if(!url)
315  return E_OUTOFMEMORY;
316 
317  wk1 = pszUrl;
318  wk2 = url;
319  do {
320  while(*wk1 == '\t')
321  wk1++;
322  *wk2++ = *wk1;
323  } while(*wk1++);
324 
325  /* Allocate memory for simplified URL (before escaping) */
326  nByteLen = (wk2-url)*sizeof(WCHAR);
327  lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0,
328  nByteLen+sizeof(wszFilePrefix)+sizeof(WCHAR));
329  if(!lpszUrlCpy) {
330  HeapFree(GetProcessHeap(), 0, url);
331  return E_OUTOFMEMORY;
332  }
333 
334  is_file_url = !strncmpW(wszFile, url, sizeof(wszFile)/sizeof(WCHAR));
335 
336  if ((nByteLen >= sizeof(wszHttp) &&
337  !memcmp(wszHttp, url, sizeof(wszHttp))) || is_file_url)
338  slash = '/';
339 
340  if((dwFlags & (URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY)) && is_file_url)
341  slash = '\\';
342 
343  if(nByteLen >= sizeof(wszRes) && !memcmp(wszRes, url, sizeof(wszRes))) {
345  slash = '\0';
346  }
347 
348  /*
349  * state =
350  * 0 initial 1,3
351  * 1 have 2[+] alnum 2,3
352  * 2 have scheme (found :) 4,6,3
353  * 3 failed (no location)
354  * 4 have // 5,3
355  * 5 have 1[+] alnum 6,3
356  * 6 have location (found /) save root location
357  */
358 
359  wk1 = url;
360  wk2 = lpszUrlCpy;
361  state = 0;
362 
363  if(url[1] == ':') { /* Assume path */
364  memcpy(wk2, wszFilePrefix, sizeof(wszFilePrefix));
365  wk2 += sizeof(wszFilePrefix)/sizeof(WCHAR);
367  {
368  slash = '\\';
369  --wk2;
370  }
371  else
373  state = 5;
374  is_file_url = TRUE;
375  } else if(url[0] == '/') {
376  state = 5;
377  is_file_url = TRUE;
378  }
379 
380  while (*wk1) {
381  switch (state) {
382  case 0:
383  if (!isalnumW(*wk1)) {state = 3; break;}
384  *wk2++ = *wk1++;
385  if (!isalnumW(*wk1)) {state = 3; break;}
386  *wk2++ = *wk1++;
387  state = 1;
388  break;
389  case 1:
390  *wk2++ = *wk1;
391  if (*wk1++ == ':') state = 2;
392  break;
393  case 2:
394  *wk2++ = *wk1++;
395  if (*wk1 != '/') {state = 6; break;}
396  *wk2++ = *wk1++;
397  if((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszLocalhost)
398  && is_file_url
399  && !memcmp(wszLocalhost, wk1, sizeof(wszLocalhost))){
400  wk1 += sizeof(wszLocalhost)/sizeof(WCHAR);
401  while(*wk1 == '\\' && (dwFlags & URL_FILE_USE_PATHURL))
402  wk1++;
403  }
404 
405  if(*wk1 == '/' && (dwFlags & URL_FILE_USE_PATHURL)){
406  wk1++;
407  }else if(is_file_url){
408  const WCHAR *body = wk1;
409 
410  while(*body == '/')
411  ++body;
412 
413  if(isalnumW(*body) && *(body+1) == ':'){
415  if(slash)
416  *wk2++ = slash;
417  else
418  *wk2++ = '/';
419  }
420  }else{
422  if(*wk1 == '/' && *(wk1+1) != '/'){
423  *wk2++ = '\\';
424  }else{
425  *wk2++ = '\\';
426  *wk2++ = '\\';
427  }
428  }else{
429  if(*wk1 == '/' && *(wk1+1) != '/'){
430  if(slash)
431  *wk2++ = slash;
432  else
433  *wk2++ = '/';
434  }
435  }
436  }
437  wk1 = body;
438  }
439  state = 4;
440  break;
441  case 3:
442  nWkLen = strlenW(wk1);
443  memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR));
444  mp = wk2;
445  wk1 += nWkLen;
446  wk2 += nWkLen;
447 
448  if(slash) {
449  while(mp < wk2) {
450  if(*mp == '/' || *mp == '\\')
451  *mp = slash;
452  mp++;
453  }
454  }
455  break;
456  case 4:
457  if (!isalnumW(*wk1) && (*wk1 != '-') && (*wk1 != '.') && (*wk1 != ':'))
458  {state = 3; break;}
459  while(isalnumW(*wk1) || (*wk1 == '-') || (*wk1 == '.') || (*wk1 == ':'))
460  *wk2++ = *wk1++;
461  state = 5;
462  if (!*wk1) {
463  if(slash)
464  *wk2++ = slash;
465  else
466  *wk2++ = '/';
467  }
468  break;
469  case 5:
470  if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;}
471  while(*wk1 == '/' || *wk1 == '\\') {
472  if(slash)
473  *wk2++ = slash;
474  else
475  *wk2++ = *wk1;
476  wk1++;
477  }
478  state = 6;
479  break;
480  case 6:
481  if(dwFlags & URL_DONT_SIMPLIFY) {
482  state = 3;
483  break;
484  }
485 
486  /* Now at root location, cannot back up any more. */
487  /* "root" will point at the '/' */
488 
489  root = wk2-1;
490  while (*wk1) {
491  mp = strchrW(wk1, '/');
492  mp2 = strchrW(wk1, '\\');
493  if(mp2 && (!mp || mp2 < mp))
494  mp = mp2;
495  if (!mp) {
496  nWkLen = strlenW(wk1);
497  memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR));
498  wk1 += nWkLen;
499  wk2 += nWkLen;
500  continue;
501  }
502  nLen = mp - wk1;
503  if(nLen) {
504  memcpy(wk2, wk1, nLen * sizeof(WCHAR));
505  wk2 += nLen;
506  wk1 += nLen;
507  }
508  if(slash)
509  *wk2++ = slash;
510  else
511  *wk2++ = *wk1;
512  wk1++;
513 
514  while (*wk1 == '.') {
515  TRACE("found '/.'\n");
516  if (wk1[1] == '/' || wk1[1] == '\\') {
517  /* case of /./ -> skip the ./ */
518  wk1 += 2;
519  }
520  else if (wk1[1] == '.' && (wk1[2] == '/'
521  || wk1[2] == '\\' || wk1[2] == '?'
522  || wk1[2] == '#' || !wk1[2])) {
523  /* case /../ -> need to backup wk2 */
524  TRACE("found '/../'\n");
525  *(wk2-1) = '\0'; /* set end of string */
526  mp = strrchrW(root, '/');
527  mp2 = strrchrW(root, '\\');
528  if(mp2 && (!mp || mp2 < mp))
529  mp = mp2;
530  if (mp && (mp >= root)) {
531  /* found valid backup point */
532  wk2 = mp + 1;
533  if(wk1[2] != '/' && wk1[2] != '\\')
534  wk1 += 2;
535  else
536  wk1 += 3;
537  }
538  else {
539  /* did not find point, restore '/' */
540  *(wk2-1) = slash;
541  break;
542  }
543  }
544  else
545  break;
546  }
547  }
548  *wk2 = '\0';
549  break;
550  default:
551  FIXME("how did we get here - state=%d\n", state);
552  HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
553  HeapFree(GetProcessHeap(), 0, url);
554  return E_INVALIDARG;
555  }
556  *wk2 = '\0';
557  TRACE("Simplified, orig <%s>, simple <%s>\n",
558  debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));
559  }
560  nLen = lstrlenW(lpszUrlCpy);
561  while ((nLen > 0) && ((lpszUrlCpy[nLen-1] <= ' ')))
562  lpszUrlCpy[--nLen]=0;
563 
564  if((dwFlags & URL_UNESCAPE) ||
565  ((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszFile)
566  && !memcmp(wszFile, url, sizeof(wszFile))))
567  UrlUnescapeW(lpszUrlCpy, NULL, &nLen, URL_UNESCAPE_INPLACE);
568 
569  if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE |
574  EscapeFlags &= ~URL_ESCAPE_UNSAFE;
575  hr = UrlEscapeW(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
576  EscapeFlags);
577  } else { /* No escaping needed, just copy the string */
578  nLen = lstrlenW(lpszUrlCpy);
579  if(nLen < *pcchCanonicalized)
580  memcpy(pszCanonicalized, lpszUrlCpy, (nLen + 1)*sizeof(WCHAR));
581  else {
582  hr = E_POINTER;
583  nLen++;
584  }
585  *pcchCanonicalized = nLen;
586  }
587 
588  HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
589  HeapFree(GetProcessHeap(), 0, url);
590 
591  if (hr == S_OK)
592  TRACE("result %s\n", debugstr_w(pszCanonicalized));
593 
594  return hr;
595 }
596 
597 /*************************************************************************
598  * UrlCombineA [SHLWAPI.@]
599  *
600  * Combine two Urls.
601  *
602  * PARAMS
603  * pszBase [I] Base Url
604  * pszRelative [I] Url to combine with pszBase
605  * pszCombined [O] Destination for combined Url
606  * pcchCombined [O] Destination for length of pszCombined
607  * dwFlags [I] URL_ flags from "shlwapi.h"
608  *
609  * RETURNS
610  * Success: S_OK. pszCombined contains the combined Url, pcchCombined
611  * contains its length.
612  * Failure: An HRESULT error code indicating the error.
613  */
614 HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative,
615  LPSTR pszCombined, LPDWORD pcchCombined,
616  DWORD dwFlags)
617 {
618  LPWSTR base, relative, combined;
619  DWORD ret, len, len2;
620 
621  TRACE("(base %s, Relative %s, Combine size %d, flags %08x) using W version\n",
622  debugstr_a(pszBase),debugstr_a(pszRelative),
623  pcchCombined?*pcchCombined:0,dwFlags);
624 
625  if(!pszBase || !pszRelative || !pcchCombined)
626  return E_INVALIDARG;
627 
629  (3*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
630  relative = base + INTERNET_MAX_URL_LENGTH;
631  combined = relative + INTERNET_MAX_URL_LENGTH;
632 
634  MultiByteToWideChar(CP_ACP, 0, pszRelative, -1, relative, INTERNET_MAX_URL_LENGTH);
635  len = *pcchCombined;
636 
637  ret = UrlCombineW(base, relative, pszCombined?combined:NULL, &len, dwFlags);
638  if (ret != S_OK) {
639  *pcchCombined = len;
641  return ret;
642  }
643 
644  len2 = WideCharToMultiByte(CP_ACP, 0, combined, len, NULL, 0, NULL, NULL);
645  if (len2 > *pcchCombined) {
646  *pcchCombined = len2;
648  return E_POINTER;
649  }
650  WideCharToMultiByte(CP_ACP, 0, combined, len+1, pszCombined, (*pcchCombined)+1,
651  NULL, NULL);
652  *pcchCombined = len2;
654  return S_OK;
655 }
656 
657 /*************************************************************************
658  * UrlCombineW [SHLWAPI.@]
659  *
660  * See UrlCombineA.
661  */
662 HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
663  LPWSTR pszCombined, LPDWORD pcchCombined,
664  DWORD dwFlags)
665 {
666  PARSEDURLW base, relative;
667  DWORD myflags, sizeloc = 0;
668  DWORD i, len, res1, res2, process_case = 0;
669  LPWSTR work, preliminary, mbase, mrelative;
670  static const WCHAR myfilestr[] = {'f','i','l','e',':','/','/','/','\0'};
671  static const WCHAR fragquerystr[] = {'#','?',0};
672  HRESULT ret;
673 
674  TRACE("(base %s, Relative %s, Combine size %d, flags %08x)\n",
675  debugstr_w(pszBase),debugstr_w(pszRelative),
676  pcchCombined?*pcchCombined:0,dwFlags);
677 
678  if(!pszBase || !pszRelative || !pcchCombined)
679  return E_INVALIDARG;
680 
681  base.cbSize = sizeof(base);
682  relative.cbSize = sizeof(relative);
683 
684  /* Get space for duplicates of the input and the output */
685  preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
686  sizeof(WCHAR));
687  mbase = preliminary + INTERNET_MAX_URL_LENGTH;
688  mrelative = mbase + INTERNET_MAX_URL_LENGTH;
689  *preliminary = '\0';
690 
691  /* Canonicalize the base input prior to looking for the scheme */
692  myflags = dwFlags & (URL_DONT_SIMPLIFY | URL_UNESCAPE);
694  UrlCanonicalizeW(pszBase, mbase, &len, myflags);
695 
696  /* Canonicalize the relative input prior to looking for the scheme */
698  UrlCanonicalizeW(pszRelative, mrelative, &len, myflags);
699 
700  /* See if the base has a scheme */
701  res1 = ParseURLW(mbase, &base);
702  if (res1) {
703  /* if pszBase has no scheme, then return pszRelative */
704  TRACE("no scheme detected in Base\n");
705  process_case = 1;
706  }
707  else do {
708  BOOL manual_search = FALSE;
709 
710  work = (LPWSTR)base.pszProtocol;
711  for(i=0; i<base.cchProtocol; i++)
712  work[i] = tolowerW(work[i]);
713 
714  /* mk is a special case */
715  if(base.nScheme == URL_SCHEME_MK) {
716  static const WCHAR wsz[] = {':',':',0};
717 
718  WCHAR *ptr = strstrW(base.pszSuffix, wsz);
719  if(ptr) {
720  int delta;
721 
722  ptr += 2;
723  delta = ptr-base.pszSuffix;
724  base.cchProtocol += delta;
725  base.pszSuffix += delta;
726  base.cchSuffix -= delta;
727  }
728  }else {
729  /* get size of location field (if it exists) */
730  work = (LPWSTR)base.pszSuffix;
731  sizeloc = 0;
732  if (*work++ == '/') {
733  if (*work++ == '/') {
734  /* At this point have start of location and
735  * it ends at next '/' or end of string.
736  */
737  while(*work && (*work != '/')) work++;
738  sizeloc = (DWORD)(work - base.pszSuffix);
739  }
740  }
741  }
742 
743  /* If there is a '?', then the remaining part can only contain a
744  * query string or fragment, so start looking for the last leaf
745  * from the '?'. Otherwise, if there is a '#' and the characters
746  * immediately preceding it are ".htm[l]", then begin looking for
747  * the last leaf starting from the '#'. Otherwise the '#' is not
748  * meaningful and just start looking from the end. */
749  if ((work = strpbrkW(base.pszSuffix + sizeloc, fragquerystr))) {
750  const WCHAR htmlW[] = {'.','h','t','m','l',0};
751  const int len_htmlW = 5;
752  const WCHAR htmW[] = {'.','h','t','m',0};
753  const int len_htmW = 4;
754 
755  if (*work == '?' || base.nScheme == URL_SCHEME_HTTP || base.nScheme == URL_SCHEME_HTTPS)
756  manual_search = TRUE;
757  else if (work - base.pszSuffix > len_htmW) {
758  work -= len_htmW;
759  if (strncmpiW(work, htmW, len_htmW) == 0)
760  manual_search = TRUE;
761  work += len_htmW;
762  }
763 
764  if (!manual_search &&
765  work - base.pszSuffix > len_htmlW) {
766  work -= len_htmlW;
767  if (strncmpiW(work, htmlW, len_htmlW) == 0)
768  manual_search = TRUE;
769  work += len_htmlW;
770  }
771  }
772 
773  if (manual_search) {
774  /* search backwards starting from the current position */
775  while (*work != '/' && work > base.pszSuffix + sizeloc)
776  --work;
777  base.cchSuffix = work - base.pszSuffix + 1;
778  }else {
779  /* search backwards starting from the end of the string */
780  work = strrchrW((base.pszSuffix+sizeloc), '/');
781  if (work) {
782  len = (DWORD)(work - base.pszSuffix + 1);
783  base.cchSuffix = len;
784  }else
785  base.cchSuffix = sizeloc;
786  }
787 
788  /*
789  * At this point:
790  * .pszSuffix points to location (starting with '//')
791  * .cchSuffix length of location (above) and rest less the last
792  * leaf (if any)
793  * sizeloc length of location (above) up to but not including
794  * the last '/'
795  */
796 
797  res2 = ParseURLW(mrelative, &relative);
798  if (res2) {
799  /* no scheme in pszRelative */
800  TRACE("no scheme detected in Relative\n");
801  relative.pszSuffix = mrelative; /* case 3,4,5 depends on this */
802  relative.cchSuffix = strlenW(mrelative);
803  if (*pszRelative == ':') {
804  /* case that is either left alone or uses pszBase */
806  process_case = 5;
807  break;
808  }
809  process_case = 1;
810  break;
811  }
812  if (isalnumW(*mrelative) && (*(mrelative + 1) == ':')) {
813  /* case that becomes "file:///" */
814  strcpyW(preliminary, myfilestr);
815  process_case = 1;
816  break;
817  }
818  if ((*mrelative == '/') && (*(mrelative+1) == '/')) {
819  /* pszRelative has location and rest */
820  process_case = 3;
821  break;
822  }
823  if (*mrelative == '/') {
824  /* case where pszRelative is root to location */
825  process_case = 4;
826  break;
827  }
828  if (*mrelative == '#') {
829  if(!(work = strchrW(base.pszSuffix+base.cchSuffix, '#')))
830  work = (LPWSTR)base.pszSuffix + strlenW(base.pszSuffix);
831 
832  memcpy(preliminary, base.pszProtocol, (work-base.pszProtocol)*sizeof(WCHAR));
833  preliminary[work-base.pszProtocol] = '\0';
834  process_case = 1;
835  break;
836  }
837  process_case = (*base.pszSuffix == '/' || base.nScheme == URL_SCHEME_MK) ? 5 : 3;
838  break;
839  }else {
840  work = (LPWSTR)relative.pszProtocol;
841  for(i=0; i<relative.cchProtocol; i++)
842  work[i] = tolowerW(work[i]);
843  }
844 
845  /* handle cases where pszRelative has scheme */
846  if ((base.cchProtocol == relative.cchProtocol) &&
847  (strncmpW(base.pszProtocol, relative.pszProtocol, base.cchProtocol) == 0)) {
848 
849  /* since the schemes are the same */
850  if ((*relative.pszSuffix == '/') && (*(relative.pszSuffix+1) == '/')) {
851  /* case where pszRelative replaces location and following */
852  process_case = 3;
853  break;
854  }
855  if (*relative.pszSuffix == '/') {
856  /* case where pszRelative is root to location */
857  process_case = 4;
858  break;
859  }
860  /* replace either just location if base's location starts with a
861  * slash or otherwise everything */
862  process_case = (*base.pszSuffix == '/') ? 5 : 1;
863  break;
864  }
865  if ((*relative.pszSuffix == '/') && (*(relative.pszSuffix+1) == '/')) {
866  /* case where pszRelative replaces scheme, location,
867  * and following and handles PLUGGABLE
868  */
869  process_case = 2;
870  break;
871  }
872  process_case = 1;
873  break;
874  } while(FALSE); /* a little trick to allow easy exit from nested if's */
875 
876  ret = S_OK;
877  switch (process_case) {
878 
879  case 1: /*
880  * Return pszRelative appended to what ever is in pszCombined,
881  * (which may the string "file:///"
882  */
883  strcatW(preliminary, mrelative);
884  break;
885 
886  case 2: /* case where pszRelative replaces scheme, and location */
887  strcpyW(preliminary, mrelative);
888  break;
889 
890  case 3: /*
891  * Return the pszBase scheme with pszRelative. Basically
892  * keeps the scheme and replaces the domain and following.
893  */
894  memcpy(preliminary, base.pszProtocol, (base.cchProtocol + 1)*sizeof(WCHAR));
895  work = preliminary + base.cchProtocol + 1;
896  strcpyW(work, relative.pszSuffix);
897  break;
898 
899  case 4: /*
900  * Return the pszBase scheme and location but everything
901  * after the location is pszRelative. (Replace document
902  * from root on.)
903  */
904  memcpy(preliminary, base.pszProtocol, (base.cchProtocol+1+sizeloc)*sizeof(WCHAR));
905  work = preliminary + base.cchProtocol + 1 + sizeloc;
907  *(work++) = '/';
908  strcpyW(work, relative.pszSuffix);
909  break;
910 
911  case 5: /*
912  * Return the pszBase without its document (if any) and
913  * append pszRelative after its scheme.
914  */
915  memcpy(preliminary, base.pszProtocol,
916  (base.cchProtocol+1+base.cchSuffix)*sizeof(WCHAR));
917  work = preliminary + base.cchProtocol+1+base.cchSuffix - 1;
918  if (*work++ != '/')
919  *(work++) = '/';
920  if (relative.pszSuffix[0] == '.' && relative.pszSuffix[1] == 0)
921  *work = 0;
922  else
923  strcpyW(work, relative.pszSuffix);
924  break;
925 
926  default:
927  FIXME("How did we get here????? process_case=%d\n", process_case);
928  ret = E_INVALIDARG;
929  }
930 
931  if (ret == S_OK) {
932  /* Reuse mrelative as temp storage as it's already allocated and not needed anymore */
933  if(*pcchCombined == 0)
934  *pcchCombined = 1;
935  ret = UrlCanonicalizeW(preliminary, mrelative, pcchCombined, (dwFlags & ~URL_FILE_USE_PATHURL));
936  if(SUCCEEDED(ret) && pszCombined) {
937  lstrcpyW(pszCombined, mrelative);
938  }
939  TRACE("return-%d len=%d, %s\n",
940  process_case, *pcchCombined, debugstr_w(pszCombined));
941  }
942  HeapFree(GetProcessHeap(), 0, preliminary);
943  return ret;
944 }
945 
946 /*************************************************************************
947  * UrlEscapeA [SHLWAPI.@]
948  */
949 
951  LPCSTR pszUrl,
952  LPSTR pszEscaped,
953  LPDWORD pcchEscaped,
954  DWORD dwFlags)
955 {
957  WCHAR *escapedW = bufW;
958  UNICODE_STRING urlW;
959  HRESULT ret;
960  DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
961 
962  if (!pszEscaped || !pcchEscaped || !*pcchEscaped)
963  return E_INVALIDARG;
964 
965  if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
966  return E_INVALIDARG;
968  RtlFreeUnicodeString(&urlW);
969  return E_NOTIMPL;
970  }
971  if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
972  escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
973  ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
974  }
975  if(ret == S_OK) {
976  RtlUnicodeToMultiByteSize(&lenA, escapedW, lenW * sizeof(WCHAR));
977  if(*pcchEscaped > lenA) {
978  RtlUnicodeToMultiByteN(pszEscaped, *pcchEscaped - 1, &lenA, escapedW, lenW * sizeof(WCHAR));
979  pszEscaped[lenA] = 0;
980  *pcchEscaped = lenA;
981  } else {
982  *pcchEscaped = lenA + 1;
983  ret = E_POINTER;
984  }
985  }
986  if(escapedW != bufW) HeapFree(GetProcessHeap(), 0, escapedW);
987  RtlFreeUnicodeString(&urlW);
988  return ret;
989 }
990 
991 #define WINE_URL_BASH_AS_SLASH 0x01
992 #define WINE_URL_COLLAPSE_SLASHES 0x02
993 #define WINE_URL_ESCAPE_SLASH 0x04
994 #define WINE_URL_ESCAPE_HASH 0x08
995 #define WINE_URL_ESCAPE_QUESTION 0x10
996 #define WINE_URL_STOP_ON_HASH 0x20
997 #define WINE_URL_STOP_ON_QUESTION 0x40
998 
999 static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD flags, DWORD int_flags)
1000 {
1002  return ch == ' ';
1003 
1004  if ((flags & URL_ESCAPE_PERCENT) && (ch == '%'))
1005  return TRUE;
1006 
1007  if ((flags & URL_ESCAPE_AS_UTF8) && (ch >= 0x80))
1008  return TRUE;
1009 
1010  if (ch <= 31 || (ch >= 127 && ch <= 255) )
1011  return TRUE;
1012 
1013  if (isalnumW(ch))
1014  return FALSE;
1015 
1016  switch (ch) {
1017  case ' ':
1018  case '<':
1019  case '>':
1020  case '\"':
1021  case '{':
1022  case '}':
1023  case '|':
1024  case '\\':
1025  case '^':
1026  case ']':
1027  case '[':
1028  case '`':
1029  case '&':
1030  return TRUE;
1031  case '/':
1032  return !!(int_flags & WINE_URL_ESCAPE_SLASH);
1033  case '?':
1034  return !!(int_flags & WINE_URL_ESCAPE_QUESTION);
1035  case '#':
1036  return !!(int_flags & WINE_URL_ESCAPE_HASH);
1037  default:
1038  return FALSE;
1039  }
1040 }
1041 
1042 
1043 /*************************************************************************
1044  * UrlEscapeW [SHLWAPI.@]
1045  *
1046  * Converts unsafe characters in a Url into escape sequences.
1047  *
1048  * PARAMS
1049  * pszUrl [I] Url to modify
1050  * pszEscaped [O] Destination for modified Url
1051  * pcchEscaped [I/O] Length of pszUrl, destination for length of pszEscaped
1052  * dwFlags [I] URL_ flags from "shlwapi.h"
1053  *
1054  * RETURNS
1055  * Success: S_OK. pszEscaped contains the escaped Url, pcchEscaped
1056  * contains its length.
1057  * Failure: E_POINTER, if pszEscaped is not large enough. In this case
1058  * pcchEscaped is set to the required length.
1059  *
1060  * Converts unsafe characters into their escape sequences.
1061  *
1062  * NOTES
1063  * - By default this function stops converting at the first '?' or
1064  * '#' character.
1065  * - If dwFlags contains URL_ESCAPE_SPACES_ONLY then only spaces are
1066  * converted, but the conversion continues past a '?' or '#'.
1067  * - Note that this function did not work well (or at all) in shlwapi version 4.
1068  *
1069  * BUGS
1070  * Only the following flags are implemented:
1071  *| URL_ESCAPE_SPACES_ONLY
1072  *| URL_DONT_ESCAPE_EXTRA_INFO
1073  *| URL_ESCAPE_SEGMENT_ONLY
1074  *| URL_ESCAPE_PERCENT
1075  */
1077  LPCWSTR pszUrl,
1078  LPWSTR pszEscaped,
1079  LPDWORD pcchEscaped,
1080  DWORD dwFlags)
1081 {
1082  LPCWSTR src;
1083  DWORD needed = 0, ret;
1084  BOOL stop_escaping = FALSE;
1085  WCHAR next[12], *dst, *dst_ptr;
1086  INT i, len;
1087  PARSEDURLW parsed_url;
1088  DWORD int_flags;
1089  DWORD slashes = 0;
1090  static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
1091 
1092  TRACE("(%p(%s) %p %p 0x%08x)\n", pszUrl, debugstr_w(pszUrl),
1093  pszEscaped, pcchEscaped, dwFlags);
1094 
1095  if(!pszUrl || !pcchEscaped || !pszEscaped || *pcchEscaped == 0)
1096  return E_INVALIDARG;
1097 
1103  FIXME("Unimplemented flags: %08x\n", dwFlags);
1104 
1105  dst_ptr = dst = HeapAlloc(GetProcessHeap(), 0, *pcchEscaped*sizeof(WCHAR));
1106  if(!dst_ptr)
1107  return E_OUTOFMEMORY;
1108 
1109  /* fix up flags */
1111  /* if SPACES_ONLY specified, reset the other controls */
1115 
1116  else
1117  /* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
1119 
1120 
1121  int_flags = 0;
1124  } else {
1125  parsed_url.cbSize = sizeof(parsed_url);
1126  if(ParseURLW(pszUrl, &parsed_url) != S_OK)
1127  parsed_url.nScheme = URL_SCHEME_INVALID;
1128 
1129  TRACE("scheme = %d (%s)\n", parsed_url.nScheme, debugstr_wn(parsed_url.pszProtocol, parsed_url.cchProtocol));
1130 
1133 
1134  switch(parsed_url.nScheme) {
1135  case URL_SCHEME_FILE:
1137  int_flags &= ~WINE_URL_STOP_ON_HASH;
1138  break;
1139 
1140  case URL_SCHEME_HTTP:
1141  case URL_SCHEME_HTTPS:
1142  int_flags |= WINE_URL_BASH_AS_SLASH;
1143  if(parsed_url.pszSuffix[0] != '/' && parsed_url.pszSuffix[0] != '\\')
1144  int_flags |= WINE_URL_ESCAPE_SLASH;
1145  break;
1146 
1147  case URL_SCHEME_MAILTO:
1150  break;
1151 
1152  case URL_SCHEME_INVALID:
1153  break;
1154 
1155  case URL_SCHEME_FTP:
1156  default:
1157  if(parsed_url.pszSuffix[0] != '/')
1158  int_flags |= WINE_URL_ESCAPE_SLASH;
1159  break;
1160  }
1161  }
1162 
1163  for(src = pszUrl; *src; ) {
1164  WCHAR cur = *src;
1165  len = 0;
1166 
1167  if((int_flags & WINE_URL_COLLAPSE_SLASHES) && src == pszUrl + parsed_url.cchProtocol + 1) {
1168  int localhost_len = sizeof(localhost)/sizeof(WCHAR) - 1;
1169  while(cur == '/' || cur == '\\') {
1170  slashes++;
1171  cur = *++src;
1172  }
1173  if(slashes == 2 && !strncmpiW(src, localhost, localhost_len)) { /* file://localhost/ -> file:/// */
1174  if(*(src + localhost_len) == '/' || *(src + localhost_len) == '\\')
1175  src += localhost_len + 1;
1176  slashes = 3;
1177  }
1178 
1179  switch(slashes) {
1180  case 1:
1181  case 3:
1182  next[0] = next[1] = next[2] = '/';
1183  len = 3;
1184  break;
1185  case 0:
1186  len = 0;
1187  break;
1188  default:
1189  next[0] = next[1] = '/';
1190  len = 2;
1191  break;
1192  }
1193  }
1194  if(len == 0) {
1195 
1196  if(cur == '#' && (int_flags & WINE_URL_STOP_ON_HASH))
1197  stop_escaping = TRUE;
1198 
1199  if(cur == '?' && (int_flags & WINE_URL_STOP_ON_QUESTION))
1200  stop_escaping = TRUE;
1201 
1202  if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';
1203 
1204  if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
1205  if(dwFlags & URL_ESCAPE_AS_UTF8) {
1206  char utf[16];
1207 
1208  if ((cur >= 0xd800 && cur <= 0xdfff) &&
1209  (src[1] >= 0xdc00 && src[1] <= 0xdfff))
1210  {
1211 #ifdef __REACTOS__
1212  len = WideCharToMultiByte( CP_UTF8, 0, src, 2,
1213  utf, sizeof(utf), NULL, NULL );
1214 #else
1216  utf, sizeof(utf), NULL, NULL );
1217 #endif
1218  src++;
1219  }
1220  else
1221 #ifdef __REACTOS__
1222  len = WideCharToMultiByte( CP_UTF8, 0, &cur, 1,
1223  utf, sizeof(utf), NULL, NULL );
1224 #else
1226  utf, sizeof(utf), NULL, NULL );
1227 #endif
1228 
1229  if (!len) {
1230  utf[0] = 0xef;
1231  utf[1] = 0xbf;
1232  utf[2] = 0xbd;
1233  len = 3;
1234  }
1235 
1236  for(i = 0; i < len; i++) {
1237  next[i*3+0] = '%';
1238  next[i*3+1] = hexDigits[(utf[i] >> 4) & 0xf];
1239  next[i*3+2] = hexDigits[utf[i] & 0xf];
1240  }
1241  len *= 3;
1242  } else {
1243  next[0] = '%';
1244  next[1] = hexDigits[(cur >> 4) & 0xf];
1245  next[2] = hexDigits[cur & 0xf];
1246  len = 3;
1247  }
1248  } else {
1249  next[0] = cur;
1250  len = 1;
1251  }
1252  src++;
1253  }
1254 
1255  if(needed + len <= *pcchEscaped) {
1256  memcpy(dst, next, len*sizeof(WCHAR));
1257  dst += len;
1258  }
1259  needed += len;
1260  }
1261 
1262  if(needed < *pcchEscaped) {
1263  *dst = '\0';
1264  memcpy(pszEscaped, dst_ptr, (needed+1)*sizeof(WCHAR));
1265 
1266  ret = S_OK;
1267  } else {
1268  needed++; /* add one for the '\0' */
1269  ret = E_POINTER;
1270  }
1271  *pcchEscaped = needed;
1272 
1273  HeapFree(GetProcessHeap(), 0, dst_ptr);
1274  return ret;
1275 }
1276 
1277 
1278 /*************************************************************************
1279  * UrlUnescapeA [SHLWAPI.@]
1280  *
1281  * Converts Url escape sequences back to ordinary characters.
1282  *
1283  * PARAMS
1284  * pszUrl [I/O] Url to convert
1285  * pszUnescaped [O] Destination for converted Url
1286  * pcchUnescaped [I/O] Size of output string
1287  * dwFlags [I] URL_ESCAPE_ Flags from "shlwapi.h"
1288  *
1289  * RETURNS
1290  * Success: S_OK. The converted value is in pszUnescaped, or in pszUrl if
1291  * dwFlags includes URL_ESCAPE_INPLACE.
1292  * Failure: E_POINTER if the converted Url is bigger than pcchUnescaped. In
1293  * this case pcchUnescaped is set to the size required.
1294  * NOTES
1295  * If dwFlags includes URL_DONT_ESCAPE_EXTRA_INFO, the conversion stops at
1296  * the first occurrence of either a '?' or '#' character.
1297  */
1299  LPSTR pszUrl,
1300  LPSTR pszUnescaped,
1301  LPDWORD pcchUnescaped,
1302  DWORD dwFlags)
1303 {
1304  char *dst, next;
1305  LPCSTR src;
1306  HRESULT ret;
1307  DWORD needed;
1308  BOOL stop_unescaping = FALSE;
1309 
1310  TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_a(pszUrl), pszUnescaped,
1311  pcchUnescaped, dwFlags);
1312 
1313  if (!pszUrl) return E_INVALIDARG;
1314 
1316  dst = pszUrl;
1317  else
1318  {
1319  if (!pszUnescaped || !pcchUnescaped) return E_INVALIDARG;
1320  dst = pszUnescaped;
1321  }
1322 
1323  for(src = pszUrl, needed = 0; *src; src++, needed++) {
1325  (*src == '#' || *src == '?')) {
1326  stop_unescaping = TRUE;
1327  next = *src;
1328  } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
1329  && stop_unescaping == FALSE) {
1330  INT ih;
1331  char buf[3];
1332  memcpy(buf, src + 1, 2);
1333  buf[2] = '\0';
1334  ih = strtol(buf, NULL, 16);
1335  next = (CHAR) ih;
1336  src += 2; /* Advance to end of escape */
1337  } else
1338  next = *src;
1339 
1340  if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
1341  *dst++ = next;
1342  }
1343 
1344  if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
1345  *dst = '\0';
1346  ret = S_OK;
1347  } else {
1348  needed++; /* add one for the '\0' */
1349  ret = E_POINTER;
1350  }
1351  if(!(dwFlags & URL_UNESCAPE_INPLACE))
1352  *pcchUnescaped = needed;
1353 
1354  if (ret == S_OK) {
1355  TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
1356  debugstr_a(pszUrl) : debugstr_a(pszUnescaped));
1357  }
1358 
1359  return ret;
1360 }
1361 
1362 /*************************************************************************
1363  * UrlUnescapeW [SHLWAPI.@]
1364  *
1365  * See UrlUnescapeA.
1366  */
1368  LPWSTR pszUrl,
1369  LPWSTR pszUnescaped,
1370  LPDWORD pcchUnescaped,
1371  DWORD dwFlags)
1372 {
1373  WCHAR *dst, next;
1374  LPCWSTR src;
1375  HRESULT ret;
1376  DWORD needed;
1377  BOOL stop_unescaping = FALSE;
1378 
1379  TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_w(pszUrl), pszUnescaped,
1380  pcchUnescaped, dwFlags);
1381 
1382  if(!pszUrl) return E_INVALIDARG;
1383 
1385  dst = pszUrl;
1386  else
1387  {
1388  if (!pszUnescaped || !pcchUnescaped) return E_INVALIDARG;
1389  dst = pszUnescaped;
1390  }
1391 
1392  for(src = pszUrl, needed = 0; *src; src++, needed++) {
1394  (*src == '#' || *src == '?')) {
1395  stop_unescaping = TRUE;
1396  next = *src;
1397  } else if(*src == '%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2))
1398  && stop_unescaping == FALSE) {
1399  INT ih;
1400  WCHAR buf[5] = {'0','x',0};
1401  memcpy(buf + 2, src + 1, 2*sizeof(WCHAR));
1402  buf[4] = 0;
1404  next = (WCHAR) ih;
1405  src += 2; /* Advance to end of escape */
1406  } else
1407  next = *src;
1408 
1409  if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
1410  *dst++ = next;
1411  }
1412 
1413  if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
1414  *dst = '\0';
1415  ret = S_OK;
1416  } else {
1417  needed++; /* add one for the '\0' */
1418  ret = E_POINTER;
1419  }
1420  if(!(dwFlags & URL_UNESCAPE_INPLACE))
1421  *pcchUnescaped = needed;
1422 
1423  if (ret == S_OK) {
1424  TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
1425  debugstr_w(pszUrl) : debugstr_w(pszUnescaped));
1426  }
1427 
1428  return ret;
1429 }
1430 
1431 /*************************************************************************
1432  * UrlGetLocationA [SHLWAPI.@]
1433  *
1434  * Get the location from a Url.
1435  *
1436  * PARAMS
1437  * pszUrl [I] Url to get the location from
1438  *
1439  * RETURNS
1440  * A pointer to the start of the location in pszUrl, or NULL if there is
1441  * no location.
1442  *
1443  * NOTES
1444  * - MSDN erroneously states that "The location is the segment of the Url
1445  * starting with a '?' or '#' character". Neither V4 nor V5 of shlwapi.dll
1446  * stop at '?' and always return a NULL in this case.
1447  * - MSDN also erroneously states that "If a file URL has a query string,
1448  * the returned string is the query string". In all tested cases, if the
1449  * Url starts with "fi" then a NULL is returned. V5 gives the following results:
1450  *| Result Url
1451  *| ------ ---
1452  *| NULL file://aa/b/cd#hohoh
1453  *| #hohoh http://aa/b/cd#hohoh
1454  *| NULL fi://aa/b/cd#hohoh
1455  *| #hohoh ff://aa/b/cd#hohoh
1456  */
1458  LPCSTR pszUrl)
1459 {
1460  PARSEDURLA base;
1461  DWORD res1;
1462 
1463  base.cbSize = sizeof(base);
1464  res1 = ParseURLA(pszUrl, &base);
1465  if (res1) return NULL; /* invalid scheme */
1466 
1467  /* if scheme is file: then never return pointer */
1468  if (strncmp(base.pszProtocol, "file", min(4,base.cchProtocol)) == 0) return NULL;
1469 
1470  /* Look for '#' and return its addr */
1471  return strchr(base.pszSuffix, '#');
1472 }
1473 
1474 /*************************************************************************
1475  * UrlGetLocationW [SHLWAPI.@]
1476  *
1477  * See UrlGetLocationA.
1478  */
1480  LPCWSTR pszUrl)
1481 {
1482  PARSEDURLW base;
1483  DWORD res1;
1484 
1485  base.cbSize = sizeof(base);
1486  res1 = ParseURLW(pszUrl, &base);
1487  if (res1) return NULL; /* invalid scheme */
1488 
1489  /* if scheme is file: then never return pointer */
1490  if (strncmpW(base.pszProtocol, fileW, min(4,base.cchProtocol)) == 0) return NULL;
1491 
1492  /* Look for '#' and return its addr */
1493  return strchrW(base.pszSuffix, '#');
1494 }
1495 
1496 /*************************************************************************
1497  * UrlCompareA [SHLWAPI.@]
1498  *
1499  * Compare two Urls.
1500  *
1501  * PARAMS
1502  * pszUrl1 [I] First Url to compare
1503  * pszUrl2 [I] Url to compare to pszUrl1
1504  * fIgnoreSlash [I] TRUE = compare only up to a final slash
1505  *
1506  * RETURNS
1507  * less than zero, zero, or greater than zero indicating pszUrl2 is greater
1508  * than, equal to, or less than pszUrl1 respectively.
1509  */
1511  LPCSTR pszUrl1,
1512  LPCSTR pszUrl2,
1513  BOOL fIgnoreSlash)
1514 {
1515  INT ret, len, len1, len2;
1516 
1517  if (!fIgnoreSlash)
1518  return strcmp(pszUrl1, pszUrl2);
1519  len1 = strlen(pszUrl1);
1520  if (pszUrl1[len1-1] == '/') len1--;
1521  len2 = strlen(pszUrl2);
1522  if (pszUrl2[len2-1] == '/') len2--;
1523  if (len1 == len2)
1524  return strncmp(pszUrl1, pszUrl2, len1);
1525  len = min(len1, len2);
1526  ret = strncmp(pszUrl1, pszUrl2, len);
1527  if (ret) return ret;
1528  if (len1 > len2) return 1;
1529  return -1;
1530 }
1531 
1532 /*************************************************************************
1533  * UrlCompareW [SHLWAPI.@]
1534  *
1535  * See UrlCompareA.
1536  */
1538  LPCWSTR pszUrl1,
1539  LPCWSTR pszUrl2,
1540  BOOL fIgnoreSlash)
1541 {
1542  INT ret;
1543  size_t len, len1, len2;
1544 
1545  if (!fIgnoreSlash)
1546  return strcmpW(pszUrl1, pszUrl2);
1547  len1 = strlenW(pszUrl1);
1548  if (pszUrl1[len1-1] == '/') len1--;
1549  len2 = strlenW(pszUrl2);
1550  if (pszUrl2[len2-1] == '/') len2--;
1551  if (len1 == len2)
1552  return strncmpW(pszUrl1, pszUrl2, len1);
1553  len = min(len1, len2);
1554  ret = strncmpW(pszUrl1, pszUrl2, len);
1555  if (ret) return ret;
1556  if (len1 > len2) return 1;
1557  return -1;
1558 }
1559 
1560 /*************************************************************************
1561  * HashData [SHLWAPI.@]
1562  *
1563  * Hash an input block into a variable sized digest.
1564  *
1565  * PARAMS
1566  * lpSrc [I] Input block
1567  * nSrcLen [I] Length of lpSrc
1568  * lpDest [I] Output for hash digest
1569  * nDestLen [I] Length of lpDest
1570  *
1571  * RETURNS
1572  * Success: TRUE. lpDest is filled with the computed hash value.
1573  * Failure: FALSE, if any argument is invalid.
1574  */
1575 HRESULT WINAPI HashData(const unsigned char *lpSrc, DWORD nSrcLen,
1576  unsigned char *lpDest, DWORD nDestLen)
1577 {
1578  INT srcCount = nSrcLen - 1, destCount = nDestLen - 1;
1579 
1580  if (!lpSrc || !lpDest)
1581  return E_INVALIDARG;
1582 
1583  while (destCount >= 0)
1584  {
1585  lpDest[destCount] = (destCount & 0xff);
1586  destCount--;
1587  }
1588 
1589  while (srcCount >= 0)
1590  {
1591  destCount = nDestLen - 1;
1592  while (destCount >= 0)
1593  {
1594  lpDest[destCount] = HashDataLookup[lpSrc[srcCount] ^ lpDest[destCount]];
1595  destCount--;
1596  }
1597  srcCount--;
1598  }
1599  return S_OK;
1600 }
1601 
1602 /*************************************************************************
1603  * UrlHashA [SHLWAPI.@]
1604  *
1605  * Produce a Hash from a Url.
1606  *
1607  * PARAMS
1608  * pszUrl [I] Url to hash
1609  * lpDest [O] Destinationh for hash
1610  * nDestLen [I] Length of lpDest
1611  *
1612  * RETURNS
1613  * Success: S_OK. lpDest is filled with the computed hash value.
1614  * Failure: E_INVALIDARG, if any argument is invalid.
1615  */
1616 HRESULT WINAPI UrlHashA(LPCSTR pszUrl, unsigned char *lpDest, DWORD nDestLen)
1617 {
1618  if (IsBadStringPtrA(pszUrl, -1) || IsBadWritePtr(lpDest, nDestLen))
1619  return E_INVALIDARG;
1620 
1621  HashData((const BYTE*)pszUrl, (int)strlen(pszUrl), lpDest, nDestLen);
1622  return S_OK;
1623 }
1624 
1625 /*************************************************************************
1626  * UrlHashW [SHLWAPI.@]
1627  *
1628  * See UrlHashA.
1629  */
1630 HRESULT WINAPI UrlHashW(LPCWSTR pszUrl, unsigned char *lpDest, DWORD nDestLen)
1631 {
1632  char szUrl[MAX_PATH];
1633 
1634  TRACE("(%s,%p,%d)\n",debugstr_w(pszUrl), lpDest, nDestLen);
1635 
1636  if (IsBadStringPtrW(pszUrl, -1) || IsBadWritePtr(lpDest, nDestLen))
1637  return E_INVALIDARG;
1638 
1639  /* Win32 hashes the data as an ASCII string, presumably so that both A+W
1640  * return the same digests for the same URL.
1641  */
1642  WideCharToMultiByte(CP_ACP, 0, pszUrl, -1, szUrl, MAX_PATH, NULL, NULL);
1643  HashData((const BYTE*)szUrl, (int)strlen(szUrl), lpDest, nDestLen);
1644  return S_OK;
1645 }
1646 
1647 /*************************************************************************
1648  * UrlApplySchemeA [SHLWAPI.@]
1649  *
1650  * Apply a scheme to a Url.
1651  *
1652  * PARAMS
1653  * pszIn [I] Url to apply scheme to
1654  * pszOut [O] Destination for modified Url
1655  * pcchOut [I/O] Length of pszOut/destination for length of pszOut
1656  * dwFlags [I] URL_ flags from "shlwapi.h"
1657  *
1658  * RETURNS
1659  * Success: S_OK: pszOut contains the modified Url, pcchOut contains its length.
1660  * Failure: An HRESULT error code describing the error.
1661  */
1663 {
1664  LPWSTR in, out;
1665  HRESULT ret;
1666  DWORD len;
1667 
1668  TRACE("(%s, %p, %p:out size %d, 0x%08x)\n", debugstr_a(pszIn),
1669  pszOut, pcchOut, pcchOut ? *pcchOut : 0, dwFlags);
1670 
1671  if (!pszIn || !pszOut || !pcchOut) return E_INVALIDARG;
1672 
1673  in = HeapAlloc(GetProcessHeap(), 0,
1674  (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
1676 
1679 
1681  if (ret != S_OK) {
1682  HeapFree(GetProcessHeap(), 0, in);
1683  return ret;
1684  }
1685 
1686  len = WideCharToMultiByte(CP_ACP, 0, out, -1, NULL, 0, NULL, NULL);
1687  if (len > *pcchOut) {
1688  ret = E_POINTER;
1689  goto cleanup;
1690  }
1691 
1692  WideCharToMultiByte(CP_ACP, 0, out, -1, pszOut, *pcchOut, NULL, NULL);
1693  len--;
1694 
1695 cleanup:
1696  *pcchOut = len;
1697  HeapFree(GetProcessHeap(), 0, in);
1698  return ret;
1699 }
1700 
1701 static HRESULT URL_GuessScheme(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
1702 {
1703  HKEY newkey;
1704  BOOL j;
1705  INT index;
1706  DWORD value_len, data_len, dwType, i;
1707  WCHAR reg_path[MAX_PATH];
1709  WCHAR Wxx, Wyy;
1710 
1712  "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes",
1713  -1, reg_path, MAX_PATH);
1714  RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey);
1715  index = 0;
1716  while(value_len = data_len = MAX_PATH,
1717  RegEnumValueW(newkey, index, value, &value_len,
1718  0, &dwType, (LPVOID)data, &data_len) == 0) {
1719  TRACE("guess %d %s is %s\n",
1721 
1722  j = FALSE;
1723  for(i=0; i<value_len; i++) {
1724  Wxx = pszIn[i];
1725  Wyy = value[i];
1726  /* remember that TRUE is not-equal */
1727  j = ChrCmpIW(Wxx, Wyy);
1728  if (j) break;
1729  }
1730  if ((i == value_len) && !j) {
1731  if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
1732  *pcchOut = strlenW(data) + strlenW(pszIn) + 1;
1733  RegCloseKey(newkey);
1734  return E_POINTER;
1735  }
1736  strcpyW(pszOut, data);
1737  strcatW(pszOut, pszIn);
1738  *pcchOut = strlenW(pszOut);
1739  TRACE("matched and set to %s\n", debugstr_w(pszOut));
1740  RegCloseKey(newkey);
1741  return S_OK;
1742  }
1743  index++;
1744  }
1745  RegCloseKey(newkey);
1746  return E_FAIL;
1747 }
1748 
1749 static HRESULT URL_CreateFromPath(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl)
1750 {
1751  DWORD needed;
1752  HRESULT ret = S_OK;
1753  WCHAR *pszNewUrl;
1754  WCHAR file_colonW[] = {'f','i','l','e',':',0};
1755  WCHAR three_slashesW[] = {'/','/','/',0};
1756  PARSEDURLW parsed_url;
1757 
1758  parsed_url.cbSize = sizeof(parsed_url);
1759  if(ParseURLW(pszPath, &parsed_url) == S_OK) {
1760  if(parsed_url.nScheme != URL_SCHEME_INVALID && parsed_url.cchProtocol > 1) {
1761  needed = strlenW(pszPath);
1762  if (needed >= *pcchUrl) {
1763  *pcchUrl = needed + 1;
1764  return E_POINTER;
1765  } else {
1766  *pcchUrl = needed;
1767  return S_FALSE;
1768  }
1769  }
1770  }
1771 
1772  pszNewUrl = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath) + 9) * sizeof(WCHAR)); /* "file:///" + pszPath_len + 1 */
1773  strcpyW(pszNewUrl, file_colonW);
1774  if(isalphaW(pszPath[0]) && pszPath[1] == ':')
1775  strcatW(pszNewUrl, three_slashesW);
1776  strcatW(pszNewUrl, pszPath);
1777  ret = UrlEscapeW(pszNewUrl, pszUrl, pcchUrl, URL_ESCAPE_PERCENT);
1778  HeapFree(GetProcessHeap(), 0, pszNewUrl);
1779  return ret;
1780 }
1781 
1782 static HRESULT URL_ApplyDefault(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
1783 {
1784  HKEY newkey;
1785  DWORD data_len, dwType;
1786  WCHAR data[MAX_PATH];
1787 
1788  static const WCHAR prefix_keyW[] =
1789  {'S','o','f','t','w','a','r','e',
1790  '\\','M','i','c','r','o','s','o','f','t',
1791  '\\','W','i','n','d','o','w','s',
1792  '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n',
1793  '\\','U','R','L',
1794  '\\','D','e','f','a','u','l','t','P','r','e','f','i','x',0};
1795 
1796  /* get and prepend default */
1797  RegOpenKeyExW(HKEY_LOCAL_MACHINE, prefix_keyW, 0, 1, &newkey);
1798  data_len = sizeof(data);
1799  RegQueryValueExW(newkey, NULL, 0, &dwType, (LPBYTE)data, &data_len);
1800  RegCloseKey(newkey);
1801  if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
1802  *pcchOut = strlenW(data) + strlenW(pszIn) + 1;
1803  return E_POINTER;
1804  }
1805  strcpyW(pszOut, data);
1806  strcatW(pszOut, pszIn);
1807  *pcchOut = strlenW(pszOut);
1808  TRACE("used default %s\n", debugstr_w(pszOut));
1809  return S_OK;
1810 }
1811 
1812 /*************************************************************************
1813  * UrlApplySchemeW [SHLWAPI.@]
1814  *
1815  * See UrlApplySchemeA.
1816  */
1818 {
1819  PARSEDURLW in_scheme;
1820  DWORD res1;
1821  HRESULT ret;
1822 
1823  TRACE("(%s, %p, %p:out size %d, 0x%08x)\n", debugstr_w(pszIn),
1824  pszOut, pcchOut, pcchOut ? *pcchOut : 0, dwFlags);
1825 
1826  if (!pszIn || !pszOut || !pcchOut) return E_INVALIDARG;
1827 
1828  if (dwFlags & URL_APPLY_GUESSFILE) {
1829  if (*pcchOut > 1 && ':' == pszIn[1]) {
1830  res1 = *pcchOut;
1831  ret = URL_CreateFromPath(pszIn, pszOut, &res1);
1832  if (ret == S_OK || ret == E_POINTER){
1833  *pcchOut = res1;
1834  return ret;
1835  }
1836  else if (ret == S_FALSE)
1837  {
1838  return ret;
1839  }
1840  }
1841  }
1842 
1843  in_scheme.cbSize = sizeof(in_scheme);
1844  /* See if the base has a scheme */
1845  res1 = ParseURLW(pszIn, &in_scheme);
1846  if (res1) {
1847  /* no scheme in input, need to see if we need to guess */
1849  if ((ret = URL_GuessScheme(pszIn, pszOut, pcchOut)) != E_FAIL)
1850  return ret;
1851  }
1852  }
1853 
1854  /* If we are here, then either invalid scheme,
1855  * or no scheme and can't/failed guess.
1856  */
1857  if ( ( ((res1 == 0) && (dwFlags & URL_APPLY_FORCEAPPLY)) ||
1858  ((res1 != 0)) ) &&
1859  (dwFlags & URL_APPLY_DEFAULT)) {
1860  /* find and apply default scheme */
1861  return URL_ApplyDefault(pszIn, pszOut, pcchOut);
1862  }
1863 
1864  return S_FALSE;
1865 }
1866 
1867 /*************************************************************************
1868  * UrlIsA [SHLWAPI.@]
1869  *
1870  * Determine if a Url is of a certain class.
1871  *
1872  * PARAMS
1873  * pszUrl [I] Url to check
1874  * Urlis [I] URLIS_ constant from "shlwapi.h"
1875  *
1876  * RETURNS
1877  * TRUE if pszUrl belongs to the class type in Urlis.
1878  * FALSE Otherwise.
1879  */
1881 {
1882  PARSEDURLA base;
1883  DWORD res1;
1884  LPCSTR last;
1885 
1886  TRACE("(%s %d)\n", debugstr_a(pszUrl), Urlis);
1887 
1888  if(!pszUrl)
1889  return FALSE;
1890 
1891  switch (Urlis) {
1892 
1893  case URLIS_OPAQUE:
1894  base.cbSize = sizeof(base);
1895  res1 = ParseURLA(pszUrl, &base);
1896  if (res1) return FALSE; /* invalid scheme */
1897  switch (base.nScheme)
1898  {
1899  case URL_SCHEME_MAILTO:
1900  case URL_SCHEME_SHELL:
1901  case URL_SCHEME_JAVASCRIPT:
1902  case URL_SCHEME_VBSCRIPT:
1903  case URL_SCHEME_ABOUT:
1904  return TRUE;
1905  }
1906  return FALSE;
1907 
1908  case URLIS_FILEURL:
1909  return (CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, pszUrl, 5,
1910  "file:", 5) == CSTR_EQUAL);
1911 
1912  case URLIS_DIRECTORY:
1913  last = pszUrl + strlen(pszUrl) - 1;
1914  return (last >= pszUrl && (*last == '/' || *last == '\\' ));
1915 
1916  case URLIS_URL:
1917  return PathIsURLA(pszUrl);
1918 
1919  case URLIS_NOHISTORY:
1920  case URLIS_APPLIABLE:
1921  case URLIS_HASQUERY:
1922  default:
1923  FIXME("(%s %d): stub\n", debugstr_a(pszUrl), Urlis);
1924  }
1925  return FALSE;
1926 }
1927 
1928 /*************************************************************************
1929  * UrlIsW [SHLWAPI.@]
1930  *
1931  * See UrlIsA.
1932  */
1934 {
1935  static const WCHAR file_colon[] = { 'f','i','l','e',':',0 };
1936  PARSEDURLW base;
1937  DWORD res1;
1938  LPCWSTR last;
1939 
1940  TRACE("(%s %d)\n", debugstr_w(pszUrl), Urlis);
1941 
1942  if(!pszUrl)
1943  return FALSE;
1944 
1945  switch (Urlis) {
1946 
1947  case URLIS_OPAQUE:
1948  base.cbSize = sizeof(base);
1949  res1 = ParseURLW(pszUrl, &base);
1950  if (res1) return FALSE; /* invalid scheme */
1951  switch (base.nScheme)
1952  {
1953  case URL_SCHEME_MAILTO:
1954  case URL_SCHEME_SHELL:
1955  case URL_SCHEME_JAVASCRIPT:
1956  case URL_SCHEME_VBSCRIPT:
1957  case URL_SCHEME_ABOUT:
1958  return TRUE;
1959  }
1960  return FALSE;
1961 
1962  case URLIS_FILEURL:
1963  return (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pszUrl, 5,
1964  file_colon, 5) == CSTR_EQUAL);
1965 
1966  case URLIS_DIRECTORY:
1967  last = pszUrl + strlenW(pszUrl) - 1;
1968  return (last >= pszUrl && (*last == '/' || *last == '\\'));
1969 
1970  case URLIS_URL:
1971  return PathIsURLW(pszUrl);
1972 
1973  case URLIS_NOHISTORY:
1974  case URLIS_APPLIABLE:
1975  case URLIS_HASQUERY:
1976  default:
1977  FIXME("(%s %d): stub\n", debugstr_w(pszUrl), Urlis);
1978  }
1979  return FALSE;
1980 }
1981 
1982 /*************************************************************************
1983  * UrlIsNoHistoryA [SHLWAPI.@]
1984  *
1985  * Determine if a Url should not be stored in the users history list.
1986  *
1987  * PARAMS
1988  * pszUrl [I] Url to check
1989  *
1990  * RETURNS
1991  * TRUE, if pszUrl should be excluded from the history list,
1992  * FALSE otherwise.
1993  */
1995 {
1996  return UrlIsA(pszUrl, URLIS_NOHISTORY);
1997 }
1998 
1999 /*************************************************************************
2000  * UrlIsNoHistoryW [SHLWAPI.@]
2001  *
2002  * See UrlIsNoHistoryA.
2003  */
2005 {
2006  return UrlIsW(pszUrl, URLIS_NOHISTORY);
2007 }
2008 
2009 /*************************************************************************
2010  * UrlIsOpaqueA [SHLWAPI.@]
2011  *
2012  * Determine if a Url is opaque.
2013  *
2014  * PARAMS
2015  * pszUrl [I] Url to check
2016  *
2017  * RETURNS
2018  * TRUE if pszUrl is opaque,
2019  * FALSE Otherwise.
2020  *
2021  * NOTES
2022  * An opaque Url is one that does not start with "<protocol>://".
2023  */
2025 {
2026  return UrlIsA(pszUrl, URLIS_OPAQUE);
2027 }
2028 
2029 /*************************************************************************
2030  * UrlIsOpaqueW [SHLWAPI.@]
2031  *
2032  * See UrlIsOpaqueA.
2033  */
2035 {
2036  return UrlIsW(pszUrl, URLIS_OPAQUE);
2037 }
2038 
2039 /*************************************************************************
2040  * Scans for characters of type "type" and when not matching found,
2041  * returns pointer to it and length in size.
2042  *
2043  * Characters tested based on RFC 1738
2044  */
2046 {
2047  static DWORD alwayszero = 0;
2048  BOOL cont = TRUE;
2049 
2050  *size = 0;
2051 
2052  switch(type){
2053 
2054  case SCHEME:
2055  while (cont) {
2056  if ( (islowerW(*start) && isalphaW(*start)) ||
2057  isdigitW(*start) ||
2058  (*start == '+') ||
2059  (*start == '-') ||
2060  (*start == '.')) {
2061  start++;
2062  (*size)++;
2063  }
2064  else
2065  cont = FALSE;
2066  }
2067 
2068  if(*start != ':')
2069  *size = 0;
2070 
2071  break;
2072 
2073  case USERPASS:
2074  while (cont) {
2075  if ( isalphaW(*start) ||
2076  isdigitW(*start) ||
2077  /* user/password only characters */
2078  (*start == ';') ||
2079  (*start == '?') ||
2080  (*start == '&') ||
2081  (*start == '=') ||
2082  /* *extra* characters */
2083  (*start == '!') ||
2084  (*start == '*') ||
2085  (*start == '\'') ||
2086  (*start == '(') ||
2087  (*start == ')') ||
2088  (*start == ',') ||
2089  /* *safe* characters */
2090  (*start == '$') ||
2091  (*start == '_') ||
2092  (*start == '+') ||
2093  (*start == '-') ||
2094  (*start == '.') ||
2095  (*start == ' ')) {
2096  start++;
2097  (*size)++;
2098  } else if (*start == '%') {
2099  if (isxdigitW(*(start+1)) &&
2100  isxdigitW(*(start+2))) {
2101  start += 3;
2102  *size += 3;
2103  } else
2104  cont = FALSE;
2105  } else
2106  cont = FALSE;
2107  }
2108  break;
2109 
2110  case PORT:
2111  while (cont) {
2112  if (isdigitW(*start)) {
2113  start++;
2114  (*size)++;
2115  }
2116  else
2117  cont = FALSE;
2118  }
2119  break;
2120 
2121  case HOST:
2122  while (cont) {
2123  if (isalnumW(*start) ||
2124  (*start == '-') ||
2125  (*start == '.') ||
2126  (*start == ' ') ||
2127  (*start == '*') ) {
2128  start++;
2129  (*size)++;
2130  }
2131  else
2132  cont = FALSE;
2133  }
2134  break;
2135  default:
2136  FIXME("unknown type %d\n", type);
2137  return (LPWSTR)&alwayszero;
2138  }
2139  /* TRACE("scanned %d characters next char %p<%c>\n",
2140  *size, start, *start); */
2141  return start;
2142 }
2143 
2144 /*************************************************************************
2145  * Attempt to parse URL into pieces.
2146  */
2148 {
2149  LPCWSTR work;
2150 
2151  memset(pl, 0, sizeof(WINE_PARSE_URL));
2152  pl->pScheme = pszUrl;
2153  work = URL_ScanID(pl->pScheme, &pl->szScheme, SCHEME);
2154  if (!*work || (*work != ':')) goto ErrorExit;
2155  work++;
2156  if ((*work != '/') || (*(work+1) != '/')) goto SuccessExit;
2157  pl->pUserName = work + 2;
2158  work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS);
2159  if (*work == ':' ) {
2160  /* parse password */
2161  work++;
2162  pl->pPassword = work;
2163  work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS);
2164  if (*work != '@') {
2165  /* what we just parsed must be the hostname and port
2166  * so reset pointers and clear then let it parse */
2167  pl->szUserName = pl->szPassword = 0;
2168  work = pl->pUserName - 1;
2169  pl->pUserName = pl->pPassword = 0;
2170  }
2171  } else if (*work == '@') {
2172  /* no password */
2173  pl->szPassword = 0;
2174  pl->pPassword = 0;
2175  } else if (!*work || (*work == '/') || (*work == '.')) {
2176  /* what was parsed was hostname, so reset pointers and let it parse */
2177  pl->szUserName = pl->szPassword = 0;
2178  work = pl->pUserName - 1;
2179  pl->pUserName = pl->pPassword = 0;
2180  } else goto ErrorExit;
2181 
2182  /* now start parsing hostname or hostnumber */
2183  work++;
2184  pl->pHostName = work;
2185  work = URL_ScanID(pl->pHostName, &pl->szHostName, HOST);
2186  if (*work == ':') {
2187  /* parse port */
2188  work++;
2189  pl->pPort = work;
2190  work = URL_ScanID(pl->pPort, &pl->szPort, PORT);
2191  }
2192  if (*work == '/') {
2193  /* see if query string */
2194  pl->pQuery = strchrW(work, '?');
2195  if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery);
2196  }
2197  SuccessExit:
2198  TRACE("parse successful: scheme=%p(%d), user=%p(%d), pass=%p(%d), host=%p(%d), port=%p(%d), query=%p(%d)\n",
2199  pl->pScheme, pl->szScheme,
2200  pl->pUserName, pl->szUserName,
2201  pl->pPassword, pl->szPassword,
2202  pl->pHostName, pl->szHostName,
2203  pl->pPort, pl->szPort,
2204  pl->pQuery, pl->szQuery);
2205  return S_OK;
2206  ErrorExit:
2207  FIXME("failed to parse %s\n", debugstr_w(pszUrl));
2208  return E_INVALIDARG;
2209 }
2210 
2211 /*************************************************************************
2212  * UrlGetPartA [SHLWAPI.@]
2213  *
2214  * Retrieve part of a Url.
2215  *
2216  * PARAMS
2217  * pszIn [I] Url to parse
2218  * pszOut [O] Destination for part of pszIn requested
2219  * pcchOut [I] Size of pszOut
2220  * [O] length of pszOut string EXCLUDING '\0' if S_OK, otherwise
2221  * needed size of pszOut INCLUDING '\0'.
2222  * dwPart [I] URL_PART_ enum from "shlwapi.h"
2223  * dwFlags [I] URL_ flags from "shlwapi.h"
2224  *
2225  * RETURNS
2226  * Success: S_OK. pszOut contains the part requested, pcchOut contains its length.
2227  * Failure: An HRESULT error code describing the error.
2228  */
2230  DWORD dwPart, DWORD dwFlags)
2231 {
2232  LPWSTR in, out;
2233  DWORD ret, len, len2;
2234 
2235  if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0)
2236  return E_INVALIDARG;
2237 
2238  in = HeapAlloc(GetProcessHeap(), 0,
2239  (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
2241 
2243 
2245  ret = UrlGetPartW(in, out, &len, dwPart, dwFlags);
2246 
2247  if (FAILED(ret)) {
2248  HeapFree(GetProcessHeap(), 0, in);
2249  return ret;
2250  }
2251 
2252  len2 = WideCharToMultiByte(CP_ACP, 0, out, len, NULL, 0, NULL, NULL);
2253  if (len2 > *pcchOut) {
2254  *pcchOut = len2+1;
2255  HeapFree(GetProcessHeap(), 0, in);
2256  return E_POINTER;
2257  }
2258  len2 = WideCharToMultiByte(CP_ACP, 0, out, len+1, pszOut, *pcchOut, NULL, NULL);
2259  *pcchOut = len2-1;
2260  HeapFree(GetProcessHeap(), 0, in);
2261  return ret;
2262 }
2263 
2264 /*************************************************************************
2265  * UrlGetPartW [SHLWAPI.@]
2266  *
2267  * See UrlGetPartA.
2268  */
2270  DWORD dwPart, DWORD dwFlags)
2271 {
2272  WINE_PARSE_URL pl;
2273  HRESULT ret;
2274  DWORD scheme, size, schsize;
2275  LPCWSTR addr, schaddr;
2276 
2277  TRACE("(%s %p %p(%d) %08x %08x)\n",
2278  debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags);
2279 
2280  if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0)
2281  return E_INVALIDARG;
2282 
2283  *pszOut = '\0';
2284 
2285  addr = strchrW(pszIn, ':');
2286  if(!addr)
2288  else
2289  scheme = get_scheme_code(pszIn, addr-pszIn);
2290 
2291  ret = URL_ParseUrl(pszIn, &pl);
2292 
2293  switch (dwPart) {
2294  case URL_PART_SCHEME:
2295  if (!pl.szScheme) {
2296  *pcchOut = 0;
2297  return S_FALSE;
2298  }
2299  addr = pl.pScheme;
2300  size = pl.szScheme;
2301  break;
2302 
2303  case URL_PART_HOSTNAME:
2304  switch(scheme) {
2305  case URL_SCHEME_FTP:
2306  case URL_SCHEME_HTTP:
2307  case URL_SCHEME_GOPHER:
2308  case URL_SCHEME_TELNET:
2309  case URL_SCHEME_FILE:
2310  case URL_SCHEME_HTTPS:
2311  break;
2312  default:
2313  *pcchOut = 0;
2314  return E_FAIL;
2315  }
2316 
2317  if(scheme==URL_SCHEME_FILE && (!pl.szHostName ||
2318  (pl.szHostName==1 && *(pl.pHostName+1)==':'))) {
2319  *pcchOut = 0;
2320  return S_FALSE;
2321  }
2322 
2323  if (!pl.szHostName) {
2324  *pcchOut = 0;
2325  return S_FALSE;
2326  }
2327  addr = pl.pHostName;
2328  size = pl.szHostName;
2329  break;
2330 
2331  case URL_PART_USERNAME:
2332  if (!pl.szUserName) {
2333  *pcchOut = 0;
2334  return S_FALSE;
2335  }
2336  addr = pl.pUserName;
2337  size = pl.szUserName;
2338  break;
2339 
2340  case URL_PART_PASSWORD:
2341  if (!pl.szPassword) {
2342  *pcchOut = 0;
2343  return S_FALSE;
2344  }
2345  addr = pl.pPassword;
2346  size = pl.szPassword;
2347  break;
2348 
2349  case URL_PART_PORT:
2350  if (!pl.szPort) {
2351  *pcchOut = 0;
2352  return S_FALSE;
2353  }
2354  addr = pl.pPort;
2355  size = pl.szPort;
2356  break;
2357 
2358  case URL_PART_QUERY:
2359  if (!pl.szQuery) {
2360  *pcchOut = 0;
2361  return S_FALSE;
2362  }
2363  addr = pl.pQuery;
2364  size = pl.szQuery;
2365  break;
2366 
2367  default:
2368  *pcchOut = 0;
2369  return E_INVALIDARG;
2370  }
2371 
2373  if(!pl.pScheme || !pl.szScheme) {
2374  *pcchOut = 0;
2375  return E_FAIL;
2376  }
2377  schaddr = pl.pScheme;
2378  schsize = pl.szScheme;
2379  if (*pcchOut < schsize + size + 2) {
2380  *pcchOut = schsize + size + 2;
2381  return E_POINTER;
2382  }
2383  memcpy(pszOut, schaddr, schsize*sizeof(WCHAR));
2384  pszOut[schsize] = ':';
2385  memcpy(pszOut+schsize+1, addr, size*sizeof(WCHAR));
2386  pszOut[schsize+1+size] = 0;
2387  *pcchOut = schsize + 1 + size;
2388  }
2389  else {
2390  if (*pcchOut < size + 1) {*pcchOut = size+1; return E_POINTER;}
2391  memcpy(pszOut, addr, size*sizeof(WCHAR));
2392  pszOut[size] = 0;
2393  *pcchOut = size;
2394  }
2395  TRACE("len=%d %s\n", *pcchOut, debugstr_w(pszOut));
2396 
2397  return ret;
2398 }
2399 
2400 /*************************************************************************
2401  * PathIsURLA [SHLWAPI.@]
2402  *
2403  * Check if the given path is a Url.
2404  *
2405  * PARAMS
2406  * lpszPath [I] Path to check.
2407  *
2408  * RETURNS
2409  * TRUE if lpszPath is a Url.
2410  * FALSE if lpszPath is NULL or not a Url.
2411  */
2413 {
2414  PARSEDURLA base;
2415  HRESULT hres;
2416 
2417  TRACE("%s\n", debugstr_a(lpstrPath));
2418 
2419  if (!lpstrPath || !*lpstrPath) return FALSE;
2420 
2421  /* get protocol */
2422  base.cbSize = sizeof(base);
2423  hres = ParseURLA(lpstrPath, &base);
2424  return hres == S_OK && (base.nScheme != URL_SCHEME_INVALID);
2425 }
2426 
2427 /*************************************************************************
2428  * PathIsURLW [SHLWAPI.@]
2429  *
2430  * See PathIsURLA.
2431  */
2433 {
2434  PARSEDURLW base;
2435  HRESULT hres;
2436 
2437  TRACE("%s\n", debugstr_w(lpstrPath));
2438 
2439  if (!lpstrPath || !*lpstrPath) return FALSE;
2440 
2441  /* get protocol */
2442  base.cbSize = sizeof(base);
2443  hres = ParseURLW(lpstrPath, &base);
2444  return hres == S_OK && (base.nScheme != URL_SCHEME_INVALID);
2445 }
2446 
2447 /*************************************************************************
2448  * UrlCreateFromPathA [SHLWAPI.@]
2449  *
2450  * See UrlCreateFromPathW
2451  */
2453 {
2455  WCHAR *urlW = bufW;
2456  UNICODE_STRING pathW;
2457  HRESULT ret;
2458  DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
2459 
2460  if(!RtlCreateUnicodeStringFromAsciiz(&pathW, pszPath))
2461  return E_INVALIDARG;
2462  if((ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved)) == E_POINTER) {
2463  urlW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
2464  ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved);
2465  }
2466  if(ret == S_OK || ret == S_FALSE) {
2467  RtlUnicodeToMultiByteSize(&lenA, urlW, lenW * sizeof(WCHAR));
2468  if(*pcchUrl > lenA) {
2469  RtlUnicodeToMultiByteN(pszUrl, *pcchUrl - 1, &lenA, urlW, lenW * sizeof(WCHAR));
2470  pszUrl[lenA] = 0;
2471  *pcchUrl = lenA;
2472  } else {
2473  *pcchUrl = lenA + 1;
2474  ret = E_POINTER;
2475  }
2476  }
2477  if(urlW != bufW) HeapFree(GetProcessHeap(), 0, urlW);
2478  RtlFreeUnicodeString(&pathW);
2479  return ret;
2480 }
2481 
2482 /*************************************************************************
2483  * UrlCreateFromPathW [SHLWAPI.@]
2484  *
2485  * Create a Url from a file path.
2486  *
2487  * PARAMS
2488  * pszPath [I] Path to convert
2489  * pszUrl [O] Destination for the converted Url
2490  * pcchUrl [I/O] Length of pszUrl
2491  * dwReserved [I] Reserved, must be 0
2492  *
2493  * RETURNS
2494  * Success: S_OK pszUrl contains the converted path, S_FALSE if the path is already a Url
2495  * Failure: An HRESULT error code.
2496  */
2498 {
2499  HRESULT ret;
2500 
2501  TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_w(pszPath), pszUrl, pcchUrl, dwReserved);
2502 
2503  /* Validate arguments */
2504  if (dwReserved != 0)
2505  return E_INVALIDARG;
2506  if (!pszUrl || !pcchUrl)
2507  return E_INVALIDARG;
2508 
2509  ret = URL_CreateFromPath(pszPath, pszUrl, pcchUrl);
2510 
2511  if (S_FALSE == ret)
2512  strcpyW(pszUrl, pszPath);
2513 
2514  return ret;
2515 }
2516 
2517 /*************************************************************************
2518  * SHAutoComplete [SHLWAPI.@]
2519  *
2520  * Enable auto-completion for an edit control.
2521  *
2522  * PARAMS
2523  * hwndEdit [I] Handle of control to enable auto-completion for
2524  * dwFlags [I] SHACF_ flags from "shlwapi.h"
2525  *
2526  * RETURNS
2527  * Success: S_OK. Auto-completion is enabled for the control.
2528  * Failure: An HRESULT error code indicating the error.
2529  */
2531 {
2532  FIXME("stub\n");
2533  return S_FALSE;
2534 }
2535 
2536 /*************************************************************************
2537  * MLBuildResURLA [SHLWAPI.405]
2538  *
2539  * Create a Url pointing to a resource in a module.
2540  *
2541  * PARAMS
2542  * lpszLibName [I] Name of the module containing the resource
2543  * hMod [I] Callers module handle
2544  * dwFlags [I] Undocumented flags for loading the module
2545  * lpszRes [I] Resource name
2546  * lpszDest [O] Destination for resulting Url
2547  * dwDestLen [I] Length of lpszDest
2548  *
2549  * RETURNS
2550  * Success: S_OK. lpszDest contains the resource Url.
2551  * Failure: E_INVALIDARG, if any argument is invalid, or
2552  * E_FAIL if dwDestLen is too small.
2553  */
2555  LPCSTR lpszRes, LPSTR lpszDest, DWORD dwDestLen)
2556 {
2557  WCHAR szLibName[MAX_PATH], szRes[MAX_PATH], szDest[MAX_PATH];
2558  HRESULT hRet;
2559 
2560  if (lpszLibName)
2561  MultiByteToWideChar(CP_ACP, 0, lpszLibName, -1, szLibName, sizeof(szLibName)/sizeof(WCHAR));
2562 
2563  if (lpszRes)
2564  MultiByteToWideChar(CP_ACP, 0, lpszRes, -1, szRes, sizeof(szRes)/sizeof(WCHAR));
2565 
2566  if (dwDestLen > sizeof(szLibName)/sizeof(WCHAR))
2567  dwDestLen = sizeof(szLibName)/sizeof(WCHAR);
2568 
2569  hRet = MLBuildResURLW(lpszLibName ? szLibName : NULL, hMod, dwFlags,
2570  lpszRes ? szRes : NULL, lpszDest ? szDest : NULL, dwDestLen);
2571  if (SUCCEEDED(hRet) && lpszDest)
2572  WideCharToMultiByte(CP_ACP, 0, szDest, -1, lpszDest, dwDestLen, NULL, NULL);
2573 
2574  return hRet;
2575 }
2576 
2577 /*************************************************************************
2578  * MLBuildResURLA [SHLWAPI.406]
2579  *
2580  * See MLBuildResURLA.
2581  */
2583  LPCWSTR lpszRes, LPWSTR lpszDest, DWORD dwDestLen)
2584 {
2585  static const WCHAR szRes[] = { 'r','e','s',':','/','/','\0' };
2586 #define szResLen ((sizeof(szRes) - sizeof(WCHAR))/sizeof(WCHAR))
2587  HRESULT hRet = E_FAIL;
2588 
2589  TRACE("(%s,%p,0x%08x,%s,%p,%d)\n", debugstr_w(lpszLibName), hMod, dwFlags,
2590  debugstr_w(lpszRes), lpszDest, dwDestLen);
2591 
2592  if (!lpszLibName || !hMod || hMod == INVALID_HANDLE_VALUE || !lpszRes ||
2593  !lpszDest || (dwFlags && dwFlags != 2))
2594  return E_INVALIDARG;
2595 
2596  if (dwDestLen >= szResLen + 1)
2597  {
2598  dwDestLen -= (szResLen + 1);
2599  memcpy(lpszDest, szRes, sizeof(szRes));
2600 
2601  hMod = MLLoadLibraryW(lpszLibName, hMod, dwFlags);
2602 
2603  if (hMod)
2604  {
2605  WCHAR szBuff[MAX_PATH];
2606  DWORD len;
2607 
2608  len = GetModuleFileNameW(hMod, szBuff, sizeof(szBuff)/sizeof(WCHAR));
2609  if (len && len < sizeof(szBuff)/sizeof(WCHAR))
2610  {
2611  DWORD dwPathLen = strlenW(szBuff) + 1;
2612 
2613  if (dwDestLen >= dwPathLen)
2614  {
2615  DWORD dwResLen;
2616 
2617  dwDestLen -= dwPathLen;
2618  memcpy(lpszDest + szResLen, szBuff, dwPathLen * sizeof(WCHAR));
2619 
2620  dwResLen = strlenW(lpszRes) + 1;
2621  if (dwDestLen >= dwResLen + 1)
2622  {
2623  lpszDest[szResLen + dwPathLen-1] = '/';
2624  memcpy(lpszDest + szResLen + dwPathLen, lpszRes, dwResLen * sizeof(WCHAR));
2625  hRet = S_OK;
2626  }
2627  }
2628  }
2629  MLFreeLibrary(hMod);
2630  }
2631  }
2632  return hRet;
2633 }
2634 
2635 /***********************************************************************
2636  * UrlFixupW [SHLWAPI.462]
2637  *
2638  * Checks the scheme part of a URL and attempts to correct misspellings.
2639  *
2640  * PARAMS
2641  * lpszUrl [I] Pointer to the URL to be corrected
2642  * lpszTranslatedUrl [O] Pointer to a buffer to store corrected URL
2643  * dwMaxChars [I] Maximum size of corrected URL
2644  *
2645  * RETURNS
2646  * success: S_OK if URL corrected or already correct
2647  * failure: S_FALSE if unable to correct / COM error code if other error
2648  *
2649  */
2650 HRESULT WINAPI UrlFixupW(LPCWSTR url, LPWSTR translatedUrl, DWORD maxChars)
2651 {
2652  DWORD srcLen;
2653 
2654  FIXME("(%s,%p,%d) STUB\n", debugstr_w(url), translatedUrl, maxChars);
2655 
2656  if (!url)
2657  return E_FAIL;
2658 
2659  srcLen = lstrlenW(url) + 1;
2660 
2661  /* For now just copy the URL directly */
2662  lstrcpynW(translatedUrl, url, (maxChars < srcLen) ? maxChars : srcLen);
2663 
2664  return S_OK;
2665 }
2666 
2667 /*************************************************************************
2668  * IsInternetESCEnabled [SHLWAPI.@]
2669  */
2671 {
2672  FIXME(": stub\n");
2673  return FALSE;
2674 }
#define URL_APPLY_FORCEAPPLY
Definition: shlwapi.h:1201
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
static const WCHAR wszHttp[]
Definition: urlmon_main.c:389
HRESULT WINAPI UrlCreateFromPathA(LPCSTR pszPath, LPSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
Definition: url.c:2452
#define WINE_URL_ESCAPE_QUESTION
Definition: url.c:995
WINE_UNICODE_INLINE int islowerW(WCHAR wc)
Definition: unicode.h:180
LPCWSTR pScheme
Definition: url.c:88
#define TRUE
Definition: types.h:120
HRESULT WINAPI UrlEscapeW(LPCWSTR pszUrl, LPWSTR pszEscaped, LPDWORD pcchEscaped, DWORD dwFlags)
Definition: url.c:1076
BOOL NTAPI IsBadWritePtr(IN LPVOID lp, IN UINT_PTR ucb)
Definition: except.c:885
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
DWORD ret
Definition: url.c:448
#define WINE_URL_STOP_ON_HASH
Definition: url.c:996
#define WideCharToMultiByte
Definition: compat.h:101
HRESULT hr
Definition: shlfolder.c:183
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
HRESULT WINAPI UrlApplySchemeA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
Definition: url.c:1662
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
static BOOL URL_NeedEscapeW(WCHAR ch, DWORD flags, DWORD int_flags)
Definition: url.c:999
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
POINT last
Definition: font.c:46
DWORD szHostName
Definition: url.c:95
HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwPart, DWORD dwFlags)
Definition: url.c:2229
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
#define URL_UNESCAPE_INPLACE
Definition: shlwapi.h:1224
#define CP_ACP
Definition: compat.h:99
DWORD cbSize
Definition: shlwapi.h:1432
char CHAR
Definition: xmlstorage.h:175
struct _root root
LPCWSTR pQuery
Definition: url.c:98
#define WINE_URL_COLLAPSE_SLASHES
Definition: url.c:992
HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized, LPDWORD pcchCanonicalized, DWORD dwFlags)
Definition: url.c:247
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteSize(PULONG MbSize, PCWCH UnicodeString, ULONG UnicodeSize)
#define INTERNET_MAX_SCHEME_LENGTH
Definition: wininet.h:50
#define URL_DONT_UNESCAPE_EXTRA_INFO
Definition: shlwapi.h:1218
HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y)
Definition: url.c:161
static const BYTE localhost[]
Definition: encode.c:1442
BOOL WINAPI UrlIsOpaqueA(LPCSTR pszUrl)
Definition: url.c:2024
DWORD scheme
static const struct @525 shlwapi_schemes[]
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
HRESULT WINAPI HashData(const unsigned char *lpSrc, DWORD nSrcLen, unsigned char *lpDest, DWORD nDestLen)
Definition: url.c:1575
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
#define URL_ESCAPE_AS_UTF8
Definition: shlwapi.h:1227
LPCWSTR pszSuffix
Definition: shlwapi.h:1435
#define NORM_IGNORECASE
Definition: winnls.h:173
Definition: url.c:105
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
_Check_return_ _CRTIMP int __cdecl isalnum(_In_ int _C)
char * LPSTR
Definition: xmlstorage.h:182
#define lstrlenW
Definition: compat.h:407
#define E_FAIL
Definition: ddrawi.h:102
int32_t INT
Definition: typedefs.h:56
BOOL WINAPI UrlIsNoHistoryW(LPCWSTR pszUrl)
Definition: url.c:2004
#define lstrcpynW
Definition: compat.h:397
WINE_UNICODE_INLINE int strncmpW(const WCHAR *str1, const WCHAR *str2, int n)
Definition: unicode.h:235
BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
Definition: url.c:2432
BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
Definition: url.c:2412
DWORD szPassword
Definition: url.c:93
HRESULT WINAPI UrlUnescapeW(LPWSTR pszUrl, LPWSTR pszUnescaped, LPDWORD pcchUnescaped, DWORD dwFlags)
Definition: url.c:1367
static LPCWSTR URL_ScanID(LPCWSTR start, LPDWORD size, WINE_URL_SCAN_TYPE type)
Definition: url.c:2045
HRESULT WINAPI UrlUnescapeA(LPSTR pszUrl, LPSTR pszUnescaped, LPDWORD pcchUnescaped, DWORD dwFlags)
Definition: url.c:1298
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
static const CHAR hexDigits[]
Definition: url.c:109
#define CP_UTF8
Definition: nls.h:20
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:90
static const WCHAR wszFile[]
Definition: urlmon_main.c:386
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint base
Definition: 3dtext.c:35
long LONG
Definition: pedump.c:60
LPCWSTR pPassword
Definition: url.c:92
#define debugstr_w
Definition: kernel32.h:32
#define FIXME(fmt,...)
Definition: debug.h:110
URL_SCHEME scheme_number
Definition: url.c:64
static HRESULT URL_CreateFromPath(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl)
Definition: url.c:1749
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
Definition: url.c:1880
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2867
#define strstrW(d, s)
Definition: unicode.h:32
smooth NULL
Definition: ftsmooth.c:416
#define WINE_URL_ESCAPE_HASH
Definition: url.c:994
#define INTERNET_MAX_URL_LENGTH
Definition: session.c:1380
WCHAR scheme_name[12]
Definition: url.c:65
#define URL_WININET_COMPATIBILITY
Definition: shlwapi.h:1209
WINE_URL_SCAN_TYPE
Definition: url.c:102
WCHAR lpszDest[260]
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeStringFromAsciiz(_Out_ PUNICODE_STRING Destination, _In_ PCSZ Source)
#define URL_E_INVALID_SYNTAX
Definition: intshcut.h:32
#define WINE_URL_STOP_ON_QUESTION
Definition: url.c:997
GLuint index
Definition: glext.h:6031
#define URL_PARTFLAG_KEEPSCHEME
Definition: shlwapi.h:1187
const char * LPCSTR
Definition: xmlstorage.h:183
#define URL_ESCAPE_SEGMENT_ONLY
Definition: shlwapi.h:1229
LPCWSTR pPort
Definition: url.c:96
WINE_DEFAULT_DEBUG_CHANNEL(shell)
HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwPart, DWORD dwFlags)
Definition: url.c:2269
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
INT WINAPI CompareStringA(LCID lcid, DWORD flags, LPCSTR str1, INT len1, LPCSTR str2, INT len2)
Definition: lang.c:2299
INT WINAPI CompareStringW(LCID lcid, DWORD flags, LPCWSTR str1, INT len1, LPCWSTR str2, INT len2)
Definition: lang.c:2275
HRESULT WINAPI MLBuildResURLA(LPCSTR lpszLibName, HMODULE hMod, DWORD dwFlags, LPCSTR lpszRes, LPSTR lpszDest, DWORD dwDestLen)
Definition: url.c:2554
BOOL WINAPI UrlIsOpaqueW(LPCWSTR pszUrl)
Definition: url.c:2034
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
Definition: url.c:106
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
if(!(yy_init))
Definition: macro.lex.yy.c:714
DWORD szQuery
Definition: url.c:99
__wchar_t WCHAR
Definition: xmlstorage.h:180
HRESULT WINAPI UrlCreateFromPathW(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
Definition: url.c:2497
#define debugstr_a
Definition: kernel32.h:31
#define URL_APPLY_DEFAULT
Definition: shlwapi.h:1204
LONG HRESULT
Definition: typedefs.h:77
static const unsigned char HashDataLookup[256]
Definition: url.c:113
HRESULT WINAPI UrlHashA(LPCSTR pszUrl, unsigned char *lpDest, DWORD nDestLen)
Definition: url.c:1616
LPCWSTR pHostName
Definition: url.c:94
WINE_UNICODE_INLINE WCHAR * strpbrkW(const WCHAR *str, const WCHAR *accept)
Definition: unicode.h:261
#define WC_ERR_INVALID_CHARS
Definition: unicode.h:47
#define MAX_PATH
Definition: compat.h:26
#define WINAPI
Definition: msvc.h:8
HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, LPDWORD pcchCanonicalized, DWORD dwFlags)
Definition: url.c:282
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
static FILE * out
Definition: regtests2xml.c:44
WINE_UNICODE_INLINE WCHAR tolowerW(WCHAR ch)
Definition: unicode.h:135
unsigned long DWORD
Definition: ntddk_ex.h:95
INT WINAPI UrlCompareW(LPCWSTR pszUrl1, LPCWSTR pszUrl2, BOOL fIgnoreSlash)
Definition: url.c:1537
DWORD szPort
Definition: url.c:97
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
UINT cchSuffix
Definition: shlwapi.h:1436
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLbitfield flags
Definition: glext.h:7161
#define URL_FILE_USE_PATHURL
Definition: shlwapi.h:1226
BOOL WINAPI IsInternetESCEnabled(void)
Definition: url.c:2670
BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, LPINT lpiRet)
Definition: string.c:970
UINT cchProtocol
Definition: shlwapi.h:1434
WINE_UNICODE_INLINE int isxdigitW(WCHAR wc)
Definition: unicode.h:175
UINT nScheme
Definition: shlwapi.h:1437
BOOL WINAPI UrlIsNoHistoryA(LPCSTR pszUrl)
Definition: url.c:1994
static HRESULT URL_ApplyDefault(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
Definition: url.c:1782
NTSYSAPI NTSTATUS NTAPI RtlUnicodeToMultiByteN(PCHAR MbString, ULONG MbSize, PULONG ResultSize, PCWCH UnicodeString, ULONG UnicodeSize)
HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
Definition: url.c:197
GLenum const GLvoid * addr
Definition: glext.h:9621
#define index(s, c)
Definition: various.h:29
const char * url
Definition: url.c:447
static LONG URL_ParseUrl(LPCWSTR pszUrl, WINE_PARSE_URL *pl)
Definition: url.c:2147
HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
Definition: url.c:1817
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
Definition: url.c:104
#define URL_DONT_SIMPLIFY
Definition: shlwapi.h:1214
static int state
Definition: maze.c:121
#define WINE_URL_BASH_AS_SLASH
Definition: url.c:991
#define STIF_SUPPORT_HEX
Definition: shlwapi.h:1452
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
DWORD szUserName
Definition: url.c:91
unsigned char BYTE
Definition: mem.h:68
#define CSTR_EQUAL
Definition: winnls.h:453
#define WINE_URL_ESCAPE_SLASH
Definition: url.c:993
HMODULE WINAPI MLLoadLibraryW(LPCWSTR, HMODULE, DWORD)
Definition: ordinal.c:3606
static LPWSTR
Definition: url.c:35
HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative, LPSTR pszCombined, LPDWORD pcchCombined, DWORD dwFlags)
Definition: url.c:614
GLenum src
Definition: glext.h:6340
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
Definition: url.c:1933
static DWORD get_scheme_code(LPCWSTR scheme, DWORD scheme_len)
Definition: url.c:135
LPCWSTR WINAPI UrlGetLocationW(LPCWSTR pszUrl)
Definition: url.c:1479
#define debugstr_wn
Definition: kernel32.h:33
WINE_UNICODE_INLINE int isalnumW(WCHAR wc)
Definition: unicode.h:190
HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative, LPWSTR pszCombined, LPDWORD pcchCombined, DWORD dwFlags)
Definition: url.c:662
#define URL_ESCAPE_PERCENT
Definition: shlwapi.h:1230
Definition: url.c:103
#define URL_ESCAPE_UNSAFE
Definition: shlwapi.h:1211
#define szResLen
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
HWND hwndEdit
Definition: combotst.c:65
#define LOCALE_INVARIANT
INT WINAPI UrlCompareA(LPCSTR pszUrl1, LPCSTR pszUrl2, BOOL fIgnoreSlash)
Definition: url.c:1510
#define S_OK
Definition: intsafe.h:59
static WCHAR * heap_strdupAtoW(const char *str)
Definition: url.c:45
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
static unsigned __int64 next
Definition: rand_nt.c:6
BOOL NTAPI IsBadStringPtrA(IN LPCSTR lpsz, IN UINT_PTR ucchMax)
Definition: except.c:991
GLuint in
Definition: glext.h:9616
#define lstrcpyW
Definition: compat.h:406
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
GLuint start
Definition: gl.h:1545
static VOID ErrorExit(LPTSTR lpszMessage)
Definition: telnetd.c:647
LPCWSTR pszProtocol
Definition: shlwapi.h:1433
#define E_NOTIMPL
Definition: ddrawi.h:99
GLenum GLenum dst
Definition: glext.h:6340
WINE_UNICODE_INLINE WCHAR * strcatW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:242
WINE_UNICODE_INLINE int isdigitW(WCHAR wc)
Definition: unicode.h:170
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:100
#define URL_UNESCAPE
Definition: shlwapi.h:1212
#define min(a, b)
Definition: monoChain.cc:55
HRESULT WINAPI UrlEscapeA(LPCSTR pszUrl, LPSTR pszEscaped, LPDWORD pcchEscaped, DWORD dwFlags)
Definition: url.c:950
BOOL NTAPI IsBadStringPtrW(IN LPCWSTR lpsz, IN UINT_PTR ucchMax)
Definition: except.c:952
LPCSTR WINAPI UrlGetLocationA(LPCSTR pszUrl)
Definition: url.c:1457
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
#define MultiByteToWideChar
Definition: compat.h:100
HRESULT WINAPI MLBuildResURLW(LPCWSTR, HMODULE, DWORD, LPCWSTR, LPWSTR, DWORD)
Definition: url.c:2582
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define URL_APPLY_GUESSSCHEME
Definition: shlwapi.h:1203
#define isxdigit(c)
Definition: acclib.h:70
HRESULT WINAPI UrlHashW(LPCWSTR pszUrl, unsigned char *lpDest, DWORD nDestLen)
Definition: url.c:1630
URLIS
Definition: shlwapi.h:1190
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
WINE_UNICODE_INLINE int strcmpW(const WCHAR *str1, const WCHAR *str2)
Definition: unicode.h:229
DWORD szScheme
Definition: url.c:89
URL_SCHEME
Definition: shlwapi.h:1144
static const WCHAR wszRes[]
Definition: misc.c:321
uint32_t * LPDWORD
Definition: typedefs.h:57
LPCWSTR pUserName
Definition: url.c:90
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
BOOL WINAPI MLFreeLibrary(HMODULE)
Definition: ordinal.c:3863
char * cleanup(char *str)
Definition: wpickclick.c:99
HRESULT WINAPI SHAutoComplete(HWND hwndEdit, DWORD dwFlags)
Definition: url.c:2530
#define memicmpW(s1, s2, n)
Definition: unicode.h:27
WINE_UNICODE_INLINE int isalphaW(WCHAR wc)
Definition: unicode.h:195
static DWORD
Definition: url.c:34
#define URL_ESCAPE_SPACES_ONLY
Definition: shlwapi.h:1216
#define URL_APPLY_GUESSFILE
Definition: shlwapi.h:1202
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define URL_PLUGGABLE_PROTOCOL
Definition: shlwapi.h:1210
#define E_POINTER
Definition: winerror.h:2365
static HRESULT URL_GuessScheme(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
Definition: url.c:1701
#define memset(x, y, z)
Definition: compat.h:39
static const WCHAR fileW[]
Definition: url.c:111
HRESULT WINAPI UrlFixupW(LPCWSTR url, LPWSTR translatedUrl, DWORD maxChars)
Definition: url.c:2650
#define CHAR(Char)
#define HeapFree(x, y, z)
Definition: compat.h:394
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define URL_DONT_ESCAPE_EXTRA_INFO
Definition: shlwapi.h:1217
BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
Definition: string.c:217
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12