Commit in reactos/lib/shlwapi on MAIN
clist.c+21.1 -> 1.2
istream.c+21.8 -> 1.9
ordinal.c+4-41.13 -> 1.14
path.c+94-651.8 -> 1.9
reg.c+8-71.11 -> 1.12
regstream.c+21.4 -> 1.5
thread.c+21.3 -> 1.4
url.c+364-5231.10 -> 1.11
winehq2ros.patch+169-281.7 -> 1.8
+647-627
9 modified files
Sync to Wine-20041019:
Francois Gouget <fgouget@free.fr>
- Don't define COBJMACROS in objbase.h.
- Update the Wine sources accordingly.
Robert Shearman <rob@codeweavers.com>
- Don't define GWL_USERDATA, GWL_ID, GWL_HWNDPARENT, GWL_HINSTANCE and
GWL_WNDPROC when compiling the Wine source.
Mike McCormack <mike@codeweavers.com>
- Fix some -Wsigned-compare warnings.
Huw Davies <huw@codeweavers.com>
- Rewrite PathCreateFromUrl.
- Implement PathSearchAndQualify.
- Fix UrlUnescapeW.
- PathIsURL should return TRUE even if a scheme is unknown.
- UrlEscape has different rules depending on the protocol.
- Added a load of tests.
- ParseURL is now documented, so move it into shlwapi.h.
Bill Medland <billmedland@mercuryspeed.com>
- Fix SHDeleteKey so that it will handle deleting a key with more than
one subkey.  Also includes test.
Steven Edwards <steven_ed4153@yahoo.com>
- Move URL_SCHEME typedef to match PSDK.

reactos/lib/shlwapi
clist.c 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- clist.c	9 Dec 2003 16:50:52 -0000	1.1
+++ clist.c	20 Oct 2004 16:49:27 -0000	1.2
@@ -20,6 +20,8 @@
 #include <stdarg.h>
 #include <string.h>
 
+#define COBJMACROS
+
 #include "windef.h"
 #include "winbase.h"
 #include "objbase.h"

reactos/lib/shlwapi
istream.c 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- istream.c	19 Sep 2004 10:46:48 -0000	1.8
+++ istream.c	20 Oct 2004 16:49:27 -0000	1.9
@@ -20,8 +20,10 @@
 #include <stdarg.h>
 #include <string.h>
 
+#define COBJMACROS
 #define NONAMELESSUNION
 #define NONAMELESSSTRUCT
+
 #include "windef.h"
 #include "winbase.h"
 #include "winerror.h"

reactos/lib/shlwapi
ordinal.c 1.13 -> 1.14
diff -u -r1.13 -r1.14
--- ordinal.c	24 Sep 2004 11:12:44 -0000	1.13
+++ ordinal.c	20 Oct 2004 16:49:27 -0000	1.14
@@ -576,8 +576,8 @@
     }
     memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
 
-    if(*buflen > lstrlenW(mystr)) {
-	*buflen = lstrlenW(mystr);
+    if(*buflen > strlenW(mystr)) {
+	*buflen = strlenW(mystr);
 	retval = S_OK;
     } else {
 	*buflen = 0;
@@ -2439,7 +2439,7 @@
     SetWindowLongA(hWnd, DWL_MSGRESULT, z);
 
     if (wndProc)
-      SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
+      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
   }
   return hWnd;
 }
@@ -2726,7 +2726,7 @@
     SetWindowLongA(hWnd, DWL_MSGRESULT, z);
 
     if (wndProc)
-      SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
+      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
   }
   return hWnd;
 }

reactos/lib/shlwapi
path.c 1.8 -> 1.9
diff -u -r1.8 -r1.9
--- path.c	24 Sep 2004 15:17:20 -0000	1.8
+++ path.c	20 Oct 2004 16:49:27 -0000	1.9
@@ -32,7 +32,7 @@
 #include "wingdi.h"
 #include "winuser.h"
 #include "winreg.h"
-#include "winnls.h"
+#include "winternl.h"
 #define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "wine/debug.h"
@@ -3116,8 +3116,11 @@
  */
 BOOL WINAPI PathSearchAndQualifyA(LPCSTR lpszPath, LPSTR lpszBuf, UINT cchBuf)
 {
-  FIXME("(%s,%p,0x%08x)-stub\n", debugstr_a(lpszPath), lpszBuf, cchBuf);
-  return FALSE;
+    TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszPath), lpszBuf, cchBuf);
+
+    if(SearchPathA(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL))
+        return TRUE;
+    return !!GetFullPathNameA(lpszPath, cchBuf, lpszBuf, NULL);
 }
 
 /*************************************************************************
@@ -3127,8 +3130,11 @@
  */
 BOOL WINAPI PathSearchAndQualifyW(LPCWSTR lpszPath, LPWSTR lpszBuf, UINT cchBuf)
 {
-  FIXME("(%s,%p,0x%08x)-stub\n", debugstr_w(lpszPath), lpszBuf, cchBuf);
-  return FALSE;
+    TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszPath), lpszBuf, cchBuf);
+
+    if(SearchPathW(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL))
+        return TRUE;
+    return !!GetFullPathNameW(lpszPath, cchBuf, lpszBuf, NULL);
 }
 
 /*************************************************************************
@@ -3200,6 +3206,42 @@
 /*************************************************************************
  * PathCreateFromUrlA   [SHLWAPI.@]
  *
+ * See PathCreateFromUrlW
+ */
+HRESULT WINAPI PathCreateFromUrlA(LPCSTR pszUrl, LPSTR pszPath,
+                                  LPDWORD pcchPath, DWORD dwReserved)
+{
+    WCHAR bufW[MAX_PATH];
+    WCHAR *pathW = bufW;
+    UNICODE_STRING urlW;
+    HRESULT ret;
+    DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
+
+    if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
+        return E_INVALIDARG;
+    if((ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved)) == E_POINTER) {
+        pathW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
+        ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved);
+    }
+    if(ret == S_OK) {
+        RtlUnicodeToMultiByteSize(&lenA, pathW, lenW * sizeof(WCHAR));
+        if(*pcchPath > lenA) {
+            RtlUnicodeToMultiByteN(pszPath, *pcchPath - 1, &lenA, pathW, lenW * sizeof(WCHAR));
+            pszPath[lenA] = 0;
+            *pcchPath = lenA;
+        } else {
+            *pcchPath = lenA + 1;
+            ret = E_POINTER;
+        }
+    }
+    if(pathW != bufW) HeapFree(GetProcessHeap(), 0, pathW);
+    RtlFreeUnicodeString(&urlW);
+    return ret;
+}
+
+/*************************************************************************
+ * PathCreateFromUrlW   [SHLWAPI.@]
+ *
  * Create a path from a URL
  *
  * PARAMS
@@ -3212,79 +3254,66 @@
  *  Success: S_OK. lpszPath contains the URL in path format,
  *  Failure: An HRESULT error code such as E_INVALIDARG.
  */
-HRESULT WINAPI PathCreateFromUrlA(LPCSTR lpszUrl, LPSTR lpszPath,
-                                  LPDWORD pcchPath, DWORD dwFlags)
+HRESULT WINAPI PathCreateFromUrlW(LPCWSTR pszUrl, LPWSTR pszPath,
+                                  LPDWORD pcchPath, DWORD dwReserved)
 {
-  LPSTR pszPathPart;
-  TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_a(lpszUrl), lpszPath, pcchPath, dwFlags);
+    static const WCHAR file_colon[] = { 'f','i','l','e',':',0 };
+    HRESULT hr;
+    DWORD nslashes = 0;
+    WCHAR *ptr;
 
