Changeset 7820 for trunk/src


Ignore:
Timestamp:
Feb 6, 2002, 9:18:30 PM (24 years ago)
Author:
sandervl
Message:

Wine resync

Location:
trunk/src/shlwapi
Files:
2 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/shlwapi/makefile

    r7397 r7820  
    1 # $Id: makefile,v 1.24 2001-11-19 12:34:54 sandervl Exp $
     1# $Id: makefile,v 1.25 2002-02-06 20:18:27 sandervl Exp $
    22
    33#
     
    1919OBJS = \
    2020$(OBJDIR)\shlwapi.obj \
     21$(OBJDIR)\shlwapi_main.obj \
    2122$(OBJDIR)\shlstub.obj \
    2223$(OBJDIR)\url.obj \
     
    2930$(OBJDIR)\string_odin.obj \
    3031$(OBJDIR)\string.obj \
    31 $(OBJDIR)\shlwapirsrc.obj \
    3232$(OBJDIR)\ordinal.obj \
    3333$(OBJDIR)\ordinal_odin.obj \
     34$(OBJDIR)\shlwapirsrc.obj \
    3435$(DLLENTRY)
    3536
     
    4041LIBS = \
    4142$(ODIN32_LIB)/kernel32.lib \
     43$(ODIN32_LIB)/ntdll.lib \
    4244$(ODIN32_LIB)/user32.lib \
    4345$(ODIN32_LIB)/gdi32.lib \
  • trunk/src/shlwapi/ordinal.c

    r7508 r7820  
    1919#include "wine/unicode.h"
    2020#include "wine/obj_base.h"
     21#include "wine/obj_inplace.h"
     22#include "wine/obj_serviceprovider.h"
    2123#include "wingdi.h"
     24#include "winreg.h"
    2225#include "winuser.h"
    2326#include "debugtools.h"
     27#include "ordinal.h"
     28#include "shlwapi.h"
    2429
    2530DEFAULT_DEBUG_CHANNEL(shell);
    2631
    27 #ifdef __WIN32OS2__
    28 extern HINSTANCE shlwapi_hInstance = 0;
    29 extern HMODULE SHLWAPI_hshell32 = 0;
    30 extern HMODULE SHLWAPI_hwinmm = 0;
    31 extern HMODULE SHLWAPI_hcomdlg32 = 0;
    32 extern HMODULE SHLWAPI_hmpr = 0;
    33 extern HMODULE SHLWAPI_hmlang = 0;
    34 #else
    3532extern HINSTANCE shlwapi_hInstance;
    3633extern HMODULE SHLWAPI_hshell32;
     
    3936extern HMODULE SHLWAPI_hmpr;
    4037extern HMODULE SHLWAPI_hmlang;
    41 #endif
     38
     39typedef HANDLE HSHARED; /* Shared memory */
     40
     41/* following is GUID for IObjectWithSite::SetSite  -- see _174           */
     42static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
     43/* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
     44static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
     45
     46/* The following schemes were identified in the native version of
     47 * SHLWAPI.DLL version 5.50
     48 */
     49typedef enum {
     50    URL_SCHEME_INVALID     = -1,
     51    URL_SCHEME_UNKNOWN     =  0,
     52    URL_SCHEME_FTP,
     53    URL_SCHEME_HTTP,
     54    URL_SCHEME_GOPHER,
     55    URL_SCHEME_MAILTO,
     56    URL_SCHEME_NEWS,
     57    URL_SCHEME_NNTP,
     58    URL_SCHEME_TELNET,
     59    URL_SCHEME_WAIS,
     60    URL_SCHEME_FILE,
     61    URL_SCHEME_MK,
     62    URL_SCHEME_HTTPS,
     63    URL_SCHEME_SHELL,
     64    URL_SCHEME_SNEWS,
     65    URL_SCHEME_LOCAL,
     66    URL_SCHEME_JAVASCRIPT,
     67    URL_SCHEME_VBSCRIPT,
     68    URL_SCHEME_ABOUT,
     69    URL_SCHEME_RES,
     70    URL_SCHEME_MAXVALUE
     71} URL_SCHEME;
     72
     73typedef struct {
     74    URL_SCHEME  scheme_number;
     75    LPCSTR scheme_name;
     76} SHL_2_inet_scheme;
     77
     78static const SHL_2_inet_scheme shlwapi_schemes[] = {
     79  {URL_SCHEME_FTP,        "ftp"},
     80  {URL_SCHEME_HTTP,       "http"},
     81  {URL_SCHEME_GOPHER,     "gopher"},
     82  {URL_SCHEME_MAILTO,     "mailto"},
     83  {URL_SCHEME_NEWS,       "news"},
     84  {URL_SCHEME_NNTP,       "nntp"},
     85  {URL_SCHEME_TELNET,     "telnet"},
     86  {URL_SCHEME_WAIS,       "wais"},
     87  {URL_SCHEME_FILE,       "file"},
     88  {URL_SCHEME_MK,         "mk"},
     89  {URL_SCHEME_HTTPS,      "https"},
     90  {URL_SCHEME_SHELL,      "shell"},
     91  {URL_SCHEME_SNEWS,      "snews"},
     92  {URL_SCHEME_LOCAL,      "local"},
     93  {URL_SCHEME_JAVASCRIPT, "javascript"},
     94  {URL_SCHEME_VBSCRIPT,   "vbscript"},
     95  {URL_SCHEME_ABOUT,      "about"},
     96  {URL_SCHEME_RES,        "res"},
     97  {0, 0}
     98};
    4299
    43100/* Macro to get function pointer for a module*/
     
    57114 and recommend the builtin rather than reimplementing the calls here!
    58115*/
    59 #ifndef __WIN32OS2__
    60 /*************************************************************************
    61  *      SHLWAPI_1       [SHLWAPI.1]
    62  */
    63 DWORD WINAPI SHLWAPI_1 (
    64         LPSTR   lpURL,
    65         LPDWORD lpdwFlags)
    66 {
    67   if (lpURL == NULL)
    68     return E_INVALIDARG;
    69  
    70   if (lpdwFlags == NULL)
    71     return E_INVALIDARG;
    72  
    73   // verify flags
    74   if (*lpdwFlags != 0x18)   // some unknown flag
    75     return E_INVALIDARG;      // some unknown error condition
    76  
    77   FIXME("(%p %s %p %s)\n",lpStr, debugstr_a(lpStr),x, debugstr_a(x));
    78   return 0;
    79 }
    80 
    81 /*************************************************************************
    82  *      SHLWAPI_2       [SHLWAPI.2]
    83  */
    84 DWORD WINAPI SHLWAPI_2 (LPCWSTR x,LPVOID y)
    85 {
    86         FIXME("(%s,%p)\n",debugstr_w(x),y);
     116
     117/*************************************************************************
     118 *      @       [SHLWAPI.1]
     119 *
     120 * Identifies the Internet "scheme" in the passed string. ASCII based.
     121 * Also determines start and length of item after the ':'
     122 */
     123DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
     124{
     125    DWORD cnt;
     126    const SHL_2_inet_scheme *inet_pro;
     127
     128    if (y->size != 0x18) return E_INVALIDARG;
     129    /* FIXME: leading white space generates error of 0x80041001 which
     130     *        is undefined
     131     */
     132    if (*x <= ' ') return 0x80041001;
     133    cnt = 0;
     134    y->sizep1 = 0;
     135    y->ap1 = x;
     136    while (*x) {
     137        if (*x == ':') {
     138            y->sizep1 = cnt;
     139            cnt = -1;
     140            y->ap2 = x+1;
     141            break;
     142        }
     143        x++;
     144        cnt++;
     145    }
     146
     147    /* check for no scheme in string start */
     148    /* (apparently schemes *must* be larger than a single character)  */
     149    if ((*x == '\0') || (y->sizep1 <= 1)) {
     150        y->ap1 = 0;
     151        return 0x80041001;
     152    }
     153
     154    /* found scheme, set length of remainder */
     155    y->sizep2 = lstrlenA(y->ap2);
     156
     157    /* see if known scheme and return indicator number */
     158    y->fcncde = URL_SCHEME_UNKNOWN;
     159    inet_pro = shlwapi_schemes;
     160    while (inet_pro->scheme_name) {
     161        if (!strncasecmp(inet_pro->scheme_name, y->ap1,
     162                    min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
     163            y->fcncde = inet_pro->scheme_number;
     164            break;
     165        }
     166        inet_pro++;
     167    }
     168    return S_OK;
     169}
     170
     171/*************************************************************************
     172 *      @       [SHLWAPI.2]
     173 *
     174 * Identifies the Internet "scheme" in the passed string. UNICODE based.
     175 * Also determines start and length of item after the ':'
     176 */
     177DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
     178{
     179    DWORD cnt;
     180    const SHL_2_inet_scheme *inet_pro;
     181    LPSTR cmpstr;
     182    INT len;
     183
     184    if (y->size != 0x18) return E_INVALIDARG;
     185    /* FIXME: leading white space generates error of 0x80041001 which
     186     *        is undefined
     187     */
     188    if (*x <= L' ') return 0x80041001;
     189    cnt = 0;
     190    y->sizep1 = 0;
     191    y->ap1 = x;
     192    while (*x) {
     193        if (*x == L':') {
     194            y->sizep1 = cnt;
     195            cnt = -1;
     196            y->ap2 = x+1;
     197            break;
     198        }
     199        x++;
     200        cnt++;
     201    }
     202
     203    /* check for no scheme in string start */
     204    /* (apparently schemes *must* be larger than a single character)  */
     205    if ((*x == L'\0') || (y->sizep1 <= 1)) {
     206        y->ap1 = 0;
     207        return 0x80041001;
     208    }
     209
     210    /* found scheme, set length of remainder */
     211    y->sizep2 = lstrlenW(y->ap2);
     212
     213    /* see if known scheme and return indicator number */
     214    len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
     215    cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
     216    WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
     217    y->fcncde = URL_SCHEME_UNKNOWN;
     218    inet_pro = shlwapi_schemes;
     219    while (inet_pro->scheme_name) {
     220        if (!strncasecmp(inet_pro->scheme_name, cmpstr,
     221                    min(len, lstrlenA(inet_pro->scheme_name)))) {
     222            y->fcncde = inet_pro->scheme_number;
     223            break;
     224        }
     225        inet_pro++;
     226    }
     227    HeapFree(GetProcessHeap(), 0, cmpstr);
     228    return S_OK;
     229}
     230
     231/*************************************************************************
     232 * SHLWAPI_DupSharedHandle
     233 *
     234 * Internal implemetation of SHLWAPI_11.
     235 */
     236static
     237HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
     238                                       DWORD dwSrcProcId, DWORD dwAccess,
     239                                       DWORD dwOptions)
     240{
     241  HANDLE hDst, hSrc;
     242  DWORD dwMyProcId = GetCurrentProcessId();
     243  HSHARED hRet = (HSHARED)NULL;
     244
     245  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
     246        dwAccess, dwOptions);
     247
     248  /* Get dest process handle */
     249  if (dwDstProcId == dwMyProcId)
     250    hDst = GetCurrentProcess();
     251  else
     252    hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
     253
     254  if (hDst)
     255  {
     256    /* Get src process handle */
     257    if (dwSrcProcId == dwMyProcId)
     258      hSrc = GetCurrentProcess();
     259    else
     260      hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
     261
     262    if (hSrc)
     263    {
     264      /* Make handle available to dest process */
     265      if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
     266                           dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
     267        hRet = (HSHARED)NULL;
     268
     269      if (dwSrcProcId != dwMyProcId)
     270        CloseHandle(hSrc);
     271    }
     272
     273    if (dwDstProcId != dwMyProcId)
     274      CloseHandle(hDst);
     275  }
     276
     277  TRACE("Returning handle %p\n", (PVOID)hRet);
     278  return hRet;
     279}
     280
     281/*************************************************************************
     282 * @  [SHLWAPI.7]
     283 *
     284 * Create a block of sharable memory and initialise it with data.
     285 *
     286 * PARAMS
     287 * dwProcId [I] ID of process owning data
     288 * lpvData  [I] Pointer to data to write
     289 * dwSize   [I] Size of data
     290 *
     291 * RETURNS
     292 * Success: A shared memory handle
     293 * Failure: NULL
     294 *
     295 * NOTES
     296 * Ordinals 7-11 provide a set of calls to create shared memory between a
     297 * group of processes. The shared memory is treated opaquely in that its size
     298 * is not exposed to clients who map it. This is accomplished by storing
     299 * the size of the map as the first DWORD of mapped data, and then offsetting
     300 * the view pointer returned by this size.
     301 *
     302 * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
     303 * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
     304 * SHLWAPI_11           - Helper function; Duplicate cross-process handles
     305   */
     306HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, LPCVOID lpvData, DWORD dwSize)
     307{
     308  HANDLE hMap;
     309  LPVOID pMapped;
     310  HSHARED hRet = (HSHARED)NULL;
     311
     312  TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
     313
     314  /* Create file mapping of the correct length */
     315  hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
     316                            dwSize + sizeof(dwSize), NULL);
     317  if (!hMap)
     318    return hRet;
     319
     320  /* Get a view in our process address space */
     321  pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
     322
     323  if (pMapped)
     324  {
     325    /* Write size of data, followed by the data, to the view */
     326    *((DWORD*)pMapped) = dwSize;
     327    if (dwSize)
     328      memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
     329
     330    /* Release view. All further views mapped will be opaque */
     331    UnmapViewOfFile(pMapped);
     332    hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
     333                                   GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
     334                                   DUPLICATE_SAME_ACCESS);
     335  }
     336
     337  CloseHandle(hMap);
     338  return hRet;
     339}
     340
     341/*************************************************************************
     342 * @ [SHLWAPI.8]
     343 *
     344 * Get a pointer to a block of shared memory from a shared memory handle.
     345 *
     346 * PARAMS
     347 * hShared  [I] Shared memory handle
     348 * dwProcId [I] ID of process owning hShared
     349 *
     350 * RETURNS
     351 * Success: A pointer to the shared memory
     352 * Failure: NULL
     353 *
     354 * NOTES
     355 * See SHLWAPI_7.
     356   */
     357PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
     358  {
     359  HSHARED hDup;
     360  LPVOID pMapped;
     361
     362  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
     363
     364  /* Get handle to shared memory for current process */
     365  hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
     366                                 FILE_MAP_ALL_ACCESS, 0);
     367  /* Get View */
     368  pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
     369  CloseHandle(hDup);
     370
     371  if (pMapped)
     372    return (char *) pMapped + sizeof(DWORD); /* Hide size */
     373  return NULL;
     374}
     375
     376/*************************************************************************
     377 * @ [SHLWAPI.9]
     378 *
     379 * Release a pointer to a block of shared memory.
     380 *
     381 * PARAMS
     382 * lpView [I] Shared memory pointer
     383 *
     384 * RETURNS
     385 * Success: TRUE
     386 * Failure: FALSE
     387 *
     388 * NOTES
     389 * See SHLWAPI_7.
     390 */
     391BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
     392{
     393  TRACE("(%p)\n", lpView);
     394  return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
     395}
     396
     397/*************************************************************************
     398 * @ [SHLWAPI.10]
     399 *
     400 * Destroy a block of sharable memory.
     401 *
     402 * PARAMS
     403 * hShared  [I] Shared memory handle
     404 * dwProcId [I] ID of process owning hShared
     405 *
     406 * RETURNS
     407 * Success: TRUE
     408 * Failure: FALSE
     409 *
     410 * NOTES
     411 * See SHLWAPI_7.
     412 */
     413BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
     414{
     415  HSHARED hClose;
     416
     417  TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
     418
     419  /* Get a copy of the handle for our process, closing the source handle */
     420  hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
     421                                   FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
     422  /* Close local copy */
     423  return CloseHandle((HANDLE)hClose);
     424}
     425
     426/*************************************************************************
     427 * @   [SHLWAPI.11]
     428 *
     429 * Copy a sharable memory handle from one process to another.
     430 *
     431 * PARAMS
     432 * hShared     [I] Shared memory handle to duplicate
     433 * dwDstProcId [I] ID of the process wanting the duplicated handle
     434 * dwSrcProcId [I] ID of the process owning hShared
     435 * dwAccess    [I] Desired DuplicateHandle access
     436 * dwOptions   [I] Desired DuplicateHandle options
     437 *
     438 * RETURNS
     439 * Success: A handle suitable for use by the dwDstProcId process.
     440 * Failure: A NULL handle.
     441 *
     442 * NOTES
     443 * See SHLWAPI_7.
     444 */
     445HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
     446                          DWORD dwAccess, DWORD dwOptions)
     447{
     448  HSHARED hRet;
     449
     450  hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
     451                                 dwAccess, dwOptions);
     452  return hRet;
     453}
     454
     455/*************************************************************************
     456 *      @       [SHLWAPI.13]
     457 * (Used by IE4 during startup)
     458 */
     459HRESULT WINAPI SHLWAPI_13 (
     460        LPVOID w,
     461        LPVOID x)
     462{
     463        FIXME("(%p %p)stub\n",w,x);
     464        return 1;
     465#if 0
     466        /* pseudo code extracted from relay trace */
     467        RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Aceepted Documents", &newkey);
     468        ret = 0;
     469        i = 0;
     470        size = 0;
     471        while(!ret) {
     472            ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
     473            size += ???;
     474            i++;
     475        }
     476        b1 = LocalAlloc(0x40, size);
     477        ret = 0;
     478        i = 0;
     479        while(!ret) {
     480            ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
     481            RegisterClipBoardFormatA(a4);
     482            i++;
     483        }
     484        hwnd1 = GetModuleHandleA("URLMON.DLL");
     485        proc = GetProcAddress(hwnd1, "CreateFormatEnumerator");
     486        HeapAlloc(??, 0, 0x14);
     487        HeapAlloc(??, 0, 0x50);
     488        LocalAlloc(0x40, 0x78);
     489        /* FIXME: bad string below */
     490        lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
     491        StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
     492
     493        GetTickCount();
     494        IsBadReadPtr(c1 = 0x403fd210,4);
     495        InterlockedIncrement(c1+4);
     496        LocalFree(b1);
     497        RegCloseKey(newkey);
     498        IsBadReadPtr(c1 = 0x403fd210,4);
     499        InterlockedIncrement(c1+4);
     500
     501        HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
     502        HeapAlloc(40350000,00000000,00000050) retval=403feb44;
     503        hwnd1 = GetModuleHandleA("URLMON.DLL");
     504        proc = GetProcAddress(hwnd1, "RegisterFormatEnumerator");
     505        /* 0x1a40c88c is in URLMON.DLL just before above proc
     506         * content is L"_EnumFORMATETC_"
     507         * label is d1
     508         */
     509        IsBadReadPtr(d1 = 0x1a40c88c,00000002);
     510        lstrlenW(d1);
     511        lstrlenW(d1);
     512        HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
     513        IsBadReadPtr(d2 = 0x403fd0a8,00000004);
     514        InterlockedIncrement(d2+4);
     515        IsBadReadPtr(d2 = 0x403fd0a8,00000004);
     516        InterlockedDecrement(d2+4);
     517        IsBadReadPtr(c1,00000004);
     518        InterlockedDecrement(c1+4);
     519        IsBadReadPtr(c1,00000004);
     520        InterlockedDecrement(c1+4);
     521
     522#endif
     523}
     524
     525/*************************************************************************
     526 *      @       [SHLWAPI.14]
     527 *
     528 * Function:
     529 *    Retrieves IE "AcceptLanguage" value from registry. ASCII mode.
     530 * 
     531 */
     532HRESULT WINAPI SHLWAPI_14 (
     533        LPSTR langbuf,
     534        LPDWORD buflen)
     535{
     536        CHAR *mystr;
     537        DWORD mystrlen, mytype;
     538        HKEY mykey;
     539        LCID mylcid;
     540
     541        mystrlen = (*buflen > 6) ? *buflen : 6;
     542        mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
     543                                 HEAP_ZERO_MEMORY, mystrlen);
     544        RegOpenKeyA(HKEY_CURRENT_USER,
     545                    "Software\\Microsoft\\Internet Explorer\\International",
     546                    &mykey);
     547        if (RegQueryValueExA(mykey, "AcceptLanguage",
     548                              0, &mytype, mystr, &mystrlen)) {
     549            /* Did not find value */
     550            mylcid = GetUserDefaultLCID();
     551            /* somehow the mylcid translates into "en-us"
     552             *  this is similar to "LOCALE_SABBREVLANGNAME"
     553             *  which could be gotten via GetLocaleInfo.
     554             *  The only problem is LOCALE_SABBREVLANGUAGE" is
     555             *  a 3 char string (first 2 are country code and third is
     556             *  letter for "sublanguage", which does not come close to
     557             *  "en-us"
     558             */
     559            lstrcpyA(mystr, "en-us");
     560            mystrlen = lstrlenA(mystr);
     561        }
     562        else {
     563            /* handle returned string */
     564            FIXME("missing code\n");
     565        }
     566        if (mystrlen > *buflen)
     567            lstrcpynA(langbuf, mystr, *buflen);
     568        else {
     569            lstrcpyA(langbuf, mystr);
     570            *buflen = lstrlenA(langbuf);
     571        }       
     572        RegCloseKey(mykey);
     573        HeapFree(GetProcessHeap(), 0, mystr);
     574        TRACE("language is %s\n", debugstr_a(langbuf));
    87575        return 0;
    88576}
    89577
    90578/*************************************************************************
    91  *      SHLWAPI_16      [SHLWAPI.16]
     579 *      @       [SHLWAPI.15]
     580 *
     581 * Function:
     582 *    Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
     583 * 
     584 */
     585HRESULT WINAPI SHLWAPI_15 (
     586        LPWSTR langbuf,
     587        LPDWORD buflen)
     588{
     589        CHAR *mystr;
     590        DWORD mystrlen, mytype;
     591        HKEY mykey;
     592        LCID mylcid;
     593
     594        mystrlen = (*buflen > 6) ? *buflen : 6;
     595        mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
     596                                 HEAP_ZERO_MEMORY, mystrlen);
     597        RegOpenKeyA(HKEY_CURRENT_USER,
     598                    "Software\\Microsoft\\Internet Explorer\\International",
     599                    &mykey);
     600        if (RegQueryValueExA(mykey, "AcceptLanguage",
     601                              0, &mytype, mystr, &mystrlen)) {
     602            /* Did not find value */
     603            mylcid = GetUserDefaultLCID();
     604            /* somehow the mylcid translates into "en-us"
     605             *  this is similar to "LOCALE_SABBREVLANGNAME"
     606             *  which could be gotten via GetLocaleInfo.
     607             *  The only problem is LOCALE_SABBREVLANGUAGE" is
     608             *  a 3 char string (first 2 are country code and third is
     609             *  letter for "sublanguage", which does not come close to
     610             *  "en-us"
     611             */
     612            lstrcpyA(mystr, "en-us");
     613            mystrlen = lstrlenA(mystr);
     614        }
     615        else {
     616            /* handle returned string */
     617            FIXME("missing code\n");
     618        }
     619        RegCloseKey(mykey);
     620        *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
     621        HeapFree(GetProcessHeap(), 0, mystr);
     622        TRACE("language is %s\n", debugstr_w(langbuf));
     623        return 0;
     624}
     625
     626/*************************************************************************
     627 *      @       [SHLWAPI.16]
    92628 */
    93629HRESULT WINAPI SHLWAPI_16 (
     
    100636        return 0xabba1252;
    101637}
    102 #endif
    103 
    104 /*************************************************************************
    105  *      SHLWAPI_23      [SHLWAPI.23]
     638
     639/*************************************************************************
     640 *      @       [SHLWAPI.18]
     641 *
     642 *  w is pointer to address of callback routine
     643 *  x is pointer to LPVOID to receive address of locally allocated
     644 *         space size 0x14
     645 *  return is 0 (unless out of memory???)
     646 *
     647 * related to _19, _21 and _22 below
     648 *  only seen invoked by SHDOCVW
     649 */
     650LONG WINAPI SHLWAPI_18 (
     651        LPVOID *w,
     652        LPVOID x)
     653{
     654        FIXME("(%p %p)stub\n",w,x);
     655        *((LPDWORD)x) = 0;
     656        return 0;
     657}
     658
     659/*************************************************************************
     660 *      @       [SHLWAPI.19]
     661 *
     662 *  w is address of allocated memory from _21
     663 *  return is 0 (unless out of memory???)
     664 *
     665 * related to _18, _21 and _22 below
     666 *  only seen invoked by SHDOCVW
     667 */
     668LONG WINAPI SHLWAPI_19 (
     669        LPVOID w)
     670{
     671        FIXME("(%p) stub\n",w);
     672        return 0;
     673}
     674
     675/*************************************************************************
     676 *      @       [SHLWAPI.21]
     677 *
     678 *  w points to space allocated via .18 above
     679 *      LocalSize is done on it (retrieves 18)
     680 *      LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
     681 *  x values seen 0xa0000005
     682 *  returns 1
     683 *
     684 *  relates to _18, _19 and _22 above and below
     685 *   only seen invoked by SHDOCVW
     686 */
     687LONG WINAPI SHLWAPI_21 (
     688        LPVOID w,
     689        DWORD  x)
     690{
     691        FIXME("(%p %lx)stub\n",w,x);
     692        return 1;
     693}
     694
     695/*************************************************************************
     696 *      @       [SHLWAPI.22]
     697 *
     698 *  return is 'w' value seen in x is 0xa0000005
     699 *
     700 *  relates to _18, _19 and _21 above
     701 *   only seen invoked by SHDOCVW
     702 */
     703LPVOID WINAPI SHLWAPI_22 (
     704        LPVOID w,
     705        DWORD  x)
     706{
     707        FIXME("(%p %lx)stub\n",w,x);
     708        return w;
     709}
     710
     711/*************************************************************************
     712 *      @       [SHLWAPI.23]
    106713 *
    107714 * NOTES
     
    127734
    128735/*************************************************************************
    129  *      SHLWAPI_24      [SHLWAPI.24]
     736 *      @       [SHLWAPI.24]
    130737 *
    131738 * NOTES
     
    148755
    149756/*************************************************************************
    150  *      SHLWAPI_30      [SHLWAPI.30]
    151  *
    152  * Seems to be an isspaceW.
    153  */
    154 BOOL WINAPI SHLWAPI_30(LPWSTR lpcChar)
    155 {
    156   switch (*lpcChar)
    157   {
    158   case (WCHAR)'\t':
    159   case (WCHAR)' ':
    160   case 160:
    161   case 12288:
    162   case 65279:
     757 *      @       [SHLWAPI.25]
     758 *
     759 * Seems to be iswalpha
     760 */
     761BOOL WINAPI SHLWAPI_25(WCHAR wc)
     762{
     763    return (get_char_typeW(wc) & C1_ALPHA) != 0;
     764}
     765
     766/*************************************************************************
     767 *      @       [SHLWAPI.26]
     768 *
     769 * Seems to be iswupper
     770 */
     771BOOL WINAPI SHLWAPI_26(WCHAR wc)
     772{
     773    return (get_char_typeW(wc) & C1_UPPER) != 0;
     774}
     775
     776/*************************************************************************
     777 *      @       [SHLWAPI.27]
     778 *
     779 * Seems to be iswlower
     780 */
     781BOOL WINAPI SHLWAPI_27(WCHAR wc)
     782{
     783    return (get_char_typeW(wc) & C1_LOWER) != 0;
     784}
     785
     786/*************************************************************************
     787 *      @       [SHLWAPI.28]
     788 *
     789 * Seems to be iswalnum
     790 */
     791BOOL WINAPI SHLWAPI_28(WCHAR wc)
     792{
     793    return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
     794}
     795
     796/*************************************************************************
     797 *      @       [SHLWAPI.29]
     798 *
     799 * Seems to be iswspace
     800 */
     801BOOL WINAPI SHLWAPI_29(WCHAR wc)
     802{
     803    return (get_char_typeW(wc) & C1_SPACE) != 0;
     804}
     805
     806/*************************************************************************
     807 *      @       [SHLWAPI.30]
     808 *
     809 * Seems to be iswblank
     810 */
     811BOOL WINAPI SHLWAPI_30(WCHAR wc)
     812{
     813    return (get_char_typeW(wc) & C1_BLANK) != 0;
     814}
     815
     816/*************************************************************************
     817 *      @       [SHLWAPI.31]
     818 *
     819 * Seems to be iswpunct
     820 */
     821BOOL WINAPI SHLWAPI_31(WCHAR wc)
     822{
     823    return (get_char_typeW(wc) & C1_PUNCT) != 0;
     824}
     825
     826/*************************************************************************
     827 *      @       [SHLWAPI.32]
     828 *
     829 * Seems to be iswcntrl
     830 */
     831BOOL WINAPI SHLWAPI_32(WCHAR wc)
     832{
     833    return (get_char_typeW(wc) & C1_CNTRL) != 0;
     834}
     835
     836/*************************************************************************
     837 *      @       [SHLWAPI.33]
     838 *
     839 * Seems to be iswdigit
     840 */
     841BOOL WINAPI SHLWAPI_33(WCHAR wc)
     842{
     843    return (get_char_typeW(wc) & C1_DIGIT) != 0;
     844}
     845
     846/*************************************************************************
     847 *      @       [SHLWAPI.34]
     848 *
     849 * Seems to be iswxdigit
     850 */
     851BOOL WINAPI SHLWAPI_34(WCHAR wc)
     852{
     853    return (get_char_typeW(wc) & C1_XDIGIT) != 0;
     854}
     855
     856/*************************************************************************
     857 *      @       [SHLWAPI.35]
     858 *
     859 */
     860BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
     861{
     862    FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
    163863    return TRUE;
    164   }
    165   return FALSE;
    166 }
    167 
    168 /*************************************************************************
    169  *      SHLWAPI_32      [SHLWAPI.32]
    170  */
    171 BOOL WINAPI SHLWAPI_32(LPCWSTR lpcChar)
    172 {
    173  if (*lpcChar < (WCHAR)' ')
    174    return TRUE;
    175 
    176  /* This is probably a shlwapi bug, but we do it the same for compatability */
    177  if (((DWORD)lpcChar & 0xffff) - 127 <= (WCHAR)' ')
    178    return TRUE;
    179  return FALSE;
    180 }
    181 
    182 /*************************************************************************
    183  *      SHLWAPI_40      [SHLWAPI.40]
     864}
     865
     866/*************************************************************************
     867 *      @       [SHLWAPI.36]
     868 *
     869 */
     870BOOL WINAPI SHLWAPI_36(HMENU h1, UINT ui2, UINT h3, LPCWSTR p4)
     871{
     872    TRACE("(0x%08x, 0x%08x, 0x%08x, %s): stub\n",
     873          h1, ui2, h3, debugstr_w(p4));
     874    return AppendMenuW(h1, ui2, h3, p4);
     875}
     876
     877/*************************************************************************
     878 *      @       [SHLWAPI.40]
    184879 *
    185880 * Get pointer to next Unicode character.
     
    191886
    192887/*************************************************************************
    193  *      SHLWAPI_74      [SHLWAPI.74]
     888 *      @       [SHLWAPI.74]
    194889 *
    195890 * Get the text from a given dialog item.
     
    205900  return 0;
    206901}
    207 /*************************************************************************
    208  *      SHLWAPI_151     [SHLWAPI.151]
    209  */
    210 #ifdef __WIN32OS2__
     902
     903/*************************************************************************
     904 *      @       [SHLWAPI.151]
     905 * Function:  Compare two ASCII strings for "len" bytes.
     906 * Returns:   *str1-*str2  (case sensitive)
     907 */
    211908DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
    212909{
    213   dprintf(("SHLWAPI_151 (strcmpn) %s %s %d", str1, str2, len));
    214   if (!len)
    215     return 0;
    216 
    217   while (--len && *str1 && *str1 == *str2)
    218   {
    219     str1++;
    220     str2++;
    221   }
    222   return *str1 - *str2;
    223 
    224 }
    225 #else
    226 DWORD WINAPI SHLWAPI_151(void)
    227 {
    228   FIXME(": stub\n");
    229   return 0;
    230 }
    231 #endif
    232 
    233 /*************************************************************************
    234  *      SHLWAPI_152     [SHLWAPI.152]
     910    return strncmp( str1, str2, len );
     911}
     912
     913/*************************************************************************
     914 *      @       [SHLWAPI.152]
     915 *
     916 * Function:  Compare two WIDE strings for "len" bytes.
     917 * Returns:   *str1-*str2  (case sensitive)
    235918 */
    236919DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
    237920{
    238   if (!len)
    239     return 0;
    240 
    241   while (--len && *str1 && *str1 == *str2)
    242   {
    243     str1++;
    244     str2++;
    245   }
    246   return *str1 - *str2;
    247 }
    248 
    249 /*************************************************************************
    250  *      SHLWAPI_153     [SHLWAPI.153]
    251  */
    252 #ifdef __WIN32OS2__
    253 //case insensitive string compare with length (ascii)
     921    return strncmpW( str1, str2, len );
     922}
     923
     924/*************************************************************************
     925 *      @       [SHLWAPI.153]
     926 * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
     927 * Returns:   *str1-*str2  (case insensitive)
     928 */
    254929DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
    255930{
    256   if (!len)
    257     return 0;
    258 
    259   return lstrncmpiA(str1, str2, len);
    260 }
    261 
    262 //case insensitive string compare with length (unicode)
     931    return strncasecmp( str1, str2, len );
     932}
     933
     934/*************************************************************************
     935 *      @       [SHLWAPI.154]
     936 *
     937 * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
     938 * Returns:   *str1-*str2  (case insensitive)
     939 */
    263940DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
    264941{
    265   if (!len)
    266     return 0;
    267 
    268   return lstrncmpiW(str1, str2, len);
    269 }
    270 
    271 #else
    272 DWORD WINAPI SHLWAPI_153(DWORD dw1, DWORD dw2, DWORD dw3)
    273 {
    274     FIXME("%08lx %08lx %08lx - stub\n", dw1, dw2, dw3);
    275     return 0;
    276 }
    277 #endif
    278 
    279 /*************************************************************************
    280  *      SHLWAPI_156     [SHLWAPI.156]
     942    return strncmpiW( str1, str2, len );
     943}
     944
     945/*************************************************************************
     946 *      @       [SHLWAPI.156]
    281947 *
    282948 *      Case sensitive string compare. Does not SetLastError().
     
    284950DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
    285951{
    286   while (*str1 && (*str1 == *str2)) { str1++; str2++; }
    287   return (INT)(*str1 - *str2);
    288 }
    289 
    290 /*************************************************************************
    291  *      SHLWAPI_162     [SHLWAPI.162]
     952    return strcmpW( str1, str2 );
     953}
     954
     955/*************************************************************************
     956 *      @       [SHLWAPI.158]
     957 *
     958 *      Case insensitive string compare. Does not SetLastError(). ??
     959 */
     960DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
     961{
     962    return strcmpiW( str1, str2 );
     963}
     964
     965/*************************************************************************
     966 *      @       [SHLWAPI.162]
    292967 *
    293968 * Ensure a multibyte character string doesn't end in a hanging lead byte.
     
    313988
    314989/*************************************************************************
    315  *      SHLWAPI_165     [SHLWAPI.165]
     990 *      @       [SHLWAPI.164]
     991 */
     992DWORD WINAPI SHLWAPI_164 (
     993        LPVOID u,
     994        LPVOID v,
     995        LPVOID w,
     996        LPVOID x,
     997        LPVOID y,
     998        LPVOID z)
     999{
     1000        TRACE("(%p %p %p %p %p %p) stub\n",u,v,w,x,y,z);
     1001        return 0x80004002;    /* E_NOINTERFACE */
     1002}
     1003
     1004/*************************************************************************
     1005 *      @       [SHLWAPI.165]
    3161006 *
    3171007 * SetWindowLongA with mask.
     
    3281018
    3291019/*************************************************************************
    330  *      SHLWAPI_169     [SHLWAPI.169]
    331  */
    332 DWORD WINAPI SHLWAPI_169 (IUnknown * lpUnknown)
    333 {
     1020 *      @       [SHLWAPI.169]
     1021 *
     1022 *  Do IUnknown::Release on passed object.
     1023 */
     1024DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
     1025{
     1026        IUnknown *temp;
     1027
    3341028        TRACE("(%p)\n",lpUnknown);
    335 #if 0
    3361029        if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
    337         return IUnknown_Release(lpUnknown);
    338 #endif
    339         return 0;
    340 }
    341 
    342 /*************************************************************************
    343  *      SHLWAPI_170     [SHLWAPI.170]
     1030        temp = *lpUnknown;
     1031        *lpUnknown = NULL;
     1032        TRACE("doing Release\n");
     1033        return IUnknown_Release(temp);
     1034}
     1035
     1036/*************************************************************************
     1037 *      @       [SHLWAPI.170]
    3441038 *
    3451039 * Skip URL '//' sequence.
     
    3531047
    3541048/*************************************************************************
    355  *      SHLWAPI_181     [SHLWAPI.181]
     1049 *      @       [SHLWAPI.172]
     1050 * Get window handle of OLE object
     1051 */
     1052DWORD WINAPI SHLWAPI_172 (
     1053        IUnknown *y,       /* [in]   OLE object interface */
     1054        LPHWND z)          /* [out]  location to put window handle */
     1055{
     1056        DWORD ret;
     1057        IUnknown *pv;
     1058
     1059        TRACE("(%p %p)\n",y,z);
     1060        if (!y) return E_FAIL;
     1061
     1062        if ((ret = IUnknown_QueryInterface(y, &IID_IOleWindow,(LPVOID *)&pv)) < 0) {
     1063            /* error */
     1064            return ret;
     1065        }
     1066        ret = IOleWindow_GetWindow((IOleWindow *)pv, z);
     1067        IUnknown_Release(pv);
     1068        TRACE("result hwnd=%08x\n", *z);
     1069        return ret;
     1070}
     1071
     1072/*************************************************************************
     1073 *      @       [SHLWAPI.174]
     1074 *
     1075 * Seems to do call either IObjectWithSite::SetSite or
     1076 *   IPersistMoniker::GetClassID.  But since we do not implement either
     1077 *   of those classes in our headers, we will fake it out.
     1078 */
     1079DWORD WINAPI SHLWAPI_174(
     1080        IUnknown *p1,     /* [in]   OLE object                          */
     1081        LPVOID *p2)       /* [out]  ptr to result of either GetClassID
     1082                                    or SetSite call.                    */
     1083{
     1084    DWORD ret, aa;
     1085
     1086    if (!p1) return E_FAIL;
     1087
     1088    /* see if SetSite interface exists for IObjectWithSite object */
     1089    ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
     1090    TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
     1091    if (ret) {
     1092
     1093        /* see if GetClassId interface exists for IPersistMoniker object */
     1094        ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
     1095        TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
     1096        if (ret) return ret;
     1097
     1098        /* fake a GetClassId call */
     1099        ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
     1100        TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
     1101              *(LPDWORD)p2);
     1102        IUnknown_Release((IUnknown *)aa);
     1103    }
     1104    else {
     1105        /* fake a SetSite call */
     1106        ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
     1107        TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
     1108              *(LPDWORD)p2);
     1109        IUnknown_Release((IUnknown *)p1);
     1110    }
     1111    return ret;
     1112}
     1113
     1114/*************************************************************************
     1115 *      @       [SHLWAPI.176]
     1116 *
     1117 * Function appears to be interface to IServiceProvider::QueryService
     1118 *
     1119 * NOTE:
     1120 *   returns E_NOINTERFACE
     1121 *           E_FAIL  if w == 0
     1122 *           S_OK    if _219 called successfully
     1123 */
     1124DWORD WINAPI SHLWAPI_176 (
     1125        IUnknown* unk,    /* [in]    object to give Service Provider */
     1126        REFGUID   sid,    /* [in]    Service ID                      */
     1127        REFIID    riid,   /* [in]    Function requested              */
     1128        LPVOID    *z)     /* [out]   place to save interface pointer */
     1129{
     1130    DWORD ret;
     1131    LPVOID aa;
     1132    *z = 0;
     1133    if (!unk) return E_FAIL;
     1134    ret = IUnknown_QueryInterface(unk, &IID_IServiceProvider, &aa);
     1135    TRACE("did IU_QI retval=%08lx, aa=%p\n", ret, aa);
     1136    if (ret) return ret;
     1137    ret = IServiceProvider_QueryService((IServiceProvider *)aa, sid, riid,
     1138                                        (void **)z);
     1139    TRACE("did ISP_QS retval=%08lx, *z=%p\n", ret, (LPVOID)*z);
     1140    IUnknown_Release((IUnknown*)aa);
     1141    return ret;
     1142}
     1143
     1144/*************************************************************************
     1145 *      @       [SHLWAPI.181]
    3561146 *
    3571147 *      Enable or disable a menu item.
     
    3631153
    3641154/*************************************************************************
    365  *      SHLWAPI_183     [SHLWAPI.183]
     1155 *      @       [SHLWAPI.183]
    3661156 *
    3671157 * Register a window class if it isn't already.
     
    3761166
    3771167/*************************************************************************
    378  *      SHLWAPI_193     [SHLWAPI.193]
     1168 *      @       [SHLWAPI.193]
    3791169 */
    3801170DWORD WINAPI SHLWAPI_193 ()
     
    3921182
    3931183/*************************************************************************
    394  *      SHLWAPI_215     [SHLWAPI.215]
     1184 *      @       [SHLWAPI.199]
     1185 *
     1186 * Copy interface pointer
     1187 */
     1188DWORD WINAPI SHLWAPI_199 (
     1189        IUnknown **dest,   /* [out] pointer to copy of interface ptr */
     1190        IUnknown *src)     /* [in]  interface pointer */
     1191{
     1192        TRACE("(%p %p)\n",dest,src);
     1193        if (*dest != src) {
     1194            if (*dest)
     1195                IUnknown_Release(*dest);
     1196            if (src) {
     1197                IUnknown_AddRef(src);
     1198                *dest = src;
     1199            }
     1200        }
     1201        return 4;
     1202}
     1203
     1204/*************************************************************************
     1205 *      @       [SHLWAPI.208]
     1206 *
     1207 * Some sort of memory management process - associated with _210
     1208 */
     1209DWORD WINAPI SHLWAPI_208 (
     1210        DWORD    a,
     1211        DWORD    b,
     1212        LPVOID   c,
     1213        LPVOID   d,
     1214        DWORD    e)
     1215{
     1216    FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
     1217          a, b, c, d, e);
     1218    return 1;
     1219}
     1220
     1221/*************************************************************************
     1222 *      @       [SHLWAPI.210]
     1223 *
     1224 * Some sort of memory management process - associated with _208
     1225 */
     1226DWORD WINAPI SHLWAPI_210 (
     1227        LPVOID   a,
     1228        DWORD    b,
     1229        LPVOID   c)
     1230{
     1231    FIXME("(%p 0x%08lx %p) stub\n",
     1232          a, b, c);
     1233    return 0;
     1234}
     1235
     1236/*************************************************************************
     1237 *      @       [SHLWAPI.211]
     1238 */
     1239DWORD WINAPI SHLWAPI_211 (
     1240        LPVOID   a,
     1241        DWORD    b)
     1242{
     1243    FIXME("(%p 0x%08lx) stub\n",
     1244          a, b);
     1245    return 1;
     1246}
     1247
     1248/*************************************************************************
     1249 *      @       [SHLWAPI.215]
    3951250 *
    3961251 * NOTES
    3971252 *  check me!
    3981253 */
    399 LPWSTR WINAPI SHLWAPI_215 (
    400         LPWSTR lpStrSrc,
    401         LPVOID lpwStrDest,
     1254DWORD WINAPI SHLWAPI_215 (
     1255        LPCSTR lpStrSrc,
     1256        LPWSTR lpwStrDest,
    4021257        int len)
    4031258{
    404         WARN("(%p %p %u)\n",lpStrSrc,lpwStrDest,len);
    405         return strncpyW(lpwStrDest, lpStrSrc, len);
    406 }
    407 
    408 /*************************************************************************
    409  *      SHLWAPI_218     [SHLWAPI.218]
     1259        INT len_a, ret;
     1260
     1261        len_a = lstrlenA(lpStrSrc);
     1262        ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
     1263        TRACE("%s %s %d, ret=%d\n",
     1264              debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
     1265        return ret;
     1266}
     1267
     1268/*************************************************************************
     1269 *      @       [SHLWAPI.218]
    4101270 *
    4111271 * WideCharToMultiByte with multi language support.
     
    4141274                       LPINT lpnMultiCharCount)
    4151275{
    416 #ifdef __WIN32OS2__
    4171276  static HRESULT (* WINAPI pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
    418 #else
    419   static HRESULT (* WINAPI pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
    420 #endif
    4211277  WCHAR emptyW[] = { '\0' };
    4221278  int len , reqLen;
     
    5011357
    5021358/*************************************************************************
    503  *      SHLWAPI_217     [SHLWAPI.217]
    504  *
    505  */
    506 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, LPINT lpnMultiCharCount)
    507 {
    508   return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, lpnMultiCharCount);
    509 }
    510 
    511 #ifndef __WIN32OS2__
    512 /*************************************************************************
    513  *      SHLWAPI_219     [SHLWAPI.219]
     1359 *      @       [SHLWAPI.217]
     1360 *
     1361 * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
     1362 * --> Crash. Something wrong here.
     1363 *
     1364 * It seems from OE v5 that the third param is the count. (GA 11/2001)
     1365 */
     1366INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
     1367{
     1368    INT myint = MultiCharCount;
     1369
     1370    return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
     1371}
     1372
     1373/*************************************************************************
     1374 *      @       [SHLWAPI.219]
     1375 *
     1376 * Seems to be "super" QueryInterface. Supplied with at table of interfaces
     1377 * and an array of IIDs and offsets into the table.
    5141378 *
    5151379 * NOTES
    5161380 *  error codes: E_POINTER, E_NOINTERFACE
    5171381 */
     1382typedef struct {
     1383    REFIID   refid;
     1384    DWORD    indx;
     1385} IFACE_INDEX_TBL;
     1386
    5181387HRESULT WINAPI SHLWAPI_219 (
    519         LPVOID w, /* [???] NOTE: returned by LocalAlloc, 0x450 bytes, iface */
    520         LPVOID x,
    521         REFIID riid,
    522         LPWSTR z) /* [???] NOTE: OUT: path */
    523 {
    524         FIXME("(%p %p %s %p)stub\n",w,x,debugstr_guid(riid),z);
    525         return 0xabba1252;
    526 }
    527 #endif
    528 
    529 /*************************************************************************
    530  *      SHLWAPI_222     [SHLWAPI.222]
     1388        LPVOID w,           /* [in]   table of interfaces                   */
     1389        IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
     1390        REFIID riid,        /* [in]   REFIID to get interface for           */
     1391        LPVOID *z)          /* [out]  location to get interface pointer     */
     1392{
     1393        HRESULT ret;
     1394        IUnknown *a_vtbl;
     1395        IFACE_INDEX_TBL *xmove;
     1396
     1397        TRACE("(%p %p %s %p)\n",
     1398              w,x,debugstr_guid(riid),z);
     1399        if (z) {
     1400            xmove = x;
     1401            while (xmove->refid) {
     1402                TRACE("trying (indx %ld) %s\n", xmove->indx,
     1403                      debugstr_guid(xmove->refid));
     1404                if (IsEqualIID(riid, xmove->refid)) {
     1405                    a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
     1406                    TRACE("matched, returning (%p)\n", a_vtbl);
     1407                    *z = (LPVOID)a_vtbl;
     1408                    IUnknown_AddRef(a_vtbl);
     1409                    return S_OK;
     1410                }
     1411                xmove++;
     1412            }
     1413
     1414            if (IsEqualIID(riid, &IID_IUnknown)) {
     1415                a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
     1416                TRACE("returning first for IUnknown (%p)\n", a_vtbl);
     1417                *z = (LPVOID)a_vtbl;
     1418                IUnknown_AddRef(a_vtbl);
     1419                return S_OK;
     1420            }
     1421            *z = 0;
     1422            ret = E_NOINTERFACE;
     1423        } else
     1424            ret = E_POINTER;
     1425        return ret;
     1426}
     1427
     1428/*************************************************************************
     1429 *      @       [SHLWAPI.222]
    5311430 *
    5321431 * NOTES
     
    5461445
    5471446/*************************************************************************
    548  *      SHLWAPI_223     [SHLWAPI.223]
     1447 *      @       [SHLWAPI.223]
    5491448 *
    5501449 * NOTES
     
    5631462
    5641463/*************************************************************************
    565  *      SHLWAPI_237     [SHLWAPI.237]
     1464 *      @       [SHLWAPI.236]
     1465 */
     1466HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
     1467{
     1468    HKEY newkey;
     1469    DWORD type, count;
     1470    CHAR value[MAX_PATH], string[MAX_PATH];
     1471
     1472    strcpy(string, "CLSID\\");
     1473    strcat(string, debugstr_guid(lpUnknown));
     1474    strcat(string, "\\InProcServer32");
     1475
     1476    count = MAX_PATH;
     1477    RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
     1478    RegQueryValueExA(newkey, 0, 0, &type, value, &count);
     1479    RegCloseKey(newkey);
     1480    return LoadLibraryExA(value, 0, 0);
     1481}
     1482
     1483/*************************************************************************
     1484 *      @       [SHLWAPI.237]
    5661485 *
    5671486 * Unicode version of SHLWAPI_183.
     
    5791498
    5801499/*************************************************************************
    581  *      SHLWAPI_240     [SHLWAPI.240]
     1500 *      @       [SHLWAPI.239]
     1501 */
     1502DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
     1503{
     1504    FIXME("(0x%08x %p 0x%08lx) stub\n",
     1505          hInstance, p2, dw3);
     1506    return 0;
     1507#if 0
     1508    /* pseudo code from relay trace */
     1509    WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
     1510    GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
     1511    /* above pair repeated for:
     1512           TridentThicketUrlDlClass
     1513           Shell Embedding
     1514           CIESplashScreen
     1515           Inet Notify_Hidden
     1516           OCHost
     1517    */
     1518#endif
     1519}
     1520
     1521/*************************************************************************
     1522 *      @       [SHLWAPI.240]
    5821523 *
    5831524 *      Calls ASCII or Unicode WindowProc for the given window.
     
    5891530        return DefWindowProcA(hWnd, uMessage, wParam, lParam);
    5901531}
    591 #ifndef __WIN32OS2__
    592 /*************************************************************************
    593  *      SHLWAPI_241     [SHLWAPI.241]
     1532
     1533/*************************************************************************
     1534 *      @       [SHLWAPI.241]
    5941535 *
    5951536 */
     
    5971538{
    5981539        FIXME("()stub\n");
    599         return 0xabba1243;
    600 }
    601 
    602 /*************************************************************************
    603  *      SHLWAPI_266     [SHLWAPI.266]
     1540        return /* 0xabba1243 */ 0;
     1541}
     1542
     1543/*************************************************************************
     1544 *      @       [SHLWAPI.266]
    6041545 */
    6051546DWORD WINAPI SHLWAPI_266 (
     
    6141555
    6151556/*************************************************************************
    616  *      SHLWAPI_267     [SHLWAPI.267]
     1557 *      @       [SHLWAPI.267]
    6171558 */
    6181559HRESULT WINAPI SHLWAPI_267 (
     
    6281569
    6291570/*************************************************************************
    630  *      SHLWAPI_268     [SHLWAPI.268]
     1571 *      @       [SHLWAPI.268]
    6311572 */
    6321573DWORD WINAPI SHLWAPI_268 (
     
    6391580
    6401581/*************************************************************************
    641  *      SHLWAPI_276     [SHLWAPI.276]
     1582 *      @       [SHLWAPI.276]
    6421583 *
    6431584 */
     
    6451586{
    6461587        FIXME("()stub\n");
    647         return 0xabba1244;
    648 }
    649 #endif
    650 /*************************************************************************
    651  *      SHLWAPI_278     [SHLWAPI.278]
    652  *
    653  */
    654 DWORD WINAPI SHLWAPI_278 (
     1588        return /* 0xabba1244 */ 0;
     1589}
     1590
     1591/*************************************************************************
     1592 *      @       [SHLWAPI.278]
     1593 *
     1594 */
     1595HWND WINAPI SHLWAPI_278 (
    6551596        LONG wndProc,
    6561597        HWND hWndParent,
     
    6651606        char * clsname = "WorkerA";
    6661607
    667         FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx)stub\n",
     1608        FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
    6681609          wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
    6691610
     
    6901631
    6911632/*************************************************************************
    692  *      SHLWAPI_289     [SHLWAPI.289]
     1633 *      @       [SHLWAPI.289]
    6931634 *
    6941635 * Late bound call to winmm.PlaySoundW
     
    7031644
    7041645/*************************************************************************
    705  *      SHLWAPI_313     [SHLWAPI.313]
     1646 *      @       [SHLWAPI.294]
     1647 */
     1648BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
     1649{
     1650    /*
     1651     * str1:            "I"     "I"     pushl esp+0x20
     1652     * str2:            "U"     "I"     pushl 0x77c93810
     1653     * (is "I" and "U" "integer" and "unsigned" ??)
     1654     *
     1655     * pStr:            ""      ""      pushl eax
     1656     * some_len:        0x824   0x104   pushl 0x824
     1657     * lpStr2:          "%l"    "%l"    pushl esp+0xc
     1658     *
     1659     * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
     1660     * LocalAlloc(0x00, some_len) -> irrelevant_var
     1661     * LocalAlloc(0x40, irrelevant_len) -> pStr
     1662     * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
     1663     * shlwapi.PathRemoveBlanksW(pStr);
     1664     */
     1665    ERR("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
     1666    return TRUE;
     1667}
     1668
     1669/*************************************************************************
     1670 *      @       [SHLWAPI.313]
    7061671 *
    7071672 * Late bound call to shell32.SHGetFileInfoW
     
    7171682
    7181683/*************************************************************************
    719  *      SHLWAPI_318     [SHLWAPI.318]
     1684 *      @       [SHLWAPI.318]
    7201685 *
    7211686 * Late bound call to shell32.DragQueryFileW
     
    7301695
    7311696/*************************************************************************
    732  *      SHLWAPI_333     [SHLWAPI.333]
     1697 *      @       [SHLWAPI.333]
    7331698 *
    7341699 * Late bound call to shell32.SHBrowseForFolderW
     
    7431708
    7441709/*************************************************************************
    745  *      SHLWAPI_334     [SHLWAPI.334]
     1710 *      @       [SHLWAPI.334]
    7461711 *
    7471712 * Late bound call to shell32.SHGetPathFromIDListW
     
    7561721
    7571722/*************************************************************************
    758  *      SHLWAPI_335     [SHLWAPI.335]
     1723 *      @       [SHLWAPI.335]
    7591724 *
    7601725 * Late bound call to shell32.ShellExecuteExW
     
    7691734
    7701735/*************************************************************************
    771  *      SHLWAPI_336     [SHLWAPI.336]
     1736 *      @       [SHLWAPI.336]
    7721737 *
    7731738 * Late bound call to shell32.SHFileOperationW.
     
    7821747
    7831748/*************************************************************************
    784  *      SHLWAPI_337     [SHLWAPI.337]
     1749 *      @       [SHLWAPI.337]
    7851750 *
    7861751 * Late bound call to shell32.ExtractIconExW.
     
    7941759  return pfnFunc(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
    7951760}
    796 #ifndef __WIN32OS2__
    797 //Bugbug: is forwarder for InterlockedCompareExchange
    798 /*************************************************************************
    799  *      SHLWAPI_342     [SHLWAPI.342]
     1761
     1762/*************************************************************************
     1763 *      @       [SHLWAPI.342]
    8001764 *
    8011765 */
    8021766DWORD WINAPI SHLWAPI_342 (
    803         LPVOID w,
    804         LPVOID x,
    805         LPVOID y,
    806         LPVOID z)
    807 {
    808         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
    809         return 0xabba1249;
    810 }
    811 #endif
    812 /*************************************************************************
    813  *      SHLWAPI_346     [SHLWAPI.346]
     1767        LPDWORD  w,   /* [out] location to put HKEY value???   */
     1768        HKEY     x,   /* [in]  appears to be HKEY_CURRENT_USER */
     1769        LPVOID y)
     1770{
     1771        FIXME("(%p 0x%08x %p)stub\n", w,x,y);
     1772        *w = (DWORD)x;
     1773        return /* 0xabba1249 */ 0;
     1774}
     1775
     1776/*************************************************************************
     1777 *      @       [SHLWAPI.346]
    8141778 */
    8151779DWORD WINAPI SHLWAPI_346 (
     
    8241788
    8251789/*************************************************************************
    826  *      SHLWAPI_357     [SHLWAPI.357]
     1790 *      @       [SHLWAPI.356]
     1791 */
     1792DWORD WINAPI SHLWAPI_356 (
     1793        LPVOID x,
     1794        LPVOID y,
     1795        LPVOID z)
     1796{
     1797        FIXME("(%p %p %p)stub\n", x,y,z);
     1798        return 0;
     1799}
     1800
     1801/*************************************************************************
     1802 *      @       [SHLWAPI.357]
    8271803 *
    8281804 * Late bound call to shell32.SHGetNewLinkInfoW
     
    8381814
    8391815/*************************************************************************
    840  *      SHLWAPI_358     [SHLWAPI.358]
     1816 *      @       [SHLWAPI.358]
    8411817 *
    8421818 * Late bound call to shell32.SHDefExtractIconW
     
    8531829
    8541830/*************************************************************************
    855  *      SHLWAPI_364     [SHLWAPI.364]
     1831 *      @       [SHLWAPI.364]
    8561832 *
    8571833 * Wrapper for lstrcpynA with src and dst swapped.
     
    8641840
    8651841/*************************************************************************
    866  *      SHLWAPI_370     [SHLWAPI.370]
     1842 *      @       [SHLWAPI.370]
    8671843 *
    8681844 * Late bound call to shell32.ExtractIconW
     
    8781854
    8791855/*************************************************************************
    880  *      SHLWAPI_376     [SHLWAPI.376]
    881  */
    882 DWORD WINAPI SHLWAPI_376 (LONG x)
    883 {
    884         FIXME("(0x%08lx)stub\n", x );
    885   /* FIXME: This should be a forward in the .spec file to the win2k function
    886    * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
    887    */
    888   return 0xabba1245;
    889 }
    890 #ifndef __WIN32OS2__
    891 /*************************************************************************
    892  *      SHLWAPI_377     [SHLWAPI.377]
    893  */
    894 DWORD WINAPI SHLWAPI_377 (LPVOID x, LPVOID y, LPVOID z)
    895 {
    896         FIXME("(%p %p %p)stub\n", x,y,z);
    897         return 0xabba1246;
    898 }
    899 #endif
    900 /*************************************************************************
    901  *      SHLWAPI_378     [SHLWAPI.378]
     1856 *      @       [SHLWAPI.376]
     1857 */
     1858LANGID WINAPI SHLWAPI_376 ()
     1859{
     1860    FIXME("() stub\n");
     1861    /* FIXME: This should be a forward in the .spec file to the win2k function
     1862     * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
     1863     */
     1864    return GetUserDefaultLangID();
     1865}
     1866
     1867/*************************************************************************
     1868 *      @       [SHLWAPI.377]
     1869 *
     1870 * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
     1871 *        each call here.
     1872 * FIXME: Native shows calls to:
     1873 *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
     1874 *                      CheckVersion
     1875 *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
     1876 *  RegQueryValueExA for "LPKInstalled"
     1877 *  RegCloseKey
     1878 *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
     1879 *  RegQueryValueExA for "ResourceLocale"
     1880 *  RegCloseKey
     1881 *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
     1882 *  RegQueryValueExA for "Locale"
     1883 *  RegCloseKey
     1884 *  and then tests the Locale ("en" for me).
     1885 *     code below
     1886 *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
     1887 */
     1888DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
     1889{
     1890    CHAR mod_path[2*MAX_PATH];
     1891    LPSTR ptr;
     1892
     1893    GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
     1894    ptr = strrchr(mod_path, '\\');
     1895    if (ptr) {
     1896        strcpy(ptr+1, new_mod);
     1897        TRACE("loading %s\n", debugstr_a(mod_path));
     1898        return (DWORD)LoadLibraryA(mod_path);
     1899    }
     1900    return 0;
     1901}
     1902
     1903/*************************************************************************
     1904 *      @       [SHLWAPI.378]
     1905 *
     1906 *  This is Unicode version of .377
    9021907 */
    9031908DWORD WINAPI SHLWAPI_378 (
    904         LPSTR x,
    905         LPVOID y, /* [???] 0x50000000 */
    906         LPVOID z) /* [???] 4 */
    907 {
    908         FIXME("(%s %p %p)stub\n", x,y,z);
    909         return LoadLibraryA(x);
    910 }
    911 
    912 /*************************************************************************
    913  *      SHLWAPI_389     [SHLWAPI.389]
     1909        LPCWSTR   new_mod,          /* [in] new module name        */
     1910        HMODULE   inst_hwnd,        /* [in] calling module handle  */
     1911        LPVOID z)                   /* [???] 4 */
     1912{
     1913    WCHAR mod_path[2*MAX_PATH];
     1914    LPWSTR ptr;
     1915
     1916    GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
     1917    ptr = strrchrW(mod_path, '\\');
     1918    if (ptr) {
     1919        strcpyW(ptr+1, new_mod);
     1920        TRACE("loading %s\n", debugstr_w(mod_path));
     1921        return (DWORD)LoadLibraryW(mod_path);
     1922    }
     1923    return 0;
     1924}
     1925
     1926/*************************************************************************
     1927 *      @       [SHLWAPI.389]
    9141928 *
    9151929 * Late bound call to comdlg32.GetSaveFileNameW
     
    9241938
    9251939/*************************************************************************
    926  *      SHLWAPI_390     [SHLWAPI.390]
     1940 *      @       [SHLWAPI.390]
    9271941 *
    9281942 * Late bound call to mpr.WNetRestoreConnectionW
     
    9381952
    9391953/*************************************************************************
    940  *      SHLWAPI_391     [SHLWAPI.391]
     1954 *      @       [SHLWAPI.391]
    9411955 *
    9421956 * Late bound call to mpr.WNetGetLastErrorW
     
    9531967
    9541968/*************************************************************************
    955  *      SHLWAPI_401     [SHLWAPI.401]
     1969 *      @       [SHLWAPI.401]
    9561970 *
    9571971 * Late bound call to comdlg32.PageSetupDlgW
     
    9661980
    9671981/*************************************************************************
    968  *      SHLWAPI_402     [SHLWAPI.402]
     1982 *      @       [SHLWAPI.402]
    9691983 *
    9701984 * Late bound call to comdlg32.PrintDlgW
     
    9791993
    9801994/*************************************************************************
    981  *      SHLWAPI_403     [SHLWAPI.403]
     1995 *      @       [SHLWAPI.403]
    9821996 *
    9831997 * Late bound call to comdlg32.GetOpenFileNameW
     
    10442058
    10452059/*************************************************************************
    1046  *      SHLWAPI_431     [SHLWAPI.431]
     2060 *      @       [SHLWAPI.413]
     2061 *
     2062 * Function unknown seems to always to return 0
     2063 */
     2064DWORD WINAPI SHLWAPI_413 (DWORD x)
     2065{
     2066        FIXME("(0x%08lx)stub\n", x);
     2067        return 0;
     2068}
     2069
     2070/*************************************************************************
     2071 *      @       [SHLWAPI.431]
    10472072 */
    10482073DWORD WINAPI SHLWAPI_431 (DWORD x)
     
    10542079#ifndef __WIN32OS2__
    10552080/*************************************************************************
    1056  *      SHLWAPI_437     [SHLWAPI.437]
     2081 *      @       [SHLWAPI.437]
    10572082 *
    10582083 * NOTES
    1059  *  In the real shlwapi, One time initilisation calls GetVersionEx and reads
     2084 *  In the real shlwapi, One time initialisation calls GetVersionEx and reads
    10602085 *  the registry to determine what O/S & Service Pack level is running, and
    10612086 *  therefore which functions are available. Currently we always run as NT,
     
    10682093{
    10692094        FIXME("(0x%08lx)stub\n", functionToCall);
    1070         return 0xabba1247;
     2095        return /* 0xabba1247 */ 0;
    10712096}
    10722097#endif
     2098/*************************************************************************
     2099 *      ColorRGBToHLS   [SHLWAPI.445]
     2100 *
     2101 * Convert from RGB COLORREF into the HLS color space.
     2102 *
     2103 * NOTES
     2104 * Input HLS values are constrained to the range (0..240).
     2105 */
     2106VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue,
     2107                          LPWORD wLuminance, LPWORD pwSaturation)
     2108{
     2109    FIXME("stub\n");
     2110    return;
     2111}
    10732112
    10742113/*************************************************************************
     
    10822121
    10832122/*************************************************************************
    1084  *      SHGetInverseCMAP
     2123 *      SHGetInverseCMAP (SHLWAPI.@)
    10852124 */
    10862125DWORD WINAPI SHGetInverseCMAP (LPVOID x, DWORD why)
     
    10892128        return 0;
    10902129}
     2130
    10912131#ifndef __WIN32OS2__
    10922132/*************************************************************************
     
    10992139}
    11002140#endif
    1101 
    11022141/*************************************************************************
    11032142 *      GetMenuPosFromID        [SHLWAPI.@]
     
    11192158
    11202159/*************************************************************************
    1121  *      _SHGetInstanceExplorer  [SHLWAPI.@]
     2160 *      _SHGetInstanceExplorer@4        [SHLWAPI.@]
    11222161 *
    11232162 * Late bound call to shell32.SHGetInstanceExplorer.
  • trunk/src/shlwapi/ordinal_odin.cpp

    r6615 r7820  
    1 /* $Id: ordinal_odin.cpp,v 1.4 2001-08-31 19:56:34 phaller Exp $ */
     1/* $Id: ordinal_odin.cpp,v 1.5 2002-02-06 20:18:27 sandervl Exp $ */
    22
    33/*
     
    6868
    6969
     70#if 0
    7071/*****************************************************************************
    7172 * Prototypes                                                                *
     
    7475HANDLE WIN32API SHLWAPI_11(HANDLE, DWORD, DWORD, DWORD, DWORD);
    7576
    76 
    77 #define debugstr_guid(a) a
    7877
    7978
     
    269268  return NO_ERROR;
    270269}
    271 
    272 
    273 /*****************************************************************************
    274  * Name      : ParseURLIntoProtocolAndURI_W
    275  * Purpose   :
    276  * Parameters:
    277  * Variables :
    278  * Result    :
    279  * Remark    :
    280  * Status    : UNTESTED
    281  *
    282  * Author    : Patrick Haller [2001-08-30]
    283  *****************************************************************************/
    284 
    285 ODINFUNCTION2(DWORD,              SHLWAPI_2,
    286               LPWSTR,             lpszURL,
    287               LPPROTOCOLHANDLERW, lpHandler)
    288 {
    289   dprintf(("not yet implemented"));
    290 
    291   // PH: do unicode conversion, call SHLWAPI_1
    292 
    293   return 0;
    294 }
     270#endif
     271
    295272
    296273
     
    424401}
    425402
     403
     404
     405
     406
     407/*****************************************************************************
     408 * Name      : ???
     409 * Purpose   : Looks like a strdup()
     410 * Parameters: Unknown (wrong)
     411 * Variables :
     412 * Result    : Unknown
     413 * Remark    :
     414 * Status    : UNTESTED STUB
     415 *
     416 * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
     417 *****************************************************************************/
     418
     419ODINFUNCTION2(DWORD,SHLWAPI_12,
     420              DWORD,arg0,
     421              DWORD,arg1)
     422{
     423  dprintf(("not implemented, explorer.exe will trap now"));
     424
     425  return 0;
     426}
     427
     428
     429
     430
    426431/*****************************************************************************
    427432 * Name      : ???
     
    436441 *****************************************************************************/
    437442
    438 ODINFUNCTION3(DWORD,SHLWAPI_7,
     443ODINFUNCTION2(DWORD,SHLWAPI_17,
    439444              DWORD, arg0,
    440               DWORD, arg1,
    441               DWORD, arg2)
    442 {
    443   HANDLE hMap;
    444   LPVOID lpMap;
    445   DWORD  dwResult;
    446 
    447   dprintf(("not implemented"));
    448 
    449   // create mapping
    450   hMap = CreateFileMappingA(-1,
    451                             NULL,
    452                             PAGE_READWRITE,
    453                             0,
    454                             arg1,
    455                             0);
    456   if (hMap == NULL)
    457     return FALSE;
    458 
    459   // now map the thing
    460   lpMap = MapViewOfFile(hMap,
    461                         FILE_MAP_READ | FILE_MAP_WRITE,
    462                         0,
    463                         0,
    464                         0);
    465   if (lpMap == NULL)
    466   {
    467     CloseHandle(hMap);
    468     return FALSE;
    469   }
    470 
    471   /*  @@@PH copy someting into the shared segment */
    472 
    473   UnmapViewOfFile(lpMap);
    474   dwResult = SHLWAPI_11(hMap,
    475                         GetCurrentProcessId(),
    476                         arg2,
    477                         FILE_MAP_ALL_ACCESS,
    478                         2);
    479   CloseHandle(hMap);
    480 
    481   return dwResult;
    482 }
     445              DWORD, arg1)
     446{
     447  dprintf(("not implemented, explorer.exe will trap now"));
     448
     449  return 0;
     450}
     451
     452
    483453
    484454
     
    495465 *****************************************************************************/
    496466
    497 ODINFUNCTION2(DWORD,  SHLWAPI_8,
    498               HANDLE, hMap,
    499               DWORD,  arg1)
    500 {
    501   HANDLE hHandle;
    502   LPVOID lpBase;
    503 
    504   hHandle = SHLWAPI_11(hMap,
    505                        arg1,
    506                        GetCurrentProcessId(),
    507                        FILE_MAP_ALL_ACCESS,
    508                        0);
    509   lpBase = MapViewOfFile(hHandle,
    510                          FILE_MAP_READ | FILE_MAP_WRITE,
    511                          0,
    512                          0,
    513                          0);
    514   CloseHandle(hHandle);
    515 
    516   if (lpBase == NULL)
    517     return NULL;
    518   else
    519     return (DWORD)lpBase+4; // lea eax, [ebx + 4]
    520 }
    521 
    522 
    523 /*****************************************************************************
    524  * Name      :
    525  * Purpose   :
    526  * Parameters:
    527  * Variables :
    528  * Result    :
    529  * Remark    :
    530  * Status    : COMPLETELY IMPLEMENTED UNTESTED
    531  *
    532  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    533  *****************************************************************************/
    534 
    535 ODINFUNCTION1(DWORD,  SHLWAPI_9,
    536               LPBYTE, lpBase)
    537 {
    538   return (UnmapViewOfFile( (LPVOID) ((DWORD)lpBase & 0xFFFFFFFC)) );
    539 }
    540 
    541 
    542 /*****************************************************************************
    543  * Name      : ???
    544  * Purpose   :
    545  * Parameters:
    546  * Variables :
    547  * Result    :
    548  * Remark    :
    549  * Status    : COMPLETELY IMPLEMENTED UNTESTED
    550  *
    551  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    552  *****************************************************************************/
    553 
    554 ODINFUNCTION2(DWORD,  SHLWAPI_10,
    555               HANDLE, hMap,
    556               DWORD,  arg1)
    557 {
    558   HANDLE hHandle;
    559 
    560   hHandle = SHLWAPI_11(hMap,
    561                        arg1,
    562                        GetCurrentProcessId(),
    563                        FILE_MAP_ALL_ACCESS,
    564                        1);
    565   return CloseHandle(hHandle);
    566 }
    567 
    568 
    569 /*****************************************************************************
    570  * Name      :
    571  * Purpose   : Duplicate the handle to the shell shared segment
    572  * Parameters:
    573  * Variables :
    574  * Result    :
    575  * Remark    : SHLWAPI.11 - wrong implementation, check again
    576  * Status    : UNTESTED STUB
    577  *
    578  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    579  *****************************************************************************/
    580 
    581 ODINFUNCTION5(HANDLE, SHLWAPI_11,
    582               HANDLE, hMap,
    583               DWORD,  dwProcessDest,
    584               DWORD,  dwCurrentPID,
    585               DWORD,  dwAccess,
    586               DWORD,  dwFlag)
    587 {
    588   dprintf(("not implemented, explorer.exe will trap now"));
    589 
    590   DWORD  dwMyPID = GetCurrentProcessId();
    591   HANDLE hProcess;
    592   HANDLE hTargetHandle;
    593   HANDLE hTargetProcessHandle = dwProcessDest;
    594   BOOL   fResult;
    595 
    596   // open desired process
    597   if (dwMyPID == dwProcessDest)
    598     hProcess == GetCurrentProcess();
    599   else
    600     hProcess == OpenProcess(PROCESS_DUP_HANDLE,
    601                             FALSE,
    602                             dwProcessDest);
    603 
    604   // verify result
    605   if (hProcess == NULL)
    606     return 0;
    607 
    608   // duplicate handle
    609   fResult = DuplicateHandle(hProcess,
    610                             hMap,
    611                             hTargetProcessHandle,
    612                             &hTargetHandle,
    613                             dwAccess,
    614                             0,
    615                             dwFlag | 0x02);
    616   //CloseHandle()
    617 
    618   return fResult;
    619 }
    620 
    621 
    622 /*****************************************************************************
    623  * Name      : ???
    624  * Purpose   : Looks like a strdup()
    625  * Parameters: Unknown (wrong)
    626  * Variables :
    627  * Result    : Unknown
    628  * Remark    :
    629  * Status    : UNTESTED STUB
    630  *
    631  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    632  *****************************************************************************/
    633 
    634 ODINFUNCTION2(DWORD,SHLWAPI_12,
    635               DWORD,arg0,
    636               DWORD,arg1)
    637 {
    638   dprintf(("not implemented, explorer.exe will trap now"));
    639 
    640   return 0;
    641 }
    642 
    643 
    644 /*****************************************************************************
    645  * Name      : ???
    646  * Purpose   : Unknown (used by explorer.exe)
    647  * Parameters:
    648  * Variables :
    649  * Result    : Unknown
    650  * Remark    :
    651  * Status    : UNTESTED STUB
    652  *
    653  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    654  *****************************************************************************/
    655 
    656 ODINFUNCTION2(DWORD,SHLWAPI_13,
    657               DWORD, arg0,
    658               DWORD, arg1)
    659 {
    660   dprintf(("not implemented, explorer.exe will trap now"));
    661 
    662   return 0;
    663 }
    664 
    665 
    666 /*****************************************************************************
    667  * Name      : ???
    668  * Purpose   : Unknown (used by explorer.exe)
    669  * Parameters: Unknown (wrong)
    670  * Variables :
    671  * Result    : Unknown
    672  * Remark    :
    673  * Status    : UNTESTED STUB
    674  *
    675  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    676  *****************************************************************************/
    677 
    678 ODINFUNCTION2(DWORD,SHLWAPI_14,
    679               DWORD, arg0,
    680               DWORD, arg1)
    681 {
    682   dprintf(("not implemented, explorer.exe will trap now"));
    683 
    684   return 0;
    685 }
    686 
    687 
    688 /*****************************************************************************
    689  * Name      : ???
    690  * Purpose   : Unknown (used by explorer.exe)
    691  * Parameters: Unknown (wrong)
    692  * Variables :
    693  * Result    : Unknown
    694  * Remark    :
    695  * Status    : UNTESTED STUB
    696  *
    697  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    698  *****************************************************************************/
    699 
    700 ODINFUNCTION2(DWORD,SHLWAPI_15,
    701               DWORD, arg0,
    702               DWORD, arg1)
    703 {
    704   dprintf(("not implemented, explorer.exe will trap now"));
    705 
    706   return 0;
    707 }
    708 
    709 
    710 /*****************************************************************************
    711  * Name      : ???
    712  * Purpose   : Unknown (used by explorer.exe)
    713  * Parameters: Unknown (wrong)
    714  * Variables :
    715  * Result    : Unknown
    716  * Remark    : SHLWAPI.16
    717  * Status    : UNTESTED STUB
    718  *
    719  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    720  *****************************************************************************/
    721 
    722 ODINFUNCTION4(HANDLE,SHCreateThread,
    723               DWORD, arg0,
    724               DWORD, arg1,
    725               DWORD, arg2,
    726               DWORD, arg3)
    727 {
    728   dprintf(("not implemented, explorer.exe will trap now"));
    729 
    730   return 0;
    731 }
    732 
    733 
    734 /*****************************************************************************
    735  * Name      : ???
    736  * Purpose   : Unknown (used by explorer.exe)
    737  * Parameters: Unknown (wrong)
    738  * Variables :
    739  * Result    : Unknown
    740  * Remark    :
    741  * Status    : UNTESTED STUB
    742  *
    743  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    744  *****************************************************************************/
    745 
    746 ODINFUNCTION2(DWORD,SHLWAPI_17,
    747               DWORD, arg0,
    748               DWORD, arg1)
    749 {
    750   dprintf(("not implemented, explorer.exe will trap now"));
    751 
    752   return 0;
    753 }
    754 
    755 
    756 /*****************************************************************************
    757  * Name      : ???
    758  * Purpose   : Unknown (used by explorer.exe)
    759  * Parameters: Unknown (wrong)
    760  * Variables :
    761  * Result    : Unknown
    762  * Remark    :
    763  * Status    : UNTESTED STUB
    764  *
    765  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    766  *****************************************************************************/
    767 
    768 ODINFUNCTION2(DWORD,SHLWAPI_18,
    769               DWORD, arg0,
    770               DWORD, arg1)
    771 {
    772   dprintf(("not implemented, explorer.exe will trap now"));
    773 
    774   return 0;
    775 }
    776 
    777 
    778 /*****************************************************************************
    779  * Name      : SHLWAPI_19
    780  * Purpose   : Free memory
    781  * Parameters: LPVOID lpMem
    782  * Variables :
    783  * Result    :
    784  * Remark    : SHLWAPI.19
    785  * Status    : COMPLETELY IMPLEMENTED ? UNTESTED
    786  *
    787  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    788  *****************************************************************************/
    789 
    790 ODINPROCEDURE1(SHLWAPI_19,
    791                HLOCAL, hMem)
    792 {
    793   if (hMem != NULL)
    794     LocalFree(hMem);
    795 }
    796 
    797 
    798 /*****************************************************************************
    799  * Name      : ???
    800  * Purpose   : Unknown (used by explorer.exe)
    801  * Parameters: Unknown (wrong)
    802  * Variables :
    803  * Result    : Unknown
    804  * Remark    :
    805  * Status    : UNTESTED STUB
    806  *
    807  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    808  *****************************************************************************/
    809 
    810467ODINFUNCTION2(DWORD,SHLWAPI_20,
    811468              DWORD, arg0,
     
    818475
    819476
    820 /*****************************************************************************
    821  * Name      : ???
    822  * Purpose   : Unknown (used by explorer.exe)
    823  * Parameters: Unknown (wrong)
    824  * Variables :
    825  * Result    : Unknown
    826  * Remark    :
    827  * Status    : UNTESTED STUB
    828  *
    829  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    830  *****************************************************************************/
    831 
    832 ODINFUNCTION2(DWORD,SHLWAPI_21,
    833               DWORD, arg0,
    834               DWORD, arg1)
    835 {
    836   dprintf(("not implemented, explorer.exe will trap now"));
    837 
    838   return 0;
    839 }
    840 
    841 
    842 /*****************************************************************************
    843  * Name      : ???
    844  * Purpose   : Unknown (used by explorer.exe)
    845  * Parameters: Unknown (wrong)
    846  * Variables :
    847  * Result    : Unknown
    848  * Remark    :
    849  * Status    : UNTESTED STUB
    850  *
    851  * Author    : Patrick Haller [Sun, 2000/06/09 04:47]
    852  *****************************************************************************/
    853 
    854 ODINFUNCTION2(DWORD,SHLWAPI_22,
    855               DWORD, arg0,
    856               DWORD, arg1)
    857 {
    858   dprintf(("not implemented, explorer.exe will trap now"));
    859 
    860   return 0;
    861 }
    862 
    863 
    864 
    865 
    866 /*****************************************************************************
    867  * Name      : SHLWAPI_28
    868  * Purpose   :
    869  * Parameters:
    870  * Variables :
    871  * Result    :
    872  * Remark    :
    873  * Status    : UNTESTED STUB
    874  *
    875  * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
    876  *****************************************************************************/
    877 
    878 ODINFUNCTION1(DWORD,SHLWAPI_28,
    879               DWORD,arg0)
    880 {
    881   dprintf(("not yet implemented"));
    882 
    883   return 0;
    884 }
    885 
    886 
    887 
    888 
    889 
    890 
    891 /*****************************************************************************
    892  * Name      : DWORD SHLWAPI_158
    893  * Purpose   : Case-ignoring wide string compare
    894  * Parameters: LPSTR lpStr1
    895  *             LPSTR lpStr2
    896  * Variables :
    897  * Result    : case-insensitive comparsion result between the two strings
    898  * Remark    : SHLWAPI.158
    899  * Status    : COMPLETELY IMPLEMENTED UNTESTED
    900  *
    901  * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
    902  *****************************************************************************/
    903 
    904 ODINFUNCTION2(int,     SHLWAPI_158,
    905               LPWSTR,  lpStr1,
    906               LPWSTR,  lpStr2)
    907 {
    908   WCHAR ch1;
    909   WCHAR ch2;
    910   int   res;
    911 
    912   for (;
    913 
    914        *lpStr1 != 0;
    915 
    916        lpStr1++,
    917        lpStr2++)
    918   {
    919     ch1 = *lpStr1;
    920     ch2 = *lpStr2;
    921 
    922     /* ignore case of characters */
    923     if ( (ch1 >= 'A') && (ch1 <= 'Z')) ch1 += 0x20;
    924     if ( (ch2 >= 'A') && (ch2 <= 'Z')) ch1 += 0x20;
    925 
    926     /* compare characters */
    927     res = ch1 - ch2;
    928     if (res)
    929       return res;
    930   }
    931 
    932   /* OK, strings compared til end of string1 */
    933   return 0;
    934 }
     477
     478
     479
     480
    935481
    936482
     
    1121667
    1122668
    1123 /*************************************************************************
    1124 *      SHLWAPI_219 [SHLWAPI]
    1125 */
    1126 ODINFUNCTION4(HRESULT, SHLWAPI_219,
    1127               LPVOID,  w, /* returned by LocalAlloc */
    1128               LPVOID,  x,
    1129               LPVOID,  y,
    1130               LPWSTR,  z) /* OUT: path */
    1131 {
    1132   FIXME("(%p %p %p %p)stub\n",w,x,y,z);
    1133   return 0xabba1252;
    1134 }
    1135 
    1136 
    1137 
    1138 
    1139 
    1140 /*************************************************************************
    1141 *      SHLWAPI_241 [SHLWAPI]
    1142 *
    1143 */
    1144 ODINFUNCTION0(DWORD, SHLWAPI_241)
    1145 {
    1146   FIXME("()stub\n");
    1147   return 0xabba1243;
    1148 }
    1149 
    1150669
    1151670/*****************************************************************************
     
    1171690  return 0;
    1172691}
    1173 
    1174 
    1175 /*************************************************************************
    1176 *      SHLWAPI_266 [SHLWAPI]
    1177 */
    1178 ODINFUNCTION4(DWORD,  SHLWAPI_266,
    1179               LPVOID, w,
    1180               LPVOID, x,
    1181               LPVOID, y,
    1182               LPVOID, z)
    1183 {
    1184   FIXME("(%p %p %p %p)stub\n",w,x,y,z);
    1185   return 0xabba1248;
    1186 }
    1187 
    1188 /*************************************************************************
    1189 *      SHLWAPI_267 [SHLWAPI]
    1190 */
    1191 ODINFUNCTION4(HRESULT, SHLWAPI_267,
    1192               LPVOID,  w, /* same as 1th parameter of SHLWAPI_219 */
    1193               LPVOID,  x, /* same as 2nd parameter of SHLWAPI_219 */
    1194               LPVOID,  y,
    1195               LPVOID,  z)
    1196 {
    1197   FIXME("(%p %p %p %p)stub\n",w,x,y,z);
    1198   *((LPDWORD)z) = 0xabba1200;
    1199   return 0xabba1254;
    1200 }
    1201 
    1202 /*************************************************************************
    1203 *      SHLWAPI_268 [SHLWAPI]
    1204 */
    1205 ODINFUNCTION2(DWORD,  SHLWAPI_268,
    1206               LPVOID, w,
    1207               LPVOID, x)
    1208 {
    1209   FIXME("(%p %p)\n",w,x);
    1210   return 0xabba1251; /* 0 = failure */
    1211 }
    1212 
    1213 /*************************************************************************
    1214 *      SHLWAPI_276 [SHLWAPI]
    1215 
    1216 * dynamically load SHELL32.DllGetVersion
    1217 *
    1218 */
    1219 ODINFUNCTION0(DWORD, SHLWAPI_276)
    1220 {
    1221   FIXME("()stub\n");
    1222   return 0xabba1244;
    1223 }
    1224 
    1225 /*****************************************************************************
    1226  * Name      : DWORD SHLWAPI_376
    1227  * Purpose   : Try to determine user interface language
    1228  * Parameters:
    1229  * Variables :
    1230  * Result    :
    1231  * Remark    : SHLWAPI.366
    1232  * Status    : PARTIALLY IMPLEMENTED UNTESTED
    1233  *
    1234  * Author    : Patrick Haller [Sun, 2000/06/10 04:02]
    1235  *****************************************************************************/
    1236 
    1237 ODINFUNCTION0(DWORD, SHLWAPI_376)
    1238 {
    1239   /* Microsoft does a hell of a job here: looks for
    1240    * - Internet Explorer
    1241    * - Office
    1242    * - Lpk ?
    1243    * - Resource Locales
    1244    * - etc.
    1245    */
    1246 
    1247   return 0x0409; // @@@PH maybe this is 'nuf for now.
    1248 }
    1249 
    1250 
    1251 
    1252 /*************************************************************************
    1253 *      SHLWAPI_377 [SHLWAPI]
    1254 */
    1255 ODINFUNCTION3(DWORD,   SHLWAPI_377,
    1256               LPSTR,   lpstrModule,
    1257               HMODULE, hModule,
    1258               LPVOID,  z)
    1259 {
    1260   static BOOL flagSHLWAPI_377Initialized       = FALSE;
    1261   static BOOL flagInternetExplorerCheckVersion = FALSE;
    1262 
    1263   dprintf(("not (properly) implemented.\n"));
    1264 
    1265   char szModuleName[260]; // MAXPATHLEN
    1266   HMODULE hModLanguage;
    1267 
    1268   // initialize this subsystem
    1269   if (flagSHLWAPI_377Initialized == FALSE)
    1270   {
    1271     flagSHLWAPI_377Initialized = TRUE;
    1272 
    1273     flagInternetExplorerCheckVersion =
    1274     SHRegGetBoolUSValueA("Software\\Microsoft\\Internet Explorer\\International",
    1275                          "CheckVersion",
    1276                          1,
    1277                          1);
    1278   }
    1279 
    1280   if (lpstrModule == NULL) // Garbage in - garbage out
    1281     return 0;
    1282 
    1283   if (0 == GetModuleFileNameA(hModule,
    1284                               szModuleName,
    1285                               sizeof(szModuleName)))
    1286   {
    1287     // treat error
    1288   }
    1289   else
    1290   {
    1291     PathRemoveFileSpecA(szModuleName);
    1292     PathAppendA(szModuleName,
    1293                 lpstrModule);
    1294     // @@@PH twiddle around with the current IE codepage
    1295     hModLanguage = LoadLibraryA(szModuleName);
    1296   }
    1297 
    1298 
    1299   return hModLanguage;
    1300 }
    1301 
    1302692
    1303693/*****************************************************************************
  • trunk/src/shlwapi/path.c

    r7508 r7820  
    22 * Path Functions
    33 */
    4 #ifdef __WIN32OS2__
    5 #include <odin.h>
    6 #include <odinwrap.h>
    7 #include <os2sel.h>
    8 
    9 #include <string.h>
    10 #include <wctype.h>
    11 #include <wcstr.h>
    12 #define HAVE_WCTYPE_H
    13 #include <win\shlwapi.h>
    14 
    15 #include <heapstring.h>
    16 #include <wine\undocshell.h>
    17 #endif
    184
    195#include <ctype.h>
    206#include <string.h>
     7#include <stdlib.h>
    218
    229#include "winerror.h"
     
    2512#include "wingdi.h"
    2613#include "winuser.h"
     14#include "winreg.h"
     15#define NO_SHLWAPI_STREAM
    2716#include "shlwapi.h"
    2817#include "debugtools.h"
    29 
     18#include "ordinal.h"
    3019
    3120DEFAULT_DEBUG_CHANNEL(shell);
     21
     22INT __cdecl _wtoi(LPWSTR string);
    3223
    3324#define isSlash(x) ((x)=='\\' || (x)=='/')
     
    453444
    454445/*************************************************************************
    455  * PathStripPathA       [SHELLWAPI.@]
     446 * PathStripPathA       [SHLWAPI.@]
    456447 *
    457448 * NOTES
     
    469460
    470461/*************************************************************************
    471  * PathStripPathW       [SHELLWAPI.@]
     462 * PathStripPathW       [SHLWAPI.@]
    472463 */
    473464void WINAPI PathStripPathW(LPWSTR lpszPath)
     
    747738{
    748739        LPSTR lpstrComma = strchr(lpszPath, ',');
    749        
    750         FIXME("%s stub\n", debugstr_a(lpszPath));
     740        int ret = 0;
     741       
     742        TRACE("%s\n", debugstr_a(lpszPath));
    751743
    752744        if (lpstrComma && lpstrComma[1])
    753745        {
    754746          lpstrComma[0]='\0';
    755 /*        return atoi(&lpstrComma[1]);  FIXME */
     747          ret = atoi(&lpstrComma[1]);
    756748        }
    757749       
    758750        PathUnquoteSpacesA(lpszPath);
    759         return 0;
     751        return ret;
    760752}
    761753
     
    766758{
    767759        LPWSTR lpstrComma = strchrW(lpszPath, ',');
    768        
    769         FIXME("%s stub\n", debugstr_w(lpszPath));
     760        int ret = 0;
     761       
     762        TRACE("%s\n", debugstr_w(lpszPath));
    770763
    771764        if (lpstrComma && lpstrComma[1])
    772765        {
    773766          lpstrComma[0]='\0';
    774 /*        return _wtoi(&lpstrComma[1]); FIXME */
     767          ret = _wtoi(&lpstrComma[1]);
    775768        }
    776769        PathUnquoteSpacesW(lpszPath);
    777         return 0;
     770        return ret;
    778771}
    779772
     
    785778 * PathFindOnPathA      [SHLWAPI.@]
    786779 */
    787 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
    788 {
    789         FIXME("%s %s\n",sFile, sOtherDirs);
     780BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR *sOtherDirs)
     781{
     782        FIXME("%s %p\n",sFile, sOtherDirs);
    790783        return FALSE;
    791784}
     
    794787 * PathFindOnPathW      [SHLWAPI.@]
    795788 */
    796 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
    797 {
    798         FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
     789BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR *sOtherDirs)
     790{
     791        FIXME("%s %p\n",debugstr_w(sFile), sOtherDirs);
    799792        return FALSE;
    800793}
     
    11181111            if (lpszPath1[pos]=='\\') bsfound++;
    11191112            if (bsfound == 2) return TRUE;
    1120             pos++; /* fixme: use CharNext*/
     1113            pos++; /* FIXME: use CharNext*/
    11211114          }
    11221115          return (lpszPath1[pos] == lpszPath2[pos]);
     
    11501143            if (lpszPath1[pos]=='\\') bsfound++;
    11511144            if (bsfound == 2) return TRUE;
    1152             pos++;/* fixme: use CharNext*/
     1145            pos++;/* FIXME: use CharNext*/
    11531146          }
    11541147          return (lpszPath1[pos] == lpszPath2[pos]);
     
    11581151
    11591152/*************************************************************************
    1160  * PathIsURLA
     1153 * PathIsURLA (SHLWAPI.@)
    11611154 */
    11621155BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
    11631156{
    1164   // 2001-08-30 PH
    1165   // SHLWAPI/W95 Code:
    1166   //
    1167   // if (lpstrPath == NULL)
    1168   //   return FALSE;
    1169   //
    1170   // DWORD dwUnknown = SHREG_xxx; // 0x18
    1171   // return SHLWAPI_1(lpstrPath, &dwUnknown);
    1172  
    1173  
    1174         LPSTR lpstrRes;
    1175         int iSize, i=0;
    1176         static LPSTR SupportedProtocol[] =
    1177           {"http","https","ftp","gopher","file","mailto",NULL};
    1178 
    1179         if(!lpstrPath) return FALSE;
    1180 
    1181         /* get protocol        */
    1182         lpstrRes = strchr(lpstrPath,':');
    1183         if(!lpstrRes) return FALSE;
    1184         iSize = lpstrRes - lpstrPath;
    1185 
    1186         while(SupportedProtocol[i])
    1187         {
    1188           if (iSize == strlen(SupportedProtocol[i]))
    1189             if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize))
    1190               return TRUE;
    1191           i++;
    1192         }
    1193 
    1194         return FALSE;
     1157    UNKNOWN_SHLWAPI_1 base;
     1158    DWORD res1;
     1159
     1160    if (!lpstrPath || !*lpstrPath) return FALSE;
     1161
     1162    /* get protocol        */
     1163    base.size = 24;
     1164    res1 = SHLWAPI_1(lpstrPath, &base);
     1165    return (base.fcncde) ? TRUE : FALSE;
    11951166
    11961167
    11971168/*************************************************************************
    1198  * PathIsURLW
     1169 * PathIsURLW (SHLWAPI.@)
    11991170 */
    12001171BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
    12011172{
    1202         LPWSTR lpstrRes;
    1203         int iSize, i=0;
    1204         static WCHAR SupportedProtocol[7][7] =
    1205           {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
    1206           {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
    1207           {'m','a','i','l','t','o','\0'},{0}};
    1208 
    1209         if(!lpstrPath) return FALSE;
    1210 
    1211         /* get protocol        */
    1212         lpstrRes = strchrW(lpstrPath,':');
    1213         if(!lpstrRes) return FALSE;
    1214         iSize = lpstrRes - lpstrPath;
    1215 
    1216         while(SupportedProtocol[i])
    1217         {
    1218           if (iSize == strlenW(SupportedProtocol[i]))
    1219             if(!strncmpiW(lpstrPath, SupportedProtocol[i], iSize))
    1220               return TRUE;
    1221           i++;
    1222         }
    1223 
    1224         return FALSE;
     1173    UNKNOWN_SHLWAPI_2 base;
     1174    DWORD res1;
     1175
     1176    if (!lpstrPath || !*lpstrPath) return FALSE;
     1177
     1178    /* get protocol        */
     1179    base.size = 24;
     1180    res1 = SHLWAPI_2(lpstrPath, &base);
     1181    return (base.fcncde) ? TRUE : FALSE;
    12251182
    12261183
     
    13021259 */
    13031260BOOL WINAPI PathIsUNCServerA(
    1304         LPCSTR pszPath)
    1305 {
    1306         FIXME("%s\n", pszPath);
     1261        LPCSTR lpszPath)
     1262{
     1263        TRACE("%s\n", debugstr_a(lpszPath));
     1264        if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
     1265        {
     1266          int foundbackslash = 0;
     1267          lpszPath += 2;
     1268          while (*lpszPath)
     1269          {
     1270            if (*lpszPath=='\\') foundbackslash++;
     1271            lpszPath = CharNextA(lpszPath);
     1272          }
     1273          if (foundbackslash == 0)
     1274            return TRUE;
     1275        }
    13071276        return FALSE;
    13081277}
     
    13121281 */
    13131282BOOL WINAPI PathIsUNCServerW(
    1314         LPCWSTR pszPath)
    1315 {
    1316         FIXME("%s\n", debugstr_w(pszPath));
     1283        LPCWSTR lpszPath)
     1284{
     1285        TRACE("%s\n", debugstr_w(lpszPath));
     1286        if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
     1287        {
     1288          int foundbackslash = 0;
     1289          lpszPath += 2;
     1290          while (*lpszPath)
     1291          {
     1292            if (*lpszPath=='\\') foundbackslash++;
     1293            lpszPath = CharNextW(lpszPath);
     1294          }
     1295          if (foundbackslash == 0)
     1296            return TRUE;
     1297        }
    13171298        return FALSE;
    13181299}
     
    13221303 */
    13231304BOOL WINAPI PathIsUNCServerShareA(
    1324         LPCSTR pszPath)
    1325 {
    1326         FIXME("%s\n", pszPath);
     1305        LPCSTR lpszPath)
     1306{
     1307        TRACE("%s\n", debugstr_a(lpszPath));
     1308        if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
     1309        {
     1310          int foundbackslash = 0;
     1311          lpszPath += 2;
     1312          while (*lpszPath)
     1313          {
     1314            if (*lpszPath=='\\') foundbackslash++;
     1315            lpszPath = CharNextA(lpszPath);
     1316          }
     1317          if (foundbackslash == 1)
     1318            return TRUE;
     1319        }
    13271320        return FALSE;
    13281321}
     
    13321325 */
    13331326BOOL WINAPI PathIsUNCServerShareW(
    1334         LPCWSTR pszPath)
    1335 {
    1336         FIXME("%s\n", debugstr_w(pszPath));
     1327        LPCWSTR lpszPath)
     1328{
     1329        TRACE("%s\n", debugstr_w(lpszPath));
     1330        if (lpszPath[0]=='\\' && lpszPath[1]=='\\')             
     1331        {
     1332          int foundbackslash = 0;
     1333          lpszPath += 2;
     1334          while (*lpszPath)
     1335          {
     1336            if (*lpszPath=='\\') foundbackslash++;
     1337            lpszPath = CharNextW(lpszPath);
     1338          }
     1339          if (foundbackslash == 1)
     1340            return TRUE;
     1341        }
    13371342        return FALSE;
    13381343}
     
    16931698BOOL WINAPI PathRenameExtensionA(LPSTR pszPath, LPCSTR pszExt)
    16941699{
    1695         FIXME("%s %s\n", pszPath, pszExt);
    1696         return FALSE;
     1700        LPSTR pszExtension = PathFindExtensionA(pszPath);
     1701
     1702        if (!pszExtension) return FALSE;
     1703        if (pszExtension-pszPath + strlen(pszExt) > MAX_PATH) return FALSE;
     1704
     1705        strcpy(pszExtension, pszExt);
     1706        TRACE("%s\n", pszPath);
     1707        return TRUE;
    16971708}
    16981709
     
    17021713BOOL WINAPI PathRenameExtensionW(LPWSTR pszPath, LPCWSTR pszExt)
    17031714{
    1704         FIXME("%s %s\n", debugstr_w(pszPath), debugstr_w(pszExt));
    1705         return FALSE;
     1715        LPWSTR pszExtension = PathFindExtensionW(pszPath);
     1716
     1717        if (!pszExtension) return FALSE;
     1718        if (pszExtension-pszPath + strlenW(pszExt) > MAX_PATH) return FALSE;
     1719
     1720        strcpyW(pszExtension, pszExt);
     1721        TRACE("%s\n", debugstr_w(pszPath));
     1722        return TRUE;
    17061723}
    17071724
     
    17591776        DWORD dwFlags)
    17601777{
     1778    /* extracts thing prior to : in pszURL and checks against:
     1779     *   https
     1780     *   shell
     1781     *   local
     1782     *   about  - if match returns E_INVALIDARG
     1783     */
    17611784        FIXME("%s %p %p 0x%08lx\n",
    17621785          pszUrl, pszPath, pcchPath, dwFlags);
    1763         return S_OK;
     1786        return E_INVALIDARG;
    17641787}
    17651788
     
    17731796        DWORD dwFlags)
    17741797{
     1798    /* extracts thing prior to : in pszURL and checks against:
     1799     *   https
     1800     *   shell
     1801     *   local
     1802     *   about  - if match returns E_INVALIDARG
     1803     */
    17751804        FIXME("%s %p %p 0x%08lx\n",
    17761805          debugstr_w(pszUrl), pszPath, pcchPath, dwFlags);
    1777         return S_OK;
     1806        return E_INVALIDARG;
    17781807}
    17791808
  • trunk/src/shlwapi/reg.c

    r7508 r7820  
    99#include "winuser.h"
    1010#include "winerror.h"
     11#include "winnls.h"
    1112#include "winreg.h"
    1213#include "debugtools.h"
     14#define NO_SHLWAPI_STREAM
    1315#include "shlwapi.h"
    1416#include "wine/unicode.h"
    1517
     18DEFAULT_DEBUG_CHANNEL(shell);
     19
    1620#ifdef __WIN32OS2__
    17 
    18 #include "shlwapi_odin.h"
    19 
     21typedef DWORD (* WINAPI RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
     22#else
     23typedef DWORD (WINAPI *RegQueryFn)(HKEY,LPCVOID,LPDWORD,LPDWORD,LPBYTE,LPDWORD);
    2024#endif
    21 
    22 DEFAULT_DEBUG_CHANNEL(shell);
    2325
    2426static const char *lpszContentTypeA = "Content Type";
    2527static const WCHAR lpszContentTypeW[] = { 'C','o','n','t','e','n','t',' ','T','y','p','e','\0'};
    2628
    27 /*************************************************************************
    28  * SHRegGetUSValueA     [SHLWAPI.@]
    29  *
    30  * Gets a user-specific registry value
    31  */
    32 LONG WINAPI SHRegGetUSValueA(
    33         LPCSTR   pSubKey,
    34         LPCSTR   pValue,
    35         LPDWORD  pwType,
    36         LPVOID   pvData,
    37         LPDWORD  pbData,
    38         BOOL     fIgnoreHKCU,
    39         LPVOID   pDefaultData,
    40         DWORD    wDefaultDataSize)
    41 {
    42         FIXME("(%p),stub!\n", pSubKey);
    43         return ERROR_SUCCESS;  /* return success */
    44 }
    45 
    46 /*************************************************************************
    47  * SHRegGetUSValueW     [SHLWAPI.@]
    48  *
    49  * Gets a user-specific registry value
    50  */
    51 LONG WINAPI SHRegGetUSValueW(
    52         LPCWSTR  pSubKey,
    53         LPCWSTR  pValue,
    54         LPDWORD  pwType,
    55         LPVOID   pvData,
    56         LPDWORD  pbData,
    57         BOOL     flagIgnoreHKCU,
    58         LPVOID   pDefaultData,
    59         DWORD    wDefaultDataSize)
    60 {
    61         FIXME("(%p),stub!\n", pSubKey);
    62         return ERROR_SUCCESS;  /* return success */
    63 }
     29/* internal structure of what the HUSKEY points to */
     30typedef struct {
     31    HKEY     HKCUkey;                  /* HKEY of opened HKCU key      */
     32    HKEY     HKLMkey;                  /* HKEY of opened HKLM key      */
     33    HKEY     start;                    /* HKEY of where to start       */
     34    WCHAR    key_string[MAX_PATH];     /* additional path from 'start' */
     35} Internal_HUSKEY, *LPInternal_HUSKEY;
     36
     37
     38#define REG_HKCU  TRUE
     39#define REG_HKLM  FALSE
     40/*************************************************************************
     41 * REG_GetHKEYFromHUSKEY
     42 *
     43 * Function:  Return the proper registry key from the HUSKEY structure
     44 *            also allow special predefined values.
     45 */
     46HKEY REG_GetHKEYFromHUSKEY(HUSKEY hUSKey, BOOL which)
     47{
     48        HKEY test = (HKEY) hUSKey;
     49        LPInternal_HUSKEY mihk = (LPInternal_HUSKEY) hUSKey;
     50
     51        if ((test == HKEY_CLASSES_ROOT)        ||
     52            (test == HKEY_CURRENT_CONFIG)      ||
     53            (test == HKEY_CURRENT_USER)        ||
     54            (test == HKEY_DYN_DATA)            ||
     55            (test == HKEY_LOCAL_MACHINE)       ||
     56            (test == HKEY_PERFORMANCE_DATA)    ||
     57/* FIXME:  need to define for Win2k, ME, XP
     58 *          (test == HKEY_PERFORMANCE_TEXT)    ||
     59 *          (test == HKEY_PERFORMANCE_NLSTEXT) ||
     60 */
     61            (test == HKEY_USERS)) return test;
     62        if (which == REG_HKCU) return mihk->HKCUkey;
     63        return mihk->HKLMkey;
     64}
     65
    6466
    6567/*************************************************************************
    6668 * SHRegOpenUSKeyA      [SHLWAPI.@]
    6769 *
    68  * Openss a user-specific registry key
     70 * Opens a user-specific registry key
    6971 */
    7072LONG WINAPI SHRegOpenUSKeyA(
    71         LPCSTR lpszPath,
    72         DWORD  dwAccessType,
     73        LPCSTR Path,
     74        REGSAM AccessType,
    7375        HUSKEY hRelativeUSKey,
    7476        PHUSKEY phNewUSKey,
    7577        BOOL fIgnoreHKCU)
    7678{
    77         FIXME("stub!\n");
    78         return ERROR_SUCCESS;  /* return success */
     79    HKEY openHKCUkey=0;
     80    HKEY openHKLMkey=0;
     81    LONG ret2, ret1 = ~ERROR_SUCCESS;
     82    LPInternal_HUSKEY ihky;
     83
     84    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_a(Path),
     85          (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
     86          (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
     87
     88    /* now create the internal version of HUSKEY */
     89    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
     90                                        sizeof(Internal_HUSKEY));
     91    MultiByteToWideChar(0, 0, Path, -1, ihky->key_string,
     92                        sizeof(ihky->key_string)-1);
     93
     94    if (hRelativeUSKey) {
     95        openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
     96        openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
     97    }
     98    else {
     99        openHKCUkey = HKEY_CURRENT_USER;
     100        openHKLMkey = HKEY_LOCAL_MACHINE;
     101    }
     102
     103    ihky->HKCUkey = 0;
     104    ihky->HKLMkey = 0;
     105    if (!fIgnoreHKCU) {
     106        ret1 = RegOpenKeyExA(openHKCUkey, Path,
     107                             0, AccessType, &ihky->HKCUkey);
     108        /* if successful, then save real starting point */
     109        if (ret1 != ERROR_SUCCESS)
     110            ihky->HKCUkey = 0;
     111    }
     112    ret2 = RegOpenKeyExA(openHKLMkey, Path,
     113                         0, AccessType, &ihky->HKLMkey);
     114    if (ret2 != ERROR_SUCCESS)
     115        ihky->HKLMkey = 0;
     116
     117    if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
     118        TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
     119
     120    /* if all attempts have failed then bail */
     121    if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
     122        HeapFree(GetProcessHeap(), 0, ihky);
     123        if (phNewUSKey)
     124            *phNewUSKey = (HUSKEY)0;
     125        return ret2;
     126    }
     127
     128    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
     129    if (phNewUSKey)
     130        *phNewUSKey = (HUSKEY)ihky;
     131    return ERROR_SUCCESS;
    79132}
    80133
     
    82135 * SHRegOpenUSKeyW      [SHLWAPI.@]
    83136 *
    84  * Openss a user-specific registry key
     137 * Opens a user-specific registry key
    85138 */
    86139LONG WINAPI SHRegOpenUSKeyW(
    87         LPCSTR lpszPath,
    88         DWORD  dwAccessType,
     140        LPCWSTR Path,
     141        REGSAM AccessType,
    89142        HUSKEY hRelativeUSKey,
    90         HUSKEY hNewUSKey,
     143        PHUSKEY phNewUSKey,
    91144        BOOL fIgnoreHKCU)
    92145{
    93         FIXME("stub!\n");
    94         return ERROR_SUCCESS;  /* return success */
    95 }
    96 
    97 #ifndef __WIN32OS2__
    98 /*************************************************************************
    99  * SHRegGetBoolUSValueA   [SHLWAPI.@]
    100  */
    101 BOOL WINAPI SHRegGetBoolUSValueA(
    102         LPCSTR pszSubKey,
    103         LPCSTR pszValue,
    104         BOOL fIgnoreHKCU,
    105         BOOL fDefault)
    106 {
    107         FIXME("%s %s\n", pszSubKey,pszValue);
    108         return fDefault;
    109 }
    110 
    111 /*************************************************************************
    112  * SHRegGetBoolUSValueW   [SHLWAPI.@]
    113  */
    114 BOOL WINAPI SHRegGetBoolUSValueW(
    115         LPCWSTR pszSubKey,
    116         LPCWSTR pszValue,
    117         BOOL fIgnoreHKCU,
    118         BOOL fDefault)
    119 {
    120         FIXME("%s %s\n", debugstr_w(pszSubKey),debugstr_w(pszValue));
    121         return fDefault;
    122 }
    123 #endif
    124 
    125 /*************************************************************************
    126  *      SHRegQueryUSValueA      [SHLWAPI]
     146    HKEY openHKCUkey=0;
     147    HKEY openHKLMkey=0;
     148    LONG ret2, ret1 = ~ERROR_SUCCESS;
     149    LPInternal_HUSKEY ihky;
     150
     151    TRACE("(%s, 0x%lx, 0x%lx, %p, %s)\n", debugstr_w(Path),
     152          (LONG)AccessType, (LONG)hRelativeUSKey, phNewUSKey,
     153          (fIgnoreHKCU) ? "Ignoring HKCU" : "Process HKCU then HKLM");
     154
     155    /* now create the internal version of HUSKEY */
     156    ihky = (LPInternal_HUSKEY)HeapAlloc(GetProcessHeap(), 0 ,
     157                                        sizeof(Internal_HUSKEY));
     158    lstrcpynW(ihky->key_string, Path, sizeof(ihky->key_string));
     159
     160    if (hRelativeUSKey) {
     161        openHKCUkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKCUkey;
     162        openHKLMkey = ((LPInternal_HUSKEY)hRelativeUSKey)->HKLMkey;
     163    }
     164    else {
     165        openHKCUkey = HKEY_CURRENT_USER;
     166        openHKLMkey = HKEY_LOCAL_MACHINE;
     167    }
     168
     169    ihky->HKCUkey = 0;
     170    ihky->HKLMkey = 0;
     171    if (!fIgnoreHKCU) {
     172        ret1 = RegOpenKeyExW(openHKCUkey, Path,
     173                            0, AccessType, &ihky->HKCUkey);
     174        /* if successful, then save real starting point */
     175        if (ret1 != ERROR_SUCCESS)
     176            ihky->HKCUkey = 0;
     177    }
     178    ret2 = RegOpenKeyExW(openHKLMkey, Path,
     179                        0, AccessType, &ihky->HKLMkey);
     180    if (ret2 != ERROR_SUCCESS)
     181        ihky->HKLMkey = 0;
     182
     183    if ((ret1 != ERROR_SUCCESS) || (ret2 != ERROR_SUCCESS))
     184        TRACE("one or more opens failed: HKCU=%ld HKLM=%ld\n", ret1, ret2);
     185
     186    /* if all attempts have failed then bail */
     187    if ((ret1 != ERROR_SUCCESS) && (ret2 != ERROR_SUCCESS)) {
     188        HeapFree(GetProcessHeap(), 0, ihky);
     189        if (phNewUSKey)
     190            *phNewUSKey = (HUSKEY)0;
     191        return ret2;
     192    }
     193
     194    TRACE("HUSKEY=0x%08lx\n", (LONG)ihky);
     195    if (phNewUSKey)
     196        *phNewUSKey = (HUSKEY)ihky;
     197    return ERROR_SUCCESS;
     198}
     199
     200/*************************************************************************
     201 * SHRegCloseUSKey      [SHLWAPI.@]
     202 *
     203 * Closes a user-specific registry key
     204 */
     205LONG WINAPI SHRegCloseUSKey(
     206        HUSKEY hUSKey)
     207{
     208    LPInternal_HUSKEY mihk = (LPInternal_HUSKEY)hUSKey;
     209    LONG ret = ERROR_SUCCESS;
     210
     211    if (mihk->HKCUkey)
     212        ret = RegCloseKey(mihk->HKCUkey);
     213    if (mihk->HKLMkey)
     214        ret = RegCloseKey(mihk->HKLMkey);
     215    HeapFree(GetProcessHeap(), 0, mihk);
     216    return ret;
     217}
     218
     219/*************************************************************************
     220 *      SHRegQueryUSValueA      [SHLWAPI.@]
    127221 */
    128222LONG WINAPI SHRegQueryUSValueA(
    129         HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
     223        HUSKEY hUSKey,             /* [in] */
    130224        LPCSTR pszValue,
    131225        LPDWORD pdwType,
     
    136230        DWORD dwDefaultDataSize)
    137231{
    138         FIXME("%s stub\n",pszValue);
    139         return 1;
    140 }
    141 
    142 /*************************************************************************
    143  *      SHRegQueryUSValueA      [SHLWAPI]
     232        LONG ret = ~ERROR_SUCCESS;
     233        LONG i, maxmove;
     234        HKEY dokey;
     235        CHAR *src, *dst;
     236
     237        /* if user wants HKCU, and it exists, then try it */
     238        if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     239            ret = RegQueryValueExA(dokey,
     240                                   pszValue, 0, pdwType, pvData, pcbData);
     241            TRACE("HKCU RegQueryValue returned %08lx\n", ret);
     242        }
     243
     244        /* if HKCU did not work and HKLM exists, then try it */
     245        if ((ret != ERROR_SUCCESS) &&
     246            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     247            ret = RegQueryValueExA(dokey,
     248                                   pszValue, 0, pdwType, pvData, pcbData);
     249            TRACE("HKLM RegQueryValue returned %08lx\n", ret);
     250        }
     251
     252        /* if neither worked, and default data exists, then use it */
     253        if (ret != ERROR_SUCCESS) {
     254            if (pvDefaultData && (dwDefaultDataSize != 0)) {
     255                maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
     256                src = (CHAR*)pvDefaultData;
     257                dst = (CHAR*)pvData;
     258                for(i=0; i<maxmove; i++) *dst++ = *src++;
     259                *pcbData = maxmove;
     260                TRACE("setting default data\n");
     261                ret = ERROR_SUCCESS;
     262            }
     263        }
     264        return ret;
     265}
     266
     267
     268/*************************************************************************
     269 *      SHRegQueryUSValueW      [SHLWAPI.@]
    144270 */
    145271LONG WINAPI SHRegQueryUSValueW(
    146         HUSKEY hUSKey,             /* [in] FIXME: HUSKEY */
    147         LPCSTR pszValue,
     272        HUSKEY hUSKey,             /* [in] */
     273        LPCWSTR pszValue,
    148274        LPDWORD pdwType,
    149         void *pvData,
     275        LPVOID pvData,
    150276        LPDWORD pcbData,
    151277        BOOL fIgnoreHKCU,
    152         void *pvDefaultData,
     278        LPVOID pvDefaultData,
    153279        DWORD dwDefaultDataSize)
    154280{
    155         FIXME("%s stub\n",pszValue);
    156         return 1;
    157 }
    158 
    159 /*************************************************************************
    160  * SHRegGetPathA   [SHLWAPI.@]
    161  */
    162 DWORD WINAPI SHRegGetPathA(
    163         HKEY hKey,
    164         LPCSTR pcszSubKey,
    165         LPCSTR pcszValue,
    166         LPSTR pszPath,
    167         DWORD dwFlags)
    168 {
    169         FIXME("%s %s\n", pcszSubKey, pcszValue);
    170         return 0;
    171 }
    172 
    173 /*************************************************************************
    174  * SHRegGetPathW   [SHLWAPI.@]
    175  */
    176 DWORD WINAPI SHRegGetPathW(
    177         HKEY hKey,
    178         LPCWSTR pcszSubKey,
    179         LPCWSTR pcszValue,
    180         LPWSTR pszPath,
    181         DWORD dwFlags)
    182 {
    183         FIXME("%s %s\n", debugstr_w(pcszSubKey), debugstr_w(pcszValue));
    184         return 0;
    185 }
    186 
    187 /*************************************************************************
    188  * SHGetValueA   [SHLWAPI.@]
    189  *
    190  * Gets a value from the registry
    191  */
    192 DWORD WINAPI SHGetValueA(
    193         HKEY     hkey,
     281        LONG ret = ~ERROR_SUCCESS;
     282        LONG i, maxmove;
     283        HKEY dokey;
     284        CHAR *src, *dst;
     285
     286        /* if user wants HKCU, and it exists, then try it */
     287        if (!fIgnoreHKCU && (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     288            ret = RegQueryValueExW(dokey,
     289                                   pszValue, 0, pdwType, pvData, pcbData);
     290            TRACE("HKCU RegQueryValue returned %08lx\n", ret);
     291        }
     292
     293        /* if HKCU did not work and HKLM exists, then try it */
     294        if ((ret != ERROR_SUCCESS) &&
     295            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     296            ret = RegQueryValueExW(dokey,
     297                                   pszValue, 0, pdwType, pvData, pcbData);
     298            TRACE("HKLM RegQueryValue returned %08lx\n", ret);
     299        }
     300
     301        /* if neither worked, and default data exists, then use it */
     302        if (ret != ERROR_SUCCESS) {
     303            if (pvDefaultData && (dwDefaultDataSize != 0)) {
     304                maxmove = (dwDefaultDataSize >= *pcbData) ? *pcbData : dwDefaultDataSize;
     305                src = (CHAR*)pvDefaultData;
     306                dst = (CHAR*)pvData;
     307                for(i=0; i<maxmove; i++) *dst++ = *src++;
     308                *pcbData = maxmove;
     309                TRACE("setting default data\n");
     310                ret = ERROR_SUCCESS;
     311            }
     312        }
     313        return ret;
     314}
     315
     316/*************************************************************************
     317 * SHRegGetUSValueA     [SHLWAPI.@]
     318 *
     319 * Gets a user-specific registry value
     320 *   Will open the key, query the value, and close the key
     321 */
     322LONG WINAPI SHRegGetUSValueA(
    194323        LPCSTR   pSubKey,
    195324        LPCSTR   pValue,
    196325        LPDWORD  pwType,
    197326        LPVOID   pvData,
    198         LPDWORD  pbData)
    199 {
    200         HKEY hSubKey;
    201         DWORD res;
    202 
    203         TRACE("(%s %s)\n", pSubKey, pValue);
    204 
    205         if((res = RegOpenKeyA(hkey, pSubKey, &hSubKey))) return res;
    206         res = RegQueryValueExA(hSubKey, pValue, 0, pwType, pvData, pbData);
    207         RegCloseKey( hSubKey );
    208 
    209         return res;
    210 }
    211 
    212 /*************************************************************************
    213  * SHGetValueW   [SHLWAPI.@]
    214  *
    215  * Gets a value from the registry
    216  */
    217 DWORD WINAPI SHGetValueW(
    218         HKEY     hkey,
     327        LPDWORD  pcbData,
     328        BOOL     flagIgnoreHKCU,
     329        LPVOID   pDefaultData,
     330        DWORD    wDefaultDataSize)
     331{
     332        HUSKEY myhuskey;
     333        LONG ret;
     334
     335        if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
     336        TRACE("key '%s', value '%s', datalen %ld,  %s\n",
     337              debugstr_a(pSubKey), debugstr_a(pValue), *pcbData,
     338              (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
     339
     340        ret = SHRegOpenUSKeyA(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
     341        if (ret == ERROR_SUCCESS) {
     342            ret = SHRegQueryUSValueA(myhuskey, pValue, pwType, pvData,
     343                                     pcbData, flagIgnoreHKCU, pDefaultData,
     344                                     wDefaultDataSize);
     345            SHRegCloseUSKey(myhuskey);
     346        }
     347        return ret;
     348}
     349
     350/*************************************************************************
     351 * SHRegGetUSValueW     [SHLWAPI.@]
     352 *
     353 * Gets a user-specific registry value
     354 *   Will open the key, query the value, and close the key
     355 */
     356LONG WINAPI SHRegGetUSValueW(
    219357        LPCWSTR  pSubKey,
    220358        LPCWSTR  pValue,
    221359        LPDWORD  pwType,
    222360        LPVOID   pvData,
    223         LPDWORD  pbData)
    224 {
    225         HKEY hSubKey;
    226         DWORD res;
    227 
    228         TRACE("(%s %s)\n", debugstr_w(pSubKey), debugstr_w(pValue));
    229 
    230         if((res = RegOpenKeyW(hkey, pSubKey, &hSubKey))) return res;
    231         res = RegQueryValueExW(hSubKey, pValue, 0, pwType, pvData, pbData);
    232         RegCloseKey( hSubKey );
    233 
    234         return res;
    235 }
    236 
    237 /*************************************************************************
    238  *      SHSetValueA   [SHLWAPI.@]
    239  */
    240 HRESULT WINAPI SHSetValueA(
    241         HKEY hkey,
     361        LPDWORD  pcbData,
     362        BOOL     flagIgnoreHKCU,
     363        LPVOID   pDefaultData,
     364        DWORD    wDefaultDataSize)
     365{
     366        HUSKEY myhuskey;
     367        LONG ret;
     368
     369        if (!pvData || !pcbData) return ERROR_INVALID_FUNCTION; /* FIXME:wrong*/
     370        TRACE("key '%s', value '%s', datalen %ld,  %s\n",
     371              debugstr_w(pSubKey), debugstr_w(pValue), *pcbData,
     372              (flagIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
     373
     374        ret = SHRegOpenUSKeyW(pSubKey, 0x1, 0, &myhuskey, flagIgnoreHKCU);
     375        if (ret == ERROR_SUCCESS) {
     376            ret = SHRegQueryUSValueW(myhuskey, pValue, pwType, pvData,
     377                                     pcbData, flagIgnoreHKCU, pDefaultData,
     378                                     wDefaultDataSize);
     379            SHRegCloseUSKey(myhuskey);
     380        }
     381        return ret;
     382}
     383
     384/*************************************************************************
     385 * SHRegGetBoolUSValueA   [SHLWAPI.@]
     386 */
     387BOOL WINAPI SHRegGetBoolUSValueA(
    242388        LPCSTR pszSubKey,
    243389        LPCSTR pszValue,
    244         DWORD dwType,
    245         LPCVOID pvData,
    246         DWORD cbData)
    247 {
    248     HKEY        subkey;
    249     HRESULT     hres;
    250 
    251     hres = RegCreateKeyA(hkey,pszSubKey,&subkey);
    252     if (!hres)
    253         return hres;
    254     hres = RegSetValueExA(subkey,pszValue,0,dwType,pvData,cbData);
    255     RegCloseKey(subkey);
    256     return hres;
    257 }
    258 
    259 /*************************************************************************
    260  *      SHSetValueW   [SHLWAPI.@]
    261  */
    262 HRESULT WINAPI SHSetValueW(
    263         HKEY hkey,
     390        BOOL fIgnoreHKCU,
     391        BOOL fDefault)
     392{
     393        LONG retvalue;
     394        DWORD type, datalen, work;
     395        BOOL ret = fDefault;
     396        CHAR data[10];
     397
     398        TRACE("key '%s', value '%s', %s\n",
     399              debugstr_a(pszSubKey), debugstr_a(pszValue),
     400              (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
     401
     402        datalen = sizeof(data)-1;
     403        if (!(retvalue = SHRegGetUSValueA( pszSubKey, pszValue, &type,
     404                                           data, &datalen,
     405                                           fIgnoreHKCU, 0, 0))) {
     406            /* process returned data via type into bool */
     407            switch (type) {
     408            case REG_SZ:
     409                data[9] = '\0';     /* set end of string */
     410                if (lstrcmpiA(data, "YES") == 0) ret = TRUE;
     411                if (lstrcmpiA(data, "TRUE") == 0) ret = TRUE;
     412                if (lstrcmpiA(data, "NO") == 0) ret = FALSE;
     413                if (lstrcmpiA(data, "FALSE") == 0) ret = FALSE;
     414                break;
     415            case REG_DWORD:
     416                work = *(LPDWORD)data;
     417                ret = (work != 0);
     418                break;
     419            case REG_BINARY:
     420                if (datalen == 1) {
     421                    ret = (data[0] != '\0');
     422                    break;
     423                }
     424            default:
     425                FIXME("Unsupported registry data type %ld\n", type);
     426                ret = FALSE;
     427            }
     428            TRACE("got value (type=%ld), returing <%s>\n", type,
     429                  (ret) ? "TRUE" : "FALSE");
     430        }
     431        else {
     432            ret = fDefault;
     433            TRACE("returning default data <%s>\n",
     434                  (ret) ? "TRUE" : "FALSE");
     435        }
     436        return ret;
     437}
     438
     439/*************************************************************************
     440 * SHRegGetBoolUSValueW   [SHLWAPI.@]
     441 */
     442BOOL WINAPI SHRegGetBoolUSValueW(
    264443        LPCWSTR pszSubKey,
    265444        LPCWSTR pszValue,
    266         DWORD dwType,
    267         LPCVOID pvData,
    268         DWORD cbData)
    269 {
    270     HKEY        subkey;
    271     HRESULT     hres;
    272 
    273     hres = RegCreateKeyW(hkey,pszSubKey,&subkey);
    274     if (!hres)
    275         return hres;
    276     hres = RegSetValueExW(subkey,pszValue,0,dwType,pvData,cbData);
    277     RegCloseKey(subkey);
    278     return hres;
    279 }
    280 
    281 /*************************************************************************
    282  * SHQueryValueExA              [SHLWAPI.@]
    283  *
    284  */
    285 HRESULT WINAPI SHQueryValueExA(
    286         HKEY hkey,
    287         LPSTR lpValueName,
    288         LPDWORD lpReserved,
    289         LPDWORD lpType,
    290         LPBYTE lpData,
    291         LPDWORD lpcbData)
    292 {
    293         TRACE("0x%04x %s %p %p %p %p\n", hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
    294         return RegQueryValueExA (hkey, lpValueName, lpReserved, lpType, lpData, lpcbData);
    295 }
    296 
     445        BOOL fIgnoreHKCU,
     446        BOOL fDefault)
     447{
     448        static const WCHAR wYES[]=  {'Y','E','S','\0'};
     449        static const WCHAR wTRUE[]= {'T','R','U','E','\0'};
     450        static const WCHAR wNO[]=   {'N','O','\0'};
     451        static const WCHAR wFALSE[]={'F','A','L','S','E','\0'};
     452        LONG retvalue;
     453        DWORD type, datalen, work;
     454        BOOL ret = fDefault;
     455        WCHAR data[10];
     456
     457        TRACE("key '%s', value '%s', %s\n",
     458              debugstr_w(pszSubKey), debugstr_w(pszValue),
     459              (fIgnoreHKCU) ? "Ignoring HKCU" : "Tries HKCU then HKLM");
     460
     461        datalen = (sizeof(data)-1) * sizeof(WCHAR);
     462        if (!(retvalue = SHRegGetUSValueW( pszSubKey, pszValue, &type,
     463                                           data, &datalen,
     464                                           fIgnoreHKCU, 0, 0))) {
     465            /* process returned data via type into bool */
     466            switch (type) {
     467            case REG_SZ:
     468                data[9] = L'\0';     /* set end of string */
     469                if (lstrcmpiW(data, wYES)==0 || lstrcmpiW(data, wTRUE)==0)
     470                    ret = TRUE;
     471                else if (lstrcmpiW(data, wNO)==0 || lstrcmpiW(data, wFALSE)==0)
     472                    ret = FALSE;
     473                break;
     474            case REG_DWORD:
     475                work = *(LPDWORD)data;
     476                ret = (work != 0);
     477                break;
     478            case REG_BINARY:
     479                if (datalen == 1) {
     480                    ret = (data[0] != L'\0');
     481                    break;
     482                }
     483            default:
     484                FIXME("Unsupported registry data type %ld\n", type);
     485                ret = FALSE;
     486            }
     487            TRACE("got value (type=%ld), returing <%s>\n", type,
     488                  (ret) ? "TRUE" : "FALSE");
     489        }
     490        else {
     491            ret = fDefault;
     492            TRACE("returning default data <%s>\n",
     493                  (ret) ? "TRUE" : "FALSE");
     494        }
     495        return ret;
     496}
     497
     498/*************************************************************************
     499 *      SHRegQueryInfoUSKeyA    [SHLWAPI.@]
     500 */
     501LONG WINAPI SHRegQueryInfoUSKeyA(
     502        HUSKEY hUSKey,             /* [in]  */
     503        LPDWORD pcSubKeys,
     504        LPDWORD pcchMaxSubKeyLen,
     505        LPDWORD pcValues,
     506        LPDWORD pcchMaxValueNameLen,
     507        SHREGENUM_FLAGS enumRegFlags)
     508{
     509        HKEY dokey;
     510        LONG ret;
     511
     512        TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
     513              (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
     514              pcchMaxValueNameLen,enumRegFlags);
     515
     516        /* if user wants HKCU, and it exists, then try it */
     517        if (((enumRegFlags == SHREGENUM_HKCU) ||
     518             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     519            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     520            ret = RegQueryInfoKeyA(dokey, 0, 0, 0,
     521                                   pcSubKeys, pcchMaxSubKeyLen, 0,
     522                                   pcValues, pcchMaxValueNameLen, 0, 0, 0);
     523            if ((ret == ERROR_SUCCESS) ||
     524                (enumRegFlags == SHREGENUM_HKCU))
     525                return ret;
     526        }
     527        if (((enumRegFlags == SHREGENUM_HKLM) ||
     528             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     529            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     530            return RegQueryInfoKeyA(dokey, 0, 0, 0,
     531                                    pcSubKeys, pcchMaxSubKeyLen, 0,
     532                                    pcValues, pcchMaxValueNameLen, 0, 0, 0);
     533        }
     534        return ERROR_INVALID_FUNCTION;
     535}
     536
     537/*************************************************************************
     538 *      SHRegQueryInfoUSKeyW    [SHLWAPI.@]
     539 */
     540LONG WINAPI SHRegQueryInfoUSKeyW(
     541        HUSKEY hUSKey,             /* [in]  */
     542        LPDWORD pcSubKeys,
     543        LPDWORD pcchMaxSubKeyLen,
     544        LPDWORD pcValues,
     545        LPDWORD pcchMaxValueNameLen,
     546        SHREGENUM_FLAGS enumRegFlags)
     547{
     548        HKEY dokey;
     549        LONG ret;
     550
     551        TRACE("(0x%lx,%p,%p,%p,%p,%d)\n",
     552              (LONG)hUSKey,pcSubKeys,pcchMaxSubKeyLen,pcValues,
     553              pcchMaxValueNameLen,enumRegFlags);
     554
     555        /* if user wants HKCU, and it exists, then try it */
     556        if (((enumRegFlags == SHREGENUM_HKCU) ||
     557             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     558            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     559            ret = RegQueryInfoKeyW(dokey, 0, 0, 0,
     560                                   pcSubKeys, pcchMaxSubKeyLen, 0,
     561                                   pcValues, pcchMaxValueNameLen, 0, 0, 0);
     562            if ((ret == ERROR_SUCCESS) ||
     563                (enumRegFlags == SHREGENUM_HKCU))
     564                return ret;
     565        }
     566        if (((enumRegFlags == SHREGENUM_HKLM) ||
     567             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     568            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     569            return RegQueryInfoKeyW(dokey, 0, 0, 0,
     570                                    pcSubKeys, pcchMaxSubKeyLen, 0,
     571                                    pcValues, pcchMaxValueNameLen, 0, 0, 0);
     572        }
     573        return ERROR_INVALID_FUNCTION;
     574}
     575
     576/*************************************************************************
     577 *      SHRegEnumUSKeyA         [SHLWAPI.@]
     578 */
     579LONG WINAPI SHRegEnumUSKeyA(
     580        HUSKEY hUSKey,                 /* [in]  */
     581        DWORD dwIndex,                 /* [in]  */
     582        LPSTR pszName,                 /* [out] */
     583        LPDWORD pcchValueNameLen,      /* [in/out] */
     584        SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
     585{
     586        HKEY dokey;
     587
     588        TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
     589              (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
     590              *pcchValueNameLen, enumRegFlags);
     591
     592        if (((enumRegFlags == SHREGENUM_HKCU) ||
     593             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     594            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     595            return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
     596                                0, 0, 0, 0);
     597        }
     598
     599        if (((enumRegFlags == SHREGENUM_HKLM) ||
     600             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     601            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     602            return RegEnumKeyExA(dokey, dwIndex, pszName, pcchValueNameLen,
     603                                0, 0, 0, 0);
     604        }
     605        FIXME("no support for SHREGNUM_BOTH\n");
     606        return ERROR_INVALID_FUNCTION;
     607}
     608
     609/*************************************************************************
     610 *      SHRegEnumUSKeyW         [SHLWAPI.@]
     611 */
     612LONG WINAPI SHRegEnumUSKeyW(
     613        HUSKEY hUSKey,                 /* [in]  */
     614        DWORD dwIndex,                 /* [in]  */
     615        LPWSTR pszName,                /* [out] */
     616        LPDWORD pcchValueNameLen,      /* [in/out] */
     617        SHREGENUM_FLAGS enumRegFlags)  /* [in]  */
     618{
     619        HKEY dokey;
     620
     621        TRACE("(0x%lx,%ld,%p,%p(%ld),%d)\n",
     622              (LONG)hUSKey, dwIndex, pszName, pcchValueNameLen,
     623              *pcchValueNameLen, enumRegFlags);
     624
     625        if (((enumRegFlags == SHREGENUM_HKCU) ||
     626             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     627            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKCU))) {
     628            return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
     629                                0, 0, 0, 0);
     630        }
     631
     632        if (((enumRegFlags == SHREGENUM_HKLM) ||
     633             (enumRegFlags == SHREGENUM_DEFAULT)) &&
     634            (dokey = REG_GetHKEYFromHUSKEY(hUSKey,REG_HKLM))) {
     635            return RegEnumKeyExW(dokey, dwIndex, pszName, pcchValueNameLen,
     636                                0, 0, 0, 0);
     637        }
     638        FIXME("no support for SHREGNUM_BOTH\n");
     639        return ERROR_INVALID_FUNCTION;
     640}
     641
     642/*************************************************************************
     643 *      SHRegWriteUSValueA      [SHLWAPI.@]
     644 */
     645LONG  WINAPI SHRegWriteUSValueA(HUSKEY hUSKey, LPCSTR pszValue, DWORD dwType,
     646                                LPVOID pvData, DWORD cbData, DWORD dwFlags)
     647{
     648    FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
     649          (LONG)hUSKey, debugstr_a(pszValue), dwType, pvData, cbData, dwFlags);
     650    return ERROR_SUCCESS;
     651}
     652
     653/*************************************************************************
     654 *      SHRegWriteUSValueW      [SHLWAPI.@]
     655 */
     656LONG  WINAPI SHRegWriteUSValueW(HUSKEY hUSKey, LPCWSTR pszValue, DWORD dwType,
     657                                LPVOID pvData, DWORD cbData, DWORD dwFlags)
     658{
     659    FIXME("(0x%lx,%s,%ld,%p,%ld,%ld): stub\n",
     660          (LONG)hUSKey, debugstr_w(pszValue), dwType, pvData, cbData, dwFlags);
     661    return ERROR_SUCCESS;
     662}
     663
     664/*************************************************************************
     665 * SHRegGetPathA   [SHLWAPI.@]
     666 *
     667 * Get a path from the registry.
     668 *
     669 * PARAMS
     670 *   hKey       [I] Handle to registry key
     671 *   lpszSubKey [I] Name of sub key containing path to get
     672 *   lpszValue  [I] Name of value containing path to get
     673 *   lpszPath   [O] Buffer for returned path
     674 *   dwFlags    [I] Reserved
     675 *
     676 * RETURNS
     677 *   Success: ERROR_SUCCESS. lpszPath contains the path.
     678 *   Failure: An error code from RegOpenKeyExA or SHQueryValueExA.
     679 */
     680DWORD WINAPI SHRegGetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
     681                           LPSTR lpszPath, DWORD dwFlags)
     682{
     683  HKEY hSubKey;
     684  DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
     685
     686  TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
     687        debugstr_a(lpszValue), lpszPath, dwFlags);
     688
     689  if (lpszSubKey && *lpszSubKey)
     690    dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     691  else
     692    hSubKey = hKey;
     693
     694  if (!dwRet)
     695    dwRet = SHQueryValueExA(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
     696
     697  if (hSubKey != hKey)
     698    RegCloseKey(hSubKey);
     699
     700  return dwRet;
     701}
     702
     703/*************************************************************************
     704 * SHRegGetPathW   [SHLWAPI.@]
     705 *
     706 * See SHRegGetPathA.
     707 */
     708DWORD WINAPI SHRegGetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
     709                           LPWSTR lpszPath, DWORD dwFlags)
     710{
     711  HKEY hSubKey;
     712  DWORD dwType = REG_SZ, dwSize = MAX_PATH, dwRet = ERROR_SUCCESS;
     713
     714  TRACE("(hkey=0x%08x,%s,%s,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
     715        debugstr_w(lpszValue), lpszPath, dwFlags);
     716
     717  if (lpszSubKey && *lpszSubKey)
     718    dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     719  else
     720    hSubKey = hKey;
     721
     722  if (!dwRet)
     723    dwRet = SHQueryValueExW(hSubKey, lpszValue, NULL, &dwType, lpszPath, &dwSize);
     724
     725  if (hSubKey != hKey)
     726    RegCloseKey(hSubKey);
     727
     728  return dwRet;
     729}
     730
     731
     732/*************************************************************************
     733 * SHRegSetPathA   [SHLWAPI.@]
     734 *
     735 * Write a path to the registry.
     736 *
     737 * PARAMS
     738 *   hKey       [I] Handle to registry key
     739 *   lpszSubKey [I] Name of sub key containing path to set
     740 *   lpszValue  [I] Name of value containing path to set
     741 *   lpszPath   [O] Path to write
     742 *   dwFlags    [I] Reserved
     743 *
     744 * RETURNS
     745 *   Success: ERROR_SUCCESS.
     746 *   Failure: An error code from SHSetValueA.
     747 */
     748DWORD WINAPI SHRegSetPathA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
     749                           LPCSTR lpszPath, DWORD dwFlags)
     750{
     751  char szBuff[MAX_PATH];
     752
     753  FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_a(lpszSubKey),
     754        debugstr_a(lpszValue), lpszPath, dwFlags);
     755
     756  lstrcpyA(szBuff, lpszPath);
     757
     758  /* FIXME: PathUnExpandEnvStringsA(szBuff); */
     759
     760  return SHSetValueA(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
     761                     lstrlenA(szBuff));
     762}
     763
     764/*************************************************************************
     765 * SHRegSetPathW   [SHLWAPI.@]
     766 *
     767 * See SHRegSetPathA.
     768 */
     769DWORD WINAPI SHRegSetPathW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
     770                           LPCWSTR lpszPath, DWORD dwFlags)
     771{
     772  WCHAR szBuff[MAX_PATH];
     773
     774  FIXME("(hkey=0x%08x,%s,%s,%p,%ld) - semi-stub",hKey, debugstr_w(lpszSubKey),
     775        debugstr_w(lpszValue), lpszPath, dwFlags);
     776
     777  lstrcpyW(szBuff, lpszPath);
     778
     779  /* FIXME: PathUnExpandEnvStringsW(szBuff); */
     780
     781  return SHSetValueW(hKey,lpszSubKey, lpszValue, REG_SZ, szBuff,
     782                     lstrlenW(szBuff));
     783}
     784
     785/*************************************************************************
     786 * SHGetValueA   [SHLWAPI.@]
     787 *
     788 * Get a value from the registry.
     789 *
     790 * PARAMS
     791 *   hKey       [I] Handle to registry key
     792 *   lpszSubKey [I] Name of sub key containing value to get
     793 *   lpszValue  [I] Name of value to get
     794 *   pwType     [O] Pointer to the values type
     795 *   pvData     [O] Pointer to the values data
     796 *   pcbData    [O] Pointer to the values size
     797 *
     798 * RETURNS
     799 *   Success: ERROR_SUCCESS. Output parameters contain the details read.
     800 *   Failure: An error code from RegOpenKeyExA or RegQueryValueExA.
     801 */
     802DWORD WINAPI SHGetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
     803                         LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
     804{
     805  DWORD dwRet;
     806  HKEY hSubKey;
     807
     808  TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_a(lpszSubKey),
     809        debugstr_a(lpszValue), pwType, pvData, pcbData);
     810
     811  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
     812  if (!dwRet)
     813  {
     814    dwRet = RegQueryValueExA(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
     815    RegCloseKey(hSubKey);
     816  }
     817  return dwRet;
     818}
     819
     820/*************************************************************************
     821 * SHGetValueW   [SHLWAPI.@]
     822 *
     823 * See SHGetValueA.
     824 */
     825DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
     826                         LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
     827{
     828  DWORD dwRet;
     829  HKEY hSubKey;
     830
     831  TRACE("(hkey=0x%08x,%s,%s,%p,%p,%p)\n", hKey, debugstr_w(lpszSubKey),
     832        debugstr_w(lpszValue), pwType, pvData, pcbData);
     833
     834  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_QUERY_VALUE, &hSubKey);
     835  if (!dwRet)
     836  {
     837    dwRet = RegQueryValueExW(hSubKey, lpszValue, 0, pwType, pvData, pcbData);
     838    RegCloseKey(hSubKey);
     839  }
     840  return dwRet;
     841}
     842
     843/*************************************************************************
     844 * SHSetValueA   [SHLWAPI.@]
     845 *
     846 * Set a value in the registry.
     847 *
     848 * PARAMS
     849 *   hKey       [I] Handle to registry key
     850 *   lpszSubKey [I] Name of sub key under hKey
     851 *   lpszValue  [I] Name of value to set
     852 *   dwType     [I] Type of the value
     853 *   pvData     [I] Data of the value
     854 *   cbData     [I] Size of the value
     855 *
     856 * RETURNS
     857 *   Success: ERROR_SUCCESS. The value is set with the data given.
     858 *   Failure: An error code from RegCreateKeyExA or RegSetValueExA
     859 *
     860 * NOTES
     861 *   If the sub key does not exist, it is created before the value is set. If
     862 *   The sub key is NULL or an empty string, then the value is added directly
     863 *   to hKey instead.
     864 */
     865DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
     866                         DWORD dwType, LPCVOID pvData, DWORD cbData)
     867{
     868  DWORD dwRet = ERROR_SUCCESS, dwDummy;
     869  HKEY  hSubKey;
     870  LPSTR szEmpty = "";
     871
     872  TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
     873          debugstr_a(lpszValue), dwType, pvData, cbData);
     874
     875  if (lpszSubKey && *lpszSubKey)
     876    dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, szEmpty,
     877                            0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
     878  else
     879    hSubKey = hKey;
     880  if (!dwRet)
     881  {
     882    dwRet = RegSetValueExA(hSubKey, lpszValue, 0, dwType, pvData, cbData);
     883    if (hSubKey != hKey)
     884      RegCloseKey(hSubKey);
     885  }
     886  return dwRet;
     887}
     888
     889/*************************************************************************
     890 * SHSetValueW   [SHLWAPI.@]
     891 *
     892 * See SHSetValueA.
     893 */
     894DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
     895                         DWORD dwType, LPCVOID pvData, DWORD cbData)
     896{
     897  DWORD dwRet = ERROR_SUCCESS, dwDummy;
     898  HKEY  hSubKey;
     899  WCHAR szEmpty[] = { '\0' };
     900
     901  TRACE("(hkey=0x%08x,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
     902        debugstr_w(lpszValue), dwType, pvData, cbData);
     903
     904  if (lpszSubKey && *lpszSubKey)
     905    dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, szEmpty,
     906                            0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
     907  else
     908    hSubKey = hKey;
     909  if (!dwRet)
     910  {
     911    dwRet = RegSetValueExW(hSubKey, lpszValue, 0, dwType, pvData, cbData);
     912    if (hSubKey != hKey)
     913      RegCloseKey(hSubKey);
     914  }
     915  return dwRet;
     916}
     917
     918/*************************************************************************
     919 * SHQueryInfoKeyA   [SHLWAPI.@]
     920 *
     921 * Get information about a registry key. See RegQueryInfoKeyA.
     922 */
     923LONG WINAPI SHQueryInfoKeyA(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
     924                            LPDWORD pwValues, LPDWORD pwValueMax)
     925{
     926  TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
     927        pwValues, pwValueMax);
     928  return RegQueryInfoKeyA(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
     929                          NULL, pwValues, pwValueMax, NULL, NULL, NULL);
     930}
     931
     932/*************************************************************************
     933 * SHQueryInfoKeyW   [SHLWAPI.@]
     934 *
     935 * See SHQueryInfoKeyA
     936 */
     937LONG WINAPI SHQueryInfoKeyW(HKEY hKey, LPDWORD pwSubKeys, LPDWORD pwSubKeyMax,
     938                            LPDWORD pwValues, LPDWORD pwValueMax)
     939{
     940  TRACE("(hkey=0x%08x,%p,%p,%p,%p)\n", hKey, pwSubKeys, pwSubKeyMax,
     941        pwValues, pwValueMax);
     942  return RegQueryInfoKeyW(hKey, NULL, NULL, NULL, pwSubKeys, pwSubKeyMax,
     943                          NULL, pwValues, pwValueMax, NULL, NULL, NULL);
     944}
     945
     946/*************************************************************************
     947 * SHQueryValueExAW
     948 *
     949 * Internal implementation of SHQueryValueExA/SHQueryValueExW.
     950 */
     951static DWORD WINAPI SHQueryValueExAW(RegQueryFn pfn,
     952                                     HKEY hKey, LPCVOID lpszValue,
     953                                     LPDWORD lpReserved, LPDWORD pwType,
     954                                     LPBYTE pvData, LPDWORD pcbData)
     955{
     956  DWORD dwRet, dwType, dwDataLen;
     957
     958  if (pcbData)
     959    dwDataLen = *pcbData;
     960
     961  dwRet = pfn(hKey, lpszValue, lpReserved, &dwType, pvData, &dwDataLen);
     962  if (!dwRet)
     963  {
     964    if (dwType == REG_EXPAND_SZ)
     965    {
     966      /* Expand type REG_EXPAND_SZ into REG_SZ */
     967      LPSTR szExpand;
     968      LPBYTE pData = pvData;
     969
     970      if (!pData)
     971      {
     972        /* Create a buffer to hold the data, to get the size */
     973        if (!pcbData ||
     974            !(pData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData)))
     975          return ERROR_OUTOFMEMORY;
     976        /* Read the data in to the buffer */
     977        if ((dwRet = pfn(hKey, lpszValue, lpReserved, &dwType,
     978                         pData, &dwDataLen)))
     979          return dwRet;
     980      }
     981
     982      if (!pcbData && pData != pvData)
     983      {
     984        /* Note: In this case the caller will crash under Win32 */
     985        WARN("Invalid pcbData would crash under Win32!");
     986        return ERROR_OUTOFMEMORY;
     987      }
     988
     989      szExpand = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pcbData);
     990      if (!szExpand)
     991      {
     992        if (pData != pvData)
     993          HeapFree(GetProcessHeap(), 0, pData);
     994        return ERROR_OUTOFMEMORY;
     995      }
     996      if ((ExpandEnvironmentStringsA(pvData, szExpand, *pcbData) <= 0))
     997      {
     998        dwDataLen = strlen(szExpand) + 1;
     999        strncpy(pvData, szExpand, *pcbData);
     1000      }
     1001      else
     1002      {
     1003        if (pData != pvData)
     1004          HeapFree(GetProcessHeap(), 0, pData);
     1005        HeapFree(GetProcessHeap(), 0, szExpand);
     1006        return GetLastError();
     1007      }
     1008      if (pData != pvData)
     1009        HeapFree(GetProcessHeap(), 0, pData);
     1010      HeapFree(GetProcessHeap(), 0, szExpand);
     1011      dwType = REG_SZ;
     1012    }
     1013    if (dwType == REG_SZ && pvData && pcbData && dwDataLen >= *pcbData)
     1014    {
     1015      /* String type too long: truncate it */
     1016      pvData[*pcbData] = '\0';
     1017    }
     1018  }
     1019  /* Update the type and data size if the caller wanted them */
     1020  if (pwType)
     1021    *pwType = dwType;
     1022  if (pcbData)
     1023    *pcbData  = dwDataLen;
     1024  return dwRet;
     1025}
     1026
     1027/*************************************************************************
     1028 * SHQueryValueExA   [SHLWAPI.@]
     1029 *
     1030 * Get a value from the registry, expanding environment variable strings.
     1031 *
     1032 * PARAMS
     1033 *   hKey       [I] Handle to registry key
     1034 *   lpszValue  [I] Name of value to delete
     1035 *   lpReserved [O] Reserved for future use; must be NULL
     1036 *   pwType     [O] Optional pointer updated with the values type
     1037 *   pvData     [O] Optional pointer updated with the values data
     1038 *   pcbData    [O] Optional pointer updated with the values size
     1039 *
     1040 * RETURNS
     1041 *   Success: ERROR_SUCCESS. Any non-NULL output parameters are updated with
     1042 *            information about the value.
     1043 *   Failure: ERROR_OUTOFMEMORY if memory allocation fails, or the type of the
     1044 *            data is REG_EXPAND_SZ and pcbData is NULL. Otherwise an error
     1045 *            code from RegQueryValueExA or ExpandEnvironmentStringsA.
     1046 *
     1047 * NOTES
     1048 *   Either pwType, pvData or pcbData may be NULL if the caller doesn't want
     1049 *   the type, data or size information for the value.
     1050 *
     1051 *   If the type of the data is REG_EXPAND_SZ, it is expanded to REG_SZ. The
     1052 *   value returned will be truncated if it is of type REG_SZ and bigger than
     1053 *   the buffer given to store it.
     1054 */
     1055DWORD WINAPI SHQueryValueExA(HKEY hKey, LPCSTR lpszValue,
     1056                             LPDWORD lpReserved, LPDWORD pwType,
     1057                             LPVOID pvData, LPDWORD pcbData)
     1058{
     1059  TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_a(lpszValue),
     1060        lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
     1061
     1062  return SHQueryValueExAW((RegQueryFn)RegQueryValueExA, hKey, lpszValue,
     1063                          lpReserved, pwType, pvData, pcbData);
     1064}
    2971065
    2981066/*************************************************************************
    2991067 * SHQueryValueExW   [SHLWAPI.@]
    3001068 *
    301  * FIXME
    302  *  if the datatype REG_EXPAND_SZ then expand the string and change
    303  *  *pdwType to REG_SZ.
    304  */
    305 HRESULT WINAPI SHQueryValueExW (
    306         HKEY hkey,
    307         LPWSTR pszValue,
    308         LPDWORD pdwReserved,
    309         LPDWORD pdwType,
    310         LPVOID pvData,
    311         LPDWORD pcbData)
    312 {
    313         WARN("0x%04x %s %p %p %p %p semi-stub\n",
    314              hkey, debugstr_w(pszValue), pdwReserved, pdwType, pvData, pcbData);
    315         return RegQueryValueExW ( hkey, pszValue, pdwReserved, pdwType, pvData, pcbData);
     1069 * See SHQueryValueExA.
     1070 */
     1071DWORD WINAPI SHQueryValueExW(HKEY hKey, LPCWSTR lpszValue,
     1072                             LPDWORD lpReserved, LPDWORD pwType,
     1073                             LPVOID pvData, LPDWORD pcbData)
     1074{
     1075  TRACE("(hkey=0x%08x,%s,%p,%p,%p,%p=%ld)\n", hKey, debugstr_w(lpszValue),
     1076        lpReserved, pwType, pvData, pcbData, pcbData ? *pcbData : 0);
     1077
     1078  return SHQueryValueExAW((RegQueryFn)RegQueryValueExW, hKey, lpszValue,
     1079                          lpReserved, pwType, pvData, pcbData);
    3161080}
    3171081
     
    3191083 * SHDeleteKeyA   [SHLWAPI.@]
    3201084 *
    321  * It appears this function is made available to account for the differences
    322  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
    323  *
    324  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
    325  * WinNt/2k will only delete the key if empty.
    326  */
    327 HRESULT WINAPI SHDeleteKeyA(
    328         HKEY hKey,
    329         LPCSTR lpszSubKey)
    330 {
    331     DWORD r, dwKeyCount, dwSize, i, dwMaxSubkeyLen;
    332     HKEY hSubKey;
    333     LPSTR lpszName;
    334 
    335     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
    336 
    337     hSubKey = 0;
    338     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
    339     if(r != ERROR_SUCCESS)
    340         return r;
    341 
    342     /* find how many subkeys there are */
    343     dwKeyCount = 0;
    344     dwMaxSubkeyLen = 0;
    345     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
    346                     &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
    347     if(r != ERROR_SUCCESS)
     1085 * Delete a registry key and any sub keys/values present
     1086 *
     1087 * PARAMS
     1088 *   hKey       [I] Handle to registry key
     1089 *   lpszSubKey [I] Name of sub key to delete
     1090 *
     1091 * RETURNS
     1092 *   Success: ERROR_SUCCESS. The key is deleted.
     1093 *   Failure: An error code from RegOpenKeyExA, RegQueryInfoKeyA,
     1094 *          RegEnumKeyExA or RegDeleteKeyA.
     1095 */
     1096DWORD WINAPI SHDeleteKeyA(HKEY hKey, LPCSTR lpszSubKey)
     1097{
     1098  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
     1099  CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
     1100  HKEY hSubKey = 0;
     1101
     1102  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
     1103
     1104  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1105  if(!dwRet)
     1106  {
     1107    /* Find how many subkeys there are */
     1108    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1109                             &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
     1110    if(!dwRet)
    3481111    {
    349         RegCloseKey(hSubKey);
    350         return r;
     1112      dwMaxSubkeyLen++;
     1113      if (dwMaxSubkeyLen > sizeof(szNameBuf))
     1114        /* Name too big: alloc a buffer for it */
     1115        lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
     1116
     1117      if(!lpszName)
     1118        dwRet = ERROR_NOT_ENOUGH_MEMORY;
     1119      else
     1120      {
     1121        /* Recursively delete all the subkeys */
     1122        for(i = 0; i < dwKeyCount && !dwRet; i++)
     1123        {
     1124          dwSize = dwMaxSubkeyLen;
     1125          dwRet = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
     1126          if(!dwRet)
     1127            dwRet = SHDeleteKeyA(hSubKey, lpszName);
     1128        }
     1129        if (lpszName != szNameBuf)
     1130          HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
     1131      }
    3511132    }
    3521133
    353     /* alloc memory for the longest string terminating 0 */
    354     dwMaxSubkeyLen++;
    355     lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(CHAR));
    356     if(!lpszName)
     1134    RegCloseKey(hSubKey);
     1135    if(!dwRet)
     1136      dwRet = RegDeleteKeyA(hKey, lpszSubKey);
     1137  }
     1138  return dwRet;
     1139}
     1140
     1141/*************************************************************************
     1142 * SHDeleteKeyW   [SHLWAPI.@]
     1143 *
     1144 * See SHDeleteKeyA.
     1145 */
     1146DWORD WINAPI SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
     1147{
     1148  DWORD dwRet, dwKeyCount = 0, dwMaxSubkeyLen = 0, dwSize, i;
     1149  WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
     1150  HKEY hSubKey = 0;
     1151
     1152  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_w(lpszSubKey));
     1153
     1154  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1155  if(!dwRet)
     1156  {
     1157    /* Find how many subkeys there are */
     1158    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1159                             &dwMaxSubkeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
     1160    if(!dwRet)
    3571161    {
    358         RegCloseKey(hSubKey);
    359         return ERROR_NOT_ENOUGH_MEMORY;
     1162      dwMaxSubkeyLen++;
     1163      if (dwMaxSubkeyLen > sizeof(szNameBuf)/sizeof(WCHAR))
     1164        /* Name too big: alloc a buffer for it */
     1165        lpszName = HeapAlloc(GetProcessHeap(), 0, dwMaxSubkeyLen*sizeof(WCHAR));
     1166
     1167      if(!lpszName)
     1168        dwRet = ERROR_NOT_ENOUGH_MEMORY;
     1169      else
     1170      {
     1171        /* Recursively delete all the subkeys */
     1172        for(i = 0; i < dwKeyCount && !dwRet; i++)
     1173        {
     1174          dwSize = dwMaxSubkeyLen;
     1175          dwRet = RegEnumKeyExW(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
     1176          if(!dwRet)
     1177            dwRet = SHDeleteKeyW(hSubKey, lpszName);
     1178        }
     1179
     1180        if (lpszName != szNameBuf)
     1181          HeapFree(GetProcessHeap(), 0, lpszName); /* Free buffer if allocated */
     1182      }
    3601183    }
    3611184
    362     /* recursively delete all the subkeys */
    363     for(i=0; i<dwKeyCount; i++)
     1185    RegCloseKey(hSubKey);
     1186    if(!dwRet)
     1187      dwRet = RegDeleteKeyW(hKey, lpszSubKey);
     1188  }
     1189  return dwRet;
     1190}
     1191
     1192/*************************************************************************
     1193 * SHDeleteEmptyKeyA   [SHLWAPI.@]
     1194 *
     1195 * Delete a registry key with no sub keys.
     1196 *
     1197 * PARAMS
     1198 *   hKey       [I] Handle to registry key
     1199 *   lpszSubKey [I] Name of sub key to delete
     1200 *
     1201 * RETURNS
     1202 *   Success: ERROR_SUCCESS. The key is deleted.
     1203 *   Failure: If the key is not empty, returns ERROR_KEY_HAS_CHILDREN. Otherwise
     1204 *          returns an error code from RegOpenKeyExA, RegQueryInfoKeyA or
     1205 *          RegDeleteKeyA.
     1206 */
     1207DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
     1208{
     1209  DWORD dwRet, dwKeyCount = 0;
     1210  HKEY hSubKey = 0;
     1211
     1212  TRACE("(hkey=0x%08x,%s)\n", hKey, debugstr_a(lpszSubKey));
     1213
     1214  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1215  if(!dwRet)
     1216  {
     1217    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1218                             NULL, NULL, NULL, NULL, NULL, NULL, NULL);
     1219    RegCloseKey(hSubKey);
     1220    if(!dwRet)
    3641221    {
    365         dwSize = dwMaxSubkeyLen;
    366         r = RegEnumKeyExA(hSubKey, i, lpszName, &dwSize, NULL, NULL, NULL, NULL);
    367         if(r != ERROR_SUCCESS)
    368             break;
    369         r = SHDeleteKeyA(hSubKey, lpszName);
    370         if(r != ERROR_SUCCESS)
    371             break;
     1222      if (!dwKeyCount)
     1223        dwRet = RegDeleteKeyA(hKey, lpszSubKey);
     1224      else
     1225        dwRet = ERROR_KEY_HAS_CHILDREN;
    3721226    }
    373 
    374     HeapFree(GetProcessHeap(), 0, lpszName);
    375 
     1227  }
     1228  return dwRet;
     1229}
     1230
     1231/*************************************************************************
     1232 * SHDeleteEmptyKeyW   [SHLWAPI.@]
     1233 *
     1234 * See SHDeleteEmptyKeyA.
     1235 */
     1236DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
     1237{
     1238  DWORD dwRet, dwKeyCount = 0;
     1239  HKEY hSubKey = 0;
     1240
     1241  TRACE("(hkey=0x%08x, %s)\n", hKey, debugstr_w(lpszSubKey));
     1242
     1243  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1244  if(!dwRet)
     1245  {
     1246    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1247                             NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    3761248    RegCloseKey(hSubKey);
    377 
    378     if(r == ERROR_SUCCESS)
    379         r = RegDeleteKeyA(hKey, lpszSubKey);
    380 
    381     return r;
    382 }
    383 
    384 /*************************************************************************
    385  * SHDeleteKeyW   [SHLWAPI.@]
    386  *
    387  * It appears this function is made available to account for the differences
    388  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
    389  *
    390  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
    391  * WinNt/2k will only delete the key if empty.
    392  */
    393 HRESULT WINAPI SHDeleteKeyW(
    394         HKEY hkey,
    395         LPCWSTR pszSubKey)
    396 {
    397         FIXME("hkey=0x%08x, %s\n", hkey, debugstr_w(pszSubKey));
    398         return 0;
     1249    if(!dwRet)
     1250    {
     1251      if (!dwKeyCount)
     1252        dwRet = RegDeleteKeyW(hKey, lpszSubKey);
     1253      else
     1254        dwRet = ERROR_KEY_HAS_CHILDREN;
     1255    }
     1256  }
     1257  return dwRet;
     1258}
     1259
     1260/*************************************************************************
     1261 * SHDeleteOrphanKeyA   [SHLWAPI.@]
     1262 *
     1263 * Delete a registry key with no sub keys or values.
     1264 *
     1265 * PARAMS
     1266 *   hKey       [I] Handle to registry key
     1267 *   lpszSubKey [I] Name of sub key to possibly delete
     1268 *
     1269 * RETURNS
     1270 *   Success: ERROR_SUCCESS. The key has been deleted if it was an orphan.
     1271 *   Failure: An error from RegOpenKeyExA, RegQueryValueExA, or RegDeleteKeyA.
     1272 */
     1273DWORD WINAPI SHDeleteOrphanKeyA(HKEY hKey, LPCSTR lpszSubKey)
     1274{
     1275  HKEY hSubKey;
     1276  DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
     1277
     1278  TRACE("(hkey=0x%08x,%s)", hKey, debugstr_a(lpszSubKey));
     1279
     1280  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1281
     1282  if(!dwRet)
     1283  {
     1284    /* Get subkey and value count */
     1285    dwRet = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1286                             NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
     1287
     1288    if(!dwRet && !dwKeyCount && !dwValueCount)
     1289    {
     1290      dwRet = RegDeleteKeyA(hKey, lpszSubKey);
     1291    }
     1292    RegCloseKey(hSubKey);
     1293  }
     1294  return dwRet;
     1295}
     1296
     1297/*************************************************************************
     1298 * SHDeleteOrphanKeyW   [SHLWAPI.@]
     1299 *
     1300 * See SHDeleteOrphanKeyA.
     1301 */
     1302DWORD WINAPI SHDeleteOrphanKeyW(HKEY hKey, LPCWSTR lpszSubKey)
     1303{
     1304  HKEY hSubKey;
     1305  DWORD dwKeyCount = 0, dwValueCount = 0, dwRet;
     1306
     1307  TRACE("(hkey=0x%08x,%s)", hKey, debugstr_w(lpszSubKey));
     1308
     1309  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
     1310
     1311  if(!dwRet)
     1312  {
     1313    /* Get subkey and value count */
     1314    dwRet = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwKeyCount,
     1315                             NULL, NULL, &dwValueCount, NULL, NULL, NULL, NULL);
     1316
     1317    if(!dwRet && !dwKeyCount && !dwValueCount)
     1318    {
     1319      dwRet = RegDeleteKeyW(hKey, lpszSubKey);
     1320    }
     1321    RegCloseKey(hSubKey);
     1322  }
     1323  return dwRet;
    3991324}
    4001325
     
    4021327 * SHDeleteValueA   [SHLWAPI.@]
    4031328 *
    404  * Function opens the key, get/set/delete the value, then close the key.
    405  */
    406 HRESULT WINAPI SHDeleteValueA(HKEY hkey, LPCSTR pszSubKey, LPCSTR pszValue) {
    407     HKEY        subkey;
    408     HRESULT     hres;
    409 
    410     hres = RegOpenKeyA(hkey,pszSubKey,&subkey);
    411     if (hres)
    412         return hres;
    413     hres = RegDeleteValueA(subkey,pszValue);
    414     RegCloseKey(subkey);
    415     return hres;
     1329 * Delete a value from the registry.
     1330 *
     1331 * PARAMS
     1332 *   hKey       [I] Handle to registry key
     1333 *   lpszSubKey [I] Name of sub key containing value to delete
     1334 *   lpszValue  [I] Name of value to delete
     1335 *
     1336 * RETURNS
     1337 *   Success: ERROR_SUCCESS. The value is deleted.
     1338 *   Failure: An error code from RegOpenKeyExA or RegDeleteValueA.
     1339 */
     1340DWORD WINAPI SHDeleteValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue)
     1341{
     1342  DWORD dwRet;
     1343  HKEY hSubKey;
     1344
     1345  TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_a(lpszSubKey), debugstr_a(lpszValue));
     1346
     1347  dwRet = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
     1348  if (!dwRet)
     1349  {
     1350    dwRet = RegDeleteValueA(hSubKey, lpszValue);
     1351    RegCloseKey(hSubKey);
     1352  }
     1353  return dwRet;
    4161354}
    4171355
     
    4191357 * SHDeleteValueW   [SHLWAPI.@]
    4201358 *
    421  * Function opens the key, get/set/delete the value, then close the key.
    422  */
    423 HRESULT WINAPI SHDeleteValueW(HKEY hkey, LPCWSTR pszSubKey, LPCWSTR pszValue) {
    424     HKEY        subkey;
    425     HRESULT     hres;
    426 
    427     hres = RegOpenKeyW(hkey,pszSubKey,&subkey);
    428     if (hres)
    429         return hres;
    430     hres = RegDeleteValueW(subkey,pszValue);
    431     RegCloseKey(subkey);
    432     return hres;
    433 }
    434 
    435 /*************************************************************************
    436  * SHDeleteEmptyKeyA   [SHLWAPI.@]
    437  *
    438  * It appears this function is made available to account for the differences
    439  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
    440  *
    441  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
    442  * WinNt/2k will only delete the key if empty.
    443  */
    444 DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey)
    445 {
    446     DWORD r, dwKeyCount;
    447     HKEY hSubKey;
    448 
    449     TRACE("hkey=0x%08x, %s\n", hKey, debugstr_a(lpszSubKey));
    450 
    451     hSubKey = 0;
    452     r = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
    453     if(r != ERROR_SUCCESS)
    454         return r;
    455 
    456     dwKeyCount = 0;
    457     r = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, &dwKeyCount,
    458                     NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    459     if(r != ERROR_SUCCESS)
    460         return r;
    461 
     1359 * See SHDeleteValueA.
     1360 */
     1361DWORD WINAPI SHDeleteValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue)
     1362{
     1363  DWORD dwRet;
     1364  HKEY hSubKey;
     1365
     1366  TRACE("(hkey=0x%08x,%s,%s)\n", hKey, debugstr_w(lpszSubKey), debugstr_w(lpszValue));
     1367
     1368  dwRet = RegOpenKeyExW(hKey, lpszSubKey, 0, KEY_SET_VALUE, &hSubKey);
     1369  if (!dwRet)
     1370  {
     1371    dwRet = RegDeleteValueW(hSubKey, lpszValue);
    4621372    RegCloseKey(hSubKey);
    463 
    464     if(dwKeyCount)
    465         return ERROR_KEY_HAS_CHILDREN;
    466 
    467     r = RegDeleteKeyA(hKey, lpszSubKey);
    468 
    469     return r;
    470 }
    471 
    472 /*************************************************************************
    473  * SHDeleteEmptyKeyW   [SHLWAPI.@]
    474  *
    475  * It appears this function is made available to account for the differences
    476  * between the Win9x and WinNT/2k RegDeleteKeyA functions.
    477  *
    478  * According to docs, Win9x RegDeleteKeyA will delete all subkeys, whereas
    479  * WinNt/2k will only delete the key if empty.
    480  */
    481 DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey)
    482 {
    483     FIXME("hkey=0x%08x, %s\n", hKey, debugstr_w(lpszSubKey));
    484     return 0;
    485 }
    486 
    487 /*************************************************************************
    488  * SHLWAPI_205   [SHLWAPI.205]
     1373  }
     1374  return dwRet;
     1375}
     1376
     1377/*************************************************************************
     1378 * SHEnumKeyExA   [SHLWAPI.@]
     1379 *
     1380 * Enumerate sub keys in a registry key.
     1381 *
     1382 * PARAMS
     1383 *   hKey       [I] Handle to registry key
     1384 *   dwIndex    [I] Index of key to enumerate
     1385 *   lpszSubKey [O] Pointer updated with the subkey name
     1386 *   pwLen      [O] Pointer updated with the subkey length
     1387 *
     1388 * RETURN
     1389 *   Success: ERROR_SUCCESS. lpszSubKey and pwLen are updated.
     1390 *   Failure: An error code from RegEnumKeyExA.
     1391 */
     1392LONG WINAPI SHEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpszSubKey,
     1393                         LPDWORD pwLen)
     1394{
     1395  TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_a(lpszSubKey), pwLen);
     1396
     1397  return RegEnumKeyExA(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
     1398}
     1399
     1400/*************************************************************************
     1401 * SHEnumKeyExW   [SHLWAPI.@]
     1402 *
     1403 * See SHEnumKeyExA.
     1404 */
     1405LONG WINAPI SHEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpszSubKey,
     1406                         LPDWORD pwLen)
     1407{
     1408  TRACE("(hkey=0x%08x,%ld,%s,%p)\n", hKey, dwIndex, debugstr_w(lpszSubKey), pwLen);
     1409
     1410  return RegEnumKeyExW(hKey, dwIndex, lpszSubKey, pwLen, NULL, NULL, NULL, NULL);
     1411}
     1412
     1413/*************************************************************************
     1414 * SHEnumValueA   [SHLWAPI.@]
     1415 *
     1416 * Enumerate values in a registry key.
     1417 *
     1418 * PARAMS
     1419 *   hKey      [I] Handle to registry key
     1420 *   dwIndex   [I] Index of key to enumerate
     1421 *   lpszValue [O] Pointer updated with the values name
     1422 *   pwLen     [O] Pointer updated with the values length
     1423 *   pwType    [O] Pointer updated with the values type
     1424 *   pvData    [O] Pointer updated with the values data
     1425 *   pcbData   [O] Pointer updated with the values size
     1426 *
     1427 * RETURNS
     1428 *   Success: ERROR_SUCCESS. Output parameters are updated.
     1429 *   Failure: An error code from RegEnumValueExA.
     1430 */
     1431LONG WINAPI SHEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpszValue,
     1432                         LPDWORD pwLen, LPDWORD pwType,
     1433                         LPVOID pvData, LPDWORD pcbData)
     1434{
     1435  TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
     1436        debugstr_a(lpszValue), pwLen, pwType, pvData, pcbData);
     1437
     1438 return RegEnumValueA(hKey, dwIndex, lpszValue, pwLen, NULL,
     1439                      pwType, pvData, pcbData);
     1440}
     1441
     1442/*************************************************************************
     1443 * SHEnumValueW   [SHLWAPI.@]
     1444 *
     1445 * See SHEnumValueA.
     1446 */
     1447LONG WINAPI SHEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpszValue,
     1448                         LPDWORD pwLen, LPDWORD pwType,
     1449                         LPVOID pvData, LPDWORD pcbData)
     1450{
     1451  TRACE("(hkey=0x%08x,%ld,%s,%p,%p,%p,%p)\n", hKey, dwIndex,
     1452        debugstr_w(lpszValue), pwLen, pwType, pvData, pcbData);
     1453
     1454  return RegEnumValueW(hKey, dwIndex, lpszValue, pwLen, NULL,
     1455                       pwType, pvData, pcbData);
     1456}
     1457
     1458/*************************************************************************
     1459 * @   [SHLWAPI.205]
    4891460 *
    4901461 * Wrapper for SHGetValueA in case machine is in safe mode.
     
    4991470
    5001471/*************************************************************************
    501  * SHLWAPI_206   [SHLWAPI.206]
     1472 * @   [SHLWAPI.206]
    5021473 *
    5031474 * Unicode version of SHLWAPI_205.
     
    5121483
    5131484/*************************************************************************
    514  * SHLWAPI_320   [SHLWAPI.320]
    515  *
     1485 * @   [SHLWAPI.320]
     1486 *
     1487 * Set a content type in the registry.
     1488 *
     1489 * PARAMS
     1490 *   hKey       [I] Handle to registry key
     1491 *   lpszSubKey [I] Name of sub key under hKey
     1492 *   lpszValue  [I] Value to set
     1493 *
     1494 * RETURNS
     1495 *   Success: TRUE
     1496 *   Failure: FALSE
    5161497 */
    5171498BOOL WINAPI SHLWAPI_320(LPCSTR lpszSubKey, LPCSTR lpszValue)
    5181499{
    519   DWORD dwLen = strlen(lpszValue);
    520   HRESULT ret = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
    521                             REG_SZ, lpszValue, dwLen);
    522   return ret ? FALSE : TRUE;
    523 }
    524 
    525 /*************************************************************************
    526  * SHLWAPI_321   [SHLWAPI.321]
     1500  DWORD dwRet;
     1501
     1502  if (!lpszValue)
     1503  {
     1504    WARN("Invalid lpszValue would crash under Win32!");
     1505    return FALSE;
     1506  }
     1507
     1508  dwRet = SHSetValueA(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeA,
     1509                      REG_SZ, lpszValue, strlen(lpszValue));
     1510  return dwRet ? FALSE : TRUE;
     1511}
     1512
     1513/*************************************************************************
     1514 * @   [SHLWAPI.321]
    5271515 *
    5281516 * Unicode version of SHLWAPI_320.
     
    5301518BOOL WINAPI SHLWAPI_321(LPCWSTR lpszSubKey, LPCWSTR lpszValue)
    5311519{
    532   DWORD dwLen = strlenW(lpszValue);
    533   HRESULT ret = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
    534                             REG_SZ, lpszValue, dwLen);
    535   return ret ? FALSE : TRUE;
    536 }
    537 
    538 /*************************************************************************
    539  * SHLWAPI_322   [SHLWAPI.322]
    540  *
     1520  DWORD dwRet;
     1521
     1522  if (!lpszValue)
     1523  {
     1524    WARN("Invalid lpszValue would crash under Win32!");
     1525    return FALSE;
     1526  }
     1527
     1528  dwRet = SHSetValueW(HKEY_CLASSES_ROOT, lpszSubKey, lpszContentTypeW,
     1529                      REG_SZ, lpszValue, strlenW(lpszValue));
     1530  return dwRet ? FALSE : TRUE;
     1531}
     1532
     1533/*************************************************************************
     1534 * @   [SHLWAPI.322]
     1535 *
     1536 * Delete a content type from the registry.
     1537 *
     1538 * PARAMS
     1539 *   lpszSubKey [I] Name of sub key
     1540 *
     1541 * RETURNS
     1542 *   Success: TRUE
     1543 *   Failure: FALSE
    5411544 */
    5421545BOOL WINAPI SHLWAPI_322(LPCSTR lpszSubKey)
     
    5471550
    5481551/*************************************************************************
    549  * SHLWAPI_323   [SHLWAPI.323]
     1552 * @   [SHLWAPI.323]
    5501553 *
    5511554 * Unicode version of SHLWAPI_322.
     
    5571560}
    5581561
     1562
     1563/*************************************************************************
     1564 * SHRegDuplicateHKey   [SHLWAPI.@]
     1565 */
     1566HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
     1567{
     1568    HKEY newKey = 0;
     1569
     1570    RegOpenKeyExA(hKey, 0, 0, MAXIMUM_ALLOWED, &newKey);
     1571    TRACE("new key is %08x\n", newKey);
     1572    return newKey;
     1573}
  • trunk/src/shlwapi/reg_odin.cpp

    r6608 r7820  
    1 /* $Id: reg_odin.cpp,v 1.2 2001-08-30 19:19:57 phaller Exp $ */
     1/* $Id: reg_odin.cpp,v 1.3 2002-02-06 20:18:28 sandervl Exp $ */
    22
    33/*
     
    2727#include "winnls.h"
    2828#include "winversion.h"
     29#include "winuser.h"
    2930#include "winreg.h"
     31#include "wingdi.h"
    3032
    3133#include <heapstring.h>
     
    3335#include <win\winerror.h>
    3436#include "shlwapi_odin.h"
     37#define NO_SHLWAPI_STREAM
     38#include <shlwapi.h>
    3539
    3640
     
    5054 *****************************************************************************/
    5155
    52 ODINFUNCTION5(DWORD,  SHRegCreateUSKeyA,
    53               LPSTR,  lpszKeyName,
     56ODINFUNCTION5(LONG,  SHRegCreateUSKeyA,
     57              LPCSTR,  lpszKeyName,
    5458              REGSAM,  AccessType,
    5559              HUSKEY,  hRelativeUSKey,
     
    7478 *****************************************************************************/
    7579
    76 ODINFUNCTION5(DWORD,   SHRegCreateUSKeyW,
    77               LPWSTR,  lpszKeyName,
     80ODINFUNCTION5(LONG,   SHRegCreateUSKeyW,
     81              LPCWSTR,  lpszKeyName,
    7882              REGSAM,  AccessType,
    7983              HUSKEY,  hRelativeUSKey,
     
    114118
    115119
    116 /*****************************************************************************
    117  * Name      : DWORD SHRegGetBoolUSValueA
    118  * Purpose   : unknown
    119  * Parameters: unknown
    120  * Variables :
    121  * Result    : unknown
    122  * Remark    : SHLWAPI.SHRegGetBoolUSValueA
    123  * Status    : COMPLETELY IMPLEMENTED ? UNTESTED
    124  *
    125  * Author    : Patrick Haller [Wed, 1999/12/29 23:02]
    126  *****************************************************************************/
    127 
    128 ODINFUNCTION4(BOOL,    SHRegGetBoolUSValueA,
    129               LPCSTR,  pszSubKey,
    130               LPCSTR,  pszValue,
    131               BOOL,    fIgnoreHKCU,
    132               BOOL,    fDefault)
    133 {
    134   char  szBuffer[260];
    135   DWORD dwLength = sizeof(szBuffer);
    136   LONG  rc;
    137 
    138   dprintf(("subkey=%s, value=%s\n",
    139            pszSubKey,
    140            pszValue));
    141 
    142   rc = SHRegGetUSValueA(pszSubKey,
    143                         pszValue,
    144                         &fDefault,
    145                         szBuffer,
    146                         &dwLength,
    147                         fIgnoreHKCU,
    148                         fDefault ? "YES" : "NO",
    149                         fDefault ? 4 : 3);
    150   if (rc != ERROR_SUCCESS)
    151     return rc;
    152 
    153   if (lstrcmpiA("YES",
    154                 szBuffer) == 0)
    155     return 1;
    156   else
    157   if (lstrcmpiA("TRUE",
    158                 szBuffer) == 0)
    159     return 1;
    160   else
    161   if (lstrcmpiA("NO",
    162                 szBuffer) == 0)
    163     return 0;
    164   else
    165   if (lstrcmpiA("FALSE",
    166                 szBuffer) == 0)
    167     return 0;
    168 
    169 
    170   return ERROR_SUCCESS;  /* return success */
    171 }
    172 
    173 
    174 /*****************************************************************************
    175  * Name      : DWORD SHRegGetBoolUSValueW
    176  * Purpose   : unknown
    177  * Parameters: unknown
    178  * Variables :
    179  * Result    : unknown
    180  * Remark    : SHLWAPI.SHRegGetBoolUSValueW
    181  * Status    : STUB UNTESTED
    182  *
    183  * Author    : Patrick Haller [Wed, 1999/12/29 23:02]
    184  *****************************************************************************/
    185 
    186 ODINFUNCTION4(BOOL,    SHRegGetBoolUSValueW,
    187               LPCWSTR, pszSubKey,
    188               LPCWSTR, pszValue,
    189               BOOL,    fIgnoreHKCU,
    190               BOOL,    fDefault)
    191 {
    192   char  szBuffer[264];
    193   int   iLength;
    194 
    195   dprintf(("(%p),stub!\n", pszSubKey));
    196 
    197   return ERROR_SUCCESS;  /* return success */
    198 }
    199 
    200120
    201121/*****************************************************************************
     
    255175
    256176
    257 /*****************************************************************************
    258  * Name      : LONG SHRegCloseUSKey
    259  * Purpose   :
    260  * Parameters:
    261  * Variables :
    262  * Result    :
    263  * Remark    :
    264  * Status    : STUB UNTESTED
    265  *
    266  * Author    : Patrick Haller [2001-08-30]
    267  *****************************************************************************/
    268 
    269 ODINFUNCTION1(LONG,    SHRegCloseUSKey,
    270               HUSKEY,  hUSKey)
    271 {
    272   dprintf(("not implemented\n"));
    273  
    274   LONG rc = RegCloseKey(hUSKey);
    275   return rc;
    276 }
    277 
    278177
    279178/*****************************************************************************
     
    291190ODINFUNCTION3(LONG,    SHRegDeleteUSValueA,
    292191              HUSKEY,  hUSKey,
    293               LPSTR,   lpValue,
    294               DWORD,   dwFlags)
     192              LPCSTR,   lpValue,
     193              SHREGDEL_FLAGS,   dwFlags)
    295194{
    296195  dprintf(("not implemented\n"));
    297196 
    298197  LONG rc = RegDeleteValueA(hUSKey,
    299                             lpValue);
     198                            (LPSTR)lpValue);
    300199  return rc;
    301200}
     
    315214
    316215ODINFUNCTION3(LONG,    SHRegDeleteUSValueW,
    317               HKEY,    hKey,
    318               LPWSTR,  lpValue,
    319               DWORD,   dwFlags)
     216              HUSKEY,   hKey,
     217              LPCWSTR,  lpValue,
     218              SHREGDEL_FLAGS,   dwFlags)
    320219{
    321220  dprintf(("not implemented\n"));
    322221 
    323222  LONG rc = RegDeleteValueW(hKey,
    324                             lpValue);
     223                            (LPWSTR)lpValue);
    325224  return rc;
    326225}
    327226
    328227
    329 /*****************************************************************************
    330  * Name      : LONG SHDeleteOrphanKeyA
    331  * Purpose   :
    332  * Parameters:
    333  * Variables :
    334  * Result    :
    335  * Remark    :
    336  * Status    : STUB UNTESTED
    337  *
    338  * Author    : Patrick Haller [2001-08-30]
    339  *****************************************************************************/
    340 
    341 ODINFUNCTION2(LONG,    SHDeleteOrphanKeyA,
    342               HKEY,    hKey,
    343               LPCSTR,  lpszSubkey)
    344 {
    345   dprintf(("not implemented\n"));
    346  
    347   LONG rc = RegDeleteKeyA(hKey,
    348                           lpszSubkey);
    349   return rc;
    350 }
    351 
    352 
    353 /*****************************************************************************
    354  * Name      : LONG SHDeleteOrphanKeyW
    355  * Purpose   :
    356  * Parameters:
    357  * Variables :
    358  * Result    :
    359  * Remark    :
    360  * Status    : STUB UNTESTED
    361  *
    362  * Author    : Patrick Haller [2001-08-30]
    363  *****************************************************************************/
    364 
    365 ODINFUNCTION2(LONG,    SHDeleteOrphanKeyW,
    366               HKEY,    hKey,
    367               LPWSTR,  lpszSubkey)
    368 {
    369   dprintf(("not implemented\n"));
    370  
    371   LONG rc = RegDeleteKeyW(hKey,
    372                           lpszSubkey);
    373   return rc;
    374 }
    375 
    376228
    377229/*****************************************************************************
     
    389241ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyA,
    390242              HUSKEY,  hUSKey,
     243              LPCSTR,   lpszSubkey,
     244              SHREGDEL_FLAGS,   dwFlags)
     245{
     246  dprintf(("not yet implemented"));
     247  return 0;
     248}
     249
     250
     251/*****************************************************************************
     252 * Name      : LONG SHRegDeleteEmptyUSKeyW
     253 * Purpose   :
     254 * Parameters:
     255 * Variables :
     256 * Result    :
     257 * Remark    :
     258 * Status    : STUB UNTESTED
     259 *
     260 * Author    : Patrick Haller [2001-08-30]
     261 *****************************************************************************/
     262
     263ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyW,
     264              HUSKEY,  hUSKey,
     265              LPCWSTR,  lpszSubkey,
     266              SHREGDEL_FLAGS,   dwFlags)
     267{
     268  dprintf(("not yet implemented"));
     269  return 0;
     270}
     271
     272
     273/*****************************************************************************
     274 * Name      : LONG SHRegDeleteUSKeyA
     275 * Purpose   :
     276 * Parameters:
     277 * Variables :
     278 * Result    :
     279 * Remark    :
     280 * Status    : STUB UNTESTED
     281 *
     282 * Author    : Patrick Haller [2001-08-30]
     283 *****************************************************************************/
     284
     285ODINFUNCTION3(LONG,    SHRegDeleteUSKeyA,
     286              HUSKEY,  hUSKey,
    391287              LPSTR,   lpszSubkey,
    392288              DWORD,   dwFlags)
     
    398294
    399295/*****************************************************************************
    400  * Name      : LONG SHRegDeleteEmptyUSKeyW
    401  * Purpose   :
    402  * Parameters:
    403  * Variables :
    404  * Result    :
    405  * Remark    :
    406  * Status    : STUB UNTESTED
    407  *
    408  * Author    : Patrick Haller [2001-08-30]
    409  *****************************************************************************/
    410 
    411 ODINFUNCTION3(LONG,    SHRegDeleteEmptyUSKeyW,
     296 * Name      : LONG SHRegDeleteUSKeyW
     297 * Purpose   :
     298 * Parameters:
     299 * Variables :
     300 * Result    :
     301 * Remark    :
     302 * Status    : STUB UNTESTED
     303 *
     304 * Author    : Patrick Haller [2001-08-30]
     305 *****************************************************************************/
     306
     307ODINFUNCTION3(LONG,    SHRegDeleteUSKeyW,
    412308              HUSKEY,  hUSKey,
    413309              LPWSTR,  lpszSubkey,
     
    419315
    420316
    421 /*****************************************************************************
    422  * Name      : LONG SHRegDeleteUSKeyA
    423  * Purpose   :
    424  * Parameters:
    425  * Variables :
    426  * Result    :
    427  * Remark    :
    428  * Status    : STUB UNTESTED
    429  *
    430  * Author    : Patrick Haller [2001-08-30]
    431  *****************************************************************************/
    432 
    433 ODINFUNCTION3(LONG,    SHRegDeleteUSKeyA,
    434               HUSKEY,  hUSKey,
    435               LPSTR,   lpszSubkey,
    436               DWORD,   dwFlags)
    437 {
    438   dprintf(("not yet implemented"));
    439   return 0;
    440 }
    441 
    442 
    443 /*****************************************************************************
    444  * Name      : LONG SHRegDeleteUSKeyW
    445  * Purpose   :
    446  * Parameters:
    447  * Variables :
    448  * Result    :
    449  * Remark    :
    450  * Status    : STUB UNTESTED
    451  *
    452  * Author    : Patrick Haller [2001-08-30]
    453  *****************************************************************************/
    454 
    455 ODINFUNCTION3(LONG,    SHRegDeleteUSKeyW,
    456               HUSKEY,  hUSKey,
    457               LPWSTR,  lpszSubkey,
    458               DWORD,   dwFlags)
    459 {
    460   dprintf(("not yet implemented"));
    461   return 0;
    462 }
    463 
    464 
    465 /*****************************************************************************
    466  * Name      : LONG SHRegEnumUSKeyA
    467  * Purpose   :
    468  * Parameters:
    469  * Variables :
    470  * Result    :
    471  * Remark    :
    472  * Status    : STUB UNTESTED
    473  *
    474  * Author    : Patrick Haller [2001-08-30]
    475  *****************************************************************************/
    476 
    477 ODINFUNCTION5(LONG,    SHRegEnumUSKeyA,
    478               HUSKEY,  hUSKey,
    479               DWORD,   dwIndex,
    480               LPSTR,   lpszKeyName,
    481               LPDWORD, lpdwKeyNameSize,
    482               SHREGENUM_FLAGS, dwFlags)
    483 {
    484   dprintf(("not yet implemented"));
    485   return 0;
    486 }
    487 
    488 
    489 /*****************************************************************************
    490  * Name      : LONG SHRegEnumUSKeyW
    491  * Purpose   :
    492  * Parameters:
    493  * Variables :
    494  * Result    :
    495  * Remark    :
    496  * Status    : STUB UNTESTED
    497  *
    498  * Author    : Patrick Haller [2001-08-30]
    499  *****************************************************************************/
    500 
    501 ODINFUNCTION5(LONG,    SHRegEnumUSKeyW,
    502               HUSKEY,  hUSKey,
    503               DWORD,   dwIndex,
    504               LPWSTR,  lpszKeyName,
    505               LPDWORD, lpdwKeyNameSize,
    506               SHREGENUM_FLAGS, dwFlags)
    507 {
    508   dprintf(("not yet implemented"));
    509   return 0;
    510 }
    511317
    512318
     
    565371
    566372
    567 /*****************************************************************************
    568  * Name      : LONG SHRegQueryInfoUSKeyA
    569  * Purpose   :
    570  * Parameters:
    571  * Variables :
    572  * Result    :
    573  * Remark    :
    574  * Status    : STUB UNTESTED
    575  *
    576  * Author    : Patrick Haller [2001-08-30]
    577  *****************************************************************************/
    578 
    579 ODINFUNCTION5(LONG,    SHRegQueryInfoUSKeyA,
    580               LPDWORD,  lpdwSubKeyNum,
    581               LPDWORD,  lpdwMaxSubKeyNameSize,
    582               LPDWORD,  lpdwValueNum,
    583               LPDWORD,  lpdwMaxValueNameSize,
    584               SHREGENUM_FLAGS, dwFlags)
    585 {
    586   dprintf(("not yet implemented"));
    587   return 0;
    588 }
    589 
    590 
    591 /*****************************************************************************
    592  * Name      : LONG SHRegQueryInfoUSKeyW
    593  * Purpose   :
    594  * Parameters:
    595  * Variables :
    596  * Result    :
    597  * Remark    :
    598  * Status    : STUB UNTESTED
    599  *
    600  * Author    : Patrick Haller [2001-08-30]
    601  *****************************************************************************/
    602 
    603 ODINFUNCTION5(LONG,    SHRegQueryInfoUSKeyW,
    604               LPDWORD,  lpdwSubKeyNum,
    605               LPDWORD,  lpdwMaxSubKeyNameSize,
    606               LPDWORD,  lpdwValueNum,
    607               LPDWORD,  lpdwMaxValueNameSize,
    608               SHREGENUM_FLAGS, dwFlags)
    609 {
    610   dprintf(("not yet implemented"));
    611   return 0;
    612 }
    613 
    614 
    615 /*****************************************************************************
    616  * Name      : LONG SHRegWriteUSValueA
    617  * Purpose   :
    618  * Parameters:
    619  * Variables :
    620  * Result    :
    621  * Remark    :
    622  * Status    : STUB UNTESTED
    623  *
    624  * Author    : Patrick Haller [2001-08-30]
    625  *****************************************************************************/
    626 
    627 ODINFUNCTION6(LONG,     SHRegWriteUSValueA,
    628               HUSKEY,   hUSKey,
    629               LPCSTR,   lpszValueName,
    630               DWORD,    dwValueType,
    631               LPVOID,   lpValue,
    632               DWORD,    dwValueSize,
    633               DWORD,    dwFlags)
    634 {
    635   dprintf(("not yet implemented"));
    636   return 0;
    637 }
    638 
    639 
    640 /*****************************************************************************
    641  * Name      : LONG SHRegWriteUSValueW
    642  * Purpose   :
    643  * Parameters:
    644  * Variables :
    645  * Result    :
    646  * Remark    :
    647  * Status    : STUB UNTESTED
    648  *
    649  * Author    : Patrick Haller [2001-08-30]
    650  *****************************************************************************/
    651 
    652 ODINFUNCTION6(LONG,     SHRegWriteUSValueW,
    653               HUSKEY,   hUSKey,
    654               LPCWSTR,  lpszValueName,
    655               DWORD,    dwValueType,
    656               LPVOID,   lpValue,
    657               DWORD,    dwValueSize,
    658               DWORD,    dwFlags)
    659 {
    660   dprintf(("not yet implemented"));
    661   return 0;
    662 }
     373
  • trunk/src/shlwapi/regstream.c

    r6712 r7820  
    22 *      SHRegOpenStream
    33 */
    4 #ifdef __WIN32OS2__
    5 #include <odin.h>
    6 #include <odinwrap.h>
    7 #include <os2sel.h>
    8 
    94#include <string.h>
    10 #include <ctype.h>
    11 #include <wctype.h>
    12 #define HAVE_WCTYPE_H
    13 
    14 #define ICOM_CINTERFACE 1
    15 #define CINTERFACE 1
    16 
    17 #endif
    18 
    19 #include <string.h>
    205
    216#include "winerror.h"
     7#include "winbase.h"
    228#include "winreg.h"
    23 #include "wine/obj_storage.h"
    24 
    25 #include "heap.h"
     9#include "shlobj.h"
     10
    2611#include "debugtools.h"
    2712
     
    120105        ICOM_THIS(ISHRegStream, iface);
    121106
    122 ////    TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
     107        TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
    123108
    124109        *ppvObj = NULL;
     
    307292/*************************************************************************
    308293 * SHOpenRegStreamA                             [SHLWAPI.@]
     294 * SHOpenRegStream2A                            [SHLWAPI.@]
    309295 */
    310296IStream * WINAPI SHOpenRegStreamA(
     
    322308/*************************************************************************
    323309 * SHOpenRegStreamW                             [SHLWAPI.@]
     310 * SHOpenRegStream2W                            [SHLWAPI.@]
    324311 */
    325312IStream * WINAPI SHOpenRegStreamW(
  • trunk/src/shlwapi/shlstub.cpp

    r6608 r7820  
    1 /* $Id: shlstub.cpp,v 1.2 2001-08-30 19:19:58 phaller Exp $ */
     1/* $Id: shlstub.cpp,v 1.3 2002-02-06 20:18:28 sandervl Exp $ */
    22
    33/*
     
    3535
    3636ODINDEBUGCHANNEL(SHLWAPI-SHLSTUB)
    37 
    38 #include "shlwapi.h"
    3937
    4038
  • trunk/src/shlwapi/shlwapi.cpp

    r6375 r7820  
    1 /* $Id: shlwapi.cpp,v 1.11 2001-07-20 15:37:52 sandervl Exp $ */
     1/* $Id: shlwapi.cpp,v 1.12 2002-02-06 20:18:29 sandervl Exp $ */
    22
    33/*
     
    3333
    3434#include "debugtools.h"
     35#include "winbase.h"
    3536#include "winnls.h"
    3637#include "winversion.h"
     
    5152ODINDEBUGCHANNEL(SHLWAPI)
    5253
    53 #include "shlwapi.h"
    5454
    5555
     
    7070}
    7171
    72 #if 0
    73 // ----------------------------------------------------------------------
    74 // WINE_StringFromCLSID
    75 // ----------------------------------------------------------------------
    76 HRESULT WINAPI WINE_StringFromCLSID(const CLSID *rclsid, LPSTR idstr)
    77 {
    78 //    dprintf(("OLE32: WINE_StringFromCLSID"));
    79 
    80     if (rclsid == NULL)
    81     {
    82         dprintf(("       clsid: (NULL)"));
    83         *idstr = 0;
    84         return E_FAIL;
    85     }
    86 
    87     // Setup new string...
    88     sprintf(idstr, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
    89             rclsid->Data1,
    90             rclsid->Data2,
    91             rclsid->Data3,
    92             rclsid->Data4[0],
    93             rclsid->Data4[1],
    94             rclsid->Data4[2],
    95             rclsid->Data4[3],
    96             rclsid->Data4[4],
    97             rclsid->Data4[5],
    98             rclsid->Data4[6],
    99             rclsid->Data4[7]);
    100 
    101 //    dprintf(("       clsid: %s", idstr));
    102 
    103     return OLE_OK;
    104 }
    105 
    106 // ----------------------------------------------------------------------
    107 // StringFromGUID2
    108 // ----------------------------------------------------------------------
    109 int WINAPI StringFromGUID2(REFGUID rguid, LPOLESTR lpsz, int cbMax)
    110 {
    111 // NB cbMax is a CHARACTER count not a BYTE count... :-)
    112     char        tmp[50];
    113     size_t      strLen;
    114 
    115     // Setup new string...
    116     WINE_StringFromCLSID(rguid, tmp);
    117 
    118     strLen = (strlen(tmp) + 1);
    119     if (strLen > cbMax)
    120         strLen = cbMax;
    121 
    122     AsciiToUnicodeN(tmp, lpsz, strLen);
    123 
    124     return strLen;  // Num CHARACTERS including 0 terminator
    125 }
    126 #endif
    127 
    128 /*****************************************************************************
    129  * Name      : DllGetVersion
    130  * Purpose   : Return version information about the DLL used
    131  * Parameters:
    132  * Variables :
    133  * Result    :
    134  * Remark    : SHLWAPI.446
    135  * Status    : UNTESTED
    136  *
    137  * Author    :
    138  *****************************************************************************/
    139 
    140 typedef struct tagDLLVERSION
    141 {
    142   DWORD dwLength; // == 0x14
    143   DWORD dwMajorVersion;
    144   DWORD dwMinorVersion;
    145   DWORD dwRevision;
    146   DWORD dwBuildNumber;
    147 } DLLVERSION, *LPDLLVERSION;
    148 
    149 
    150 ODINFUNCTION1(DWORD,        DllGetVersion,
    151               LPDLLVERSION, lpBuffer)
    152 {
    153   if (lpBuffer == NULL)
    154     return E_INVALIDARG; // error code: invalid parameters
    155 
    156   if (IsBadWritePtr(lpBuffer,
    157                     20))
    158     return E_INVALIDARG;
    159  
    160   if (lpBuffer->dwLength != sizeof(DLLVERSION))
    161     return E_INVALIDARG;
    162      
    163   // our current version is 5.0.2314.1000
    164   lpBuffer->dwMajorVersion = 5;
    165 //lpBuffer->dwMinorVersion = 0;  // @@@PH not touched in windows code ?
    166   lpBuffer->dwRevision     = 2314;
    167   lpBuffer->dwBuildNumber  = 1;
    168  
    169   return ERROR_SUCCESS;
    170 }
  • trunk/src/shlwapi/shlwapi.def

    r6615 r7820  
    1 ; $Id: shlwapi.def,v 1.27 2001-08-31 19:56:34 phaller Exp $
     1; $Id: shlwapi.def,v 1.28 2002-02-06 20:18:29 sandervl Exp $
    22
    33; updated export ordinals to NT4 SP6 version of SHLWAPI.DLL
     
    3535                             _SHLWAPI_9@4                         @9  NONAME
    3636                             _SHLWAPI_10@8                        @10 NONAME
     37
    3738                             _SHLWAPI_11@20                       @11 NONAME
    3839                             _SHLWAPI_12@8                        @12 NONAME
     
    4041                             _SHLWAPI_14@8                        @14 NONAME
    4142                             _SHLWAPI_15@8                        @15 NONAME
    42     SHCreateThread         = _SHCreateThread@16                   @16
     43                             _SHLWAPI_16@16                       @16 NONAME
    4344                             _SHLWAPI_17@8                        @17 NONAME
    4445                             _SHLWAPI_18@8                        @18 NONAME
    4546                             _SHLWAPI_19@4                        @19 NONAME
     47
    4648                             _SHLWAPI_20@8                        @20 NONAME
    4749                             _SHLWAPI_21@8                        @21 NONAME
     
    4951                             _SHLWAPI_23@12                       @23 NONAME
    5052                             _SHLWAPI_24@12                       @24 NONAME
     53                             _SHLWAPI_25@4                        @25 NONAME
     54                             _SHLWAPI_26@4                        @26 NONAME
     55                             _SHLWAPI_27@4                        @27 NONAME
    5156                             _SHLWAPI_28@4                        @28 NONAME
     57                             _SHLWAPI_29@4                        @29 NONAME
     58
    5259                             _SHLWAPI_30@4                        @30 NONAME
     60                             _SHLWAPI_31@4                        @31 NONAME
    5361                             _SHLWAPI_32@4                        @32 NONAME
     62                             _SHLWAPI_33@4                        @33 NONAME
     63                             _SHLWAPI_34@4                        @34 NONAME
     64                             _SHLWAPI_35@12                       @35 NONAME
     65                             _SHLWAPI_36@16                       @36 NONAME
    5466                             _CallWindowProcW@20                  @37 NONAME
    5567                             _CharLowerW@4                        @38 NONAME
    5668                             _CharLowerBuffW@8                    @39 NONAME
     69
    5770                             _CharNextW@4                         @40 NONAME
    5871                             _CharPrevW@8                         @41 NONAME
     
    6073                             _CharUpperW@4                        @43 NONAME
    6174                             _CharUpperBuffW@8                    @44 NONAME
    62                              _CompareStringW@24                   @45 NONAME 
     75                             _CompareStringW@24                   @45 NONAME
    6376                             _CopyAcceleratorTableW@12            @46 NONAME
    6477                             _CreateAcceleratorTableW@8           @47 NONAME
    6578                             _CreateDCW@16                        @48 NONAME
    6679                             _CreateDialogParamW@20               @49 NONAME ; @@@PH imcomplete
     80
    6781                             _CreateDirectoryW@8                  @50 NONAME
    6882                             _CreateEventW@16                     @51 NONAME
     
    7589                             _DialogBoxIndirectParamW@20          @58 NONAME ; @@@PH imcomplete
    7690                             _DialogBoxParamW@20                  @59 NONAME ; @@@PH imcomplete
     91
    7792                             _DispatchMessageW@4                  @60 NONAME
    7893                             _DrawTextW@20                        @61 NONAME
     
    85100                             _FormatMessageW@28                   @68 NONAME
    86101                             _GetClassInfoW@12                    @69 NONAME
     102
    87103                             _GetClassLongW@8                     @70 NONAME
    88104                             _GetClassNameW@12                    @71 NONAME
     
    95111                             _GetMenuItemInfoW@16                 @78 NONAME
    96112                             _GetMessageW@16                      @79 NONAME
     113
    97114                             _GetModuleFileNameW@12               @80 NONAME
    98115                             _GetSystemDirectoryW@8               @81 NONAME
     
    105122                             _GetStringTypeExW@20                 @88 NONAME
    106123                             _GetTempFileNameW@16                 @89 NONAME
     124
    107125                             _GetTempPathW@8                      @90 NONAME
    108126                             _GetTextExtentPoint32W@16            @91 NONAME
     
    115133                             _InsertMenuW@20                      @98 NONAME
    116134                             _IsDialogMessageW@8                  @99 NONAME
     135
    117136                             _LoadAcceleratorsW@8                 @100 NONAME
    118137                             _LoadBitmapW@8                       @101 NONAME
     
    125144                             _MessageBoxIndirectW@4               @108 NONAME
    126145                             _ModifyMenuW@20                      @109 NONAME
     146
    127147                             _GetCharWidth32W@16                  @110 NONAME
    128148                             _GetCharacterPlacementW@24           @111 NONAME
     
    135155                             _PostThreadMessageW@16               @118 NONAME
    136156                             _RegCreateKeyW@12                    @119 NONAME
     157
    137158                             _RegCreateKeyExW@36                  @120 NONAME
    138159                             _RegDeleteKeyW@8                     @121 NONAME
     
    145166                             _RegQueryValueExW@24                 @128 NONAME
    146167                             _RegSetValueW@20                     @129 NONAME
     168
    147169                             _RegSetValueExW@24                   @130 NONAME
    148170                             _RegisterClassW@4                    @131 NONAME
     
    153175                             _SendMessageW@16                     @136 NONAME
    154176                             _SetCurrentDirectoryW@4              @137 NONAME
    155                              _SetDlgItemTextW@12                  @138
    156                              _SetMenuItemInfoW@16                 @139 ; @@@PH imcomplete
     177                             _SetDlgItemTextW@12                  @138 NONAME
     178                             _SetMenuItemInfoW@16                 @139 NONAME ; @@@PH imcomplete
     179
    157180                             _SetPropW@12                         @140 NONAME
    158181                             _SetWindowLongW@12                   @141 NONAME
     
    166189                             _WinHelpW@16                         @149 NONAME
    167190                             _wvsprintfW@12                       @150 NONAME
     191
    168192                             _SHLWAPI_151@12                      @151 NONAME
    169193                             _SHLWAPI_152@12                      @152 NONAME
    170194                             _SHLWAPI_153@12                      @153 NONAME
    171195                             _SHLWAPI_154@12                      @154 NONAME
    172 
     196;;;;_SHLWAPI_155@??                      @155 NONAME
    173197                             _SHLWAPI_156@8                       @156 NONAME
    174198                             _SHLWAPI_158@8                       @158 NONAME
    175 ; @@@PH dupe                 _CompareStringW@24                   @159 NONAME
     199                             _CompareStringW@24                   @159 NONAME
     200
    176201                             _SHLWAPI_160@8                       @160 NONAME
    177202                             _SHLWAPI_162@8                       @162 NONAME
     203
     204                             _SHLWAPI_164@24                      @164 NONAME
    178205                             _SHLWAPI_165@16                      @165 NONAME
    179206                             _SHLWAPI_169@4                       @169 NONAME
     207
    180208                             _SHLWAPI_170@4                       @170 NONAME
     209                             _SHLWAPI_172@8                       @172 NONAME
     210                             _SHLWAPI_174@8                       @174 NONAME
     211                             _SHLWAPI_176@16                      @176 NONAME
     212
     213
    181214                             _SHLWAPI_181@12                      @181 NONAME
    182215                             _SHLWAPI_183@4                       @183 NONAME
    183216                             _SHLWAPI_185@24                      @185 NONAME
     217
    184218                             _SHLWAPI_191@24                      @191 NONAME
    185219                             _SHLWAPI_193@0                       @193 NONAME
    186220                             _SHLWAPI_197@12                      @197 NONAME
     221                             _SHLWAPI_199@8                       @199 NONAME
     222
    187223                             _SHLWAPI_205@24                      @205 NONAME
    188224                             _SHLWAPI_206@24                      @206 NONAME
     225                             _SHLWAPI_208@20                      @208 NONAME
     226
     227                             _SHLWAPI_210@12                      @210 NONAME
     228                             _SHLWAPI_211@8                       @211 NONAME
     229
    189230                             _SHLWAPI_215@12                      @215 NONAME
    190231                             _SHLWAPI_217@12                      @217 NONAME
    191232                             _SHLWAPI_218@16                      @218 NONAME
    192233                             _SHLWAPI_219@16                      @219 NONAME
     234
    193235                             _SHLWAPI_222@4                       @222 NONAME
    194236                             _SHLWAPI_223@4                       @223 NONAME
     237
     238                             _SHLWAPI_236@4                       @236 NONAME
    195239                             _SHLWAPI_237@4                       @237 NONAME
     240                             _SHLWAPI_239@12                      @239 NONAME
     241
    196242                             _SHLWAPI_240@16                      @240 NONAME
    197 ; PH                          _SHLWAPI_241@0                       @241 NONAME
     243;;PH                             _SHLWAPI_241@0                       @241 NONAME
    198244                             _PathRemoveArgsA@4                   @241 NONAME
    199245                             _SHLWAPI_243@20                      @243 NONAME
     246
    200247;   AssocCreate            = _AssocCreate@20                      @253 ;by name
    201248;   AssocQueryKeyA         = _AssocQueryKeyA@20                   @254 ;by name
    202249;   AssocQueryKeyW         = _AssocQueryKeyW@20                   @255 ;by name
     250
    203251                             _SHLWAPI_266@16                      @266 NONAME
    204252                             _SHLWAPI_267@16                      @267 NONAME
    205253                             _SHLWAPI_268@8                       @268 NONAME
     254
    206255                             _SHLWAPI_276@0                       @276 NONAME ; -> SHEnumKeyExA
    207256                             _SHLWAPI_278@24                      @278 NONAME
     257
     258                             _SHLWAPI_289@12                      @289 NONAME
     259;;                             _SHLWAPI_284@20                      @294 NONAME
    208260                             _WritePrivateProfileStringW@16       @298 NONAME
    209261
     262                             _CreateFontW@56                      @300 NONAME
    210263                             _DrawTextExW@24                      @301 NONAME
    211 ; @@@PH dupe                 _GetMenuItemInfoW@16                 @302 NONAME ; FIXME CreateFontW
     264                             _GetMenuItemInfoW@16                 @302 NONAME
    212265                             _InsertMenuItemW@16                  @303 NONAME
    213266                             _CreateMetaFileW@4                   @304 NONAME
     
    223276                             _RegisterClassExW@4                  @314 NONAME
    224277                             _GetClassInfoExW@12                  @315 NONAME
    225 
     278;;316 stub SHCreateStreamOnFileAOld
     279;;317 stub SHCreateStreamOnFileWOld
    226280                             _SHLWAPI_318@16                      @318 NONAME
    227281                             _FindWindowExW@16                    @319 NONAME
     
    246300                             _RegDeleteValueW@8                   @347 NONAME
    247301
     302                             _SHLWAPI_356@12                      @356 NONAME
    248303                             _SHLWAPI_357@20                      @357 NONAME
    249304                             _SHLWAPI_358@24                      @358 NONAME
     
    253308
    254309                             _SHLWAPI_364@12                      @364 NONAME
    255                      
     310
    256311                             _RegEnumValueW@32                    @366 NONAME
    257312                             _WritePrivateProfileStructW@20       @367 NONAME
     
    266321;   AssocQueryStringA      = _AssocQueryStringA@20                @381
    267322;   AssocQueryStringByKeyA = _AssocQueryStringByKeyA@20           @382
     323;;383 stub AssocQueryStringByKeyW
     324;;384 stub AssocQueryStringW
    268325    ChrCmpIA               = _ChrCmpIA@8                          @385
    269   ; ChrCmpIW               = _ChrCmpIW@8                          @386
     326    ChrCmpIW               = _ChrCmpIW@8                          @386
     327;;387 stub ColorAdjustLuma
    270328
    271329                             _SHLWAPI_389@4                       @389 NONAME
     
    283341;                            _SHLWAPI_410@12                      @410 NONAME
    284342
     343                             _SHLWAPI_413@4                       @413 NONAME
     344
     345                             _TrackPopupMenuEx@24                 @428 NONAME
     346
    285347                             _SHLWAPI_431@4                       @431 NONAME
    286348
     
    288350
    289351                             _SHLWAPI_437@4                       @437 NONAME
    290          
     352
    291353                             _GetEnvironmentVariableW@12          @442 NONAME
    292354                             _GetSystemWindowsDirectoryA@8        @443 NONAME
    293355                             _GetSystemWindowsDirectoryW@8        @444 NONAME
    294   ; ColorRGBToHLS @445
    295 
    296     DllGetVersion          = _DllGetVersion@4                     @446
     356    ColorRGBToHLS          = _ColorRGBToHLS@16                    @445
     357
     358    DllGetVersion          = _SHLWAPI_DllGetVersion@4             @446
    297359    GetMenuPosFromID       = _GetMenuPosFromID@8                  @447
    298360    HashData               = _HashData@16                         @448
     
    424486    SHDeleteValueA         = _SHDeleteValueA@12                   @573
    425487    SHDeleteValueW         = _SHDeleteValueW@12                   @574
    426   ; SHEnumKeyExA           = _SHEnumKeyExA@?                      @575
    427   ; SHEnumKeyExW           = _SHEnumKeyExW@?                      @576
    428   ; SHEnumValueA           = _SHEnumValueA@?                      @577
    429   ; SHEnumValueW           = _SHEnumValueW@?                      @578
     488    SHEnumKeyExA           = _SHEnumKeyExA@16                     @575
     489    SHEnumKeyExW           = _SHEnumKeyExW@16                     @576
     490    SHEnumValueA           = _SHEnumValueA@28                     @577
     491    SHEnumValueW           = _SHEnumValueW@28                     @578
    430492    _SHGetInstanceExplorer = __SHGetInstanceExplorer@4            @579
    431493    SHGetInverseCMAP       = _SHGetInverseCMAP@8                  @580
     
    438500    SHOpenRegStreamA       = _SHOpenRegStreamA@16                 @587
    439501    SHOpenRegStreamW       = _SHOpenRegStreamW@16                 @588
    440   ; SHQueryInfoKeyA        = _SHQueryInfoKeyA@?                   @589
    441   ; SHQueryInfoKeyW        = _SHQueryInfoKeyW@?                   @590
     502    SHQueryInfoKeyA        = _SHQueryInfoKeyA@20                  @589
     503    SHQueryInfoKeyW        = _SHQueryInfoKeyW@20                  @590
    442504    SHQueryValueExA        = _SHQueryValueExA@24                  @591
    443505    SHQueryValueExW        = _SHQueryValueExW@24                  @592
     
    460522    SHRegOpenUSKeyA        = _SHRegOpenUSKeyA@20                  @609
    461523    SHRegOpenUSKeyW        = _SHRegOpenUSKeyW@20                  @610
    462   ; SHRegQueryInfoKeyA     = _SHRegQueryInfoKeyA@?                @611
    463   ; SHRegQueryInfoKeyW     = _SHRegQueryInfoKeyW@?                @612
     524;    SHRegQueryInfoKeyA     = _SHRegQueryInfoKeyA@24               @611
     525;    SHRegQueryInfoKeyW     = _SHRegQueryInfoKeyW@24               @612
    464526    SHRegQueryUSValueA     = _SHRegQueryUSValueA@32               @613
    465527    SHRegQueryUSValueW     = _SHRegQueryUSValueW@32               @614
     
    493555    StrCmpW                = _lstrcmpW@8                          @641
    494556    StrCpyNW               = _lstrcpynW@12                        @642
    495     StrCpyA                = _StrCpyA@8                                 ; not exported ?
     557;;;    StrCpyA                = _StrCpyA@8                                 ; not exported ?
    496558    StrCpyW                = _StrCpyW@8                           @643
    497559    StrDupA                = _StrDupA@4                           @644
     
    511573    StrPBrkW               = _StrPBrkW@8                          @658
    512574    StrRChrA               = _StrRChrA@12                         @659
    513   ; StrRChrIA              = _StrRChrIA@12                        @660
    514   ; StrRChrIW              = _StrRChrIW@12                        @661
     575    StrRChrIA              = _StrRChrIA@12                        @660
     576    StrRChrIW              = _StrRChrIW@12                        @661
    515577    StrRChrW               = _StrRChrW@12                         @662
    516     StrRStrIA              = _StrRStrIA@8                         @663
    517     StrRStrIW              = _StrRStrIW@8                         @664
     578    StrRStrIA              = _StrRStrIA@12                        @663
     579    StrRStrIW              = _StrRStrIW@12                        @664
    518580    StrRetToBufA           = _StrRetToBufA@16                     @665
    519581    StrRetToBufW           = _StrRetToBufW@16                     @666
  • trunk/src/shlwapi/shlwapi_odin.h

    r6608 r7820  
    1 /* $Id: shlwapi_odin.h,v 1.2 2001-08-30 19:19:58 phaller Exp $ */
     1/* $Id: shlwapi_odin.h,v 1.3 2002-02-06 20:18:29 sandervl Exp $ */
    22
    33/*
     
    3131typedef HUSKEY *PHUSKEY;
    3232
    33 typedef DWORD SHREGDEL_FLAGS;
    34 #define SHREGDEL_BOTH
    35 
    36 typedef DWORD SHREGENUM_FLAGS;
    37 #define SHREGENUM_HKCU   
    38 #define SHREGENUM_DEFAULT
    39 #define SHREGENUM_HKLM
    40 
    41 typedef DWORD SHREGSET_FLAGS;
    42 #define SHREGSET_HKLM
    43 #define SHREGSET_DEFAULT
    44    
     33   
    4534   
    4635   
  • trunk/src/shlwapi/string.c

    r7508 r7820  
    1 //Note: Odin changes marked by #ifdef __WIN32OS2__!
    2 #ifdef __WIN32OS2__
    3 #include <odin.h>
    4 #include <odinwrap.h>
    5 #include <os2sel.h>
    6 
    7 #include <string.h>
    8 #include <wctype.h>
    9 #include <wcstr.h>
    10 #define HAVE_WCTYPE_H
    11 #include <win\shlwapi.h>
    12 
    13 #include <heapstring.h>
    14 #include <winnls.h>
    15 #endif
    161#include <ctype.h>
    172#include <stdlib.h>
     
    249#include "wingdi.h"
    2510#include "winuser.h"
     11#include "winreg.h"
     12#ifdef __WIN32OS2__
     13#include "shlobj.h"
     14#define NO_SHLWAPI_STREAM
     15#include "shlwapi.h"
     16#else
     17#define NO_SHLWAPI_STREAM
    2618#include "shlwapi.h"
    2719#include "shlobj.h"
     20#endif
    2821#include "wine/unicode.h"
    2922#include "debugtools.h"
     
    3225
    3326/*************************************************************************
    34  * StrChrA                                      [SHLWAPI]
     27 * ChrCmpIA                                     [SHLWAPI.385]
     28 *
     29 * Note: Returns 0 (FALSE) if characters are equal (insensitive).
     30 */
     31BOOL WINAPI ChrCmpIA (WORD w1, WORD w2)
     32{
     33        TRACE("%c ? %c\n", w1, w2);
     34        return (toupper(w1) != toupper(w2));
     35}
     36
     37/*************************************************************************
     38 * ChrCmpIW                                     [SHLWAPI.386]
     39 *
     40 * Note: Returns 0 (FALSE) if characters are equal (insensitive).
     41 */
     42BOOL WINAPI ChrCmpIW (WCHAR w1, WCHAR w2)
     43{
     44        TRACE("%c ? %c\n", w1, w2);
     45        return (toupperW(w1) != toupperW(w2));
     46}
     47
     48/*************************************************************************
     49 * StrChrA                                      [SHLWAPI.@]
    3550 */
    3651LPSTR WINAPI StrChrA (LPCSTR str, WORD c)
     
    4156
    4257/*************************************************************************
    43  * StrChrW                                      [SHLWAPI]
     58 * StrChrW                                      [SHLWAPI.@]
    4459 *
    4560 */
     
    4964        return strchrW(str, x);
    5065}
    51 #ifndef __WIN32OS2__
    52 /*************************************************************************
    53  * StrCmpIW                                     [SHLWAPI]
     66
     67/*************************************************************************
     68 * StrCmpIW                                     [SHLWAPI.@]
    5469 */
    5570int WINAPI StrCmpIW ( LPCWSTR wstr1, LPCWSTR wstr2 )
     
    5873    return strcmpiW( wstr1, wstr2 );
    5974}
    60 #endif
    61 
    62 /*************************************************************************
    63  * StrCmpNA                                     [SHLWAPI]
     75
     76/*************************************************************************
     77 * StrCmpNA                                     [SHLWAPI.@]
    6478 */
    6579INT WINAPI StrCmpNA ( LPCSTR str1, LPCSTR str2, INT len)
     
    7084
    7185/*************************************************************************
    72  * StrCmpNW                                     [SHLWAPI]
     86 * StrCmpNW                                     [SHLWAPI.@]
    7387 */
    7488INT WINAPI StrCmpNW ( LPCWSTR wstr1, LPCWSTR wstr2, INT len)
     
    7993
    8094/*************************************************************************
    81  * StrCmpNIA                                    [SHLWAPI]
     95 * StrCmpNIA                                    [SHLWAPI.@]
    8296 */
    8397int WINAPI StrCmpNIA ( LPCSTR str1, LPCSTR str2, int len)
     
    88102
    89103/*************************************************************************
    90  * StrCmpNIW                                    [SHLWAPI]
     104 * StrCmpNIW                                    [SHLWAPI.@]
    91105 */
    92106int WINAPI StrCmpNIW ( LPCWSTR wstr1, LPCWSTR wstr2, int len)
     
    97111
    98112/*************************************************************************
    99  * StrCmpW                                      [SHLWAPI]
     113 * StrCmpW                                      [SHLWAPI.@]
    100114 */
    101115int WINAPI StrCmpW ( LPCWSTR wstr1, LPCWSTR wstr2 )
     
    106120
    107121/*************************************************************************
    108  * StrCatW                                      [SHLWAPI]
     122 * StrCatW                                      [SHLWAPI.@]
    109123 */
    110124LPWSTR WINAPI StrCatW( LPWSTR wstr1, LPCWSTR wstr2 )
     
    115129
    116130/*************************************************************************
    117  * StrCpyW                                      [SHLWAPI]
     131 * StrCpyW                                      [SHLWAPI.@]
    118132 */
    119133LPWSTR WINAPI StrCpyW( LPWSTR wstr1, LPCWSTR wstr2 )
     
    124138
    125139/*************************************************************************
    126  * StrCpyNW                                     [SHLWAPI]
     140 * StrCpyNW                                     [SHLWAPI.@]
    127141 */
    128142LPWSTR WINAPI StrCpyNW( LPWSTR wstr1, LPCWSTR wstr2, int n )
     
    133147
    134148/*************************************************************************
    135  * StrStrA                                      [SHLWAPI]
     149 * StrStrA                                      [SHLWAPI.@]
    136150 */
    137151LPSTR WINAPI StrStrA(LPCSTR lpFirst, LPCSTR lpSrch)
     
    148162
    149163/*************************************************************************
    150  * StrStrW                                      [SHLWAPI]
     164 * StrStrW                                      [SHLWAPI.@]
    151165 */
    152166LPWSTR WINAPI StrStrW(LPCWSTR lpFirst, LPCWSTR lpSrch)
     
    163177
    164178/*************************************************************************
    165  * StrStrIA                                     [SHLWAPI]
     179 * StrStrIA                                     [SHLWAPI.@]
    166180 */
    167181LPSTR WINAPI StrStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
     
    178192
    179193/*************************************************************************
    180  * StrStrIW                                     [SHLWAPI]
     194 * StrStrIW                                     [SHLWAPI.@]
    181195 */
    182196LPWSTR WINAPI StrStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
     
    193207
    194208/*************************************************************************
    195  *      StrToIntA                       [SHLWAPI]
     209 *      StrToIntA                       [SHLWAPI.@]
    196210 */
    197211int WINAPI StrToIntA(LPCSTR lpSrc)
     
    202216
    203217/*************************************************************************
    204  *      StrToIntW                       [SHLWAPI]
     218 *      StrToIntW                       [SHLWAPI.@]
    205219 */
    206220int WINAPI StrToIntW(LPCWSTR lpSrc)
     
    215229
    216230/*************************************************************************
    217  *      StrToIntExA                     [SHLWAPI]
     231 *      StrToIntExA                     [SHLWAPI.@]
    218232 */
    219233BOOL WINAPI StrToIntExA( LPCSTR pszString, DWORD dwFlags, LPINT piRet)
     
    225239
    226240/*************************************************************************
    227  *      StrToIntExW                     [SHLWAPI]
     241 *      StrToIntExW                     [SHLWAPI.@]
    228242 */
    229243BOOL WINAPI StrToIntExW( LPCWSTR pszString, DWORD dwFlags, LPINT piRet)
     
    235249
    236250/*************************************************************************
    237  *      StrDupA                 [SHLWAPI]
     251 *      StrDupA                 [SHLWAPI.@]
    238252 */
    239253LPSTR WINAPI StrDupA (LPCSTR lpSrc)
     
    249263
    250264/*************************************************************************
    251  *      StrDupW                 [SHLWAPI]
     265 *      StrDupW                 [SHLWAPI.@]
    252266 */
    253267LPWSTR WINAPI StrDupW (LPCWSTR lpSrc)
     
    263277
    264278/*************************************************************************
    265  *      StrCSpnA                [SHLWAPI]
     279 *      StrCSpnA                [SHLWAPI.@]
    266280 */
    267281int WINAPI StrCSpnA (LPCSTR lpStr, LPCSTR lpSet)
     
    287301
    288302/*************************************************************************
    289  *      StrCSpnW                [SHLWAPI]
     303 *      StrCSpnW                [SHLWAPI.@]
    290304 */
    291305int WINAPI StrCSpnW (LPCWSTR lpStr, LPCWSTR lpSet)
     
    320334
    321335    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
    322 
     336    if (!lpStart && !lpEnd) return NULL;
    323337    if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
    324338
     
    342356
    343357    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
     358    if (!lpStart && !lpEnd) return NULL;
    344359    if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
    345360
     
    351366
    352367
    353 /*************************************************************************
    354  *      StrCatBuffA             [SHLWAPI]
     368/**************************************************************************
     369 * StrRChrIA [SHLWAPI.@]
     370 *
     371 */
     372LPSTR WINAPI StrRChrIA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
     373{
     374    LPCSTR lpGotIt = NULL;
     375    BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
     376
     377    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
     378    if (!lpStart && !lpEnd) return NULL;
     379    if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
     380
     381    for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
     382    {
     383        if (dbcs) {
     384            /*
     385            if (_mbctoupper(*lpStart) == _mbctoupper(wMatch))
     386                lpGotIt = lpStart;
     387            */
     388            if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
     389        } else {
     390            if (toupper(*lpStart) == toupper(wMatch)) lpGotIt = lpStart;
     391        }
     392    }   
     393    return (LPSTR)lpGotIt;
     394}
     395
     396
     397/**************************************************************************
     398 * StrRChrIW [SHLWAPI.@]
     399 *
     400 */
     401LPWSTR WINAPI StrRChrIW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
     402{
     403    LPCWSTR lpGotIt = NULL;
     404
     405    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
     406    if (!lpStart && !lpEnd) return NULL;
     407    if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
     408
     409    for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
     410        if (toupperW(*lpStart) == toupperW(wMatch)) lpGotIt = lpStart;
     411
     412    return (LPWSTR)lpGotIt;
     413}
     414
     415
     416/*************************************************************************
     417 *      StrCatBuffA             [SHLWAPI.@]
    355418 *
    356419 * Appends back onto front, stopping when front is size-1 characters long.
     
    370433
    371434/*************************************************************************
    372  *      StrCatBuffW             [SHLWAPI]
     435 *      StrCatBuffW             [SHLWAPI.@]
    373436 *
    374437 * Appends back onto front, stopping when front is size-1 characters long.
     
    394457 * NOTES
    395458 *  the pidl is for STRRET OFFSET
     459 *
     460 * ***** NOTE *****
     461 *  This routine is identical to StrRetToStrNA in dlls/shell32/shellstring.c.
     462 *  It was duplicated there because not every version of Shlwapi.dll exports
     463 *  StrRetToBufA. If you change one routine, change them both. YOU HAVE BEEN
     464 *  WARNED.
     465 * ***** NOTE *****
    396466 */
    397467HRESULT WINAPI StrRetToBufA (LPSTRRET src, const ITEMIDLIST *pidl, LPSTR dest, DWORD len)
    398468{
    399         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
     469        TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest,len,src,pidl);
    400470
    401471        switch (src->uType)
     
    432502 * NOTES
    433503 *  the pidl is for STRRET OFFSET
     504 *
     505 * ***** NOTE *****
     506 *  This routine is identical to StrRetToStrNW in dlls/shell32/shellstring.c.
     507 *  It was duplicated there because not every version of Shlwapi.dll exports
     508 *  StrRetToBufW. If you change one routine, change them both. YOU HAVE BEEN
     509 *  WARNED.
     510 * ***** NOTE *****
    434511 */
    435512HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, DWORD len)
    436513{
    437         TRACE("dest=0x%p len=0x%lx strret=0x%p pidl=%p stub\n",dest,len,src,pidl);
     514        TRACE("dest=%p len=0x%lx strret=%p pidl=%p stub\n",dest,len,src,pidl);
    438515
    439516        switch (src->uType)
     
    469546
    470547/*************************************************************************
    471  * StrFormatByteSizeA                           [SHLWAPI]
     548 * StrFormatByteSizeA                           [SHLWAPI.@]
    472549 */
    473550LPSTR WINAPI StrFormatByteSizeA ( DWORD dw, LPSTR pszBuf, UINT cchBuf )
     
    491568
    492569/*************************************************************************
    493  * StrFormatByteSizeW                           [SHLWAPI]
     570 * StrFormatByteSizeW                           [SHLWAPI.@]
    494571 */
    495572LPWSTR WINAPI StrFormatByteSizeW ( DWORD dw, LPWSTR pszBuf, UINT cchBuf )
     
    503580
    504581/*************************************************************************
    505  *      StrNCatA        [SHLWAPI]
     582 *      StrNCatA        [SHLWAPI.@]
    506583 */
    507584LPSTR WINAPI StrNCatA(LPSTR front, LPCSTR back, INT cchMax)
     
    512589
    513590/*************************************************************************
    514  *      StrNCatW        [SHLWAPI]
     591 *      StrNCatW        [SHLWAPI.@]
    515592 */
    516593LPWSTR WINAPI StrNCatW(LPWSTR front, LPCWSTR back, INT cchMax)
     
    546623
    547624/*************************************************************************
    548  *      wnsprintfA      [SHLWAPI]
     625 *      wnsprintfA      [SHLWAPI.@]
    549626 */
    550627int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
     
    560637
    561638/*************************************************************************
    562  *      wnsprintfW      [SHLWAPI]
     639 *      wnsprintfW      [SHLWAPI.@]
    563640 */
    564641int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
  • trunk/src/shlwapi/string_odin.cpp

    r6650 r7820  
    1 /* $Id: string_odin.cpp,v 1.5 2001-09-05 13:48:39 bird Exp $ */
     1 /* $Id: string_odin.cpp,v 1.6 2002-02-06 20:18:30 sandervl Exp $ */
     2
    23/*
    34 * Win32 Lightweight SHELL32 for OS/2
     
    6970
    7071
    71 /*****************************************************************************
    72  * Name      : ChrCmpIA
    73  * Purpose   :
    74  * Parameters:
    75  * Variables :
    76  * Result    :
    77  * Remark    :
    78  * Status    : PARTIALLY IMPLEMENTED UNTESTED
    79  *
    80  * Author    : Patrick Haller [Wed, 1999/12/29 09:00]
    81  *****************************************************************************/
    82 
    83 ODINFUNCTION2(INT,    ChrCmpIA,
    84               INT,    ch1,
    85               INT,    ch2)
    86 {
    87   // Note: IsDBCSLeadByte ignored !
    88 
    89   if ( (ch1 >= 'A') && (ch1 <= 'Z') ) ch1 |= 0x20;
    90   if ( (ch2 >= 'A') && (ch2 <= 'Z') ) ch2 |= 0x20;
    91 
    92   return ch1 - ch2;
    93 }
    94 
    95 
    96 #if 0
    97 /*************************************************************************
    98  * OleStrToStrN                                 [SHELL32.78]
    99  */
    100 BOOL WINAPI OleStrToStrNA (LPSTR lpStr, INT nStr, LPCWSTR lpOle, INT nOle)
    101 {
    102         TRACE("%p %x %s %x\n", lpStr, nStr, debugstr_w(lpOle), nOle);
    103         return WideCharToMultiByte (0, 0, lpOle, nOle, lpStr, nStr, NULL, NULL);
    104 }
    105 
    106 BOOL WINAPI OleStrToStrNW (LPWSTR lpwStr, INT nwStr, LPCWSTR lpOle, INT nOle)
    107 {
    108         TRACE("%p %x %s %x\n", lpwStr, nwStr, debugstr_w(lpOle), nOle);
    109 
    110         if (lstrcpynW ( lpwStr, lpOle, nwStr))
    111         { return lstrlenW (lpwStr);
    112         }
    113         return 0;
    114 }
    115 
    116 BOOL WINAPI OleStrToStrNAW (LPVOID lpOut, INT nOut, LPCVOID lpIn, INT nIn)
    117 {
    118         if (VERSION_OsIsUnicode())
    119           return OleStrToStrNW ((LPWSTR)lpOut, nOut, (LPCWSTR)lpIn, nIn);
    120         return OleStrToStrNA ((LPSTR)lpOut, nOut, (LPCWSTR)lpIn, nIn);
    121 }
    122 
    123 /*************************************************************************
    124  * StrToOleStrN                                 [SHELL32.79]
    125  *  lpMulti, nMulti, nWide [IN]
    126  *  lpWide [OUT]
    127  */
    128 BOOL WINAPI StrToOleStrNA (LPWSTR lpWide, INT nWide, LPCSTR lpStrA, INT nStr)
    129 {
    130         TRACE("%p %x %s %x\n", lpWide, nWide, lpStrA, nStr);
    131         return MultiByteToWideChar (0, 0, lpStrA, nStr, lpWide, nWide);
    132 }
    133 BOOL WINAPI StrToOleStrNW (LPWSTR lpWide, INT nWide, LPCWSTR lpStrW, INT nStr)
    134 {
    135         TRACE("%p %x %s %x\n", lpWide, nWide, debugstr_w(lpStrW), nStr);
    136 
    137         if (lstrcpynW (lpWide, lpStrW, nWide))
    138         { return lstrlenW (lpWide);
    139         }
    140         return 0;
    141 }
    142 
    143 BOOL WINAPI StrToOleStrNAW (LPWSTR lpWide, INT nWide, LPCVOID lpStr, INT nStr)
    144 {
    145         if (VERSION_OsIsUnicode())
    146           return StrToOleStrNW (lpWide, nWide, (LPWSTR)lpStr, nStr);
    147         return StrToOleStrNA (lpWide, nWide, (LPSTR)lpStr, nStr);
    148 }
    149 
    150 
    151 
    152 
    153 /************************************************************************
    154  *      StrToOleStr                     [SHELL32.163]
    155  *
    156  */
    157 int WINAPI StrToOleStrA (LPWSTR lpWideCharStr, LPCSTR lpMultiByteString)
    158 {
    159         TRACE("%p %p(%s)\n",
    160         lpWideCharStr, lpMultiByteString, lpMultiByteString);
    161 
    162         return MultiByteToWideChar(0, 0, lpMultiByteString, -1, lpWideCharStr, MAX_PATH);
    163 
    164 }
    165 int WINAPI StrToOleStrW (LPWSTR lpWideCharStr, LPCWSTR lpWString)
    166 {
    167         TRACE("%p %p(%s)\n",
    168         lpWideCharStr, lpWString, debugstr_w(lpWString));
    169 
    170         if (lstrcpyW (lpWideCharStr, lpWString ))
    171         { return lstrlenW (lpWideCharStr);
    172         }
    173         return 0;
    174 }
    175 
    176 BOOL WINAPI StrToOleStrAW (LPWSTR lpWideCharStr, LPCVOID lpString)
    177 {
    178         if (VERSION_OsIsUnicode())
    179           return StrToOleStrW (lpWideCharStr, (LPCWSTR)lpString);
    180         return StrToOleStrA (lpWideCharStr, (LPCSTR)lpString);
    181 }
    182 #endif
    18372
    18473
     
    20089ODINFUNCTION2(LPSTR,  StrChrIA,
    20190              LPCSTR, lpStart,
    202               WORD,   wMatch)
     91              char,   cMatch)
    20392{
    20493  LPSTR lpRes;
    20594
    206   wMatch = tolower(wMatch);
    207   lpRes = strchr(lpStart, wMatch);    // lower case comparsion
     95  cMatch = tolower(cMatch);
     96  lpRes = strchr(lpStart, cMatch);    // lower case comparsion
    20897  if (NULL == lpRes)
    20998  {
    210     wMatch = toupper(wMatch);
    211     lpRes = strchr(lpStart, wMatch);  // upper case comparsion
     99    cMatch = toupper(cMatch);
     100    lpRes = strchr(lpStart, cMatch);  // upper case comparsion
    212101  }
    213102
     
    293182       (lpString2 == NULL) )
    294183    return 0;
    295 
     184 
    296185  LPSTR lpLoop = (LPSTR)lpString1;
    297 
     186 
    298187  for (; (*lpLoop != 0); lpLoop++ )
    299188    if ( StrChrA( lpString2, *lpLoop ) )
    300189      return (INT) (lpLoop - lpString1);
    301 
     190 
    302191  return (INT) (lpLoop - lpString1);
    303192}
     
    327216       (lpString2 == NULL) )
    328217    return 0;
    329 
     218 
    330219  LPWSTR lpLoop = (LPWSTR)lpString1;
    331 
     220 
    332221  for (; (*lpLoop != 0); lpLoop++ )
    333222    if ( StrChrW( lpString2, *lpLoop ) )
    334223      return (INT) (lpLoop - lpString1);
    335 
     224 
    336225  return (INT) (lpLoop - lpString1);
    337226}
     
    344233 * Variables :
    345234 * Result    :
    346  * Remark    :
     235 * Remark    : 
    347236 * Status    : UNTESTED
    348237 *
     
    355244{
    356245  register LPSTR s1;
    357 
     246 
    358247  while (*lpString1)
    359248  {
     
    369258    lpString1++;
    370259  }
    371 
     260 
    372261  return (LPSTR)NULL;
    373262}
     
    380269 * Variables :
    381270 * Result    :
    382  * Remark    :
     271 * Remark    : 
    383272 * Status    : UNTESTED
    384273 *
     
    391280{
    392281  register LPWSTR s1;
    393 
     282 
    394283  while (*lpString1)
    395284  {
     
    405294    lpString1++;
    406295  }
    407 
     296 
    408297  return (LPWSTR)NULL;
    409298}
     
    411300
    412301/*************************************************************************
    413  * StrRStrIA                    [SHLWAPI]
     302 * StrRStrIA                                    [SHLWAPI]
    414303 */
    415 LPSTR WINAPI StrRStrIA(LPCSTR lpFirst, LPCSTR lpSrch)
     304LPSTR WINAPI StrRStrIA(LPCSTR lpFirst, LPCSTR lpSrch, LPCSTR unknown)
    416305{
    417306  INT   iLen = lstrlenA(lpFirst) - lstrlenA(lpSrch);
    418307
     308  dprintf(("StrRStrIA %x %x %x NOT IMPLEMENTED correctly", lpFirst, lpSrch, unknown));
     309 
    419310  // lpSrch cannot fit into lpFirst
    420311  if (iLen < 0)
    421312    return (LPSTR)NULL;
    422 
     313 
    423314  LPSTR lpThis = (LPSTR)lpFirst + iLen;
    424 
     315 
    425316  while (lpThis >= lpFirst)
    426317  {
     
    430321    lpThis--;
    431322  }
    432 
     323 
    433324  return NULL;
    434325}
     
    436327
    437328/*************************************************************************
    438  * StrRStrIW                    [SHLWAPI]
     329 * StrRStrIW                                    [SHLWAPI]
    439330 */
    440 LPWSTR WINAPI StrRStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch)
     331LPWSTR WINAPI StrRStrIW(LPCWSTR lpFirst, LPCWSTR lpSrch, LPCWSTR unknown)
    441332{
    442333  INT   iLen = lstrlenW(lpFirst) - lstrlenW(lpSrch);
    443334
     335  dprintf(("StrRStrIA %x %x %x NOT IMPLEMENTED correctly", lpFirst, lpSrch, unknown));
     336 
    444337  // lpSrch cannot fit into lpFirst
    445338  if (iLen < 0)
    446339    return (LPWSTR)NULL;
    447 
     340 
    448341  LPWSTR lpThis = (LPWSTR)lpFirst + iLen;
    449 
     342 
    450343  while (lpThis >= lpFirst)
    451344  {
     
    455348    lpThis--;
    456349  }
    457 
     350 
    458351  return NULL;
    459352}
  • trunk/src/shlwapi/url.c

    r7647 r7820  
    44 * Copyright 2000 Huw D M Davies for CodeWeavers.
    55 */
     6#ifdef __WIN32OS2__
     7#include <ctype.h>
     8#include <stdarg.h>
     9#include <winuser.h>
     10#endif
    611
    712#include <string.h>
     13#include <stdlib.h>
    814#include "windef.h"
     15#include "winnls.h"
    916#include "winbase.h"
    1017#include "winerror.h"
     18#include "wine/unicode.h"
     19#include "wininet.h"
     20#include "winreg.h"
     21#define NO_SHLWAPI_STREAM
    1122#include "shlwapi.h"
    1223#include "debugtools.h"
    13 
    14 #ifdef __WIN32OS2__
    15 #include <ctype.h>
    16 #endif
     24#include "ordinal.h"
     25
    1726
    1827DEFAULT_DEBUG_CHANNEL(shell);
     28
     29typedef struct {
     30    LPCWSTR pScheme;      /* [out] start of scheme                     */
     31    DWORD   szScheme;     /* [out] size of scheme (until colon)        */
     32    LPCWSTR pUserName;    /* [out] start of Username                   */
     33    DWORD   szUserName;   /* [out] size of Username (until ":" or "@") */
     34    LPCWSTR pPassword;    /* [out] start of Password                   */
     35    DWORD   szPassword;   /* [out] size of Password (until "@")        */
     36    LPCWSTR pHostName;    /* [out] start of Hostname                   */
     37    DWORD   szHostName;   /* [out] size of Hostname (until ":" or "/") */
     38    LPCWSTR pPort;        /* [out] start of Port                       */
     39    DWORD   szPort;       /* [out] size of Port (until "/" or eos)     */
     40    LPCWSTR pQuery;       /* [out] start of Query                      */
     41    DWORD   szQuery;      /* [out] size of Query (until eos)           */
     42} WINE_PARSE_URL;
     43
     44typedef enum {
     45    SCHEME,
     46    HOST,
     47    PORT,
     48    USERPASS,
     49} WINE_URL_SCAN_TYPE;
     50
     51static const WCHAR fileW[] = {'f','i','l','e','\0'};
    1952
    2053static const unsigned char HashDataLookup[256] = {
     
    4073 0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
    4174
    42 static BOOL URL_NeedEscape(CHAR ch, DWORD dwFlags)
     75static BOOL URL_NeedEscapeA(CHAR ch, DWORD dwFlags)
    4376{
    4477
     
    5285            return FALSE;
    5386    }
     87
     88    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
     89        return TRUE;
    5490
    5591    if (ch <= 31 || ch >= 127)
     
    73109            return TRUE;
    74110
     111        case '/':
     112        case '?':
     113            if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
    75114        default:
    76115            return FALSE;
     
    79118}
    80119
    81 /*************************************************************************
    82  *        UrlCanonicalizeA     [SHLWAPI]
     120static BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags)
     121{
     122
     123    if (isalnumW(ch))
     124        return FALSE;
     125
     126    if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
     127        if(ch == L' ')
     128            return TRUE;
     129        else
     130            return FALSE;
     131    }
     132
     133    if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == L'%'))
     134        return TRUE;
     135
     136    if (ch <= 31 || ch >= 127)
     137        return TRUE;
     138
     139    else {
     140        switch (ch) {
     141        case L' ':
     142        case L'<':
     143        case L'>':
     144        case L'\"':
     145        case L'{':
     146        case L'}':
     147        case L'|':
     148        case L'\\':
     149        case L'^':
     150        case L']':
     151        case L'[':
     152        case L'`':
     153        case L'&':
     154            return TRUE;
     155
     156        case L'/':
     157        case L'?':
     158            if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
     159        default:
     160            return FALSE;
     161        }
     162    }
     163}
     164
     165static BOOL URL_JustLocation(LPCWSTR str)
     166{
     167    while(*str && (*str == L'/')) str++;
     168    if (*str) {
     169        while (*str && ((*str == L'-') ||
     170                        (*str == L'.') ||
     171                        isalnumW(*str))) str++;
     172        if (*str == L'/') return FALSE;
     173    }
     174    return TRUE;
     175}
     176
     177
     178/*************************************************************************
     179 *        UrlCanonicalizeA     [SHLWAPI.@]
     180 *
     181 * Uses the W version to do job.
    83182 */
    84183HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
    85184        LPDWORD pcchCanonicalized, DWORD dwFlags)
    86185{
     186    LPWSTR base, canonical;
     187    DWORD ret, len, len2;
     188
     189    TRACE("(%s %p %p 0x%08lx) using W version\n",
     190          debugstr_a(pszUrl), pszCanonicalized,
     191          pcchCanonicalized, dwFlags);
     192
     193    base = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
     194                              (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
     195    canonical = base + INTERNET_MAX_URL_LENGTH;
     196
     197    MultiByteToWideChar(0, 0, pszUrl, -1, base, INTERNET_MAX_URL_LENGTH);
     198    len = INTERNET_MAX_URL_LENGTH;
     199
     200    ret = UrlCanonicalizeW(base, canonical, &len, dwFlags);
     201    if (ret != S_OK) {
     202        HeapFree(GetProcessHeap(), 0, base);
     203        return ret;
     204    }
     205
     206    len2 = WideCharToMultiByte(0, 0, canonical, len, 0, 0, 0, 0);
     207    if (len2 > *pcchCanonicalized) {
     208        *pcchCanonicalized = len;
     209        HeapFree(GetProcessHeap(), 0, base);
     210        return E_POINTER;
     211    }
     212    WideCharToMultiByte(0, 0, canonical, len+1, pszCanonicalized,
     213                        *pcchCanonicalized, 0, 0);
     214    *pcchCanonicalized = len2;
     215    HeapFree(GetProcessHeap(), 0, base);
     216    return S_OK;
     217}
     218
     219/*************************************************************************
     220 *        UrlCanonicalizeW     [SHLWAPI.@]
     221 *
     222 *
     223 * MSDN is wrong (at 10/30/01 - go figure). This should support the
     224 * following flags:                                      GLA
     225 *    URL_DONT_ESCAPE_EXTRA_INFO    0x02000000
     226 *    URL_ESCAPE_SPACES_ONLY        0x04000000
     227 *    URL_ESCAPE_PERCENT            0x00001000
     228 *    URL_ESCAPE_UNSAFE             0x10000000
     229 *    URL_UNESCAPE                  0x10000000
     230 *    URL_DONT_SIMPLIFY             0x08000000
     231 *    URL_ESCAPE_SEGMENT_ONLY       0x00002000
     232 */
     233HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
     234                                LPDWORD pcchCanonicalized, DWORD dwFlags)
     235{
    87236    HRESULT hr = S_OK;
    88 
    89     LPSTR lpszUrlCpy;
    90     INT nLen;
    91 
    92     TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszCanonicalized,
     237    DWORD EscapeFlags;
     238    LPWSTR lpszUrlCpy, wk1, wk2, mp, root;
     239    INT nLen, nByteLen, state;
     240
     241    TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized,
    93242          pcchCanonicalized, dwFlags);
    94243
    95     nLen = strlen(pszUrl);
    96     lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nLen + 1);
     244    nByteLen = (lstrlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */
     245    lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nByteLen);
    97246
    98247    if (dwFlags & URL_DONT_SIMPLIFY)
    99         memcpy(lpszUrlCpy, pszUrl, nLen + 1);
     248        memcpy(lpszUrlCpy, pszUrl, nByteLen);
    100249    else {
    101         FIXME("Simplify path\n");
    102         memcpy(lpszUrlCpy, pszUrl, nLen + 1);
     250
     251        /*
     252         * state =
     253         *         0   initial  1,3
     254         *         1   have 2[+] alnum  2,3
     255         *         2   have scheme (found :)  4,6,3
     256         *         3   failed (no location)
     257         *         4   have //  5,3
     258         *         5   have 1[+] alnum  6,3
     259         *         6   have location (found /) save root location
     260         */
     261
     262        wk1 = (LPWSTR)pszUrl;
     263        wk2 = lpszUrlCpy;
     264        state = 0;
     265        while (*wk1) {
     266            switch (state) {
     267            case 0:
     268                if (!isalnumW(*wk1)) {state = 3; break;}
     269                *wk2++ = *wk1++;
     270                if (!isalnumW(*wk1)) {state = 3; break;}
     271                *wk2++ = *wk1++;
     272                state = 1;
     273                break;
     274            case 1:
     275                *wk2++ = *wk1;
     276                if (*wk1++ == L':') state = 2;
     277                break;
     278            case 2:
     279                if (*wk1 != L'/') {state = 3; break;}
     280                *wk2++ = *wk1++;
     281                if (*wk1 != L'/') {state = 6; break;}
     282                *wk2++ = *wk1++;
     283                state = 4;
     284                break;
     285            case 3:
     286                strcpyW(wk2, wk1);
     287                wk1 += strlenW(wk1);
     288                wk2 += strlenW(wk2);
     289                break;
     290            case 4:
     291                if (!isalnumW(*wk1) && (*wk1 != L'-')) {state = 3; break;}
     292                while(isalnumW(*wk1) || (*wk1 == L'-')) *wk2++ = *wk1++;
     293                state = 5;
     294                break;
     295            case 5:
     296                if (*wk1 != L'/') {state = 3; break;}
     297                *wk2++ = *wk1++;
     298                state = 6;
     299                break;
     300            case 6:
     301                /* Now at root location, cannot back up any more. */
     302                /* "root" will point at the '/' */
     303                root = wk2-1;
     304                while (*wk1) {
     305                    TRACE("wk1=%c\n", (CHAR)*wk1);
     306                    mp = strchrW(wk1, L'/');
     307                    if (!mp) {
     308                        strcpyW(wk2, wk1);
     309                        wk1 += strlenW(wk1);
     310                        wk2 += strlenW(wk2);
     311                        continue;
     312                    }
     313                    nLen = mp - wk1 + 1;
     314                    strncpyW(wk2, wk1, nLen);
     315                    wk2 += nLen;
     316                    wk1 += nLen;
     317                    if (*wk1 == L'.') {
     318                        TRACE("found '/.'\n");
     319                        if (*(wk1+1) == L'/') {
     320                            /* case of /./ -> skip the ./ */
     321                            wk1 += 2;
     322                        }
     323                        else if (*(wk1+1) == L'.') {
     324                            /* found /..  look for next / */
     325                            TRACE("found '/..'\n");
     326                            if (*(wk1+2) == L'/') {
     327                                /* case /../ -> need to backup wk2 */
     328                                TRACE("found '/../'\n");
     329                                *(wk2-1) = L'\0';  /* set end of string */
     330                                mp = strrchrW(root, L'/');
     331                                if (mp && (mp >= root)) {
     332                                    /* found valid backup point */
     333                                    wk2 = mp + 1;
     334                                    wk1 += 3;
     335                                }
     336                                else {
     337                                    /* did not find point, restore '/' */
     338                                    *(wk2-1) = L'/';
     339                                }
     340                            }
     341                        }
     342                    }
     343                }
     344                *wk2 = L'\0';
     345                break;
     346            default:
     347                FIXME("how did we get here - state=%d\n", state);
     348                return E_INVALIDARG;
     349            }
     350        }
     351        *wk2 = L'\0';
     352        TRACE("Simplified, orig <%s>, simple <%s>\n",
     353              debugstr_w(pszUrl), debugstr_w(lpszUrlCpy));
    103354    }
    104355
    105356    if(dwFlags & URL_UNESCAPE)
    106         UrlUnescapeA(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
    107 
    108     if(dwFlags & (URL_ESCAPE_UNSAFE | URL_ESCAPE_SPACES_ONLY)) {
    109         DWORD EscapeFlags = dwFlags & (URL_ESCAPE_SPACES_ONLY
    110                                        /* | URL_ESCAPE_PERCENT */);
    111         hr = UrlEscapeA(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
     357        UrlUnescapeW(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
     358
     359    if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE |
     360                                 URL_ESCAPE_SPACES_ONLY |
     361                                 URL_ESCAPE_PERCENT |
     362                                 URL_DONT_ESCAPE_EXTRA_INFO |
     363                                 URL_ESCAPE_SEGMENT_ONLY ))) {
     364        EscapeFlags &= ~URL_ESCAPE_UNSAFE;
     365        hr = UrlEscapeW(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
    112366                        EscapeFlags);
    113     } else { /* No escapping needed, just copy the string */
    114         nLen = strlen(lpszUrlCpy);
     367    } else { /* No escaping needed, just copy the string */
     368        nLen = lstrlenW(lpszUrlCpy);
    115369        if(nLen < *pcchCanonicalized)
    116             memcpy(pszCanonicalized, lpszUrlCpy, nLen + 1);
     370            memcpy(pszCanonicalized, lpszUrlCpy, (nLen + 1)*sizeof(WCHAR));
    117371        else {
    118372            hr = E_POINTER;
     
    124378    HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
    125379 
     380    if (hr == S_OK)
     381        TRACE("result %s\n", debugstr_w(pszCanonicalized));
     382
    126383    return hr;
    127384}
    128385
    129386/*************************************************************************
    130  *        UrlCanonicalizeW     [SHLWAPI]
    131  */
    132 HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
    133                                 LPDWORD pcchCanonicalized, DWORD dwFlags)
    134 {
    135     FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
    136           pszCanonicalized, pcchCanonicalized, dwFlags);
    137     return E_NOTIMPL;
    138 }
    139 
    140 /*************************************************************************
    141  *      UrlEscapeA      [SHLWAPI]
     387 *        UrlCombineA     [SHLWAPI.@]
     388 *
     389 * Uses the W version to do job.
     390 */
     391HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative,
     392                           LPSTR pszCombined, LPDWORD pcchCombined,
     393                           DWORD dwFlags)
     394{
     395    LPWSTR base, relative, combined;
     396    DWORD ret, len, len2;
     397
     398    TRACE("(base %s, Relative %s, Combine size %ld, flags %08lx) using W version\n",
     399          debugstr_a(pszBase),debugstr_a(pszRelative),
     400          *pcchCombined,dwFlags);
     401
     402    base = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
     403                              (3*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
     404    relative = base + INTERNET_MAX_URL_LENGTH;
     405    combined = relative + INTERNET_MAX_URL_LENGTH;
     406
     407    MultiByteToWideChar(0, 0, pszBase, -1, base, INTERNET_MAX_URL_LENGTH);
     408    MultiByteToWideChar(0, 0, pszRelative, -1, relative, INTERNET_MAX_URL_LENGTH);
     409    len = INTERNET_MAX_URL_LENGTH;
     410
     411    ret = UrlCombineW(base, relative, combined, &len, dwFlags);
     412    if (ret != S_OK) {
     413        HeapFree(GetProcessHeap(), 0, base);
     414        return ret;
     415    }
     416
     417    len2 = WideCharToMultiByte(0, 0, combined, len, 0, 0, 0, 0);
     418    if (len2 > *pcchCombined) {
     419        *pcchCombined = len2;
     420        HeapFree(GetProcessHeap(), 0, base);
     421        return E_POINTER;
     422    }
     423    WideCharToMultiByte(0, 0, combined, len+1, pszCombined, *pcchCombined,
     424                        0, 0);
     425    *pcchCombined = len2;
     426    HeapFree(GetProcessHeap(), 0, base);
     427    return S_OK;
     428}
     429
     430/*************************************************************************
     431 *        UrlCombineW     [SHLWAPI.@]
     432 */
     433HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative,
     434                           LPWSTR pszCombined, LPDWORD pcchCombined,
     435                           DWORD dwFlags)
     436{
     437    UNKNOWN_SHLWAPI_2 base, relative;
     438    DWORD myflags, sizeloc = 0;
     439    DWORD len, res1, res2, process_case = 0;
     440    LPWSTR work, preliminary, mbase, mrelative;
     441    WCHAR myfilestr[] = {'f','i','l','e',':','/','/','/','\0'};
     442    WCHAR single_slash[] = {'/','\0'};
     443    HRESULT ret;
     444
     445    TRACE("(base %s, Relative %s, Combine size %ld, flags %08lx)\n",
     446          debugstr_w(pszBase),debugstr_w(pszRelative),
     447          *pcchCombined,dwFlags);
     448
     449    base.size = 24;
     450    relative.size = 24;
     451
     452    /* Get space for duplicates of the input and the output */
     453    preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
     454                            sizeof(WCHAR));
     455    mbase = preliminary + INTERNET_MAX_URL_LENGTH;
     456    mrelative = mbase + INTERNET_MAX_URL_LENGTH;
     457    *preliminary = L'\0';
     458
     459    /* Canonicalize the base input prior to looking for the scheme */
     460    myflags = dwFlags & (URL_DONT_SIMPLIFY | URL_UNESCAPE);
     461    len = INTERNET_MAX_URL_LENGTH;
     462    ret = UrlCanonicalizeW(pszBase, mbase, &len, myflags);
     463
     464    /* Canonicalize the relative input prior to looking for the scheme */
     465    len = INTERNET_MAX_URL_LENGTH;
     466    ret = UrlCanonicalizeW(pszRelative, mrelative, &len, myflags);
     467
     468    /* See if the base has a scheme */
     469    res1 = SHLWAPI_2(mbase, &base);
     470    if (res1) {
     471        /* if pszBase has no scheme, then return pszRelative */
     472        TRACE("no scheme detected in Base\n");
     473        process_case = 1;
     474    }
     475    else do {
     476
     477        /* get size of location field (if it exists) */
     478        work = (LPWSTR)base.ap2;
     479        sizeloc = 0;
     480        if (*work++ == L'/') {
     481            if (*work++ == L'/') {
     482                /* At this point have start of location and
     483                 * it ends at next '/' or end of string.
     484                 */
     485                while(*work && (*work != L'/')) work++;
     486                sizeloc = work - base.ap2;
     487            }
     488        }
     489
     490        /* Change .sizep2 to not have the last leaf in it,
     491         * Note: we need to start after the location (if it exists)
     492         */
     493        work = strrchrW((base.ap2+sizeloc), L'/');
     494        if (work) {
     495            len = work - base.ap2 + 1;
     496            base.sizep2 = len;
     497        }
     498        /*
     499         * At this point:
     500         *    .ap2      points to location (starting with '//')
     501         *    .sizep2   length of location (above) and rest less the last
     502         *              leaf (if any)
     503         *    sizeloc   length of location (above) up to but not including
     504         *              the last '/'
     505         */
     506
     507        res2 = SHLWAPI_2(mrelative, &relative);
     508        if (res2) {
     509            /* no scheme in pszRelative */
     510            TRACE("no scheme detected in Relative\n");
     511            relative.ap2 = mrelative;  /* case 3,4,5 depends on this */
     512            relative.sizep2 = strlenW(mrelative);
     513            if (*pszRelative  == L':') {
     514                /* case that is either left alone or uses pszBase */
     515                if (dwFlags & URL_PLUGGABLE_PROTOCOL) {
     516                    process_case = 5;
     517                    break;
     518                }
     519                process_case = 1;
     520                break;
     521            }
     522            if (isalnum(*mrelative) && (*(mrelative + 1) == L':')) {
     523                /* case that becomes "file:///" */
     524                strcpyW(preliminary, myfilestr);
     525                process_case = 1;
     526                break;
     527            }
     528            if ((*mrelative == L'/') && (*(mrelative+1) == L'/')) {
     529                /* pszRelative has location and rest */
     530                process_case = 3;
     531                break;
     532            }
     533            if (*mrelative == L'/') {
     534                /* case where pszRelative is root to location */
     535                process_case = 4;
     536                break;
     537            }
     538            process_case = (*base.ap2 == L'/') ? 5 : 3;
     539            break;
     540        }
     541
     542        /* handle cases where pszRelative has scheme */
     543        if ((base.sizep1 == relative.sizep1) &&
     544            (strncmpW(base.ap1, relative.ap1, base.sizep1) == 0)) {
     545
     546            /* since the schemes are the same */
     547            if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
     548                /* case where pszRelative replaces location and following */
     549                process_case = 3;
     550                break;
     551            }
     552            if (*relative.ap2 == L'/') {
     553                /* case where pszRelative is root to location */
     554                process_case = 4;
     555                break;
     556            }
     557            /* case where scheme is followed by document path */
     558            process_case = 5;
     559            break;
     560        }
     561        if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
     562            /* case where pszRelative replaces scheme, location,
     563             * and following and handles PLUGGABLE
     564             */
     565            process_case = 2;
     566            break;
     567        }
     568        process_case = 1;
     569        break;
     570    } while(FALSE); /* a litte trick to allow easy exit from nested if's */
     571
     572
     573    ret = S_OK;
     574    switch (process_case) {
     575
     576    case 1:  /*
     577              * Return pszRelative appended to what ever is in pszCombined,
     578              * (which may the string "file:///"
     579              */
     580        len = strlenW(mrelative) + strlenW(preliminary);
     581        if (len+1 > *pcchCombined) {
     582            *pcchCombined = len;
     583            ret = E_POINTER;
     584            break;
     585        }
     586        strcatW(preliminary, mrelative);
     587        break;
     588
     589    case 2:  /*
     590              * Same as case 1, but if URL_PLUGGABLE_PROTOCOL was specified
     591              * and pszRelative starts with "//", then append a "/"
     592              */
     593        len = strlenW(mrelative) + 1;
     594        if (len+1 > *pcchCombined) {
     595            *pcchCombined = len;
     596            ret = E_POINTER;
     597            break;
     598        }
     599        strcpyW(preliminary, mrelative);
     600        if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
     601            URL_JustLocation(relative.ap2))
     602            strcatW(preliminary, single_slash);
     603        break;
     604
     605    case 3:  /*
     606              * Return the pszBase scheme with pszRelative. Basicly
     607              * keeps the scheme and replaces the domain and following.
     608              */
     609        len = base.sizep1 + 1 + relative.sizep2 + 1;
     610        if (len+1 > *pcchCombined) {
     611            *pcchCombined = len;
     612            ret = E_POINTER;
     613            break;
     614        }
     615        strncpyW(preliminary, base.ap1, base.sizep1 + 1);
     616        work = preliminary + base.sizep1 + 1;
     617        strcpyW(work, relative.ap2);
     618        if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
     619            URL_JustLocation(relative.ap2))
     620            strcatW(work, single_slash);
     621        break;
     622
     623    case 4:  /*
     624              * Return the pszBase scheme and location but everything
     625              * after the location is pszRelative. (Replace document
     626              * from root on.)
     627              */
     628        len = base.sizep1 + 1 + sizeloc + relative.sizep2 + 1;
     629        if (len+1 > *pcchCombined) {
     630            *pcchCombined = len;
     631            ret = E_POINTER;
     632            break;
     633        }
     634        strncpyW(preliminary, base.ap1, base.sizep1+1+sizeloc);
     635        work = preliminary + base.sizep1 + 1 + sizeloc;
     636        if (dwFlags & URL_PLUGGABLE_PROTOCOL)
     637            *(work++) = L'/';
     638        strcpyW(work, relative.ap2);
     639        break;
     640
     641    case 5:  /*
     642              * Return the pszBase without its document (if any) and
     643              * append pszRelative after its scheme.
     644              */
     645        len = base.sizep1 + 1 + base.sizep2 + relative.sizep2;
     646        if (len+1 > *pcchCombined) {
     647            *pcchCombined = len;
     648            ret = E_POINTER;
     649            break;
     650        }
     651        strncpyW(preliminary, base.ap1, base.sizep1+1+base.sizep2);
     652        work = preliminary + base.sizep1+1+base.sizep2 - 1;
     653        if (*work++ != L'/')
     654            *(work++) = L'/';
     655        strcpyW(work, relative.ap2);
     656        break;
     657
     658    default:
     659        FIXME("How did we get here????? process_case=%ld\n", process_case);
     660        ret = E_INVALIDARG;
     661    }
     662
     663    if (ret == S_OK) {
     664        /*
     665         * Now that the combining is done, process the escape options if
     666         * necessary, otherwise just copy the string.
     667         */
     668        myflags = dwFlags & (URL_ESCAPE_PERCENT |
     669                             URL_ESCAPE_SPACES_ONLY |
     670                             URL_DONT_ESCAPE_EXTRA_INFO |
     671                             URL_ESCAPE_SEGMENT_ONLY);
     672        if (myflags)
     673            ret = UrlEscapeW(preliminary, pszCombined,
     674                             pcchCombined, myflags);
     675        else {
     676            len = (strlenW(preliminary) + 1) * sizeof(WCHAR);
     677            memcpy(pszCombined, preliminary, len);
     678            *pcchCombined = strlenW(preliminary);
     679        }
     680        TRACE("return-%ld len=%ld, %s\n",
     681              process_case, *pcchCombined, debugstr_w(pszCombined));
     682    }
     683    HeapFree(GetProcessHeap(), 0, preliminary);
     684    return ret;
     685}
     686
     687/*************************************************************************
     688 *      UrlEscapeA      [SHLWAPI.@]
    142689 *
    143690 * Converts unsafe characters into their escape sequences.
     
    156703 *
    157704 * BUGS:
    158  *
    159  * None of the URL_ define values are documented, so they were
    160  * determined by trial and error.  MSDN mentions URL_ESCAPE_PERCENT
    161  * but I can't find a value that does this under win2000.
    162  * URL_DONT_ESCAPE_EXTRA_INFO appears to be the default which is what
    163  * we assume here.  URL_ESCAPE_SEGMENT_ONLY is not implemented
    164  * (value??).  A value of 0x2000 for dwFlags seems to escape
    165  * '/'s too - this is neither documented on MSDN nor implemented here.
    166  * For character values that are converted see URL_NeedEscape.
     705 *  Have now implemented the following flags:
     706 *     URL_ESCAPE_SPACES_ONLY
     707 *     URL_DONT_ESCAPE_EXTRA_INFO
     708 *     URL_ESCAPE_SEGMENT_ONLY
     709 *     URL_ESCAPE_PERCENT
     710 *  Initial testing seems to indicate that this is now working like
     711 *  native shlwapi version 5. Note that these functions did not work
     712 *  well (or at all) in shlwapi version 4.
     713 *
    167714 */
    168715HRESULT WINAPI UrlEscapeA(
     
    174721    LPCSTR src;
    175722    DWORD needed = 0, ret;
    176     BOOL stop_escapping = FALSE;
     723    BOOL stop_escaping = FALSE;
    177724    char next[3], *dst = pszEscaped;
    178725    char hex[] = "0123456789ABCDEF";
     
    182729          pcchEscaped, dwFlags);
    183730
    184     if(dwFlags & ~URL_ESCAPE_SPACES_ONLY)
     731    if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
     732                   URL_ESCAPE_SEGMENT_ONLY |
     733                   URL_DONT_ESCAPE_EXTRA_INFO |
     734                   URL_ESCAPE_PERCENT))
    185735        FIXME("Unimplemented flags: %08lx\n", dwFlags);
    186736
     737    /* fix up flags */
     738    if (dwFlags & URL_ESCAPE_SPACES_ONLY)
     739        /* if SPACES_ONLY specified, reset the other controls */
     740        dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO |
     741                     URL_ESCAPE_PERCENT |
     742                     URL_ESCAPE_SEGMENT_ONLY);
     743
     744    else
     745        /* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
     746        dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
     747
    187748    for(src = pszUrl; *src; src++) {
    188         if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
     749        if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
     750           (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
    189751           (*src == '#' || *src == '?'))
    190             stop_escapping = TRUE;
    191 
    192         if(URL_NeedEscape(*src, dwFlags) && stop_escapping == FALSE) {
     752            stop_escaping = TRUE;
     753
     754        if(URL_NeedEscapeA(*src, dwFlags) && stop_escaping == FALSE) {
     755            /* TRACE("escaping %c\n", *src); */
    193756            next[0] = '%';
    194757            next[1] = hex[(*src >> 4) & 0xf];
     
    196759            len = 3;
    197760        } else {
     761            /* TRACE("passing %c\n", *src); */
    198762            next[0] = *src;
    199763            len = 1;
     
    219783
    220784/*************************************************************************
    221  *      UrlEscapeW      [SHLWAPI]
     785 *      UrlEscapeW      [SHLWAPI.@]
     786 *
     787 * See UrlEscapeA for list of assumptions, bugs, and FIXMEs
    222788 */
    223789HRESULT WINAPI UrlEscapeW(
     
    227793        DWORD dwFlags)
    228794{
    229     FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
    230           pszEscaped, pcchEscaped, dwFlags);
    231     return E_NOTIMPL;
    232 }
    233 
    234 
    235 /*************************************************************************
    236  *      UrlUnescapeA    [SHLWAPI]
     795    LPCWSTR src;
     796    DWORD needed = 0, ret;
     797    BOOL stop_escaping = FALSE;
     798    WCHAR next[5], *dst = pszEscaped;
     799    CHAR hex[] = "0123456789ABCDEF";
     800    INT len;
     801
     802    TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszEscaped,
     803          pcchEscaped, dwFlags);
     804
     805    if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
     806                   URL_ESCAPE_SEGMENT_ONLY |
     807                   URL_DONT_ESCAPE_EXTRA_INFO |
     808                   URL_ESCAPE_PERCENT))
     809        FIXME("Unimplemented flags: %08lx\n", dwFlags);
     810
     811    /* fix up flags */
     812    if (dwFlags & URL_ESCAPE_SPACES_ONLY)
     813        /* if SPACES_ONLY specified, reset the other controls */
     814        dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO |
     815                     URL_ESCAPE_PERCENT |
     816                     URL_ESCAPE_SEGMENT_ONLY);
     817
     818    else
     819        /* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
     820        dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
     821
     822    for(src = pszUrl; *src; src++) {
     823        /*
     824         * if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
     825         *   (*src == L'#' || *src == L'?'))
     826         *    stop_escaping = TRUE;
     827         */
     828        if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
     829           (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
     830           (*src == L'#' || *src == L'?'))
     831            stop_escaping = TRUE;
     832
     833        if(URL_NeedEscapeW(*src, dwFlags) && stop_escaping == FALSE) {
     834            /* TRACE("escaping %c\n", *src); */
     835            next[0] = L'%';
     836            /*
     837             * I would have assumed that the W form would escape
     838             * the character with 4 hex digits (or even 8),
     839             * however, experiments show that native shlwapi escapes
     840             * with only 2 hex digits.
     841             *   next[1] = hex[(*src >> 12) & 0xf];
     842             *   next[2] = hex[(*src >> 8) & 0xf];
     843             *   next[3] = hex[(*src >> 4) & 0xf];
     844             *   next[4] = hex[*src & 0xf];
     845             *   len = 5;
     846             */
     847            next[1] = hex[(*src >> 4) & 0xf];
     848            next[2] = hex[*src & 0xf];
     849            len = 3;
     850        } else {
     851            /* TRACE("passing %c\n", *src); */
     852            next[0] = *src;
     853            len = 1;
     854        }
     855
     856        if(needed + len <= *pcchEscaped) {
     857            memcpy(dst, next, len*sizeof(WCHAR));
     858            dst += len;
     859        }
     860        needed += len;
     861    }
     862
     863    if(needed < *pcchEscaped) {
     864        *dst = L'\0';
     865        ret = S_OK;
     866    } else {
     867        needed++; /* add one for the '\0' */
     868        ret = E_POINTER;
     869    }
     870    *pcchEscaped = needed;
     871    return ret;
     872}
     873
     874
     875/*************************************************************************
     876 *      UrlUnescapeA    [SHLWAPI.@]
    237877 *
    238878 * Converts escape sequences back to ordinary characters.
     
    260900    HRESULT ret;
    261901    DWORD needed;
    262     BOOL stop_unescapping = FALSE;
    263 
    264     TRACE("(%s, %p, %p, %08lx): stub\n", debugstr_a(pszUrl), pszUnescaped,
     902    BOOL stop_unescaping = FALSE;
     903
     904    TRACE("(%s, %p, %p, 0x%08lx)\n", debugstr_a(pszUrl), pszUnescaped,
    265905          pcchUnescaped, dwFlags);
    266906
     
    273913        if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
    274914           (*src == '#' || *src == '?')) {
    275             stop_unescapping = TRUE;
     915            stop_unescaping = TRUE;
    276916            next = *src;
    277917        } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
    278                   && stop_unescapping == FALSE) {
     918                  && stop_unescaping == FALSE) {
    279919            INT ih;
    280920            char buf[3];
     
    301941        *pcchUnescaped = needed;
    302942
     943    if (ret == S_OK) {
     944        TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
     945              debugstr_a(pszUrl) : debugstr_a(pszUnescaped));
     946    }
     947
    303948    return ret;
    304949}
    305950
    306951/*************************************************************************
    307  *      UrlUnescapeW    [SHLWAPI]
     952 *      UrlUnescapeW    [SHLWAPI.@]
     953 *
     954 * See UrlUnescapeA for list of assumptions, bugs, and FIXMEs
    308955 */
    309956HRESULT WINAPI UrlUnescapeW(
     
    313960        DWORD dwFlags)
    314961{
    315     FIXME("(%s, %p, %p, %08lx): stub\n", debugstr_w(pszUrl), pszUnescaped,
     962    WCHAR *dst, next;
     963    LPCWSTR src;
     964    HRESULT ret;
     965    DWORD needed;
     966    BOOL stop_unescaping = FALSE;
     967
     968    TRACE("(%s, %p, %p, 0x%08lx)\n", debugstr_w(pszUrl), pszUnescaped,
    316969          pcchUnescaped, dwFlags);
    317     return E_NOTIMPL;
    318 }
    319 
    320 /*************************************************************************
    321  *      HashData        [SHLWAPI]
     970
     971    if(dwFlags & URL_UNESCAPE_INPLACE)
     972        dst = (WCHAR*)pszUrl;
     973    else
     974        dst = pszUnescaped;
     975
     976    for(src = pszUrl, needed = 0; *src; src++, needed++) {
     977        if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
     978           (*src == L'#' || *src == L'?')) {
     979            stop_unescaping = TRUE;
     980            next = *src;
     981        } else if(*src == L'%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2))
     982                  && stop_unescaping == FALSE) {
     983            INT ih;
     984            WCHAR buf[3];
     985            memcpy(buf, src + 1, 2*sizeof(WCHAR));
     986            buf[2] = L'\0';
     987            ih = StrToIntW(buf);
     988            next = (WCHAR) ih;
     989            src += 2; /* Advance to end of escape */
     990        } else
     991            next = *src;
     992
     993        if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
     994            *dst++ = next;
     995    }
     996
     997    if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
     998        *dst = L'\0';
     999        ret = S_OK;
     1000    } else {
     1001        needed++; /* add one for the '\0' */
     1002        ret = E_POINTER;
     1003    }
     1004    if(!(dwFlags & URL_UNESCAPE_INPLACE))
     1005        *pcchUnescaped = needed;
     1006
     1007    if (ret == S_OK) {
     1008        TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ?
     1009              debugstr_w(pszUrl) : debugstr_w(pszUnescaped));
     1010    }
     1011
     1012    return ret;
     1013}
     1014
     1015/*************************************************************************
     1016 *      UrlGetLocationA         [SHLWAPI.@]
     1017 *
     1018 * Bugs/Features:
     1019 *  MSDN (as of 2001-11-01) says that:
     1020 *         "The location is the segment of the URL starting with a ?
     1021 *          or # character."
     1022 *     Neither V4 nor V5 of shlwapi.dll implement the '?' and always return
     1023 *     a NULL.
     1024 *  MSDN further states that:
     1025 *         "If a file URL has a query string, ther returned string
     1026 *          the query string."
     1027 *     In all test cases if the scheme starts with "fi" then a NULL is
     1028 *     returned. V5 gives the following results:
     1029 *       NULL     file://aa/b/cd#hohoh
     1030 *       #hohoh   http://aa/b/cd#hohoh
     1031 *       NULL     fi://aa/b/cd#hohoh
     1032 *       #hohoh   ff://aa/b/cd#hohoh
     1033 */
     1034LPCSTR WINAPI UrlGetLocationA(
     1035        LPCSTR pszUrl)
     1036{
     1037    UNKNOWN_SHLWAPI_1 base;
     1038    DWORD res1;
     1039
     1040    base.size = 24;
     1041    res1 = SHLWAPI_1(pszUrl, &base);
     1042    if (res1) return NULL;  /* invalid scheme */
     1043
     1044    /* if scheme is file: then never return pointer */
     1045    if (strncmp(base.ap1, "file", min(4,base.sizep1)) == 0) return NULL;
     1046
     1047    /* Look for '#' and return its addr */
     1048    return strchr(base.ap2, '#');
     1049}
     1050
     1051/*************************************************************************
     1052 *      UrlGetLocationW         [SHLWAPI.@]
     1053 *
     1054 * See UrlGetLocationA for list of assumptions, bugs, and FIXMEs
     1055 */
     1056LPCWSTR WINAPI UrlGetLocationW(
     1057        LPCWSTR pszUrl)
     1058{
     1059    UNKNOWN_SHLWAPI_2 base;
     1060    DWORD res1;
     1061
     1062    base.size = 24;
     1063    res1 = SHLWAPI_2(pszUrl, &base);
     1064    if (res1) return NULL;  /* invalid scheme */
     1065
     1066    /* if scheme is file: then never return pointer */
     1067    if (strncmpW(base.ap1, fileW, min(4,base.sizep1)) == 0) return NULL;
     1068
     1069    /* Look for '#' and return its addr */
     1070    return strchrW(base.ap2, L'#');
     1071}
     1072
     1073/*************************************************************************
     1074 *      UrlCompareA     [SHLWAPI.@]
     1075 */
     1076INT WINAPI UrlCompareA(
     1077        LPCSTR pszUrl1,
     1078        LPCSTR pszUrl2,
     1079        BOOL fIgnoreSlash)
     1080{
     1081    INT ret, len, len1, len2;
     1082
     1083    if (!fIgnoreSlash)
     1084        return strcmp(pszUrl1, pszUrl2);
     1085    len1 = strlen(pszUrl1);
     1086    if (pszUrl1[len1-1] == L'/') len1--;
     1087    len2 = strlen(pszUrl2);
     1088    if (pszUrl2[len2-1] == L'/') len2--;
     1089    if (len1 == len2)
     1090        return strncmp(pszUrl1, pszUrl2, len1);
     1091    len = min(len1, len2);
     1092    ret = strncmp(pszUrl1, pszUrl2, len);
     1093    if (ret) return ret;
     1094    if (len1 > len2) return 1;
     1095    return -1;
     1096}
     1097
     1098/*************************************************************************
     1099 *      UrlCompareW     [SHLWAPI.@]
     1100 */
     1101INT WINAPI UrlCompareW(
     1102        LPCWSTR pszUrl1,
     1103        LPCWSTR pszUrl2,
     1104        BOOL fIgnoreSlash)
     1105{
     1106    INT ret, len, len1, len2;
     1107
     1108    if (!fIgnoreSlash)
     1109        return strcmpW(pszUrl1, pszUrl2);
     1110    len1 = strlenW(pszUrl1);
     1111    if (pszUrl1[len1-1] == L'/') len1--;
     1112    len2 = strlenW(pszUrl2);
     1113    if (pszUrl2[len2-1] == L'/') len2--;
     1114    if (len1 == len2)
     1115        return strncmpW(pszUrl1, pszUrl2, len1);
     1116    len = min(len1, len2);
     1117    ret = strncmpW(pszUrl1, pszUrl2, len);
     1118    if (ret) return ret;
     1119    if (len1 > len2) return 1;
     1120    return -1;
     1121}
     1122
     1123/*************************************************************************
     1124 *      HashData        [SHLWAPI.@]
    3221125 *
    3231126 * Hash an input block into a variable sized digest.
     
    3521155
    3531156/*************************************************************************
    354  *      UrlHashA        [SHLWAPI]
     1157 *      UrlHashA        [SHLWAPI.@]
    3551158 *
    3561159 * Hash an ASCII URL.
     
    3661169
    3671170/*************************************************************************
     1171 *      UrlApplySchemeA [SHLWAPI.@]
     1172 */
     1173HRESULT WINAPI UrlApplySchemeA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
     1174{
     1175    LPWSTR in, out;
     1176    DWORD ret, len, len2;
     1177
     1178    TRACE("(in %s, out size %ld, flags %08lx) using W version\n",
     1179          debugstr_a(pszIn), *pcchOut, dwFlags);
     1180
     1181    in = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
     1182                              (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
     1183    out = in + INTERNET_MAX_URL_LENGTH;
     1184
     1185    MultiByteToWideChar(0, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH);
     1186    len = INTERNET_MAX_URL_LENGTH;
     1187
     1188    ret = UrlApplySchemeW(in, out, &len, dwFlags);
     1189    if ((ret != S_OK) && (ret != S_FALSE)) {
     1190        HeapFree(GetProcessHeap(), 0, in);
     1191        return ret;
     1192    }
     1193
     1194    len2 = WideCharToMultiByte(0, 0, out, len+1, 0, 0, 0, 0);
     1195    if (len2 > *pcchOut) {
     1196        *pcchOut = len2;
     1197        HeapFree(GetProcessHeap(), 0, in);
     1198        return E_POINTER;
     1199    }
     1200    WideCharToMultiByte(0, 0, out, len+1, pszOut, *pcchOut, 0, 0);
     1201    *pcchOut = len2;
     1202    HeapFree(GetProcessHeap(), 0, in);
     1203    return ret;
     1204}
     1205
     1206HRESULT URL_GuessScheme(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
     1207{
     1208    HKEY newkey;
     1209    BOOL j;
     1210    INT index, i;
     1211    DWORD value_len, data_len, dwType;
     1212    WCHAR reg_path[MAX_PATH];
     1213    WCHAR value[MAX_PATH], data[MAX_PATH];
     1214    WCHAR Wxx, Wyy;
     1215
     1216    MultiByteToWideChar(0, 0,
     1217              "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes",
     1218                        -1, reg_path, MAX_PATH);
     1219    RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey);
     1220    index = 0;
     1221    while(value_len = data_len = MAX_PATH,
     1222          RegEnumValueW(newkey, index, value, &value_len,
     1223                        0, &dwType, (LPVOID)data, &data_len) == 0) {
     1224        TRACE("guess %d %s is %s\n",
     1225              index, debugstr_w(value), debugstr_w(data));
     1226
     1227        j = FALSE;
     1228        for(i=0; i<value_len; i++) {
     1229            Wxx = pszIn[i];
     1230            Wyy = value[i];
     1231            /* remember that TRUE is not-equal */
     1232            j = ChrCmpIW(Wxx, Wyy);
     1233            if (j) break;
     1234        }
     1235        if ((i == value_len) && !j) {
     1236            if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
     1237                *pcchOut = strlenW(data) + strlenW(pszIn) + 1;
     1238                RegCloseKey(newkey);
     1239                return E_POINTER;
     1240            }
     1241            strcpyW(pszOut, data);
     1242            strcatW(pszOut, pszIn);
     1243            *pcchOut = strlenW(pszOut);
     1244            TRACE("matched and set to %s\n", debugstr_w(pszOut));
     1245            RegCloseKey(newkey);
     1246            return S_OK;
     1247        }
     1248        index++;
     1249    }
     1250    RegCloseKey(newkey);
     1251    return -1;
     1252}
     1253
     1254HRESULT URL_ApplyDefault(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut)
     1255{
     1256    HKEY newkey;
     1257    DWORD data_len, dwType;
     1258    WCHAR reg_path[MAX_PATH];
     1259    WCHAR value[MAX_PATH], data[MAX_PATH];
     1260
     1261    /* get and prepend default */
     1262    MultiByteToWideChar(0, 0,
     1263         "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\DefaultPrefix",
     1264                        -1, reg_path, MAX_PATH);
     1265    RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey);
     1266    data_len = MAX_PATH;
     1267    value[0] = L'@';
     1268    value[1] = L'\0';
     1269    RegQueryValueExW(newkey, value, 0, &dwType, (LPBYTE)data, &data_len);
     1270    RegCloseKey(newkey);
     1271    if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) {
     1272        *pcchOut = strlenW(data) + strlenW(pszIn) + 1;
     1273        return E_POINTER;
     1274    }
     1275    strcpyW(pszOut, data);
     1276    strcatW(pszOut, pszIn);
     1277    *pcchOut = strlenW(pszOut);
     1278    TRACE("used default %s\n", debugstr_w(pszOut));
     1279    return S_OK;
     1280}
     1281
     1282/*************************************************************************
    3681283 *      UrlApplySchemeW [SHLWAPI.@]
    3691284 */
    3701285HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
    3711286{
    372     HRESULT err = NOERROR;
    373     FIXME("(%s %p %p %08lx): stub !\n", debugstr_w(pszIn), pszOut, pcchOut, dwFlags);
    374     lstrcpyW(pszOut, pszIn);
    375     *pcchOut = (err != E_POINTER) ? lstrlenW(pszOut) : 0;
    376     return err;
    377 }
     1287    UNKNOWN_SHLWAPI_2 in_scheme;
     1288    DWORD res1;
     1289    HRESULT ret;
     1290
     1291    TRACE("(in %s, out size %ld, flags %08lx)\n",
     1292          debugstr_w(pszIn), *pcchOut, dwFlags);
     1293
     1294    if (dwFlags & URL_APPLY_GUESSFILE) {
     1295        FIXME("(%s %p %p(%ld) 0x%08lx): stub URL_APPLY_GUESSFILE not implemented\n",
     1296              debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwFlags);
     1297        strcpyW(pszOut, pszIn);
     1298        *pcchOut = strlenW(pszOut);
     1299        return S_FALSE;
     1300    }
     1301
     1302    in_scheme.size = 24;
     1303    /* See if the base has a scheme */
     1304    res1 = SHLWAPI_2(pszIn, &in_scheme);
     1305    if (res1) {
     1306        /* no scheme in input, need to see if we need to guess */
     1307        if (dwFlags & URL_APPLY_GUESSSCHEME) {
     1308            if ((ret = URL_GuessScheme(pszIn, pszOut, pcchOut)) != -1)
     1309                return ret;
     1310        }
     1311    }
     1312    else {
     1313        /* we have a scheme, see if valid (known scheme) */
     1314        if (in_scheme.fcncde) {
     1315            /* have valid scheme, so just copy and exit */
     1316            if (strlenW(pszIn) + 1 > *pcchOut) {
     1317                *pcchOut = strlenW(pszIn) + 1;
     1318                return E_POINTER;
     1319            }
     1320            strcpyW(pszOut, pszIn);
     1321            *pcchOut = strlenW(pszOut);
     1322            TRACE("valid scheme, returing copy\n");
     1323            return S_OK;
     1324        }
     1325    }
     1326
     1327    /* If we are here, then either invalid scheme,
     1328     * or no scheme and can't/failed guess.
     1329     */
     1330    if ( ( ((res1 == 0) && (dwFlags & URL_APPLY_FORCEAPPLY)) ||
     1331           ((res1 != 0)) ) &&
     1332         (dwFlags & URL_APPLY_DEFAULT)) {
     1333        /* find and apply default scheme */
     1334        return URL_ApplyDefault(pszIn, pszOut, pcchOut);
     1335    }
     1336
     1337    /* just copy and give proper return code */
     1338    if (strlenW(pszIn) + 1 > *pcchOut) {
     1339        *pcchOut = strlenW(pszIn) + 1;
     1340        return E_POINTER;
     1341    }
     1342    strcpyW(pszOut, pszIn);
     1343    *pcchOut = strlenW(pszOut);
     1344    TRACE("returing copy, left alone\n");
     1345    return S_FALSE;
     1346}
     1347
     1348/*************************************************************************
     1349 *      UrlIsA          [SHLWAPI.@]
     1350 */
     1351BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
     1352{
     1353    UNKNOWN_SHLWAPI_1 base;
     1354    DWORD res1;
     1355
     1356    switch (Urlis) {
     1357
     1358    case URLIS_OPAQUE:
     1359        base.size = 24;
     1360        res1 = SHLWAPI_1(pszUrl, &base);
     1361        if (res1) return FALSE;  /* invalid scheme */
     1362        if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
     1363            /* has scheme followed by 2 '/' */
     1364            return FALSE;
     1365        return TRUE;
     1366
     1367    case URLIS_URL:
     1368    case URLIS_NOHISTORY:
     1369    case URLIS_FILEURL:
     1370    case URLIS_APPLIABLE:
     1371    case URLIS_DIRECTORY:
     1372    case URLIS_HASQUERY:
     1373    default:
     1374        FIXME("(%s %d): stub\n", debugstr_a(pszUrl), Urlis);
     1375    }
     1376    return FALSE;
     1377}
     1378
     1379/*************************************************************************
     1380 *      UrlIsW          [SHLWAPI.@]
     1381 */
     1382BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
     1383{
     1384    UNKNOWN_SHLWAPI_2 base;
     1385    DWORD res1;
     1386
     1387    switch (Urlis) {
     1388
     1389    case URLIS_OPAQUE:
     1390        base.size = 24;
     1391        res1 = SHLWAPI_2(pszUrl, &base);
     1392        if (res1) return FALSE;  /* invalid scheme */
     1393        if ((*base.ap2 == L'/') && (*(base.ap2+1) == L'/'))
     1394            /* has scheme followed by 2 '/' */
     1395            return FALSE;
     1396        return TRUE;
     1397
     1398    case URLIS_URL:
     1399    case URLIS_NOHISTORY:
     1400    case URLIS_FILEURL:
     1401    case URLIS_APPLIABLE:
     1402    case URLIS_DIRECTORY:
     1403    case URLIS_HASQUERY:
     1404    default:
     1405        FIXME("(%s %d): stub\n", debugstr_w(pszUrl), Urlis);
     1406    }
     1407    return FALSE;
     1408}
     1409
     1410/*************************************************************************
     1411 *      UrlIsNoHistoryA         [SHLWAPI.@]
     1412 */
     1413BOOL WINAPI UrlIsNoHistoryA(LPCSTR pszUrl)
     1414{
     1415    return UrlIsA(pszUrl, URLIS_NOHISTORY);
     1416}
     1417
     1418/*************************************************************************
     1419 *      UrlIsNoHistoryW         [SHLWAPI.@]
     1420 */
     1421BOOL WINAPI UrlIsNoHistoryW(LPCWSTR pszUrl)
     1422{
     1423    return UrlIsW(pszUrl, URLIS_NOHISTORY);
     1424}
     1425
     1426/*************************************************************************
     1427 *      UrlIsOpaqueA    [SHLWAPI.@]
     1428 */
     1429BOOL WINAPI UrlIsOpaqueA(LPCSTR pszUrl)
     1430{
     1431    return UrlIsA(pszUrl, URLIS_OPAQUE);
     1432}
     1433
     1434/*************************************************************************
     1435 *      UrlIsOpaqueW    [SHLWAPI.@]
     1436 */
     1437BOOL WINAPI UrlIsOpaqueW(LPCWSTR pszUrl)
     1438{
     1439    return UrlIsW(pszUrl, URLIS_OPAQUE);
     1440}
     1441
     1442/*************************************************************************
     1443 *  Scans for characters of type "type" and when not matching found,
     1444 *  returns pointer to it and length in size.
     1445 *
     1446 * Characters tested based on RFC 1738
     1447 */
     1448LPCWSTR  URL_ScanID(LPCWSTR start, LPDWORD size, WINE_URL_SCAN_TYPE type)
     1449{
     1450    static DWORD alwayszero = 0;
     1451    BOOL cont = TRUE;
     1452
     1453    *size = 0;
     1454
     1455    switch(type){
     1456
     1457    case SCHEME:
     1458        while (cont) {
     1459            if ( (islowerW(*start) && isalphaW(*start)) ||
     1460                 isdigitW(*start) ||
     1461                 (*start == L'+') ||
     1462                 (*start == L'-') ||
     1463                 (*start == L'.')) {
     1464                start++;
     1465                (*size)++;
     1466            }
     1467            else
     1468                cont = FALSE;
     1469        }
     1470        break;
     1471
     1472    case USERPASS:
     1473        while (cont) {
     1474            if ( isalphaW(*start) ||
     1475                 isdigitW(*start) ||
     1476                 /* user/password only characters */
     1477                 (*start == L';') ||
     1478                 (*start == L'?') ||
     1479                 (*start == L'&') ||
     1480                 (*start == L'=') ||
     1481                 /* *extra* characters */
     1482                 (*start == L'!') ||
     1483                 (*start == L'*') ||
     1484                 (*start == L'\'') ||
     1485                 (*start == L'(') ||
     1486                 (*start == L')') ||
     1487                 (*start == L',') ||
     1488                 /* *safe* characters */
     1489                 (*start == L'$') ||
     1490                 (*start == L'_') ||
     1491                 (*start == L'+') ||
     1492                 (*start == L'-') ||
     1493                 (*start == L'.')) {
     1494                start++;
     1495                (*size)++;
     1496            } else if (*start == L'%') {
     1497                if (isxdigitW(*(start+1)) &&
     1498                    isxdigitW(*(start+2))) {
     1499                    start += 3;
     1500                    *size += 3;
     1501                } else
     1502                    cont = FALSE;
     1503            } else
     1504                cont = FALSE;
     1505        }
     1506        break;
     1507
     1508    case PORT:
     1509        while (cont) {
     1510            if (isdigitW(*start)) {
     1511                start++;
     1512                (*size)++;
     1513            }
     1514            else
     1515                cont = FALSE;
     1516        }
     1517        break;
     1518
     1519    case HOST:
     1520        while (cont) {
     1521            if (isalnumW(*start) ||
     1522                (*start == L'-') ||
     1523                (*start == L'.') ) {
     1524                start++;
     1525                (*size)++;
     1526            }
     1527            else
     1528                cont = FALSE;
     1529        }
     1530        break;
     1531    default:
     1532        FIXME("unknown type %d\n", type);
     1533        return (LPWSTR)&alwayszero;
     1534    }
     1535    /* TRACE("scanned %ld characters next char %p<%c>\n",
     1536     *size, start, *start); */
     1537    return start;
     1538}
     1539
     1540/*************************************************************************
     1541 *  Attempt to parse URL into pieces.
     1542 */
     1543LONG URL_ParseUrl(LPCWSTR pszUrl, WINE_PARSE_URL *pl)
     1544{
     1545    LPCWSTR work;
     1546
     1547    memset(pl, 0, sizeof(WINE_PARSE_URL));
     1548    pl->pScheme = pszUrl;
     1549    work = URL_ScanID(pl->pScheme, &pl->szScheme, SCHEME);
     1550#ifdef __WIN32OS2__
     1551    if (!*work || (*work != L':')) goto __ERROR;
     1552    work++;
     1553    if ((*work != L'/') || (*(work+1) != L'/')) goto __ERROR;
     1554#else
     1555    if (!*work || (*work != L':')) goto ERROR1;
     1556    work++;
     1557    if ((*work != L'/') || (*(work+1) != L'/')) goto ERROR;
     1558#endif
     1559    pl->pUserName = work + 2;
     1560    work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS);
     1561    if (*work == L':' ) {
     1562        /* parse password */
     1563        work++;
     1564        pl->pPassword = work;
     1565        work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS);
     1566        if (*work != L'@') {
     1567            /* what we just parsed must be the hostname and port
     1568             * so reset pointers and clear then let it parse */
     1569            pl->szUserName = pl->szPassword = 0;
     1570            work = pl->pUserName - 1;
     1571            pl->pUserName = pl->pPassword = 0;
     1572        }
     1573    } else if (*work == L'@') {
     1574        /* no password */
     1575        pl->szPassword = 0;
     1576        pl->pPassword = 0;
     1577    } else if (!*work || (*work == L'/') || (*work == L'.')) {
     1578        /* what was parsed was hostname, so reset pointers and let it parse */
     1579        pl->szUserName = pl->szPassword = 0;
     1580        work = pl->pUserName - 1;
     1581        pl->pUserName = pl->pPassword = 0;
     1582#ifdef __WIN32OS2__
     1583    } else goto __ERROR;
     1584#else
     1585    } else goto ERROR1;
     1586#endif
     1587    /* now start parsing hostname or hostnumber */
     1588    work++;
     1589    pl->pHostName = work;
     1590    work = URL_ScanID(pl->pHostName, &pl->szHostName, HOST);
     1591    if (*work == L':') {
     1592        /* parse port */
     1593        work++;
     1594        pl->pPort = work;
     1595        work = URL_ScanID(pl->pPort, &pl->szPort, PORT);
     1596    }
     1597    if (*work == L'/') {
     1598        /* see if query string */
     1599        pl->pQuery = strchrW(work, L'?');
     1600        if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery);
     1601    }
     1602    TRACE("parse successful: scheme=%p(%ld), user=%p(%ld), pass=%p(%ld), host=%p(%ld), port=%p(%ld), query=%p(%ld)\n",
     1603          pl->pScheme, pl->szScheme,
     1604          pl->pUserName, pl->szUserName,
     1605          pl->pPassword, pl->szPassword,
     1606          pl->pHostName, pl->szHostName,
     1607          pl->pPort, pl->szPort,
     1608          pl->pQuery, pl->szQuery);
     1609    return S_OK;
     1610#ifdef __WIN32OS2__
     1611  __ERROR:
     1612#else
     1613  ERROR:
     1614#endif
     1615    FIXME("failed to parse %s\n", debugstr_w(pszUrl));
     1616    return E_INVALIDARG;
     1617}
     1618
     1619/*************************************************************************
     1620 *      UrlGetPartA     [SHLWAPI.@]
     1621 */
     1622HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut,
     1623                           DWORD dwPart, DWORD dwFlags)
     1624{
     1625    LPWSTR in, out;
     1626    DWORD ret, len, len2;
     1627
     1628    in = (LPWSTR) HeapAlloc(GetProcessHeap(), 0,
     1629                              (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
     1630    out = in + INTERNET_MAX_URL_LENGTH;
     1631
     1632    MultiByteToWideChar(0, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH);
     1633
     1634    len = INTERNET_MAX_URL_LENGTH;
     1635    ret = UrlGetPartW(in, out, &len, dwPart, dwFlags);
     1636
     1637    if (ret != S_OK) {
     1638        HeapFree(GetProcessHeap(), 0, in);
     1639        return ret;
     1640    }
     1641
     1642    len2 = WideCharToMultiByte(0, 0, out, len, 0, 0, 0, 0);
     1643    if (len2 > *pcchOut) {
     1644        *pcchOut = len2;
     1645        HeapFree(GetProcessHeap(), 0, in);
     1646        return E_POINTER;
     1647    }
     1648    WideCharToMultiByte(0, 0, out, len+1, pszOut, *pcchOut, 0, 0);
     1649    *pcchOut = len2;
     1650    HeapFree(GetProcessHeap(), 0, in);
     1651    return S_OK;
     1652}
     1653
     1654/*************************************************************************
     1655 *      UrlGetPartW     [SHLWAPI.@]
     1656 */
     1657HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut,
     1658                           DWORD dwPart, DWORD dwFlags)
     1659{
     1660    WINE_PARSE_URL pl;
     1661    HRESULT ret;
     1662    DWORD size, schsize;
     1663    LPCWSTR addr, schaddr;
     1664    LPWSTR work;
     1665
     1666    TRACE("(%s %p %p(%ld) %08lx %08lx)\n",
     1667          debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags);
     1668
     1669    ret = URL_ParseUrl(pszIn, &pl);
     1670    if (!ret) {
     1671        schaddr = pl.pScheme;
     1672        schsize = pl.szScheme;
     1673
     1674        switch (dwPart) {
     1675        case URL_PART_SCHEME:
     1676            if (!pl.szScheme) return E_INVALIDARG;
     1677            addr = pl.pScheme;
     1678            size = pl.szScheme;
     1679            break;
     1680
     1681        case URL_PART_HOSTNAME:
     1682            if (!pl.szHostName) return E_INVALIDARG;
     1683            addr = pl.pHostName;
     1684            size = pl.szHostName;
     1685            break;
     1686
     1687        case URL_PART_USERNAME:
     1688            if (!pl.szUserName) return E_INVALIDARG;
     1689            addr = pl.pUserName;
     1690            size = pl.szUserName;
     1691            break;
     1692
     1693        case URL_PART_PASSWORD:
     1694            if (!pl.szPassword) return E_INVALIDARG;
     1695            addr = pl.pPassword;
     1696            size = pl.szPassword;
     1697            break;
     1698
     1699        case URL_PART_PORT:
     1700            if (!pl.szPort) return E_INVALIDARG;
     1701            addr = pl.pPort;
     1702            size = pl.szPort;
     1703            break;
     1704
     1705        case URL_PART_QUERY:
     1706            if (!pl.szQuery) return E_INVALIDARG;
     1707            addr = pl.pQuery;
     1708            size = pl.szQuery;
     1709            break;
     1710
     1711        default:
     1712            return E_INVALIDARG;
     1713        }
     1714
     1715        if (dwFlags == URL_PARTFLAG_KEEPSCHEME) {
     1716            if (*pcchOut < size + schsize + 2) {
     1717                *pcchOut = size + schsize + 2;
     1718                return E_POINTER;
     1719            }
     1720            strncpyW(pszOut, schaddr, schsize);
     1721            work = pszOut + schsize;
     1722            *work = L':';
     1723            strncpyW(work+1, addr, size);
     1724            *pcchOut = size + schsize + 1;
     1725            work += (size + 1);
     1726            *work = L'\0';
     1727        }
     1728        else {
     1729            if (*pcchOut < size + 1) {*pcchOut = size+1; return E_POINTER;}
     1730            strncpyW(pszOut, addr, size);
     1731            *pcchOut = size;
     1732            work = pszOut + size;
     1733            *work = L'\0';
     1734        }
     1735        TRACE("len=%ld %s\n", *pcchOut, debugstr_w(pszOut));
     1736    }
     1737    return ret;
     1738}
  • trunk/src/shlwapi/url_odin.cpp

    r6615 r7820  
    1 /* $Id: url_odin.cpp,v 1.3 2001-08-31 19:56:34 phaller Exp $ */
     1/* $Id: url_odin.cpp,v 1.4 2002-02-06 20:18:30 sandervl Exp $ */
    22
    33/*
     
    4141
    4242ODINDEBUGCHANNEL(SHLWAPI-URL)
    43 
    44 
    45 /*****************************************************************************
    46  * Defines                                                                   *
    47  *****************************************************************************/
    48 
    49 
    50 typedef struct tagURLSCHEME
    51 {
    52   LPSTR pszName;       /* such as http://                    */
    53   BOOL  flagOpaque;    /* has a double-slash '//             */
    54   BOOL  flagNoHistory; /* usually not in history of browsers */
    55   DWORD dwType;        /* URL type                           */
    56 
    57 } URLSCHEME, *PURLSCHEME;
    58 
    59 
    60 typedef enum tagURLIS
    61 {
    62   URLIS_APPLIABLE,   /* Attempt to determine a valid scheme for the URL. */
    63   URLIS_DIRECTORY,   /* Does the URL string end with a directory?        */
    64   URLIS_FILEURL,     /* Is the URL a file URL?                           */
    65   URLIS_HASQUERY,    /* Does the URL have an appended query string?      */
    66   URLIS_NOHISTORY,   /* Is the URL a "No History" URL?                   */
    67   URLIS_OPAQUE,      /* Is the URL opaque?                               */
    68   URLIS_URL          /* Is the URL valid?                                */
    69 } URLIS;
    70 
    71 
    72 static URLSCHEME arrUrlSchemes[] =
    73 { /* scheme     opaque hist   type */
    74   {"http://",   FALSE, FALSE, 0},
    75   {"https://",  FALSE, FALSE, 0},
    76   {"shttp://",  FALSE, FALSE, 0},
    77   {"file://",   FALSE, FALSE, 0},
    78   {"ftp://",    FALSE, FALSE, 0},
    79   {"telnet://", FALSE, TRUE,  0},
    80   {"news://",   FALSE, TRUE,  0},
    81   {"snews://",  FALSE, TRUE,  0},
    82   {"mailto:",   TRUE,  TRUE,  0},
    83   {"gopher://", FALSE, FALSE, 0},
    84   {"wais://",   FALSE, FALSE, 0},
    85 };
    86 
    87 
    88 
    89 
    90 /*****************************************************************************
    91  * Name      : UrlApplyScheme
    92  * Purpose   : Takes a URL string, determines a scheme for it, and returns a
    93  *             string with an appropriate prefix.
    94  * Parameters: pszIn   [in]     A NULL-terminated URL string.
    95  *             pszOut  [out]    A buffer to receive a NULL-terminated string,
    96  *                              set to the URL specified by pszIn, converted
    97  *                              to the standard scheme://URL_string format.
    98  *             pcchOut [in/out] Address of a value set to the number of
    99  *                              characters in the pszOut buffer. When the
    100  *                              function returns, the value depends on whether
    101  *                              the function is successful or returns
    102  *                              E_POINTER. For other return values, the value
    103  *                              of this parameter is meaningless.
    104  *             dwFlags [in]     Flags that specify how to determine the
    105  *                              scheme. The following flags can be combined.
    106  *                              URL_APPLY_DEFAULT
    107  *                                Apply the default scheme if UrlApplyScheme
    108  *                                can't determine one. The default prefix is
    109  *                                stored in the registry but is typically "http".
    110  *                              URL_APPLY_GUESSSCHEME
    111  *                                Attempt to determine the scheme by examining
    112  *                                pszIn.
    113  *                              URL_APPLY_GUESSFILE
    114  *                                Attempt to determine a file URL from pszIn.
    115  *                              URL_APPLY_FORCEAPPLY
    116  *                                Force UrlApplyScheme to determine a scheme
    117  *                                for pszIn.
    118  * Variables :
    119  * Result    : S_OK      A scheme was determined. pszOut points to a string
    120  *                       containing the URL with the scheme's prefix. The value
    121  *                       of pcchOut is set to the number of characters in the
    122  *                       string, not counting the terminating NULL character.
    123  *             S_FALSE   There were no errors, but no prefix was prepended.
    124  *             E_POINTER The buffer was too small. The value of pcchOut is
    125  *                       set to the minimum number of characters that the
    126  *                       buffer must be able to contain, including the
    127  *                       terminating NULL character.
    128  *             Other errors - A standard OLE error value is returned.
    129  * Remark    : If the URL has a valid scheme, the string will not be modified.
    130  *             However, almost any combination of two or more characters
    131  *             followed by a colon will be parsed as a scheme. Valid
    132  *             characters include some common punctuation marks, such as ".".
    133  *             If your input string fits this description, UrlApplyScheme may
    134  *             treat it as valid and not apply a scheme. To force the function
    135  *             to apply a scheme to a URL, set the URL_APPLY_FORCEAPPLY and
    136  *             URL_APPLY_DEFAULT flags in dwFlags. This combination of flags
    137  *             forces the function to apply a scheme to the URL. Typically,
    138  *             the function will not be able to determine a valid scheme. The
    139  *             second flag guarantees that, if no valid scheme can be
    140  *             determined, the function will apply the default scheme to the URL.
    141  * Status    : PARTIALLY IMPLEMENTED UNTESTED
    142  *
    143  * Author    : Patrick Haller [Thu, 2000/04/20 19:46]
    144  *****************************************************************************/
    145 
    146 ODINFUNCTION4(HRESULT, UrlApplySchemeA,
    147               LPCSTR,  pszIn,
    148               LPSTR,   pszOut,
    149               LPDWORD, pcchOut,
    150               DWORD,   dwFlags)
    151 {
    152   dprintf(("not implemented correctly (In=%s).",
    153           pszIn));
    154 
    155   strncpy(pszOut,
    156           pszIn,
    157           *pcchOut);
    158   *pcchOut = lstrlenA(pszIn);
    159 
    160   return S_OK;
    161 }
    162 
    163 
    164 /*****************************************************************************
    165  * Name      : UrlCombine
    166  * Purpose   : Takes a relative URL and its base and returns a URL in canonical form.
    167  * Parameters: pszBase     [in]  Pointer to a string with the base URL.
    168  *             pszRelative [in]  Pointer to a string with the relative URL.
    169  *             pszCombined [out] Pointer to a buffer to receive a
    170  *                               NULL-terminated string containing the combined URL.
    171  *             pcchCombined [in/out] Pointer to a value set to the number of
    172  *                               characters in the pszCombined buffer. When the
    173  *                               function returns, the value depends on whether
    174  *                               the function is successful or returns E_POINTER.
    175  *                               For other return values, the value of this
    176  *                               parameter is meaningless.
    177  *             dwFlags     [in]  Flags that specify how the URL will be converted
    178  *                               to canonical form. The following flags can be combined.
    179  *                               URL_DONT_SIMPLIFY
    180  *                                 Treat '/./' and '/../' in a URL string as literal
    181  *                                 characters, not as shorthand for
    182  *                                 navigation. See Remarks for further discussion.
    183  *                               URL_ESCAPE_PERCENT
    184  *                                 Convert any occurrence of '%' to its escape sequence.
    185  *                               URL_ESCAPE_SPACES_ONLY
    186  *                                 Replace only spaces with escape sequences. This flag
    187  *                                 takes precedence over
    188  *                                 URL_ESCAPE_UNSAFE, but does not apply to opaque URLs.
    189  *                               URL_ESCAPE_UNSAFE
    190  *                                 Replace unsafe values with their escape sequences.
    191  *                                 This flag applies to all URLs,
    192  *                                 including opaque URLs.
    193  *                               URL_PLUGGABLE_PROTOCOL
    194  *                                 Combine URLs with client-defined pluggable protocols,
    195  *                                 according to the W3C specification. This flag does not
    196  *                                 apply to standard protocols such as ftp, http,
    197  *                                 gopher, and so on. If this flag is set,
    198  *                                 UrlCombine will not simplify URLs, so there is
    199  *                                 no need to also set URL_DONT_SIMPLIFY.
    200  *                               URL_UNESCAPE
    201  *                                 Unescape any escape sequences that the URLs contain,
    202  *                                 with two exceptions. The escape sequences
    203  *                                 for '?' and '#' will not be unescaped.
    204  *                                 If one of the URL_ESCAPE_XXX flags is also
    205  *                                 set, the two URLs will unescaped, then
    206  *                                 combined, then escaped.
    207  * Variables :
    208  * Result    : S_OK      pszCombined points to a string containing the
    209  *                       combined URLs. The value of pcchCombined is set to
    210  *                       the number of characters in the string, not counting
    211  *                       the terminating NULL character.
    212  *             E_POINTER The buffer was too small. The value of pcchCombined
    213  *                       is set to the minimum number of characters that the
    214  *                       buffer must be able to contain, including the
    215  *                       terminating NULL character.
    216  *             Other errors A standard OLE error value is returned.
    217  * Remark    : SHLWAPI.
    218  * Status    : STUB UNTESTED
    219  *
    220  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    221  *****************************************************************************/
    222 
    223 ODINFUNCTION5(HRESULT,UrlCombineA,
    224               LPCSTR, pszBase,
    225               LPCSTR, pszRelative,
    226               LPSTR,  pszCombined,
    227               LPDWORD,pcchCombined,
    228               DWORD,  dwFlags)
    229 {
    230   dprintf(("not implemented."));
    231 
    232   return S_OK;
    233 }
    234 
    235 
    236 /**
    237  * @status      stub
    238  */
    239 ODINFUNCTION5(HRESULT, UrlCombineW,
    240               LPCWSTR, pszBase,
    241               LPCWSTR, pszRelative,
    242               LPWSTR,  pszCombined,
    243               LPDWORD, pcchCombined,
    244               DWORD,   dwFlags)
    245 {
    246   dprintf(("not implemented."));
    247 
    248   return S_OK;
    249 }
    250 
    251 
    252 /*****************************************************************************
    253  * Name      : UrlCompare
    254  * Purpose   : Does a case-sensitive comparison of two URL strings.
    255  * Parameters: pszURL1      [in] NULL-terminated string with the first URL.
    256  *             pszURL2      [in] NULL-terminated string with the second URL.
    257  *             fIgnoreSlash [in] Value that is set to TRUE to have UrlCompare
    258  *                               ignore a trailing '/' character on either or
    259  *                               both URLs.
    260  * Variables :
    261  * Result    : Returns zero if the two strings are equal, apart from a
    262  *             trailing '\' character if fIgnoreSlash is set to TRUE.
    263  *             Returns a negative integer if the string pointed to by pszURL1
    264  *             is less than the string pointed to by pszURL2. Otherwise, it
    265  *             returns a positive integer.
    266  * Remark    : SHLWAPI.
    267  *             For the best results, you should first canonicalize the URLs
    268  *             with UrlCanonicalize. Then, compare the canonicalized URLs with
    269  *             UrlCompare.
    270  * Status    : PARTIALLY IMPLEMENTED UNTESTED
    271  *
    272  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    273  *****************************************************************************/
    274 
    275 ODINFUNCTION3(int,    UrlCompareA,
    276               LPCSTR, pszURL1,
    277               LPCSTR, pszURL2,
    278               BOOL,   fIgnoreSlash)
    279 {
    280   dprintf(("not correctly implemented."));
    281 
    282   return strcmp(pszURL1,
    283                 pszURL2);
    284 }
    285 
    286 /**
    287  * @status      stub
    288  */
    289 ODINFUNCTION3(int,     UrlCompareW,
    290               LPCWSTR, pszURL1,
    291               LPCWSTR, pszURL2,
    292               BOOL,    fIgnoreSlash)
    293 {
    294   dprintf(("not correctly implemented."));
    295 
    296   return wcscmp((const wchar_t *)pszURL1,
    297                 (const wchar_t *)pszURL2);
    298 }
    29943
    30044
     
    34589
    34690
    347 /*****************************************************************************
    348  * Name      : UrlGetLocation
    349  * Purpose   : Retrieves the location from a URL.
    350  * Parameters: pszURL [in] Pointer to a NULL-terminated string that contains
    351  *             the location.
    352  * Variables :
    353  * Result    : Returns a pointer to a NULL-terminated string with the
    354  *             location, or NULL otherwise.
    355  * Remark    : SHLWAPI.
    356  *             The location is the segment of the URL starting with a ? or #
    357  *             character. If a file URL has a query string, the returned
    358  *             string includes the query string.
    359  * Status    : STUB UNTESTED
    360  *
    361  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    362  *****************************************************************************/
    363 
    364 ODINFUNCTION1(LPCSTR, UrlGetLocationA,
    365               LPCSTR, pszURL)
    366 {
    367   dprintf(("not implemented."));
    368 
    369   return pszURL;
    370 }
    371 
    372 
    373 /**
    374  * @status      stub
    375  */
    376 ODINFUNCTION1(LPCWSTR, UrlGetLocationW,
    377               LPCWSTR, pszURL)
    378 {
    379   dprintf(("not implemented."));
    380 
    381   return pszURL;
    382 }
    383 
    384 
    385 /*****************************************************************************
    386  * Name      : UrlGetPart
    387  * Purpose   : Takes a URL string and returns a specified part.
    388  * Parameters: pszIn   [in]     NULL-terminated string that contains the URL.
    389  *             pszOut  [out]    A buffer that will receive a NULL-terminated
    390  *                              string with the specified part.
    391  *             pcchOut [in/out] Address of a value set to the number of
    392  *                              characters in the pszOut buffer. When the
    393  *                              function returns, the value depends on whether
    394  *                              the function is successful or returns E_POINTER.
    395  *                              For other return values, the value of this
    396  *                              parameter is meaningless.
    397  *             dwPart  [in]     Flags that specify which part of the URL to retrieve.
    398  *                              It can have one of the following values.
    399  *               Flag                Description
    400  *               URL_PART_HOSTNAME   The host name.
    401  *               URL_PART_PASSWORD   The password.
    402  *               URL_PART_PORT       The port number.
    403  *               URL_PART_QUERY      The query portion of the URL.
    404  *               URL_PART_SCHEME     The URL scheme.
    405  *               URL_PART_USERNAME   The username.
    406  *
    407  *             dwFlags [in]     Flag that can be set to keep the URL scheme,
    408  *                              in addition to the part that is specified by dwPart.
    409  *               Flag                    Description
    410  *               URL_PARTFLAG_KEEPSCHEME Keep the URL scheme.
    411  * Variables :
    412  * Result    :
    413  * Remark    : SHLWAPI.
    414  *             Returns an OLE success code if successful. The value pointed to
    415  *             by pcchOut will be set to the number of characters written to
    416  *             the output buffer, excluding the terminating NULL. If the buffer
    417  *             was too small, E_POINTER is returned, and the value pointed to
    418  *             by pcchOut will be set to the minimum number of characters that
    419  *             the buffer must be able to contain, including the terminating
    420  *             NULL character. Otherwise, an OLE error value is returned.
    421  * Status    : STUB UNTESTED
    422  *
    423  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    424  *****************************************************************************/
    425 
    426 ODINFUNCTION5(HRESULT, UrlGetPartA,
    427               LPCSTR,  pszIn,
    428               LPSTR,   pszOut,
    429               LPDWORD, pcchOut,
    430               DWORD,   dwPart,
    431               DWORD,   dwFlags)
    432 {
    433   dprintf(("not implemented."));
    434 
    435   return S_OK;
    436 }
    437 
    438 
    439 /**
    440  * @status      stub
    441  */
    442 ODINFUNCTION5(HRESULT, UrlGetPartW,
    443               LPCWSTR, pszIn,
    444               LPWSTR,  pszOut,
    445               LPDWORD, pcchOut,
    446               DWORD,   dwPart,
    447               DWORD,   dwFlags)
    448 {
    449   dprintf(("not implemented."));
    450 
    451   return S_OK;
    452 }
    45391
    45492
     
    469107
    470108
    471 /*****************************************************************************
    472  * Name      : UrlIs
    473  * Purpose   : Tests whether or not a URL is a specified type.
    474  * Parameters: pszUrl [in] Pointer to a string containing the URL.
    475  *             UrlIs  [in] Type of URL to be tested for.
    476  *                         UrlIs can take one of the following values:
    477  *               URLIS_APPLIABLE Attempt to determine a valid scheme for the URL.
    478  *               URLIS_DIRECTORY Does the URL string end with a directory?
    479  *               URLIS_FILEURL   Is the URL a file URL?
    480  *               URLIS_HASQUERY  Does the URL have an appended query string?
    481  *               URLIS_NOHISTORY Is the URL a "No History" URL?
    482  *               URLIS_OPAQUE    Is the URL opaque?
    483  *               URLIS_URL       Is the URL valid?
    484  * Variables :
    485  * Result    : For all but one of the URL types, UrlIs returns TRUE if the URL
    486  *             is the specified type, or FALSE if not. If UrlIs is set to
    487  *             URLIS_APPLIABLE, UrlIs will attempt to determine the URL scheme.
    488  *             If the function is able to determine a scheme, it returns TRUE,
    489  *             or FALSE otherwise.
    490  * Remark    : SHLWAPI.
    491  * Status    : STUB UNTESTED
    492  *
    493  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    494  *****************************************************************************/
    495 
    496 ODINFUNCTION2(BOOL,   UrlIsA,
    497               LPCSTR, pszUrl,
    498               URLIS,  UrlIs)
    499 {
    500   dprintf(("not implemented."));
    501 
    502   return TRUE;
    503 }
    504 
    505 
    506 /**
    507  * @status      stub
    508  */
    509 ODINFUNCTION2(BOOL,    UrlIsW,
    510               LPCWSTR, pszUrl,
    511               URLIS,   UrlIs)
    512 {
    513   dprintf(("not implemented."));
    514 
    515   return TRUE;
    516 }
    517 
    518 /*****************************************************************************
    519  * Name      : UrlIsNoHistory
    520  * Purpose   : Returns whether or not a URL is a No History URL.
    521  * Parameters: pszURL [in] NULL-terminated string with the URL.
    522  * Variables :
    523  * Result    : Returns a non-zero value if the URL is a No History URL, or zero otherwise.
    524  * Remark    : SHLWAPI.
    525  *             A No History URL is a URL that browsers typically do not
    526  *             include in their navigation history.
    527  * Status    : STUB UNTESTED
    528  *
    529  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    530  *****************************************************************************/
    531 
    532 ODINFUNCTION1(BOOL,  UrlIsNoHistoryA,
    533               LPCSTR,pszURL)
    534 {
    535   return UrlIsA(pszURL, URLIS_NOHISTORY);
    536 }
    537 
    538 
    539 /**
    540  * @status      stub
    541  */
    542 ODINFUNCTION1(BOOL,   UrlIsNoHistoryW,
    543               LPCWSTR,pszURL)
    544 {
    545   return UrlIsW(pszURL, URLIS_NOHISTORY);
    546 }
    547 
    548 
    549 /*****************************************************************************
    550  * Name      : UrlIsOpaque
    551  * Purpose   : Returns whether a URL is opaque.
    552  * Parameters: pszURL [in] NULL-terminated string with the URL.
    553  * Variables :
    554  * Result    : Returns a non-zero value if the URL is opaque, or zero
    555  *             otherwise.
    556  * Remark    : SHLWAPI.
    557  *             A URL that has a scheme that is not followed by two slashes (//)
    558  *             is opaque. For example, mailto:xyz@somecompany.com is an opaque
    559  *             URL. Opaque URLs cannot be separated into the standard
    560  *             URL heirarchy.
    561  * Status    : STUB UNTESTED
    562  *
    563  * Author    : Patrick Haller [Tue, 2000/04/25 02:02]
    564  *****************************************************************************/
    565 
    566 ODINFUNCTION1(BOOL,   UrlIsOpaqueA,
    567               LPCSTR, pszURL)
    568 {
    569   return UrlIsA(pszURL, URLIS_OPAQUE);
    570 }
    571 
    572 
    573 /**
    574  * @status      stub
    575  */
    576 ODINFUNCTION1(BOOL,   UrlIsOpaqueW,
    577               LPCWSTR,pszURL)
    578 {
    579   return UrlIsW(pszURL, URLIS_OPAQUE);
    580 }
    581 
    582 
Note: See TracChangeset for help on using the changeset viewer.