Index: trunk/src/shlwapi/makefile
===================================================================
--- trunk/src/shlwapi/makefile	(revision 7815)
+++ trunk/src/shlwapi/makefile	(revision 7820)
@@ -1,3 +1,3 @@
-# $Id: makefile,v 1.24 2001-11-19 12:34:54 sandervl Exp $
+# $Id: makefile,v 1.25 2002-02-06 20:18:27 sandervl Exp $
 
 #
@@ -19,4 +19,5 @@
 OBJS = \
 $(OBJDIR)\shlwapi.obj \
+$(OBJDIR)\shlwapi_main.obj \
 $(OBJDIR)\shlstub.obj \
 $(OBJDIR)\url.obj \
@@ -29,7 +30,7 @@
 $(OBJDIR)\string_odin.obj \
 $(OBJDIR)\string.obj \
-$(OBJDIR)\shlwapirsrc.obj \
 $(OBJDIR)\ordinal.obj \
 $(OBJDIR)\ordinal_odin.obj \
+$(OBJDIR)\shlwapirsrc.obj \
 $(DLLENTRY)
 
@@ -40,4 +41,5 @@
 LIBS = \
 $(ODIN32_LIB)/kernel32.lib \
+$(ODIN32_LIB)/ntdll.lib \
 $(ODIN32_LIB)/user32.lib \
 $(ODIN32_LIB)/gdi32.lib \
Index: trunk/src/shlwapi/ordinal.c
===================================================================
--- trunk/src/shlwapi/ordinal.c	(revision 7815)
+++ trunk/src/shlwapi/ordinal.c	(revision 7820)
@@ -19,18 +19,15 @@
 #include "wine/unicode.h"
 #include "wine/obj_base.h"
+#include "wine/obj_inplace.h"
+#include "wine/obj_serviceprovider.h"
 #include "wingdi.h"
+#include "winreg.h"
 #include "winuser.h"
 #include "debugtools.h"
+#include "ordinal.h"
+#include "shlwapi.h"
 
 DEFAULT_DEBUG_CHANNEL(shell);
 
-#ifdef __WIN32OS2__
-extern HINSTANCE shlwapi_hInstance = 0;
-extern HMODULE SHLWAPI_hshell32 = 0;
-extern HMODULE SHLWAPI_hwinmm = 0;
-extern HMODULE SHLWAPI_hcomdlg32 = 0;
-extern HMODULE SHLWAPI_hmpr = 0;
-extern HMODULE SHLWAPI_hmlang = 0;
-#else
 extern HINSTANCE shlwapi_hInstance;
 extern HMODULE SHLWAPI_hshell32;
@@ -39,5 +36,65 @@
 extern HMODULE SHLWAPI_hmpr;
 extern HMODULE SHLWAPI_hmlang;
-#endif
+
+typedef HANDLE HSHARED; /* Shared memory */
+
+/* following is GUID for IObjectWithSite::SetSite  -- see _174           */
+static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
+/* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
+static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
+
+/* 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;
+} SHL_2_inet_scheme;
+
+static const SHL_2_inet_scheme shlwapi_schemes[] = {
+  {URL_SCHEME_FTP,        "ftp"},
+  {URL_SCHEME_HTTP,       "http"},
+  {URL_SCHEME_GOPHER,     "gopher"},
+  {URL_SCHEME_MAILTO,     "mailto"},
+  {URL_SCHEME_NEWS,       "news"},
+  {URL_SCHEME_NNTP,       "nntp"},
+  {URL_SCHEME_TELNET,     "telnet"},
+  {URL_SCHEME_WAIS,       "wais"},
+  {URL_SCHEME_FILE,       "file"},
+  {URL_SCHEME_MK,         "mk"},
+  {URL_SCHEME_HTTPS,      "https"},
+  {URL_SCHEME_SHELL,      "shell"},
+  {URL_SCHEME_SNEWS,      "snews"},
+  {URL_SCHEME_LOCAL,      "local"},
+  {URL_SCHEME_JAVASCRIPT, "javascript"},
+  {URL_SCHEME_VBSCRIPT,   "vbscript"},
+  {URL_SCHEME_ABOUT,      "about"},
+  {URL_SCHEME_RES,        "res"},
+  {0, 0}
+};
 
 /* Macro to get function pointer for a module*/
@@ -57,37 +114,516 @@
  and recommend the builtin rather than reimplementing the calls here!
 */
-#ifndef __WIN32OS2__
-/*************************************************************************
- *      SHLWAPI_1	[SHLWAPI.1]
- */
-DWORD WINAPI SHLWAPI_1 (
-	LPSTR   lpURL,
-	LPDWORD lpdwFlags)
-{
-  if (lpURL == NULL)
-    return E_INVALIDARG;
-  
-  if (lpdwFlags == NULL)
-    return E_INVALIDARG;
-  
-  // verify flags
-  if (*lpdwFlags != 0x18)   // some unknown flag
-    return E_INVALIDARG;      // some unknown error condition
-  
-  FIXME("(%p %s %p %s)\n",lpStr, debugstr_a(lpStr),x, debugstr_a(x));
-  return 0;
-}
-
-/*************************************************************************
- *      SHLWAPI_2	[SHLWAPI.2]
- */
-DWORD WINAPI SHLWAPI_2 (LPCWSTR x,LPVOID y)
-{
-	FIXME("(%s,%p)\n",debugstr_w(x),y);
+
+/*************************************************************************
+ *      @	[SHLWAPI.1]
+ *
+ * Identifies the Internet "scheme" in the passed string. ASCII based.
+ * Also determines start and length of item after the ':'
+ */
+DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
+{
+    DWORD cnt;
+    const SHL_2_inet_scheme *inet_pro;
+
+    if (y->size != 0x18) 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;
+    while (*x) {
+	if (*x == ':') {
+	    y->sizep1 = cnt;
+	    cnt = -1;
+	    y->ap2 = x+1;
+	    break;
+	}
+	x++;
+	cnt++;
+    }
+
+    /* 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;
+	return 0x80041001;
+    }
+
+    /* found scheme, set length of remainder */
+    y->sizep2 = lstrlenA(y->ap2);
+
+    /* see if known scheme and return indicator number */
+    y->fcncde = 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;
+	    break;
+	}
+	inet_pro++;
+    }
+    return S_OK;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.2]
+ *
+ * Identifies the Internet "scheme" in the passed string. UNICODE based.
+ * Also determines start and length of item after the ':'
+ */
+DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
+{
+    DWORD cnt;
+    const SHL_2_inet_scheme *inet_pro;
+    LPSTR cmpstr;
+    INT len;
+
+    if (y->size != 0x18) 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;
+    while (*x) {
+	if (*x == L':') {
+	    y->sizep1 = cnt;
+	    cnt = -1;
+	    y->ap2 = x+1;
+	    break;
+	}
+	x++;
+	cnt++;
+    }
+
+    /* 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;
+	return 0x80041001;
+    }
+
+    /* found scheme, set length of remainder */
+    y->sizep2 = lstrlenW(y->ap2);
+
+    /* see if known scheme and return indicator number */
+    len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
+    cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
+    WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
+    y->fcncde = 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;
+	    break;
+	}
+	inet_pro++;
+    }
+    HeapFree(GetProcessHeap(), 0, cmpstr);
+    return S_OK;
+}
+
+/*************************************************************************
+ * SHLWAPI_DupSharedHandle
+ *
+ * Internal implemetation of SHLWAPI_11.
+ */
+static
+HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
+                                       DWORD dwSrcProcId, DWORD dwAccess,
+                                       DWORD dwOptions)
+{
+  HANDLE hDst, hSrc;
+  DWORD dwMyProcId = GetCurrentProcessId();
+  HSHARED hRet = (HSHARED)NULL;
+
+  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
+        dwAccess, dwOptions);
+
+  /* Get dest process handle */
+  if (dwDstProcId == dwMyProcId)
+    hDst = GetCurrentProcess();
+  else
+    hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
+
+  if (hDst)
+  {
+    /* Get src process handle */
+    if (dwSrcProcId == dwMyProcId)
+      hSrc = GetCurrentProcess();
+    else
+      hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
+
+    if (hSrc)
+    {
+      /* Make handle available to dest process */
+      if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
+                           dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
+        hRet = (HSHARED)NULL;
+
+      if (dwSrcProcId != dwMyProcId)
+        CloseHandle(hSrc);
+    }
+
+    if (dwDstProcId != dwMyProcId)
+      CloseHandle(hDst);
+  }
+
+  TRACE("Returning handle %p\n", (PVOID)hRet);
+  return hRet;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.7]
+ *
+ * Create a block of sharable memory and initialise it with data.
+ *
+ * PARAMS
+ * dwProcId [I] ID of process owning data
+ * lpvData  [I] Pointer to data to write
+ * dwSize   [I] Size of data
+ *
+ * RETURNS
+ * Success: A shared memory handle
+ * Failure: NULL
+ *
+ * NOTES
+ * Ordinals 7-11 provide a set of calls to create shared memory between a
+ * group of processes. The shared memory is treated opaquely in that its size
+ * is not exposed to clients who map it. This is accomplished by storing
+ * the size of the map as the first DWORD of mapped data, and then offsetting
+ * the view pointer returned by this size.
+ *
+ * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
+ * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
+ * SHLWAPI_11           - Helper function; Duplicate cross-process handles
+   */
+HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, LPCVOID lpvData, DWORD dwSize)
+{
+  HANDLE hMap;
+  LPVOID pMapped;
+  HSHARED hRet = (HSHARED)NULL;
+
+  TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
+
+  /* Create file mapping of the correct length */
+  hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
+                            dwSize + sizeof(dwSize), NULL);
+  if (!hMap)
+    return hRet;
+
+  /* Get a view in our process address space */
+  pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+
+  if (pMapped)
+  {
+    /* Write size of data, followed by the data, to the view */
+    *((DWORD*)pMapped) = dwSize;
+    if (dwSize)
+      memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
+
+    /* Release view. All further views mapped will be opaque */
+    UnmapViewOfFile(pMapped);
+    hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
+                                   GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
+                                   DUPLICATE_SAME_ACCESS);
+  }
+
+  CloseHandle(hMap);
+  return hRet;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.8]
+ *
+ * Get a pointer to a block of shared memory from a shared memory handle.
+ *
+ * PARAMS
+ * hShared  [I] Shared memory handle
+ * dwProcId [I] ID of process owning hShared
+ *
+ * RETURNS
+ * Success: A pointer to the shared memory
+ * Failure: NULL
+ *
+ * NOTES
+ * See SHLWAPI_7.
+   */
+PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
+  {
+  HSHARED hDup;
+  LPVOID pMapped;
+
+  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
+
+  /* Get handle to shared memory for current process */
+  hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
+                                 FILE_MAP_ALL_ACCESS, 0);
+  /* Get View */
+  pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+  CloseHandle(hDup);
+
+  if (pMapped)
+    return (char *) pMapped + sizeof(DWORD); /* Hide size */
+  return NULL;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.9]
+ *
+ * Release a pointer to a block of shared memory.
+ *
+ * PARAMS
+ * lpView [I] Shared memory pointer
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * See SHLWAPI_7.
+ */
+BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
+{
+  TRACE("(%p)\n", lpView);
+  return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.10]
+ *
+ * Destroy a block of sharable memory.
+ *
+ * PARAMS
+ * hShared  [I] Shared memory handle
+ * dwProcId [I] ID of process owning hShared
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * See SHLWAPI_7.
+ */
+BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
+{
+  HSHARED hClose;
+
+  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
+
+  /* Get a copy of the handle for our process, closing the source handle */
+  hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
+                                   FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
+  /* Close local copy */
+  return CloseHandle((HANDLE)hClose);
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.11]
+ *
+ * Copy a sharable memory handle from one process to another.
+ *
+ * PARAMS
+ * hShared     [I] Shared memory handle to duplicate
+ * dwDstProcId [I] ID of the process wanting the duplicated handle
+ * dwSrcProcId [I] ID of the process owning hShared
+ * dwAccess    [I] Desired DuplicateHandle access
+ * dwOptions   [I] Desired DuplicateHandle options
+ *
+ * RETURNS
+ * Success: A handle suitable for use by the dwDstProcId process.
+ * Failure: A NULL handle.
+ *
+ * NOTES
+ * See SHLWAPI_7.
+ */
+HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
+                          DWORD dwAccess, DWORD dwOptions)
+{
+  HSHARED hRet;
+
+  hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
+                                 dwAccess, dwOptions);
+  return hRet;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.13]
+ * (Used by IE4 during startup)
+ */
+HRESULT WINAPI SHLWAPI_13 (
+	LPVOID w,
+	LPVOID x)
+{
+	FIXME("(%p %p)stub\n",w,x);
+	return 1;
+#if 0
+	/* pseudo code extracted from relay trace */
+	RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Aceepted Documents", &newkey);
+	ret = 0;
+	i = 0;
+	size = 0;
+	while(!ret) {
+	    ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
+	    size += ???;
+	    i++;
+	}
+	b1 = LocalAlloc(0x40, size);
+	ret = 0;
+	i = 0;
+	while(!ret) {
+	    ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
+	    RegisterClipBoardFormatA(a4);
+	    i++;
+	}
+	hwnd1 = GetModuleHandleA("URLMON.DLL");
+	proc = GetProcAddress(hwnd1, "CreateFormatEnumerator");
+	HeapAlloc(??, 0, 0x14);
+	HeapAlloc(??, 0, 0x50);
+	LocalAlloc(0x40, 0x78);
+	/* FIXME: bad string below */
+	lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
+	StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
+
+	GetTickCount();
+	IsBadReadPtr(c1 = 0x403fd210,4);
+	InterlockedIncrement(c1+4);
+	LocalFree(b1);
+	RegCloseKey(newkey);
+	IsBadReadPtr(c1 = 0x403fd210,4);
+	InterlockedIncrement(c1+4);
+
+	HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
+	HeapAlloc(40350000,00000000,00000050) retval=403feb44;
+	hwnd1 = GetModuleHandleA("URLMON.DLL");
+	proc = GetProcAddress(hwnd1, "RegisterFormatEnumerator");
+	/* 0x1a40c88c is in URLMON.DLL just before above proc
+	 * content is L"_EnumFORMATETC_"
+	 * label is d1
+	 */
+        IsBadReadPtr(d1 = 0x1a40c88c,00000002);
+	lstrlenW(d1);
+	lstrlenW(d1);
+	HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
+	IsBadReadPtr(d2 = 0x403fd0a8,00000004);
+	InterlockedIncrement(d2+4);
+	IsBadReadPtr(d2 = 0x403fd0a8,00000004);
+	InterlockedDecrement(d2+4);
+	IsBadReadPtr(c1,00000004);
+	InterlockedDecrement(c1+4);
+	IsBadReadPtr(c1,00000004);
+	InterlockedDecrement(c1+4);
+
+#endif
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.14]
+ *
+ * Function:
+ *    Retrieves IE "AcceptLanguage" value from registry. ASCII mode.
+ *  
+ */
+HRESULT WINAPI SHLWAPI_14 (
+	LPSTR langbuf,
+	LPDWORD buflen)
+{
+	CHAR *mystr;
+	DWORD mystrlen, mytype;
+	HKEY mykey;
+	LCID mylcid;
+
+	mystrlen = (*buflen > 6) ? *buflen : 6;
+	mystr = (CHAR*)HeapAlloc(GetProcessHeap(), 
+				 HEAP_ZERO_MEMORY, mystrlen);
+	RegOpenKeyA(HKEY_CURRENT_USER, 
+		    "Software\\Microsoft\\Internet Explorer\\International", 
+		    &mykey);
+	if (RegQueryValueExA(mykey, "AcceptLanguage", 
+			      0, &mytype, mystr, &mystrlen)) {
+	    /* Did not find value */
+	    mylcid = GetUserDefaultLCID();
+	    /* somehow the mylcid translates into "en-us"
+	     *  this is similar to "LOCALE_SABBREVLANGNAME"
+	     *  which could be gotten via GetLocaleInfo.
+	     *  The only problem is LOCALE_SABBREVLANGUAGE" is
+	     *  a 3 char string (first 2 are country code and third is
+	     *  letter for "sublanguage", which does not come close to
+	     *  "en-us"
+	     */
+	    lstrcpyA(mystr, "en-us");
+	    mystrlen = lstrlenA(mystr);
+	}
+	else {
+	    /* handle returned string */
+	    FIXME("missing code\n");
+	}
+	if (mystrlen > *buflen) 
+	    lstrcpynA(langbuf, mystr, *buflen);
+	else {
+	    lstrcpyA(langbuf, mystr);
+	    *buflen = lstrlenA(langbuf);
+	}        
+	RegCloseKey(mykey);
+	HeapFree(GetProcessHeap(), 0, mystr);
+	TRACE("language is %s\n", debugstr_a(langbuf));
 	return 0;
 }
 
 /*************************************************************************
- *      SHLWAPI_16	[SHLWAPI.16]
+ *      @	[SHLWAPI.15]
+ *
+ * Function:
+ *    Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
+ *  
+ */
+HRESULT WINAPI SHLWAPI_15 (
+	LPWSTR langbuf,
+	LPDWORD buflen)
+{
+	CHAR *mystr;
+	DWORD mystrlen, mytype;
+	HKEY mykey;
+	LCID mylcid;
+
+	mystrlen = (*buflen > 6) ? *buflen : 6;
+	mystr = (CHAR*)HeapAlloc(GetProcessHeap(), 
+				 HEAP_ZERO_MEMORY, mystrlen);
+	RegOpenKeyA(HKEY_CURRENT_USER, 
+		    "Software\\Microsoft\\Internet Explorer\\International", 
+		    &mykey);
+	if (RegQueryValueExA(mykey, "AcceptLanguage", 
+			      0, &mytype, mystr, &mystrlen)) {
+	    /* Did not find value */
+	    mylcid = GetUserDefaultLCID();
+	    /* somehow the mylcid translates into "en-us"
+	     *  this is similar to "LOCALE_SABBREVLANGNAME"
+	     *  which could be gotten via GetLocaleInfo.
+	     *  The only problem is LOCALE_SABBREVLANGUAGE" is
+	     *  a 3 char string (first 2 are country code and third is
+	     *  letter for "sublanguage", which does not come close to
+	     *  "en-us"
+	     */
+	    lstrcpyA(mystr, "en-us");
+	    mystrlen = lstrlenA(mystr);
+	}
+	else {
+	    /* handle returned string */
+	    FIXME("missing code\n");
+	}
+	RegCloseKey(mykey);
+	*buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
+	HeapFree(GetProcessHeap(), 0, mystr);
+	TRACE("language is %s\n", debugstr_w(langbuf));
+	return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.16]
  */
 HRESULT WINAPI SHLWAPI_16 (
@@ -100,8 +636,79 @@
 	return 0xabba1252;
 }
-#endif
-
-/*************************************************************************
- *      SHLWAPI_23	[SHLWAPI.23]
+
+/*************************************************************************
+ *      @	[SHLWAPI.18]
+ *
+ *  w is pointer to address of callback routine
+ *  x is pointer to LPVOID to receive address of locally allocated
+ *         space size 0x14
+ *  return is 0 (unless out of memory???)
+ *
+ * related to _19, _21 and _22 below
+ *  only seen invoked by SHDOCVW
+ */
+LONG WINAPI SHLWAPI_18 (
+	LPVOID *w,
+	LPVOID x)
+{
+	FIXME("(%p %p)stub\n",w,x);
+	*((LPDWORD)x) = 0;
+	return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.19]
+ *
+ *  w is address of allocated memory from _21
+ *  return is 0 (unless out of memory???)
+ *
+ * related to _18, _21 and _22 below
+ *  only seen invoked by SHDOCVW
+ */
+LONG WINAPI SHLWAPI_19 (
+	LPVOID w)
+{
+	FIXME("(%p) stub\n",w);
+	return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.21]
+ *
+ *  w points to space allocated via .18 above
+ *      LocalSize is done on it (retrieves 18)
+ *      LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
+ *  x values seen 0xa0000005
+ *  returns 1
+ *
+ *  relates to _18, _19 and _22 above and below
+ *   only seen invoked by SHDOCVW
+ */
+LONG WINAPI SHLWAPI_21 (
+	LPVOID w,
+	DWORD  x)
+{
+	FIXME("(%p %lx)stub\n",w,x);
+	return 1;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.22]
+ *
+ *  return is 'w' value seen in x is 0xa0000005
+ *
+ *  relates to _18, _19 and _21 above
+ *   only seen invoked by SHDOCVW
+ */
+LPVOID WINAPI SHLWAPI_22 (
+	LPVOID w,
+	DWORD  x)
+{
+	FIXME("(%p %lx)stub\n",w,x);
+	return w;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.23]
  *
  * NOTES
@@ -127,5 +734,5 @@
 
 /*************************************************************************
- *      SHLWAPI_24	[SHLWAPI.24]
+ *      @	[SHLWAPI.24]
  *
  * NOTES
@@ -148,38 +755,126 @@
 
 /*************************************************************************
- *      SHLWAPI_30	[SHLWAPI.30]
- *
- * Seems to be an isspaceW.
- */
-BOOL WINAPI SHLWAPI_30(LPWSTR lpcChar)
-{
-  switch (*lpcChar)
-  {
-  case (WCHAR)'\t':
-  case (WCHAR)' ':
-  case 160:
-  case 12288:
-  case 65279:
+ *      @	[SHLWAPI.25]
+ *
+ * Seems to be iswalpha
+ */
+BOOL WINAPI SHLWAPI_25(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_ALPHA) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.26]
+ *
+ * Seems to be iswupper
+ */
+BOOL WINAPI SHLWAPI_26(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_UPPER) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.27]
+ *
+ * Seems to be iswlower
+ */
+BOOL WINAPI SHLWAPI_27(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_LOWER) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.28]
+ *
+ * Seems to be iswalnum
+ */
+BOOL WINAPI SHLWAPI_28(WCHAR wc)
+{
+    return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.29]
+ *
+ * Seems to be iswspace
+ */
+BOOL WINAPI SHLWAPI_29(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_SPACE) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.30]
+ *
+ * Seems to be iswblank
+ */
+BOOL WINAPI SHLWAPI_30(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_BLANK) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.31]
+ *
+ * Seems to be iswpunct
+ */
+BOOL WINAPI SHLWAPI_31(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_PUNCT) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.32]
+ *
+ * Seems to be iswcntrl
+ */
+BOOL WINAPI SHLWAPI_32(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_CNTRL) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.33]
+ *
+ * Seems to be iswdigit
+ */
+BOOL WINAPI SHLWAPI_33(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_DIGIT) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.34]
+ *
+ * Seems to be iswxdigit
+ */
+BOOL WINAPI SHLWAPI_34(WCHAR wc)
+{
+    return (get_char_typeW(wc) & C1_XDIGIT) != 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.35]
+ *
+ */
+BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
+{
+    FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
     return TRUE;
-  }
-  return FALSE;
-}
-
-/*************************************************************************
- *      SHLWAPI_32	[SHLWAPI.32]
- */
-BOOL WINAPI SHLWAPI_32(LPCWSTR lpcChar)
-{
- if (*lpcChar < (WCHAR)' ')
-   return TRUE;
-
- /* This is probably a shlwapi bug, but we do it the same for compatability */
- if (((DWORD)lpcChar & 0xffff) - 127 <= (WCHAR)' ')
-   return TRUE;
- return FALSE;
-}
-
-/*************************************************************************
- *      SHLWAPI_40	[SHLWAPI.40]
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.36]
+ *
+ */
+BOOL WINAPI SHLWAPI_36(HMENU h1, UINT ui2, UINT h3, LPCWSTR p4)
+{
+    TRACE("(0x%08x, 0x%08x, 0x%08x, %s): stub\n", 
+	  h1, ui2, h3, debugstr_w(p4));
+    return AppendMenuW(h1, ui2, h3, p4);
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.40]
  *
  * Get pointer to next Unicode character.
@@ -191,5 +886,5 @@
 
 /*************************************************************************
- *      SHLWAPI_74	[SHLWAPI.74]
+ *      @	[SHLWAPI.74]
  *
  * Get the text from a given dialog item.
@@ -205,78 +900,49 @@
   return 0;
 }
-/*************************************************************************
- *      SHLWAPI_151	[SHLWAPI.151]
- */
-#ifdef __WIN32OS2__
+
+/*************************************************************************
+ *      @	[SHLWAPI.151]
+ * Function:  Compare two ASCII strings for "len" bytes.
+ * Returns:   *str1-*str2  (case sensitive)
+ */
 DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
 {
-  dprintf(("SHLWAPI_151 (strcmpn) %s %s %d", str1, str2, len));
-  if (!len)
-    return 0;
-
-  while (--len && *str1 && *str1 == *str2)
-  {
-    str1++;
-    str2++;
-  }
-  return *str1 - *str2;
-
-}
-#else
-DWORD WINAPI SHLWAPI_151(void)
-{
-  FIXME(": stub\n");
-  return 0;
-}
-#endif
-
-/*************************************************************************
- *      SHLWAPI_152	[SHLWAPI.152]
+    return strncmp( str1, str2, len );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.152]
+ *
+ * Function:  Compare two WIDE strings for "len" bytes.
+ * Returns:   *str1-*str2  (case sensitive)
  */
 DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
 {
-  if (!len)
-    return 0;
-
-  while (--len && *str1 && *str1 == *str2)
-  {
-    str1++;
-    str2++;
-  }
-  return *str1 - *str2;
-}
-
-/*************************************************************************
- *      SHLWAPI_153	[SHLWAPI.153]
- */
-#ifdef __WIN32OS2__
-//case insensitive string compare with length (ascii)
+    return strncmpW( str1, str2, len );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.153]
+ * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
+ * Returns:   *str1-*str2  (case insensitive)
+ */
 DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
 {
-  if (!len)
-    return 0;
-
-  return lstrncmpiA(str1, str2, len);
-}
-
-//case insensitive string compare with length (unicode)
+    return strncasecmp( str1, str2, len );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.154]
+ *
+ * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
+ * Returns:   *str1-*str2  (case insensitive)
+ */
 DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
 {
-  if (!len)
-    return 0;
-
-  return lstrncmpiW(str1, str2, len);
-}
-
-#else
-DWORD WINAPI SHLWAPI_153(DWORD dw1, DWORD dw2, DWORD dw3)
-{
-    FIXME("%08lx %08lx %08lx - stub\n", dw1, dw2, dw3);
-    return 0;
-}
-#endif
-
-/*************************************************************************
- *      SHLWAPI_156	[SHLWAPI.156]
+    return strncmpiW( str1, str2, len );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.156]
  *
  *	Case sensitive string compare. Does not SetLastError().
@@ -284,10 +950,19 @@
 DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
 {
-  while (*str1 && (*str1 == *str2)) { str1++; str2++; }
-  return (INT)(*str1 - *str2);
-}
-
-/*************************************************************************
- *      SHLWAPI_162	[SHLWAPI.162]
+    return strcmpW( str1, str2 );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.158]
+ *
+ *	Case insensitive string compare. Does not SetLastError(). ??
+ */
+DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
+{
+    return strcmpiW( str1, str2 );
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.162]
  *
  * Ensure a multibyte character string doesn't end in a hanging lead byte.
@@ -313,5 +988,20 @@
 
 /*************************************************************************
- *      SHLWAPI_165	[SHLWAPI.165]
+ *      @	[SHLWAPI.164]
+ */
+DWORD WINAPI SHLWAPI_164 (
+	LPVOID u,
+	LPVOID v,
+	LPVOID w,
+	LPVOID x,
+	LPVOID y,
+	LPVOID z)
+{
+        TRACE("(%p %p %p %p %p %p) stub\n",u,v,w,x,y,z);
+	return 0x80004002;    /* E_NOINTERFACE */
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.165]
  *
  * SetWindowLongA with mask.
@@ -328,18 +1018,22 @@
 
 /*************************************************************************
- *      SHLWAPI_169	[SHLWAPI.169]
- */
-DWORD WINAPI SHLWAPI_169 (IUnknown * lpUnknown)
-{
+ *      @	[SHLWAPI.169]
+ *
+ *  Do IUnknown::Release on passed object.
+ */
+DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
+{
+        IUnknown *temp;
+
 	TRACE("(%p)\n",lpUnknown);
-#if 0
 	if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
-	return IUnknown_Release(lpUnknown);
-#endif
-	return 0;
-}
-
-/*************************************************************************
- *      SHLWAPI_170	[SHLWAPI.170]
+	temp = *lpUnknown;
+	*lpUnknown = NULL;
+	TRACE("doing Release\n");
+	return IUnknown_Release(temp);
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.170]
  *
  * Skip URL '//' sequence.
@@ -353,5 +1047,101 @@
 
 /*************************************************************************
- *      SHLWAPI_181	[SHLWAPI.181]
+ *      @	[SHLWAPI.172]
+ * Get window handle of OLE object
+ */
+DWORD WINAPI SHLWAPI_172 (
+	IUnknown *y,       /* [in]   OLE object interface */
+	LPHWND z)          /* [out]  location to put window handle */
+{
+        DWORD ret;
+	IUnknown *pv;
+
+        TRACE("(%p %p)\n",y,z);
+	if (!y) return E_FAIL;
+
+	if ((ret = IUnknown_QueryInterface(y, &IID_IOleWindow,(LPVOID *)&pv)) < 0) {
+	    /* error */
+	    return ret;
+	}
+	ret = IOleWindow_GetWindow((IOleWindow *)pv, z);
+	IUnknown_Release(pv);
+	TRACE("result hwnd=%08x\n", *z);
+	return ret;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.174]
+ *
+ * Seems to do call either IObjectWithSite::SetSite or 
+ *   IPersistMoniker::GetClassID.  But since we do not implement either
+ *   of those classes in our headers, we will fake it out.
+ */
+DWORD WINAPI SHLWAPI_174(
+	IUnknown *p1,     /* [in]   OLE object                          */
+        LPVOID *p2)       /* [out]  ptr to result of either GetClassID 
+                                    or SetSite call.                    */
+{
+    DWORD ret, aa;
+
+    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);
+    if (ret) { 
+
+	/* see if GetClassId interface exists for IPersistMoniker object */
+	ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
+	TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
+	if (ret) return ret;
+
+	/* fake a GetClassId call */
+	ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
+	TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret, 
+	      *(LPDWORD)p2);
+	IUnknown_Release((IUnknown *)aa);
+    }
+    else {
+	/* fake a SetSite call */
+	ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
+	TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret, 
+	      *(LPDWORD)p2);
+	IUnknown_Release((IUnknown *)p1);
+    }
+    return ret;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.176]
+ *
+ * Function appears to be interface to IServiceProvider::QueryService
+ *
+ * NOTE:
+ *   returns E_NOINTERFACE
+ *           E_FAIL  if w == 0
+ *           S_OK    if _219 called successfully
+ */
+DWORD WINAPI SHLWAPI_176 (
+	IUnknown* unk,    /* [in]    object to give Service Provider */
+	REFGUID   sid,    /* [in]    Service ID                      */
+        REFIID    riid,   /* [in]    Function requested              */
+	LPVOID    *z)     /* [out]   place to save interface pointer */
+{
+    DWORD ret;
+    LPVOID aa;
+    *z = 0;
+    if (!unk) return E_FAIL;
+    ret = IUnknown_QueryInterface(unk, &IID_IServiceProvider, &aa);
+    TRACE("did IU_QI retval=%08lx, aa=%p\n", ret, aa); 
+    if (ret) return ret;
+    ret = IServiceProvider_QueryService((IServiceProvider *)aa, sid, riid, 
+					(void **)z);
+    TRACE("did ISP_QS retval=%08lx, *z=%p\n", ret, (LPVOID)*z); 
+    IUnknown_Release((IUnknown*)aa);
+    return ret;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.181]
  *
  *	Enable or disable a menu item.
@@ -363,5 +1153,5 @@
 
 /*************************************************************************
- *      SHLWAPI_183	[SHLWAPI.183]
+ *      @	[SHLWAPI.183]
  *
  * Register a window class if it isn't already.
@@ -376,5 +1166,5 @@
 
 /*************************************************************************
- *      SHLWAPI_193	[SHLWAPI.193]
+ *      @	[SHLWAPI.193]
  */
 DWORD WINAPI SHLWAPI_193 ()