-  if (!lpszUrl || !lpszPath || !pcchPath || !*pcchPath)
-    return E_INVALIDARG;
+    TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_w(pszUrl), pszPath, pcchPath, dwReserved);
 
-  pszPathPart = StrChrA(lpszUrl, ':');
-  if ((((pszPathPart - lpszUrl) == 1) && isalpha(*lpszUrl)) ||
-         !lstrcmpA(lpszUrl, "file:"))
-  {
-    return UrlUnescapeA(pszPathPart, lpszPath, pcchPath, dwFlags);
-  }
-    /* extracts thing prior to : in pszURL and checks against:
-     *   https
-     *   shell
-     *   local
-     *   about  - if match returns E_INVALIDARG
-     */
+    if (!pszUrl || !pszPath || !pcchPath || !*pcchPath)
+        return E_INVALIDARG;
 
-  return E_INVALIDARG;
-}
 
-/*************************************************************************
- * PathCreateFromUrlW   [SHLWAPI.@]
- *
- * See PathCreateFromUrlA.
- */
-HRESULT WINAPI PathCreateFromUrlW(LPCWSTR lpszUrl, LPWSTR lpszPath,
-                                  LPDWORD pcchPath, DWORD dwFlags)
-{
-  static const WCHAR stemp[] = { 'f','i','l','e',':','/','/','/',0 };
-  LPWSTR pwszPathPart;
-  HRESULT hr;
+    if (strncmpW(pszUrl, file_colon, 5))
+        return E_INVALIDARG;
+    pszUrl += 5;
 
-  TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_w(lpszUrl), lpszPath, pcchPath, dwFlags);
+    while(*pszUrl == '/' || *pszUrl == '\\') {
+        nslashes++;
+        pszUrl++;
+    }
 
-  if (!lpszUrl || !lpszPath || !pcchPath || !*pcchPath)
-    return E_INVALIDARG;
+    if(isalphaW(*pszUrl) && (pszUrl[1] == ':' || pszUrl[1] == '|') && (pszUrl[2] == '/' || pszUrl[2] == '\\'))
+        nslashes = 0;
 
-  /* Path of the form file:///... */
-  if (!strncmpW(lpszUrl, stemp, 8))
-  {
-    lpszUrl += 8;
-  }
-  /* Path of the form file://... */
-  else if (!strncmpW(lpszUrl, stemp, 7))
-  {
-    lpszUrl += 7;
-  }
-  /* Path of the form file:... */
-  else if (!strncmpW(lpszUrl, stemp, 5))
-  {
-    lpszUrl += 5;
-  }
+    switch(nslashes) {
+    case 2:
+        pszUrl -= 2;
+        break;
+    case 0:
+        break;
+    default:
+        pszUrl -= 1;
+        break;
+    }
 
-  /* Ensure that path is of the form c:... or c|... */
-  if (lpszUrl[1] != ':' && lpszUrl[1] != '|' && isalphaW(*lpszUrl))
-    return E_INVALIDARG;
+    hr = UrlUnescapeW((LPWSTR)pszUrl, pszPath, pcchPath, 0);
+    if(hr != S_OK) return hr;
 
-  hr = UrlUnescapeW((LPWSTR) lpszUrl, lpszPath, pcchPath, dwFlags);
-  if (lpszPath[1] == '|')
-    lpszPath[1] = ':';
+    for(ptr = pszPath; *ptr; ptr++)
+        if(*ptr == '/') *ptr = '\\';
 
-  for (pwszPathPart = lpszPath; *pwszPathPart; pwszPathPart++)
-    if (*pwszPathPart == '/')
-      *pwszPathPart = '\\';
+    while(*pszPath == '\\')
+        pszPath++;
+ 
+    if(isalphaW(*pszPath) && pszPath[1] == '|' && pszPath[2] == '\\') /* c|\ -> c:\ */
+        pszPath[1] = ':';
+
+    if(nslashes == 2 && (ptr = strchrW(pszPath, '\\'))) { /* \\host\c:\ -> \\hostc:\ */
+        ptr++;
+        if(isalphaW(*ptr) && (ptr[1] == ':' || ptr[1] == '|') && ptr[2] == '\\') {
+            memmove(ptr - 1, ptr, (strlenW(ptr) + 1) * sizeof(WCHAR));
+            (*pcchPath)--;
+        }
+    }
 
-  TRACE("Returning %s\n",debugstr_w(lpszPath));
+    TRACE("Returning %s\n",debugstr_w(pszPath));
 
