ReactOS  0.4.15-dev-1200-gc3b3fcd
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 "ws2tcpip.h"
21 #include <stdarg.h>
22 
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "winhttp.h"
27 #include "shlwapi.h"
28 
29 #include "wine/debug.h"
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 {
41 };
42 
43 static DWORD set_component( struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow )
44 {
45  if (*comp->str && !*comp->len) return ERROR_INVALID_PARAMETER;
46  if (!*comp->len) return ERROR_SUCCESS;
47  if (!*comp->str)
48  {
49  if (len && *comp->len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER;
50  *comp->str = value;
51  *comp->len = len;
52  }
53  else
54  {
55  if (len >= *comp->len)
56  {
57  *comp->len = len + 1;
58  *overflow = TRUE;
59  return ERROR_SUCCESS;
60  }
61  memcpy( *comp->str, value, len * sizeof(WCHAR) );
62  (*comp->str)[len] = 0;
63  *comp->len = len;
64  }
65  return ERROR_SUCCESS;
66 }
67 
69 {
70  const WCHAR *p = url;
71  WCHAR hex[3], *q, *ret;
72 
73  if (!(ret = heap_alloc( *len * sizeof(WCHAR) ))) return NULL;
74  q = ret;
75  while (*len > 0)
76  {
77  if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
78  {
79  hex[0] = p[1];
80  hex[1] = p[2];
81  hex[2] = 0;
82  *q++ = strtolW( hex, NULL, 16 );
83  p += 3;
84  *len -= 3;
85  }
86  else
87  {
88  *q++ = *p++;
89  *len -= 1;
90  }
91  }
92  *len = q - ret;
93  return ret;
94 }
95 
96 static inline BOOL need_escape( WCHAR ch )
97 {
98  static const WCHAR escapes[] = {' ','"','#','%','<','>','[','\\',']','^','`','{','|','}','~',0};
99  const WCHAR *p = escapes;
100 
101  if (ch <= 31 || ch >= 127) return TRUE;
102  while (*p)
103  {
104  if (ch == *p++) return TRUE;
105  }
106  return FALSE;
107 }
108 
109 static BOOL escape_string( const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len )
110 {
111  static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
112  WCHAR *p = dst;
113  DWORD i;
114 
115  *dst_len = src_len;
116  for (i = 0; i < src_len; i++)
117  {
118  if (src[i] > 0xff) return FALSE;
119  if (need_escape( src[i] ))
120  {
121  if (dst)
122  {
123  p[0] = '%';
124  p[1] = hex[(src[i] >> 4) & 0xf];
125  p[2] = hex[src[i] & 0xf];
126  p += 3;
127  }
128  *dst_len += 2;
129  }
130  else if (dst) *p++ = src[i];
131  }
132 
133  if (dst) dst[*dst_len] = 0;
134  return TRUE;
135 }
136 
137 static DWORD escape_url( const WCHAR *url, DWORD *len, WCHAR **ret )
138 {
139  const WCHAR *p;
140  DWORD len_base, len_path;
141 
142  if ((p = strrchrW( url, '/' )))
143  {
144  len_base = p - url;
145  if (!escape_string( p, *len - len_base, NULL, &len_path )) return ERROR_INVALID_PARAMETER;
146  }
147  else
148  {
149  len_base = *len;
150  len_path = 0;
151  }
152 
153  if (!(*ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
154  memcpy( *ret, url, len_base * sizeof(WCHAR) );
155 
156  if (p) escape_string( p, *len - (p - url), *ret + len_base, &len_path );
157  (*ret)[len_base + len_path] = 0;
158 
159  *len = len_base + len_path;
160  return ERROR_SUCCESS;
161 }
162 
164 {
165  const WCHAR *p = str;
166  DWORD port = 0;
167  while (len && isdigitW( *p ))
168  {
169  if ((port = port * 10 + *p - '0') > 65535) return ERROR_WINHTTP_INVALID_URL;
170  p++; len--;
171  }
172  *ret = port;
173  return ERROR_SUCCESS;
174 }
175 
176 /***********************************************************************
177  * WinHttpCrackUrl (winhttp.@)
178  */
180 {
181  WCHAR *p, *q, *r, *url_decoded = NULL, *url_escaped = NULL;
184  BOOL overflow = FALSE;
185  DWORD err;
186 
187  TRACE("%s, %d, %x, %p\n", debugstr_wn(url, len), len, flags, uc);
188 
189  if (!url || !uc || uc->dwStructSize != sizeof(*uc))
190  {
192  return FALSE;
193  }
194  if (!len) len = strlenW( url );
195 
196  if (flags & ICU_ESCAPE)
197  {
198  if ((err = escape_url( url, &len, &url_escaped )))
199  {
200  SetLastError( err );
201  return FALSE;
202  }
203  url = url_escaped;
204  }
205  else if (flags & ICU_DECODE)
206  {
207  if (!(url_decoded = decode_url( url, &len )))
208  {
210  return FALSE;
211  }
212  url = url_decoded;
213  }
214  if (!(p = strchrW( url, ':' )))
215  {
217  return FALSE;
218  }
220  else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme_number = INTERNET_SCHEME_HTTPS;
221  else
222  {
224  goto exit;
225  }
226 
227  scheme.str = &uc->lpszScheme;
228  scheme.len = &uc->dwSchemeLength;
229 
230  if ((err = set_component( &scheme, (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 
245  username.str = &uc->lpszUserName;
246  username.len = &uc->dwUserNameLength;
247 
248  password.str = &uc->lpszPassword;
249  password.len = &uc->dwPasswordLength;
250 
251  if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
252  {
253 
254  if ((r = memchrW( p, ':', q - p )))
255  {
256  if ((err = set_component( &username, p, r - p, flags, &overflow ))) goto exit;
257  r++;
258  if ((err = set_component( &password, r, q - r, flags, &overflow ))) goto exit;
259  }
260  else
261  {
262  if ((err = set_component( &username, p, q - p, flags, &overflow ))) goto exit;
263  if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
264  }
265  p = q + 1;
266  }
267  else
268  {
269  if ((err = set_component( &username, NULL, 0, flags, &overflow ))) goto exit;
270  if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
271  }
272 
273  hostname.str = &uc->lpszHostName;
274  hostname.len = &uc->dwHostNameLength;
275 
276  path.str = &uc->lpszUrlPath;
277  path.len = &uc->dwUrlPathLength;
278 
279  extra.str = &uc->lpszExtraInfo;
280  extra.len = &uc->dwExtraInfoLength;
281 
282  if ((q = memchrW( p, '/', len - (p - url) )))
283  {
284  if ((r = memchrW( p, ':', q - p )))
285  {
286  if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
287  r++;
288  if ((err = parse_port( r, q - r, &uc->nPort ))) goto exit;
289  }
290  else
291  {
292  if ((err = set_component( &hostname, p, q - p, flags, &overflow ))) goto exit;
295  }
296 
297  if ((r = memchrW( q, '?', len - (q - url) )))
298  {
299  if (*extra.len)
300  {
301  if ((err = set_component( &path, q, r - q, flags, &overflow ))) goto exit;
302  if ((err = set_component( &extra, r, len - (r - url), flags, &overflow ))) goto exit;
303  }
304  else if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
305  }
306  else
307  {
308  if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
309  if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
310  }
311  }
312  else
313  {
314  if ((r = memchrW( p, ':', len - (p - url) )))
315  {
316  if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
317  r++;
318  if ((err = parse_port( r, len - (r - url), &uc->nPort ))) goto exit;
319  }
320  else
321  {
322  if ((err = set_component( &hostname, p, len - (p - url), flags, &overflow ))) goto exit;
325  }
326  if ((err = set_component( &path, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
327  if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
328  }
329 
330  TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn(*scheme.str, *scheme.len),
331  debugstr_wn(*hostname.str, *hostname.len ), uc->nPort, debugstr_wn(*path.str, *path.len),
332  debugstr_wn(*extra.str, *extra.len));
333 
334 exit:
335  if (!err)
336  {
337  if (overflow) err = ERROR_INSUFFICIENT_BUFFER;
338  uc->nScheme = scheme_number;
339  }
340  heap_free( url_decoded );
341  heap_free( url_escaped );
342  SetLastError( err );
343  return !err;
344 }
345 
347 {
350  return 0;
351 }
352 
354 {
355  if (scheme == INTERNET_SCHEME_HTTP) return scheme_http;
357  return NULL;
358 }
359 
361 {
364  return FALSE;
365 }
366 
368 {
369  DWORD ret;
370  unsigned int i;
371 
372  ret = len ? len : strlenW( comp );
373  if (!(flags & ICU_ESCAPE)) return ret;
374  for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
375  return ret;
376 }
377 
379 {
380  static const WCHAR formatW[] = {'%','u',0};
382 
383  *len = 0;
384  if (uc->lpszScheme)
385  {
386  DWORD scheme_len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
387  *len += scheme_len;
388  scheme = get_scheme( uc->lpszScheme, scheme_len );
389  }
390  else
391  {
392  scheme = uc->nScheme;
395  }
396  *len += 3; /* "://" */
397 
398  if (uc->lpszUserName)
399  {
401  *len += 1; /* "@" */
402  }
403  else
404  {
405  if (uc->lpszPassword)
406  {
408  return FALSE;
409  }
410  }
411  if (uc->lpszPassword)
412  {
413  *len += 1; /* ":" */
415  }
416  if (uc->lpszHostName)
417  {
419 
420  if (!uses_default_port( scheme, uc->nPort ))
421  {
422  WCHAR port[sizeof("65535")];
423 
424  *len += sprintfW( port, formatW, uc->nPort );
425  *len += 1; /* ":" */
426  }
427  if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
428  }
431  return TRUE;
432 }
433 
434 /***********************************************************************
435  * WinHttpCreateUrl (winhttp.@)
436  */
438 {
439  static const WCHAR formatW[] = {'%','u',0};
440  DWORD len, len_escaped;
442 
443  TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
444 
445  if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
446  {
448  return FALSE;
449  }
450 
451  if (!get_url_length( uc, flags, &len )) return FALSE;
452 
453  if (*required < len)
454  {
455  *required = len + 1;
457  return FALSE;
458  }
459  if (!url)
460  {
462  return FALSE;
463  }
464 
465  url[0] = 0;
466  *required = len;
467  if (uc->lpszScheme)
468  {
469  len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
470  memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
471  url += len;
472 
473  scheme = get_scheme( uc->lpszScheme, len );
474  }
475  else
476  {
477  const WCHAR *schemeW;
478  scheme = uc->nScheme;
479 
481 
482  schemeW = get_scheme_string( scheme );
483  len = strlenW( schemeW );
484  memcpy( url, schemeW, len * sizeof(WCHAR) );
485  url += len;
486  }
487 
488  *url++ = ':';
489  *url++ = '/';
490  *url++ = '/';
491 
492  if (uc->lpszUserName)
493  {
495  memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
496  url += len;
497 
498  if (uc->lpszPassword)
499  {
500  *url++ = ':';
502  memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
503  url += len;
504  }
505  *url++ = '@';
506  }
507  if (uc->lpszHostName)
508  {
510  memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
511  url += len;
512 
513  if (!uses_default_port( scheme, uc->nPort ))
514  {
515  *url++ = ':';
516  url += sprintfW( url, formatW, uc->nPort );
517  }
518 
519  /* add slash between hostname and path if necessary */
520  if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
521  {
522  *url++ = '/';
523  }
524  }
525  if (uc->lpszUrlPath)
526  {
528  if (flags & ICU_ESCAPE)
529  {
530  if (!escape_string( uc->lpszUrlPath, len, url, &len_escaped ))
531  {
533  return FALSE;
534  }
535  url += len_escaped;
536  }
537  else
538  {
539  memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
540  url += len;
541  }
542  }
543  if (uc->lpszExtraInfo)
544  {
546  if (flags & ICU_ESCAPE)
547  {
548  if (!escape_string( uc->lpszExtraInfo, len, url, &len_escaped ))
549  {
551  return FALSE;
552  }
553  url += len_escaped;
554  }
555  else
556  {
557  memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
558  url += len;
559  }
560  }
561  *url = 0;
563  return TRUE;
564 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static BOOL get_url_length(URL_COMPONENTS *uc, DWORD flags, DWORD *len)
Definition: url.c:378
LPWSTR lpszExtraInfo
Definition: winhttp.h:478
DWORD dwHostNameLength
Definition: winhttp.h:470
LPWSTR lpszUrlPath
Definition: winhttp.h:476
WINE_UNICODE_INLINE unsigned int strlenW(const WCHAR *str)
Definition: unicode.h:212
static DWORD escape_url(const WCHAR *url, DWORD *len, WCHAR **ret)
Definition: url.c:137
#define ERROR_SUCCESS
Definition: deptool.c:10
DWORD ret
Definition: url.c:452
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define TRUE
Definition: types.h:120
DWORD dwUserNameLength
Definition: winhttp.h:473
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
WINE_UNICODE_INLINE WCHAR * strchrW(const WCHAR *str, WCHAR ch)
Definition: unicode.h:248
#define strtolW(s, e, b)
Definition: unicode.h:33
static DWORD get_comp_length(DWORD len, DWORD flags, WCHAR *comp)
Definition: url.c:367
DWORD scheme
static INTERNET_SCHEME get_scheme(const WCHAR *scheme, DWORD len)
Definition: url.c:346
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
char * hostname
Definition: ftp.c:88
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
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
URL_SCHEME scheme_number
Definition: url.c:64
const WCHAR * str
smooth NULL
Definition: ftsmooth.c:416
static BOOL uses_default_port(INTERNET_SCHEME scheme, INTERNET_PORT port)
Definition: url.c:360
INTERNET_SCHEME nScheme
Definition: winhttp.h:468
WINE_DEFAULT_DEBUG_CHANNEL(shell)
static const WCHAR scheme_http[]
Definition: url.c:34
static WCHAR username[]
Definition: url.c:32
BOOL WINAPI WinHttpCrackUrl(LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc)
Definition: url.c:179
#define ICU_ESCAPE
Definition: winhttp.h:48
#define TRACE(s)
Definition: solgame.cpp:4
static BOOL escape_string(const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len)
Definition: url.c:109
Definition: id3.c:95
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
#define WINAPI
Definition: msvc.h:6
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:611
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
static DWORD set_component(struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow)
Definition: url.c:43
DWORD dwStructSize
Definition: winhttp.h:465
const char * url
Definition: url.c:451
T1_FIELD_DICT_PRIVATE password
Definition: t1tokens.h:64
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
static const WCHAR * get_scheme_string(INTERNET_SCHEME scheme)
Definition: url.c:353
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:437
static WCHAR * decode_url(LPCWSTR url, DWORD *len)
Definition: url.c:68
LPWSTR lpszPassword
Definition: winhttp.h:474
static BOOL need_escape(WCHAR ch)
Definition: url.c:96
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 * len
Definition: url.c:40
DWORD dwPasswordLength
Definition: winhttp.h:475
static DWORD parse_port(const WCHAR *str, DWORD len, INTERNET_PORT *ret)
Definition: url.c:163
uint32_t * LPDWORD
Definition: typedefs.h:59
static const WCHAR scheme_https[]
Definition: url.c:35
#define ICU_DECODE
Definition: winhttp.h:291
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:228
WCHAR ** str
Definition: url.c:39
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