- Forward ordinals 40, 41, 143, 362 to appropriate routines.
[wine] / dlls / shlwapi / ordinal.c
1 /*
2  * SHLWAPI ordinal functions
3  *
4  * Copyright 1997 Marcus Meissner
5  *           1998 Jürgen Schmied
6  *           2001 Jon Griffiths
7  */
8
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "windef.h"
13 #include "winnls.h"
14 #include "winbase.h"
15 #include "ddeml.h"
16 #include "shlobj.h"
17 #include "shellapi.h"
18 #include "commdlg.h"
19 #include "wine/unicode.h"
20 #include "wine/obj_base.h"
21 #include "wine/obj_inplace.h"
22 #include "wine/obj_serviceprovider.h"
23 #include "wingdi.h"
24 #include "winreg.h"
25 #include "winuser.h"
26 #include "debugtools.h"
27 #include "ordinal.h"
28 #include "shlwapi.h"
29
30 DEFAULT_DEBUG_CHANNEL(shell);
31
32 extern HINSTANCE shlwapi_hInstance;
33 extern HMODULE SHLWAPI_hshell32;
34 extern HMODULE SHLWAPI_hwinmm;
35 extern HMODULE SHLWAPI_hcomdlg32;
36 extern HMODULE SHLWAPI_hmpr;
37 extern HMODULE SHLWAPI_hmlang;
38 extern HMODULE SHLWAPI_hversion;
39
40 extern DWORD SHLWAPI_ThreadRef_index;
41
42 typedef HANDLE HSHARED; /* Shared memory */
43
44 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
45 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
46 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
47 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
48
49 /* The following schemes were identified in the native version of
50  * SHLWAPI.DLL version 5.50
51  */
52 typedef enum {
53     URL_SCHEME_INVALID     = -1,
54     URL_SCHEME_UNKNOWN     =  0,
55     URL_SCHEME_FTP,
56     URL_SCHEME_HTTP,
57     URL_SCHEME_GOPHER,
58     URL_SCHEME_MAILTO,
59     URL_SCHEME_NEWS,
60     URL_SCHEME_NNTP,
61     URL_SCHEME_TELNET,
62     URL_SCHEME_WAIS,
63     URL_SCHEME_FILE,
64     URL_SCHEME_MK,
65     URL_SCHEME_HTTPS,
66     URL_SCHEME_SHELL,
67     URL_SCHEME_SNEWS,
68     URL_SCHEME_LOCAL,
69     URL_SCHEME_JAVASCRIPT,
70     URL_SCHEME_VBSCRIPT,
71     URL_SCHEME_ABOUT,
72     URL_SCHEME_RES,
73     URL_SCHEME_MAXVALUE
74 } URL_SCHEME;
75
76 typedef struct {
77     URL_SCHEME  scheme_number;
78     LPCSTR scheme_name;
79 } SHL_2_inet_scheme;
80
81 static const SHL_2_inet_scheme shlwapi_schemes[] = {
82   {URL_SCHEME_FTP,        "ftp"},
83   {URL_SCHEME_HTTP,       "http"},
84   {URL_SCHEME_GOPHER,     "gopher"},
85   {URL_SCHEME_MAILTO,     "mailto"},
86   {URL_SCHEME_NEWS,       "news"},
87   {URL_SCHEME_NNTP,       "nntp"},
88   {URL_SCHEME_TELNET,     "telnet"},
89   {URL_SCHEME_WAIS,       "wais"},
90   {URL_SCHEME_FILE,       "file"},
91   {URL_SCHEME_MK,         "mk"},
92   {URL_SCHEME_HTTPS,      "https"},
93   {URL_SCHEME_SHELL,      "shell"},
94   {URL_SCHEME_SNEWS,      "snews"},
95   {URL_SCHEME_LOCAL,      "local"},
96   {URL_SCHEME_JAVASCRIPT, "javascript"},
97   {URL_SCHEME_VBSCRIPT,   "vbscript"},
98   {URL_SCHEME_ABOUT,      "about"},
99   {URL_SCHEME_RES,        "res"},
100   {0, 0}
101 };
102
103 /* Macro to get function pointer for a module*/
104 #define GET_FUNC(module, name, fail) \
105   if (!SHLWAPI_h##module) SHLWAPI_h##module = LoadLibraryA(#module ".dll"); \
106   if (!SHLWAPI_h##module) return fail; \
107   if (!pfnFunc) pfnFunc = (void*)GetProcAddress(SHLWAPI_h##module, name); \
108   if (!pfnFunc) return fail
109
110 /*
111  NOTES: Most functions exported by ordinal seem to be superflous.
112  The reason for these functions to be there is to provide a wraper
113  for unicode functions to provide these functions on systems without
114  unicode functions eg. win95/win98. Since we have such functions we just
115  call these. If running Wine with native DLL's, some late bound calls may
116  fail. However, its better to implement the functions in the forward DLL
117  and recommend the builtin rather than reimplementing the calls here!
118 */
119
120 /*************************************************************************
121  *      @       [SHLWAPI.1]
122  *
123  * Identifies the Internet "scheme" in the passed string. ASCII based.
124  * Also determines start and length of item after the ':'
125  */
126 DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
127 {
128     DWORD cnt;
129     const SHL_2_inet_scheme *inet_pro;
130
131     if (y->size != 0x18) return E_INVALIDARG;
132     /* FIXME: leading white space generates error of 0x80041001 which 
133      *        is undefined
134      */
135     if (*x <= ' ') return 0x80041001;
136     cnt = 0;
137     y->sizep1 = 0;
138     y->ap1 = x;
139     while (*x) {
140         if (*x == ':') {
141             y->sizep1 = cnt;
142             cnt = -1;
143             y->ap2 = x+1;
144             break;
145         }
146         x++;
147         cnt++;
148     }
149
150     /* check for no scheme in string start */
151     /* (apparently schemes *must* be larger than a single character)  */
152     if ((*x == '\0') || (y->sizep1 <= 1)) {
153         y->ap1 = 0;
154         return 0x80041001;
155     }
156
157     /* found scheme, set length of remainder */
158     y->sizep2 = lstrlenA(y->ap2);
159
160     /* see if known scheme and return indicator number */
161     y->fcncde = URL_SCHEME_UNKNOWN;
162     inet_pro = shlwapi_schemes;
163     while (inet_pro->scheme_name) {
164         if (!strncasecmp(inet_pro->scheme_name, y->ap1,
165                     min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
166             y->fcncde = inet_pro->scheme_number;
167             break;
168         }
169         inet_pro++;
170     }
171     return S_OK;
172 }
173
174 /*************************************************************************
175  *      @       [SHLWAPI.2]
176  *
177  * Identifies the Internet "scheme" in the passed string. UNICODE based.
178  * Also determines start and length of item after the ':'
179  */
180 DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
181 {
182     DWORD cnt;
183     const SHL_2_inet_scheme *inet_pro;
184     LPSTR cmpstr;
185     INT len;
186
187     if (y->size != 0x18) return E_INVALIDARG;
188     /* FIXME: leading white space generates error of 0x80041001 which 
189      *        is undefined
190      */
191     if (*x <= L' ') return 0x80041001;
192     cnt = 0;
193     y->sizep1 = 0;
194     y->ap1 = x;
195     while (*x) {
196         if (*x == L':') {
197             y->sizep1 = cnt;
198             cnt = -1;
199             y->ap2 = x+1;
200             break;
201         }
202         x++;
203         cnt++;
204     }
205
206     /* check for no scheme in string start */
207     /* (apparently schemes *must* be larger than a single character)  */
208     if ((*x == L'\0') || (y->sizep1 <= 1)) {
209         y->ap1 = 0;
210         return 0x80041001;
211     }
212
213     /* found scheme, set length of remainder */
214     y->sizep2 = lstrlenW(y->ap2);
215
216     /* see if known scheme and return indicator number */
217     len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
218     cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
219     WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
220     y->fcncde = URL_SCHEME_UNKNOWN;
221     inet_pro = shlwapi_schemes;
222     while (inet_pro->scheme_name) {
223         if (!strncasecmp(inet_pro->scheme_name, cmpstr,
224                     min(len, lstrlenA(inet_pro->scheme_name)))) {
225             y->fcncde = inet_pro->scheme_number;
226             break;
227         }
228         inet_pro++;
229     }
230     HeapFree(GetProcessHeap(), 0, cmpstr);
231     return S_OK;
232 }
233
234 /*************************************************************************
235  * SHLWAPI_DupSharedHandle
236  *
237  * Internal implemetation of SHLWAPI_11.
238  */
239 static
240 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
241                                        DWORD dwSrcProcId, DWORD dwAccess,
242                                        DWORD dwOptions)
243 {
244   HANDLE hDst, hSrc;
245   DWORD dwMyProcId = GetCurrentProcessId();
246   HSHARED hRet = (HSHARED)NULL;
247
248   TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
249         dwAccess, dwOptions);
250
251   /* Get dest process handle */
252   if (dwDstProcId == dwMyProcId)
253     hDst = GetCurrentProcess();
254   else
255     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
256
257   if (hDst)
258   {
259     /* Get src process handle */
260     if (dwSrcProcId == dwMyProcId)
261       hSrc = GetCurrentProcess();
262     else
263       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
264
265     if (hSrc)
266     {
267       /* Make handle available to dest process */
268       if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
269                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
270         hRet = (HSHARED)NULL;
271
272       if (dwSrcProcId != dwMyProcId)
273         CloseHandle(hSrc);
274     }
275
276     if (dwDstProcId != dwMyProcId)
277       CloseHandle(hDst);
278   }
279
280   TRACE("Returning handle %p\n", (PVOID)hRet);
281   return hRet;
282 }
283
284 /*************************************************************************
285  * @  [SHLWAPI.7]
286  *
287  * Create a block of sharable memory and initialise it with data.
288  *
289  * PARAMS
290  * dwProcId [I] ID of process owning data
291  * lpvData  [I] Pointer to data to write
292  * dwSize   [I] Size of data
293  *
294  * RETURNS
295  * Success: A shared memory handle
296  * Failure: NULL
297  *
298  * NOTES
299  * Ordinals 7-11 provide a set of calls to create shared memory between a
300  * group of processes. The shared memory is treated opaquely in that its size
301  * is not exposed to clients who map it. This is accomplished by storing
302  * the size of the map as the first DWORD of mapped data, and then offsetting
303  * the view pointer returned by this size.
304  *
305  * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
306  * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
307  * SHLWAPI_11           - Helper function; Duplicate cross-process handles
308    */
309 HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
310 {
311   HANDLE hMap;
312   LPVOID pMapped;
313   HSHARED hRet = (HSHARED)NULL;
314
315   TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
316
317   /* Create file mapping of the correct length */
318   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
319                             dwSize + sizeof(dwSize), NULL);
320   if (!hMap)
321     return hRet;
322
323   /* Get a view in our process address space */
324   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
325
326   if (pMapped)
327   {
328     /* Write size of data, followed by the data, to the view */
329     *((DWORD*)pMapped) = dwSize;
330     if (dwSize)
331       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
332
333     /* Release view. All further views mapped will be opaque */
334     UnmapViewOfFile(pMapped);
335     hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
336                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
337                                    DUPLICATE_SAME_ACCESS);
338   }
339
340   CloseHandle(hMap);
341   return hRet;
342 }
343
344 /*************************************************************************
345  * @ [SHLWAPI.8]
346  *
347  * Get a pointer to a block of shared memory from a shared memory handle.
348  *
349  * PARAMS
350  * hShared  [I] Shared memory handle
351  * dwProcId [I] ID of process owning hShared
352  *
353  * RETURNS
354  * Success: A pointer to the shared memory
355  * Failure: NULL
356  *
357  * NOTES
358  * See SHLWAPI_7.
359    */
360 PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
361   {
362   HSHARED hDup;
363   LPVOID pMapped;
364
365   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
366
367   /* Get handle to shared memory for current process */
368   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
369                                  FILE_MAP_ALL_ACCESS, 0);
370   /* Get View */
371   pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
372   CloseHandle(hDup);
373
374   if (pMapped)
375     return (char *) pMapped + sizeof(DWORD); /* Hide size */
376   return NULL;
377 }
378
379 /*************************************************************************
380  * @ [SHLWAPI.9]
381  *
382  * Release a pointer to a block of shared memory.
383  *
384  * PARAMS
385  * lpView [I] Shared memory pointer
386  *
387  * RETURNS
388  * Success: TRUE
389  * Failure: FALSE
390  *
391  * NOTES
392  * See SHLWAPI_7.
393  */
394 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
395 {
396   TRACE("(%p)\n", lpView);
397   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
398 }
399
400 /*************************************************************************
401  * @ [SHLWAPI.10]
402  *
403  * Destroy a block of sharable memory.
404  *
405  * PARAMS
406  * hShared  [I] Shared memory handle
407  * dwProcId [I] ID of process owning hShared
408  *
409  * RETURNS
410  * Success: TRUE
411  * Failure: FALSE
412  *
413  * NOTES
414  * See SHLWAPI_7.
415  */
416 BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
417 {
418   HSHARED hClose;
419
420   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
421
422   /* Get a copy of the handle for our process, closing the source handle */
423   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
424                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
425   /* Close local copy */
426   return CloseHandle((HANDLE)hClose);
427 }
428
429 /*************************************************************************
430  * @   [SHLWAPI.11]
431  *
432  * Copy a sharable memory handle from one process to another.
433  *
434  * PARAMS
435  * hShared     [I] Shared memory handle to duplicate
436  * dwDstProcId [I] ID of the process wanting the duplicated handle
437  * dwSrcProcId [I] ID of the process owning hShared
438  * dwAccess    [I] Desired DuplicateHandle access
439  * dwOptions   [I] Desired DuplicateHandle options
440  *
441  * RETURNS
442  * Success: A handle suitable for use by the dwDstProcId process.
443  * Failure: A NULL handle.
444  *
445  * NOTES
446  * See SHLWAPI_7.
447  */
448 HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
449                           DWORD dwAccess, DWORD dwOptions)
450 {
451   HSHARED hRet;
452
453   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
454                                  dwAccess, dwOptions);
455   return hRet;
456 }
457
458 /*************************************************************************
459  *      @       [SHLWAPI.13]
460  * (Used by IE4 during startup)
461  */
462 HRESULT WINAPI SHLWAPI_13 (
463         LPVOID w,
464         LPVOID x)
465 {
466         FIXME("(%p %p)stub\n",w,x);
467         return 1;
468 #if 0
469         /* pseudo code extracted from relay trace */
470         RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Aceepted Documents", &newkey);
471         ret = 0;
472         i = 0;
473         size = 0;
474         while(!ret) {
475             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
476             size += ???;
477             i++;
478         }
479         b1 = LocalAlloc(0x40, size);
480         ret = 0;
481         i = 0;
482         while(!ret) {
483             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
484             RegisterClipBoardFormatA(a4);
485             i++;
486         }
487         hwnd1 = GetModuleHandleA("URLMON.DLL");
488         proc = GetProcAddress(hwnd1, "CreateFormatEnumerator");
489         HeapAlloc(??, 0, 0x14);
490         HeapAlloc(??, 0, 0x50);
491         LocalAlloc(0x40, 0x78);
492         /* FIXME: bad string below */
493         lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
494         StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
495
496         GetTickCount();
497         IsBadReadPtr(c1 = 0x403fd210,4);
498         InterlockedIncrement(c1+4);
499         LocalFree(b1);
500         RegCloseKey(newkey);
501         IsBadReadPtr(c1 = 0x403fd210,4);
502         InterlockedIncrement(c1+4);
503
504         HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
505         HeapAlloc(40350000,00000000,00000050) retval=403feb44;
506         hwnd1 = GetModuleHandleA("URLMON.DLL");
507         proc = GetProcAddress(hwnd1, "RegisterFormatEnumerator");
508         /* 0x1a40c88c is in URLMON.DLL just before above proc
509          * content is L"_EnumFORMATETC_"
510          * label is d1
511          */
512         IsBadReadPtr(d1 = 0x1a40c88c,00000002);
513         lstrlenW(d1);
514         lstrlenW(d1);
515         HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
516         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
517         InterlockedIncrement(d2+4);
518         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
519         InterlockedDecrement(d2+4);
520         IsBadReadPtr(c1,00000004);
521         InterlockedDecrement(c1+4);
522         IsBadReadPtr(c1,00000004);
523         InterlockedDecrement(c1+4);
524
525 #endif
526 }
527
528 /*************************************************************************
529  *      @       [SHLWAPI.14]
530  *
531  * Function:
532  *    Retrieves IE "AcceptLanguage" value from registry. ASCII mode.
533  *  
534  */
535 HRESULT WINAPI SHLWAPI_14 (
536         LPSTR langbuf,
537         LPDWORD buflen)
538 {
539         CHAR *mystr;
540         DWORD mystrlen, mytype;
541         HKEY mykey;
542         LCID mylcid;
543
544         mystrlen = (*buflen > 6) ? *buflen : 6;
545         mystr = (CHAR*)HeapAlloc(GetProcessHeap(), 
546                                  HEAP_ZERO_MEMORY, mystrlen);
547         RegOpenKeyA(HKEY_CURRENT_USER, 
548                     "Software\\Microsoft\\Internet Explorer\\International", 
549                     &mykey);
550         if (RegQueryValueExA(mykey, "AcceptLanguage", 
551                               0, &mytype, mystr, &mystrlen)) {
552             /* Did not find value */
553             mylcid = GetUserDefaultLCID();
554             /* somehow the mylcid translates into "en-us"
555              *  this is similar to "LOCALE_SABBREVLANGNAME"
556              *  which could be gotten via GetLocaleInfo.
557              *  The only problem is LOCALE_SABBREVLANGUAGE" is
558              *  a 3 char string (first 2 are country code and third is
559              *  letter for "sublanguage", which does not come close to
560              *  "en-us"
561              */
562             lstrcpyA(mystr, "en-us");
563             mystrlen = lstrlenA(mystr);
564         }
565         else {
566             /* handle returned string */
567             FIXME("missing code\n");
568         }
569         if (mystrlen > *buflen) 
570             lstrcpynA(langbuf, mystr, *buflen);
571         else {
572             lstrcpyA(langbuf, mystr);
573             *buflen = lstrlenA(langbuf);
574         }        
575         RegCloseKey(mykey);
576         HeapFree(GetProcessHeap(), 0, mystr);
577         TRACE("language is %s\n", debugstr_a(langbuf));
578         return 0;
579 }
580
581 /*************************************************************************
582  *      @       [SHLWAPI.15]
583  *
584  * Function:
585  *    Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
586  *  
587  */
588 HRESULT WINAPI SHLWAPI_15 (
589         LPWSTR langbuf,
590         LPDWORD buflen)
591 {
592         CHAR *mystr;
593         DWORD mystrlen, mytype;
594         HKEY mykey;
595         LCID mylcid;
596
597         mystrlen = (*buflen > 6) ? *buflen : 6;
598         mystr = (CHAR*)HeapAlloc(GetProcessHeap(), 
599                                  HEAP_ZERO_MEMORY, mystrlen);
600         RegOpenKeyA(HKEY_CURRENT_USER, 
601                     "Software\\Microsoft\\Internet Explorer\\International", 
602                     &mykey);
603         if (RegQueryValueExA(mykey, "AcceptLanguage", 
604                               0, &mytype, mystr, &mystrlen)) {
605             /* Did not find value */
606             mylcid = GetUserDefaultLCID();
607             /* somehow the mylcid translates into "en-us"
608              *  this is similar to "LOCALE_SABBREVLANGNAME"
609              *  which could be gotten via GetLocaleInfo.
610              *  The only problem is LOCALE_SABBREVLANGUAGE" is
611              *  a 3 char string (first 2 are country code and third is
612              *  letter for "sublanguage", which does not come close to
613              *  "en-us"
614              */
615             lstrcpyA(mystr, "en-us");
616             mystrlen = lstrlenA(mystr);
617         }
618         else {
619             /* handle returned string */
620             FIXME("missing code\n");
621         }
622         RegCloseKey(mykey);
623         *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
624         HeapFree(GetProcessHeap(), 0, mystr);
625         TRACE("language is %s\n", debugstr_w(langbuf));
626         return 0;
627 }
628
629 /*************************************************************************
630  *      @       [SHLWAPI.16]
631  */
632 HRESULT WINAPI SHLWAPI_16 (
633         LPVOID w,
634         LPVOID x,
635         LPVOID y,
636         LPWSTR z)
637 {
638         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
639         return 0xabba1252;
640 }
641
642 /*************************************************************************
643  *      @       [SHLWAPI.18]
644  *
645  *  w is pointer to address of callback routine
646  *  x is pointer to LPVOID to receive address of locally allocated
647  *         space size 0x14
648  *  return is 0 (unless out of memory???)
649  *
650  * related to _19, _21 and _22 below
651  *  only seen invoked by SHDOCVW
652  */
653 LONG WINAPI SHLWAPI_18 (
654         LPVOID *w,
655         LPVOID x)
656 {
657         FIXME("(%p %p)stub\n",w,x);
658         *((LPDWORD)x) = 0;
659         return 0;
660 }
661
662 /*************************************************************************
663  *      @       [SHLWAPI.19]
664  *
665  *  w is address of allocated memory from _21
666  *  return is 0 (unless out of memory???)
667  *
668  * related to _18, _21 and _22 below
669  *  only seen invoked by SHDOCVW
670  */
671 LONG WINAPI SHLWAPI_19 (
672         LPVOID w)
673 {
674         FIXME("(%p) stub\n",w);
675         return 0;
676 }
677
678 /*************************************************************************
679  *      @       [SHLWAPI.21]
680  *
681  *  w points to space allocated via .18 above
682  *      LocalSize is done on it (retrieves 18)
683  *      LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
684  *  x values seen 0xa0000005
685  *  returns 1
686  *
687  *  relates to _18, _19 and _22 above and below
688  *   only seen invoked by SHDOCVW
689  */
690 LONG WINAPI SHLWAPI_21 (
691         LPVOID w,
692         DWORD  x)
693 {
694         FIXME("(%p %lx)stub\n",w,x);
695         return 1;
696 }
697
698 /*************************************************************************
699  *      @       [SHLWAPI.22]
700  *
701  *  return is 'w' value seen in x is 0xa0000005
702  *
703  *  relates to _18, _19 and _21 above
704  *   only seen invoked by SHDOCVW
705  */
706 LPVOID WINAPI SHLWAPI_22 (
707         LPVOID w,
708         DWORD  x)
709 {
710         FIXME("(%p %lx)stub\n",w,x);
711         return w;
712 }
713
714 /*************************************************************************
715  *      @       [SHLWAPI.23]
716  *
717  * NOTES
718  *      converts a guid to a string
719  *      returns strlen(str)
720  */
721 DWORD WINAPI SHLWAPI_23 (
722         REFGUID guid,   /* [in]  clsid */
723         LPSTR str,      /* [out] buffer */
724         INT cmax)       /* [in]  size of buffer */
725 {
726         char xguid[40];
727
728         sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
729                  guid->Data1, guid->Data2, guid->Data3,
730                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
731                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
732         TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
733         if (strlen(xguid)>=cmax) return 0;
734         strcpy(str,xguid);
735         return strlen(xguid) + 1;
736 }
737
738 /*************************************************************************
739  *      @       [SHLWAPI.24]
740  *
741  * NOTES
742  *      converts a guid to a string
743  *      returns strlen(str)
744  */
745 DWORD WINAPI SHLWAPI_24 (
746         REFGUID guid,   /* [in]  clsid */
747         LPWSTR str,     /* [out] buffer */
748         INT cmax)       /* [in]  size of buffer */
749 {
750     char xguid[40];
751
752     sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
753              guid->Data1, guid->Data2, guid->Data3,
754              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
755              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
756     return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
757 }
758
759 /*************************************************************************
760  *      @       [SHLWAPI.25]
761  *
762  * Seems to be iswalpha
763  */
764 BOOL WINAPI SHLWAPI_25(WCHAR wc)
765 {
766     return (get_char_typeW(wc) & C1_ALPHA) != 0;
767 }
768
769 /*************************************************************************
770  *      @       [SHLWAPI.26]
771  *
772  * Seems to be iswupper
773  */
774 BOOL WINAPI SHLWAPI_26(WCHAR wc)
775 {
776     return (get_char_typeW(wc) & C1_UPPER) != 0;
777 }
778
779 /*************************************************************************
780  *      @       [SHLWAPI.27]
781  *
782  * Seems to be iswlower
783  */
784 BOOL WINAPI SHLWAPI_27(WCHAR wc)
785 {
786     return (get_char_typeW(wc) & C1_LOWER) != 0;
787 }
788
789 /*************************************************************************
790  *      @       [SHLWAPI.28]
791  *
792  * Seems to be iswalnum
793  */
794 BOOL WINAPI SHLWAPI_28(WCHAR wc)
795 {
796     return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
797 }
798
799 /*************************************************************************
800  *      @       [SHLWAPI.29]
801  *
802  * Seems to be iswspace
803  */
804 BOOL WINAPI SHLWAPI_29(WCHAR wc)
805 {
806     return (get_char_typeW(wc) & C1_SPACE) != 0;
807 }
808
809 /*************************************************************************
810  *      @       [SHLWAPI.30]
811  *
812  * Seems to be iswblank
813  */
814 BOOL WINAPI SHLWAPI_30(WCHAR wc)
815 {
816     return (get_char_typeW(wc) & C1_BLANK) != 0;
817 }
818
819 /*************************************************************************
820  *      @       [SHLWAPI.31]
821  *
822  * Seems to be iswpunct
823  */
824 BOOL WINAPI SHLWAPI_31(WCHAR wc)
825 {
826     return (get_char_typeW(wc) & C1_PUNCT) != 0;
827 }
828
829 /*************************************************************************
830  *      @       [SHLWAPI.32]
831  *
832  * Seems to be iswcntrl
833  */
834 BOOL WINAPI SHLWAPI_32(WCHAR wc)
835 {
836     return (get_char_typeW(wc) & C1_CNTRL) != 0;
837 }
838
839 /*************************************************************************
840  *      @       [SHLWAPI.33]
841  *
842  * Seems to be iswdigit
843  */
844 BOOL WINAPI SHLWAPI_33(WCHAR wc)
845 {
846     return (get_char_typeW(wc) & C1_DIGIT) != 0;
847 }
848
849 /*************************************************************************
850  *      @       [SHLWAPI.34]
851  *
852  * Seems to be iswxdigit
853  */
854 BOOL WINAPI SHLWAPI_34(WCHAR wc)
855 {
856     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
857 }
858
859 /*************************************************************************
860  *      @       [SHLWAPI.35]
861  *
862  */
863 BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
864 {
865     FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
866     return TRUE;
867 }
868
869 /*************************************************************************
870  *      @       [SHLWAPI.36]
871  *
872  */
873 BOOL WINAPI SHLWAPI_36(HMENU h1, UINT ui2, UINT h3, LPCWSTR p4)
874 {
875     TRACE("(0x%08x, 0x%08x, 0x%08x, %s): stub\n", 
876           h1, ui2, h3, debugstr_w(p4));
877     return AppendMenuW(h1, ui2, h3, p4);
878 }
879
880 /*************************************************************************
881  *      @       [SHLWAPI.74]
882  *
883  * Get the text from a given dialog item.
884  */
885 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
886 {
887   HWND hItem = GetDlgItem(hWnd, nItem);
888
889   if (hItem)
890     return GetWindowTextW(hItem, lpsDest, nDestLen);
891   if (nDestLen)
892     *lpsDest = (WCHAR)'\0';
893   return 0;
894 }
895
896 /*************************************************************************
897  *      @       [SHLWAPI.151]
898  * Function:  Compare two ASCII strings for "len" bytes.
899  * Returns:   *str1-*str2  (case sensitive)
900  */
901 DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
902 {
903     return strncmp( str1, str2, len );
904 }
905
906 /*************************************************************************
907  *      @       [SHLWAPI.152]
908  *
909  * Function:  Compare two WIDE strings for "len" bytes.
910  * Returns:   *str1-*str2  (case sensitive)
911  */
912 DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
913 {
914     return strncmpW( str1, str2, len );
915 }
916
917 /*************************************************************************
918  *      @       [SHLWAPI.153]
919  * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
920  * Returns:   *str1-*str2  (case insensitive)
921  */
922 DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
923 {
924     return strncasecmp( str1, str2, len );
925 }
926
927 /*************************************************************************
928  *      @       [SHLWAPI.154]
929  *
930  * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
931  * Returns:   *str1-*str2  (case insensitive)
932  */
933 DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
934 {
935     return strncmpiW( str1, str2, len );
936 }
937
938 /*************************************************************************
939  *      @       [SHLWAPI.155]
940  *
941  *      Case sensitive string compare (ASCII). Does not SetLastError().
942  */
943 DWORD WINAPI SHLWAPI_155 ( LPSTR str1, LPSTR str2)
944 {
945     return strcmp(str1, str2);
946 }
947
948 /*************************************************************************
949  *      @       [SHLWAPI.156]
950  *
951  *      Case sensitive string compare. Does not SetLastError().
952  */
953 DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
954 {
955     return strcmpW( str1, str2 );
956 }
957
958 /*************************************************************************
959  *      @       [SHLWAPI.158]
960  *
961  *      Case insensitive string compare. Does not SetLastError(). ??
962  */
963 DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
964 {
965     return strcmpiW( str1, str2 );
966 }
967
968 /*************************************************************************
969  *      @       [SHLWAPI.162]
970  *
971  * Ensure a multibyte character string doesn't end in a hanging lead byte.
972  */
973 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
974 {
975   if (lpStr && size)
976   {
977     LPSTR lastByte = lpStr + size - 1;
978
979     while(lpStr < lastByte)
980       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
981
982     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
983     {
984       *lpStr = '\0';
985       size--;
986     }
987     return size;
988   }
989   return 0;
990 }
991
992 /*************************************************************************
993  *      @       [SHLWAPI.164]
994  */
995 DWORD WINAPI SHLWAPI_164 (
996         LPVOID u,
997         LPVOID v,
998         LPVOID w,
999         LPVOID x,
1000         LPVOID y,
1001         LPVOID z)
1002 {
1003         TRACE("(%p %p %p %p %p %p) stub\n",u,v,w,x,y,z);
1004         return 0x80004002;    /* E_NOINTERFACE */
1005 }
1006
1007 /*************************************************************************
1008  *      @       [SHLWAPI.165]
1009  *
1010  * SetWindowLongA with mask.
1011  */
1012 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wFlags, UINT wMask)
1013 {
1014   LONG ret = GetWindowLongA(hwnd, offset);
1015   UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
1016
1017   if (newFlags != ret)
1018     ret = SetWindowLongA(hwnd, offset, newFlags);
1019   return ret;
1020 }
1021
1022 /*************************************************************************
1023  *      @       [SHLWAPI.169]
1024  *
1025  *  Do IUnknown::Release on passed object.
1026  */
1027 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1028 {
1029         IUnknown *temp;
1030
1031         TRACE("(%p)\n",lpUnknown);
1032         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1033         temp = *lpUnknown;
1034         *lpUnknown = NULL;
1035         TRACE("doing Release\n");
1036         return IUnknown_Release(temp);
1037 }
1038
1039 /*************************************************************************
1040  *      @       [SHLWAPI.170]
1041  *
1042  * Skip URL '//' sequence.
1043  */
1044 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1045 {
1046   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1047     lpszSrc += 2;
1048   return lpszSrc;
1049 }
1050
1051 /*************************************************************************
1052  *      @       [SHLWAPI.172]
1053  * Get window handle of OLE object
1054  */
1055 DWORD WINAPI SHLWAPI_172 (
1056         IUnknown *y,       /* [in]   OLE object interface */
1057         LPHWND z)          /* [out]  location to put window handle */
1058 {
1059         DWORD ret;
1060         IUnknown *pv;
1061
1062         TRACE("(%p %p)\n",y,z);
1063         if (!y) return E_FAIL;
1064
1065         if ((ret = IUnknown_QueryInterface(y, &IID_IOleWindow,(LPVOID *)&pv)) < 0) {
1066             /* error */
1067             return ret;
1068         }
1069         ret = IOleWindow_GetWindow((IOleWindow *)pv, z);
1070         IUnknown_Release(pv);
1071         TRACE("result hwnd=%08x\n", *z);
1072         return ret;
1073 }
1074
1075 /*************************************************************************
1076  *      @       [SHLWAPI.174]
1077  *
1078  * Seems to do call either IObjectWithSite::SetSite or 
1079  *   IPersistMoniker::GetClassID.  But since we do not implement either
1080  *   of those classes in our headers, we will fake it out.
1081  */
1082 DWORD WINAPI SHLWAPI_174(
1083         IUnknown *p1,     /* [in]   OLE object                          */
1084         LPVOID *p2)       /* [out]  ptr to result of either GetClassID 
1085                                     or SetSite call.                    */
1086 {
1087     DWORD ret, aa;
1088
1089     if (!p1) return E_FAIL;
1090
1091     /* see if SetSite interface exists for IObjectWithSite object */
1092     ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1093     TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1094     if (ret) { 
1095
1096         /* see if GetClassId interface exists for IPersistMoniker object */
1097         ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1098         TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1099         if (ret) return ret;
1100
1101         /* fake a GetClassId call */
1102         ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1103         TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret, 
1104               *(LPDWORD)p2);
1105         IUnknown_Release((IUnknown *)aa);
1106     }
1107     else {
1108         /* fake a SetSite call */
1109         ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1110         TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret, 
1111               *(LPDWORD)p2);
1112         IUnknown_Release((IUnknown *)p1);
1113     }
1114     return ret;
1115 }
1116
1117 /*************************************************************************
1118  *      @       [SHLWAPI.176]
1119  *
1120  * Function appears to be interface to IServiceProvider::QueryService
1121  *
1122  * NOTE:
1123  *   returns E_NOINTERFACE
1124  *           E_FAIL  if w == 0
1125  *           S_OK    if _219 called successfully
1126  */
1127 DWORD WINAPI SHLWAPI_176 (
1128         IUnknown* unk,    /* [in]    object to give Service Provider */
1129         REFGUID   sid,    /* [in]    Service ID                      */
1130         REFIID    riid,   /* [in]    Function requested              */
1131         LPVOID    *z)     /* [out]   place to save interface pointer */
1132 {
1133     DWORD ret;
1134     LPVOID aa;
1135     *z = 0;
1136     if (!unk) return E_FAIL;
1137     ret = IUnknown_QueryInterface(unk, &IID_IServiceProvider, &aa);
1138     TRACE("did IU_QI retval=%08lx, aa=%p\n", ret, aa); 
1139     if (ret) return ret;
1140     ret = IServiceProvider_QueryService((IServiceProvider *)aa, sid, riid, 
1141                                         (void **)z);
1142     TRACE("did ISP_QS retval=%08lx, *z=%p\n", ret, (LPVOID)*z); 
1143     IUnknown_Release((IUnknown*)aa);
1144     return ret;
1145 }
1146
1147 /*************************************************************************
1148  *      @       [SHLWAPI.181]
1149  *
1150  *      Enable or disable a menu item.
1151  */
1152 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1153 {
1154   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1155 }
1156
1157 /*************************************************************************
1158  *      @       [SHLWAPI.183]
1159  *
1160  * Register a window class if it isn't already.
1161  */
1162 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1163 {
1164   WNDCLASSA wca;
1165   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1166     return TRUE;
1167   return (DWORD)RegisterClassA(wndclass);
1168 }
1169
1170 /*************************************************************************
1171  *      @       [SHLWAPI.193]
1172  */
1173 DWORD WINAPI SHLWAPI_193 ()
1174 {
1175         HDC hdc;
1176         DWORD ret;
1177
1178         TRACE("()\n");
1179
1180         hdc = GetDC(0);
1181         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1182         ReleaseDC(0, hdc);
1183         return ret;
1184 }
1185
1186 /*************************************************************************
1187  *      @       [SHLWAPI.199]
1188  *
1189  * Copy interface pointer
1190  */
1191 DWORD WINAPI SHLWAPI_199 (
1192         IUnknown **dest,   /* [out] pointer to copy of interface ptr */
1193         IUnknown *src)     /* [in]  interface pointer */
1194 {
1195         TRACE("(%p %p)\n",dest,src);
1196         if (*dest != src) {
1197             if (*dest)
1198                 IUnknown_Release(*dest);
1199             if (src) {
1200                 IUnknown_AddRef(src);
1201                 *dest = src;
1202             }
1203         }
1204         return 4;
1205 }
1206
1207 /*************************************************************************
1208  *      @       [SHLWAPI.208]
1209  *
1210  * Some sort of memory management process - associated with _210
1211  */
1212 DWORD WINAPI SHLWAPI_208 (
1213         DWORD    a,
1214         DWORD    b,
1215         LPVOID   c,
1216         LPVOID   d,
1217         DWORD    e)
1218 {
1219     FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
1220           a, b, c, d, e);
1221     return 1;
1222 }
1223
1224 /*************************************************************************
1225  *      @       [SHLWAPI.209]
1226  *
1227  * Some sort of memory management process - associated with _208
1228  */
1229 DWORD WINAPI SHLWAPI_209 (
1230         LPVOID   a)
1231 {
1232     FIXME("(%p) stub\n",
1233           a);
1234     return 1;
1235 }
1236
1237 /*************************************************************************
1238  *      @       [SHLWAPI.210]
1239  *
1240  * Some sort of memory management process - associated with _208
1241  */
1242 DWORD WINAPI SHLWAPI_210 (
1243         LPVOID   a,
1244         DWORD    b,
1245         LPVOID   c)
1246 {
1247     FIXME("(%p 0x%08lx %p) stub\n",
1248           a, b, c);
1249     return 0;
1250 }
1251
1252 /*************************************************************************
1253  *      @       [SHLWAPI.211]
1254  */
1255 DWORD WINAPI SHLWAPI_211 (
1256         LPVOID   a,
1257         DWORD    b)
1258 {
1259     FIXME("(%p 0x%08lx) stub\n",
1260           a, b);
1261     return 1;
1262 }
1263
1264 /*************************************************************************
1265  *      @       [SHLWAPI.215]
1266  *
1267  * NOTES
1268  *  check me!
1269  */
1270 DWORD WINAPI SHLWAPI_215 (
1271         LPCSTR lpStrSrc,
1272         LPWSTR lpwStrDest,
1273         int len)
1274 {
1275         INT len_a, ret;
1276
1277         len_a = lstrlenA(lpStrSrc);
1278         ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
1279         TRACE("%s %s %d, ret=%d\n", 
1280               debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
1281         return ret;
1282 }
1283
1284 /*************************************************************************
1285  *      @       [SHLWAPI.218]
1286  *
1287  * WideCharToMultiByte with multi language support.
1288  */
1289 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
1290                        LPINT lpnMultiCharCount)
1291 {
1292   static HRESULT (WINAPI *pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
1293   WCHAR emptyW[] = { '\0' };
1294   int len , reqLen;
1295   LPSTR mem;
1296
1297   if (!lpDstStr || !lpnMultiCharCount)
1298     return 0;
1299
1300   if (!lpSrcStr)
1301     lpSrcStr = emptyW;
1302
1303   *lpDstStr = '\0';
1304
1305   len = strlenW(lpSrcStr) + 1;
1306
1307   switch (CodePage)
1308   {
1309   case CP_WINUNICODE:
1310     CodePage = CP_UTF8; /* Fall through... */
1311   case 0x0000C350: /* FIXME: CP_ #define */
1312   case CP_UTF7:
1313   case CP_UTF8:
1314     {
1315       DWORD dwMode = 0;
1316       INT nWideCharCount = len - 1;
1317
1318       GET_FUNC(mlang, "ConvertINetUnicodeToMultiByte", 0);
1319       if (!pfnFunc(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
1320                    lpnMultiCharCount))
1321         return 0;
1322
1323       if (nWideCharCount < len - 1)
1324       {
1325         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
1326         if (!mem)
1327           return 0;
1328
1329         *lpnMultiCharCount = 0;
1330
1331         if (pfnFunc(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
1332         {
1333           SHLWAPI_162 (mem, *lpnMultiCharCount);
1334           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
1335           return *lpnMultiCharCount + 1;
1336         }
1337         HeapFree(GetProcessHeap(), 0, mem);
1338         return *lpnMultiCharCount;
1339       }
1340       lpDstStr[*lpnMultiCharCount] = '\0';
1341       return *lpnMultiCharCount;
1342     }
1343     break;
1344   default:
1345     break;
1346   }
1347
1348   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
1349                                *lpnMultiCharCount, NULL, NULL);
1350
1351   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1352   {
1353     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
1354     if (reqLen)
1355     {
1356       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
1357       if (mem)
1358       {
1359         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
1360                                      reqLen, NULL, NULL);
1361
1362         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
1363         reqLen++;
1364
1365         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
1366
1367         HeapFree(GetProcessHeap(), 0, mem);
1368       }
1369     }
1370   }
1371   return reqLen;
1372 }
1373
1374 /*************************************************************************
1375  *      @       [SHLWAPI.217]
1376  *
1377  * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
1378  * --> Crash. Something wrong here.
1379  *
1380  * It seems from OE v5 that the third param is the count. (GA 11/2001)
1381  */
1382 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
1383 {
1384     INT myint = MultiCharCount;
1385
1386     return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
1387 }
1388
1389 /*************************************************************************
1390  *      @       [SHLWAPI.219]
1391  *
1392  * Seems to be "super" QueryInterface. Supplied with at table of interfaces
1393  * and an array of IIDs and offsets into the table.
1394  *
1395  * NOTES
1396  *  error codes: E_POINTER, E_NOINTERFACE
1397  */
1398 typedef struct {
1399     REFIID   refid;
1400     DWORD    indx;
1401 } IFACE_INDEX_TBL;
1402
1403 HRESULT WINAPI SHLWAPI_219 (
1404         LPVOID w,           /* [in]   table of interfaces                   */
1405         IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
1406         REFIID riid,        /* [in]   REFIID to get interface for           */
1407         LPVOID *z)          /* [out]  location to get interface pointer     */
1408 {
1409         HRESULT ret;
1410         IUnknown *a_vtbl;
1411         IFACE_INDEX_TBL *xmove;
1412
1413         TRACE("(%p %p %s %p)\n",
1414               w,x,debugstr_guid(riid),z);
1415         if (z) {
1416             xmove = x;
1417             while (xmove->refid) {
1418                 TRACE("trying (indx %ld) %s\n", xmove->indx, 
1419                       debugstr_guid(xmove->refid));
1420                 if (IsEqualIID(riid, xmove->refid)) {
1421                     a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
1422                     TRACE("matched, returning (%p)\n", a_vtbl);
1423                     *z = (LPVOID)a_vtbl;
1424                     IUnknown_AddRef(a_vtbl);
1425                     return S_OK;
1426                 }
1427                 xmove++;
1428             }
1429
1430             if (IsEqualIID(riid, &IID_IUnknown)) {
1431                 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
1432                 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
1433                 *z = (LPVOID)a_vtbl;
1434                 IUnknown_AddRef(a_vtbl);
1435                 return S_OK;
1436             }
1437             *z = 0;
1438             ret = E_NOINTERFACE;
1439         } else
1440             ret = E_POINTER;
1441         return ret;
1442 }
1443
1444 /*************************************************************************
1445  *      @       [SHLWAPI.222]
1446  *
1447  * NOTES
1448  *  securityattributes missing
1449  */
1450 HANDLE WINAPI SHLWAPI_222 (LPCLSID guid)
1451 {
1452         char lpstrName[80];
1453
1454         sprintf( lpstrName, "shell.{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1455                  guid->Data1, guid->Data2, guid->Data3,
1456                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1457                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
1458         FIXME("(%s) stub\n", lpstrName);
1459         return CreateSemaphoreA(NULL,0, 0x7fffffff, lpstrName);
1460 }
1461
1462 /*************************************************************************
1463  *      @       [SHLWAPI.223]
1464  *
1465  * NOTES
1466  *  get the count of the semaphore
1467  */
1468 DWORD WINAPI SHLWAPI_223 (HANDLE handle)
1469 {
1470         DWORD oldCount;
1471
1472         FIXME("(0x%08x) stub\n",handle);
1473
1474         ReleaseSemaphore( handle, 1, &oldCount);        /* +1 */
1475         WaitForSingleObject( handle, 0 );               /* -1 */
1476         return oldCount;
1477 }
1478
1479 /*************************************************************************
1480  *      @       [SHLWAPI.236]
1481  */
1482 HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
1483 {
1484     HKEY newkey;
1485     DWORD type, count;
1486     CHAR value[MAX_PATH], string[MAX_PATH];
1487
1488     strcpy(string, "CLSID\\");
1489     strcat(string, debugstr_guid(lpUnknown));
1490     strcat(string, "\\InProcServer32");
1491
1492     count = MAX_PATH;
1493     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
1494     RegQueryValueExA(newkey, 0, 0, &type, value, &count);
1495     RegCloseKey(newkey);
1496     return LoadLibraryExA(value, 0, 0);
1497 }
1498
1499 /*************************************************************************
1500  *      @       [SHLWAPI.237]
1501  *
1502  * Unicode version of SHLWAPI_183.
1503  */
1504 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
1505 {
1506         WNDCLASSW WndClass;
1507
1508         TRACE("(0x%08x %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
1509
1510         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
1511                 return TRUE;
1512         return RegisterClassW(lpWndClass);
1513 }
1514
1515 /*************************************************************************
1516  *      @       [SHLWAPI.239]
1517  */
1518 DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
1519 {
1520     FIXME("(0x%08x %p 0x%08lx) stub\n",
1521           hInstance, p2, dw3);
1522     return 0;
1523 #if 0
1524     /* pseudo code from relay trace */
1525     WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
1526     GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
1527     /* above pair repeated for:
1528            TridentThicketUrlDlClass
1529            Shell Embedding
1530            CIESplashScreen
1531            Inet Notify_Hidden
1532            OCHost
1533     */
1534 #endif
1535 }
1536
1537 /*************************************************************************
1538  *      @       [SHLWAPI.240]
1539  *
1540  *      Calls ASCII or Unicode WindowProc for the given window.
1541  */
1542 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1543 {
1544         if (IsWindowUnicode(hWnd))
1545                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1546         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
1547 }
1548
1549 /*************************************************************************
1550  *      @       [SHLWAPI.241]
1551  *
1552  */
1553 DWORD WINAPI SHLWAPI_241 ()
1554 {
1555         FIXME("()stub\n");
1556         return /* 0xabba1243 */ 0;
1557 }
1558
1559 /*************************************************************************
1560  *      @       [SHLWAPI.266]
1561  */
1562 DWORD WINAPI SHLWAPI_266 (
1563         LPVOID w,
1564         LPVOID x,
1565         LPVOID y,
1566         LPVOID z)
1567 {
1568         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1569         return 0xabba1248;
1570 }
1571
1572 /*************************************************************************
1573  *      @       [SHLWAPI.267]
1574  */
1575 HRESULT WINAPI SHLWAPI_267 (
1576         LPVOID w, /* [???] NOTE: same as 1th parameter of SHLWAPI_219 */
1577         LPVOID x, /* [???] NOTE: same as 2nd parameter of SHLWAPI_219 */
1578         LPVOID y,
1579         LPVOID z)
1580 {
1581         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1582         *((LPDWORD)z) = 0xabba1200;
1583         return 0xabba1254;
1584 }
1585
1586 /*************************************************************************
1587  *      @       [SHLWAPI.268]
1588  */
1589 DWORD WINAPI SHLWAPI_268 (
1590         LPVOID w,
1591         LPVOID x)
1592 {
1593         FIXME("(%p %p)\n",w,x);
1594         return 0xabba1251; /* 0 = failure */
1595 }
1596
1597 /*************************************************************************
1598  *      @       [SHLWAPI.276]
1599  *
1600  */
1601 DWORD WINAPI SHLWAPI_276 ()
1602 {
1603         FIXME("()stub\n");
1604         return /* 0xabba1244 */ 0;
1605 }
1606
1607 /*************************************************************************
1608  *      @       [SHLWAPI.278]
1609  *
1610  */
1611 HWND WINAPI SHLWAPI_278 (
1612         LONG wndProc,
1613         HWND hWndParent,
1614         DWORD dwExStyle,
1615         DWORD dwStyle,
1616         HMENU hMenu,
1617         LONG z)
1618 {
1619         WNDCLASSA wndclass;
1620         HWND hwnd;
1621         HCURSOR hCursor;
1622         char * clsname = "WorkerA";
1623
1624         FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
1625           wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
1626
1627         hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
1628
1629         if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
1630         {
1631           RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
1632           wndclass.lpfnWndProc = DefWindowProcW;
1633           wndclass.cbWndExtra = 4;
1634           wndclass.hInstance = shlwapi_hInstance;
1635           wndclass.hCursor = hCursor;
1636           wndclass.hbrBackground = COLOR_BTNSHADOW;
1637           wndclass.lpszMenuName = NULL;
1638           wndclass.lpszClassName = clsname;
1639           RegisterClassA (&wndclass);
1640         }
1641         hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
1642                 hMenu,shlwapi_hInstance,0);
1643         SetWindowLongA(hwnd, 0, z);
1644         SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
1645         return hwnd;
1646 }
1647
1648 /*************************************************************************
1649  *      @       [SHLWAPI.289]
1650  *
1651  * Late bound call to winmm.PlaySoundW
1652  */
1653 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
1654 {
1655   static BOOL (WINAPI *pfnFunc)(LPCWSTR, HMODULE, DWORD) = NULL;
1656
1657   GET_FUNC(winmm, "PlaySoundW", FALSE);
1658   return pfnFunc(pszSound, hmod, fdwSound);
1659 }
1660
1661 /*************************************************************************
1662  *      @       [SHLWAPI.294]
1663  */
1664 BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
1665 {
1666     /*
1667      * str1:            "I"     "I"     pushl esp+0x20
1668      * str2:            "U"     "I"     pushl 0x77c93810
1669      * (is "I" and "U" "integer" and "unsigned" ??)
1670      *
1671      * pStr:            ""      ""      pushl eax
1672      * some_len:        0x824   0x104   pushl 0x824
1673      * lpStr2:          "%l"    "%l"    pushl esp+0xc
1674      *
1675      * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
1676      * LocalAlloc(0x00, some_len) -> irrelevant_var
1677      * LocalAlloc(0x40, irrelevant_len) -> pStr
1678      * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
1679      * shlwapi.PathRemoveBlanksW(pStr);
1680      */
1681     ERR("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
1682     return TRUE;
1683 }
1684
1685 /*************************************************************************
1686  *      @       [SHLWAPI.313]
1687  *
1688  * Late bound call to shell32.SHGetFileInfoW
1689  */
1690 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
1691                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
1692 {
1693   static DWORD (WINAPI *pfnFunc)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT) = NULL;
1694
1695   GET_FUNC(shell32, "SHGetFileInfoW", 0);
1696   return pfnFunc(path, dwFileAttributes, psfi, sizeofpsfi, flags);
1697 }
1698
1699 /*************************************************************************
1700  *      @       [SHLWAPI.318]
1701  *
1702  * Late bound call to shell32.DragQueryFileW
1703  */
1704 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
1705 {
1706   static UINT (WINAPI *pfnFunc)(HDROP, UINT, LPWSTR, UINT) = NULL;
1707
1708   GET_FUNC(shell32, "DragQueryFileW", 0);
1709   return pfnFunc(hDrop, lFile, lpszFile, lLength);
1710 }
1711
1712 /*************************************************************************
1713  *      @       [SHLWAPI.333]
1714  *
1715  * Late bound call to shell32.SHBrowseForFolderW
1716  */
1717 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
1718 {
1719   static LPITEMIDLIST (WINAPI *pfnFunc)(LPBROWSEINFOW) = NULL;
1720
1721   GET_FUNC(shell32, "SHBrowseForFolderW", NULL);
1722   return pfnFunc(lpBi);
1723 }
1724
1725 /*************************************************************************
1726  *      @       [SHLWAPI.334]
1727  *
1728  * Late bound call to shell32.SHGetPathFromIDListW
1729  */
1730 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
1731 {
1732   static BOOL (WINAPI *pfnFunc)(LPCITEMIDLIST, LPWSTR) = NULL;
1733
1734   GET_FUNC(shell32, "SHGetPathFromIDListW", 0);
1735   return pfnFunc(pidl, pszPath);
1736 }
1737
1738 /*************************************************************************
1739  *      @       [SHLWAPI.335]
1740  *
1741  * Late bound call to shell32.ShellExecuteExW
1742  */
1743 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
1744 {
1745   static BOOL (WINAPI *pfnFunc)(LPSHELLEXECUTEINFOW) = NULL;
1746
1747   GET_FUNC(shell32, "ShellExecuteExW", FALSE);
1748   return pfnFunc(lpExecInfo);
1749 }
1750
1751 /*************************************************************************
1752  *      @       [SHLWAPI.336]
1753  *
1754  * Late bound call to shell32.SHFileOperationW.
1755  */
1756 DWORD WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
1757 {
1758   static HICON (WINAPI *pfnFunc)(LPSHFILEOPSTRUCTW) = NULL;
1759
1760   GET_FUNC(shell32, "SHFileOperationW", 0);
1761   return pfnFunc(lpFileOp);
1762 }
1763
1764 /*************************************************************************
1765  *      @       [SHLWAPI.337]
1766  *
1767  * Late bound call to shell32.ExtractIconExW.
1768  */
1769 HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
1770                          HICON *phiconSmall, UINT nIcons)
1771 {
1772   static HICON (WINAPI *pfnFunc)(LPCWSTR, INT,HICON *,HICON *, UINT) = NULL;
1773
1774   GET_FUNC(shell32, "ExtractIconExW", (HICON)0);
1775   return pfnFunc(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
1776 }
1777
1778 /*************************************************************************
1779  *      @       [SHLWAPI.342]
1780  *
1781  */
1782 DWORD WINAPI SHLWAPI_342 (
1783         LPDWORD  w,   /* [out] location to put HKEY value???   */
1784         HKEY     x,   /* [in]  appears to be HKEY_CURRENT_USER */
1785         LPVOID y)
1786 {
1787         FIXME("(%p 0x%08x %p)stub\n", w,x,y);
1788         *w = (DWORD)x;
1789         return /* 0xabba1249 */ 0;
1790 }
1791
1792 /*************************************************************************
1793  *      @       [SHLWAPI.346]
1794  */
1795 DWORD WINAPI SHLWAPI_346 (
1796         LPCWSTR src,
1797         LPWSTR dest,
1798         int len)
1799 {
1800         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
1801         lstrcpynW(dest, src, len);
1802         return lstrlenW(dest)+1;
1803 }
1804
1805 /*************************************************************************
1806  *      @       [SHLWAPI.350]
1807  *
1808  * seems to be W interface to GetFileVersionInfoSizeA
1809  */
1810 DWORD WINAPI SHLWAPI_350 (
1811         LPWSTR x,
1812         LPVOID y)
1813 {
1814 static DWORD   WINAPI (*pfnFunc)(LPCSTR,LPDWORD) = NULL;
1815         CHAR mbpath[MAX_PATH];
1816         DWORD ret;
1817
1818         GET_FUNC(version, "GetFileVersionInfoSizeA", 0);
1819         WideCharToMultiByte(0, 0, x, -1, mbpath, MAX_PATH, 0, 0);
1820         ret = pfnFunc(mbpath, y);
1821         return 0x208 + ret;
1822 }
1823
1824 /*************************************************************************
1825  *      @       [SHLWAPI.351]
1826  *
1827  * seems to be W interface to GetFileVersionInfoA
1828  */
1829 BOOL  WINAPI SHLWAPI_351 (
1830         LPWSTR w,   /* [in] path to dll */
1831         DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
1832         DWORD  y,   /* [in] return value from .350 - assume length */
1833         LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA) */
1834 {
1835         static BOOL    WINAPI (*pfnFunc)(LPCSTR,DWORD,DWORD,LPVOID) = NULL;
1836         CHAR mbpath[MAX_PATH];
1837
1838         GET_FUNC(version, "GetFileVersionInfoA", 0);
1839         WideCharToMultiByte(0, 0, w, -1, mbpath, MAX_PATH, 0, 0);
1840         return pfnFunc(mbpath  , x, y-0x208, z+0x208);
1841 }
1842
1843 /*************************************************************************
1844  *      @       [SHLWAPI.352]
1845  *
1846  * seems to be W interface to VerQueryValueA
1847  */
1848 WORD WINAPI SHLWAPI_352 (
1849         LPVOID w,   /* [in] buffer from _351 */
1850         LPWSTR x,   /* [in]   value to retrieve - 
1851                               converted and passed to VerQueryValueA as #2 */
1852         LPVOID y,   /* [out]  ver buffer - passed to VerQueryValueA as #3 */
1853         UINT*  z)   /* [in]   ver length - passed to VerQueryValueA as #4 */
1854 {
1855         static WORD    WINAPI (*pfnFunc)(LPVOID,LPCSTR,LPVOID*,UINT*) = NULL;
1856         CHAR buf1[MAX_PATH];
1857         WORD ret;
1858
1859         GET_FUNC(version, "VerQueryValueA", 0);
1860         WideCharToMultiByte(0, 0, x, lstrlenW(x)+1, buf1, MAX_PATH, 0, 0);
1861         ret = pfnFunc(w+0x208, buf1, y, z);
1862         if (CompareStringA(GetThreadLocale(), NORM_IGNORECASE, buf1, 1,
1863                            "\\StringFileInfo", 15) == 2 /* CSTR_EQUAL */) {
1864             ERR("Need to translate back to wide - should fail now\n");
1865         }
1866         return ret;
1867 }
1868
1869 /*************************************************************************
1870  *      @       [SHLWAPI.356]
1871  */
1872 DWORD WINAPI SHLWAPI_356 (
1873         LPVOID x,
1874         LPVOID y,
1875         LPVOID z)
1876 {
1877         FIXME("(%p %p %p)stub\n", x,y,z);
1878         return 0;
1879 }
1880
1881 /*************************************************************************
1882  *      @       [SHLWAPI.357]
1883  *
1884  * Late bound call to shell32.SHGetNewLinkInfoW
1885  */
1886 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
1887                         BOOL *pfMustCopy, UINT uFlags)
1888 {
1889   static BOOL (WINAPI *pfnFunc)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT) = NULL;
1890
1891   GET_FUNC(shell32, "SHGetNewLinkInfoW", FALSE);
1892   return pfnFunc(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
1893 }
1894
1895 /*************************************************************************
1896  *      @       [SHLWAPI.358]
1897  *
1898  * Late bound call to shell32.SHDefExtractIconW
1899  */
1900 DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
1901                          LPVOID arg5, LPVOID arg6)
1902 {
1903   /* FIXME: Correct args */
1904   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
1905
1906   GET_FUNC(shell32, "SHDefExtractIconW", 0);
1907   return pfnFunc(arg1, arg2, arg3, arg4, arg5, arg6);
1908 }
1909
1910 /*************************************************************************
1911  *      @       [SHLWAPI.364]
1912  *
1913  * Wrapper for lstrcpynA with src and dst swapped.
1914  */
1915 DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
1916 {
1917   lstrcpynA(dst, src, n);
1918   return TRUE;
1919 }
1920
1921 /*************************************************************************
1922  *      @       [SHLWAPI.370]
1923  *
1924  * Late bound call to shell32.ExtractIconW
1925  */
1926 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
1927                          UINT nIconIndex)
1928 {
1929   static HICON (WINAPI *pfnFunc)(HINSTANCE, LPCWSTR, UINT) = NULL;
1930
1931   GET_FUNC(shell32, "ExtractIconW", (HICON)0);
1932   return pfnFunc(hInstance, lpszExeFileName, nIconIndex);
1933 }
1934
1935 /*************************************************************************
1936  *      @       [SHLWAPI.376]
1937  */
1938 LANGID WINAPI SHLWAPI_376 ()
1939 {
1940     FIXME("() stub\n");
1941     /* FIXME: This should be a forward in the .spec file to the win2k function
1942      * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
1943      */
1944     return GetUserDefaultLangID();
1945 }
1946
1947 /*************************************************************************
1948  *      @       [SHLWAPI.377]
1949  *
1950  * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for 
1951  *        each call here.
1952  * FIXME: Native shows calls to:
1953  *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
1954  *                      CheckVersion
1955  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
1956  *  RegQueryValueExA for "LPKInstalled"
1957  *  RegCloseKey
1958  *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
1959  *  RegQueryValueExA for "ResourceLocale"
1960  *  RegCloseKey
1961  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
1962  *  RegQueryValueExA for "Locale"
1963  *  RegCloseKey
1964  *  and then tests the Locale ("en" for me).
1965  *     code below
1966  *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
1967  */
1968 DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
1969 {
1970     CHAR mod_path[2*MAX_PATH];
1971     LPSTR ptr;
1972
1973     GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
1974     ptr = strrchr(mod_path, '\\');
1975     if (ptr) {
1976         strcpy(ptr+1, new_mod);
1977         TRACE("loading %s\n", debugstr_a(mod_path));
1978         return (DWORD)LoadLibraryA(mod_path);
1979     }
1980     return 0;
1981 }
1982
1983 /*************************************************************************
1984  *      @       [SHLWAPI.378]
1985  *
1986  *  This is Unicode version of .377
1987  */
1988 DWORD WINAPI SHLWAPI_378 (
1989         LPCWSTR   new_mod,          /* [in] new module name        */
1990         HMODULE   inst_hwnd,        /* [in] calling module handle  */
1991         LPVOID z)                   /* [???] 4 */
1992 {
1993     WCHAR mod_path[2*MAX_PATH];
1994     LPWSTR ptr;
1995
1996     GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
1997     ptr = strrchrW(mod_path, '\\');
1998     if (ptr) {
1999         strcpyW(ptr+1, new_mod);
2000         TRACE("loading %s\n", debugstr_w(mod_path));
2001         return (DWORD)LoadLibraryW(mod_path);
2002     }
2003     return 0;
2004 }
2005
2006 /*************************************************************************
2007  *      @       [SHLWAPI.389]
2008  *
2009  * Late bound call to comdlg32.GetSaveFileNameW
2010  */
2011 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
2012 {
2013   static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
2014
2015   GET_FUNC(comdlg32, "GetSaveFileNameW", FALSE);
2016   return pfnFunc(ofn);
2017 }
2018
2019 /*************************************************************************
2020  *      @       [SHLWAPI.390]
2021  *
2022  * Late bound call to mpr.WNetRestoreConnectionW
2023  */
2024 DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
2025 {
2026   /* FIXME: Correct args */
2027   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID) = NULL;
2028
2029   GET_FUNC(mpr, "WNetRestoreConnectionW", 0);
2030   return pfnFunc(arg1, arg2);
2031 }
2032
2033 /*************************************************************************
2034  *      @       [SHLWAPI.391]
2035  *
2036  * Late bound call to mpr.WNetGetLastErrorW
2037  */
2038 DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2039                          LPVOID arg5)
2040 {
2041   /* FIXME: Correct args */
2042   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
2043
2044   GET_FUNC(mpr, "WNetGetLastErrorW", 0);
2045   return pfnFunc(arg1, arg2, arg3, arg4, arg5);
2046 }
2047
2048 /*************************************************************************
2049  *      @       [SHLWAPI.401]
2050  *
2051  * Late bound call to comdlg32.PageSetupDlgW
2052  */
2053 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
2054 {
2055   static BOOL (WINAPI *pfnFunc)(LPPAGESETUPDLGW) = NULL;
2056
2057   GET_FUNC(comdlg32, "PageSetupDlgW", FALSE);
2058   return pfnFunc(pagedlg);
2059 }
2060
2061 /*************************************************************************
2062  *      @       [SHLWAPI.402]
2063  *
2064  * Late bound call to comdlg32.PrintDlgW
2065  */
2066 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
2067 {
2068   static BOOL (WINAPI *pfnFunc)(LPPRINTDLGW) = NULL;
2069
2070   GET_FUNC(comdlg32, "PrintDlgW", FALSE);
2071   return pfnFunc(printdlg);
2072 }
2073
2074 /*************************************************************************
2075  *      @       [SHLWAPI.403]
2076  *
2077  * Late bound call to comdlg32.GetOpenFileNameW
2078  */
2079 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
2080 {
2081   static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
2082
2083   GET_FUNC(comdlg32, "GetOpenFileNameW", FALSE);
2084   return pfnFunc(ofn);
2085 }
2086
2087 /* INTERNAL: Map from HLS color space to RGB */
2088 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
2089 {
2090   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
2091
2092   if (wHue > 160)
2093     return wMid1;
2094   else if (wHue > 120)
2095     wHue = 160 - wHue;
2096   else if (wHue > 40)
2097     return wMid2;
2098
2099   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
2100 }
2101
2102 /* Convert to RGB and scale into RGB range (0..255) */
2103 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
2104
2105 /*************************************************************************
2106  *      ColorHLSToRGB   [SHLWAPI.404]
2107  *
2108  * Convert from HLS color space into an RGB COLORREF.
2109  *
2110  * NOTES
2111  * Input HLS values are constrained to the range (0..240).
2112  */
2113 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
2114 {
2115   WORD wRed;
2116
2117   if (wSaturation)
2118   {
2119     WORD wGreen, wBlue, wMid1, wMid2;
2120
2121     if (wLuminosity > 120)
2122       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
2123     else
2124       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
2125
2126     wMid1 = wLuminosity * 2 - wMid2;
2127
2128     wRed   = GET_RGB(wHue + 80);
2129     wGreen = GET_RGB(wHue);
2130     wBlue  = GET_RGB(wHue - 80);
2131
2132     return RGB(wRed, wGreen, wBlue);
2133   }
2134
2135   wRed = wLuminosity * 255 / 240;
2136   return RGB(wRed, wRed, wRed);
2137 }
2138
2139 /*************************************************************************
2140  *      @       [SHLWAPI.413]
2141  *
2142  * Function unknown seems to always to return 0
2143  */
2144 DWORD WINAPI SHLWAPI_413 (DWORD x)
2145 {
2146         FIXME("(0x%08lx)stub\n", x);
2147         return 0;
2148 }
2149
2150 /*************************************************************************
2151  *      @       [SHLWAPI.418]
2152  *
2153  * Function seems to do FreeLibrary plus other things.
2154  *
2155  * FIXME native shows the following calls:
2156  *   RtlEnterCriticalSection
2157  *   LocalFree
2158  *   GetProcAddress(Comctl32??, 150L)
2159  *   DPA_DeletePtr
2160  *   RtlLeaveCriticalSection
2161  *  followed by the FreeLibrary.
2162  *  The above code may be related to .377 above.
2163  */
2164 BOOL  WINAPI SHLWAPI_418 (HMODULE x)
2165 {
2166         FIXME("(0x%08lx) partial stub\n", (LONG)x);
2167         return FreeLibrary(x);
2168 }
2169
2170 /*************************************************************************
2171  *      @       [SHLWAPI.431]
2172  */
2173 DWORD WINAPI SHLWAPI_431 (DWORD x)
2174 {
2175         FIXME("(0x%08lx)stub\n", x);
2176         return 0xabba1247;
2177 }
2178
2179 /*************************************************************************
2180  *      @       [SHLWAPI.436]
2181  *
2182  *  This is really CLSIDFromString which is exported by ole32.dll,
2183  *  however the native shlwapi.dll does *not* import ole32. Nor does
2184  *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
2185  *  that MS duplicated the code for CLSIDFromString.
2186  *
2187  *  This is a duplicate (with changes for UNICODE) of CLSIDFromString16
2188  *  in dlls/ole32/compobj.c
2189  */
2190 DWORD WINAPI SHLWAPI_436 (LPWSTR idstr, CLSID *id)
2191 {
2192     LPWSTR s = idstr;
2193     BYTE *p;
2194     INT i;
2195     WCHAR table[256];
2196
2197     if (!s) {
2198         memset(s, 0, sizeof(CLSID));
2199         return S_OK;
2200     }
2201     else {  /* validate the CLSID string */
2202
2203         if (strlenW(s) != 38)
2204             return CO_E_CLASSSTRING;
2205
2206         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
2207             return CO_E_CLASSSTRING;
2208
2209         for (i=1; i<37; i++)
2210             {
2211                 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
2212                 if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
2213                       ((s[i] >= L'a') && (s[i] <= L'f'))  ||
2214                       ((s[i] >= L'A') && (s[i] <= L'F')))
2215                     )
2216                     return CO_E_CLASSSTRING;
2217             }
2218     }
2219
2220     TRACE("%s -> %p\n", debugstr_w(s), id);
2221
2222   /* quick lookup table */
2223     memset(table, 0, 256*sizeof(WCHAR));
2224
2225     for (i = 0; i < 10; i++) {
2226         table['0' + i] = i;
2227     }
2228     for (i = 0; i < 6; i++) {
2229         table['A' + i] = i+10;
2230         table['a' + i] = i+10;
2231     }
2232
2233     /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
2234
2235     p = (BYTE *) id;
2236
2237     s++;        /* skip leading brace  */
2238     for (i = 0; i < 4; i++) {
2239         p[3 - i] = table[*s]<<4 | table[*(s+1)];
2240         s += 2;
2241     }
2242     p += 4;
2243     s++;        /* skip - */
2244
2245     for (i = 0; i < 2; i++) {
2246         p[1-i] = table[*s]<<4 | table[*(s+1)];
2247         s += 2;
2248     }
2249     p += 2;
2250     s++;        /* skip - */
2251
2252     for (i = 0; i < 2; i++) {
2253         p[1-i] = table[*s]<<4 | table[*(s+1)];
2254         s += 2;
2255     }
2256     p += 2;
2257     s++;        /* skip - */
2258
2259     /* these are just sequential bytes */
2260     for (i = 0; i < 2; i++) {
2261         *p++ = table[*s]<<4 | table[*(s+1)];
2262         s += 2;
2263     }
2264     s++;        /* skip - */
2265
2266     for (i = 0; i < 6; i++) {
2267         *p++ = table[*s]<<4 | table[*(s+1)];
2268         s += 2;
2269     }
2270
2271     return S_OK;
2272 }
2273
2274 /*************************************************************************
2275  *      @       [SHLWAPI.437]
2276  *
2277  * NOTES
2278  *  In the real shlwapi, One time initialisation calls GetVersionEx and reads
2279  *  the registry to determine what O/S & Service Pack level is running, and
2280  *  therefore which functions are available. Currently we always run as NT,
2281  *  since this means that we don't need extra code to emulate Unicode calls,
2282  *  they are forwarded directly to the appropriate API call instead.
2283  *  Since the flags for whether to call or emulate Unicode are internal to
2284  *  the dll, this function does not need a full implementation.
2285  */
2286 DWORD WINAPI SHLWAPI_437 (DWORD functionToCall)
2287 {
2288         FIXME("(0x%08lx)stub\n", functionToCall);
2289         return /* 0xabba1247 */ 0;
2290 }
2291
2292 /*************************************************************************
2293  *      ColorRGBToHLS   [SHLWAPI.445]
2294  *
2295  * Convert from RGB COLORREF into the HLS color space.
2296  *
2297  * NOTES
2298  * Input HLS values are constrained to the range (0..240).
2299  */
2300 VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue, 
2301                           LPWORD wLuminance, LPWORD pwSaturation)
2302 {
2303     FIXME("stub\n");
2304     return;
2305 }
2306
2307 /*************************************************************************
2308  *      SHCreateShellPalette    [SHLWAPI.@]
2309  */
2310 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
2311 {
2312         FIXME("stub\n");
2313         return CreateHalftonePalette(hdc);
2314 }
2315
2316 /*************************************************************************
2317  *      SHGetInverseCMAP (SHLWAPI.@)
2318  */
2319 DWORD WINAPI SHGetInverseCMAP (LPDWORD* x, DWORD why)
2320 {
2321     if (why == 4) {
2322         FIXME(" - returning bogus address for SHGetInverseCMAP\n");
2323         *x = (LPDWORD)0xabba1249;
2324         return 0;
2325     }
2326     FIXME("(%p, %#lx)stub\n", x, why);
2327     return 0;
2328 }
2329
2330 /*************************************************************************
2331  *      SHIsLowMemoryMachine    [SHLWAPI.@]
2332  */
2333 DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
2334 {
2335         FIXME("0x%08lx\n", x);
2336         return 0;
2337 }
2338
2339 /*************************************************************************
2340  *      GetMenuPosFromID        [SHLWAPI.@]
2341  */
2342 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
2343 {
2344  MENUITEMINFOA mi;
2345  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
2346
2347  while (nIter < nCount)
2348  {
2349    mi.wID = 0;
2350    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
2351      return nIter;
2352    nIter++;
2353  }
2354  return -1;
2355 }
2356
2357 /*************************************************************************
2358  *      _SHGetInstanceExplorer@4        [SHLWAPI.@]
2359  *
2360  * Late bound call to shell32.SHGetInstanceExplorer.
2361  */
2362 HRESULT WINAPI _SHGetInstanceExplorer (LPUNKNOWN *lpUnknown)
2363 {
2364   static HRESULT (WINAPI *pfnFunc)(LPUNKNOWN *) = NULL;
2365
2366   GET_FUNC(shell32, "SHGetInstanceExplorer", E_FAIL);
2367   return pfnFunc(lpUnknown);
2368 }
2369
2370 /*************************************************************************
2371  *      SHGetThreadRef  [SHLWAPI.@]
2372  *
2373  * Retrieves the per-thread object reference set by SHSetThreadRef
2374  * "punk" - Address of a pointer to the IUnknown interface. Returns S_OK if
2375  *          successful or E_NOINTERFACE otherwise.
2376  */
2377 HRESULT WINAPI SHGetThreadRef (IUnknown ** ppunk)
2378 {
2379     if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
2380     *ppunk = (IUnknown *)TlsGetValue(SHLWAPI_ThreadRef_index);
2381     return S_OK;
2382 }
2383
2384 /*************************************************************************
2385  *      SHSetThreadRef  [SHLWAPI.@]
2386  *
2387  * Stores a per-thread reference to a COM object
2388  * "punk" - Pointer to the IUnknown interface of the object to
2389  *          which you want to store a reference. Returns S_OK if successful
2390  *          or an OLE error value.
2391  */
2392 HRESULT WINAPI SHSetThreadRef (IUnknown * punk)
2393 {
2394     if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
2395     TlsSetValue(SHLWAPI_ThreadRef_index, (LPVOID) punk);
2396     return S_OK;
2397 }