-  return hr;
+    return hr;
 }
 
 /*************************************************************************

reactos/lib/shlwapi
reg.c 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- reg.c	19 Sep 2004 10:46:48 -0000	1.11
+++ reg.c	20 Oct 2004 16:49:27 -0000	1.12
@@ -1298,7 +1298,7 @@
  */
 DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
 {
-  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
+  DWORD dwRet, dwMaxSubkeyLen = 0, dwSize;
   CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
   HKEY hSubKey = 0;
 
@@ -1307,8 +1307,8 @@
   dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
   if(!dwRet)
   {
-    /* Find how many subkeys there are */
-    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+    /* Find the maximum subkey length so that we can allocate a buffer */
+    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
                              &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
     if(!dwRet)
     {
@@ -1321,14 +1321,15 @@
         dwRet = ERROR_NOT_ENOUGH_MEMORY;
       else
       {
-        /* Recursively delete all the subkeys */
-        for(i = 0; i < dwKeyCount && !dwRet; i++)
+        while (dwRet == ERROR_SUCCESS)
         {
           dwSize = dwMaxSubkeyLen;
-          dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
-          if(!dwRet)
+          dwRet = RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL, NULL, NULL, NULL);
+          if (dwRet == ERROR_SUCCESS || dwRet == ERROR_MORE_DATA)
             dwRet = SHDeleteKeyA(hSubKey, lpszName);
         }
+        if (dwRet == ERROR_NO_MORE_ITEMS)
+          dwRet = ERROR_SUCCESS;
         if (lpszName != szNameBuf)
           HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
       }

reactos/lib/shlwapi
regstream.c 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- regstream.c	19 Sep 2004 10:46:48 -0000	1.4
+++ regstream.c	20 Oct 2004 16:49:27 -0000	1.5
@@ -22,6 +22,8 @@
 #include <stdarg.h>
 #include <string.h>
 
+#define COBJMACROS
+
 #include "winerror.h"
 #include "windef.h"
 #include "winbase.h"

reactos/lib/shlwapi
thread.c 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- thread.c	8 May 2004 13:49:05 -0000	1.3
+++ thread.c	20 Oct 2004 16:49:27 -0000	1.4
@@ -21,6 +21,8 @@
 #include <stdarg.h>
 #include <string.h>
 
+#define COBJMACROS
+
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"

reactos/lib/shlwapi
url.c 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- url.c	19 Sep 2004 10:46:48 -0000	1.10
+++ url.c	20 Oct 2004 16:49:27 -0000	1.11
@@ -30,6 +30,7 @@
 #include "wine/unicode.h"
 #include "wininet.h"
 #include "winreg.h"
+#include "winternl.h"
 #define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "wine/debug.h"
@@ -43,30 +44,6 @@
 /* The following schemes were identified in the native version of
  * SHLWAPI.DLL version 5.50
  */
-typedef enum {
-    URL_SCHEME_INVALID     = -1,
-    URL_SCHEME_UNKNOWN     =  0,
-    URL_SCHEME_FTP,
-    URL_SCHEME_HTTP,
-    URL_SCHEME_GOPHER,
-    URL_SCHEME_MAILTO,
-    URL_SCHEME_NEWS,
-    URL_SCHEME_NNTP,
-    URL_SCHEME_TELNET,
-    URL_SCHEME_WAIS,
-    URL_SCHEME_FILE,
-    URL_SCHEME_MK,
-    URL_SCHEME_HTTPS,
-    URL_SCHEME_SHELL,
-    URL_SCHEME_SNEWS,
-    URL_SCHEME_LOCAL,
-    URL_SCHEME_JAVASCRIPT,
-    URL_SCHEME_VBSCRIPT,
-    URL_SCHEME_ABOUT,
-    URL_SCHEME_RES,
-    URL_SCHEME_MAXVALUE
-} URL_SCHEME;
-
 typedef struct {
     URL_SCHEME  scheme_number;
     LPCSTR scheme_name;
@@ -116,24 +93,6 @@
     USERPASS,
 } WINE_URL_SCAN_TYPE;
 
-typedef struct {
-    INT     size;      /* [in]  (always 0x18)                       */
-    LPCSTR  ap1;       /* [out] start of scheme                     */
-    INT     sizep1;    /* [out] size of scheme (until colon)        */
-    LPCSTR  ap2;       /* [out] pointer following first colon       */
-    INT     sizep2;    /* [out] size of remainder                   */
-    INT     fcncde;    /* [out] function match of p1 (0 if unknown) */
-} UNKNOWN_SHLWAPI_1;
-
-typedef struct {
-    INT     size;      /* [in]  (always 0x18)                       */
-    LPCWSTR ap1;       /* [out] start of scheme                     */
-    INT     sizep1;    /* [out] size of scheme (until colon)        */
-    LPCWSTR ap2;       /* [out] pointer following first colon       */
-    INT     sizep2;    /* [out] size of remainder                   */
-    INT     fcncde;    /* [out] function match of p1 (0 if unknown) */
-} UNKNOWN_SHLWAPI_2;
-
 static const CHAR hexDigits[] = "0123456789ABCDEF";
 
 static const WCHAR fileW[] = {'f','i','l','e','\0'};
@@ -160,96 +119,6 @@
  0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB,
  0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
 
-static inline BOOL URL_NeedEscapeA(CHAR ch, DWORD dwFlags)
-{
-
-    if (isalnum(ch))
-        return FALSE;
-
-    if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
-        if(ch == ' ')
-	    return TRUE;
-	else
-	    return FALSE;
-    }
-
-    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
-	return TRUE;
-
-    if (ch <= 31 || ch >= 127)
-	return TRUE;
-
-    else {
-        switch (ch) {
-	case ' ':
-	case '<':
-	case '>':
-	case '\"':
-	case '{':
-	case '}':
-	case '|':
-/*	case '\\': */
-	case '^':
-	case ']':
-	case '[':
-	case '`':
-	case '&':
-	    return TRUE;
-
-	case '/':
-	case '?':
-	    if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
-	default:
-	    return FALSE;
-	}
-    }
-}
-
-static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags)
-{
-
-    if (isalnumW(ch))
-        return FALSE;
-
-    if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
-        if(ch == L' ')
-	    return TRUE;
-	else
-	    return FALSE;
-    }
-
-    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == L'%'))
-	return TRUE;
-
-    if (ch <= 31 || ch >= 127)
-	return TRUE;
-
-    else {
-        switch (ch) {
-	case L' ':
-	case L'<':
-	case L'>':
-	case L'\"':
-	case L'{':
-	case L'}':
-	case L'|':
-	case L'\\':
-	case L'^':
-	case L']':
-	case L'[':
-	case L'`':
-	case L'&':
-	    return TRUE;
-
-	case L'/':
-	case L'?':
-	    if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
-	default:
-	    return FALSE;
-	}
-    }
-}
-
 static BOOL URL_JustLocation(LPCWSTR str)
 {
     while(*str && (*str == L'/')) str++;
@@ -276,25 +145,25 @@
  *  Success: S_OK. y contains the parsed Url details.
  *  Failure: An HRESULT error code.
  */
-DWORD WINAPI ParseURLA(LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
+HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y)
 {
     DWORD cnt;
     const SHL_2_inet_scheme *inet_pro;
 
-    y->fcncde = URL_SCHEME_INVALID;
-    if (y->size != 0x18) return E_INVALIDARG;
+    y->nScheme = URL_SCHEME_INVALID;
+    if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
     /* FIXME: leading white space generates error of 0x80041001 which
      *        is undefined
      */
     if (*x <= ' ') return 0x80041001;
     cnt = 0;
-    y->sizep1 = 0;
-    y->ap1 = x;
+    y->cchProtocol = 0;
+    y->pszProtocol = x;
     while (*x) {
 	if (*x == ':') {
-	    y->sizep1 = cnt;
+	    y->cchProtocol = cnt;
 	    cnt = -1;
-	    y->ap2 = x+1;
+	    y->pszSuffix = x+1;
 	    break;
 	}
 	x++;
@@ -303,21 +172,21 @@
 
     /* check for no scheme in string start */
     /* (apparently schemes *must* be larger than a single character)  */
-    if ((*x == '\0') || (y->sizep1 <= 1)) {
-	y->ap1 = 0;
+    if ((*x == '\0') || (y->cchProtocol <= 1)) {
+	y->pszProtocol = NULL;
 	return 0x80041001;
     }
 
     /* found scheme, set length of remainder */
-    y->sizep2 = lstrlenA(y->ap2);
+    y->cchSuffix = lstrlenA(y->pszSuffix);
 
     /* see if known scheme and return indicator number */
-    y->fcncde = URL_SCHEME_UNKNOWN;
+    y->nScheme = URL_SCHEME_UNKNOWN;
     inet_pro = shlwapi_schemes;
     while (inet_pro->scheme_name) {
-	if (!strncasecmp(inet_pro->scheme_name, y->ap1,
-		    min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
-	    y->fcncde = inet_pro->scheme_number;
+	if (!strncasecmp(inet_pro->scheme_name, y->pszProtocol,
+		    min(y->cchProtocol, lstrlenA(inet_pro->scheme_name)))) {
+	    y->nScheme = inet_pro->scheme_number;
 	    break;
 	}
 	inet_pro++;
@@ -330,27 +199,27 @@
  *
  * Unicode version of ParseURLA.
  */
-DWORD WINAPI ParseURLW(LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
+HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
 {
     DWORD cnt;
     const SHL_2_inet_scheme *inet_pro;
     LPSTR cmpstr;
     INT len;
 
-    y->fcncde = URL_SCHEME_INVALID;
-    if (y->size != 0x18) return E_INVALIDARG;
+    y->nScheme = URL_SCHEME_INVALID;
+    if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
     /* FIXME: leading white space generates error of 0x80041001 which
      *        is undefined
      */
     if (*x <= L' ') return 0x80041001;
     cnt = 0;
-    y->sizep1 = 0;
-    y->ap1 = x;
+    y->cchProtocol = 0;
+    y->pszProtocol = x;
     while (*x) {
 	if (*x == L':') {
-	    y->sizep1 = cnt;
+	    y->cchProtocol = cnt;
 	    cnt = -1;
-	    y->ap2 = x+1;
+	    y->pszSuffix = x+1;
 	    break;
 	}
 	x++;
@@ -359,24 +228,24 @@
 
     /* check for no scheme in string start */
     /* (apparently schemes *must* be larger than a single character)  */
-    if ((*x == L'\0') || (y->sizep1 <= 1)) {
-	y->ap1 = 0;
+    if ((*x == L'\0') || (y->cchProtocol <= 1)) {
+	y->pszProtocol = NULL;
 	return 0x80041001;
     }
 
     /* found scheme, set length of remainder */
-    y->sizep2 = lstrlenW(y->ap2);
+    y->cchSuffix = lstrlenW(y->pszSuffix);
 
     /* see if known scheme and return indicator number */
-    len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
+    len = WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, 0, 0, 0, 0);
     cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len);
-    WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len, 0, 0);
-    y->fcncde = URL_SCHEME_UNKNOWN;
+    WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, cmpstr, len, 0, 0);
+    y->nScheme = URL_SCHEME_UNKNOWN;
     inet_pro = shlwapi_schemes;
     while (inet_pro->scheme_name) {
 	if (!strncasecmp(inet_pro->scheme_name, cmpstr,
 		    min(len, lstrlenA(inet_pro->scheme_name)))) {
-	    y->fcncde = inet_pro->scheme_number;
+	    y->nScheme = inet_pro->scheme_number;
 	    break;
 	}
 	inet_pro++;
@@ -459,7 +328,8 @@
     HRESULT hr = S_OK;
     DWORD EscapeFlags;
     LPWSTR lpszUrlCpy, wk1, wk2, mp, root;
-    INT nLen, nByteLen, state;
+    INT nByteLen, state;
+    DWORD nLen;
 
     TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized,
 	  pcchCanonicalized, dwFlags);
@@ -684,7 +554,7 @@
 			   LPWSTR pszCombined, LPDWORD pcchCombined,
 			   DWORD dwFlags)
 {
-    UNKNOWN_SHLWAPI_2 base, relative;
+    PARSEDURLW base, relative;
     DWORD myflags, sizeloc = 0;
     DWORD len, res1, res2, process_case = 0;
     LPWSTR work, preliminary, mbase, mrelative;
@@ -699,8 +569,8 @@
     if(!pszBase || !pszRelative || !pcchCombined)
 	return E_INVALIDARG;
 
-    base.size = 24;
-    relative.size = 24;
+    base.cbSize = sizeof(base);
+    relative.cbSize = sizeof(relative);
 
     /* Get space for duplicates of the input and the output */
     preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
@@ -728,7 +598,7 @@
     else do {
 
 	/* get size of location field (if it exists) */
-	work = (LPWSTR)base.ap2;
+	work = (LPWSTR)base.pszSuffix;
 	sizeloc = 0;
 	if (*work++ == L'/') {
 	    if (*work++ == L'/') {
@@ -736,23 +606,23 @@
 		 * it ends at next '/' or end of string.
 		 */
 		while(*work && (*work != L'/')) work++;
-		sizeloc = (DWORD)(work - base.ap2);
+		sizeloc = (DWORD)(work - base.pszSuffix);
 	    }
 	}
 
 	/* Change .sizep2 to not have the last leaf in it,
 	 * Note: we need to start after the location (if it exists)
 	 */
-	work = strrchrW((base.ap2+sizeloc), L'/');
+	work = strrchrW((base.pszSuffix+sizeloc), L'/');
 	if (work) {
-	    len = (DWORD)(work - base.ap2 + 1);
-	    base.sizep2 = len;
+	    len = (DWORD)(work - base.pszSuffix + 1);
+	    base.cchSuffix = len;
 	}
 	/*
 	 * At this point:
-	 *    .ap2      points to location (starting with '//')
-	 *    .sizep2   length of location (above) and rest less the last
-	 *              leaf (if any)
+	 *    .pszSuffix   points to location (starting with '//')
+	 *    .cchSuffix   length of location (above) and rest less the last
+	 *                 leaf (if any)
 	 *    sizeloc   length of location (above) up to but not including
 	 *              the last '/'
 	 */
@@ -761,8 +631,8 @@
 	if (res2) {
 	    /* no scheme in pszRelative */
 	    TRACE("no scheme detected in Relative\n");
-	    relative.ap2 = mrelative;  /* case 3,4,5 depends on this */
-	    relative.sizep2 = strlenW(mrelative);
+	    relative.pszSuffix = mrelative;  /* case 3,4,5 depends on this */
+	    relative.cchSuffix = strlenW(mrelative);
 	    if (*pszRelative  == L':') {
 		/* case that is either left alone or uses pszBase */
 		if (dwFlags & URL_PLUGGABLE_PROTOCOL) {
@@ -788,21 +658,21 @@
 		process_case = 4;
 		break;
 	    }
-	    process_case = (*base.ap2 == L'/') ? 5 : 3;
+	    process_case = (*base.pszSuffix == L'/') ? 5 : 3;
 	    break;
 	}
 
 	/* handle cases where pszRelative has scheme */
-	if ((base.sizep1 == relative.sizep1) &&
-	    (strncmpW(base.ap1, relative.ap1, base.sizep1) == 0)) {
+	if ((base.cchProtocol == relative.cchProtocol) &&
+	    (strncmpW(base.pszProtocol, relative.pszProtocol, base.cchProtocol) == 0)) {
 
 	    /* since the schemes are the same */
-	    if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+	    if ((*relative.pszSuffix == L'/') && (*(relative.pszSuffix+1) == L'/')) {
 		/* case where pszRelative replaces location and following */
 		process_case = 3;
 		break;
 	    }
-	    if (*relative.ap2 == L'/') {
+	    if (*relative.pszSuffix == L'/') {
 		/* case where pszRelative is root to location */
 		process_case = 4;
 		break;
@@ -811,7 +681,7 @@
 	    process_case = 5;
 	    break;
 	}
-	if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+	if ((*relative.pszSuffix == L'/') && (*(relative.pszSuffix+1) == L'/')) {
 	    /* case where pszRelative replaces scheme, location,
 	     * and following and handles PLUGGABLE
 	     */
@@ -839,7 +709,7 @@
 	      */
 	strcpyW(preliminary, mrelative);
 	if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
-	    URL_JustLocation(relative.ap2))
+	    URL_JustLocation(relative.pszSuffix))
 	    strcatW(preliminary, single_slash);
 	break;
 
@@ -847,11 +717,11 @@
 	      * Return the pszBase scheme with pszRelative. Basically
 	      * keeps the scheme and replaces the domain and following.
 	      */
-	strncpyW(preliminary, base.ap1, base.sizep1 + 1);
-	work = preliminary + base.sizep1 + 1;
-	strcpyW(work, relative.ap2);
+	strncpyW(preliminary, base.pszProtocol, base.cchProtocol + 1);
+	work = preliminary + base.cchProtocol + 1;
+	strcpyW(work, relative.pszSuffix);
 	if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
-	    URL_JustLocation(relative.ap2))
+	    URL_JustLocation(relative.pszSuffix))
 	    strcatW(work, single_slash);
 	break;
 
@@ -860,22 +730,22 @@
 	      * after the location is pszRelative. (Replace document
 	      * from root on.)
 	      */
-	strncpyW(preliminary, base.ap1, base.sizep1+1+sizeloc);
-	work = preliminary + base.sizep1 + 1 + sizeloc;
+	strncpyW(preliminary, base.pszProtocol, base.cchProtocol+1+sizeloc);
+	work = preliminary + base.cchProtocol + 1 + sizeloc;
 	if (dwFlags & URL_PLUGGABLE_PROTOCOL)
 	    *(work++) = L'/';
-	strcpyW(work, relative.ap2);
+	strcpyW(work, relative.pszSuffix);
 	break;
 
     case 5:  /*
 	      * Return the pszBase without its document (if any) and
 	      * append pszRelative after its scheme.
 	      */
-	strncpyW(preliminary, base.ap1, base.sizep1+1+base.sizep2);
-	work = preliminary + base.sizep1+1+base.sizep2 - 1;
+	strncpyW(preliminary, base.pszProtocol, base.cchProtocol+1+base.cchSuffix);
+	work = preliminary + base.cchProtocol+1+base.cchSuffix - 1;
 	if (*work++ != L'/')
 	    *(work++) = L'/';
-	strcpyW(work, relative.ap2);
+	strcpyW(work, relative.pszSuffix);
 	break;
 
     default:
@@ -898,6 +768,107 @@
 
 /*************************************************************************
  *      UrlEscapeA	[SHLWAPI.@]
+ */
+
+HRESULT WINAPI UrlEscapeA(
+	LPCSTR pszUrl,
+	LPSTR pszEscaped,
+	LPDWORD pcchEscaped,
+	DWORD dwFlags)
+{
+    WCHAR bufW[INTERNET_MAX_URL_LENGTH];
+    WCHAR *escapedW = bufW;
+    UNICODE_STRING urlW;
+    HRESULT ret;
+    DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
+
+    if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
+        return E_INVALIDARG;
+    if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
+        escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
+        ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
+    }
+    if(ret == S_OK) {
+        RtlUnicodeToMultiByteSize(&lenA, escapedW, lenW * sizeof(WCHAR));
+        if(*pcchEscaped > lenA) {
+            RtlUnicodeToMultiByteN(pszEscaped, *pcchEscaped - 1, &lenA, escapedW, lenW * sizeof(WCHAR));
+            pszEscaped[lenA] = 0;
+            *pcchEscaped = lenA;
+        } else {
+            *pcchEscaped = lenA + 1;
+            ret = E_POINTER;
+        }
+    }
+    if(escapedW != bufW) HeapFree(GetProcessHeap(), 0, escapedW);
+    RtlFreeUnicodeString(&urlW);
+    return ret;
+}
+
+#define WINE_URL_BASH_AS_SLASH    0x01
+#define WINE_URL_COLLAPSE_SLASHES 0x02
+#define WINE_URL_ESCAPE_SLASH     0x04
+#define WINE_URL_ESCAPE_HASH      0x08
+#define WINE_URL_ESCAPE_QUESTION  0x10
+#define WINE_URL_STOP_ON_HASH     0x20
+#define WINE_URL_STOP_ON_QUESTION 0x40
+
+static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags, DWORD int_flags)
+{
+
+    if (isalnumW(ch))
+        return FALSE;
+
+    if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
+        if(ch == ' ')
+	    return TRUE;
+	else
+	    return FALSE;
+    }
+
+    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
+	return TRUE;
+
+    if (ch <= 31 || ch >= 127)
+	return TRUE;
+
+    else {
+        switch (ch) {
+	case ' ':
+	case '<':
+	case '>':
+	case '\"':
+	case '{':
+	case '}':
+	case '|':
+	case '\\':
+	case '^':
+	case ']':
+	case '[':
+	case '`':
+	case '&':
+	    return TRUE;
+
+	case '/':
+            if (int_flags & WINE_URL_ESCAPE_SLASH) return TRUE;
+            return FALSE;
+
+	case '?':
+	    if (int_flags & WINE_URL_ESCAPE_QUESTION) return TRUE;
+            return FALSE;
+
+        case '#':
+            if (int_flags & WINE_URL_ESCAPE_HASH) return TRUE;
+            return FALSE;
+
+	default:
+	    return FALSE;
+	}
+    }
+}
+
+
+/*************************************************************************
+ *      UrlEscapeW	[SHLWAPI.@]
  *
  * Converts unsafe characters in a Url into escape sequences.
  *
@@ -912,12 +883,12 @@
  *           contains its length.
  *  Failure: E_POINTER, if pszEscaped is not large enough. In this case
  *           pcchEscaped is set to the required length.
-
+ *
  * Converts unsafe characters into their escape sequences.
  *
  * NOTES
  * - By default this function stops converting at the first '?' or
- *  '#' character (MSDN does not document this).
+ *  '#' character.
  * - If dwFlags contains URL_ESCAPE_SPACES_ONLY then only spaces are
  *   converted, but the conversion continues past a '?' or '#'.
  * - Note that this function did not work well (or at all) in shlwapi version 4.
@@ -929,82 +900,6 @@
  *|     URL_ESCAPE_SEGMENT_ONLY
  *|     URL_ESCAPE_PERCENT
  */
-HRESULT WINAPI UrlEscapeA(
-	LPCSTR pszUrl,
-	LPSTR pszEscaped,
-	LPDWORD pcchEscaped,
-	DWORD dwFlags)
-{
-    LPCSTR src;
-    DWORD needed = 0, ret;
-    BOOL stop_escaping = FALSE;
-    char next[3], *dst = pszEscaped;
-    INT len;
-
-    TRACE("(%s %p %lx 0x%08lx)\n", debugstr_a(pszUrl), pszEscaped,
-	  pcchEscaped?*pcchEscaped:0, dwFlags);
-
-    if(!pszUrl || !pszEscaped || !pcchEscaped)
-	return E_INVALIDARG;
-
-    if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
-		   URL_ESCAPE_SEGMENT_ONLY |
-		   URL_DONT_ESCAPE_EXTRA_INFO |
-		   URL_ESCAPE_PERCENT))
-        FIXME("Unimplemented flags: %08lx\n", dwFlags);
-
-    /* fix up flags */
-    if (dwFlags & URL_ESCAPE_SPACES_ONLY)
-	/* if SPACES_ONLY specified, reset the other controls */
-	dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO |
-		     URL_ESCAPE_PERCENT |
-		     URL_ESCAPE_SEGMENT_ONLY);
-
-    else
-	/* if SPACES_ONLY *not* specified then assume DONT_ESCAPE_EXTRA_INFO */
-	dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
-
-    for(src = pszUrl; *src; src++) {
-        if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
-	   (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
-	   (*src == '#' || *src == '?'))
-	    stop_escaping = TRUE;
-
-	if(URL_NeedEscapeA(*src, dwFlags) && stop_escaping == FALSE) {
-	    /* TRACE("escaping %c\n", *src); */
-	    next[0] = '%';
-	    next[1] = hexDigits[(*src >> 4) & 0xf];
-	    next[2] = hexDigits[*src & 0xf];
-	    len = 3;
-	} else {
-	    /* TRACE("passing %c\n", *src); */
-	    next[0] = *src;
-	    len = 1;
-	}
-
-	if(needed + len <= *pcchEscaped) {
-	    memcpy(dst, next, len);
-	    dst += len;
-	}
-	needed += len;
-    }
-
-    if(needed < *pcchEscaped) {
-        *dst = '\0';
-	ret = S_OK;
-    } else {
-        needed++; /* add one for the '\0' */
-	ret = E_POINTER;
-    }
-    *pcchEscaped = needed;
-    return ret;
-}
-
-/*************************************************************************
- *      UrlEscapeW	[SHLWAPI.@]
- *
- * See UrlEscapeA.
- */
 HRESULT WINAPI UrlEscapeW(
 	LPCWSTR pszUrl,
 	LPWSTR pszEscaped,
@@ -1016,6 +911,10 @@
     BOOL stop_escaping = FALSE;
     WCHAR next[5], *dst = pszEscaped;
     INT len;
+    PARSEDURLW parsed_url;
+    DWORD int_flags;
+    DWORD slashes = 0;
+    static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
 
     TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszEscaped,
 	  pcchEscaped, dwFlags);
@@ -1040,39 +939,101 @@
 	/* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
 	dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
 
-    for(src = pszUrl; *src; src++) {
-	/*
-	 * if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
-	 *   (*src == L'#' || *src == L'?'))
-	 *    stop_escaping = TRUE;
-	 */
-        if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
-	   (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
-	   (*src == L'#' || *src == L'?'))
-	    stop_escaping = TRUE;
-
-	if(URL_NeedEscapeW(*src, dwFlags) && stop_escaping == FALSE) {
-	    /* TRACE("escaping %c\n", *src); */
-	    next[0] = L'%';
-	    /*
-	     * I would have assumed that the W form would escape
-	     * the character with 4 hex digits (or even 8),
-	     * however, experiments show that native shlwapi escapes
-	     * with only 2 hex digits.
-	     *   next[1] = hexDigits[(*src >> 12) & 0xf];
-	     *   next[2] = hexDigits[(*src >> 8) & 0xf];
-	     *   next[3] = hexDigits[(*src >> 4) & 0xf];
-	     *   next[4] = hexDigits[*src & 0xf];
-	     *   len = 5;
-	     */
-	    next[1] = hexDigits[(*src >> 4) & 0xf];
-	    next[2] = hexDigits[*src & 0xf];
-	    len = 3;
-	} else {
-	    /* TRACE("passing %c\n", *src); */
-	    next[0] = *src;
-	    len = 1;
-	}
+
+    int_flags = 0;
+    if(dwFlags & URL_ESCAPE_SEGMENT_ONLY) {
+        int_flags = WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH | WINE_URL_ESCAPE_SLASH;
+    } else {
+        parsed_url.cbSize = sizeof(parsed_url);
+        if(ParseURLW(pszUrl, &parsed_url) != S_OK)
+            parsed_url.nScheme = URL_SCHEME_INVALID;
+
+        TRACE("scheme = %d (%s)\n", parsed_url.nScheme, debugstr_wn(parsed_url.pszProtocol, parsed_url.cchProtocol));
+
+        if(dwFlags & URL_DONT_ESCAPE_EXTRA_INFO)
+            int_flags = WINE_URL_STOP_ON_HASH | WINE_URL_STOP_ON_QUESTION;
+
+        switch(parsed_url.nScheme) {
+        case URL_SCHEME_FILE:
+            int_flags |= WINE_URL_BASH_AS_SLASH | WINE_URL_COLLAPSE_SLASHES | WINE_URL_ESCAPE_HASH;
+            int_flags &= ~WINE_URL_STOP_ON_HASH;
+            break;
+
+        case URL_SCHEME_HTTP:
+        case URL_SCHEME_HTTPS:
+            int_flags |= WINE_URL_BASH_AS_SLASH;
+            if(parsed_url.pszSuffix[0] != '/' && parsed_url.pszSuffix[0] != '\\')
+                int_flags |= WINE_URL_ESCAPE_SLASH;
+            break;
+
+        case URL_SCHEME_MAILTO:
+            int_flags |= WINE_URL_ESCAPE_SLASH | WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH;
+            int_flags &= ~(WINE_URL_STOP_ON_QUESTION | WINE_URL_STOP_ON_HASH);
+            break;
+
+        case URL_SCHEME_INVALID:
+            break;
+
+        case URL_SCHEME_FTP:
+        default:
+            if(parsed_url.pszSuffix[0] != '/')
+                int_flags |= WINE_URL_ESCAPE_SLASH;
+            break;
+        }
+    }
+
+    for(src = pszUrl; *src; ) {
+        WCHAR cur = *src;
+        len = 0;
+        
+        if((int_flags & WINE_URL_COLLAPSE_SLASHES) && src == pszUrl + parsed_url.cchProtocol + 1) {
+            int localhost_len = sizeof(localhost)/sizeof(WCHAR) - 1;
+            while(cur == '/' || cur == '\\') {
+                slashes++;
+                cur = *++src;
+            }
+            if(slashes == 2 && !strncmpiW(src, localhost, localhost_len)) { /* file://localhost/ -> file:/// */
+                if(*(src + localhost_len) == '/' || *(src + localhost_len) == '\\')
+                src += localhost_len + 1;
+                slashes = 3;
+            }
+
+            switch(slashes) {
+            case 1:
+            case 3:
+                next[0] = next[1] = next[2] = '/';
+                len = 3;
+                break;
+            case 0:
+                len = 0;
+                break;
+            default:
+                next[0] = next[1] = '/';
+                len = 2;
+                break;
+            }
+        }
+        if(len == 0) {
+
+            if(cur == '#' && (int_flags & WINE_URL_STOP_ON_HASH))
+                stop_escaping = TRUE;
+
+            if(cur == '?' && (int_flags & WINE_URL_STOP_ON_QUESTION))
+                stop_escaping = TRUE;
+
+            if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';
+
+            if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
+                next[0] = L'%';
+                next[1] = hexDigits[(cur >> 4) & 0xf];
+                next[2] = hexDigits[cur & 0xf];
+                len = 3;
+            } else {
+                next[0] = cur;
+                len = 1;
+            }
+            src++;
+        }
 
 	if(needed + len <= *pcchEscaped) {
 	    memcpy(dst, next, len*sizeof(WCHAR));
@@ -1082,7 +1043,7 @@
     }
 
     if(needed < *pcchEscaped) {
-        *dst = L'\0';
+        *dst = '\0';
 	ret = S_OK;
     } else {
         needed++; /* add one for the '\0' */
@@ -1211,10 +1172,10 @@
 	} else if(*src == L'%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2))
 		  && stop_unescaping == FALSE) {
 	    INT ih;
-	    WCHAR buf[3];
-	    memcpy(buf, src + 1, 2*sizeof(WCHAR));
-	    buf[2] = L'\0';
-	    ih = StrToIntW(buf);
+	    WCHAR buf[5] = {'0','x',0};
+	    memcpy(buf + 2, src + 1, 2*sizeof(WCHAR));
+	    buf[4] = 0;
+	    StrToIntExW(buf, STIF_SUPPORT_HEX, &ih);
 	    next = (WCHAR) ih;
 	    src += 2; /* Advance to end of escape */
 	} else
@@ -1271,18 +1232,18 @@
 LPCSTR WINAPI UrlGetLocationA(
 	LPCSTR pszUrl)
 {
-    UNKNOWN_SHLWAPI_1 base;
+    PARSEDURLA base;
     DWORD res1;
 
-    base.size = 24;
+    base.cbSize = sizeof(base);
     res1 = ParseURLA(pszUrl, &base);
     if (res1) return NULL;  /* invalid scheme */
 
     /* if scheme is file: then never return pointer */
-    if (strncmp(base.ap1, "file", min(4,base.sizep1)) == 0) return NULL;
+    if (strncmp(base.pszProtocol, "file", min(4,base.cchProtocol)) == 0) return NULL;
 
     /* Look for '#' and return its addr */
-    return strchr(base.ap2, '#');
+    return strchr(base.pszSuffix, '#');
 }
 
 /*************************************************************************
@@ -1293,18 +1254,18 @@
 LPCWSTR WINAPI UrlGetLocationW(
 	LPCWSTR pszUrl)
 {
-    UNKNOWN_SHLWAPI_2 base;
+    PARSEDURLW base;
     DWORD res1;
 
-    base.size = 24;
+    base.cbSize = sizeof(base);
     res1 = ParseURLW(pszUrl, &base);
     if (res1) return NULL;  /* invalid scheme */
 
     /* if scheme is file: then never return pointer */
-    if (strncmpW(base.ap1, fileW, min(4,base.sizep1)) == 0) return NULL;
+    if (strncmpW(base.pszProtocol, fileW, min(4,base.cchProtocol)) == 0) return NULL;
 
     /* Look for '#' and return its addr */
-    return strchrW(base.ap2, L'#');
+    return strchrW(base.pszSuffix, L'#');
 }
 
 /*************************************************************************
@@ -1590,7 +1551,7 @@
  */
 HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
 {
-    UNKNOWN_SHLWAPI_2 in_scheme;
+    PARSEDURLW in_scheme;
     DWORD res1;
     HRESULT ret;
 
@@ -1605,7 +1566,7 @@
 	return S_FALSE;
     }
 
-    in_scheme.size = 24;
+    in_scheme.cbSize = sizeof(in_scheme);
     /* See if the base has a scheme */
     res1 = ParseURLW(pszIn, &in_scheme);
     if (res1) {
@@ -1617,7 +1578,7 @@
     }
     else {
 	/* we have a scheme, see if valid (known scheme) */
-	if (in_scheme.fcncde) {
+	if (in_scheme.nScheme) {
 	    /* have valid scheme, so just copy and exit */
 	    if (strlenW(pszIn) + 1 > *pcchOut) {
 		*pcchOut = strlenW(pszIn) + 1;
@@ -1666,17 +1627,17 @@
  */
 BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
 {
-    UNKNOWN_SHLWAPI_1 base;
+    PARSEDURLA base;
     DWORD res1;
     LPCSTR last;
 
     switch (Urlis) {
 
     case URLIS_OPAQUE:
-	base.size = 24;
+	base.cbSize = sizeof(base);
 	res1 = ParseURLA(pszUrl, &base);
 	if (res1) return FALSE;  /* invalid scheme */
-	if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
+	if ((*base.pszSuffix == '/') && (*(base.pszSuffix+1) == '/'))
 	    /* has scheme followed by 2 '/' */
 	    return FALSE;
 	return TRUE;
@@ -1706,17 +1667,17 @@
 BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
 {
     static const WCHAR stemp[] = { 'f','i','l','e',':','/','/',0 };
-    UNKNOWN_SHLWAPI_2 base;
+    PARSEDURLW base;
     DWORD res1;
     LPCWSTR last;
 
     switch (Urlis) {
 
     case URLIS_OPAQUE:
-	base.size = 24;
+	base.cbSize = sizeof(base);
 	res1 = ParseURLW(pszUrl, &base);
 	if (res1) return FALSE;  /* invalid scheme */
-	if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
+	if ((*base.pszSuffix == '/') && (*(base.pszSuffix+1) == '/'))
 	    /* has scheme followed by 2 '/' */
 	    return FALSE;
 	return TRUE;
@@ -2109,15 +2070,15 @@
  */
 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
 {
-    UNKNOWN_SHLWAPI_1 base;
+    PARSEDURLA base;
     DWORD res1;
 
     if (!lpstrPath || !*lpstrPath) return FALSE;
 
     /* get protocol        */
-    base.size = sizeof(base);
+    base.cbSize = sizeof(base);
     res1 = ParseURLA(lpstrPath, &base);
-    return (base.fcncde > 0);
+    return (base.nScheme != URL_SCHEME_INVALID);
 }
 
 /*************************************************************************
@@ -2127,20 +2088,55 @@
  */
 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
 {
-    UNKNOWN_SHLWAPI_2 base;
+    PARSEDURLW base;
     DWORD res1;
 
     if (!lpstrPath || !*lpstrPath) return FALSE;
 
     /* get protocol        */
-    base.size = sizeof(base);
+    base.cbSize = sizeof(base);
     res1 = ParseURLW(lpstrPath, &base);
-    return (base.fcncde > 0);
+    return (base.nScheme != URL_SCHEME_INVALID);
 }
 
 /*************************************************************************
  *      UrlCreateFromPathA  	[SHLWAPI.@]
  * 
+ * See UrlCreateFromPathW
+ */
+HRESULT WINAPI UrlCreateFromPathA(LPCSTR pszPath, LPSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
+{
+    WCHAR bufW[INTERNET_MAX_URL_LENGTH];
[truncated at 1000 lines; 278 more skipped]

reactos/lib/shlwapi
winehq2ros.patch 1.7 -> 1.8
diff -u -r1.7 -r1.8
--- winehq2ros.patch	20 Aug 2004 06:58:58 -0000	1.7
+++ winehq2ros.patch	20 Oct 2004 16:49:27 -0000	1.8
@@ -1,25 +1,160 @@
+Index: ordinal.c
+===================================================================
+RCS file: /home/wine/wine/dlls/shlwapi/ordinal.c,v
+retrieving revision 1.98
+diff -u -r1.98 ordinal.c
+--- ordinal.c	25 Sep 2004 00:29:30 -0000	1.98
++++ ordinal.c	20 Oct 2004 16:50:41 -0000
+@@ -1549,16 +1549,17 @@
+         LPVOID *p2)       /* [out]  ptr for call results */
+ {
+     DWORD ret, aa;
++    IUnknown *iobjectwithsite;
+ 
+     if (!p1) return E_FAIL;
+ 
+     /* see if SetSite interface exists for IObjectWithSite object */
+-    ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
+-    TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
++    ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);
++    TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);
+     if (ret) {
+ 
+ 	/* see if GetClassId interface exists for IPersistMoniker object */
+-	ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
++	ret = IUnknown_QueryInterface(p1, (REFIID)id2, (LPVOID *)&aa);
+ 	TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
+ 	if (ret) return ret;
+ 
+@@ -1570,10 +1571,10 @@
+     }
+     else {
+ 	/* fake a SetSite call */
+-	ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
++	ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);
+ 	TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
+ 	      *(LPDWORD)p2);
+-	IUnknown_Release((IUnknown *)p1);
++	IUnknown_Release((IUnknown *)iobjectwithsite);
+     }
+     return ret;
+ }
 Index: path.c
 ===================================================================
 RCS file: /home/wine/wine/dlls/shlwapi/path.c,v
-retrieving revision 1.42
-diff -u -r1.42 path.c
---- path.c	20 Apr 2004 00:34:52 -0000	1.42
-+++ path.c	20 Aug 2004 07:09:34 -0000
-@@ -32,6 +32,7 @@
- #include "wingdi.h"
- #include "winuser.h"
- #include "winreg.h"
-+#include "winnls.h"
- #define NO_SHLWAPI_STREAM
- #include "shlwapi.h"
- #include "wine/debug.h"
+retrieving revision 1.48
+diff -u -r1.48 path.c
+--- path.c	5 Oct 2004 18:07:14 -0000	1.48
++++ path.c	20 Oct 2004 16:50:42 -0000
+@@ -3989,3 +3989,101 @@
+     return S_OK;
+   return E_FAIL;
+ }
++
++#define PATH_CHAR_CLASS_LETTER      0x0001
++#define PATH_CHAR_CLASS_ASTERIX     0x0002
++#define PATH_CHAR_CLASS_DOT         0x0004
++#define PATH_CHAR_CLASS_BACKSLASH   0x0008
++#define PATH_CHAR_CLASS_COLON       0x0010
++#define PATH_CHAR_CLASS_SEMICOLON   0x0020
++#define PATH_CHAR_CLASS_COMMA       0x0040
++#define PATH_CHAR_CLASS_SPACE       0x0080
++#define PATH_CHAR_CLASS_OTHER_VALID 0x0100
++#define PATH_CHAR_CLASS_DOUBLEQUOTE 0x0200
++
++/*************************************************************************
++ * PathIsValidCharAW     [internal]
++ *
++ * Check if a char is of a certain class
++ */
++static BOOL WINAPI PathIsValidCharAW(unsigned Ch, DWORD Class)
++{
++  static struct
++  {
++    char Ch;
++    DWORD Class;
++  } CharClass[] =
++  {
++    { ' ', PATH_CHAR_CLASS_SPACE },
++    { '!', PATH_CHAR_CLASS_OTHER_VALID },
++    { '"', PATH_CHAR_CLASS_DOUBLEQUOTE },
++    { '#', PATH_CHAR_CLASS_OTHER_VALID },
++    { '$', PATH_CHAR_CLASS_OTHER_VALID },
++    { '%', PATH_CHAR_CLASS_OTHER_VALID },
++    { '&', PATH_CHAR_CLASS_OTHER_VALID },
++    { '\'', PATH_CHAR_CLASS_OTHER_VALID },
++    { '(', PATH_CHAR_CLASS_OTHER_VALID },
++    { ')', PATH_CHAR_CLASS_OTHER_VALID },
++    { '*', PATH_CHAR_CLASS_ASTERIX },
++    { '+', PATH_CHAR_CLASS_OTHER_VALID },
++    { ',', PATH_CHAR_CLASS_COMMA },
++    { '-', PATH_CHAR_CLASS_OTHER_VALID },
++    { '.', PATH_CHAR_CLASS_DOT },
++    { ':', PATH_CHAR_CLASS_COLON },
++    { ';', PATH_CHAR_CLASS_SEMICOLON },
++    { '=', PATH_CHAR_CLASS_OTHER_VALID },
++    { '?', PATH_CHAR_CLASS_LETTER },
++    { '@', PATH_CHAR_CLASS_OTHER_VALID },
++    { '[', PATH_CHAR_CLASS_OTHER_VALID },
++    { '\\', PATH_CHAR_CLASS_BACKSLASH },
++    { ']', PATH_CHAR_CLASS_OTHER_VALID },
++    { '^', PATH_CHAR_CLASS_OTHER_VALID },
++    { '_', PATH_CHAR_CLASS_OTHER_VALID },
++    { '`', PATH_CHAR_CLASS_OTHER_VALID },
++    { '{', PATH_CHAR_CLASS_OTHER_VALID },
++    { '}', PATH_CHAR_CLASS_OTHER_VALID },
++    { '~', PATH_CHAR_CLASS_OTHER_VALID },
++    { 0x7f, PATH_CHAR_CLASS_OTHER_VALID }
++  };
++  unsigned Index;
++
++  if (('A' <= Ch && Ch <= 'Z') || ('a' <= Ch && Ch <= 'z'))
++  {
++    return (Class & PATH_CHAR_CLASS_LETTER);
++  }
++
++  if (('0' <= Ch && Ch <= '9') || 0x80 <= Ch)
++  {
++    return (Class & PATH_CHAR_CLASS_OTHER_VALID);
++  }
++
++  for (Index = 0; Index < sizeof(CharClass) / sizeof(CharClass[0]); Index++)
++  {
++    if (Ch == CharClass[Index].Ch)
++    {
++      return (Class & CharClass[Index].Class);
++    }
++  }
++
++  return FALSE;
++}
++
++/*************************************************************************
++ * @     [SHLWAPI.455]
++ *
++ * Check if an Ascii char is of a certain class
++ */
++BOOL WINAPI PathIsValidCharA(char Ch, DWORD Class)
++{
++  return PathIsValidCharAW((unsigned) Ch, Class);
++}
++
++/*************************************************************************
++ * @     [SHLWAPI.456]
++ *
++ * Check if an Unicode char is of a certain class
++ */
++BOOL WINAPI PathIsValidCharW(WCHAR Ch, DWORD Class)
++{
++  return PathIsValidCharAW((unsigned) Ch, Class);
++}
 Index: shlwapi.spec
 ===================================================================
 RCS file: /home/wine/wine/dlls/shlwapi/shlwapi.spec,v
-retrieving revision 1.93
-diff -u -r1.93 shlwapi.spec
---- shlwapi.spec	19 Jul 2004 19:32:51 -0000	1.93
-+++ shlwapi.spec	20 Aug 2004 07:09:34 -0000
+retrieving revision 1.96
+diff -u -r1.96 shlwapi.spec
+--- shlwapi.spec	25 Sep 2004 00:29:30 -0000	1.96
++++ shlwapi.spec	20 Oct 2004 16:50:42 -0000
 @@ -368,9 +368,9 @@
  368 stdcall @(wstr wstr ptr long wstr) kernel32.GetPrivateProfileStructW
  369 stdcall @(wstr wstr ptr ptr long long ptr wstr ptr ptr) kernel32.CreateProcessW
@@ -42,24 +177,30 @@
  393 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamW
  394 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamA
  395 stub -noname MLWinHelpA
-@@ -456,8 +456,8 @@
- 456 stub -noname PathIsValidCharW
+@@ -452,12 +452,12 @@
+ 452 stub -noname CharUpperNoDBCSW
+ 453 stub -noname CharLowerNoDBCSA
+ 454 stub -noname CharLowerNoDBCSW
+-455 stub -noname PathIsValidCharA
+-456 stub -noname PathIsValidCharW
++455 stdcall -noname PathIsValidCharA(long long)
++456 stdcall -noname PathIsValidCharW(long long)
  457 stub -noname GetLongPathNameWrapW
  458 stub -noname GetLongPathNameWrapA
 -459 stdcall -noname SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA
 -460 stdcall -noname SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW
 +459 stdcall SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA
 +460 stdcall SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW
- 461 stdcall -noname SHGetAppCompatFlags()
+ 461 stdcall -noname SHGetAppCompatFlags(long)
  462 stub -noname UrlFixupW
  463 stub -noname SHExpandEnvironmentStringsForUserA
 Index: string.c
 ===================================================================
 RCS file: /home/wine/wine/dlls/shlwapi/string.c,v
-retrieving revision 1.47
-diff -u -r1.47 string.c
---- string.c	21 Jul 2004 03:12:16 -0000	1.47
-+++ string.c	20 Aug 2004 07:09:35 -0000
+retrieving revision 1.49
+diff -u -r1.49 string.c
+--- string.c	13 Sep 2004 18:11:56 -0000	1.49
++++ string.c	20 Oct 2004 16:50:43 -0000
 @@ -528,7 +528,7 @@
  {
    TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
@@ -81,11 +222,11 @@
 Index: url.c
 ===================================================================
 RCS file: /home/wine/wine/dlls/shlwapi/url.c,v
-retrieving revision 1.35
-diff -u -r1.35 url.c
---- url.c	4 Jul 2004 00:06:29 -0000	1.35
-+++ url.c	20 Aug 2004 07:09:36 -0000
-@@ -1386,8 +1386,8 @@
+retrieving revision 1.43
+diff -u -r1.43 url.c
+--- url.c	5 Oct 2004 18:31:41 -0000	1.43
++++ url.c	20 Oct 2004 16:50:44 -0000
+@@ -1347,8 +1347,8 @@
   *  Success: TRUE. lpDest is filled with the computed hash value.
   *  Failure: FALSE, if any argument is invalid.
   */
CVSspam 0.2.8