@@ -392,20 +1182,90 @@
 
 /*************************************************************************
- *      SHLWAPI_215	[SHLWAPI.215]
+ *      @	[SHLWAPI.199]
+ *
+ * Copy interface pointer
+ */
+DWORD WINAPI SHLWAPI_199 (
+	IUnknown **dest,   /* [out] pointer to copy of interface ptr */
+	IUnknown *src)     /* [in]  interface pointer */
+{
+        TRACE("(%p %p)\n",dest,src);
+	if (*dest != src) {
+	    if (*dest)
+		IUnknown_Release(*dest);
+	    if (src) {
+		IUnknown_AddRef(src);
+		*dest = src;
+	    }
+	}
+	return 4;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.208]
+ *
+ * Some sort of memory management process - associated with _210
+ */
+DWORD WINAPI SHLWAPI_208 (
+	DWORD    a,
+	DWORD    b,
+	LPVOID   c,
+	LPVOID   d,
+	DWORD    e)
+{
+    FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
+	  a, b, c, d, e);
+    return 1;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.210]
+ *
+ * Some sort of memory management process - associated with _208
+ */
+DWORD WINAPI SHLWAPI_210 (
+	LPVOID   a,
+	DWORD    b,
+	LPVOID   c)
+{
+    FIXME("(%p 0x%08lx %p) stub\n",
+	  a, b, c);
+    return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.211]
+ */
+DWORD WINAPI SHLWAPI_211 (
+	LPVOID   a,
+	DWORD    b)
+{
+    FIXME("(%p 0x%08lx) stub\n",
+	  a, b);
+    return 1;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.215]
  *
  * NOTES
  *  check me!
  */
-LPWSTR WINAPI SHLWAPI_215 (
-	LPWSTR lpStrSrc,
-	LPVOID lpwStrDest,
+DWORD WINAPI SHLWAPI_215 (
+	LPCSTR lpStrSrc,
+	LPWSTR lpwStrDest,
 	int len)
 {
-	WARN("(%p %p %u)\n",lpStrSrc,lpwStrDest,len);
-	return strncpyW(lpwStrDest, lpStrSrc, len);
-}
-
-/*************************************************************************
- *      SHLWAPI_218	[SHLWAPI.218]
+	INT len_a, ret;
+
+	len_a = lstrlenA(lpStrSrc);
+	ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
+	TRACE("%s %s %d, ret=%d\n", 
+	      debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
+	return ret;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.218]
  *
  * WideCharToMultiByte with multi language support.
@@ -414,9 +1274,5 @@
                        LPINT lpnMultiCharCount)
 {
-#ifdef __WIN32OS2__
   static HRESULT (* WINAPI pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
-#else
-  static HRESULT (* WINAPI pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
-#endif
   WCHAR emptyW[] = { '\0' };
   int len , reqLen;
@@ -501,32 +1357,75 @@
 
 /*************************************************************************
- *      SHLWAPI_217	[SHLWAPI.217]
- *
- */
-INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, LPINT lpnMultiCharCount)
-{
-  return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, lpnMultiCharCount);
-}
-
-#ifndef __WIN32OS2__
-/*************************************************************************
- *      SHLWAPI_219	[SHLWAPI.219]
+ *      @	[SHLWAPI.217]
+ *
+ * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
+ * --> Crash. Something wrong here.
+ *
+ * It seems from OE v5 that the third param is the count. (GA 11/2001)
+ */
+INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
+{
+    INT myint = MultiCharCount;
+
+    return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.219]
+ *
+ * Seems to be "super" QueryInterface. Supplied with at table of interfaces
+ * and an array of IIDs and offsets into the table.
  *
  * NOTES
  *  error codes: E_POINTER, E_NOINTERFACE
  */
+typedef struct {
+    REFIID   refid;
+    DWORD    indx;
+} IFACE_INDEX_TBL;
+
 HRESULT WINAPI SHLWAPI_219 (
-	LPVOID w, /* [???] NOTE: returned by LocalAlloc, 0x450 bytes, iface */
-	LPVOID x,
-	REFIID riid,
-	LPWSTR z) /* [???] NOTE: OUT: path */
-{
-	FIXME("(%p %p %s %p)stub\n",w,x,debugstr_guid(riid),z);
-	return 0xabba1252;
-}
-#endif
-
-/*************************************************************************
- *      SHLWAPI_222	[SHLWAPI.222]
+	LPVOID w,           /* [in]   table of interfaces                   */
+	IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
+	REFIID riid,        /* [in]   REFIID to get interface for           */
+	LPVOID *z)          /* [out]  location to get interface pointer     */
+{
+	HRESULT ret;
+	IUnknown *a_vtbl;
+	IFACE_INDEX_TBL *xmove;
+
+	TRACE("(%p %p %s %p)\n",
+	      w,x,debugstr_guid(riid),z);
+	if (z) {
+	    xmove = x;
+	    while (xmove->refid) {
+		TRACE("trying (indx %ld) %s\n", xmove->indx, 
+		      debugstr_guid(xmove->refid));
+		if (IsEqualIID(riid, xmove->refid)) {
+		    a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
+		    TRACE("matched, returning (%p)\n", a_vtbl);
+		    *z = (LPVOID)a_vtbl;
+		    IUnknown_AddRef(a_vtbl);
+		    return S_OK;
+		}
+		xmove++;
+	    }
+
+	    if (IsEqualIID(riid, &IID_IUnknown)) {
+		a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
+		TRACE("returning first for IUnknown (%p)\n", a_vtbl);
+		*z = (LPVOID)a_vtbl;
+		IUnknown_AddRef(a_vtbl);
+		return S_OK;
+	    }
+	    *z = 0;
+	    ret = E_NOINTERFACE;
+	} else
+	    ret = E_POINTER;
+	return ret;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.222]
  *
  * NOTES
@@ -546,5 +1445,5 @@
 
 /*************************************************************************
- *      SHLWAPI_223	[SHLWAPI.223]
+ *      @	[SHLWAPI.223]
  *
  * NOTES
@@ -563,5 +1462,25 @@
 
 /*************************************************************************
- *      SHLWAPI_237	[SHLWAPI.237]
+ *      @	[SHLWAPI.236]
+ */
+HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
+{
+    HKEY newkey;
+    DWORD type, count;
+    CHAR value[MAX_PATH], string[MAX_PATH];
+
+    strcpy(string, "CLSID\\");
+    strcat(string, debugstr_guid(lpUnknown));
+    strcat(string, "\\InProcServer32");
+
+    count = MAX_PATH;
+    RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
+    RegQueryValueExA(newkey, 0, 0, &type, value, &count);
+    RegCloseKey(newkey);
+    return LoadLibraryExA(value, 0, 0);
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.237]
  *
  * Unicode version of SHLWAPI_183.
@@ -579,5 +1498,27 @@
 
 /*************************************************************************
- *      SHLWAPI_240	[SHLWAPI.240]
+ *      @	[SHLWAPI.239]
+ */
+DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
+{
+    FIXME("(0x%08x %p 0x%08lx) stub\n",
+	  hInstance, p2, dw3);
+    return 0;
+#if 0
+    /* pseudo code from relay trace */
+    WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
+    GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
+    /* above pair repeated for:
+           TridentThicketUrlDlClass
+	   Shell Embedding
+	   CIESplashScreen
+	   Inet Notify_Hidden
+	   OCHost
+    */
+#endif
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.240]
  *
  *	Calls ASCII or Unicode WindowProc for the given window.
@@ -589,7 +1530,7 @@
 	return DefWindowProcA(hWnd, uMessage, wParam, lParam);
 }
-#ifndef __WIN32OS2__
-/*************************************************************************
- *      SHLWAPI_241	[SHLWAPI.241]
+
+/*************************************************************************
+ *      @	[SHLWAPI.241]
  *
  */
@@ -597,9 +1538,9 @@
 {
 	FIXME("()stub\n");
-	return 0xabba1243;
-}
-
-/*************************************************************************
- *      SHLWAPI_266	[SHLWAPI.266]
+	return /* 0xabba1243 */ 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.266]
  */
 DWORD WINAPI SHLWAPI_266 (
@@ -614,5 +1555,5 @@
 
 /*************************************************************************
- *      SHLWAPI_267	[SHLWAPI.267]
+ *      @	[SHLWAPI.267]
  */
 HRESULT WINAPI SHLWAPI_267 (
@@ -628,5 +1569,5 @@
 
 /*************************************************************************
- *      SHLWAPI_268	[SHLWAPI.268]
+ *      @	[SHLWAPI.268]
  */
 DWORD WINAPI SHLWAPI_268 (
@@ -639,5 +1580,5 @@
 
 /*************************************************************************
- *      SHLWAPI_276	[SHLWAPI.276]
+ *      @	[SHLWAPI.276]
  *
  */
@@ -645,12 +1586,12 @@
 {
 	FIXME("()stub\n");
-	return 0xabba1244;
-}
-#endif
-/*************************************************************************
- *      SHLWAPI_278	[SHLWAPI.278]
- *
- */
-DWORD WINAPI SHLWAPI_278 (
+	return /* 0xabba1244 */ 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.278]
+ *
+ */
+HWND WINAPI SHLWAPI_278 (
 	LONG wndProc,
 	HWND hWndParent,
@@ -665,5 +1606,5 @@
 	char * clsname = "WorkerA";
 
-	FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx)stub\n",
+	FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
 	  wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
 
@@ -690,5 +1631,5 @@
 
 /*************************************************************************
- *      SHLWAPI_289	[SHLWAPI.289]
+ *      @	[SHLWAPI.289]
  *
  * Late bound call to winmm.PlaySoundW
@@ -703,5 +1644,29 @@
 
 /*************************************************************************
- *      SHLWAPI_313	[SHLWAPI.313]
+ *      @	[SHLWAPI.294]
+ */
+BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
+{
+    /*
+     * str1:		"I"	"I"	pushl esp+0x20
+     * str2:		"U"	"I"	pushl 0x77c93810
+     * (is "I" and "U" "integer" and "unsigned" ??)
+     *
+     * pStr:		""	""	pushl eax
+     * some_len:	0x824	0x104	pushl 0x824
+     * lpStr2:		"%l"	"%l"	pushl esp+0xc
+     *
+     * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
+     * LocalAlloc(0x00, some_len) -> irrelevant_var
+     * LocalAlloc(0x40, irrelevant_len) -> pStr
+     * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
+     * shlwapi.PathRemoveBlanksW(pStr);
+     */
+    ERR("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
+    return TRUE;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.313]
  *
  * Late bound call to shell32.SHGetFileInfoW
@@ -717,5 +1682,5 @@
 
 /*************************************************************************
- *      SHLWAPI_318	[SHLWAPI.318]
+ *      @	[SHLWAPI.318]
  *
  * Late bound call to shell32.DragQueryFileW
@@ -730,5 +1695,5 @@
 
 /*************************************************************************
- *      SHLWAPI_333	[SHLWAPI.333]
+ *      @	[SHLWAPI.333]
  *
  * Late bound call to shell32.SHBrowseForFolderW
@@ -743,5 +1708,5 @@
 
 /*************************************************************************
- *      SHLWAPI_334	[SHLWAPI.334]
+ *      @	[SHLWAPI.334]
  *
  * Late bound call to shell32.SHGetPathFromIDListW
@@ -756,5 +1721,5 @@
 
 /*************************************************************************
- *      SHLWAPI_335	[SHLWAPI.335]
+ *      @	[SHLWAPI.335]
  *
  * Late bound call to shell32.ShellExecuteExW
@@ -769,5 +1734,5 @@
 
 /*************************************************************************
- *      SHLWAPI_336	[SHLWAPI.336]
+ *      @	[SHLWAPI.336]
  *
  * Late bound call to shell32.SHFileOperationW.
@@ -782,5 +1747,5 @@
 
 /*************************************************************************
- *      SHLWAPI_337	[SHLWAPI.337]
+ *      @	[SHLWAPI.337]
  *
  * Late bound call to shell32.ExtractIconExW.
@@ -794,22 +1759,21 @@
   return pfnFunc(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
 }
-#ifndef __WIN32OS2__
-//Bugbug: is forwarder for InterlockedCompareExchange
-/*************************************************************************
- *      SHLWAPI_342	[SHLWAPI.342]
+
+/*************************************************************************
+ *      @	[SHLWAPI.342]
  *
  */
 DWORD WINAPI SHLWAPI_342 (
-	LPVOID w,
-	LPVOID x,
-	LPVOID y,
-	LPVOID z)
-{
-	FIXME("(%p %p %p %p)stub\n",w,x,y,z);
-	return 0xabba1249;
-}
-#endif
-/*************************************************************************
- *      SHLWAPI_346	[SHLWAPI.346]
+	LPDWORD  w,   /* [out] location to put HKEY value???   */
+	HKEY     x,   /* [in]  appears to be HKEY_CURRENT_USER */
+	LPVOID y)
+{
+	FIXME("(%p 0x%08x %p)stub\n", w,x,y);
+	*w = (DWORD)x;
+	return /* 0xabba1249 */ 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.346]
  */
 DWORD WINAPI SHLWAPI_346 (
@@ -824,5 +1788,17 @@
 
 /*************************************************************************
- *      SHLWAPI_357	[SHLWAPI.357]
+ *      @	[SHLWAPI.356]
+ */
+DWORD WINAPI SHLWAPI_356 (
+	LPVOID x,
+	LPVOID y,
+	LPVOID z)
+{
+	FIXME("(%p %p %p)stub\n", x,y,z);
+	return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.357]
  *
  * Late bound call to shell32.SHGetNewLinkInfoW
@@ -838,5 +1814,5 @@
 
 /*************************************************************************
- *      SHLWAPI_358	[SHLWAPI.358]
+ *      @	[SHLWAPI.358]
  *
  * Late bound call to shell32.SHDefExtractIconW
@@ -853,5 +1829,5 @@
 
 /*************************************************************************
- *      SHLWAPI_364	[SHLWAPI.364]
+ *      @	[SHLWAPI.364]
  *
  * Wrapper for lstrcpynA with src and dst swapped.
@@ -864,5 +1840,5 @@
 
 /*************************************************************************
- *      SHLWAPI_370	[SHLWAPI.370]
+ *      @	[SHLWAPI.370]
  *
  * Late bound call to shell32.ExtractIconW
@@ -878,38 +1854,76 @@
 
 /*************************************************************************
- *      SHLWAPI_376	[SHLWAPI.376]
- */
-DWORD WINAPI SHLWAPI_376 (LONG x)
-{
-	FIXME("(0x%08lx)stub\n", x );
-  /* FIXME: This should be a forward in the .spec file to the win2k function
-   * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
-   */
-  return 0xabba1245;
-}
-#ifndef __WIN32OS2__
-/*************************************************************************
- *      SHLWAPI_377	[SHLWAPI.377]
- */
-DWORD WINAPI SHLWAPI_377 (LPVOID x, LPVOID y, LPVOID z)
-{
-	FIXME("(%p %p %p)stub\n", x,y,z);
-	return 0xabba1246;
-}
-#endif
-/*************************************************************************
- *      SHLWAPI_378	[SHLWAPI.378]
+ *      @	[SHLWAPI.376]
+ */
+LANGID WINAPI SHLWAPI_376 ()
+{
+    FIXME("() stub\n");
+    /* FIXME: This should be a forward in the .spec file to the win2k function
+     * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
+     */
+    return GetUserDefaultLangID();
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.377]
+ *
+ * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for 
+ *        each call here.
+ * FIXME: Native shows calls to:
+ *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
+ *                      CheckVersion
+ *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
+ *  RegQueryValueExA for "LPKInstalled"
+ *  RegCloseKey
+ *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
+ *  RegQueryValueExA for "ResourceLocale"
+ *  RegCloseKey
+ *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
+ *  RegQueryValueExA for "Locale"
+ *  RegCloseKey
+ *  and then tests the Locale ("en" for me).
+ *     code below
+ *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
+ */
+DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
+{
+    CHAR mod_path[2*MAX_PATH];
+    LPSTR ptr;
+
+    GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
+    ptr = strrchr(mod_path, '\\');
+    if (ptr) {
+	strcpy(ptr+1, new_mod);
+	TRACE("loading %s\n", debugstr_a(mod_path));
+	return (DWORD)LoadLibraryA(mod_path);
+    }
+    return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.378]
+ *
+ *  This is Unicode version of .377
  */
 DWORD WINAPI SHLWAPI_378 (
-	LPSTR x,
-	LPVOID y, /* [???] 0x50000000 */
-	LPVOID z) /* [???] 4 */
-{
-	FIXME("(%s %p %p)stub\n", x,y,z);
-	return LoadLibraryA(x);
-}
-
-/*************************************************************************
- *      SHLWAPI_389	[SHLWAPI.389]
+	LPCWSTR   new_mod,          /* [in] new module name        */
+	HMODULE   inst_hwnd,        /* [in] calling module handle  */
+	LPVOID z)                   /* [???] 4 */
+{
+    WCHAR mod_path[2*MAX_PATH];
+    LPWSTR ptr;
+
+    GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
+    ptr = strrchrW(mod_path, '\\');
+    if (ptr) {
+	strcpyW(ptr+1, new_mod);
+	TRACE("loading %s\n", debugstr_w(mod_path));
+	return (DWORD)LoadLibraryW(mod_path);
+    }
+    return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.389]
  *
  * Late bound call to comdlg32.GetSaveFileNameW
@@ -924,5 +1938,5 @@
 
 /*************************************************************************
- *      SHLWAPI_390	[SHLWAPI.390]
+ *      @	[SHLWAPI.390]
  *
  * Late bound call to mpr.WNetRestoreConnectionW
@@ -938,5 +1952,5 @@
 
 /*************************************************************************
- *      SHLWAPI_391	[SHLWAPI.391]
+ *      @	[SHLWAPI.391]
  *
  * Late bound call to mpr.WNetGetLastErrorW
@@ -953,5 +1967,5 @@
 
 /*************************************************************************
- *      SHLWAPI_401	[SHLWAPI.401]
+ *      @	[SHLWAPI.401]
  *
  * Late bound call to comdlg32.PageSetupDlgW
@@ -966,5 +1980,5 @@
 
 /*************************************************************************
- *      SHLWAPI_402	[SHLWAPI.402]
+ *      @	[SHLWAPI.402]
  *
  * Late bound call to comdlg32.PrintDlgW
@@ -979,5 +1993,5 @@
 
 /*************************************************************************
- *      SHLWAPI_403	[SHLWAPI.403]
+ *      @	[SHLWAPI.403]
  *
  * Late bound call to comdlg32.GetOpenFileNameW
@@ -1044,5 +2058,16 @@
 
 /*************************************************************************
- *      SHLWAPI_431	[SHLWAPI.431]
+ *      @	[SHLWAPI.413]
+ *
+ * Function unknown seems to always to return 0
+ */
+DWORD WINAPI SHLWAPI_413 (DWORD x)
+{
+	FIXME("(0x%08lx)stub\n", x);
+	return 0;
+}
+
+/*************************************************************************
+ *      @	[SHLWAPI.431]
  */
 DWORD WINAPI SHLWAPI_431 (DWORD x)
@@ -1054,8 +2079,8 @@
 #ifndef __WIN32OS2__
 /*************************************************************************
- *      SHLWAPI_437	[SHLWAPI.437]
+ *      @	[SHLWAPI.437]
  *
  * NOTES
- *  In the real shlwapi, One time initilisation calls GetVersionEx and reads
+ *  In the real shlwapi, One time initialisation calls GetVersionEx and reads
  *  the registry to determine what O/S & Service Pack level is running, and
  *  therefore which functions are available. Currently we always run as NT,
@@ -1068,7 +2093,21 @@
 {
 	FIXME("(0x%08lx)stub\n", functionToCall);
-	return 0xabba1247;
+	return /* 0xabba1247 */ 0;
 }
 #endif
+/*************************************************************************
+ *      ColorRGBToHLS	[SHLWAPI.445]
+ *
+ * Convert from RGB COLORREF into the HLS color space.
+ *
+ * NOTES
+ * Input HLS values are constrained to the range (0..240).
+ */
+VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue, 
+			  LPWORD wLuminance, LPWORD pwSaturation)
+{
+    FIXME("stub\n");
+    return;
+}
 
 /*************************************************************************
@@ -1082,5 +2121,5 @@
 
 /*************************************************************************
- *	SHGetInverseCMAP
+ *	SHGetInverseCMAP (SHLWAPI.@)
  */
 DWORD WINAPI SHGetInverseCMAP (LPVOID x, DWORD why)
@@ -1089,4 +2128,5 @@
 	return 0;
 }
+
 #ifndef __WIN32OS2__
 /*************************************************************************
@@ -1099,5 +2139,4 @@
 }
 #endif
-
 /*************************************************************************
  *      GetMenuPosFromID	[SHLWAPI.@]
@@ -1119,5 +2158,5 @@
 
 /*************************************************************************
- *      _SHGetInstanceExplorer	[SHLWAPI.@]
+ *      _SHGetInstanceExplorer@4	[SHLWAPI.@]
  *
  * Late bound call to shell32.SHGetInstanceExplorer.
Index: trunk/src/shlwapi/ordinal.h
===================================================================
--- trunk/src/shlwapi/ordinal.h	(revision 7820)
+++ trunk/src/shlwapi/ordinal.h	(revision 7820)
@@ -0,0 +1,29 @@
+/*
+ * Internal structures (read "undocumented") used by the
+ * ordinal entry points.
+ *
+ * Determined by experimentation.
+ */
+
+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;
+
+DWORD WINAPI SHLWAPI_1(LPCSTR x, UNKNOWN_SHLWAPI_1 *y);
+
+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;
+
+DWORD WINAPI SHLWAPI_2(LPCWSTR x, UNKNOWN_SHLWAPI_2 *y);
+
Index: trunk/src/shlwapi/ordinal_odin.cpp
===================================================================
--- trunk/src/shlwapi/ordinal_odin.cpp	(revision 7815)
+++ trunk/src/shlwapi/ordinal_odin.cpp	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: ordinal_odin.cpp,v 1.4 2001-08-31 19:56:34 phaller Exp $ */
+/* $Id: ordinal_odin.cpp,v 1.5 2002-02-06 20:18:27 sandervl Exp $ */
 
 /*
@@ -68,4 +68,5 @@
 
 
+#if 0
 /*****************************************************************************
  * Prototypes                                                                *
@@ -74,6 +75,4 @@
 HANDLE WIN32API SHLWAPI_11(HANDLE, DWORD, DWORD, DWORD, DWORD);
 
-
-#define debugstr_guid(a) a
 
 
@@ -269,28 +268,6 @@
   return NO_ERROR;
 }
-
-
-/*****************************************************************************
- * Name      : ParseURLIntoProtocolAndURI_W
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    :
- * Status    : UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,              SHLWAPI_2,
-              LPWSTR,             lpszURL,
-              LPPROTOCOLHANDLERW, lpHandler)
-{
-  dprintf(("not yet implemented"));
-
-  // PH: do unicode conversion, call SHLWAPI_1 
-
-  return 0;
-}
+#endif
+
 
 
@@ -424,4 +401,32 @@
 }
 
+
+
+
+
+/*****************************************************************************
+ * Name      : ???
+ * Purpose   : Looks like a strdup()
+ * Parameters: Unknown (wrong)
+ * Variables :
+ * Result    : Unknown
+ * Remark    :
+ * Status    : UNTESTED STUB
+ *
+ * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
+ *****************************************************************************/
+
+ODINFUNCTION2(DWORD,SHLWAPI_12,
+              DWORD,arg0,
+              DWORD,arg1)
+{
+  dprintf(("not implemented, explorer.exe will trap now"));
+
+  return 0;
+}
+
+
+
+
 /*****************************************************************************
  * Name      : ???
@@ -436,49 +441,14 @@
  *****************************************************************************/
 
-ODINFUNCTION3(DWORD,SHLWAPI_7,
+ODINFUNCTION2(DWORD,SHLWAPI_17,
               DWORD, arg0,
-              DWORD, arg1,
-              DWORD, arg2)
-{
-  HANDLE hMap;
-  LPVOID lpMap;
-  DWORD  dwResult;
-
-  dprintf(("not implemented"));
-
-  // create mapping
-  hMap = CreateFileMappingA(-1,
-                            NULL,
-                            PAGE_READWRITE,
-                            0,
-                            arg1,
-                            0);
-  if (hMap == NULL)
-    return FALSE;
-
-  // now map the thing
-  lpMap = MapViewOfFile(hMap,
-                        FILE_MAP_READ | FILE_MAP_WRITE,
-                        0,
-                        0,
-                        0);
-  if (lpMap == NULL)
-  {
-    CloseHandle(hMap);
-    return FALSE;
-  }
-
-  /*  @@@PH copy someting into the shared segment */
-
-  UnmapViewOfFile(lpMap);
-  dwResult = SHLWAPI_11(hMap,
-                        GetCurrentProcessId(),
-                        arg2,
-                        FILE_MAP_ALL_ACCESS,
-                        2);
-  CloseHandle(hMap);
-
-  return dwResult;
-}
+              DWORD, arg1)
+{
+  dprintf(("not implemented, explorer.exe will trap now"));
+
+  return 0;
+}
+
+
 
 
@@ -495,317 +465,4 @@
  *****************************************************************************/
 
-ODINFUNCTION2(DWORD,  SHLWAPI_8,
-              HANDLE, hMap,
-              DWORD,  arg1)
-{
-  HANDLE hHandle;
-  LPVOID lpBase;
-
-  hHandle = SHLWAPI_11(hMap,
-                       arg1,
-                       GetCurrentProcessId(),
-                       FILE_MAP_ALL_ACCESS,
-                       0);
-  lpBase = MapViewOfFile(hHandle,
-                         FILE_MAP_READ | FILE_MAP_WRITE,
-                         0,
-                         0,
-                         0);
-  CloseHandle(hHandle);
-
-  if (lpBase == NULL)
-    return NULL;
-  else
-    return (DWORD)lpBase+4; // lea eax, [ebx + 4]
-}
-
-
-/*****************************************************************************
- * Name      :
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    :
- * Status    : COMPLETELY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION1(DWORD,  SHLWAPI_9,
-              LPBYTE, lpBase)
-{
-  return (UnmapViewOfFile( (LPVOID) ((DWORD)lpBase & 0xFFFFFFFC)) );
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    :
- * Status    : COMPLETELY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,  SHLWAPI_10,
-              HANDLE, hMap,
-              DWORD,  arg1)
-{
-  HANDLE hHandle;
-
-  hHandle = SHLWAPI_11(hMap,
-                       arg1,
-                       GetCurrentProcessId(),
-                       FILE_MAP_ALL_ACCESS,
-                       1);
-  return CloseHandle(hHandle);
-}
-
-
-/*****************************************************************************
- * Name      :
- * Purpose   : Duplicate the handle to the shell shared segment
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : SHLWAPI.11 - wrong implementation, check again
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION5(HANDLE, SHLWAPI_11,
-              HANDLE, hMap,
-              DWORD,  dwProcessDest,
-              DWORD,  dwCurrentPID,
-              DWORD,  dwAccess,
-              DWORD,  dwFlag)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  DWORD  dwMyPID = GetCurrentProcessId();
-  HANDLE hProcess;
-  HANDLE hTargetHandle;
-  HANDLE hTargetProcessHandle = dwProcessDest;
-  BOOL   fResult;
-
-  // open desired process
-  if (dwMyPID == dwProcessDest)
-    hProcess == GetCurrentProcess();
-  else
-    hProcess == OpenProcess(PROCESS_DUP_HANDLE,
-                            FALSE,
-                            dwProcessDest);
-
-  // verify result
-  if (hProcess == NULL)
-    return 0;
-
-  // duplicate handle
-  fResult = DuplicateHandle(hProcess,
-                            hMap,
-                            hTargetProcessHandle,
-                            &hTargetHandle,
-                            dwAccess,
-                            0,
-                            dwFlag | 0x02);
-  //CloseHandle()
-
-  return fResult;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Looks like a strdup()
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_12,
-              DWORD,arg0,
-              DWORD,arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters:
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_13,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_14,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_15,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    : SHLWAPI.16
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION4(HANDLE,SHCreateThread,
-              DWORD, arg0,
-              DWORD, arg1,
-              DWORD, arg2,
-              DWORD, arg3)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_17,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_18,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : SHLWAPI_19
- * Purpose   : Free memory
- * Parameters: LPVOID lpMem
- * Variables :
- * Result    :
- * Remark    : SHLWAPI.19
- * Status    : COMPLETELY IMPLEMENTED ? UNTESTED
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINPROCEDURE1(SHLWAPI_19,
-               HLOCAL, hMem)
-{
-  if (hMem != NULL)
-    LocalFree(hMem);
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
 ODINFUNCTION2(DWORD,SHLWAPI_20,
               DWORD, arg0,
@@ -818,119 +475,8 @@
 
 
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_21,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : ???
- * Purpose   : Unknown (used by explorer.exe)
- * Parameters: Unknown (wrong)
- * Variables :
- * Result    : Unknown
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
- *****************************************************************************/
-
-ODINFUNCTION2(DWORD,SHLWAPI_22,
-              DWORD, arg0,
-              DWORD, arg1)
-{
-  dprintf(("not implemented, explorer.exe will trap now"));
-
-  return 0;
-}
-
-
-
-
-/*****************************************************************************
- * Name      : SHLWAPI_28
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    :
- * Status    : UNTESTED STUB
- *
- * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
- *****************************************************************************/
-
-ODINFUNCTION1(DWORD,SHLWAPI_28,
-              DWORD,arg0)
-{
-  dprintf(("not yet implemented"));
-
-  return 0;
-}
-
-
-
-
-
-
-/*****************************************************************************
- * Name      : DWORD SHLWAPI_158
- * Purpose   : Case-ignoring wide string compare
- * Parameters: LPSTR lpStr1
- *             LPSTR lpStr2
- * Variables :
- * Result    : case-insensitive comparsion result between the two strings
- * Remark    : SHLWAPI.158
- * Status    : COMPLETELY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
- *****************************************************************************/
-
-ODINFUNCTION2(int,     SHLWAPI_158,
-              LPWSTR,  lpStr1,
-              LPWSTR,  lpStr2)
-{
-  WCHAR ch1;
-  WCHAR ch2;
-  int   res;
-
-  for (;
-
-       *lpStr1 != 0;
-
-       lpStr1++,
-       lpStr2++)
-  {
-    ch1 = *lpStr1;
-    ch2 = *lpStr2;
-
-    /* ignore case of characters */
-    if ( (ch1 >= 'A') && (ch1 <= 'Z')) ch1 += 0x20;
-    if ( (ch2 >= 'A') && (ch2 <= 'Z')) ch1 += 0x20;
-
-    /* compare characters */
-    res = ch1 - ch2;
-    if (res)
-      return res;
-  }
-
-  /* OK, strings compared til end of string1 */
-  return 0;
-}
+
+
+
+
 
 
@@ -1121,31 +667,4 @@
 
 
-/*************************************************************************
-*      SHLWAPI_219 [SHLWAPI]
-*/
-ODINFUNCTION4(HRESULT, SHLWAPI_219,
-              LPVOID,  w, /* returned by LocalAlloc */
-              LPVOID,  x,
-              LPVOID,  y,
-              LPWSTR,  z) /* OUT: path */
-{
-  FIXME("(%p %p %p %p)stub\n",w,x,y,z);
-  return 0xabba1252;
-}
-
-
-
-
-
-/*************************************************************************
-*      SHLWAPI_241 [SHLWAPI]
-*
-*/
-ODINFUNCTION0(DWORD, SHLWAPI_241)
-{
-  FIXME("()stub\n");
-  return 0xabba1243;
-}
-
 
 /*****************************************************************************
@@ -1171,133 +690,4 @@
   return 0;
 }
-
-
-/*************************************************************************
-*      SHLWAPI_266 [SHLWAPI]
-*/
-ODINFUNCTION4(DWORD,  SHLWAPI_266,
-              LPVOID, w,
-              LPVOID, x,
-              LPVOID, y,
-              LPVOID, z)
-{
-  FIXME("(%p %p %p %p)stub\n",w,x,y,z);
-  return 0xabba1248;
-}
-
-/*************************************************************************
-*      SHLWAPI_267 [SHLWAPI]
-*/
-ODINFUNCTION4(HRESULT, SHLWAPI_267,
-              LPVOID,  w, /* same as 1th parameter of SHLWAPI_219 */
-              LPVOID,  x, /* same as 2nd parameter of SHLWAPI_219 */
-              LPVOID,  y,
-              LPVOID,  z)
-{
-  FIXME("(%p %p %p %p)stub\n",w,x,y,z);
-  *((LPDWORD)z) = 0xabba1200;
-  return 0xabba1254;
-}
-
-/*************************************************************************
-*      SHLWAPI_268 [SHLWAPI]
-*/
-ODINFUNCTION2(DWORD,  SHLWAPI_268,
-              LPVOID, w,
-              LPVOID, x)
-{
-  FIXME("(%p %p)\n",w,x);
-  return 0xabba1251; /* 0 = failure */
-}
-
-/*************************************************************************
-*      SHLWAPI_276 [SHLWAPI]
-
-* dynamically load SHELL32.DllGetVersion
-*
-*/
-ODINFUNCTION0(DWORD, SHLWAPI_276)
-{
-  FIXME("()stub\n");
-  return 0xabba1244;
-}
-
-/*****************************************************************************
- * Name      : DWORD SHLWAPI_376
- * Purpose   : Try to determine user interface language
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : SHLWAPI.366
- * Status    : PARTIALLY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
- *****************************************************************************/
-
-ODINFUNCTION0(DWORD, SHLWAPI_376)
-{
-  /* Microsoft does a hell of a job here: looks for
-   * - Internet Explorer
-   * - Office
-   * - Lpk ?
-   * - Resource Locales
-   * - etc.
-   */
-
-  return 0x0409; // @@@PH maybe this is 'nuf for now.
-}
-
-
-
-/*************************************************************************
-*      SHLWAPI_377 [SHLWAPI]
-*/
-ODINFUNCTION3(DWORD,   SHLWAPI_377,
-              LPSTR,   lpstrModule,
-              HMODULE, hModule,
-              LPVOID,  z)
-{
-  static BOOL flagSHLWAPI_377Initialized       = FALSE;
-  static BOOL flagInternetExplorerCheckVersion = FALSE;
-
-  dprintf(("not (properly) implemented.\n"));
-
-  char szModuleName[260]; // MAXPATHLEN
-  HMODULE hModLanguage;
-
-  // initialize this subsystem
-  if (flagSHLWAPI_377Initialized == FALSE)
-  {
-    flagSHLWAPI_377Initialized = TRUE;
-
-    flagInternetExplorerCheckVersion =
-    SHRegGetBoolUSValueA("Software\\Microsoft\\Internet Explorer\\International",
-                         "CheckVersion",
-                         1,
-                         1);
-  }
-
-  if (lpstrModule == NULL) // Garbage in - garbage out
-    return 0;
-
-  if (0 == GetModuleFileNameA(hModule,
-                              szModuleName,
-                              sizeof(szModuleName)))
-  {
-    // treat error
-  }
-  else
-  {
-    PathRemoveFileSpecA(szModuleName);
-    PathAppendA(szModuleName,
-                lpstrModule);
-    // @@@PH twiddle around with the current IE codepage
-    hModLanguage = LoadLibraryA(szModuleName);
-  }
-
-
-  return hModLanguage;
-}
-
 
 /*****************************************************************************
Index: trunk/src/shlwapi/path.c
===================================================================
--- trunk/src/shlwapi/path.c	(revision 7815)
+++ trunk/src/shlwapi/path.c	(revision 7820)
@@ -2,21 +2,8 @@
  * Path Functions
  */
