ReactOS  0.4.14-dev-52-g6116262
url.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "config.h"
20 #include <stdarg.h>
21 
22 #include "wine/debug.h"
23 
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winreg.h"
27 #include "winhttp.h"
28 #include "shlwapi.h"
29 
30 #include "winhttp_private.h"
31 
33 
34 static const WCHAR scheme_http[] = {'h','t','t','p',0};
35 static const WCHAR scheme_https[] = {'h','t','t','p','s',0};
36 
38 {
39  if (*str && !*str_len) return ERROR_INVALID_PARAMETER;
40  if (!*str_len) return ERROR_SUCCESS;
41  if (!*str)
42  {
44  *str = value;
45  *str_len = len;
46  }
47  else
48  {
49  if (len >= *str_len)
50  {
51  *str_len = len+1;
52  *overflow = TRUE;
53  return ERROR_SUCCESS;
54  }
55  memcpy( *str, value, len * sizeof(WCHAR) );
56  (*str)[len] = 0;
57  *str_len = len;
58  }
59  return ERROR_SUCCESS;
60 }
61 
63 {
64  const WCHAR *p = url;
65  WCHAR hex[3], *q, *ret;
66 
67  if (!(ret = heap_alloc( *len * sizeof(WCHAR) ))) return NULL;
68  q = ret;
69  while (*len > 0)
70  {
71  if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
72  {
73  hex[0] = p[1];
74  hex[1] = p[2];
75  hex[2] = 0;
76  *q++ = strtolW( hex, NULL, 16 );
77  p += 3;
78  *len -= 3;
79  }
80  else
81  {
82  *q++ = *p++;
83  *len -= 1;
84  }
85  }
86  *len = q - ret;
87  return ret;
88 }
89 
91 {
92  if (isalnumW( c )) return FALSE;
93 
94  if (c <= 31 || c >= 127) return TRUE;
95  else
96  {
97  switch (c)
98  {
99  case ' ':
100  case '"':
101  case '#':
102  case '%':
103  case '<':
104  case '>':
105  case ']':
106  case '\\':
107  case '[':
108  case '^':
109  case '`':
110  case '{':
111  case '|':
112  case '}':
113  case '~':
114  return TRUE;
115  default:
116  return FALSE;
117  }
118  }
119 }
120 
122 {
123  static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
124  DWORD ret = len;
125  unsigned int i;
126  WCHAR *p = dst;
127 
128  for (i = 0; i < len; i++, p++)
129  {
130  if (need_escape( src[i] ))
131  {
132  p[0] = '%';
133  p[1] = hex[(src[i] >> 4) & 0xf];
134  p[2] = hex[src[i] & 0xf];
135  ret += 2;
136  p += 2;
137  }
138  else *p = src[i];
139  }
140  dst[ret] = 0;
141  return ret;
142 }
143 
145 {
146  WCHAR *ret;
147  const WCHAR *p, *q;
148 
149  if ((p = q = strrchrW( url, '/' )))
150  {
151  while (*q)
152  {
153  if (need_escape( *q )) *len += 2;
154  q++;
155  }
156  }
157  if (!(ret = heap_alloc( (*len + 1) * sizeof(WCHAR) ))) return NULL;
158  if (!p) strcpyW( ret, url );
159  else
160  {
161  memcpy( ret, url, (p - url) * sizeof(WCHAR) );
162  copy_escape( ret + (p - url), p, q - p );
163  }
164  return ret;
165 }
166 
168 {
169  const WCHAR *p = str;
170  DWORD port = 0;
171  while (len && isdigitW( *p ))
172  {
173  if ((port = port * 10 + *p - '0') > 65535) return ERROR_WINHTTP_INVALID_URL;
174  p++; len--;
175  }
176  *ret = port;
177  return ERROR_SUCCESS;
178 }
179 
180 /***********************************************************************
181  * WinHttpCrackUrl (winhttp.@)
182  */
184 {
185  WCHAR *p, *q, *r, *url_decoded = NULL, *url_escaped = NULL;
187  BOOL overflow = FALSE;
188  DWORD err;
189 
190  TRACE("%s, %d, %x, %p\n", debugstr_wn(url, len), len, flags, uc);
191 
192  if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS))
193  {
195  return FALSE;
196  }
197  if (!len) len = strlenW( url );
198 
199  if (flags & ICU_ESCAPE)
200  {
201  if (!(url_escaped = escape_url( url, &len )))
202  {
204  return FALSE;
205  }
206  url = url_escaped;
207  }
208  else if (flags & ICU_DECODE)
209  {
210  if (!(url_decoded = decode_url( url, &len )))
211  {
213  return FALSE;
214  }
215  url = url_decoded;
216  }
217  if (!(p = strchrW( url, ':' )))
218  {
220  return FALSE;
221  }
222  if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) scheme = INTERNET_SCHEME_HTTP;
223  else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme = INTERNET_SCHEME_HTTPS;
224  else
225  {
227  goto exit;
228  }
229 
230  if ((err = set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags, &overflow ))) goto exit;
231 
232  p++; /* skip ':' */
233  if (!p[0] || p[0] != '/' || p[1] != '/')
234  {
236  goto exit;
237  }
238  p += 2;
239  if (!p[0])
240  {
242  goto exit;
243  }
244  if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
245  {
246  if ((r = memchrW( p, ':', q - p )))
247  {
248  if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags, &overflow ))) goto exit;
249  r++;
250  if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags, &overflow ))) goto exit;
251  }
252  else
253  {
254  if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags, &overflow ))) goto exit;
255  if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit;
256  }
257  p = q + 1;
258  }
259  else
260  {
261  if ((err = set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags, &overflow ))) goto exit;
262  if ((err = set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags, &overflow ))) goto exit;
263  }
264  if ((q = memchrW( p, '/', len - (p - url) )))
265  {
266  if ((r = memchrW( p, ':', q - p )))
267  {
268  if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit;
269  r++;
270  if ((err = parse_port( r, q - r, &uc->nPort ))) goto exit;
271  }
272  else
273  {
274  if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags, &overflow ))) goto exit;
277  }
278 
279  if ((r = memchrW( q, '?', len - (q - url) )))
280  {
281  if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags, &overflow ))) goto exit;
282  if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags, &overflow ))) goto exit;
283  }
284  else
285  {
286  if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags, &overflow ))) goto exit;
287  if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
288  }
289  }
290  else
291  {
292  if ((r = memchrW( p, ':', len - (p - url) )))
293  {
294  if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags, &overflow ))) goto exit;
295  r++;
296  if ((err = parse_port( r, len - (r - url), &uc->nPort ))) goto exit;
297  }
298  else
299  {
300  if ((err = set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags, &overflow ))) goto exit;
303  }
304  if ((err = set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
305  if ((err = set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
306  }
307 
308  TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ),
311 
312 exit:
313  if (!err)
314  {
315  if (overflow) err = ERROR_INSUFFICIENT_BUFFER;
316  uc->nScheme = scheme;
317  }
318  heap_free( url_decoded );
319  heap_free( url_escaped );
320  set_last_error( err );
321  return !err;
322 }
323 
325 {
328  return 0;
329 }
330 
332 {
333  if (scheme == INTERNET_SCHEME_HTTP) return scheme_http;
335  return NULL;
336 }
337 
339 {
342  return FALSE;
343 }
344 
346 {
347  DWORD ret;
348  unsigned int i;
349 
350  ret = len ? len : strlenW( comp );
351  if (!(flags & ICU_ESCAPE)) return ret;
352  for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
353  return ret;
354 }
355 
357 {
358  static const WCHAR formatW[] = {'%','u',0};
360 
361  *len = 0;
362  if (uc->lpszScheme)
363  {
364  DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
365  *len += scheme_len;
366  scheme = get_scheme( uc->lpszScheme, scheme_len );
367  }
368  else
369  {
370  scheme = uc->nScheme;
373  }
374  *len += 1; /* ':' */
375  if (uc->lpszHostName) *len += 2; /* "//" */
376 
377  if (uc->lpszUserName)
378  {
379  *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
380  *len += 1; /* "@" */
381  }
382  else
383  {
384  if (uc->lpszPassword)
385  {
387  return FALSE;
388  }
389  }
390  if (uc->lpszPassword)
391  {
392  *len += 1; /* ":" */
393  *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
394  }
395  if (uc->lpszHostName)
396  {
397  *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
398 
399  if (!uses_default_port( scheme, uc->nPort ))
400  {
401  WCHAR port[sizeof("65535")];
402 
403  *len += sprintfW( port, formatW, uc->nPort );
404  *len += 1; /* ":" */
405  }
406  if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
407  }
408  if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
410  return TRUE;
411 }
412 
413 /***********************************************************************
414  * WinHttpCreateUrl (winhttp.@)
415  */
417 {
418  static const WCHAR formatW[] = {'%','u',0};
419  static const WCHAR twoslashW[] = {'/','/'};
420  DWORD len;
422 
423  TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
424 
425  if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
426  {
428  return FALSE;
429  }
430 
431  if (!calc_length( uc, flags, &len )) return FALSE;
432 
433  if (*required < len)
434  {
435  *required = len + 1;
437  return FALSE;
438  }
439  if (!url)
440  {
442  return FALSE;
443  }
444 
445  url[0] = 0;
446  *required = len;
447  if (uc->lpszScheme)
448  {
449  len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
450  memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
451  url += len;
452 
453  scheme = get_scheme( uc->lpszScheme, len );
454  }
455  else
456  {
457  const WCHAR *schemeW;
458  scheme = uc->nScheme;
459 
461 
462  schemeW = get_scheme_string( scheme );
463  len = strlenW( schemeW );
464  memcpy( url, schemeW, len * sizeof(WCHAR) );
465  url += len;
466  }
467 
468  /* all schemes are followed by at least a colon */
469  *url = ':';
470  url++;
471 
472  if (uc->lpszHostName)
473  {
474  memcpy( url, twoslashW, sizeof(twoslashW) );
475  url += sizeof(twoslashW) / sizeof(twoslashW[0]);
476  }
477  if (uc->lpszUserName)
478  {
479  len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
480  memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
481  url += len;
482 
483  if (uc->lpszPassword)
484  {
485  *url = ':';
486  url++;
487 
488  len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
489  memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
490  url += len;
491  }
492  *url = '@';
493  url++;
494  }
495  if (uc->lpszHostName)
496  {
497  len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
498  memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
499  url += len;
500 
501  if (!uses_default_port( scheme, uc->nPort ))
502  {
503  *url = ':';
504  url++;
505 
506  url += sprintfW( url, formatW, uc->nPort );
507  }
508 
509  /* add slash between hostname and path if necessary */
510  if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
511  {
512  *url = '/';
513  url++;
514  }
515  }
516  if (uc->lpszUrlPath)
517  {
518  len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
519  if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len );
520  else
521  {
522  memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
523  url += len;
524  }
525  }
526  if (uc->lpszExtraInfo)
527  {
529  if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len );
530  else
531  {
532  memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
533  url += len;
534  }
535  }
536  *url = 0;
538  return TRUE;
539 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
LPWSTR lpszExtraInfo
Definition: winhttp.h:478
DWORD dwHostNameLength
Definition: winhttp.h:470
LPWSTR lpszUrlPath
Definition: winhttp.h:476
#define TRUE
Definition: types.h:120
static DWORD copy_escape(WCHAR *dst, const WCHAR *src, DWORD len)
Definition: url.c:121
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
#define ERROR_SUCCESS
Definition: deptool.c:10
DWORD ret
Definition: url.c:448
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
DWORD dwUserNameLength
Definition: winhttp.h:473
static BOOL calc_length(URL_COMPONENTS *uc, DWORD flags, LPDWORD len)
Definition: url.c:356
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
static WCHAR * escape_url(LPCWSTR url, DWORD *len)
Definition: url.c:144
#define strtolW(s, e, b)
Definition: unicode.h:33
#define str_len
Definition: treelist.c:89
static DWORD set_component(WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow)
Definition: url.c:37
DWORD scheme
static INTERNET_SCHEME get_scheme(const WCHAR *scheme, DWORD len)
Definition: url.c:324
DWORD dwUrlPathLength
Definition: winhttp.h:477
#define strncmpiW(s1, s2, n)
Definition: unicode.h:40
static const char hex[16]
Definition: profile.c:123
static void * heap_alloc(size_t len)
Definition: appwiz.h:65
#define INTERNET_DEFAULT_HTTP_PORT
Definition: winhttp.h:36
WINE_UNICODE_INLINE int strncmpW(const WCHAR *str1, const WCHAR *str2, int n)
Definition: unicode.h:235
WORD INTERNET_PORT
Definition: winhttp.h:38
DWORD dwSchemeLength
Definition: winhttp.h:467
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
unsigned int BOOL
Definition: ntddk_ex.h:94
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static BOOL uses_default_port(INTERNET_SCHEME scheme, INTERNET_PORT port)
Definition: url.c:338
INTERNET_SCHEME nScheme
Definition: winhttp.h:468
WINE_DEFAULT_DEBUG_CHANNEL(shell)
static const WCHAR scheme_http[]
Definition: url.c:34
BOOL WINAPI WinHttpCrackUrl(LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc)
Definition: url.c:183
#define ICU_ESCAPE
Definition: winhttp.h:48
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwExtraInfoLength
Definition: winhttp.h:479
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define ERROR_WINHTTP_INVALID_URL
Definition: winhttp.h:191
INTERNET_SCHEME
Definition: wininet.h:135
static DWORD comp_length(DWORD len, DWORD flags, WCHAR *comp)
Definition: url.c:345
#define WINAPI
Definition: msvc.h:8
const GLubyte * c
Definition: glext.h:8905
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLbitfield flags
Definition: glext.h:7161
#define ERROR_WINHTTP_UNRECOGNIZED_SCHEME
Definition: winhttp.h:192
WINE_UNICODE_INLINE int isxdigitW(WCHAR wc)
Definition: unicode.h:175
DWORD dwStructSize
Definition: winhttp.h:465
const char * url
Definition: url.c:447
INTERNET_PORT nPort
Definition: winhttp.h:471
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
GLenum src
Definition: glext.h:6340
#define err(...)
LPWSTR lpszUserName
Definition: winhttp.h:472
GLsizei const GLfloat * value
Definition: glext.h:6069
LPWSTR lpszHostName
Definition: winhttp.h:469
#define debugstr_wn
Definition: kernel32.h:33
WINE_UNICODE_INLINE int isalnumW(WCHAR wc)
Definition: unicode.h:190
static const WCHAR * get_scheme_string(INTERNET_SCHEME scheme)
Definition: url.c:331
WINE_UNICODE_INLINE WCHAR * strrchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:254
#define INTERNET_DEFAULT_HTTPS_PORT
Definition: winhttp.h:37
BOOL WINAPI WinHttpCreateUrl(LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required)
Definition: url.c:416
static WCHAR * decode_url(LPCWSTR url, DWORD *len)
Definition: url.c:62
WINE_UNICODE_INLINE WCHAR * strcpyW(WCHAR *dst, const WCHAR *src)
Definition: unicode.h:219
LPWSTR lpszPassword
Definition: winhttp.h:474
GLenum GLenum dst
Definition: glext.h:6340
#define sprintfW
Definition: unicode.h:58
WINE_UNICODE_INLINE int isdigitW(WCHAR wc)
Definition: unicode.h:170
DWORD dwPasswordLength
Definition: winhttp.h:475
static DWORD parse_port(const WCHAR *str, DWORD len, INTERNET_PORT *ret)
Definition: url.c:167
uint32_t * LPDWORD
Definition: typedefs.h:57
static const WCHAR scheme_https[]
Definition: url.c:35
#define ICU_DECODE
Definition: winhttp.h:291
void set_last_error(DWORD error)
Definition: session.c:59
void exit(int exitcode)
Definition: _exit.c:33
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
WINE_UNICODE_INLINE WCHAR * memchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:295
USHORT port
Definition: uri.c:227
static BOOL need_escape(WCHAR c)
Definition: url.c:90
LPWSTR lpszScheme
Definition: winhttp.h:466
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
static BOOL heap_free(void *mem)
Definition: appwiz.h:75
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10