-#ifdef __WIN32OS2__
-#include <odin.h>
-#include <odinwrap.h>
-#include <os2sel.h>
-
-#include <string.h>
-#include <wctype.h>
-#include <wcstr.h>
-#define HAVE_WCTYPE_H
-#include <win\shlwapi.h>
-
-#include <heapstring.h>
-#include <wine\undocshell.h>
-#endif
 
 #include <ctype.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "winerror.h"
@@ -25,9 +12,13 @@
 #include "wingdi.h"
 #include "winuser.h"
+#include "winreg.h"
+#define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "debugtools.h"
-
+#include "ordinal.h"
 
 DEFAULT_DEBUG_CHANNEL(shell);
+
+INT __cdecl _wtoi(LPWSTR string);
 
 #define isSlash(x) ((x)=='\\' || (x)=='/')
@@ -453,5 +444,5 @@
 
 /*************************************************************************
- * PathStripPathA	[SHELLWAPI.@]
+ * PathStripPathA	[SHLWAPI.@]
  * 
  * NOTES
@@ -469,5 +460,5 @@
 
 /*************************************************************************
- * PathStripPathW	[SHELLWAPI.@]
+ * PathStripPathW	[SHLWAPI.@]
  */
 void WINAPI PathStripPathW(LPWSTR lpszPath)
@@ -747,15 +738,16 @@
 {
 	LPSTR lpstrComma = strchr(lpszPath, ',');
-	
-	FIXME("%s stub\n", debugstr_a(lpszPath));
+	int ret = 0;
+	
+	TRACE("%s\n", debugstr_a(lpszPath));
 
 	if (lpstrComma && lpstrComma[1])
 	{
 	  lpstrComma[0]='\0';
-/*	  return atoi(&lpstrComma[1]);	FIXME */
+	  ret = atoi(&lpstrComma[1]);
 	}
 	
 	PathUnquoteSpacesA(lpszPath);
-	return 0;
+	return ret;
 }
 
@@ -766,14 +758,15 @@
 {
 	LPWSTR lpstrComma = strchrW(lpszPath, ',');
-	
-	FIXME("%s stub\n", debugstr_w(lpszPath));
+	int ret = 0;
+	
+	TRACE("%s\n", debugstr_w(lpszPath));
 
 	if (lpstrComma && lpstrComma[1])
 	{
 	  lpstrComma[0]='\0';
-/*	  return _wtoi(&lpstrComma[1]);	FIXME */
+	  ret = _wtoi(&lpstrComma[1]);
 	}
 	PathUnquoteSpacesW(lpszPath);
-	return 0;
+	return ret;
 }
 
@@ -785,7 +778,7 @@
  * PathFindOnPathA	[SHLWAPI.@]
  */
-BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
-{
-	FIXME("%s %s\n",sFile, sOtherDirs);
+BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR *sOtherDirs)
+{
+	FIXME("%s %p\n",sFile, sOtherDirs);
 	return FALSE;
 }
@@ -794,7 +787,7 @@
  * PathFindOnPathW	[SHLWAPI.@]
  */
-BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
-{
-	FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
+BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR *sOtherDirs)
+{
+	FIXME("%s %p\n",debugstr_w(sFile), sOtherDirs);
 	return FALSE;
 }
@@ -1118,5 +1111,5 @@
 	    if (lpszPath1[pos]=='\\') bsfound++;
 	    if (bsfound == 2) return TRUE;
-	    pos++; /* fixme: use CharNext*/
+	    pos++; /* FIXME: use CharNext*/
 	  }
 	  return (lpszPath1[pos] == lpszPath2[pos]);
@@ -1150,5 +1143,5 @@
 	    if (lpszPath1[pos]=='\\') bsfound++;
 	    if (bsfound == 2) return TRUE;
-	    pos++;/* fixme: use CharNext*/
+	    pos++;/* FIXME: use CharNext*/
 	  }
 	  return (lpszPath1[pos] == lpszPath2[pos]);
@@ -1158,69 +1151,33 @@
 
 /*************************************************************************
- * PathIsURLA
+ * PathIsURLA (SHLWAPI.@)
  */
 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
 {
-  // 2001-08-30 PH
-  // SHLWAPI/W95 Code:
-  //
-  // if (lpstrPath == NULL)
-  //   return FALSE;
-  //
-  // DWORD dwUnknown = SHREG_xxx; // 0x18
-  // return SHLWAPI_1(lpstrPath, &dwUnknown);
-  
-  
-	LPSTR lpstrRes;
-	int iSize, i=0;
-	static LPSTR SupportedProtocol[] = 
-	  {"http","https","ftp","gopher","file","mailto",NULL};
-
-	if(!lpstrPath) return FALSE;
-
-	/* get protocol        */
-	lpstrRes = strchr(lpstrPath,':');
-	if(!lpstrRes) return FALSE;
-	iSize = lpstrRes - lpstrPath;
-
-	while(SupportedProtocol[i])
-	{
-	  if (iSize == strlen(SupportedProtocol[i]))
-	    if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
-	      return TRUE;
-	  i++;
-	}
-
-	return FALSE;
+    UNKNOWN_SHLWAPI_1 base;
+    DWORD res1;
+
+    if (!lpstrPath || !*lpstrPath) return FALSE;
+
+    /* get protocol        */
+    base.size = 24;
+    res1 = SHLWAPI_1(lpstrPath, &base);
+    return (base.fcncde) ? TRUE : FALSE;
 }  
 
 /*************************************************************************
- * PathIsURLW
+ * PathIsURLW (SHLWAPI.@)
  */
 BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
 {
-	LPWSTR lpstrRes;
-	int iSize, i=0;
-	static WCHAR SupportedProtocol[7][7] = 
-	  {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
-	  {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
-	  {'m','a','i','l','t','o','\0'},{0}};
-
-	if(!lpstrPath) return FALSE;
-
-	/* get protocol        */
-	lpstrRes = strchrW(lpstrPath,':');
-	if(!lpstrRes) return FALSE;
-	iSize = lpstrRes - lpstrPath;
-
-	while(SupportedProtocol[i])
-	{
-	  if (iSize == strlenW(SupportedProtocol[i]))
-	    if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
-	      return TRUE;
-	  i++;
-	}
-
-	return FALSE;
+    UNKNOWN_SHLWAPI_2 base;
+    DWORD res1;
+
+    if (!lpstrPath || !*lpstrPath) return FALSE;
+
+    /* get protocol        */
+    base.size = 24;
+    res1 = SHLWAPI_2(lpstrPath, &base);
+    return (base.fcncde) ? TRUE : FALSE;
 }  
 
@@ -1302,7 +1259,19 @@
  */
 BOOL WINAPI PathIsUNCServerA(
-	LPCSTR pszPath)
-{
-	FIXME("%s\n", pszPath);
+	LPCSTR lpszPath)
+{
+	TRACE("%s\n", debugstr_a(lpszPath));
+	if (lpszPath[0]=='\\' && lpszPath[1]=='\\')		
+	{
+	  int foundbackslash = 0;
+	  lpszPath += 2;
+	  while (*lpszPath)
+	  {
+	    if (*lpszPath=='\\') foundbackslash++;
+	    lpszPath = CharNextA(lpszPath);
+	  }
+	  if (foundbackslash == 0)
+	    return TRUE;
+	}
 	return FALSE;
 }
@@ -1312,7 +1281,19 @@
  */
 BOOL WINAPI PathIsUNCServerW(
-	LPCWSTR pszPath)
-{
-	FIXME("%s\n", debugstr_w(pszPath));
+	LPCWSTR lpszPath)
+{
+	TRACE("%s\n", debugstr_w(lpszPath));
+	if (lpszPath[0]=='\\' && lpszPath[1]=='\\')		
+	{
+	  int foundbackslash = 0;
+	  lpszPath += 2;
+	  while (*lpszPath)
+	  {
+	    if (*lpszPath=='\\') foundbackslash++;
+	    lpszPath = CharNextW(lpszPath);
+	  }
+	  if (foundbackslash == 0)
+	    return TRUE;
+	}
 	return FALSE;
 }
@@ -1322,7 +1303,19 @@
  */
 BOOL WINAPI PathIsUNCServerShareA(
-	LPCSTR pszPath)
-{
-	FIXME("%s\n", pszPath);
+	LPCSTR lpszPath)
+{
+	TRACE("%s\n", debugstr_a(lpszPath));
+	if (lpszPath[0]=='\\' && lpszPath[1]=='\\')		
+	{
+	  int foundbackslash = 0;
+	  lpszPath += 2;
+	  while (*lpszPath)
+	  {
+	    if (*lpszPath=='\\') foundbackslash++;
+	    lpszPath = CharNextA(lpszPath);
+	  }
+	  if (foundbackslash == 1)
+	    return TRUE;
+	}
 	return FALSE;
 }
@@ -1332,7 +1325,19 @@
  */
 BOOL WINAPI PathIsUNCServerShareW(
-	LPCWSTR pszPath)
-{
-	FIXME("%s\n", debugstr_w(pszPath));
+	LPCWSTR lpszPath)
+{
+	TRACE("%s\n", debugstr_w(lpszPath));
+	if (lpszPath[0]=='\\' && lpszPath[1]=='\\')		
+	{
+	  int foundbackslash = 0;
+	  lpszPath += 2;
+	  while (*lpszPath)
+	  {
+	    if (*lpszPath=='\\') foundbackslash++;
+	    lpszPath = CharNextW(lpszPath);
+	  }
+	  if (foundbackslash == 1)
+	    return TRUE;
+	}
 	return FALSE;
 }
@@ -1693,6 +1698,12 @@
 BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
 {
-	FIXME("%s %s\n", pszPath, pszExt);
-	return FALSE;
+	LPSTR pszExtension = PathFindExtensionA(pszPath);
+
+	if (!pszExtension) return FALSE;
+	if (pszExtension-pszPath + strlen(pszExt) > MAX_PATH) return FALSE;
+
+	strcpy(pszExtension, pszExt);
+	TRACE("%s\n", pszPath);
+	return TRUE;
 }
 
@@ -1702,6 +1713,12 @@
 BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
 {
-	FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
-	return FALSE;
+	LPWSTR pszExtension = PathFindExtensionW(pszPath);
+
+	if (!pszExtension) return FALSE;
+	if (pszExtension-pszPath + strlenW(pszExt) > MAX_PATH) return FALSE;
+
+	strcpyW(pszExtension, pszExt);
+	TRACE("%s\n", debugstr_w(pszPath));
+	return TRUE;
 }
 
@@ -1759,7 +1776,13 @@
 	DWORD dwFlags)
 {
+    /* extracts thing prior to : in pszURL and checks against:
+     *   https
+     *   shell
+     *   local
+     *   about  - if match returns E_INVALIDARG
+     */
 	FIXME("%s %p %p 0x%08lx\n",
 	  pszUrl, pszPath, pcchPath, dwFlags);
-	return S_OK;
+	return E_INVALIDARG;
 }
 
@@ -1773,7 +1796,13 @@
 	DWORD dwFlags)
 {
+    /* extracts thing prior to : in pszURL and checks against:
+     *   https
+     *   shell
+     *   local
+     *   about  - if match returns E_INVALIDARG
+     */
 	FIXME("%s %p %p 0x%08lx\n",
 	  debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
-	return S_OK;
+	return E_INVALIDARG;
 }
 
Index: trunk/src/shlwapi/reg.c
===================================================================
--- trunk/src/shlwapi/reg.c	(revision 7815)
+++ trunk/src/shlwapi/reg.c	(revision 7820)
@@ -9,72 +9,125 @@
 #include "winuser.h"
 #include "winerror.h"
+#include "winnls.h"
 #include "winreg.h"
 #include "debugtools.h"
+#define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "wine/unicode.h"
 
+DEFAULT_DEBUG_CHANNEL(shell);
+
 #ifdef __WIN32OS2__
-
-#include "shlwapi_odin.h"
-
+typedef DWORD (* WINAPI RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
+#else
+typedef DWORD (WINAPI *RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
 #endif
-
-DEFAULT_DEBUG_CHANNEL(shell);
 
 static const char *lpszContentTypeA = "Content Type";
 static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
 
-/*************************************************************************
- * SHRegGetUSValueA	[SHLWAPI.@]
- *
- * Gets a user-specific registry value
- */
-LONG WINAPI SHRegGetUSValueA(
-	LPCSTR   pSubKey,
-	LPCSTR   pValue,
-	LPDWORD  pwType,
-	LPVOID   pvData,
-	LPDWORD  pbData,
-	BOOL     fIgnoreHKCU,
-	LPVOID   pDefaultData,
-	DWORD    wDefaultDataSize)
-{
-	FIXME("(%p),stub!\n", pSubKey);
-	return ERROR_SUCCESS;  /* return success */
-}
-
-/*************************************************************************
- * SHRegGetUSValueW	[SHLWAPI.@]
- *
- * Gets a user-specific registry value
- */
-LONG WINAPI SHRegGetUSValueW(
-	LPCWSTR  pSubKey,
-	LPCWSTR  pValue,
-	LPDWORD  pwType,
-	LPVOID   pvData,
-	LPDWORD  pbData,
-	BOOL     flagIgnoreHKCU,
-	LPVOID   pDefaultData,
-	DWORD    wDefaultDataSize)
-{
-	FIXME("(%p),stub!\n", pSubKey);
-	return ERROR_SUCCESS;  /* return success */
-}
+/* internal structure of what the HUSKEY points to */
+typedef struct {
+    HKEY     HKCUkey;                  /* HKEY of opened HKCU key      */
+    HKEY     HKLMkey;                  /* HKEY of opened HKLM key      */
+    HKEY     start;                    /* HKEY of where to start       */
+    WCHAR    key_string[MAX_PATH];     /* additional path from 'start' */
+} Internal_HUSKEY, *LPInternal_HUSKEY;
+
+
+#define REG_HKCU  TRUE
+#define REG_HKLM  FALSE
+/*************************************************************************
+ * REG_GetHKEYFromHUSKEY
+ *
+ * Function:  Return the proper registry key from the HUSKEY structure
+ *            also allow special predefined values.
+ */
+HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
+{
+        HKEY test = (HKEY) hUSKey;
+        LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
+
+	if ((test == HKEY_CLASSES_ROOT)        ||
+	    (test == HKEY_CURRENT_CONFIG)      ||
+	    (test == HKEY_CURRENT_USER)        ||
+	    (test == HKEY_DYN_DATA)            ||
+	    (test == HKEY_LOCAL_MACHINE)       ||
+	    (test == HKEY_PERFORMANCE_DATA)    ||
+/* FIXME:  need to define for Win2k, ME, XP
+ *	    (test == HKEY_PERFORMANCE_TEXT)    ||
+ *	    (test == HKEY_PERFORMANCE_NLSTEXT) ||
+ */
+	    (test == HKEY_USERS)) return test;
+	if (which == REG_HKCU) return mihk->HKCUkey;
+	return mihk->HKLMkey;
+}
+
 
 /*************************************************************************
  * SHRegOpenUSKeyA	[SHLWAPI.@]
  *
- * Openss a user-specific registry key
+ * Opens a user-specific registry key
  */
 LONG WINAPI SHRegOpenUSKeyA(
-        LPCSTR lpszPath,
-        DWORD  dwAccessType,
+        LPCSTR Path,
+        REGSAM AccessType,
         HUSKEY hRelativeUSKey,
         PHUSKEY phNewUSKey,
         BOOL fIgnoreHKCU)
 {
-	FIXME("stub!\n");
-	return ERROR_SUCCESS;  /* return success */
+    HKEY openHKCUkey=0;
+    HKEY openHKLMkey=0;
+    LONG ret2, ret1 = ~ERROR_SUCCESS;
+    LPInternal_HUSKEY ihky;
+
+    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path), 
+	  (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey, 
+	  (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
+
+    /* now create the internal version of HUSKEY */
+    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 , 
+					sizeof(Internal_HUSKEY));
+    MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
+			sizeof(ihky->key_string)-1);
+
+    if (hRelativeUSKey) {
+	openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
+	openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
+    }
+    else {
+	openHKCUkey = HKEY_CURRENT_USER;
+	openHKLMkey = HKEY_LOCAL_MACHINE;
+    }
+
+    ihky->HKCUkey = 0;
+    ihky->HKLMkey = 0;
+    if (!fIgnoreHKCU) {
+	ret1 = RegOpenKeyExA(openHKCUkey, Path, 
+			     0, AccessType, &ihky->HKCUkey);
+	/* if successful, then save real starting point */
+	if (ret1 != ERROR_SUCCESS)
+	    ihky->HKCUkey = 0;
+    }
+    ret2 = RegOpenKeyExA(openHKLMkey, Path, 
+			 0, AccessType, &ihky->HKLMkey);
+    if (ret2 != ERROR_SUCCESS)
+	ihky->HKLMkey = 0;
+
+    if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
+	TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
+
+    /* if all attempts have failed then bail */
+    if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
+	HeapFree(GetProcessHeap(), 0, ihky);
+	if (phNewUSKey)
+	    *phNewUSKey = (HUSKEY)0;
+	return ret2;
+    }
+
+    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
+    if (phNewUSKey)
+	*phNewUSKey = (HUSKEY)ihky;
+    return ERROR_SUCCESS;
 }
 
@@ -82,50 +135,91 @@
  * SHRegOpenUSKeyW	[SHLWAPI.@]
  *
- * Openss a user-specific registry key
+ * Opens a user-specific registry key
  */
 LONG WINAPI SHRegOpenUSKeyW(
-        LPCSTR lpszPath,
-        DWORD  dwAccessType,
+        LPCWSTR Path,
+        REGSAM AccessType,
         HUSKEY hRelativeUSKey,
-        HUSKEY hNewUSKey,
+        PHUSKEY phNewUSKey,
         BOOL fIgnoreHKCU)
 {
-	FIXME("stub!\n");
-	return ERROR_SUCCESS;  /* return success */
-}
-
-#ifndef __WIN32OS2__
-/*************************************************************************
- * SHRegGetBoolUSValueA   [SHLWAPI.@]
- */
-BOOL WINAPI SHRegGetBoolUSValueA(
-	LPCSTR pszSubKey,
-	LPCSTR pszValue,
-	BOOL fIgnoreHKCU,
-	BOOL fDefault)
-{
-	FIXME("%s %s\n", pszSubKey,pszValue);
-	return fDefault;
-}
-
-/*************************************************************************
- * SHRegGetBoolUSValueW	  [SHLWAPI.@]
- */
-BOOL WINAPI SHRegGetBoolUSValueW(
-	LPCWSTR pszSubKey,
-	LPCWSTR pszValue,
-	BOOL fIgnoreHKCU,
-	BOOL fDefault)
-{
-	FIXME("%s %s\n", debugstr_w(pszSubKey),debugstr_w(pszValue));
-	return fDefault;
-}
-#endif
-
-/*************************************************************************
- *      SHRegQueryUSValueA	[SHLWAPI]
+    HKEY openHKCUkey=0;
+    HKEY openHKLMkey=0;
+    LONG ret2, ret1 = ~ERROR_SUCCESS;
+    LPInternal_HUSKEY ihky;
+
+    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path), 
+	  (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey, 
+	  (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
+
+    /* now create the internal version of HUSKEY */
+    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 , 
+					sizeof(Internal_HUSKEY));
+    lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
+
+    if (hRelativeUSKey) {
+	openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
+	openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
+    }
+    else {
+	openHKCUkey = HKEY_CURRENT_USER;
+	openHKLMkey = HKEY_LOCAL_MACHINE;
+    }
+
+    ihky->HKCUkey = 0;
+    ihky->HKLMkey = 0;
+    if (!fIgnoreHKCU) {
+	ret1 = RegOpenKeyExW(openHKCUkey, Path, 
+			    0, AccessType, &ihky->HKCUkey);
+	/* if successful, then save real starting point */
+	if (ret1 != ERROR_SUCCESS)
+	    ihky->HKCUkey = 0;
+    }
+    ret2 = RegOpenKeyExW(openHKLMkey, Path, 
+			0, AccessType, &ihky->HKLMkey);
+    if (ret2 != ERROR_SUCCESS)
+	ihky->HKLMkey = 0;
+
+    if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
+	TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
+
+    /* if all attempts have failed then bail */
+    if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
+	HeapFree(GetProcessHeap(), 0, ihky);
+	if (phNewUSKey)
+	    *phNewUSKey = (HUSKEY)0;
+	return ret2;
+    }
+
+    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
+    if (phNewUSKey)
+	*phNewUSKey = (HUSKEY)ihky;
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegCloseUSKey	[SHLWAPI.@]
+ *
+ * Closes a user-specific registry key
+ */
+LONG WINAPI SHRegCloseUSKey(
+        HUSKEY hUSKey)
+{
+    LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
+    LONG ret = ERROR_SUCCESS;
+
+    if (mihk->HKCUkey)
+	ret = RegCloseKey(mihk->HKCUkey);
+    if (mihk->HKLMkey)
+	ret = RegCloseKey(mihk->HKLMkey);
+    HeapFree(GetProcessHeap(), 0, mihk);
+    return ret;
+}
+
+/*************************************************************************
+ *      SHRegQueryUSValueA	[SHLWAPI.@]
  */
 LONG WINAPI SHRegQueryUSValueA(
-	HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
+	HUSKEY hUSKey,             /* [in]  */
 	LPCSTR pszValue,
 	LPDWORD pdwType,
@@ -136,182 +230,852 @@
 	DWORD dwDefaultDataSize)
 {
-	FIXME("%s stub\n",pszValue);
-	return 1;
-}
-
-/*************************************************************************
- *      SHRegQueryUSValueA	[SHLWAPI]
+	LONG ret = ~ERROR_SUCCESS;
+	LONG i, maxmove;
+	HKEY dokey;
+	CHAR *src, *dst;
+
+	/* if user wants HKCU, and it exists, then try it */
+	if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    ret = RegQueryValueExA(dokey,
+				   pszValue, 0, pdwType, pvData, pcbData);
+	    TRACE("HKCU RegQueryValue returned %08lx\n", ret);
+	}
+
+	/* if HKCU did not work and HKLM exists, then try it */
+	if ((ret != ERROR_SUCCESS) &&
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    ret = RegQueryValueExA(dokey,
+				   pszValue, 0, pdwType, pvData, pcbData);
+	    TRACE("HKLM RegQueryValue returned %08lx\n", ret);
+	}
+
+	/* if neither worked, and default data exists, then use it */
+	if (ret != ERROR_SUCCESS) {
+	    if (pvDefaultData && (dwDefaultDataSize != 0)) {
+		maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
+		src = (CHAR*)pvDefaultData;
+		dst = (CHAR*)pvData;
+		for(i=0; i<maxmove; i++) *dst++ = *src++;
+		*pcbData = maxmove;
+		TRACE("setting default data\n");
+		ret = ERROR_SUCCESS;
+	    }
+	}
+	return ret;
+}
+
+
+/*************************************************************************
+ *      SHRegQueryUSValueW	[SHLWAPI.@]
  */
 LONG WINAPI SHRegQueryUSValueW(
-	HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
-	LPCSTR pszValue,
+	HUSKEY hUSKey,             /* [in]  */
+	LPCWSTR pszValue,
 	LPDWORD pdwType,
-	void *pvData,
+	LPVOID pvData,
 	LPDWORD pcbData,
 	BOOL fIgnoreHKCU,
-	void *pvDefaultData,
+	LPVOID pvDefaultData,
 	DWORD dwDefaultDataSize)
 {
-	FIXME("%s stub\n",pszValue);
-	return 1;
-}
-
-/*************************************************************************
- * SHRegGetPathA   [SHLWAPI.@]
- */
-DWORD WINAPI SHRegGetPathA(
-	HKEY hKey,
-	LPCSTR pcszSubKey,
-	LPCSTR pcszValue,
-	LPSTR pszPath,
-	DWORD dwFlags)
-{
-	FIXME("%s %s\n", pcszSubKey, pcszValue);
-	return 0;
-}
-
-/*************************************************************************
- * SHRegGetPathW   [SHLWAPI.@]
- */
-DWORD WINAPI SHRegGetPathW(
-	HKEY hKey,
-	LPCWSTR pcszSubKey,
-	LPCWSTR pcszValue,
-	LPWSTR pszPath,
-	DWORD dwFlags)
-{
-	FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
-	return 0;
-}
-
-/*************************************************************************
- * SHGetValueA   [SHLWAPI.@]
- *
- * Gets a value from the registry
- */
-DWORD WINAPI SHGetValueA(
-	HKEY     hkey,
+	LONG ret = ~ERROR_SUCCESS;
+	LONG i, maxmove;
+	HKEY dokey;
+	CHAR *src, *dst;
+
+	/* if user wants HKCU, and it exists, then try it */
+	if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    ret = RegQueryValueExW(dokey,
+				   pszValue, 0, pdwType, pvData, pcbData);
+	    TRACE("HKCU RegQueryValue returned %08lx\n", ret);
+	}
+
+	/* if HKCU did not work and HKLM exists, then try it */
+	if ((ret != ERROR_SUCCESS) &&
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    ret = RegQueryValueExW(dokey,
+				   pszValue, 0, pdwType, pvData, pcbData);
+	    TRACE("HKLM RegQueryValue returned %08lx\n", ret);
+	}
+
+	/* if neither worked, and default data exists, then use it */
+	if (ret != ERROR_SUCCESS) {
+	    if (pvDefaultData && (dwDefaultDataSize != 0)) {
+		maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
+		src = (CHAR*)pvDefaultData;
+		dst = (CHAR*)pvData;
+		for(i=0; i<maxmove; i++) *dst++ = *src++;
+		*pcbData = maxmove;
+		TRACE("setting default data\n");
+		ret = ERROR_SUCCESS;
+	    }
+	}
+	return ret;
+}
+
+/*************************************************************************
+ * SHRegGetUSValueA	[SHLWAPI.@]
+ *
+ * Gets a user-specific registry value
+ *   Will open the key, query the value, and close the key
+ */
+LONG WINAPI SHRegGetUSValueA(
 	LPCSTR   pSubKey,
 	LPCSTR   pValue,
 	LPDWORD  pwType,
 	LPVOID   pvData,
-	LPDWORD  pbData)
-{
-	HKEY hSubKey;
-	DWORD res;
-
-	TRACE("(%s %s)\n", pSubKey, pValue);
-
-	if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
-	res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
-	RegCloseKey( hSubKey );
-
-	return res;
-}
-
-/*************************************************************************
- * SHGetValueW   [SHLWAPI.@]
- *
- * Gets a value from the registry
- */
-DWORD WINAPI SHGetValueW(
-	HKEY     hkey,
+	LPDWORD  pcbData,
+	BOOL     flagIgnoreHKCU,
+	LPVOID   pDefaultData,
+	DWORD    wDefaultDataSize)
+{
+	HUSKEY myhuskey;
+	LONG ret;
+
+	if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
+	TRACE("key '%s', value '%s', datalen %ld,  %s\n",
+	      debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
+	      (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
+
+	ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
+	if (ret == ERROR_SUCCESS) {
+	    ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
+				     pcbData, flagIgnoreHKCU, pDefaultData,
+				     wDefaultDataSize);
+	    SHRegCloseUSKey(myhuskey);
+	}
+	return ret;
+}
+
+/*************************************************************************
+ * SHRegGetUSValueW	[SHLWAPI.@]
+ *
+ * Gets a user-specific registry value
+ *   Will open the key, query the value, and close the key
+ */
+LONG WINAPI SHRegGetUSValueW(
 	LPCWSTR  pSubKey,
 	LPCWSTR  pValue,
 	LPDWORD  pwType,
 	LPVOID   pvData,
-	LPDWORD  pbData)
-{
-	HKEY hSubKey;
-	DWORD res;
-
-	TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
-
-	if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
-	res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
-	RegCloseKey( hSubKey );
-
-	return res;
-}
-
-/*************************************************************************
- *      SHSetValueA   [SHLWAPI.@]
- */
-HRESULT WINAPI SHSetValueA(
-	HKEY hkey,
+	LPDWORD  pcbData,
+	BOOL     flagIgnoreHKCU,
+	LPVOID   pDefaultData,
+	DWORD    wDefaultDataSize)
+{
+	HUSKEY myhuskey;
+	LONG ret;
+
+	if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
+	TRACE("key '%s', value '%s', datalen %ld,  %s\n",
+	      debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
+	      (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
+
+	ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
+	if (ret == ERROR_SUCCESS) {
+	    ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
+				     pcbData, flagIgnoreHKCU, pDefaultData,
+				     wDefaultDataSize);
+	    SHRegCloseUSKey(myhuskey);
+	}
+	return ret;
+}
+
+/*************************************************************************
+ * SHRegGetBoolUSValueA   [SHLWAPI.@]
+ */
+BOOL WINAPI SHRegGetBoolUSValueA(
 	LPCSTR pszSubKey,
 	LPCSTR pszValue,
-	DWORD dwType,
-	LPCVOID pvData,
-	DWORD cbData)
-{
-    HKEY	subkey;
-    HRESULT	hres;
-
-    hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
-    if (!hres)
-	return hres;
-    hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
-    RegCloseKey(subkey);
-    return hres;
-}
-
-/*************************************************************************
- *      SHSetValueW   [SHLWAPI.@]
- */
-HRESULT WINAPI SHSetValueW(
-	HKEY hkey,
+	BOOL fIgnoreHKCU,
+	BOOL fDefault)
+{
+	LONG retvalue;
+	DWORD type, datalen, work;
+	BOOL ret = fDefault;
+	CHAR data[10];
+
+	TRACE("key '%s', value '%s', %s\n",
+	      debugstr_a(pszSubKey), debugstr_a(pszValue),
+	      (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
+
+	datalen = sizeof(data)-1;
+	if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type, 
+					   data, &datalen,
+					   fIgnoreHKCU, 0, 0))) {
+	    /* process returned data via type into bool */
+	    switch (type) {
+	    case REG_SZ:
+		data[9] = '\0';     /* set end of string */
+		if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
+		if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
+		if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
+		if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
+		break;
+	    case REG_DWORD:
+		work = *(LPDWORD)data;
+		ret = (work != 0);
+		break;
+	    case REG_BINARY:
+		if (datalen == 1) {
+		    ret = (data[0] != '\0');
+		    break;
+		}
+	    default:
+		FIXME("Unsupported registry data type %ld\n", type);
+		ret = FALSE;
+	    }
+	    TRACE("got value (type=%ld), returing <%s>\n", type,
+		  (ret) ? "TRUE" : "FALSE");
+	}
+	else {
+	    ret = fDefault;
+	    TRACE("returning default data <%s>\n",
+		  (ret) ? "TRUE" : "FALSE");
+	}
+	return ret;
+}
+
+/*************************************************************************
+ * SHRegGetBoolUSValueW	  [SHLWAPI.@]
+ */
+BOOL WINAPI SHRegGetBoolUSValueW(
 	LPCWSTR pszSubKey,
 	LPCWSTR pszValue,
-	DWORD dwType,
-	LPCVOID pvData,
-	DWORD cbData)
-{
-    HKEY	subkey;
-    HRESULT	hres;
-
-    hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
-    if (!hres)
-	return hres;
-    hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
-    RegCloseKey(subkey);
-    return hres;
-}
-
-/*************************************************************************
- * SHQueryValueExA		[SHLWAPI.@]
- *
- */
-HRESULT WINAPI SHQueryValueExA(
-	HKEY hkey,
-	LPSTR lpValueName,
-	LPDWORD lpReserved,
-	LPDWORD lpType,
-	LPBYTE lpData,
-	LPDWORD lpcbData)
-{
-	TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
-	return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
-}
-
+	BOOL fIgnoreHKCU,
+	BOOL fDefault)
+{
+	static const WCHAR wYES[]=  {'Y','E','S','\0'};
+	static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
+	static const WCHAR wNO[]=   {'N','O','\0'};
+	static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
+	LONG retvalue;
+	DWORD type, datalen, work;
+	BOOL ret = fDefault;
+	WCHAR data[10];
+
+	TRACE("key '%s', value '%s', %s\n",
+	      debugstr_w(pszSubKey), debugstr_w(pszValue),
+	      (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
+
+	datalen = (sizeof(data)-1) * sizeof(WCHAR);
+	if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type, 
+					   data, &datalen,
+					   fIgnoreHKCU, 0, 0))) {
+	    /* process returned data via type into bool */
+	    switch (type) {
+	    case REG_SZ:
+		data[9] = L'\0';     /* set end of string */
+		if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
+		    ret = TRUE;
+		else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
+		    ret = FALSE;
+		break;
+	    case REG_DWORD:
+		work = *(LPDWORD)data;
+		ret = (work != 0);
+		break;
+	    case REG_BINARY:
+		if (datalen == 1) {
+		    ret = (data[0] != L'\0');
+		    break;
+		}
+	    default:
+		FIXME("Unsupported registry data type %ld\n", type);
+		ret = FALSE;
+	    }
+	    TRACE("got value (type=%ld), returing <%s>\n", type,
+		  (ret) ? "TRUE" : "FALSE");
+	}
+	else {
+	    ret = fDefault;
+	    TRACE("returning default data <%s>\n",
+		  (ret) ? "TRUE" : "FALSE");
+	}
+	return ret;
+}
+
+/*************************************************************************
+ *      SHRegQueryInfoUSKeyA	[SHLWAPI.@]
+ */
+LONG WINAPI SHRegQueryInfoUSKeyA(
+	HUSKEY hUSKey,             /* [in]  */
+	LPDWORD pcSubKeys,
+	LPDWORD pcchMaxSubKeyLen,
+	LPDWORD pcValues,
+	LPDWORD pcchMaxValueNameLen,
+	SHREGENUM_FLAGS enumRegFlags)
+{
+	HKEY dokey;
+	LONG ret;
+
+	TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
+	      (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
+	      pcchMaxValueNameLen,enumRegFlags);
+
+	/* if user wants HKCU, and it exists, then try it */
+	if (((enumRegFlags == SHREGENUM_HKCU) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) &&
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
+				   pcSubKeys, pcchMaxSubKeyLen, 0,
+				   pcValues, pcchMaxValueNameLen, 0, 0, 0);
+	    if ((ret == ERROR_SUCCESS) ||
+		(enumRegFlags == SHREGENUM_HKCU)) 
+		return ret;
+	}
+	if (((enumRegFlags == SHREGENUM_HKLM) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    return RegQueryInfoKeyA(dokey, 0, 0, 0,
+				    pcSubKeys, pcchMaxSubKeyLen, 0,
+				    pcValues, pcchMaxValueNameLen, 0, 0, 0);
+	}
+	return ERROR_INVALID_FUNCTION;
+}
+
+/*************************************************************************
+ *      SHRegQueryInfoUSKeyW	[SHLWAPI.@]
+ */
+LONG WINAPI SHRegQueryInfoUSKeyW(
+	HUSKEY hUSKey,             /* [in]  */
+	LPDWORD pcSubKeys,
+	LPDWORD pcchMaxSubKeyLen,
+	LPDWORD pcValues,
+	LPDWORD pcchMaxValueNameLen,
+	SHREGENUM_FLAGS enumRegFlags)
+{
+	HKEY dokey;
+	LONG ret;
+
+	TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
+	      (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
+	      pcchMaxValueNameLen,enumRegFlags);
+
+	/* if user wants HKCU, and it exists, then try it */
+	if (((enumRegFlags == SHREGENUM_HKCU) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
+				   pcSubKeys, pcchMaxSubKeyLen, 0,
+				   pcValues, pcchMaxValueNameLen, 0, 0, 0);
+	    if ((ret == ERROR_SUCCESS) ||
+		(enumRegFlags == SHREGENUM_HKCU)) 
+		return ret;
+	}
+	if (((enumRegFlags == SHREGENUM_HKLM) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    return RegQueryInfoKeyW(dokey, 0, 0, 0,
+				    pcSubKeys, pcchMaxSubKeyLen, 0,
+				    pcValues, pcchMaxValueNameLen, 0, 0, 0);
+	}
+	return ERROR_INVALID_FUNCTION;
+}
+
+/*************************************************************************
+ *      SHRegEnumUSKeyA   	[SHLWAPI.@]
+ */
+LONG WINAPI SHRegEnumUSKeyA(
+	HUSKEY hUSKey,                 /* [in]  */
+	DWORD dwIndex,                 /* [in]  */
+	LPSTR pszName,                 /* [out] */
+	LPDWORD pcchValueNameLen,      /* [in/out] */
+	SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
+{
+	HKEY dokey;
+
+	TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
+	      (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
+	      *pcchValueNameLen, enumRegFlags);
+
+	if (((enumRegFlags == SHREGENUM_HKCU) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen, 
+				0, 0, 0, 0);
+	}
+
+	if (((enumRegFlags == SHREGENUM_HKLM) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
+				0, 0, 0, 0);
+	}
+	FIXME("no support for SHREGNUM_BOTH\n");
+	return ERROR_INVALID_FUNCTION;
+}
+
+/*************************************************************************
+ *      SHRegEnumUSKeyW   	[SHLWAPI.@]
+ */
+LONG WINAPI SHRegEnumUSKeyW(
+	HUSKEY hUSKey,                 /* [in]  */
+	DWORD dwIndex,                 /* [in]  */
+	LPWSTR pszName,                /* [out] */
+	LPDWORD pcchValueNameLen,      /* [in/out] */
+	SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
+{
+	HKEY dokey;
+
+	TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
+	      (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
+	      *pcchValueNameLen, enumRegFlags);
+
+	if (((enumRegFlags == SHREGENUM_HKCU) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) && 
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
+	    return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
+				0, 0, 0, 0);
+	}
+
+	if (((enumRegFlags == SHREGENUM_HKLM) ||
+	     (enumRegFlags == SHREGENUM_DEFAULT)) &&
+	    (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
+	    return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
+				0, 0, 0, 0);
+	}
+	FIXME("no support for SHREGNUM_BOTH\n");
+	return ERROR_INVALID_FUNCTION;
+}
+
+/*************************************************************************
+ *      SHRegWriteUSValueA   	[SHLWAPI.@]
+ */
+LONG  WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
+				LPVOID pvData, DWORD cbData, DWORD dwFlags)
+{
+    FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
+	  (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ *      SHRegWriteUSValueW   	[SHLWAPI.@]
+ */
+LONG  WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
+				LPVOID pvData, DWORD cbData, DWORD dwFlags)
+{
+    FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
+	  (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
+    return ERROR_SUCCESS;
+}
+
+/*************************************************************************
+ * SHRegGetPathA   [SHLWAPI.@]
+ *
+ * Get a path from the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key containing path to get
+ *   lpszValue  [I] Name of value containing path to get
+ *   lpszPath   [O] Buffer for returned path
+ *   dwFlags    [I] Reserved
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. lpszPath contains the path.
+ *   Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
+ */
+DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
+                           LPSTR lpszPath, DWORD dwFlags)
+{
+  HKEY hSubKey;
+  DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
+
+  TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
+        debugstr_a(lpszValue), lpszPath, dwFlags);
+
+  if (lpszSubKey && *lpszSubKey)
+    dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  else
+    hSubKey = hKey;
+
+  if (!dwRet)
+    dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
+
+  if (hSubKey != hKey)
+    RegCloseKey(hSubKey);
+
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHRegGetPathW   [SHLWAPI.@]
+ *
+ * See SHRegGetPathA.
+ */
+DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
+                           LPWSTR lpszPath, DWORD dwFlags)
+{
+  HKEY hSubKey;
+  DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
+
+  TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
+        debugstr_w(lpszValue), lpszPath, dwFlags);
+
+  if (lpszSubKey && *lpszSubKey)
+    dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  else
+    hSubKey = hKey;
+
+  if (!dwRet)
+    dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
+
+  if (hSubKey != hKey)
+    RegCloseKey(hSubKey);
+
+  return dwRet;
+}
+
+
+/*************************************************************************
+ * SHRegSetPathA   [SHLWAPI.@]
+ *
+ * Write a path to the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key containing path to set
+ *   lpszValue  [I] Name of value containing path to set
+ *   lpszPath   [O] Path to write
+ *   dwFlags    [I] Reserved
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS.
+ *   Failure: An error code from SHSetValueA.
+ */
+DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
+                           LPCSTR lpszPath, DWORD dwFlags)
+{
+  char szBuff[MAX_PATH];
+
+  FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
+        debugstr_a(lpszValue), lpszPath, dwFlags);
+
+  lstrcpyA(szBuff, lpszPath);
+
+  /* FIXME: PathUnExpandEnvStringsA(szBuff); */
+
+  return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
+                     lstrlenA(szBuff));
+}
+
+/*************************************************************************
+ * SHRegSetPathW   [SHLWAPI.@]
+ *
+ * See SHRegSetPathA.
+ */
+DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
+                           LPCWSTR lpszPath, DWORD dwFlags)
+{
+  WCHAR szBuff[MAX_PATH];
+
+  FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
+        debugstr_w(lpszValue), lpszPath, dwFlags);
+
+  lstrcpyW(szBuff, lpszPath);
+
+  /* FIXME: PathUnExpandEnvStringsW(szBuff); */
+
+  return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
+                     lstrlenW(szBuff));
+}
+
+/*************************************************************************
+ * SHGetValueA   [SHLWAPI.@]
+ *
+ * Get a value from the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key containing value to get
+ *   lpszValue  [I] Name of value to get
+ *   pwType     [O] Pointer to the values type
+ *   pvData     [O] Pointer to the values data
+ *   pcbData    [O] Pointer to the values size
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. Output parameters contain the details read.
+ *   Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
+ */
+DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
+                         LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
+{
+  DWORD dwRet;
+  HKEY hSubKey;
+
+  TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
+        debugstr_a(lpszValue), pwType, pvData, pcbData);
+
+  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
+  if (!dwRet)
+  {
+    dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
+    RegCloseKey(hSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHGetValueW   [SHLWAPI.@]
+ *
+ * See SHGetValueA.
+ */
+DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
+                         LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
+{
+  DWORD dwRet;
+  HKEY hSubKey;
+
+  TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
+        debugstr_w(lpszValue), pwType, pvData, pcbData);
+
+  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
+  if (!dwRet)
+  {
+    dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
+    RegCloseKey(hSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHSetValueA   [SHLWAPI.@]
+ *
+ * Set a value in the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key under hKey
+ *   lpszValue  [I] Name of value to set
+ *   dwType     [I] Type of the value
+ *   pvData     [I] Data of the value
+ *   cbData     [I] Size of the value
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. The value is set with the data given.
+ *   Failure: An error code from RegCreateKeyExA or RegSetValueExA
+ *
+ * NOTES
+ *   If the sub key does not exist, it is created before the value is set. If
+ *   The sub key is NULL or an empty string, then the value is added directly
+ *   to hKey instead.
+ */
+DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
+                         DWORD dwType, LPCVOID pvData, DWORD cbData)
+{
+  DWORD dwRet = ERROR_SUCCESS, dwDummy;
+  HKEY  hSubKey;
+  LPSTR szEmpty = "";
+
+  TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
+          debugstr_a(lpszValue), dwType, pvData, cbData);
+
+  if (lpszSubKey && *lpszSubKey)
+    dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
+                            0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
+  else
+    hSubKey = hKey;
+  if (!dwRet)
+  {
+    dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
+    if (hSubKey != hKey)
+      RegCloseKey(hSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHSetValueW   [SHLWAPI.@]
+ *
+ * See SHSetValueA.
+ */
+DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
+                         DWORD dwType, LPCVOID pvData, DWORD cbData)
+{
+  DWORD dwRet = ERROR_SUCCESS, dwDummy;
+  HKEY  hSubKey;
+  WCHAR szEmpty[] = { '\0' };
+
+  TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
+        debugstr_w(lpszValue), dwType, pvData, cbData);
+
+  if (lpszSubKey && *lpszSubKey)
+    dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
+                            0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
+  else
+    hSubKey = hKey;
+  if (!dwRet)
+  {
+    dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
+    if (hSubKey != hKey)
+      RegCloseKey(hSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHQueryInfoKeyA   [SHLWAPI.@]
+ *
+ * Get information about a registry key. See RegQueryInfoKeyA.
+ */
+LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
+                            LPDWORD pwValues, LPDWORD pwValueMax)
+{
+  TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
+        pwValues, pwValueMax);
+  return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
+                          NULL, pwValues, pwValueMax, NULL, NULL, NULL);
+}
+
+/*************************************************************************
+ * SHQueryInfoKeyW   [SHLWAPI.@]
+ *
+ * See SHQueryInfoKeyA
+ */
+LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
+                            LPDWORD pwValues, LPDWORD pwValueMax)
+{
+  TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
+        pwValues, pwValueMax);
+  return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
+                          NULL, pwValues, pwValueMax, NULL, NULL, NULL);
+}
+
+/*************************************************************************
+ * SHQueryValueExAW
+ *
+ * Internal implementation of SHQueryValueExA/SHQueryValueExW.
+ */
+static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
+                                     HKEY hKey, LPCVOID lpszValue,
+                                     LPDWORD lpReserved, LPDWORD pwType,
+                                     LPBYTE pvData, LPDWORD pcbData)
+{
+  DWORD dwRet, dwType, dwDataLen;
+
+  if (pcbData)
+    dwDataLen = *pcbData;
+
+  dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
+  if (!dwRet)
+  {
+    if (dwType == REG_EXPAND_SZ)
+    {
+      /* Expand type REG_EXPAND_SZ into REG_SZ */
+      LPSTR szExpand;
+      LPBYTE pData = pvData;
+
+      if (!pData)
+      {
+        /* Create a buffer to hold the data, to get the size */
+        if (!pcbData ||
+            !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
+          return ERROR_OUTOFMEMORY;
+        /* Read the data in to the buffer */
+        if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
+                         pData, &dwDataLen)))
+          return dwRet;
+      }
+
+      if (!pcbData && pData != pvData)
+      {
+        /* Note: In this case the caller will crash under Win32 */
+        WARN("Invalid pcbData would crash under Win32!");
+        return ERROR_OUTOFMEMORY;
+      }
+
+      szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
+      if (!szExpand)
+      {
+        if (pData != pvData)
+          HeapFree(GetProcessHeap(), 0, pData);
+        return ERROR_OUTOFMEMORY;
+      }
+      if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
+      {
+        dwDataLen = strlen(szExpand) + 1;
+        strncpy(pvData, szExpand, *pcbData);
+      }
+      else
+      {
+        if (pData != pvData)
+          HeapFree(GetProcessHeap(), 0, pData);
+        HeapFree(GetProcessHeap(), 0, szExpand);
+        return GetLastError();
+      }
+      if (pData != pvData)
+        HeapFree(GetProcessHeap(), 0, pData);
+      HeapFree(GetProcessHeap(), 0, szExpand);
+      dwType = REG_SZ;
+    }
+    if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
+    {
+      /* String type too long: truncate it */
+      pvData[*pcbData] = '\0';
+    }
+  }
+  /* Update the type and data size if the caller wanted them */
+  if (pwType)
+    *pwType = dwType;
+  if (pcbData)
+    *pcbData  = dwDataLen;
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHQueryValueExA   [SHLWAPI.@]
+ *
+ * Get a value from the registry, expanding environment variable strings.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszValue  [I] Name of value to delete
+ *   lpReserved [O] Reserved for future use; must be NULL
+ *   pwType     [O] Optional pointer updated with the values type
+ *   pvData     [O] Optional pointer updated with the values data
+ *   pcbData    [O] Optional pointer updated with the values size
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
+ *            information about the value.
+ *   Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
+ *            data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
+ *            code from RegQueryValueExA or ExpandEnvironmentStringsA.
+ *
+ * NOTES
+ *   Either pwType, pvData or pcbData may be NULL if the caller doesn't want
+ *   the type, data or size information for the value.
+ *
+ *   If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
+ *   value returned will be truncated if it is of type REG_SZ and bigger than
+ *   the buffer given to store it.
+ */
+DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
+                             LPDWORD lpReserved, LPDWORD pwType,
+                             LPVOID pvData, LPDWORD pcbData)
+{
+  TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
+        lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
+
+  return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
+                          lpReserved, pwType, pvData, pcbData);
+}
 
 /*************************************************************************
  * SHQueryValueExW   [SHLWAPI.@]
  *
- * FIXME 
- *  if the datatype REG_EXPAND_SZ then expand the string and change
- *  *pdwType to REG_SZ.
- */
-HRESULT WINAPI SHQueryValueExW (
-	HKEY hkey,
-	LPWSTR pszValue,
-	LPDWORD pdwReserved,
-	LPDWORD pdwType,
-	LPVOID pvData,
-	LPDWORD pcbData)
-{
-	WARN("0x%04x %s %p %p %p %p semi-stub\n",
-             hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
-	return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
+ * See SHQueryValueExA.
+ */
+DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
+                             LPDWORD lpReserved, LPDWORD pwType,
+                             LPVOID pvData, LPDWORD pcbData)
+{
+  TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
+        lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
+
+  return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
+                          lpReserved, pwType, pvData, pcbData);
 }
 
@@ -319,82 +1083,243 @@
  * SHDeleteKeyA   [SHLWAPI.@]
  *
- * It appears this function is made available to account for the differences
- * between the Win9x and WinNT/2k RegDeleteKeyA functions.
- *
- * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
- * WinNt/2k will only delete the key if empty.
- */
-HRESULT WINAPI SHDeleteKeyA(
-	HKEY hKey,
-	LPCSTR lpszSubKey)
-{
-    DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
-    HKEY hSubKey;
-    LPSTR lpszName;
-
-    TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
-
-    hSubKey = 0;
-    r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
-    if(r != ERROR_SUCCESS)
-        return r;
-
-    /* find how many subkeys there are */
-    dwKeyCount = 0;
-    dwMaxSubkeyLen = 0;
-    r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
-                    &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
-    if(r != ERROR_SUCCESS)
+ * Delete a registry key and any sub keys/values present
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key to delete
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. The key is deleted.
+ *   Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
+ *          RegEnumKeyExA or RegDeleteKeyA.
+ */
+DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
+{
+  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
+  CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
+  HKEY hSubKey = 0;
+
+  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
+
+  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  if(!dwRet)
+  {
+    /* Find how many subkeys there are */
+    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
+    if(!dwRet)
     {
-        RegCloseKey(hSubKey);
-        return r;
+      dwMaxSubkeyLen++;
+      if (dwMaxSubkeyLen > sizeof(szNameBuf))
+        /* Name too big: alloc a buffer for it */
+        lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
+
+      if(!lpszName)
+        dwRet = ERROR_NOT_ENOUGH_MEMORY;
+      else
+      {
+        /* Recursively delete all the subkeys */
+        for(i = 0; i < dwKeyCount && !dwRet; i++)
+        {
+          dwSize = dwMaxSubkeyLen;
+          dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
+          if(!dwRet)
+            dwRet = SHDeleteKeyA(hSubKey, lpszName);
+        }
+        if (lpszName != szNameBuf)
+          HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
+      }
     }
 
-    /* alloc memory for the longest string terminating 0 */
-    dwMaxSubkeyLen++;
-    lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
-    if(!lpszName)
+    RegCloseKey(hSubKey);
+    if(!dwRet)
+      dwRet = RegDeleteKeyA(hKey, lpszSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHDeleteKeyW   [SHLWAPI.@]
+ *
+ * See SHDeleteKeyA.
+ */
+DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
+{
+  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
+  WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
+  HKEY hSubKey = 0;
+
+  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
+
+  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  if(!dwRet)
+  {
+    /* Find how many subkeys there are */
+    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
+    if(!dwRet)
     {
-        RegCloseKey(hSubKey);
-        return ERROR_NOT_ENOUGH_MEMORY;
+      dwMaxSubkeyLen++;
+      if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
+        /* Name too big: alloc a buffer for it */
+        lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
+
+      if(!lpszName)
+        dwRet = ERROR_NOT_ENOUGH_MEMORY;
+      else
+      {
+        /* Recursively delete all the subkeys */
+        for(i = 0; i < dwKeyCount && !dwRet; i++)
+        {
+          dwSize = dwMaxSubkeyLen;
+          dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
+          if(!dwRet)
+            dwRet = SHDeleteKeyW(hSubKey, lpszName);
+        }
+
+        if (lpszName != szNameBuf)
+          HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
+      }
     }
 
-    /* recursively delete all the subkeys */
-    for(i=0; i<dwKeyCount; i++)
+    RegCloseKey(hSubKey);
+    if(!dwRet)
+      dwRet = RegDeleteKeyW(hKey, lpszSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHDeleteEmptyKeyA   [SHLWAPI.@]
+ *
+ * Delete a registry key with no sub keys.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key to delete
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. The key is deleted.
+ *   Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
+ *          returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
+ *          RegDeleteKeyA.
+ */
+DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
+{
+  DWORD dwRet, dwKeyCount = 0;
+  HKEY hSubKey = 0;
+
+  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
+
+  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  if(!dwRet)
+  {
+    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+    RegCloseKey(hSubKey);
+    if(!dwRet)
     {
-        dwSize = dwMaxSubkeyLen;
-        r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
-        if(r != ERROR_SUCCESS)
-            break;
-        r = SHDeleteKeyA(hSubKey, lpszName);
-        if(r != ERROR_SUCCESS)
-            break;
+      if (!dwKeyCount)
+        dwRet = RegDeleteKeyA(hKey, lpszSubKey);
+      else
+        dwRet = ERROR_KEY_HAS_CHILDREN;
     }
-
-    HeapFree(GetProcessHeap(), 0, lpszName);
-
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHDeleteEmptyKeyW   [SHLWAPI.@]
+ *
+ * See SHDeleteEmptyKeyA.
+ */
+DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
+{
+  DWORD dwRet, dwKeyCount = 0;
+  HKEY hSubKey = 0;
+
+  TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
+
+  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+  if(!dwRet)
+  {
+    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             NULL, NULL, NULL, NULL, NULL, NULL, NULL);
     RegCloseKey(hSubKey);
-
-    if(r == ERROR_SUCCESS)
-        r = RegDeleteKeyA(hKey, lpszSubKey);
-
-    return r;
-}
-
-/*************************************************************************
- * SHDeleteKeyW   [SHLWAPI.@]
- *
- * It appears this function is made available to account for the differences
- * between the Win9x and WinNT/2k RegDeleteKeyA functions.
- *
- * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
- * WinNt/2k will only delete the key if empty.
- */
-HRESULT WINAPI SHDeleteKeyW(
-	HKEY hkey,
-	LPCWSTR pszSubKey)
-{
-	FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
-	return 0;
+    if(!dwRet)
+    {
+      if (!dwKeyCount)
+        dwRet = RegDeleteKeyW(hKey, lpszSubKey);
+      else
+        dwRet = ERROR_KEY_HAS_CHILDREN;
+    }
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHDeleteOrphanKeyA   [SHLWAPI.@]
+ *
+ * Delete a registry key with no sub keys or values.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key to possibly delete
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
+ *   Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
+ */
+DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
+{
+  HKEY hSubKey;
+  DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
+
+  TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
+
+  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+
+  if(!dwRet)
+  {
+    /* Get subkey and value count */
+    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
+
+    if(!dwRet && !dwKeyCount && !dwValueCount)
+    {
+      dwRet = RegDeleteKeyA(hKey, lpszSubKey);
+    }
+    RegCloseKey(hSubKey);
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHDeleteOrphanKeyW   [SHLWAPI.@]
+ *
+ * See SHDeleteOrphanKeyA.
+ */
+DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
+{
+  HKEY hSubKey;
+  DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
+
+  TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
+
+  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
+
+  if(!dwRet)
+  {
+    /* Get subkey and value count */
+    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
+                             NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
+
+    if(!dwRet && !dwKeyCount && !dwValueCount)
+    {
+      dwRet = RegDeleteKeyW(hKey, lpszSubKey);
+    }
+    RegCloseKey(hSubKey);
+  }
+  return dwRet;
 }
 
@@ -402,16 +1327,29 @@
  * SHDeleteValueA   [SHLWAPI.@]
  *
- * Function opens the key, get/set/delete the value, then close the key.
- */
-HRESULT WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
-    HKEY	subkey;
-    HRESULT	hres;
-
-    hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
-    if (hres)
-	return hres;
-    hres = RegDeleteValueA(subkey,pszValue);
-    RegCloseKey(subkey);
-    return hres;
+ * Delete a value from the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key containing value to delete
+ *   lpszValue  [I] Name of value to delete
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. The value is deleted.
+ *   Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
+ */
+DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
+{
+  DWORD dwRet;
+  HKEY hSubKey;
+
+  TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
+
+  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
+  if (!dwRet)
+  {
+    dwRet = RegDeleteValueA(hSubKey, lpszValue);
+    RegCloseKey(hSubKey);
+  }
+  return dwRet;
 }
 
@@ -419,72 +1357,105 @@
  * SHDeleteValueW   [SHLWAPI.@]
  *
- * Function opens the key, get/set/delete the value, then close the key.
- */
-HRESULT WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
-    HKEY	subkey;
-    HRESULT	hres;
-
-    hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
-    if (hres)
-	return hres;
-    hres = RegDeleteValueW(subkey,pszValue);
-    RegCloseKey(subkey);
-    return hres;
-}
-
-/*************************************************************************
- * SHDeleteEmptyKeyA   [SHLWAPI.@]
- *
- * It appears this function is made available to account for the differences
- * between the Win9x and WinNT/2k RegDeleteKeyA functions.
- *
- * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
- * WinNt/2k will only delete the key if empty.
- */
-DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
-{
-    DWORD r, dwKeyCount;
-    HKEY hSubKey;
-
-    TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
-
-    hSubKey = 0;
-    r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
-    if(r != ERROR_SUCCESS)
-        return r;
-
-    dwKeyCount = 0;
-    r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
-                    NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-    if(r != ERROR_SUCCESS)
-        return r;
-
+ * See SHDeleteValueA.
+ */
+DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
+{
+  DWORD dwRet;
+  HKEY hSubKey;
+
+  TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
+
+  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
+  if (!dwRet)
+  {
+    dwRet = RegDeleteValueW(hSubKey, lpszValue);
     RegCloseKey(hSubKey);
-
-    if(dwKeyCount)
-        return ERROR_KEY_HAS_CHILDREN;
-
-    r = RegDeleteKeyA(hKey, lpszSubKey);
-
-    return r;
-}
-
-/*************************************************************************
- * SHDeleteEmptyKeyW   [SHLWAPI.@]
- *
- * It appears this function is made available to account for the differences
- * between the Win9x and WinNT/2k RegDeleteKeyA functions.
- *
- * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
- * WinNt/2k will only delete the key if empty.
- */
-DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
-{
-    FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
-    return 0;
-}
-
-/*************************************************************************
- * SHLWAPI_205   [SHLWAPI.205]
+  }
+  return dwRet;
+}
+
+/*************************************************************************
+ * SHEnumKeyExA   [SHLWAPI.@]
+ *
+ * Enumerate sub keys in a registry key.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   dwIndex    [I] Index of key to enumerate
+ *   lpszSubKey [O] Pointer updated with the subkey name
+ *   pwLen      [O] Pointer updated with the subkey length
+ *
+ * RETURN
+ *   Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
+ *   Failure: An error code from RegEnumKeyExA.
+ */
+LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
+                         LPDWORD pwLen)
+{
+  TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
+
+  return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
+}
+
+/*************************************************************************
+ * SHEnumKeyExW   [SHLWAPI.@]
+ *
+ * See SHEnumKeyExA.
+ */
+LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
+                         LPDWORD pwLen)
+{
+  TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
+
+  return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
+}
+
+/*************************************************************************
+ * SHEnumValueA   [SHLWAPI.@]
+ *
+ * Enumerate values in a registry key.
+ *
+ * PARAMS
+ *   hKey      [I] Handle to registry key
+ *   dwIndex   [I] Index of key to enumerate
+ *   lpszValue [O] Pointer updated with the values name
+ *   pwLen     [O] Pointer updated with the values length
+ *   pwType    [O] Pointer updated with the values type
+ *   pvData    [O] Pointer updated with the values data
+ *   pcbData   [O] Pointer updated with the values size
+ *
+ * RETURNS
+ *   Success: ERROR_SUCCESS. Output parameters are updated.
+ *   Failure: An error code from RegEnumValueExA.
+ */
+LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
+                         LPDWORD pwLen, LPDWORD pwType,
+                         LPVOID pvData, LPDWORD pcbData)
+{
+  TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
+        debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
+
+ return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
+                      pwType, pvData, pcbData);
+}
+
+/*************************************************************************
+ * SHEnumValueW   [SHLWAPI.@]
+ *
+ * See SHEnumValueA.
+ */
+LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
+                         LPDWORD pwLen, LPDWORD pwType,
+                         LPVOID pvData, LPDWORD pcbData)
+{
+  TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
+        debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
+
+  return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
+                       pwType, pvData, pcbData);
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.205]
  *
  * Wrapper for SHGetValueA in case machine is in safe mode.
@@ -499,5 +1470,5 @@
 
 /*************************************************************************
- * SHLWAPI_206   [SHLWAPI.206]
+ * @   [SHLWAPI.206]
  *
  * Unicode version of SHLWAPI_205.
@@ -512,17 +1483,34 @@
 
 /*************************************************************************
- * SHLWAPI_320   [SHLWAPI.320]
- *
+ * @   [SHLWAPI.320]
+ *
+ * Set a content type in the registry.
+ *
+ * PARAMS
+ *   hKey       [I] Handle to registry key
+ *   lpszSubKey [I] Name of sub key under hKey
+ *   lpszValue  [I] Value to set
+ *
+ * RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
  */
 BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
 {
-  DWORD dwLen = strlen(lpszValue);
-  HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
-                            REG_SZ, lpszValue, dwLen);
-  return ret ? FALSE : TRUE;
-}
-
-/*************************************************************************
- * SHLWAPI_321   [SHLWAPI.321]
+  DWORD dwRet;
+
+  if (!lpszValue)
+  {
+    WARN("Invalid lpszValue would crash under Win32!");
+    return FALSE;
+  }
+
+  dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
+                      REG_SZ, lpszValue, strlen(lpszValue));
+  return dwRet ? FALSE : TRUE;
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.321]
  *
  * Unicode version of SHLWAPI_320.
@@ -530,13 +1518,28 @@
 BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
 {
-  DWORD dwLen = strlenW(lpszValue);
-  HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
-                            REG_SZ, lpszValue, dwLen);
-  return ret ? FALSE : TRUE;
-}
-
-/*************************************************************************
- * SHLWAPI_322   [SHLWAPI.322]
- *
+  DWORD dwRet;
+
+  if (!lpszValue)
+  {
+    WARN("Invalid lpszValue would crash under Win32!");
+    return FALSE;
+  }
+
+  dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
+                      REG_SZ, lpszValue, strlenW(lpszValue));
+  return dwRet ? FALSE : TRUE;
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.322]
+ *
+ * Delete a content type from the registry.
+ *
+ * PARAMS
+ *   lpszSubKey [I] Name of sub key
+ *
+ * RETURNS
+ *   Success: TRUE
+ *   Failure: FALSE
  */
 BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
@@ -547,5 +1550,5 @@
 
 /*************************************************************************
- * SHLWAPI_323   [SHLWAPI.323]
+ * @   [SHLWAPI.323]
  *
  * Unicode version of SHLWAPI_322.
@@ -557,2 +1560,14 @@
 }
 
+
+/*************************************************************************
+ * SHRegDuplicateHKey   [SHLWAPI.@]
+ */
+HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
+{
+    HKEY newKey = 0;
+
+    RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
+    TRACE("new key is %08x\n", newKey);
+    return newKey;
+}
Index: trunk/src/shlwapi/reg_odin.cpp
===================================================================
--- trunk/src/shlwapi/reg_odin.cpp	(revision 7815)
+++ trunk/src/shlwapi/reg_odin.cpp	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: reg_odin.cpp,v 1.2 2001-08-30 19:19:57 phaller Exp $ */
+/* $Id: reg_odin.cpp,v 1.3 2002-02-06 20:18:28 sandervl Exp $ */
 
 /*
@@ -27,5 +27,7 @@
 #include "winnls.h"
 #include "winversion.h"
+#include "winuser.h"
 #include "winreg.h"
+#include "wingdi.h"
 
 #include <heapstring.h>
@@ -33,4 +35,6 @@
 #include <win\winerror.h>
 #include "shlwapi_odin.h"
+#define NO_SHLWAPI_STREAM
+#include <shlwapi.h>
 
 
@@ -50,6 +54,6 @@
  *****************************************************************************/
 
-ODINFUNCTION5(DWORD,  SHRegCreateUSKeyA,
-              LPSTR,  lpszKeyName,
+ODINFUNCTION5(LONG,  SHRegCreateUSKeyA,
+              LPCSTR,  lpszKeyName,
               REGSAM,  AccessType,
               HUSKEY,  hRelativeUSKey,
@@ -74,6 +78,6 @@
  *****************************************************************************/
 
-ODINFUNCTION5(DWORD,   SHRegCreateUSKeyW,
-              LPWSTR,  lpszKeyName,
+ODINFUNCTION5(LONG,   SHRegCreateUSKeyW,
+              LPCWSTR,  lpszKeyName,
               REGSAM,  AccessType,
               HUSKEY,  hRelativeUSKey,
@@ -114,88 +118,4 @@
 
 
-/*****************************************************************************
- * Name      : DWORD SHRegGetBoolUSValueA
- * Purpose   : unknown
- * Parameters: unknown
- * Variables :
- * Result    : unknown
- * Remark    : SHLWAPI.SHRegGetBoolUSValueA
- * Status    : COMPLETELY IMPLEMENTED ? UNTESTED
- *
- * Author    : Patrick Haller [Wed, 1999/12/29 23:02]
- *****************************************************************************/
-
-ODINFUNCTION4(BOOL,    SHRegGetBoolUSValueA,
-              LPCSTR,  pszSubKey,
-              LPCSTR,  pszValue,
-              BOOL,    fIgnoreHKCU,
-              BOOL,    fDefault)
-{
-  char  szBuffer[260];
-  DWORD dwLength = sizeof(szBuffer);
-  LONG  rc;
-
-  dprintf(("subkey=%s, value=%s\n",
-           pszSubKey,
-           pszValue));
-
-  rc = SHRegGetUSValueA(pszSubKey,
-                        pszValue,
-                        &fDefault,
-                        szBuffer,
-                        &dwLength,
-                        fIgnoreHKCU,
-                        fDefault ? "YES" : "NO",
-                        fDefault ? 4 : 3);
-  if (rc != ERROR_SUCCESS)
-    return rc;
-
-  if (lstrcmpiA("YES",
-                szBuffer) == 0)
-    return 1;
-  else
-  if (lstrcmpiA("TRUE",
-                szBuffer) == 0)
-    return 1;
-  else
-  if (lstrcmpiA("NO",
-                szBuffer) == 0)
-    return 0;
-  else
-  if (lstrcmpiA("FALSE",
-                szBuffer) == 0)
-    return 0;
-
-
-  return ERROR_SUCCESS;  /* return success */
-}
-
-
-/*****************************************************************************
- * Name      : DWORD SHRegGetBoolUSValueW
- * Purpose   : unknown
- * Parameters: unknown
- * Variables :
- * Result    : unknown
- * Remark    : SHLWAPI.SHRegGetBoolUSValueW
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Wed, 1999/12/29 23:02]
- *****************************************************************************/
-
-ODINFUNCTION4(BOOL,    SHRegGetBoolUSValueW,
-              LPCWSTR, pszSubKey,
-              LPCWSTR, pszValue,
-              BOOL,    fIgnoreHKCU,
-              BOOL,    fDefault)
-{
-  char  szBuffer[264];
-  int   iLength;
-
-  dprintf(("(%p),stub!\n", pszSubKey));
-
-  return ERROR_SUCCESS;  /* return success */
-}
-
 
 /*****************************************************************************
@@ -255,25 +175,4 @@
 
 
-/*****************************************************************************
- * Name      : LONG SHRegCloseUSKey
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION1(LONG,    SHRegCloseUSKey,
-              HUSKEY,  hUSKey)
-{
-  dprintf(("not implemented\n"));
-  
-  LONG rc = RegCloseKey(hUSKey);
-  return rc;
-}
-
 
 /*****************************************************************************
@@ -291,11 +190,11 @@
 ODINFUNCTION3(LONG,    SHRegDeleteUSValueA,
               HUSKEY,  hUSKey,
-              LPSTR,   lpValue,
-              DWORD,   dwFlags)
+              LPCSTR,   lpValue,
+              SHREGDEL_FLAGS,   dwFlags)
 {
   dprintf(("not implemented\n"));
   
   LONG rc = RegDeleteValueA(hUSKey,
-                            lpValue);
+                            (LPSTR)lpValue);
   return rc;
 }
@@ -315,63 +214,16 @@
 
 ODINFUNCTION3(LONG,    SHRegDeleteUSValueW,
-              HKEY,    hKey,
-              LPWSTR,  lpValue,
-              DWORD,   dwFlags)
+              HUSKEY,   hKey,
+              LPCWSTR,  lpValue,
+              SHREGDEL_FLAGS,   dwFlags)
 {
   dprintf(("not implemented\n"));
   
   LONG rc = RegDeleteValueW(hKey,
-                            lpValue);
+                            (LPWSTR)lpValue);
   return rc;
 }
 
 
-/*****************************************************************************
- * Name      : LONG SHDeleteOrphanKeyA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION2(LONG,    SHDeleteOrphanKeyA,
-              HKEY,    hKey,
-              LPCSTR,  lpszSubkey)
-{
-  dprintf(("not implemented\n"));
-  
-  LONG rc = RegDeleteKeyA(hKey,
-                          lpszSubkey);
-  return rc;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHDeleteOrphanKeyW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION2(LONG,    SHDeleteOrphanKeyW,
-              HKEY,    hKey,
-              LPWSTR,  lpszSubkey)
-{
-  dprintf(("not implemented\n"));
-  
-  LONG rc = RegDeleteKeyW(hKey,
-                          lpszSubkey);
-  return rc;
-}
-
 
 /*****************************************************************************
@@ -389,4 +241,48 @@
 ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyA,
               HUSKEY,  hUSKey,
+              LPCSTR,   lpszSubkey,
+              SHREGDEL_FLAGS,   dwFlags)
+{
+  dprintf(("not yet implemented"));
+  return 0;
+}
+
+
+/*****************************************************************************
+ * Name      : LONG SHRegDeleteEmptyUSKeyW
+ * Purpose   :
+ * Parameters:
+ * Variables :
+ * Result    :
+ * Remark    : 
+ * Status    : STUB UNTESTED
+ *
+ * Author    : Patrick Haller [2001-08-30]
+ *****************************************************************************/
+
+ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyW,
+              HUSKEY,  hUSKey,
+              LPCWSTR,  lpszSubkey,
+              SHREGDEL_FLAGS,   dwFlags)
+{
+  dprintf(("not yet implemented"));
+  return 0;
+}
+
+
+/*****************************************************************************
+ * Name      : LONG SHRegDeleteUSKeyA
+ * Purpose   :
+ * Parameters:
+ * Variables :
+ * Result    :
+ * Remark    : 
+ * Status    : STUB UNTESTED
+ *
+ * Author    : Patrick Haller [2001-08-30]
+ *****************************************************************************/
+
+ODINFUNCTION3(LONG,    SHRegDeleteUSKeyA,
+              HUSKEY,  hUSKey,
               LPSTR,   lpszSubkey,
               DWORD,   dwFlags)
@@ -398,16 +294,16 @@
 
 /*****************************************************************************
- * Name      : LONG SHRegDeleteEmptyUSKeyW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyW,
+ * Name      : LONG SHRegDeleteUSKeyW
+ * Purpose   :
+ * Parameters:
+ * Variables :
+ * Result    :
+ * Remark    : 
+ * Status    : STUB UNTESTED
+ *
+ * Author    : Patrick Haller [2001-08-30]
+ *****************************************************************************/
+
+ODINFUNCTION3(LONG,    SHRegDeleteUSKeyW,
               HUSKEY,  hUSKey,
               LPWSTR,  lpszSubkey,
@@ -419,94 +315,4 @@
 
 
-/*****************************************************************************
- * Name      : LONG SHRegDeleteUSKeyA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION3(LONG,    SHRegDeleteUSKeyA,
-              HUSKEY,  hUSKey,
-              LPSTR,   lpszSubkey,
-              DWORD,   dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegDeleteUSKeyW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION3(LONG,    SHRegDeleteUSKeyW,
-              HUSKEY,  hUSKey,
-              LPWSTR,  lpszSubkey,
-              DWORD,   dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegEnumUSKeyA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION5(LONG,    SHRegEnumUSKeyA,
-              HUSKEY,  hUSKey,
-              DWORD,   dwIndex,
-              LPSTR,   lpszKeyName,
-              LPDWORD, lpdwKeyNameSize,
-              SHREGENUM_FLAGS, dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegEnumUSKeyW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION5(LONG,    SHRegEnumUSKeyW,
-              HUSKEY,  hUSKey,
-              DWORD,   dwIndex,
-              LPWSTR,  lpszKeyName,
-              LPDWORD, lpdwKeyNameSize,
-              SHREGENUM_FLAGS, dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
 
 
@@ -565,98 +371,3 @@
 
 
-/*****************************************************************************
- * Name      : LONG SHRegQueryInfoUSKeyA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION5(LONG,    SHRegQueryInfoUSKeyA,
-              LPDWORD,  lpdwSubKeyNum,
-              LPDWORD,  lpdwMaxSubKeyNameSize,
-              LPDWORD,  lpdwValueNum,
-              LPDWORD,  lpdwMaxValueNameSize,
-              SHREGENUM_FLAGS, dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegQueryInfoUSKeyW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION5(LONG,    SHRegQueryInfoUSKeyW,
-              LPDWORD,  lpdwSubKeyNum,
-              LPDWORD,  lpdwMaxSubKeyNameSize,
-              LPDWORD,  lpdwValueNum,
-              LPDWORD,  lpdwMaxValueNameSize,
-              SHREGENUM_FLAGS, dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegWriteUSValueA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION6(LONG,     SHRegWriteUSValueA,
-              HUSKEY,   hUSKey,
-              LPCSTR,   lpszValueName,
-              DWORD,    dwValueType,
-              LPVOID,   lpValue,
-              DWORD,    dwValueSize,
-              DWORD,    dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
-
-
-/*****************************************************************************
- * Name      : LONG SHRegWriteUSValueW
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    : 
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [2001-08-30]
- *****************************************************************************/
-
-ODINFUNCTION6(LONG,     SHRegWriteUSValueW,
-              HUSKEY,   hUSKey,
-              LPCWSTR,  lpszValueName,
-              DWORD,    dwValueType,
-              LPVOID,   lpValue,
-              DWORD,    dwValueSize,
-              DWORD,    dwFlags)
-{
-  dprintf(("not yet implemented"));
-  return 0;
-}
+
Index: trunk/src/shlwapi/regstream.c
===================================================================
--- trunk/src/shlwapi/regstream.c	(revision 7815)
+++ trunk/src/shlwapi/regstream.c	(revision 7820)
@@ -2,26 +2,11 @@
  *	SHRegOpenStream
  */
-#ifdef __WIN32OS2__
-#include <odin.h>
-#include <odinwrap.h>
-#include <os2sel.h>
-
 #include <string.h>
-#include <ctype.h>
-#include <wctype.h>
-#define HAVE_WCTYPE_H
-
-#define ICOM_CINTERFACE 1
-#define CINTERFACE 1
-
-#endif
-
-#include <string.h>
 
 #include "winerror.h"
+#include "winbase.h"
 #include "winreg.h"
-#include "wine/obj_storage.h"
-
-#include "heap.h"
+#include "shlobj.h"
+
 #include "debugtools.h"
 
@@ -120,5 +105,5 @@
 	ICOM_THIS(ISHRegStream, iface);
 
-////	TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
+	TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
 
 	*ppvObj = NULL;
@@ -307,4 +292,5 @@
 /*************************************************************************
  * SHOpenRegStreamA				[SHLWAPI.@]
+ * SHOpenRegStream2A				[SHLWAPI.@]
  */
 IStream * WINAPI SHOpenRegStreamA(
@@ -322,4 +308,5 @@
 /*************************************************************************
  * SHOpenRegStreamW				[SHLWAPI.@]
+ * SHOpenRegStream2W				[SHLWAPI.@]
  */
 IStream * WINAPI SHOpenRegStreamW(
Index: trunk/src/shlwapi/shlstub.cpp
===================================================================
--- trunk/src/shlwapi/shlstub.cpp	(revision 7815)
+++ trunk/src/shlwapi/shlstub.cpp	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: shlstub.cpp,v 1.2 2001-08-30 19:19:58 phaller Exp $ */
+/* $Id: shlstub.cpp,v 1.3 2002-02-06 20:18:28 sandervl Exp $ */
 
 /*
@@ -35,6 +35,4 @@
 
 ODINDEBUGCHANNEL(SHLWAPI-SHLSTUB)
-
-#include "shlwapi.h"
 
 
Index: trunk/src/shlwapi/shlwapi.cpp
===================================================================
--- trunk/src/shlwapi/shlwapi.cpp	(revision 7815)
+++ trunk/src/shlwapi/shlwapi.cpp	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: shlwapi.cpp,v 1.11 2001-07-20 15:37:52 sandervl Exp $ */
+/* $Id: shlwapi.cpp,v 1.12 2002-02-06 20:18:29 sandervl Exp $ */
 
 /*
@@ -33,4 +33,5 @@
 
 #include "debugtools.h"
+#include "winbase.h"
 #include "winnls.h"
 #include "winversion.h"
@@ -51,5 +52,4 @@
 ODINDEBUGCHANNEL(SHLWAPI)
 
-#include "shlwapi.h"
 
 
@@ -70,101 +70,2 @@
 }
 
-#if 0
-// ----------------------------------------------------------------------
-// WINE_StringFromCLSID
-// ----------------------------------------------------------------------
-HRESULT WINAPI WINE_StringFromCLSID(const CLSID *rclsid, LPSTR idstr)
-{
-//    dprintf(("OLE32: WINE_StringFromCLSID"));
-
-    if (rclsid == NULL)
-    {
-	dprintf(("       clsid: (NULL)"));
-	*idstr = 0;
-	return E_FAIL;
-    }
-
-    // Setup new string...
-    sprintf(idstr, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
-	    rclsid->Data1,
-	    rclsid->Data2,
-	    rclsid->Data3,
-	    rclsid->Data4[0],
-	    rclsid->Data4[1],
-	    rclsid->Data4[2],
-	    rclsid->Data4[3],
-	    rclsid->Data4[4],
-	    rclsid->Data4[5],
-	    rclsid->Data4[6],
-	    rclsid->Data4[7]);
-
-//    dprintf(("       clsid: %s", idstr));
-
-    return OLE_OK;
-}
-
-// ----------------------------------------------------------------------
-// StringFromGUID2
-// ----------------------------------------------------------------------
-int WINAPI StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cbMax)
-{
-// NB cbMax is a CHARACTER count not a BYTE count... :-)
-    char 	tmp[50];
-    size_t	strLen;
-
-    // Setup new string...
-    WINE_StringFromCLSID(rguid, tmp);
-
-    strLen = (strlen(tmp) + 1);
-    if (strLen > cbMax)
-	strLen = cbMax;
-
-    AsciiToUnicodeN(tmp, lpsz, strLen);
-
-    return strLen;  // Num CHARACTERS including 0 terminator
-}
-#endif 
-
-/*****************************************************************************
- * Name      : DllGetVersion
- * Purpose   : Return version information about the DLL used
- * Parameters: 
- * Variables :
- * Result    : 
- * Remark    : SHLWAPI.446
- * Status    : UNTESTED 
- *
- * Author    : 
- *****************************************************************************/
-
-typedef struct tagDLLVERSION
-{
-  DWORD dwLength; // == 0x14
-  DWORD dwMajorVersion;
-  DWORD dwMinorVersion;
-  DWORD dwRevision;
-  DWORD dwBuildNumber;
-} DLLVERSION, *LPDLLVERSION;
-
-
-ODINFUNCTION1(DWORD,        DllGetVersion,
-              LPDLLVERSION, lpBuffer)
-{
-  if (lpBuffer == NULL)
-    return E_INVALIDARG; // error code: invalid parameters
-
-  if (IsBadWritePtr(lpBuffer,
-                    20))
-    return E_INVALIDARG;
-  
-  if (lpBuffer->dwLength != sizeof(DLLVERSION))
-    return E_INVALIDARG;
-      
-  // our current version is 5.0.2314.1000
-  lpBuffer->dwMajorVersion = 5;
-//lpBuffer->dwMinorVersion = 0;  // @@@PH not touched in windows code ?
-  lpBuffer->dwRevision     = 2314;
-  lpBuffer->dwBuildNumber  = 1;
-  
-  return ERROR_SUCCESS;
-}
Index: trunk/src/shlwapi/shlwapi.def
===================================================================
--- trunk/src/shlwapi/shlwapi.def	(revision 7815)
+++ trunk/src/shlwapi/shlwapi.def	(revision 7820)
@@ -1,3 +1,3 @@
-; $Id: shlwapi.def,v 1.27 2001-08-31 19:56:34 phaller Exp $
+; $Id: shlwapi.def,v 1.28 2002-02-06 20:18:29 sandervl Exp $
 
 ; updated export ordinals to NT4 SP6 version of SHLWAPI.DLL
@@ -35,4 +35,5 @@
                              _SHLWAPI_9@4                         @9  NONAME
                              _SHLWAPI_10@8                        @10 NONAME
+
                              _SHLWAPI_11@20                       @11 NONAME
                              _SHLWAPI_12@8                        @12 NONAME
@@ -40,8 +41,9 @@
                              _SHLWAPI_14@8                        @14 NONAME
                              _SHLWAPI_15@8                        @15 NONAME
-    SHCreateThread         = _SHCreateThread@16                   @16
+                             _SHLWAPI_16@16                       @16 NONAME
                              _SHLWAPI_17@8                        @17 NONAME
                              _SHLWAPI_18@8                        @18 NONAME
                              _SHLWAPI_19@4                        @19 NONAME
+
                              _SHLWAPI_20@8                        @20 NONAME
                              _SHLWAPI_21@8                        @21 NONAME
@@ -49,10 +51,21 @@
                              _SHLWAPI_23@12                       @23 NONAME
                              _SHLWAPI_24@12                       @24 NONAME
+                             _SHLWAPI_25@4                        @25 NONAME
+                             _SHLWAPI_26@4                        @26 NONAME
+                             _SHLWAPI_27@4                        @27 NONAME
                              _SHLWAPI_28@4                        @28 NONAME
+                             _SHLWAPI_29@4                        @29 NONAME
+
                              _SHLWAPI_30@4                        @30 NONAME
+                             _SHLWAPI_31@4                        @31 NONAME
                              _SHLWAPI_32@4                        @32 NONAME
+                             _SHLWAPI_33@4                        @33 NONAME
+                             _SHLWAPI_34@4                        @34 NONAME
+                             _SHLWAPI_35@12                       @35 NONAME
+                             _SHLWAPI_36@16                       @36 NONAME
                              _CallWindowProcW@20                  @37 NONAME
                              _CharLowerW@4                        @38 NONAME
                              _CharLowerBuffW@8                    @39 NONAME
+
                              _CharNextW@4                         @40 NONAME
                              _CharPrevW@8                         @41 NONAME
@@ -60,9 +73,10 @@
                              _CharUpperW@4                        @43 NONAME
                              _CharUpperBuffW@8                    @44 NONAME
-                             _CompareStringW@24                   @45 NONAME 
+                             _CompareStringW@24                   @45 NONAME
                              _CopyAcceleratorTableW@12            @46 NONAME
                              _CreateAcceleratorTableW@8           @47 NONAME
                              _CreateDCW@16                        @48 NONAME
                              _CreateDialogParamW@20               @49 NONAME ; @@@PH imcomplete
+
                              _CreateDirectoryW@8                  @50 NONAME
                              _CreateEventW@16                     @51 NONAME
@@ -75,4 +89,5 @@
                              _DialogBoxIndirectParamW@20          @58 NONAME ; @@@PH imcomplete
                              _DialogBoxParamW@20                  @59 NONAME ; @@@PH imcomplete
+
                              _DispatchMessageW@4                  @60 NONAME
                              _DrawTextW@20                        @61 NONAME
@@ -85,4 +100,5 @@
                              _FormatMessageW@28                   @68 NONAME
                              _GetClassInfoW@12                    @69 NONAME
+
                              _GetClassLongW@8                     @70 NONAME
                              _GetClassNameW@12                    @71 NONAME
@@ -95,4 +111,5 @@
                              _GetMenuItemInfoW@16                 @78 NONAME
                              _GetMessageW@16                      @79 NONAME
+
                              _GetModuleFileNameW@12               @80 NONAME
                              _GetSystemDirectoryW@8               @81 NONAME
@@ -105,4 +122,5 @@
                              _GetStringTypeExW@20                 @88 NONAME
                              _GetTempFileNameW@16                 @89 NONAME
+
                              _GetTempPathW@8                      @90 NONAME
                              _GetTextExtentPoint32W@16            @91 NONAME
@@ -115,4 +133,5 @@
                              _InsertMenuW@20                      @98 NONAME
                              _IsDialogMessageW@8                  @99 NONAME
+
                              _LoadAcceleratorsW@8                 @100 NONAME
                              _LoadBitmapW@8                       @101 NONAME
@@ -125,4 +144,5 @@
                              _MessageBoxIndirectW@4               @108 NONAME
                              _ModifyMenuW@20                      @109 NONAME
+
                              _GetCharWidth32W@16                  @110 NONAME
                              _GetCharacterPlacementW@24           @111 NONAME
@@ -135,4 +155,5 @@
                              _PostThreadMessageW@16               @118 NONAME
                              _RegCreateKeyW@12                    @119 NONAME
+
                              _RegCreateKeyExW@36                  @120 NONAME
                              _RegDeleteKeyW@8                     @121 NONAME
@@ -145,4 +166,5 @@
                              _RegQueryValueExW@24                 @128 NONAME
                              _RegSetValueW@20                     @129 NONAME
+
                              _RegSetValueExW@24                   @130 NONAME
                              _RegisterClassW@4                    @131 NONAME
@@ -153,6 +175,7 @@
                              _SendMessageW@16                     @136 NONAME
                              _SetCurrentDirectoryW@4              @137 NONAME
-                             _SetDlgItemTextW@12                  @138
-                             _SetMenuItemInfoW@16                 @139 ; @@@PH imcomplete
+                             _SetDlgItemTextW@12                  @138 NONAME
+                             _SetMenuItemInfoW@16                 @139 NONAME ; @@@PH imcomplete
+
                              _SetPropW@12                         @140 NONAME
                              _SetWindowLongW@12                   @141 NONAME
@@ -166,48 +189,78 @@
                              _WinHelpW@16                         @149 NONAME
                              _wvsprintfW@12                       @150 NONAME
+
                              _SHLWAPI_151@12                      @151 NONAME
                              _SHLWAPI_152@12                      @152 NONAME
                              _SHLWAPI_153@12                      @153 NONAME
                              _SHLWAPI_154@12                      @154 NONAME
-
+;;;;_SHLWAPI_155@??                      @155 NONAME
                              _SHLWAPI_156@8                       @156 NONAME
                              _SHLWAPI_158@8                       @158 NONAME
-; @@@PH dupe                 _CompareStringW@24                   @159 NONAME
+                             _CompareStringW@24                   @159 NONAME
+
                              _SHLWAPI_160@8                       @160 NONAME
                              _SHLWAPI_162@8                       @162 NONAME
+
+                             _SHLWAPI_164@24                      @164 NONAME
                              _SHLWAPI_165@16                      @165 NONAME
                              _SHLWAPI_169@4                       @169 NONAME
+
                              _SHLWAPI_170@4                       @170 NONAME
+                             _SHLWAPI_172@8                       @172 NONAME
+                             _SHLWAPI_174@8                       @174 NONAME
+                             _SHLWAPI_176@16                      @176 NONAME
+
+
                              _SHLWAPI_181@12                      @181 NONAME
                              _SHLWAPI_183@4                       @183 NONAME
                              _SHLWAPI_185@24                      @185 NONAME
+
                              _SHLWAPI_191@24                      @191 NONAME
                              _SHLWAPI_193@0                       @193 NONAME
                              _SHLWAPI_197@12                      @197 NONAME
+                             _SHLWAPI_199@8                       @199 NONAME
+
                              _SHLWAPI_205@24                      @205 NONAME
                              _SHLWAPI_206@24                      @206 NONAME
+                             _SHLWAPI_208@20                      @208 NONAME
+
+                             _SHLWAPI_210@12                      @210 NONAME
+                             _SHLWAPI_211@8                       @211 NONAME
+
                              _SHLWAPI_215@12                      @215 NONAME
                              _SHLWAPI_217@12                      @217 NONAME
                              _SHLWAPI_218@16                      @218 NONAME
                              _SHLWAPI_219@16                      @219 NONAME
+
                              _SHLWAPI_222@4                       @222 NONAME
                              _SHLWAPI_223@4                       @223 NONAME
+
+                             _SHLWAPI_236@4                       @236 NONAME
                              _SHLWAPI_237@4                       @237 NONAME
+                             _SHLWAPI_239@12                      @239 NONAME
+
                              _SHLWAPI_240@16                      @240 NONAME
-; PH                          _SHLWAPI_241@0                       @241 NONAME
+;;PH                             _SHLWAPI_241@0                       @241 NONAME
                              _PathRemoveArgsA@4                   @241 NONAME
                              _SHLWAPI_243@20                      @243 NONAME
+
 ;   AssocCreate            = _AssocCreate@20                      @253 ;by name
 ;   AssocQueryKeyA         = _AssocQueryKeyA@20                   @254 ;by name
 ;   AssocQueryKeyW         = _AssocQueryKeyW@20                   @255 ;by name
+
                              _SHLWAPI_266@16                      @266 NONAME
                              _SHLWAPI_267@16                      @267 NONAME
                              _SHLWAPI_268@8                       @268 NONAME
+
                              _SHLWAPI_276@0                       @276 NONAME ; -> SHEnumKeyExA
                              _SHLWAPI_278@24                      @278 NONAME
+
+                             _SHLWAPI_289@12                      @289 NONAME
+;;                             _SHLWAPI_284@20                      @294 NONAME
                              _WritePrivateProfileStringW@16       @298 NONAME
 
+                             _CreateFontW@56                      @300 NONAME
                              _DrawTextExW@24                      @301 NONAME
-; @@@PH dupe                 _GetMenuItemInfoW@16                 @302 NONAME ; FIXME CreateFontW
+                             _GetMenuItemInfoW@16                 @302 NONAME
                              _InsertMenuItemW@16                  @303 NONAME
                              _CreateMetaFileW@4                   @304 NONAME
@@ -223,5 +276,6 @@
                              _RegisterClassExW@4                  @314 NONAME
                              _GetClassInfoExW@12                  @315 NONAME
-
+;;316 stub SHCreateStreamOnFileAOld
+;;317 stub SHCreateStreamOnFileWOld
                              _SHLWAPI_318@16                      @318 NONAME
                              _FindWindowExW@16                    @319 NONAME
@@ -246,4 +300,5 @@
                              _RegDeleteValueW@8                   @347 NONAME
 
+                             _SHLWAPI_356@12                      @356 NONAME
                              _SHLWAPI_357@20                      @357 NONAME
                              _SHLWAPI_358@24                      @358 NONAME
@@ -253,5 +308,5 @@
 
                              _SHLWAPI_364@12                      @364 NONAME
-                     
+
                              _RegEnumValueW@32                    @366 NONAME
                              _WritePrivateProfileStructW@20       @367 NONAME
@@ -266,6 +321,9 @@
 ;   AssocQueryStringA      = _AssocQueryStringA@20                @381
 ;   AssocQueryStringByKeyA = _AssocQueryStringByKeyA@20           @382
+;;383 stub AssocQueryStringByKeyW
+;;384 stub AssocQueryStringW
     ChrCmpIA               = _ChrCmpIA@8                          @385
-  ; ChrCmpIW               = _ChrCmpIW@8                          @386
+    ChrCmpIW               = _ChrCmpIW@8                          @386
+;;387 stub ColorAdjustLuma
 
                              _SHLWAPI_389@4                       @389 NONAME
@@ -283,4 +341,8 @@
 ;                            _SHLWAPI_410@12                      @410 NONAME
 
+                             _SHLWAPI_413@4                       @413 NONAME
+
+                             _TrackPopupMenuEx@24                 @428 NONAME
+
                              _SHLWAPI_431@4                       @431 NONAME
 
@@ -288,11 +350,11 @@
 
                              _SHLWAPI_437@4                       @437 NONAME
-         
+
                              _GetEnvironmentVariableW@12          @442 NONAME
                              _GetSystemWindowsDirectoryA@8        @443 NONAME
                              _GetSystemWindowsDirectoryW@8        @444 NONAME
-  ; ColorRGBToHLS @445
-
-    DllGetVersion          = _DllGetVersion@4                     @446
+    ColorRGBToHLS          = _ColorRGBToHLS@16                    @445
+
+    DllGetVersion          = _SHLWAPI_DllGetVersion@4             @446
     GetMenuPosFromID       = _GetMenuPosFromID@8                  @447
     HashData               = _HashData@16                         @448
@@ -424,8 +486,8 @@
     SHDeleteValueA         = _SHDeleteValueA@12                   @573
     SHDeleteValueW         = _SHDeleteValueW@12                   @574
-  ; SHEnumKeyExA           = _SHEnumKeyExA@?                      @575
-  ; SHEnumKeyExW           = _SHEnumKeyExW@?                      @576
-  ; SHEnumValueA           = _SHEnumValueA@?                      @577
-  ; SHEnumValueW           = _SHEnumValueW@?                      @578
+    SHEnumKeyExA           = _SHEnumKeyExA@16                     @575
+    SHEnumKeyExW           = _SHEnumKeyExW@16                     @576
+    SHEnumValueA           = _SHEnumValueA@28                     @577
+    SHEnumValueW           = _SHEnumValueW@28                     @578
     _SHGetInstanceExplorer = __SHGetInstanceExplorer@4            @579
     SHGetInverseCMAP       = _SHGetInverseCMAP@8                  @580
@@ -438,6 +500,6 @@
     SHOpenRegStreamA       = _SHOpenRegStreamA@16                 @587
     SHOpenRegStreamW       = _SHOpenRegStreamW@16                 @588
-  ; SHQueryInfoKeyA        = _SHQueryInfoKeyA@?                   @589
-  ; SHQueryInfoKeyW        = _SHQueryInfoKeyW@?                   @590
+    SHQueryInfoKeyA        = _SHQueryInfoKeyA@20                  @589
+    SHQueryInfoKeyW        = _SHQueryInfoKeyW@20                  @590
     SHQueryValueExA        = _SHQueryValueExA@24                  @591
     SHQueryValueExW        = _SHQueryValueExW@24                  @592
@@ -460,6 +522,6 @@
     SHRegOpenUSKeyA        = _SHRegOpenUSKeyA@20                  @609
     SHRegOpenUSKeyW        = _SHRegOpenUSKeyW@20                  @610
-  ; SHRegQueryInfoKeyA     = _SHRegQueryInfoKeyA@?                @611
-  ; SHRegQueryInfoKeyW     = _SHRegQueryInfoKeyW@?                @612
+;    SHRegQueryInfoKeyA     = _SHRegQueryInfoKeyA@24               @611
+;    SHRegQueryInfoKeyW     = _SHRegQueryInfoKeyW@24               @612
     SHRegQueryUSValueA     = _SHRegQueryUSValueA@32               @613
     SHRegQueryUSValueW     = _SHRegQueryUSValueW@32               @614
@@ -493,5 +555,5 @@
     StrCmpW                = _lstrcmpW@8                          @641
     StrCpyNW               = _lstrcpynW@12                        @642
-    StrCpyA                = _StrCpyA@8                                 ; not exported ?
+;;;    StrCpyA                = _StrCpyA@8                                 ; not exported ?
     StrCpyW                = _StrCpyW@8                           @643
     StrDupA                = _StrDupA@4                           @644
@@ -511,9 +573,9 @@
     StrPBrkW               = _StrPBrkW@8                          @658
     StrRChrA               = _StrRChrA@12                         @659
-  ; StrRChrIA              = _StrRChrIA@12                        @660
-  ; StrRChrIW              = _StrRChrIW@12                        @661
+    StrRChrIA              = _StrRChrIA@12                        @660
+    StrRChrIW              = _StrRChrIW@12                        @661
     StrRChrW               = _StrRChrW@12                         @662
-    StrRStrIA              = _StrRStrIA@8                         @663
-    StrRStrIW              = _StrRStrIW@8                         @664
+    StrRStrIA              = _StrRStrIA@12                        @663
+    StrRStrIW              = _StrRStrIW@12                        @664
     StrRetToBufA           = _StrRetToBufA@16                     @665
     StrRetToBufW           = _StrRetToBufW@16                     @666
Index: trunk/src/shlwapi/shlwapi_main.c
===================================================================
--- trunk/src/shlwapi/shlwapi_main.c	(revision 7820)
+++ trunk/src/shlwapi/shlwapi_main.c	(revision 7820)
@@ -0,0 +1,85 @@
+/*
+ * SHLWAPI initialisation
+ *
+ *  Copyright 1998 Marcus Meissner
+ *  Copyright 1998 Juergen Schmied (jsch)
+ */
+
+#include "winbase.h"
+#include "winerror.h"
+#include "winreg.h"
+#include "debugtools.h"
+#define NO_SHLWAPI_STREAM
+#ifndef __WIN32OS2__
+#include "shlwapi.h"
+#endif
+
+DEFAULT_DEBUG_CHANNEL(shell);
+
+HINSTANCE shlwapi_hInstance = 0; 
+HMODULE SHLWAPI_hshell32 = 0;
+HMODULE SHLWAPI_hwinmm = 0;
+HMODULE SHLWAPI_hcomdlg32 = 0;
+HMODULE SHLWAPI_hmpr = 0;
+HMODULE SHLWAPI_hmlang = 0;
+
+/*************************************************************************
+ * SHLWAPI LibMain
+ *
+ * NOTES
+ *  calling oleinitialize here breaks sone apps.
+ */
+BOOL WINAPI SHLWAPI_LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
+{
+	TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
+	switch (fdwReason)
+	{
+	  case DLL_PROCESS_ATTACH:
+	    shlwapi_hInstance = hinstDLL;
+	    break;
+	  case DLL_PROCESS_DETACH:
+	    if (SHLWAPI_hshell32)  FreeLibrary(SHLWAPI_hshell32);
+	    if (SHLWAPI_hwinmm)    FreeLibrary(SHLWAPI_hwinmm);
+	    if (SHLWAPI_hcomdlg32) FreeLibrary(SHLWAPI_hcomdlg32);
+	    if (SHLWAPI_hmpr)      FreeLibrary(SHLWAPI_hmpr);
+	    if (SHLWAPI_hmlang)    FreeLibrary(SHLWAPI_hmlang);
+	    break;
+	}
+	return TRUE;
+}
+
+/***********************************************************************
+ * DllGetVersion [SHLWAPI.@]
+ *
+ * Retrieves version information of the 'SHLWAPI.DLL'
+ *
+ * PARAMS
+ *     pdvi [O] pointer to version information structure.
+ *
+ * RETURNS
+ *     Success: S_OK
+ *     Failure: E_INVALIDARG
+ *
+ * NOTES
+ *     Returns version of a SHLWAPI.dll from IE5.01.
+ */
+
+HRESULT WINAPI SHLWAPI_DllGetVersion (DLLVERSIONINFO *pdvi)
+{
+	if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
+	{
+	  WARN("wrong DLLVERSIONINFO size from app\n");
+	  return E_INVALIDARG;
+	}
+
+	pdvi->dwMajorVersion = 5;
+	pdvi->dwMinorVersion = 0;
+	pdvi->dwBuildNumber = 2314;
+	pdvi->dwPlatformID = 1000;
+
+	TRACE("%lu.%lu.%lu.%lu\n",
+	   pdvi->dwMajorVersion, pdvi->dwMinorVersion,
+	   pdvi->dwBuildNumber, pdvi->dwPlatformID);
+
+	return S_OK;
+}
Index: trunk/src/shlwapi/shlwapi_odin.h
===================================================================
--- trunk/src/shlwapi/shlwapi_odin.h	(revision 7815)
+++ trunk/src/shlwapi/shlwapi_odin.h	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: shlwapi_odin.h,v 1.2 2001-08-30 19:19:58 phaller Exp $ */
+/* $Id: shlwapi_odin.h,v 1.3 2002-02-06 20:18:29 sandervl Exp $ */
 
 /*
@@ -31,16 +31,5 @@
 typedef HUSKEY *PHUSKEY;
 
-typedef DWORD SHREGDEL_FLAGS;
-#define SHREGDEL_BOTH
-
-typedef DWORD SHREGENUM_FLAGS;
-#define SHREGENUM_HKCU    
-#define SHREGENUM_DEFAULT 
-#define SHREGENUM_HKLM
-
-typedef DWORD SHREGSET_FLAGS;
-#define SHREGSET_HKLM
-#define SHREGSET_DEFAULT
-    
+   
     
     
Index: trunk/src/shlwapi/string.c
===================================================================
--- trunk/src/shlwapi/string.c	(revision 7815)
+++ trunk/src/shlwapi/string.c	(revision 7820)
@@ -1,17 +1,2 @@
-//Note: Odin changes marked by #ifdef __WIN32OS2__!
-#ifdef __WIN32OS2__
-#include <odin.h>
-#include <odinwrap.h>
-#include <os2sel.h>
-
-#include <string.h>
-#include <wctype.h>
-#include <wcstr.h>
-#define HAVE_WCTYPE_H
-#include <win\shlwapi.h>
-
-#include <heapstring.h>
-#include <winnls.h>
-#endif
 #include <ctype.h>
 #include <stdlib.h> 
@@ -24,6 +9,14 @@
 #include "wingdi.h"
 #include "winuser.h"
+#include "winreg.h"
+#ifdef __WIN32OS2__
+#include "shlobj.h"
+#define NO_SHLWAPI_STREAM
+#include "shlwapi.h"
+#else
+#define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "shlobj.h"
+#endif
 #include "wine/unicode.h"
 #include "debugtools.h"
@@ -32,5 +25,27 @@
 
 /*************************************************************************
- * StrChrA					[SHLWAPI]
+ * ChrCmpIA					[SHLWAPI.385]
+ *
+ * Note: Returns 0 (FALSE) if characters are equal (insensitive).
+ */
+BOOL WINAPI ChrCmpIA (WORD w1, WORD w2)
+{
+	TRACE("%c ? %c\n", w1, w2);
+	return (toupper(w1) != toupper(w2));
+}
+
+/*************************************************************************
+ * ChrCmpIW					[SHLWAPI.386]
+ *
+ * Note: Returns 0 (FALSE) if characters are equal (insensitive).
+ */
+BOOL WINAPI ChrCmpIW (WCHAR w1, WCHAR w2)
+{
+	TRACE("%c ? %c\n", w1, w2);
+	return (toupperW(w1) != toupperW(w2));
+}
+
+/*************************************************************************
+ * StrChrA					[SHLWAPI.@]
  */
 LPSTR WINAPI StrChrA (LPCSTR str, WORD c)
@@ -41,5 +56,5 @@
 
 /*************************************************************************
- * StrChrW					[SHLWAPI]
+ * StrChrW					[SHLWAPI.@]
  *
  */
@@ -49,7 +64,7 @@
 	return strchrW(str, x);
 }
-#ifndef __WIN32OS2__
-/*************************************************************************
- * StrCmpIW					[SHLWAPI]
+
+/*************************************************************************
+ * StrCmpIW					[SHLWAPI.@]
  */
 int WINAPI StrCmpIW ( LPCWSTR wstr1, LPCWSTR wstr2 )
@@ -58,8 +73,7 @@
     return strcmpiW( wstr1, wstr2 );
 }
-#endif
-
-/*************************************************************************
- * StrCmpNA					[SHLWAPI]
+
+/*************************************************************************
+ * StrCmpNA					[SHLWAPI.@]
  */
 INT WINAPI StrCmpNA ( LPCSTR str1, LPCSTR str2, INT len)
@@ -70,5 +84,5 @@
 
 /*************************************************************************
- * StrCmpNW					[SHLWAPI]
+ * StrCmpNW					[SHLWAPI.@]
  */
 INT WINAPI StrCmpNW ( LPCWSTR wstr1, LPCWSTR wstr2, INT len)
@@ -79,5 +93,5 @@
 
 /*************************************************************************
- * StrCmpNIA					[SHLWAPI]
+ * StrCmpNIA					[SHLWAPI.@]
  */
 int WINAPI StrCmpNIA ( LPCSTR str1, LPCSTR str2, int len)
@@ -88,5 +102,5 @@
 
 /*************************************************************************
- * StrCmpNIW					[SHLWAPI]
+ * StrCmpNIW					[SHLWAPI.@]
  */
 int WINAPI StrCmpNIW ( LPCWSTR wstr1, LPCWSTR wstr2, int len)
@@ -97,5 +111,5 @@
 
 /*************************************************************************
- * StrCmpW					[SHLWAPI]
+ * StrCmpW					[SHLWAPI.@]
  */
 int WINAPI StrCmpW ( LPCWSTR wstr1, LPCWSTR wstr2 )
@@ -106,5 +120,5 @@
 
 /*************************************************************************
- * StrCatW					[SHLWAPI]
+ * StrCatW					[SHLWAPI.@]
  */
 LPWSTR WINAPI StrCatW( LPWSTR wstr1, LPCWSTR wstr2 )
@@ -115,5 +129,5 @@
 
 /*************************************************************************
- * StrCpyW					[SHLWAPI]
+ * StrCpyW					[SHLWAPI.@]
  */
 LPWSTR WINAPI StrCpyW( LPWSTR wstr1, LPCWSTR wstr2 )
@@ -124,5 +138,5 @@
 
 /*************************************************************************
- * StrCpyNW					[SHLWAPI]
+ * StrCpyNW					[SHLWAPI.@]
  */
 LPWSTR WINAPI StrCpyNW( LPWSTR wstr1, LPCWSTR wstr2, int n )
@@ -133,5 +147,5 @@
 
 /*************************************************************************
- * StrStrA					[SHLWAPI]
+ * StrStrA					[SHLWAPI.@]
  */
 LPSTR WINAPI StrStrA(LPCSTR lpFirst, LPCSTR lpSrch)
@@ -148,5 +162,5 @@
 
 /*************************************************************************
- * StrStrW					[SHLWAPI]
+ * StrStrW					[SHLWAPI.@]
  */
 LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
@@ -163,5 +177,5 @@
 
 /*************************************************************************
- * StrStrIA					[SHLWAPI]
+ * StrStrIA					[SHLWAPI.@]
  */
 LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
@@ -178,5 +192,5 @@
 
 /*************************************************************************
- * StrStrIW					[SHLWAPI]
+ * StrStrIW					[SHLWAPI.@]
  */
 LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
@@ -193,5 +207,5 @@
 
 /*************************************************************************
- *	StrToIntA			[SHLWAPI]
+ *	StrToIntA			[SHLWAPI.@]
  */
 int WINAPI StrToIntA(LPCSTR lpSrc)
@@ -202,5 +216,5 @@
 
 /*************************************************************************
- *	StrToIntW			[SHLWAPI]
+ *	StrToIntW			[SHLWAPI.@]
  */
 int WINAPI StrToIntW(LPCWSTR lpSrc)
@@ -215,5 +229,5 @@
 
 /*************************************************************************
- *	StrToIntExA			[SHLWAPI]
+ *	StrToIntExA			[SHLWAPI.@]
  */
 BOOL WINAPI StrToIntExA( LPCSTR pszString, DWORD dwFlags, LPINT piRet)
@@ -225,5 +239,5 @@
 
 /*************************************************************************
- *	StrToIntExW			[SHLWAPI]
+ *	StrToIntExW			[SHLWAPI.@]
  */
 BOOL WINAPI StrToIntExW( LPCWSTR pszString, DWORD dwFlags, LPINT piRet)
@@ -235,5 +249,5 @@
 
 /*************************************************************************
- *	StrDupA			[SHLWAPI]
+ *	StrDupA			[SHLWAPI.@]
  */
 LPSTR WINAPI StrDupA (LPCSTR lpSrc)
@@ -249,5 +263,5 @@
 
 /*************************************************************************
- *	StrDupW			[SHLWAPI]
+ *	StrDupW			[SHLWAPI.@]
  */
 LPWSTR WINAPI StrDupW (LPCWSTR lpSrc)
@@ -263,5 +277,5 @@
 
 /*************************************************************************
- *	StrCSpnA		[SHLWAPI]
+ *	StrCSpnA		[SHLWAPI.@]
  */
 int WINAPI StrCSpnA (LPCSTR lpStr, LPCSTR lpSet)
@@ -287,5 +301,5 @@
 
 /*************************************************************************
- *	StrCSpnW		[SHLWAPI]
+ *	StrCSpnW		[SHLWAPI.@]
  */
 int WINAPI StrCSpnW (LPCWSTR lpStr, LPCWSTR lpSet)
@@ -320,5 +334,5 @@
 
     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
-
+    if (!lpStart && !lpEnd) return NULL;
     if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
 
@@ -342,4 +356,5 @@
 
     TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
+    if (!lpStart && !lpEnd) return NULL;
     if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
 
@@ -351,6 +366,54 @@
 
 
-/*************************************************************************
- *	StrCatBuffA		[SHLWAPI]
+/**************************************************************************
+ * StrRChrIA [SHLWAPI.@]
+ *
+ */
+LPSTR WINAPI StrRChrIA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
+{
+    LPCSTR lpGotIt = NULL;
+    BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
+
+    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
+    if (!lpStart && !lpEnd) return NULL;
+    if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
+
+    for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
+    {
+	if (dbcs) {
+	    /*
+	    if (_mbctoupper(*lpStart) == _mbctoupper(wMatch))
+		lpGotIt = lpStart;
+	    */
+	    if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
+	} else {
+	    if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
+	}
+    }    
+    return (LPSTR)lpGotIt;
+}
+
+
+/**************************************************************************
+ * StrRChrIW [SHLWAPI.@]
+ *
+ */
+LPWSTR WINAPI StrRChrIW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
+{
+    LPCWSTR lpGotIt = NULL;
+
+    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
+    if (!lpStart && !lpEnd) return NULL;
+    if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
+
+    for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
+        if (toupperW(*lpStart) == toupperW(wMatch)) lpGotIt = lpStart;
+
+    return (LPWSTR)lpGotIt;
+}
+
+
+/*************************************************************************
+ *	StrCatBuffA		[SHLWAPI.@]
  *
  * Appends back onto front, stopping when front is size-1 characters long.
@@ -370,5 +433,5 @@
 
 /*************************************************************************
- *	StrCatBuffW		[SHLWAPI]
+ *	StrCatBuffW		[SHLWAPI.@]
  *
  * Appends back onto front, stopping when front is size-1 characters long.
@@ -394,8 +457,15 @@
  * NOTES
  *  the pidl is for STRRET OFFSET
+ *
+ * ***** NOTE *****
+ *  This routine is identical to StrRetToStrNA in dlls/shell32/shellstring.c.
+ *  It was duplicated there because not every version of Shlwapi.dll exports
+ *  StrRetToBufA. If you change one routine, change them both. YOU HAVE BEEN
+ *  WARNED.
+ * ***** NOTE *****
  */
 HRESULT WINAPI StrRetToBufA (LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, DWORD len)
 {
-	TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
+	TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest,len,src,pidl);
 
 	switch (src->uType)
@@ -432,8 +502,15 @@
  * NOTES
  *  the pidl is for STRRET OFFSET
+ *
+ * ***** NOTE *****
+ *  This routine is identical to StrRetToStrNW in dlls/shell32/shellstring.c.
+ *  It was duplicated there because not every version of Shlwapi.dll exports
+ *  StrRetToBufW. If you change one routine, change them both. YOU HAVE BEEN
+ *  WARNED.
+ * ***** NOTE *****
  */
 HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, DWORD len)
 {
-	TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
+	TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest,len,src,pidl);
 
 	switch (src->uType)
@@ -469,5 +546,5 @@
 
 /*************************************************************************
- * StrFormatByteSizeA				[SHLWAPI]
+ * StrFormatByteSizeA				[SHLWAPI.@]
  */
 LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
@@ -491,5 +568,5 @@
 
 /*************************************************************************
- * StrFormatByteSizeW				[SHLWAPI]
+ * StrFormatByteSizeW				[SHLWAPI.@]
  */
 LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
@@ -503,5 +580,5 @@
 
 /*************************************************************************
- *      StrNCatA	[SHLWAPI]
+ *      StrNCatA	[SHLWAPI.@]
  */
 LPSTR WINAPI StrNCatA(LPSTR front, LPCSTR back, INT cchMax)
@@ -512,5 +589,5 @@
 
 /*************************************************************************
- *      StrNCatW	[SHLWAPI]
+ *      StrNCatW	[SHLWAPI.@]
  */
 LPWSTR WINAPI StrNCatW(LPWSTR front, LPCWSTR back, INT cchMax)
@@ -546,5 +623,5 @@
 
 /*************************************************************************
- *      wnsprintfA	[SHLWAPI]
+ *      wnsprintfA	[SHLWAPI.@]
  */
 int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
@@ -560,5 +637,5 @@
 
 /*************************************************************************
- *      wnsprintfW	[SHLWAPI]
+ *      wnsprintfW	[SHLWAPI.@]
  */
 int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
Index: trunk/src/shlwapi/string_odin.cpp
===================================================================
--- trunk/src/shlwapi/string_odin.cpp	(revision 7815)
+++ trunk/src/shlwapi/string_odin.cpp	(revision 7820)
@@ -1,3 +1,4 @@
-/* $Id: string_odin.cpp,v 1.5 2001-09-05 13:48:39 bird Exp $ */
+ /* $Id: string_odin.cpp,v 1.6 2002-02-06 20:18:30 sandervl Exp $ */
+
 /*
  * Win32 Lightweight SHELL32 for OS/2
@@ -69,116 +70,4 @@
 
 
-/*****************************************************************************
- * Name      : ChrCmpIA
- * Purpose   :
- * Parameters:
- * Variables :
- * Result    :
- * Remark    :
- * Status    : PARTIALLY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Wed, 1999/12/29 09:00]
- *****************************************************************************/
-
-ODINFUNCTION2(INT,    ChrCmpIA,
-              INT,    ch1,
-              INT,    ch2)
-{
-  // Note: IsDBCSLeadByte ignored !
-
-  if ( (ch1 >= 'A') && (ch1 <= 'Z') ) ch1 |= 0x20;
-  if ( (ch2 >= 'A') && (ch2 <= 'Z') ) ch2 |= 0x20;
-
-  return ch1 - ch2;
-}
-
-
-#if 0
-/*************************************************************************
- * OleStrToStrN                                 [SHELL32.78]
- */
-BOOL WINAPI OleStrToStrNA (LPSTR lpStr, INT nStr, LPCWSTR lpOle, INT nOle)
-{
-        TRACE("%p %x %s %x\n", lpStr, nStr, debugstr_w(lpOle), nOle);
-        return WideCharToMultiByte (0, 0, lpOle, nOle, lpStr, nStr, NULL, NULL);
-}
-
-BOOL WINAPI OleStrToStrNW (LPWSTR lpwStr, INT nwStr, LPCWSTR lpOle, INT nOle)
-{
-        TRACE("%p %x %s %x\n", lpwStr, nwStr, debugstr_w(lpOle), nOle);
-
-        if (lstrcpynW ( lpwStr, lpOle, nwStr))
-        { return lstrlenW (lpwStr);
-        }
-        return 0;
-}
-
-BOOL WINAPI OleStrToStrNAW (LPVOID lpOut, INT nOut, LPCVOID lpIn, INT nIn)
-{
-        if (VERSION_OsIsUnicode())
-          return OleStrToStrNW ((LPWSTR)lpOut, nOut, (LPCWSTR)lpIn, nIn);
-        return OleStrToStrNA ((LPSTR)lpOut, nOut, (LPCWSTR)lpIn, nIn);
-}
-
-/*************************************************************************
- * StrToOleStrN                                 [SHELL32.79]
- *  lpMulti, nMulti, nWide [IN]
- *  lpWide [OUT]
- */
-BOOL WINAPI StrToOleStrNA (LPWSTR lpWide, INT nWide, LPCSTR lpStrA, INT nStr)
-{
-        TRACE("%p %x %s %x\n", lpWide, nWide, lpStrA, nStr);
-        return MultiByteToWideChar (0, 0, lpStrA, nStr, lpWide, nWide);
-}
-BOOL WINAPI StrToOleStrNW (LPWSTR lpWide, INT nWide, LPCWSTR lpStrW, INT nStr)
-{
-        TRACE("%p %x %s %x\n", lpWide, nWide, debugstr_w(lpStrW), nStr);
-
-        if (lstrcpynW (lpWide, lpStrW, nWide))
-        { return lstrlenW (lpWide);
-        }
-        return 0;
-}
-
-BOOL WINAPI StrToOleStrNAW (LPWSTR lpWide, INT nWide, LPCVOID lpStr, INT nStr)
-{
-        if (VERSION_OsIsUnicode())
-          return StrToOleStrNW (lpWide, nWide, (LPWSTR)lpStr, nStr);
-        return StrToOleStrNA (lpWide, nWide, (LPSTR)lpStr, nStr);
-}
-
-
-
-
-/************************************************************************
- *      StrToOleStr                     [SHELL32.163]
- *
- */
-int WINAPI StrToOleStrA (LPWSTR lpWideCharStr, LPCSTR lpMultiByteString)
-{
-        TRACE("%p %p(%s)\n",
-        lpWideCharStr, lpMultiByteString, lpMultiByteString);
-
-        return MultiByteToWideChar(0, 0, lpMultiByteString, -1, lpWideCharStr, MAX_PATH);
-
-}
-int WINAPI StrToOleStrW (LPWSTR lpWideCharStr, LPCWSTR lpWString)
-{
-        TRACE("%p %p(%s)\n",
-        lpWideCharStr, lpWString, debugstr_w(lpWString));
-
-        if (lstrcpyW (lpWideCharStr, lpWString ))
-        { return lstrlenW (lpWideCharStr);
-        }
-        return 0;
-}
-
-BOOL WINAPI StrToOleStrAW (LPWSTR lpWideCharStr, LPCVOID lpString)
-{
-        if (VERSION_OsIsUnicode())
-          return StrToOleStrW (lpWideCharStr, (LPCWSTR)lpString);
-        return StrToOleStrA (lpWideCharStr, (LPCSTR)lpString);
-}
-#endif
 
 
@@ -200,14 +89,14 @@
 ODINFUNCTION2(LPSTR,  StrChrIA,
               LPCSTR, lpStart,
-              WORD,   wMatch)
+              char,   cMatch)
 {
   LPSTR lpRes;
 
-  wMatch = tolower(wMatch);
-  lpRes = strchr(lpStart, wMatch);    // lower case comparsion
+  cMatch = tolower(cMatch);
+  lpRes = strchr(lpStart, cMatch);    // lower case comparsion
   if (NULL == lpRes)
   {
-    wMatch = toupper(wMatch);
-    lpRes = strchr(lpStart, wMatch);  // upper case comparsion
+    cMatch = toupper(cMatch);
+    lpRes = strchr(lpStart, cMatch);  // upper case comparsion
   }
 
@@ -293,11 +182,11 @@
        (lpString2 == NULL) )
     return 0;
-
+  
   LPSTR lpLoop = (LPSTR)lpString1;
-
+  
   for (; (*lpLoop != 0); lpLoop++ )
     if ( StrChrA( lpString2, *lpLoop ) )
       return (INT) (lpLoop - lpString1);
-
+  
   return (INT) (lpLoop - lpString1);
 }
@@ -327,11 +216,11 @@
        (lpString2 == NULL) )
     return 0;
-
+  
   LPWSTR lpLoop = (LPWSTR)lpString1;
-
+  
   for (; (*lpLoop != 0); lpLoop++ )
     if ( StrChrW( lpString2, *lpLoop ) )
       return (INT) (lpLoop - lpString1);
-
+  
   return (INT) (lpLoop - lpString1);
 }
@@ -344,5 +233,5 @@
  * Variables :
  * Result    :
- * Remark    :
+ * Remark    : 
  * Status    : UNTESTED
  *
@@ -355,5 +244,5 @@
 {
   register LPSTR s1;
-
+  
   while (*lpString1)
   {
@@ -369,5 +258,5 @@
     lpString1++;
   }
-
+  
   return (LPSTR)NULL;
 }
@@ -380,5 +269,5 @@
  * Variables :
  * Result    :
- * Remark    :
+ * Remark    : 
  * Status    : UNTESTED
  *
@@ -391,5 +280,5 @@
 {
   register LPWSTR s1;
-
+  
   while (*lpString1)
   {
@@ -405,5 +294,5 @@
     lpString1++;
   }
-
+  
   return (LPWSTR)NULL;
 }
@@ -411,16 +300,18 @@
 
 /*************************************************************************
- * StrRStrIA                    [SHLWAPI]
+ * StrRStrIA					[SHLWAPI]
  */
-LPSTR WINAPI StrRStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
+LPSTR WINAPI StrRStrIA(LPCSTR lpFirst, LPCSTR lpSrch, LPCSTR unknown)
 {
   INT   iLen = lstrlenA(lpFirst) - lstrlenA(lpSrch);
 
+  dprintf(("StrRStrIA %x %x %x NOT IMPLEMENTED correctly", lpFirst, lpSrch, unknown));
+  
   // lpSrch cannot fit into lpFirst
   if (iLen < 0)
     return (LPSTR)NULL;
-
+  
   LPSTR lpThis = (LPSTR)lpFirst + iLen;
-
+  
   while (lpThis >= lpFirst)
   {
@@ -430,5 +321,5 @@
     lpThis--;
   }
-
+  
   return NULL;
 }
@@ -436,16 +327,18 @@
 
 /*************************************************************************
- * StrRStrIW                    [SHLWAPI]
+ * StrRStrIW					[SHLWAPI]
  */
-LPWSTR WINAPI StrRStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
+LPWSTR WINAPI StrRStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch, LPCWSTR unknown)
 {
   INT   iLen = lstrlenW(lpFirst) - lstrlenW(lpSrch);
 
+  dprintf(("StrRStrIA %x %x %x NOT IMPLEMENTED correctly", lpFirst, lpSrch, unknown));
+  
   // lpSrch cannot fit into lpFirst
   if (iLen < 0)
     return (LPWSTR)NULL;
-
+  
   LPWSTR lpThis = (LPWSTR)lpFirst + iLen;
-
+  
   while (lpThis >= lpFirst)
   {
@@ -455,5 +348,5 @@
     lpThis--;
   }
-
+  
   return NULL;
 }
Index: trunk/src/shlwapi/url.c
===================================================================
--- trunk/src/shlwapi/url.c	(revision 7815)
+++ trunk/src/shlwapi/url.c	(revision 7820)
@@ -4,17 +4,50 @@
  * Copyright 2000 Huw D M Davies for CodeWeavers.
  */
+#ifdef __WIN32OS2__
+#include <ctype.h>
+#include <stdarg.h>
+#include <winuser.h>
+#endif
 
 #include <string.h>
+#include <stdlib.h>
 #include "windef.h"
+#include "winnls.h"
 #include "winbase.h"
 #include "winerror.h"
+#include "wine/unicode.h"
+#include "wininet.h"
+#include "winreg.h"
+#define NO_SHLWAPI_STREAM
 #include "shlwapi.h"
 #include "debugtools.h"
-
-#ifdef __WIN32OS2__
-#include <ctype.h>
-#endif
+#include "ordinal.h"
+
 
 DEFAULT_DEBUG_CHANNEL(shell);
+
+typedef struct {
+    LPCWSTR pScheme;      /* [out] start of scheme                     */
+    DWORD   szScheme;     /* [out] size of scheme (until colon)        */
+    LPCWSTR pUserName;    /* [out] start of Username                   */
+    DWORD   szUserName;   /* [out] size of Username (until ":" or "@") */
+    LPCWSTR pPassword;    /* [out] start of Password                   */
+    DWORD   szPassword;   /* [out] size of Password (until "@")        */
+    LPCWSTR pHostName;    /* [out] start of Hostname                   */
+    DWORD   szHostName;   /* [out] size of Hostname (until ":" or "/") */
+    LPCWSTR pPort;        /* [out] start of Port                       */
+    DWORD   szPort;       /* [out] size of Port (until "/" or eos)     */
+    LPCWSTR pQuery;       /* [out] start of Query                      */
+    DWORD   szQuery;      /* [out] size of Query (until eos)           */
+} WINE_PARSE_URL;
+
+typedef enum {
+    SCHEME,
+    HOST,
+    PORT,
+    USERPASS,
+} WINE_URL_SCAN_TYPE;
+
+static const WCHAR fileW[] = {'f','i','l','e','\0'};
 
 static const unsigned char HashDataLookup[256] = {
@@ -40,5 +73,5 @@
  0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
 
-static BOOL URL_NeedEscape(CHAR ch, DWORD dwFlags)
+static BOOL URL_NeedEscapeA(CHAR ch, DWORD dwFlags)
 {
 
@@ -52,4 +85,7 @@
 	    return FALSE;
     }
+
+    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
+	return TRUE;
 
     if (ch <= 31 || ch >= 127)
@@ -73,4 +109,7 @@
 	    return TRUE;
 
+	case '/':
+	case '?':
+	    if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
 	default:
 	    return FALSE;
@@ -79,40 +118,255 @@
 }
 
-/*************************************************************************
- *        UrlCanonicalizeA     [SHLWAPI]
+static 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++;
+    if (*str) {
+	while (*str && ((*str == L'-') ||
+			(*str == L'.') ||
+			isalnumW(*str))) str++;
+	if (*str == L'/') return FALSE;
+    }
+    return TRUE;
+}
+
+
+/*************************************************************************
+ *        UrlCanonicalizeA     [SHLWAPI.@]
+ *
+ * Uses the W version to do job.
  */
 HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
 	LPDWORD pcchCanonicalized, DWORD dwFlags)
 {
+    LPWSTR base, canonical;
+    DWORD ret, len, len2;
+
+    TRACE("(%s %p %p 0x%08lx) using W version\n",
+	  debugstr_a(pszUrl), pszCanonicalized,
+	  pcchCanonicalized, dwFlags);
+
+    base = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, 
+			      (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
+    canonical = base + INTERNET_MAX_URL_LENGTH;
+
+    MultiByteToWideChar(0, 0, pszUrl, -1, base, INTERNET_MAX_URL_LENGTH);
+    len = INTERNET_MAX_URL_LENGTH;
+
+    ret = UrlCanonicalizeW(base, canonical, &len, dwFlags);
+    if (ret != S_OK) {
+	HeapFree(GetProcessHeap(), 0, base);
+	return ret;
+    }
+
+    len2 = WideCharToMultiByte(0, 0, canonical, len, 0, 0, 0, 0);
+    if (len2 > *pcchCanonicalized) {
+	*pcchCanonicalized = len;
+	HeapFree(GetProcessHeap(), 0, base);
+	return E_POINTER;
+    }
+    WideCharToMultiByte(0, 0, canonical, len+1, pszCanonicalized, 
+			*pcchCanonicalized, 0, 0);
+    *pcchCanonicalized = len2;
+    HeapFree(GetProcessHeap(), 0, base);
+    return S_OK;
+}
+
+/*************************************************************************
+ *        UrlCanonicalizeW     [SHLWAPI.@]
+ *
+ *
+ * MSDN is wrong (at 10/30/01 - go figure). This should support the 
+ * following flags:                                      GLA
+ *    URL_DONT_ESCAPE_EXTRA_INFO    0x02000000
+ *    URL_ESCAPE_SPACES_ONLY        0x04000000
+ *    URL_ESCAPE_PERCENT            0x00001000
+ *    URL_ESCAPE_UNSAFE             0x10000000
+ *    URL_UNESCAPE                  0x10000000
+ *    URL_DONT_SIMPLIFY             0x08000000
+ *    URL_ESCAPE_SEGMENT_ONLY       0x00002000
+ */
+HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, 
+				LPDWORD pcchCanonicalized, DWORD dwFlags)
+{
     HRESULT hr = S_OK;
-
-    LPSTR lpszUrlCpy;
-    INT nLen;
-
-    TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszCanonicalized,
+    DWORD EscapeFlags;
+    LPWSTR lpszUrlCpy, wk1, wk2, mp, root;
+    INT nLen, nByteLen, state;
+
+    TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized,
 	  pcchCanonicalized, dwFlags);
 
-    nLen = strlen(pszUrl);
-    lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nLen + 1);
+    nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
+    lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen);
 
     if (dwFlags & URL_DONT_SIMPLIFY)
-        memcpy(lpszUrlCpy, pszUrl, nLen + 1);
+        memcpy(lpszUrlCpy, pszUrl, nByteLen);
     else {
-        FIXME("Simplify path\n");
-        memcpy(lpszUrlCpy, pszUrl, nLen + 1);
+
+	/*
+	 * state =
+	 *         0   initial  1,3
+	 *         1   have 2[+] alnum  2,3
+	 *         2   have scheme (found :)  4,6,3
+	 *         3   failed (no location)
+	 *         4   have //  5,3
+	 *         5   have 1[+] alnum  6,3
+	 *         6   have location (found /) save root location
+	 */
+
+	wk1 = (LPWSTR)pszUrl;
+	wk2 = lpszUrlCpy;
+	state = 0;
+	while (*wk1) {
+	    switch (state) {
+	    case 0:
+		if (!isalnumW(*wk1)) {state = 3; break;}
+		*wk2++ = *wk1++;
+		if (!isalnumW(*wk1)) {state = 3; break;}
+		*wk2++ = *wk1++;
+		state = 1;
+		break;
+	    case 1:
+		*wk2++ = *wk1;
+		if (*wk1++ == L':') state = 2;
+		break;
+	    case 2:
+		if (*wk1 != L'/') {state = 3; break;}
+		*wk2++ = *wk1++;
+		if (*wk1 != L'/') {state = 6; break;}
+		*wk2++ = *wk1++;
+		state = 4;
+		break;
+	    case 3:
+		strcpyW(wk2, wk1);
+		wk1 += strlenW(wk1);
+		wk2 += strlenW(wk2);
+		break;
+	    case 4:
+		if (!isalnumW(*wk1) && (*wk1 != L'-')) {state = 3; break;}
+		while(isalnumW(*wk1) || (*wk1 == L'-')) *wk2++ = *wk1++;
+		state = 5;
+		break;
+	    case 5:
+		if (*wk1 != L'/') {state = 3; break;}
+		*wk2++ = *wk1++;
+		state = 6;
+		break;
+	    case 6:
+		/* Now at root location, cannot back up any more. */
+		/* "root" will point at the '/' */
+		root = wk2-1;
+		while (*wk1) {
+		    TRACE("wk1=%c\n", (CHAR)*wk1);
+		    mp = strchrW(wk1, L'/');
+		    if (!mp) {
+			strcpyW(wk2, wk1);
+			wk1 += strlenW(wk1);
+			wk2 += strlenW(wk2);
+			continue;
+		    }
+		    nLen = mp - wk1 + 1;
+		    strncpyW(wk2, wk1, nLen);
+		    wk2 += nLen;
+		    wk1 += nLen;
+		    if (*wk1 == L'.') {
+			TRACE("found '/.'\n");
+			if (*(wk1+1) == L'/') {
+			    /* case of /./ -> skip the ./ */
+			    wk1 += 2;
+			}
+			else if (*(wk1+1) == L'.') {
+			    /* found /..  look for next / */
+			    TRACE("found '/..'\n");
+			    if (*(wk1+2) == L'/') {
+				/* case /../ -> need to backup wk2 */
+				TRACE("found '/../'\n");
+				*(wk2-1) = L'\0';  /* set end of string */
+				mp = strrchrW(root, L'/');
+				if (mp && (mp >= root)) {
+				    /* found valid backup point */
+				    wk2 = mp + 1;
+				    wk1 += 3;
+				}
+				else {
+				    /* did not find point, restore '/' */
+				    *(wk2-1) = L'/';
+				}
+			    }
+			}
+		    }
+		}
+		*wk2 = L'\0';
+		break;
+	    default:
+		FIXME("how did we get here - state=%d\n", state);
+		return E_INVALIDARG;
+	    }
+	}
+	*wk2 = L'\0';
+	TRACE("Simplified, orig <%s>, simple <%s>\n",
+	      debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));
     }
 
     if(dwFlags & URL_UNESCAPE)
-        UrlUnescapeA(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
-
-    if(dwFlags & (URL_ESCAPE_UNSAFE | URL_ESCAPE_SPACES_ONLY)) {
-        DWORD EscapeFlags = dwFlags & (URL_ESCAPE_SPACES_ONLY
-				       /* | URL_ESCAPE_PERCENT */);
-	hr = UrlEscapeA(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
+        UrlUnescapeW(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
+
+    if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE | 
+                                 URL_ESCAPE_SPACES_ONLY |
+                                 URL_ESCAPE_PERCENT |
+                                 URL_DONT_ESCAPE_EXTRA_INFO |
+				 URL_ESCAPE_SEGMENT_ONLY ))) {
+	EscapeFlags &= ~URL_ESCAPE_UNSAFE;
+	hr = UrlEscapeW(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
 			EscapeFlags);
-    } else { /* No escapping needed, just copy the string */
-        nLen = strlen(lpszUrlCpy);
+    } else { /* No escaping needed, just copy the string */
+        nLen = lstrlenW(lpszUrlCpy);
 	if(nLen < *pcchCanonicalized)
-	    memcpy(pszCanonicalized, lpszUrlCpy, nLen + 1);
+	    memcpy(pszCanonicalized, lpszUrlCpy, (nLen + 1)*sizeof(WCHAR));
 	else {
 	    hr = E_POINTER;
@@ -124,20 +378,313 @@
     HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
   
+    if (hr == S_OK)
+	TRACE("result %s\n", debugstr_w(pszCanonicalized));
+
     return hr;
 }
 
 /*************************************************************************
- *        UrlCanonicalizeW     [SHLWAPI]
- */
-HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, 
-				LPDWORD pcchCanonicalized, DWORD dwFlags)
-{
-    FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
-	  pszCanonicalized, pcchCanonicalized, dwFlags);
-    return E_NOTIMPL;
-}
-
-/*************************************************************************
- *      UrlEscapeA	[SHLWAPI]
+ *        UrlCombineA     [SHLWAPI.@]
+ *
+ * Uses the W version to do job.
+ */
+HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative,
+			   LPSTR pszCombined, LPDWORD pcchCombined,
+			   DWORD dwFlags)
+{
+    LPWSTR base, relative, combined;
+    DWORD ret, len, len2;
+
+    TRACE("(base %s, Relative %s, Combine size %ld, flags %08lx) using W version\n",
+	  debugstr_a(pszBase),debugstr_a(pszRelative),
+	  *pcchCombined,dwFlags);
+
+    base = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, 
+			      (3*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
+    relative = base + INTERNET_MAX_URL_LENGTH;
+    combined = relative + INTERNET_MAX_URL_LENGTH;
+
+    MultiByteToWideChar(0, 0, pszBase, -1, base, INTERNET_MAX_URL_LENGTH);
+    MultiByteToWideChar(0, 0, pszRelative, -1, relative, INTERNET_MAX_URL_LENGTH);
+    len = INTERNET_MAX_URL_LENGTH;
+
+    ret = UrlCombineW(base, relative, combined, &len, dwFlags);
+    if (ret != S_OK) {
+	HeapFree(GetProcessHeap(), 0, base);
+	return ret;
+    }
+
+    len2 = WideCharToMultiByte(0, 0, combined, len, 0, 0, 0, 0);
+    if (len2 > *pcchCombined) {
+	*pcchCombined = len2;
+	HeapFree(GetProcessHeap(), 0, base);
+	return E_POINTER;
+    }
+    WideCharToMultiByte(0, 0, combined, len+1, pszCombined, *pcchCombined,
+			0, 0);
+    *pcchCombined = len2;
+    HeapFree(GetProcessHeap(), 0, base);
+    return S_OK;
+}
+
+/*************************************************************************
+ *        UrlCombineW     [SHLWAPI.@]
+ */
+HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
+			   LPWSTR pszCombined, LPDWORD pcchCombined,
+			   DWORD dwFlags)
+{
+    UNKNOWN_SHLWAPI_2 base, relative;
+    DWORD myflags, sizeloc = 0;
+    DWORD len, res1, res2, process_case = 0;
+    LPWSTR work, preliminary, mbase, mrelative;
+    WCHAR myfilestr[] = {'f','i','l','e',':','/','/','/','\0'};
+    WCHAR single_slash[] = {'/','\0'};
+    HRESULT ret;
+
+    TRACE("(base %s, Relative %s, Combine size %ld, flags %08lx)\n",
+	  debugstr_w(pszBase),debugstr_w(pszRelative),
+	  *pcchCombined,dwFlags);
+
+    base.size = 24;
+    relative.size = 24;
+
+    /* Get space for duplicates of the input and the output */
+    preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
+			    sizeof(WCHAR));
+    mbase = preliminary + INTERNET_MAX_URL_LENGTH;
+    mrelative = mbase + INTERNET_MAX_URL_LENGTH;
+    *preliminary = L'\0';
+
+    /* Canonicalize the base input prior to looking for the scheme */
+    myflags = dwFlags & (URL_DONT_SIMPLIFY | URL_UNESCAPE);
+    len = INTERNET_MAX_URL_LENGTH;
+    ret = UrlCanonicalizeW(pszBase, mbase, &len, myflags);
+
+    /* Canonicalize the relative input prior to looking for the scheme */
+    len = INTERNET_MAX_URL_LENGTH;
+    ret = UrlCanonicalizeW(pszRelative, mrelative, &len, myflags);
+
+    /* See if the base has a scheme */
+    res1 = SHLWAPI_2(mbase, &base);
+    if (res1) {
+	/* if pszBase has no scheme, then return pszRelative */
+	TRACE("no scheme detected in Base\n");
+	process_case = 1;
+    }
+    else do {
+
+	/* get size of location field (if it exists) */
+	work = (LPWSTR)base.ap2;
+	sizeloc = 0;
+	if (*work++ == L'/') {
+	    if (*work++ == L'/') {
+		/* At this point have start of location and
+		 * it ends at next '/' or end of string.
+		 */
+		while(*work && (*work != L'/')) work++;
+		sizeloc = work - base.ap2;
+	    }
+	}
+
+	/* 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'/');
+	if (work) {
+	    len = work - base.ap2 + 1;
+	    base.sizep2 = len;
+	}
+	/*
+	 * At this point:
+	 *    .ap2      points to location (starting with '//')
+	 *    .sizep2   length of location (above) and rest less the last
+	 *              leaf (if any)
+	 *    sizeloc   length of location (above) up to but not including 
+	 *              the last '/'
+	 */
+
+	res2 = SHLWAPI_2(mrelative, &relative);
+	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);
+	    if (*pszRelative  == L':') {
+		/* case that is either left alone or uses pszBase */
+		if (dwFlags & URL_PLUGGABLE_PROTOCOL) {
+		    process_case = 5;
+		    break;
+		}
+		process_case = 1;
+		break;
+	    }
+	    if (isalnum(*mrelative) && (*(mrelative + 1) == L':')) {
+		/* case that becomes "file:///" */
+		strcpyW(preliminary, myfilestr);
+		process_case = 1;
+		break;
+	    }
+	    if ((*mrelative == L'/') && (*(mrelative+1) == L'/')) {
+		/* pszRelative has location and rest */
+		process_case = 3;
+		break;
+	    }
+	    if (*mrelative == L'/') {
+		/* case where pszRelative is root to location */
+		process_case = 4;
+		break;
+	    }
+	    process_case = (*base.ap2 == L'/') ? 5 : 3;
+	    break;
+	}
+
+	/* handle cases where pszRelative has scheme */
+	if ((base.sizep1 == relative.sizep1) && 
+	    (strncmpW(base.ap1, relative.ap1, base.sizep1) == 0)) {
+
+	    /* since the schemes are the same */
+	    if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+		/* case where pszRelative replaces location and following */
+		process_case = 3;
+		break;
+	    }
+	    if (*relative.ap2 == L'/') {
+		/* case where pszRelative is root to location */
+		process_case = 4;
+		break;
+	    }
+	    /* case where scheme is followed by document path */
+	    process_case = 5;
+	    break;
+	}
+	if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+	    /* case where pszRelative replaces scheme, location,
+	     * and following and handles PLUGGABLE
+	     */
+	    process_case = 2;
+	    break;
+	}
+	process_case = 1;
+	break;
+    } while(FALSE); /* a litte trick to allow easy exit from nested if's */
+
+
+    ret = S_OK;
+    switch (process_case) {
+
+    case 1:  /*
+	      * Return pszRelative appended to what ever is in pszCombined,
+	      * (which may the string "file:///"
+	      */
+	len = strlenW(mrelative) + strlenW(preliminary);
+	if (len+1 > *pcchCombined) {
+	    *pcchCombined = len;
+	    ret = E_POINTER;
+	    break;
+	} 
+	strcatW(preliminary, mrelative);
+	break;
+
+    case 2:  /*
+	      * Same as case 1, but if URL_PLUGGABLE_PROTOCOL was specified
+	      * and pszRelative starts with "//", then append a "/"
+	      */
+	len = strlenW(mrelative) + 1;
+	if (len+1 > *pcchCombined) {
+	    *pcchCombined = len;
+	    ret = E_POINTER;
+	    break;
+	} 
+	strcpyW(preliminary, mrelative);
+	if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
+	    URL_JustLocation(relative.ap2))
+	    strcatW(preliminary, single_slash);
+	break;
+
+    case 3:  /*
+	      * Return the pszBase scheme with pszRelative. Basicly
+	      * keeps the scheme and replaces the domain and following.
+	      */
+	len = base.sizep1 + 1 + relative.sizep2 + 1;
+	if (len+1 > *pcchCombined) {
+	    *pcchCombined = len;
+	    ret = E_POINTER;
+	    break;
+	} 
+	strncpyW(preliminary, base.ap1, base.sizep1 + 1);
+	work = preliminary + base.sizep1 + 1;
+	strcpyW(work, relative.ap2);
+	if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
+	    URL_JustLocation(relative.ap2))
+	    strcatW(work, single_slash);
+	break;
+
+    case 4:  /*
+	      * Return the pszBase scheme and location but everything
+	      * after the location is pszRelative. (Replace document
+	      * from root on.)
+	      */
+	len = base.sizep1 + 1 + sizeloc + relative.sizep2 + 1;
+	if (len+1 > *pcchCombined) {
+	    *pcchCombined = len;
+	    ret = E_POINTER;
+	    break;
+	} 
+	strncpyW(preliminary, base.ap1, base.sizep1+1+sizeloc);
+	work = preliminary + base.sizep1 + 1 + sizeloc;
+	if (dwFlags & URL_PLUGGABLE_PROTOCOL)
+	    *(work++) = L'/';
+	strcpyW(work, relative.ap2);
+	break;
+
+    case 5:  /*
+	      * Return the pszBase without its document (if any) and 
+	      * append pszRelative after its scheme.
+	      */
+	len = base.sizep1 + 1 + base.sizep2 + relative.sizep2;
+	if (len+1 > *pcchCombined) {
+	    *pcchCombined = len;
+	    ret = E_POINTER;
+	    break;
+	} 
+	strncpyW(preliminary, base.ap1, base.sizep1+1+base.sizep2);
+	work = preliminary + base.sizep1+1+base.sizep2 - 1;
+	if (*work++ != L'/')
+	    *(work++) = L'/';
+	strcpyW(work, relative.ap2);
+	break;
+
+    default:
+	FIXME("How did we get here????? process_case=%ld\n", process_case);
+	ret = E_INVALIDARG;
+    }
+
+    if (ret == S_OK) {
+	/*
+	 * Now that the combining is done, process the escape options if 
+	 * necessary, otherwise just copy the string.
+	 */
+	myflags = dwFlags & (URL_ESCAPE_PERCENT |
+			     URL_ESCAPE_SPACES_ONLY |
+                             URL_DONT_ESCAPE_EXTRA_INFO |
+			     URL_ESCAPE_SEGMENT_ONLY);
+	if (myflags)
+	    ret = UrlEscapeW(preliminary, pszCombined,
+			     pcchCombined, myflags);
+	else {
+	    len = (strlenW(preliminary) + 1) * sizeof(WCHAR);
+	    memcpy(pszCombined, preliminary, len);
+	    *pcchCombined = strlenW(preliminary);
+	}
+	TRACE("return-%ld len=%ld, %s\n",
+	      process_case, *pcchCombined, debugstr_w(pszCombined));
+    }
+    HeapFree(GetProcessHeap(), 0, preliminary);
+    return ret;
+}
+
+/*************************************************************************
+ *      UrlEscapeA	[SHLWAPI.@]
  *
  * Converts unsafe characters into their escape sequences.
@@ -156,13 +703,13 @@
  *
  * BUGS:
- *
- * None of the URL_ define values are documented, so they were
- * determined by trial and error.  MSDN mentions URL_ESCAPE_PERCENT
- * but I can't find a value that does this under win2000.
- * URL_DONT_ESCAPE_EXTRA_INFO appears to be the default which is what
- * we assume here.  URL_ESCAPE_SEGMENT_ONLY is not implemented
- * (value??).  A value of 0x2000 for dwFlags seems to escape
- * '/'s too - this is neither documented on MSDN nor implemented here.
- * For character values that are converted see URL_NeedEscape.
+ *  Have now implemented the following flags:
+ *     URL_ESCAPE_SPACES_ONLY
+ *     URL_DONT_ESCAPE_EXTRA_INFO
+ *     URL_ESCAPE_SEGMENT_ONLY
+ *     URL_ESCAPE_PERCENT
+ *  Initial testing seems to indicate that this is now working like
+ *  native shlwapi version 5. Note that these functions did not work
+ *  well (or at all) in shlwapi version 4.
+ *
  */
 HRESULT WINAPI UrlEscapeA(
@@ -174,5 +721,5 @@
     LPCSTR src;
     DWORD needed = 0, ret;
-    BOOL stop_escapping = FALSE;
+    BOOL stop_escaping = FALSE;
     char next[3], *dst = pszEscaped;
     char hex[] = "0123456789ABCDEF";
@@ -182,13 +729,29 @@
 	  pcchEscaped, dwFlags);
 
-    if(dwFlags & ~URL_ESCAPE_SPACES_ONLY)
+    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 the assume DONT_ESCAPE_EXTRA_INFO */
+	dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
+
     for(src = pszUrl; *src; src++) {
-        if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
+        if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
+	   (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
 	   (*src == '#' || *src == '?'))
-	    stop_escapping = TRUE;
-
-	if(URL_NeedEscape(*src, dwFlags) && stop_escapping == FALSE) {
+	    stop_escaping = TRUE;
+
+	if(URL_NeedEscapeA(*src, dwFlags) && stop_escaping == FALSE) {
+	    /* TRACE("escaping %c\n", *src); */
 	    next[0] = '%';
 	    next[1] = hex[(*src >> 4) & 0xf];
@@ -196,4 +759,5 @@
 	    len = 3;
 	} else {
+	    /* TRACE("passing %c\n", *src); */
 	    next[0] = *src;
 	    len = 1;
@@ -219,5 +783,7 @@
 
 /*************************************************************************
- *      UrlEscapeW	[SHLWAPI]
+ *      UrlEscapeW	[SHLWAPI.@]
+ *
+ * See UrlEscapeA for list of assumptions, bugs, and FIXMEs
  */
 HRESULT WINAPI UrlEscapeW(
@@ -227,12 +793,86 @@
 	DWORD dwFlags)
 {
-    FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
-	  pszEscaped, pcchEscaped, dwFlags);
-    return E_NOTIMPL;
-}
-
-
-/*************************************************************************
- *      UrlUnescapeA	[SHLWAPI]
+    LPCWSTR src;
+    DWORD needed = 0, ret;
+    BOOL stop_escaping = FALSE;
+    WCHAR next[5], *dst = pszEscaped;
+    CHAR hex[] = "0123456789ABCDEF";
+    INT len;
+
+    TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszEscaped,
+	  pcchEscaped, dwFlags);
+
+    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 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] = hex[(*src >> 12) & 0xf];
+	     *   next[2] = hex[(*src >> 8) & 0xf];
+	     *   next[3] = hex[(*src >> 4) & 0xf];
+	     *   next[4] = hex[*src & 0xf];
+	     *   len = 5;
+	     */
+	    next[1] = hex[(*src >> 4) & 0xf];
+	    next[2] = hex[*src & 0xf];
+	    len = 3;
+	} else {
+	    /* TRACE("passing %c\n", *src); */
+	    next[0] = *src;
+	    len = 1;
+	}
+
+	if(needed + len <= *pcchEscaped) {
+	    memcpy(dst, next, len*sizeof(WCHAR));
+	    dst += len;
+	}
+	needed += len;
+    }
+
+    if(needed < *pcchEscaped) {
+        *dst = L'\0';
+	ret = S_OK;
+    } else {
+        needed++; /* add one for the '\0' */
+	ret = E_POINTER;
+    }
+    *pcchEscaped = needed;
+    return ret;
+}
+
+
+/*************************************************************************
+ *      UrlUnescapeA	[SHLWAPI.@]
  *
  * Converts escape sequences back to ordinary characters.
@@ -260,7 +900,7 @@
     HRESULT ret;
     DWORD needed;
-    BOOL stop_unescapping = FALSE;
-
-    TRACE("(%s, %p, %p, %08lx): stub\n", debugstr_a(pszUrl), pszUnescaped,
+    BOOL stop_unescaping = FALSE;
+
+    TRACE("(%s, %p, %p, 0x%08lx)\n", debugstr_a(pszUrl), pszUnescaped,
 	  pcchUnescaped, dwFlags);
 
@@ -273,8 +913,8 @@
         if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
 	   (*src == '#' || *src == '?')) {
-	    stop_unescapping = TRUE;
+	    stop_unescaping = TRUE;
 	    next = *src;
 	} else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
-		  && stop_unescapping == FALSE) {
+		  && stop_unescaping == FALSE) {
 	    INT ih;
 	    char buf[3];
@@ -301,9 +941,16 @@
         *pcchUnescaped = needed;
 
+    if (ret == S_OK) {
+	TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ? 
+	      debugstr_a(pszUrl) : debugstr_a(pszUnescaped));
+    }
+
     return ret;
 }
 
 /*************************************************************************
- *      UrlUnescapeW	[SHLWAPI]
+ *      UrlUnescapeW	[SHLWAPI.@]
+ *
+ * See UrlUnescapeA for list of assumptions, bugs, and FIXMEs
  */
 HRESULT WINAPI UrlUnescapeW(
@@ -313,11 +960,167 @@
 	DWORD dwFlags)
 {
-    FIXME("(%s, %p, %p, %08lx): stub\n", debugstr_w(pszUrl), pszUnescaped,
+    WCHAR *dst, next;
+    LPCWSTR src;
+    HRESULT ret;
+    DWORD needed;
+    BOOL stop_unescaping = FALSE;
+
+    TRACE("(%s, %p, %p, 0x%08lx)\n", debugstr_w(pszUrl), pszUnescaped,
 	  pcchUnescaped, dwFlags);
-    return E_NOTIMPL;
-}
-
-/*************************************************************************
- *      HashData	[SHLWAPI]
+
+    if(dwFlags & URL_UNESCAPE_INPLACE)
+        dst = (WCHAR*)pszUrl;
+    else
+        dst = pszUnescaped;
+
+    for(src = pszUrl, needed = 0; *src; src++, needed++) {
+        if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
+	   (*src == L'#' || *src == L'?')) {
+	    stop_unescaping = TRUE;
+	    next = *src;
+	} 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);
+	    next = (WCHAR) ih;
+	    src += 2; /* Advance to end of escape */
+	} else
+	    next = *src;
+
+	if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
+	    *dst++ = next;
+    }
+
+    if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
+        *dst = L'\0';
+	ret = S_OK;
+    } else {
+        needed++; /* add one for the '\0' */
+	ret = E_POINTER;
+    }
+    if(!(dwFlags & URL_UNESCAPE_INPLACE))
+        *pcchUnescaped = needed;
+
+    if (ret == S_OK) {
+	TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ? 
+	      debugstr_w(pszUrl) : debugstr_w(pszUnescaped));
+    }
+
+    return ret;
+}
+
+/*************************************************************************
+ *      UrlGetLocationA 	[SHLWAPI.@]
+ *
+ * Bugs/Features:
+ *  MSDN (as of 2001-11-01) says that: 
+ *         "The location is the segment of the URL starting with a ? 
+ *          or # character." 
+ *     Neither V4 nor V5 of shlwapi.dll implement the '?' and always return
+ *     a NULL.
+ *  MSDN further states that:
+ *         "If a file URL has a query string, ther returned string 
+ *          the query string."
+ *     In all test cases if the scheme starts with "fi" then a NULL is 
+ *     returned. V5 gives the following results:
+ *       NULL     file://aa/b/cd#hohoh
+ *       #hohoh   http://aa/b/cd#hohoh
+ *       NULL     fi://aa/b/cd#hohoh
+ *       #hohoh   ff://aa/b/cd#hohoh
+ */
+LPCSTR WINAPI UrlGetLocationA(
+	LPCSTR pszUrl)
+{
+    UNKNOWN_SHLWAPI_1 base;
+    DWORD res1;
+
+    base.size = 24;
+    res1 = SHLWAPI_1(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;
+
+    /* Look for '#' and return its addr */
+    return strchr(base.ap2, '#');
+}
+
+/*************************************************************************
+ *      UrlGetLocationW 	[SHLWAPI.@]
+ *
+ * See UrlGetLocationA for list of assumptions, bugs, and FIXMEs
+ */
+LPCWSTR WINAPI UrlGetLocationW(
+	LPCWSTR pszUrl)
+{
+    UNKNOWN_SHLWAPI_2 base;
+    DWORD res1;
+
+    base.size = 24;
+    res1 = SHLWAPI_2(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;
+
+    /* Look for '#' and return its addr */
+    return strchrW(base.ap2, L'#');
+}
+
+/*************************************************************************
+ *      UrlCompareA	[SHLWAPI.@]
+ */
+INT WINAPI UrlCompareA(
+	LPCSTR pszUrl1,
+	LPCSTR pszUrl2,
+	BOOL fIgnoreSlash)
+{
+    INT ret, len, len1, len2;
+
+    if (!fIgnoreSlash)
+	return strcmp(pszUrl1, pszUrl2);
+    len1 = strlen(pszUrl1);
+    if (pszUrl1[len1-1] == L'/') len1--;
+    len2 = strlen(pszUrl2);
+    if (pszUrl2[len2-1] == L'/') len2--;
+    if (len1 == len2)
+	return strncmp(pszUrl1, pszUrl2, len1);
+    len = min(len1, len2);
+    ret = strncmp(pszUrl1, pszUrl2, len);
+    if (ret) return ret;
+    if (len1 > len2) return 1;
+    return -1;
+}
+
+/*************************************************************************
+ *      UrlCompareW	[SHLWAPI.@]
+ */
+INT WINAPI UrlCompareW(
+	LPCWSTR pszUrl1,
+	LPCWSTR pszUrl2,
+	BOOL fIgnoreSlash)
+{
+    INT ret, len, len1, len2;
+
+    if (!fIgnoreSlash)
+	return strcmpW(pszUrl1, pszUrl2);
+    len1 = strlenW(pszUrl1);
+    if (pszUrl1[len1-1] == L'/') len1--;
+    len2 = strlenW(pszUrl2);
+    if (pszUrl2[len2-1] == L'/') len2--;
+    if (len1 == len2)
+	return strncmpW(pszUrl1, pszUrl2, len1);
+    len = min(len1, len2);
+    ret = strncmpW(pszUrl1, pszUrl2, len);
+    if (ret) return ret;
+    if (len1 > len2) return 1;
+    return -1;
+}
+
+/*************************************************************************
+ *      HashData	[SHLWAPI.@]
  *
  * Hash an input block into a variable sized digest.
@@ -352,5 +1155,5 @@
 
 /*************************************************************************
- *      UrlHashA	[SHLWAPI]
+ *      UrlHashA	[SHLWAPI.@]
  *
  * Hash an ASCII URL.
@@ -366,12 +1169,570 @@
 
 /*************************************************************************
+ *      UrlApplySchemeA	[SHLWAPI.@]
+ */
+HRESULT WINAPI UrlApplySchemeA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
+{
+    LPWSTR in, out;
+    DWORD ret, len, len2;
+
+    TRACE("(in %s, out size %ld, flags %08lx) using W version\n",
+	  debugstr_a(pszIn), *pcchOut, dwFlags);
+
+    in = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, 
+			      (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
+    out = in + INTERNET_MAX_URL_LENGTH;
+
+    MultiByteToWideChar(0, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH);
+    len = INTERNET_MAX_URL_LENGTH;
+
+    ret = UrlApplySchemeW(in, out, &len, dwFlags);
+    if ((ret != S_OK) && (ret != S_FALSE)) {
+	HeapFree(GetProcessHeap(), 0, in);
+	return ret;
+    }
+
+    len2 = WideCharToMultiByte(0, 0, out, len+1, 0, 0, 0, 0);
+    if (len2 > *pcchOut) {
+	*pcchOut = len2;
+	HeapFree(GetProcessHeap(), 0, in);
+	return E_POINTER;
+    }
+    WideCharToMultiByte(0, 0, out, len+1, pszOut, *pcchOut, 0, 0);
+    *pcchOut = len2;
+    HeapFree(GetProcessHeap(), 0, in);
+    return ret;
+}
+
+HRESULT URL_GuessScheme(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
+{
+    HKEY newkey;
+    BOOL j;
+    INT index, i;
+    DWORD value_len, data_len, dwType;
+    WCHAR reg_path[MAX_PATH];
+    WCHAR value[MAX_PATH], data[MAX_PATH];
+    WCHAR Wxx, Wyy;
+
+    MultiByteToWideChar(0, 0,
+	      "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes",
+			-1, reg_path, MAX_PATH);
+    RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey);
+    index = 0;
+    while(value_len = data_len = MAX_PATH,
+	  RegEnumValueW(newkey, index, value, &value_len,
+			0, &dwType, (LPVOID)data, &data_len) == 0) {
+	TRACE("guess %d %s is %s\n",
+	      index, debugstr_w(value), debugstr_w(data));
+
+	j = FALSE;
+	for(i=0; i<value_len; i++) {
+	    Wxx = pszIn[i];
+	    Wyy = value[i];
+	    /* remember that TRUE is not-equal */
+	    j = ChrCmpIW(Wxx, Wyy);
+	    if (j) break;
+	}
+	if ((i == value_len) && !j) {
+	    if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
+		*pcchOut = strlenW(data) + strlenW(pszIn) + 1;
+		RegCloseKey(newkey);
+		return E_POINTER;
+	    }
+	    strcpyW(pszOut, data);
+	    strcatW(pszOut, pszIn);
+	    *pcchOut = strlenW(pszOut);
+	    TRACE("matched and set to %s\n", debugstr_w(pszOut));
+	    RegCloseKey(newkey);
+	    return S_OK;
+	}
+	index++;
+    }
+    RegCloseKey(newkey);
+    return -1;
+}
+
+HRESULT URL_ApplyDefault(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
+{
+    HKEY newkey;
+    DWORD data_len, dwType;
+    WCHAR reg_path[MAX_PATH];
+    WCHAR value[MAX_PATH], data[MAX_PATH];
+
+    /* get and prepend default */
+    MultiByteToWideChar(0, 0,
+	 "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\DefaultPrefix",
+			-1, reg_path, MAX_PATH);
+    RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey);
+    data_len = MAX_PATH;
+    value[0] = L'@';
+    value[1] = L'\0';
+    RegQueryValueExW(newkey, value, 0, &dwType, (LPBYTE)data, &data_len);
+    RegCloseKey(newkey);
+    if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
+	*pcchOut = strlenW(data) + strlenW(pszIn) + 1;
+	return E_POINTER;
+    }
+    strcpyW(pszOut, data);
+    strcatW(pszOut, pszIn);
+    *pcchOut = strlenW(pszOut);
+    TRACE("used default %s\n", debugstr_w(pszOut));
+    return S_OK;
+}
+
+/*************************************************************************
  *      UrlApplySchemeW	[SHLWAPI.@]
  */
 HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
 {
-    HRESULT err = NOERROR;
-    FIXME("(%s %p %p %08lx): stub !\n", debugstr_w(pszIn), pszOut, pcchOut, dwFlags);
-    lstrcpyW(pszOut, pszIn);
-    *pcchOut = (err != E_POINTER) ? lstrlenW(pszOut) : 0;
-    return err;
-}
+    UNKNOWN_SHLWAPI_2 in_scheme;
+    DWORD res1;
+    HRESULT ret;
+
+    TRACE("(in %s, out size %ld, flags %08lx)\n",
+	  debugstr_w(pszIn), *pcchOut, dwFlags);
+
+    if (dwFlags & URL_APPLY_GUESSFILE) {
+	FIXME("(%s %p %p(%ld) 0x%08lx): stub URL_APPLY_GUESSFILE not implemented\n", 
+	      debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwFlags);
+	strcpyW(pszOut, pszIn);
+	*pcchOut = strlenW(pszOut);
+	return S_FALSE;
+    }
+
+    in_scheme.size = 24;
+    /* See if the base has a scheme */
+    res1 = SHLWAPI_2(pszIn, &in_scheme);
+    if (res1) {
+	/* no scheme in input, need to see if we need to guess */
+	if (dwFlags & URL_APPLY_GUESSSCHEME) {
+	    if ((ret = URL_GuessScheme(pszIn, pszOut, pcchOut)) != -1) 
+		return ret;
+	}
+    }
+    else {
+	/* we have a scheme, see if valid (known scheme) */
+	if (in_scheme.fcncde) {
+	    /* have valid scheme, so just copy and exit */
+	    if (strlenW(pszIn) + 1 > *pcchOut) {
+		*pcchOut = strlenW(pszIn) + 1;
+		return E_POINTER;
+	    }
+	    strcpyW(pszOut, pszIn);
+	    *pcchOut = strlenW(pszOut);
+	    TRACE("valid scheme, returing copy\n");
+	    return S_OK;
+	}
+    }
+
+    /* If we are here, then either invalid scheme, 
+     * or no scheme and can't/failed guess.
+     */
+    if ( ( ((res1 == 0) && (dwFlags & URL_APPLY_FORCEAPPLY)) ||
+	   ((res1 != 0)) ) &&
+	 (dwFlags & URL_APPLY_DEFAULT)) {
+	/* find and apply default scheme */
+	return URL_ApplyDefault(pszIn, pszOut, pcchOut);
+    }
+
+    /* just copy and give proper return code */
+    if (strlenW(pszIn) + 1 > *pcchOut) {
+	*pcchOut = strlenW(pszIn) + 1;
+	return E_POINTER;
+    }
+    strcpyW(pszOut, pszIn);
+    *pcchOut = strlenW(pszOut);
+    TRACE("returing copy, left alone\n");
+    return S_FALSE;
+}
+
+/*************************************************************************
+ *      UrlIsA  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
+{
+    UNKNOWN_SHLWAPI_1 base;
+    DWORD res1;
+
+    switch (Urlis) {
+
+    case URLIS_OPAQUE:
+	base.size = 24;
+	res1 = SHLWAPI_1(pszUrl, &base);
+	if (res1) return FALSE;  /* invalid scheme */
+	if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
+	    /* has scheme followed by 2 '/' */
+	    return FALSE;
+	return TRUE;
+
+    case URLIS_URL:
+    case URLIS_NOHISTORY:
+    case URLIS_FILEURL:
+    case URLIS_APPLIABLE:
+    case URLIS_DIRECTORY:
+    case URLIS_HASQUERY:
+    default:
+	FIXME("(%s %d): stub\n", debugstr_a(pszUrl), Urlis);
+    }
+    return FALSE;
+}
+
+/*************************************************************************
+ *      UrlIsW  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
+{
+    UNKNOWN_SHLWAPI_2 base;
+    DWORD res1;
+
+    switch (Urlis) {
+
+    case URLIS_OPAQUE:
+	base.size = 24;
+	res1 = SHLWAPI_2(pszUrl, &base);
+	if (res1) return FALSE;  /* invalid scheme */
+	if ((*base.ap2 == L'/') && (*(base.ap2+1) == L'/'))
+	    /* has scheme followed by 2 '/' */
+	    return FALSE;
+	return TRUE;
+
+    case URLIS_URL:
+    case URLIS_NOHISTORY:
+    case URLIS_FILEURL:
+    case URLIS_APPLIABLE:
+    case URLIS_DIRECTORY:
+    case URLIS_HASQUERY:
+    default:
+	FIXME("(%s %d): stub\n", debugstr_w(pszUrl), Urlis);
+    }
+    return FALSE;
+}
+
+/*************************************************************************
+ *      UrlIsNoHistoryA  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsNoHistoryA(LPCSTR pszUrl)
+{
+    return UrlIsA(pszUrl, URLIS_NOHISTORY);
+}
+
+/*************************************************************************
+ *      UrlIsNoHistoryW  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsNoHistoryW(LPCWSTR pszUrl)
+{
+    return UrlIsW(pszUrl, URLIS_NOHISTORY);
+}
+
+/*************************************************************************
+ *      UrlIsOpaqueA  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsOpaqueA(LPCSTR pszUrl)
+{
+    return UrlIsA(pszUrl, URLIS_OPAQUE);
+}
+
+/*************************************************************************
+ *      UrlIsOpaqueW  	[SHLWAPI.@]
+ */
+BOOL WINAPI UrlIsOpaqueW(LPCWSTR pszUrl)
+{
+    return UrlIsW(pszUrl, URLIS_OPAQUE);
+}
+
+/*************************************************************************
+ *  Scans for characters of type "type" and when not matching found,
+ *  returns pointer to it and length in size.
+ *
+ * Characters tested based on RFC 1738
+ */
+LPCWSTR  URL_ScanID(LPCWSTR start, LPDWORD size, WINE_URL_SCAN_TYPE type)
+{
+    static DWORD alwayszero = 0;
+    BOOL cont = TRUE;
+
+    *size = 0;
+
+    switch(type){
+
+    case SCHEME:
+	while (cont) {
+	    if ( (islowerW(*start) && isalphaW(*start)) ||
+		 isdigitW(*start) ||
+		 (*start == L'+') ||
+		 (*start == L'-') ||
+		 (*start == L'.')) {
+		start++;
+		(*size)++;
+	    }
+	    else
+		cont = FALSE;
+	}
+        break;
+
+    case USERPASS:
+	while (cont) {
+	    if ( isalphaW(*start) ||
+		 isdigitW(*start) ||
+		 /* user/password only characters */
+		 (*start == L';') ||
+		 (*start == L'?') ||
+		 (*start == L'&') ||
+		 (*start == L'=') ||
+		 /* *extra* characters */
+		 (*start == L'!') ||
+		 (*start == L'*') ||
+		 (*start == L'\'') ||
+		 (*start == L'(') ||
+		 (*start == L')') ||
+		 (*start == L',') ||
+		 /* *safe* characters */
+		 (*start == L'$') ||
+		 (*start == L'_') ||
+		 (*start == L'+') ||
+		 (*start == L'-') ||
+		 (*start == L'.')) {
+		start++;
+		(*size)++;
+	    } else if (*start == L'%') {
+		if (isxdigitW(*(start+1)) && 
+		    isxdigitW(*(start+2))) {
+		    start += 3;
+		    *size += 3;
+		} else
+		    cont = FALSE;
+	    } else
+		cont = FALSE;
+	}
+	break;
+
+    case PORT:
+	while (cont) {
+	    if (isdigitW(*start)) {
+		start++;
+		(*size)++;
+	    }
+	    else
+		cont = FALSE;
+	}
+	break;
+
+    case HOST:
+	while (cont) {
+	    if (isalnumW(*start) ||
+		(*start == L'-') ||
+		(*start == L'.') ) {
+		start++;
+		(*size)++;
+	    }
+	    else
+		cont = FALSE;
+	}
+	break;
+    default:
+	FIXME("unknown type %d\n", type);
+	return (LPWSTR)&alwayszero;
+    }
+    /* TRACE("scanned %ld characters next char %p<%c>\n",
+     *size, start, *start); */
+    return start;
+}
+
+/*************************************************************************
+ *  Attempt to parse URL into pieces.
+ */
+LONG URL_ParseUrl(LPCWSTR pszUrl, WINE_PARSE_URL *pl)
+{
+    LPCWSTR work;
+
+    memset(pl, 0, sizeof(WINE_PARSE_URL));
+    pl->pScheme = pszUrl;
+    work = URL_ScanID(pl->pScheme, &pl->szScheme, SCHEME);
+#ifdef __WIN32OS2__
+    if (!*work || (*work != L':')) goto __ERROR;
+    work++;
+    if ((*work != L'/') || (*(work+1) != L'/')) goto __ERROR;
+#else
+    if (!*work || (*work != L':')) goto ERROR1;
+    work++;
+    if ((*work != L'/') || (*(work+1) != L'/')) goto ERROR;
+#endif
+    pl->pUserName = work + 2;
+    work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS);
+    if (*work == L':' ) {
+	/* parse password */
+	work++;
+	pl->pPassword = work;
+	work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS);
+	if (*work != L'@') {
+	    /* what we just parsed must be the hostname and port
+	     * so reset pointers and clear then let it parse */
+	    pl->szUserName = pl->szPassword = 0;
+	    work = pl->pUserName - 1;
+	    pl->pUserName = pl->pPassword = 0;
+	}
+    } else if (*work == L'@') {
+	/* no password */
+	pl->szPassword = 0;
+	pl->pPassword = 0;
+    } else if (!*work || (*work == L'/') || (*work == L'.')) {
+	/* what was parsed was hostname, so reset pointers and let it parse */
+	pl->szUserName = pl->szPassword = 0;
+	work = pl->pUserName - 1;
+	pl->pUserName = pl->pPassword = 0;
+#ifdef __WIN32OS2__
+    } else goto __ERROR;
+#else
+    } else goto ERROR1;
+#endif
+    /* now start parsing hostname or hostnumber */
+    work++;
+    pl->pHostName = work;
+    work = URL_ScanID(pl->pHostName, &pl->szHostName, HOST);
+    if (*work == L':') {
+	/* parse port */
+	work++;
+	pl->pPort = work;
+	work = URL_ScanID(pl->pPort, &pl->szPort, PORT);
+    }
+    if (*work == L'/') {
+	/* see if query string */
+	pl->pQuery = strchrW(work, L'?');
+	if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery);
+    }
+    TRACE("parse successful: scheme=%p(%ld), user=%p(%ld), pass=%p(%ld), host=%p(%ld), port=%p(%ld), query=%p(%ld)\n",
+	  pl->pScheme, pl->szScheme,
+	  pl->pUserName, pl->szUserName,
+	  pl->pPassword, pl->szPassword,
+	  pl->pHostName, pl->szHostName,
+	  pl->pPort, pl->szPort,
+	  pl->pQuery, pl->szQuery);
+    return S_OK;
+#ifdef __WIN32OS2__
+  __ERROR:
+#else
+  ERROR:
+#endif
+    FIXME("failed to parse %s\n", debugstr_w(pszUrl));
+    return E_INVALIDARG;
+}
+
+/*************************************************************************
+ *      UrlGetPartA  	[SHLWAPI.@]
+ */
+HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, 
+			   DWORD dwPart, DWORD dwFlags)
+{
+    LPWSTR in, out;
+    DWORD ret, len, len2;
+
+    in = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, 
+			      (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
+    out = in + INTERNET_MAX_URL_LENGTH;
+
+    MultiByteToWideChar(0, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH);
+
+    len = INTERNET_MAX_URL_LENGTH;
+    ret = UrlGetPartW(in, out, &len, dwPart, dwFlags);
+
+    if (ret != S_OK) {
+	HeapFree(GetProcessHeap(), 0, in);
+	return ret;
+    }
+
+    len2 = WideCharToMultiByte(0, 0, out, len, 0, 0, 0, 0);
+    if (len2 > *pcchOut) {
+	*pcchOut = len2;
+	HeapFree(GetProcessHeap(), 0, in);
+	return E_POINTER;
+    }
+    WideCharToMultiByte(0, 0, out, len+1, pszOut, *pcchOut, 0, 0);
+    *pcchOut = len2;
+    HeapFree(GetProcessHeap(), 0, in);
+    return S_OK;
+}
+
+/*************************************************************************
+ *      UrlGetPartW  	[SHLWAPI.@]
+ */
+HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, 
+			   DWORD dwPart, DWORD dwFlags)
+{
+    WINE_PARSE_URL pl;
+    HRESULT ret;
+    DWORD size, schsize;
+    LPCWSTR addr, schaddr;
+    LPWSTR work;
+
+    TRACE("(%s %p %p(%ld) %08lx %08lx)\n",
+	  debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags);
+
+    ret = URL_ParseUrl(pszIn, &pl);
+    if (!ret) {
+	schaddr = pl.pScheme;
+	schsize = pl.szScheme;
+
+	switch (dwPart) {
+	case URL_PART_SCHEME:
+	    if (!pl.szScheme) return E_INVALIDARG;
+	    addr = pl.pScheme;
+	    size = pl.szScheme;
+	    break;
+
+	case URL_PART_HOSTNAME:
+	    if (!pl.szHostName) return E_INVALIDARG;
+	    addr = pl.pHostName;
+	    size = pl.szHostName;
+	    break;
+
+	case URL_PART_USERNAME:
+	    if (!pl.szUserName) return E_INVALIDARG;
+	    addr = pl.pUserName;
+	    size = pl.szUserName;
+	    break;
+
+	case URL_PART_PASSWORD:
+	    if (!pl.szPassword) return E_INVALIDARG;
+	    addr = pl.pPassword;
+	    size = pl.szPassword;
+	    break;
+
+	case URL_PART_PORT:
+	    if (!pl.szPort) return E_INVALIDARG;
+	    addr = pl.pPort;
+	    size = pl.szPort;
+	    break;
+
+	case URL_PART_QUERY:
+	    if (!pl.szQuery) return E_INVALIDARG;
+	    addr = pl.pQuery;
+	    size = pl.szQuery;
+	    break;
+
+	default:
+	    return E_INVALIDARG;
+	}
+
+	if (dwFlags == URL_PARTFLAG_KEEPSCHEME) {
+	    if (*pcchOut < size + schsize + 2) {
+		*pcchOut = size + schsize + 2;
+		return E_POINTER;
+	    }
+	    strncpyW(pszOut, schaddr, schsize);
+	    work = pszOut + schsize;
+	    *work = L':';
+	    strncpyW(work+1, addr, size);
+	    *pcchOut = size + schsize + 1;
+	    work += (size + 1);
+	    *work = L'\0';
+	}
+	else {
+	    if (*pcchOut < size + 1) {*pcchOut = size+1; return E_POINTER;}
+	    strncpyW(pszOut, addr, size);
+	    *pcchOut = size;
+	    work = pszOut + size;
+	    *work = L'\0';
+	}
+	TRACE("len=%ld %s\n", *pcchOut, debugstr_w(pszOut));
+    }
+    return ret;
+}
Index: trunk/src/shlwapi/url_odin.cpp
===================================================================
--- trunk/src/shlwapi/url_odin.cpp	(revision 7815)
+++ trunk/src/shlwapi/url_odin.cpp	(revision 7820)
@@ -1,3 +1,3 @@
-/* $Id: url_odin.cpp,v 1.3 2001-08-31 19:56:34 phaller Exp $ */
+/* $Id: url_odin.cpp,v 1.4 2002-02-06 20:18:30 sandervl Exp $ */
 
 /*
@@ -41,260 +41,4 @@
 
 ODINDEBUGCHANNEL(SHLWAPI-URL)
-
-
-/*****************************************************************************
- * Defines                                                                   *
- *****************************************************************************/
-
-
-typedef struct tagURLSCHEME
-{
-  LPSTR pszName;       /* such as http://                    */
-  BOOL  flagOpaque;    /* has a double-slash '//             */
-  BOOL  flagNoHistory; /* usually not in history of browsers */
-  DWORD dwType;        /* URL type                           */
-
-} URLSCHEME, *PURLSCHEME;
-
-
-typedef enum tagURLIS
-{
-  URLIS_APPLIABLE,   /* Attempt to determine a valid scheme for the URL. */
-  URLIS_DIRECTORY,   /* Does the URL string end with a directory?        */
-  URLIS_FILEURL,     /* Is the URL a file URL?                           */
-  URLIS_HASQUERY,    /* Does the URL have an appended query string?      */
-  URLIS_NOHISTORY,   /* Is the URL a "No History" URL?                   */
-  URLIS_OPAQUE,      /* Is the URL opaque?                               */
-  URLIS_URL          /* Is the URL valid?                                */
-} URLIS;
-
-
-static URLSCHEME arrUrlSchemes[] =
-{ /* scheme     opaque hist   type */
-  {"http://",   FALSE, FALSE, 0},
-  {"https://",  FALSE, FALSE, 0},
-  {"shttp://",  FALSE, FALSE, 0},
-  {"file://",   FALSE, FALSE, 0},
-  {"ftp://",    FALSE, FALSE, 0},
-  {"telnet://", FALSE, TRUE,  0},
-  {"news://",   FALSE, TRUE,  0},
-  {"snews://",  FALSE, TRUE,  0},
-  {"mailto:",   TRUE,  TRUE,  0},
-  {"gopher://", FALSE, FALSE, 0},
-  {"wais://",   FALSE, FALSE, 0},
-};
-
-
-
-
-/*****************************************************************************
- * Name      : UrlApplyScheme
- * Purpose   : Takes a URL string, determines a scheme for it, and returns a
- *             string with an appropriate prefix.
- * Parameters: pszIn   [in]     A NULL-terminated URL string.
- *             pszOut  [out]    A buffer to receive a NULL-terminated string,
- *                              set to the URL specified by pszIn, converted
- *                              to the standard scheme://URL_string format.
- *             pcchOut [in/out] Address of a value set to the number of
- *                              characters in the pszOut buffer. When the
- *                              function returns, the value depends on whether
- *                              the function is successful or returns
- *                              E_POINTER. For other return values, the value
- *                              of this parameter is meaningless.
- *             dwFlags [in]     Flags that specify how to determine the
- *                              scheme. The following flags can be combined.
- *                              URL_APPLY_DEFAULT
- *                                Apply the default scheme if UrlApplyScheme
- *                                can't determine one. The default prefix is
- *                                stored in the registry but is typically "http".
- *                              URL_APPLY_GUESSSCHEME
- *                                Attempt to determine the scheme by examining
- *                                pszIn.
- *                              URL_APPLY_GUESSFILE
- *                                Attempt to determine a file URL from pszIn.
- *                              URL_APPLY_FORCEAPPLY
- *                                Force UrlApplyScheme to determine a scheme
- *                                for pszIn.
- * Variables :
- * Result    : S_OK      A scheme was determined. pszOut points to a string
- *                       containing the URL with the scheme's prefix. The value
- *                       of pcchOut is set to the number of characters in the
- *                       string, not counting the terminating NULL character.
- *             S_FALSE   There were no errors, but no prefix was prepended.
- *             E_POINTER The buffer was too small. The value of pcchOut is
- *                       set to the minimum number of characters that the
- *                       buffer must be able to contain, including the
- *                       terminating NULL character.
- *             Other errors - A standard OLE error value is returned.
- * Remark    : If the URL has a valid scheme, the string will not be modified.
- *             However, almost any combination of two or more characters
- *             followed by a colon will be parsed as a scheme. Valid
- *             characters include some common punctuation marks, such as ".".
- *             If your input string fits this description, UrlApplyScheme may
- *             treat it as valid and not apply a scheme. To force the function
- *             to apply a scheme to a URL, set the URL_APPLY_FORCEAPPLY and
- *             URL_APPLY_DEFAULT flags in dwFlags. This combination of flags
- *             forces the function to apply a scheme to the URL. Typically,
- *             the function will not be able to determine a valid scheme. The
- *             second flag guarantees that, if no valid scheme can be
- *             determined, the function will apply the default scheme to the URL.
- * Status    : PARTIALLY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Thu, 2000/04/20 19:46]
- *****************************************************************************/
-
-ODINFUNCTION4(HRESULT, UrlApplySchemeA,
-              LPCSTR,  pszIn,
-              LPSTR,   pszOut,
-              LPDWORD, pcchOut,
-              DWORD,   dwFlags)
-{
-  dprintf(("not implemented correctly (In=%s).",
-          pszIn));
-
-  strncpy(pszOut,
-          pszIn,
-          *pcchOut);
-  *pcchOut = lstrlenA(pszIn);
-
-  return S_OK;
-}
-
-
-/*****************************************************************************
- * Name      : UrlCombine
- * Purpose   : Takes a relative URL and its base and returns a URL in canonical form.
- * Parameters: pszBase     [in]  Pointer to a string with the base URL.
- *             pszRelative [in]  Pointer to a string with the relative URL.
- *             pszCombined [out] Pointer to a buffer to receive a
- *                               NULL-terminated string containing the combined URL.
- *             pcchCombined [in/out] Pointer to a value set to the number of
- *                               characters in the pszCombined buffer. When the
- *                               function returns, the value depends on whether
- *                               the function is successful or returns E_POINTER.
- *                               For other return values, the value of this
- *                               parameter is meaningless.
- *             dwFlags     [in]  Flags that specify how the URL will be converted
- *                               to canonical form. The following flags can be combined.
- *                               URL_DONT_SIMPLIFY
- *                                 Treat '/./' and '/../' in a URL string as literal
- *                                 characters, not as shorthand for
- *                                 navigation. See Remarks for further discussion.
- *                               URL_ESCAPE_PERCENT
- *                                 Convert any occurrence of '%' to its escape sequence.
- *                               URL_ESCAPE_SPACES_ONLY
- *                                 Replace only spaces with escape sequences. This flag
- *                                 takes precedence over
- *                                 URL_ESCAPE_UNSAFE, but does not apply to opaque URLs.
- *                               URL_ESCAPE_UNSAFE
- *                                 Replace unsafe values with their escape sequences.
- *                                 This flag applies to all URLs,
- *                                 including opaque URLs.
- *                               URL_PLUGGABLE_PROTOCOL
- *                                 Combine URLs with client-defined pluggable protocols,
- *                                 according to the W3C specification. This flag does not
- *                                 apply to standard protocols such as ftp, http,
- *                                 gopher, and so on. If this flag is set,
- *                                 UrlCombine will not simplify URLs, so there is
- *                                 no need to also set URL_DONT_SIMPLIFY.
- *                               URL_UNESCAPE
- *                                 Unescape any escape sequences that the URLs contain,
- *                                 with two exceptions. The escape sequences
- *                                 for '?' and '#' will not be unescaped.
- *                                 If one of the URL_ESCAPE_XXX flags is also
- *                                 set, the two URLs will unescaped, then
- *                                 combined, then escaped.
- * Variables :
- * Result    : S_OK      pszCombined points to a string containing the
- *                       combined URLs. The value of pcchCombined is set to
- *                       the number of characters in the string, not counting
- *                       the terminating NULL character.
- *             E_POINTER The buffer was too small. The value of pcchCombined
- *                       is set to the minimum number of characters that the
- *                       buffer must be able to contain, including the
- *                       terminating NULL character.
- *             Other errors A standard OLE error value is returned.
- * Remark    : SHLWAPI.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION5(HRESULT,UrlCombineA,
-              LPCSTR, pszBase,
-              LPCSTR, pszRelative,
-              LPSTR,  pszCombined,
-              LPDWORD,pcchCombined,
-              DWORD,  dwFlags)
-{
-  dprintf(("not implemented."));
-
-  return S_OK;
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION5(HRESULT, UrlCombineW,
-              LPCWSTR, pszBase,
-              LPCWSTR, pszRelative,
-              LPWSTR,  pszCombined,
-              LPDWORD, pcchCombined,
-              DWORD,   dwFlags)
-{
-  dprintf(("not implemented."));
-
-  return S_OK;
-}
-
-
-/*****************************************************************************
- * Name      : UrlCompare
- * Purpose   : Does a case-sensitive comparison of two URL strings.
- * Parameters: pszURL1      [in] NULL-terminated string with the first URL.
- *             pszURL2      [in] NULL-terminated string with the second URL.
- *             fIgnoreSlash [in] Value that is set to TRUE to have UrlCompare
- *                               ignore a trailing '/' character on either or
- *                               both URLs.
- * Variables :
- * Result    : Returns zero if the two strings are equal, apart from a
- *             trailing '\' character if fIgnoreSlash is set to TRUE.
- *             Returns a negative integer if the string pointed to by pszURL1
- *             is less than the string pointed to by pszURL2. Otherwise, it
- *             returns a positive integer.
- * Remark    : SHLWAPI.
- *             For the best results, you should first canonicalize the URLs
- *             with UrlCanonicalize. Then, compare the canonicalized URLs with
- *             UrlCompare.
- * Status    : PARTIALLY IMPLEMENTED UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION3(int,    UrlCompareA,
-              LPCSTR, pszURL1,
-              LPCSTR, pszURL2,
-              BOOL,   fIgnoreSlash)
-{
-  dprintf(("not correctly implemented."));
-
-  return strcmp(pszURL1,
-                pszURL2);
-}
-
-/**
- * @status      stub
- */
-ODINFUNCTION3(int,     UrlCompareW,
-              LPCWSTR, pszURL1,
-              LPCWSTR, pszURL2,
-              BOOL,    fIgnoreSlash)
-{
-  dprintf(("not correctly implemented."));
-
-  return wcscmp((const wchar_t *)pszURL1,
-                (const wchar_t *)pszURL2);
-}
 
 
@@ -345,110 +89,4 @@
 
 
-/*****************************************************************************
- * Name      : UrlGetLocation
- * Purpose   : Retrieves the location from a URL.
- * Parameters: pszURL [in] Pointer to a NULL-terminated string that contains
- *             the location.
- * Variables :
- * Result    : Returns a pointer to a NULL-terminated string with the
- *             location, or NULL otherwise.
- * Remark    : SHLWAPI.
- *             The location is the segment of the URL starting with a ? or #
- *             character. If a file URL has a query string, the returned
- *             string includes the query string.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION1(LPCSTR, UrlGetLocationA,
-              LPCSTR, pszURL)
-{
-  dprintf(("not implemented."));
-
-  return pszURL;
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION1(LPCWSTR, UrlGetLocationW,
-              LPCWSTR, pszURL)
-{
-  dprintf(("not implemented."));
-
-  return pszURL;
-}
-
-
-/*****************************************************************************
- * Name      : UrlGetPart
- * Purpose   : Takes a URL string and returns a specified part.
- * Parameters: pszIn   [in]     NULL-terminated string that contains the URL.
- *             pszOut  [out]    A buffer that will receive a NULL-terminated
- *                              string with the specified part.
- *             pcchOut [in/out] Address of a value set to the number of
- *                              characters in the pszOut buffer. When the
- *                              function returns, the value depends on whether
- *                              the function is successful or returns E_POINTER.
- *                              For other return values, the value of this
- *                              parameter is meaningless.
- *             dwPart  [in]     Flags that specify which part of the URL to retrieve.
- *                              It can have one of the following values.
- *               Flag                Description
- *               URL_PART_HOSTNAME   The host name.
- *               URL_PART_PASSWORD   The password.
- *               URL_PART_PORT       The port number.
- *               URL_PART_QUERY      The query portion of the URL.
- *               URL_PART_SCHEME     The URL scheme.
- *               URL_PART_USERNAME   The username.
- *
- *             dwFlags [in]     Flag that can be set to keep the URL scheme,
- *                              in addition to the part that is specified by dwPart.
- *               Flag                    Description
- *               URL_PARTFLAG_KEEPSCHEME Keep the URL scheme.
- * Variables :
- * Result    :
- * Remark    : SHLWAPI.
- *             Returns an OLE success code if successful. The value pointed to
- *             by pcchOut will be set to the number of characters written to
- *             the output buffer, excluding the terminating NULL. If the buffer
- *             was too small, E_POINTER is returned, and the value pointed to
- *             by pcchOut will be set to the minimum number of characters that
- *             the buffer must be able to contain, including the terminating
- *             NULL character. Otherwise, an OLE error value is returned.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION5(HRESULT, UrlGetPartA,
-              LPCSTR,  pszIn,
-              LPSTR,   pszOut,
-              LPDWORD, pcchOut,
-              DWORD,   dwPart,
-              DWORD,   dwFlags)
-{
-  dprintf(("not implemented."));
-
-  return S_OK;
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION5(HRESULT, UrlGetPartW,
-              LPCWSTR, pszIn,
-              LPWSTR,  pszOut,
-              LPDWORD, pcchOut,
-              DWORD,   dwPart,
-              DWORD,   dwFlags)
-{
-  dprintf(("not implemented."));
-
-  return S_OK;
-}
 
 
@@ -469,114 +107,2 @@
 
 
-/*****************************************************************************
- * Name      : UrlIs
- * Purpose   : Tests whether or not a URL is a specified type.
- * Parameters: pszUrl [in] Pointer to a string containing the URL.
- *             UrlIs  [in] Type of URL to be tested for.
- *                         UrlIs can take one of the following values:
- *               URLIS_APPLIABLE Attempt to determine a valid scheme for the URL.
- *               URLIS_DIRECTORY Does the URL string end with a directory?
- *               URLIS_FILEURL   Is the URL a file URL?
- *               URLIS_HASQUERY  Does the URL have an appended query string?
- *               URLIS_NOHISTORY Is the URL a "No History" URL?
- *               URLIS_OPAQUE    Is the URL opaque?
- *               URLIS_URL       Is the URL valid?
- * Variables :
- * Result    : For all but one of the URL types, UrlIs returns TRUE if the URL
- *             is the specified type, or FALSE if not. If UrlIs is set to
- *             URLIS_APPLIABLE, UrlIs will attempt to determine the URL scheme.
- *             If the function is able to determine a scheme, it returns TRUE,
- *             or FALSE otherwise.
- * Remark    : SHLWAPI.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION2(BOOL,   UrlIsA,
-              LPCSTR, pszUrl,
-              URLIS,  UrlIs)
-{
-  dprintf(("not implemented."));
-
-  return TRUE;
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION2(BOOL,    UrlIsW,
-              LPCWSTR, pszUrl,
-              URLIS,   UrlIs)
-{
-  dprintf(("not implemented."));
-
-  return TRUE;
-}
-
-/*****************************************************************************
- * Name      : UrlIsNoHistory
- * Purpose   : Returns whether or not a URL is a No History URL.
- * Parameters: pszURL [in] NULL-terminated string with the URL.
- * Variables :
- * Result    : Returns a non-zero value if the URL is a No History URL, or zero otherwise.
- * Remark    : SHLWAPI.
- *             A No History URL is a URL that browsers typically do not
- *             include in their navigation history.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION1(BOOL,  UrlIsNoHistoryA,
-              LPCSTR,pszURL)
-{
-  return UrlIsA(pszURL, URLIS_NOHISTORY);
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION1(BOOL,   UrlIsNoHistoryW,
-              LPCWSTR,pszURL)
-{
-  return UrlIsW(pszURL, URLIS_NOHISTORY);
-}
-
-
-/*****************************************************************************
- * Name      : UrlIsOpaque
- * Purpose   : Returns whether a URL is opaque.
- * Parameters: pszURL [in] NULL-terminated string with the URL.
- * Variables :
- * Result    : Returns a non-zero value if the URL is opaque, or zero
- *             otherwise.
- * Remark    : SHLWAPI.
- *             A URL that has a scheme that is not followed by two slashes (//)
- *             is opaque. For example, mailto:xyz@somecompany.com is an opaque
- *             URL. Opaque URLs cannot be separated into the standard
- *             URL heirarchy.
- * Status    : STUB UNTESTED
- *
- * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
- *****************************************************************************/
-
-ODINFUNCTION1(BOOL,   UrlIsOpaqueA,
-              LPCSTR, pszURL)
-{
-  return UrlIsA(pszURL, URLIS_OPAQUE);
-}
-
-
-/**
- * @status      stub
- */
-ODINFUNCTION1(BOOL,   UrlIsOpaqueW,
-              LPCWSTR,pszURL)
-{
-  return UrlIsW(pszURL, URLIS_OPAQUE);
-}
-
-
