Leave IID check to the OleCreateFontIndirect, so that SFCF will handle
[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
39 typedef HANDLE HSHARED; /* Shared memory */
40
41 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
42 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
43 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
44 static 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  */
49 typedef 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
73 typedef struct {
74     URL_SCHEME  scheme_number;
75     LPCSTR scheme_name;
76 } SHL_2_inet_scheme;
77
78 static 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 };
99
100 /* Macro to get function pointer for a module*/
101 #define GET_FUNC(module, name, fail) \
102   if (!SHLWAPI_h##module) SHLWAPI_h##module = LoadLibraryA(#module ".dll"); \
103   if (!SHLWAPI_h##module) return fail; \
104   if (!pfnFunc) pfnFunc = (void*)GetProcAddress(SHLWAPI_h##module, name); \
105   if (!pfnFunc) return fail
106
107 /*
108  NOTES: Most functions exported by ordinal seem to be superflous.
109  The reason for these functions to be there is to provide a wraper
110  for unicode functions to provide these functions on systems without
111  unicode functions eg. win95/win98. Since we have such functions we just
112  call these. If running Wine with native DLL's, some late bound calls may
113  fail. However, its better to implement the functions in the forward DLL
114  and recommend the builtin rather than reimplementing the calls here!
115 */
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  */
123 DWORD 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  */
177 DWORD 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  */
236 static
237 HSHARED 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    */
306 HSHARED 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(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    */
357 PVOID 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 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  */
391 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
392 {
393   TRACE("(%p)\n", lpView);
394   return UnmapViewOfFile(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  */
413 BOOL 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  */
445 HSHARED 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  */
459 HRESULT 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  */
532 HRESULT 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));
575         return 0;
576 }
577
578 /*************************************************************************
579  *      @       [SHLWAPI.15]
580  *
581  * Function:
582  *    Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
583  *  
584  */
585 HRESULT 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]
628  */
629 HRESULT WINAPI SHLWAPI_16 (
630         LPVOID w,
631         LPVOID x,
632         LPVOID y,
633         LPWSTR z)
634 {
635         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
636         return 0xabba1252;
637 }
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  */
650 LONG 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  */
668 LONG 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  */
687 LONG 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  */
703 LPVOID 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]
713  *
714  * NOTES
715  *      converts a guid to a string
716  *      returns strlen(str)
717  */
718 DWORD WINAPI SHLWAPI_23 (
719         REFGUID guid,   /* [in]  clsid */
720         LPSTR str,      /* [out] buffer */
721         INT cmax)       /* [in]  size of buffer */
722 {
723         char xguid[40];
724
725         sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
726                  guid->Data1, guid->Data2, guid->Data3,
727                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
728                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
729         TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
730         if (strlen(xguid)>=cmax) return 0;
731         strcpy(str,xguid);
732         return strlen(xguid) + 1;
733 }
734
735 /*************************************************************************
736  *      @       [SHLWAPI.24]
737  *
738  * NOTES
739  *      converts a guid to a string
740  *      returns strlen(str)
741  */
742 DWORD WINAPI SHLWAPI_24 (
743         REFGUID guid,   /* [in]  clsid */
744         LPWSTR str,     /* [out] buffer */
745         INT cmax)       /* [in]  size of buffer */
746 {
747     char xguid[40];
748
749     sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
750              guid->Data1, guid->Data2, guid->Data3,
751              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
752              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
753     return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
754 }
755
756 /*************************************************************************
757  *      @       [SHLWAPI.25]
758  *
759  * Seems to be iswalpha
760  */
761 BOOL 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  */
771 BOOL 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  */
781 BOOL 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  */
791 BOOL 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  */
801 BOOL 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  */
811 BOOL 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  */
821 BOOL 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  */
831 BOOL 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  */
841 BOOL 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  */
851 BOOL WINAPI SHLWAPI_34(WCHAR wc)
852 {
853     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
854 }
855
856 /*************************************************************************
857  *      @       [SHLWAPI.35]
858  *
859  */
860 BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
861 {
862     FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
863     return TRUE;
864 }
865
866 /*************************************************************************
867  *      @       [SHLWAPI.36]
868  *
869  */
870 BOOL 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]
879  *
880  * Get pointer to next Unicode character.
881  */
882 LPCWSTR WINAPI SHLWAPI_40(LPCWSTR str)
883 {
884   return *str ? str + 1 : str;
885 }
886
887 /*************************************************************************
888  *      @       [SHLWAPI.74]
889  *
890  * Get the text from a given dialog item.
891  */
892 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
893 {
894   HWND hItem = GetDlgItem(hWnd, nItem);
895
896   if (hItem)
897     return GetWindowTextW(hItem, lpsDest, nDestLen);
898   if (nDestLen)
899     *lpsDest = (WCHAR)'\0';
900   return 0;
901 }
902
903 /*************************************************************************
904  *      @       [SHLWAPI.151]
905  * Function:  Compare two ASCII strings for "len" bytes.
906  * Returns:   *str1-*str2  (case sensitive)
907  */
908 DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
909 {
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)
918  */
919 DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
920 {
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  */
929 DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
930 {
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  */
940 DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
941 {
942     return strncmpiW( str1, str2, len );
943 }
944
945 /*************************************************************************
946  *      @       [SHLWAPI.156]
947  *
948  *      Case sensitive string compare. Does not SetLastError().
949  */
950 DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
951 {
952     return strcmpW( str1, str2 );
953 }
954
955 /*************************************************************************
956  *      @       [SHLWAPI.158]
957  *
958  *      Case insensitive string compare. Does not SetLastError(). ??
959  */
960 DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
961 {
962     return strcmpiW( str1, str2 );
963 }
964
965 /*************************************************************************
966  *      @       [SHLWAPI.162]
967  *
968  * Ensure a multibyte character string doesn't end in a hanging lead byte.
969  */
970 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
971 {
972   if (lpStr && size)
973   {
974     LPSTR lastByte = lpStr + size - 1;
975
976     while(lpStr < lastByte)
977       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
978
979     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
980     {
981       *lpStr = '\0';
982       size--;
983     }
984     return size;
985   }
986   return 0;
987 }
988
989 /*************************************************************************
990  *      @       [SHLWAPI.164]
991  */
992 DWORD 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]
1006  *
1007  * SetWindowLongA with mask.
1008  */
1009 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wFlags, UINT wMask)
1010 {
1011   LONG ret = GetWindowLongA(hwnd, offset);
1012   UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
1013
1014   if (newFlags != ret)
1015     ret = SetWindowLongA(hwnd, offset, newFlags);
1016   return ret;
1017 }
1018
1019 /*************************************************************************
1020  *      @       [SHLWAPI.169]
1021  *
1022  *  Do IUnknown::Release on passed object.
1023  */
1024 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1025 {
1026         IUnknown *temp;
1027
1028         TRACE("(%p)\n",lpUnknown);
1029         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1030         temp = *lpUnknown;
1031         *lpUnknown = NULL;
1032         TRACE("doing Release\n");
1033         return IUnknown_Release(temp);
1034 }
1035
1036 /*************************************************************************
1037  *      @       [SHLWAPI.170]
1038  *
1039  * Skip URL '//' sequence.
1040  */
1041 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1042 {
1043   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1044     lpszSrc += 2;
1045   return lpszSrc;
1046 }
1047
1048 /*************************************************************************
1049  *      @       [SHLWAPI.172]
1050  * Get window handle of OLE object
1051  */
1052 DWORD 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  */
1079 DWORD 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  */
1124 DWORD 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]
1146  *
1147  *      Enable or disable a menu item.
1148  */
1149 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1150 {
1151   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1152 }
1153
1154 /*************************************************************************
1155  *      @       [SHLWAPI.183]
1156  *
1157  * Register a window class if it isn't already.
1158  */
1159 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1160 {
1161   WNDCLASSA wca;
1162   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1163     return TRUE;
1164   return (DWORD)RegisterClassA(wndclass);
1165 }
1166
1167 /*************************************************************************
1168  *      @       [SHLWAPI.193]
1169  */
1170 DWORD WINAPI SHLWAPI_193 ()
1171 {
1172         HDC hdc;
1173         DWORD ret;
1174
1175         TRACE("()\n");
1176
1177         hdc = GetDC(0);
1178         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1179         ReleaseDC(0, hdc);
1180         return ret;
1181 }
1182
1183 /*************************************************************************
1184  *      @       [SHLWAPI.199]
1185  *
1186  * Copy interface pointer
1187  */
1188 DWORD 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  */
1209 DWORD 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  */
1226 DWORD 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  */
1239 DWORD 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]
1250  *
1251  * NOTES
1252  *  check me!
1253  */
1254 DWORD WINAPI SHLWAPI_215 (
1255         LPCSTR lpStrSrc,
1256         LPWSTR lpwStrDest,
1257         int len)
1258 {
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]
1270  *
1271  * WideCharToMultiByte with multi language support.
1272  */
1273 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
1274                        LPINT lpnMultiCharCount)
1275 {
1276   static HRESULT (WINAPI *pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
1277   WCHAR emptyW[] = { '\0' };
1278   int len , reqLen;
1279   LPSTR mem;
1280
1281   if (!lpDstStr || !lpnMultiCharCount)
1282     return 0;
1283
1284   if (!lpSrcStr)
1285     lpSrcStr = emptyW;
1286
1287   *lpDstStr = '\0';
1288
1289   len = strlenW(lpSrcStr) + 1;
1290
1291   switch (CodePage)
1292   {
1293   case CP_WINUNICODE:
1294     CodePage = CP_UTF8; /* Fall through... */
1295   case 0x0000C350: /* FIXME: CP_ #define */
1296   case CP_UTF7:
1297   case CP_UTF8:
1298     {
1299       DWORD dwMode = 0;
1300       INT nWideCharCount = len - 1;
1301
1302       GET_FUNC(mlang, "ConvertINetUnicodeToMultiByte", 0);
1303       if (!pfnFunc(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
1304                    lpnMultiCharCount))
1305         return 0;
1306
1307       if (nWideCharCount < len - 1)
1308       {
1309         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
1310         if (!mem)
1311           return 0;
1312
1313         *lpnMultiCharCount = 0;
1314
1315         if (pfnFunc(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
1316         {
1317           SHLWAPI_162 (mem, *lpnMultiCharCount);
1318           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
1319           return *lpnMultiCharCount + 1;
1320         }
1321         HeapFree(GetProcessHeap(), 0, mem);
1322         return *lpnMultiCharCount;
1323       }
1324       lpDstStr[*lpnMultiCharCount] = '\0';
1325       return *lpnMultiCharCount;
1326     }
1327     break;
1328   default:
1329     break;
1330   }
1331
1332   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
1333                                *lpnMultiCharCount, NULL, NULL);
1334
1335   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1336   {
1337     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
1338     if (reqLen)
1339     {
1340       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
1341       if (mem)
1342       {
1343         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
1344                                      reqLen, NULL, NULL);
1345
1346         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
1347         reqLen++;
1348
1349         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
1350
1351         HeapFree(GetProcessHeap(), 0, mem);
1352       }
1353     }
1354   }
1355   return reqLen;
1356 }
1357
1358 /*************************************************************************
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  */
1366 INT 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.
1378  *
1379  * NOTES
1380  *  error codes: E_POINTER, E_NOINTERFACE
1381  */
1382 typedef struct {
1383     REFIID   refid;
1384     DWORD    indx;
1385 } IFACE_INDEX_TBL;
1386
1387 HRESULT WINAPI SHLWAPI_219 (
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]
1430  *
1431  * NOTES
1432  *  securityattributes missing
1433  */
1434 HANDLE WINAPI SHLWAPI_222 (LPCLSID guid)
1435 {
1436         char lpstrName[80];
1437
1438         sprintf( lpstrName, "shell.{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1439                  guid->Data1, guid->Data2, guid->Data3,
1440                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
1441                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
1442         FIXME("(%s) stub\n", lpstrName);
1443         return CreateSemaphoreA(NULL,0, 0x7fffffff, lpstrName);
1444 }
1445
1446 /*************************************************************************
1447  *      @       [SHLWAPI.223]
1448  *
1449  * NOTES
1450  *  get the count of the semaphore
1451  */
1452 DWORD WINAPI SHLWAPI_223 (HANDLE handle)
1453 {
1454         DWORD oldCount;
1455
1456         FIXME("(0x%08x) stub\n",handle);
1457
1458         ReleaseSemaphore( handle, 1, &oldCount);        /* +1 */
1459         WaitForSingleObject( handle, 0 );               /* -1 */
1460         return oldCount;
1461 }
1462
1463 /*************************************************************************
1464  *      @       [SHLWAPI.236]
1465  */
1466 HMODULE 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]
1485  *
1486  * Unicode version of SHLWAPI_183.
1487  */
1488 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
1489 {
1490         WNDCLASSW WndClass;
1491
1492         TRACE("(0x%08x %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
1493
1494         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
1495                 return TRUE;
1496         return RegisterClassW(lpWndClass);
1497 }
1498
1499 /*************************************************************************
1500  *      @       [SHLWAPI.239]
1501  */
1502 DWORD 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]
1523  *
1524  *      Calls ASCII or Unicode WindowProc for the given window.
1525  */
1526 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1527 {
1528         if (IsWindowUnicode(hWnd))
1529                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1530         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
1531 }
1532
1533 /*************************************************************************
1534  *      @       [SHLWAPI.241]
1535  *
1536  */
1537 DWORD WINAPI SHLWAPI_241 ()
1538 {
1539         FIXME("()stub\n");
1540         return /* 0xabba1243 */ 0;
1541 }
1542
1543 /*************************************************************************
1544  *      @       [SHLWAPI.266]
1545  */
1546 DWORD WINAPI SHLWAPI_266 (
1547         LPVOID w,
1548         LPVOID x,
1549         LPVOID y,
1550         LPVOID z)
1551 {
1552         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1553         return 0xabba1248;
1554 }
1555
1556 /*************************************************************************
1557  *      @       [SHLWAPI.267]
1558  */
1559 HRESULT WINAPI SHLWAPI_267 (
1560         LPVOID w, /* [???] NOTE: same as 1th parameter of SHLWAPI_219 */
1561         LPVOID x, /* [???] NOTE: same as 2nd parameter of SHLWAPI_219 */
1562         LPVOID y,
1563         LPVOID z)
1564 {
1565         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1566         *((LPDWORD)z) = 0xabba1200;
1567         return 0xabba1254;
1568 }
1569
1570 /*************************************************************************
1571  *      @       [SHLWAPI.268]
1572  */
1573 DWORD WINAPI SHLWAPI_268 (
1574         LPVOID w,
1575         LPVOID x)
1576 {
1577         FIXME("(%p %p)\n",w,x);
1578         return 0xabba1251; /* 0 = failure */
1579 }
1580
1581 /*************************************************************************
1582  *      @       [SHLWAPI.276]
1583  *
1584  */
1585 DWORD WINAPI SHLWAPI_276 ()
1586 {
1587         FIXME("()stub\n");
1588         return /* 0xabba1244 */ 0;
1589 }
1590
1591 /*************************************************************************
1592  *      @       [SHLWAPI.278]
1593  *
1594  */
1595 HWND WINAPI SHLWAPI_278 (
1596         LONG wndProc,
1597         HWND hWndParent,
1598         DWORD dwExStyle,
1599         DWORD dwStyle,
1600         HMENU hMenu,
1601         LONG z)
1602 {
1603         WNDCLASSA wndclass;
1604         HWND hwnd;
1605         HCURSOR hCursor;
1606         char * clsname = "WorkerA";
1607
1608         FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
1609           wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
1610
1611         hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
1612
1613         if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
1614         {
1615           RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
1616           wndclass.lpfnWndProc = DefWindowProcW;
1617           wndclass.cbWndExtra = 4;
1618           wndclass.hInstance = shlwapi_hInstance;
1619           wndclass.hCursor = hCursor;
1620           wndclass.hbrBackground = COLOR_BTNSHADOW;
1621           wndclass.lpszMenuName = NULL;
1622           wndclass.lpszClassName = clsname;
1623           RegisterClassA (&wndclass);
1624         }
1625         hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
1626                 hMenu,shlwapi_hInstance,0);
1627         SetWindowLongA(hwnd, 0, z);
1628         SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
1629         return hwnd;
1630 }
1631
1632 /*************************************************************************
1633  *      @       [SHLWAPI.289]
1634  *
1635  * Late bound call to winmm.PlaySoundW
1636  */
1637 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
1638 {
1639   static BOOL (WINAPI *pfnFunc)(LPCWSTR, HMODULE, DWORD) = NULL;
1640
1641   GET_FUNC(winmm, "PlaySoundW", FALSE);
1642   return pfnFunc(pszSound, hmod, fdwSound);
1643 }
1644
1645 /*************************************************************************
1646  *      @       [SHLWAPI.294]
1647  */
1648 BOOL 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]
1671  *
1672  * Late bound call to shell32.SHGetFileInfoW
1673  */
1674 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
1675                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
1676 {
1677   static DWORD (WINAPI *pfnFunc)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT) = NULL;
1678
1679   GET_FUNC(shell32, "SHGetFileInfoW", 0);
1680   return pfnFunc(path, dwFileAttributes, psfi, sizeofpsfi, flags);
1681 }
1682
1683 /*************************************************************************
1684  *      @       [SHLWAPI.318]
1685  *
1686  * Late bound call to shell32.DragQueryFileW
1687  */
1688 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
1689 {
1690   static UINT (WINAPI *pfnFunc)(HDROP, UINT, LPWSTR, UINT) = NULL;
1691
1692   GET_FUNC(shell32, "DragQueryFileW", 0);
1693   return pfnFunc(hDrop, lFile, lpszFile, lLength);
1694 }
1695
1696 /*************************************************************************
1697  *      @       [SHLWAPI.333]
1698  *
1699  * Late bound call to shell32.SHBrowseForFolderW
1700  */
1701 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
1702 {
1703   static LPITEMIDLIST (WINAPI *pfnFunc)(LPBROWSEINFOW) = NULL;
1704
1705   GET_FUNC(shell32, "SHBrowseForFolderW", NULL);
1706   return pfnFunc(lpBi);
1707 }
1708
1709 /*************************************************************************
1710  *      @       [SHLWAPI.334]
1711  *
1712  * Late bound call to shell32.SHGetPathFromIDListW
1713  */
1714 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
1715 {
1716   static BOOL (WINAPI *pfnFunc)(LPCITEMIDLIST, LPWSTR) = NULL;
1717
1718   GET_FUNC(shell32, "SHGetPathFromIDListW", 0);
1719   return pfnFunc(pidl, pszPath);
1720 }
1721
1722 /*************************************************************************
1723  *      @       [SHLWAPI.335]
1724  *
1725  * Late bound call to shell32.ShellExecuteExW
1726  */
1727 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
1728 {
1729   static BOOL (WINAPI *pfnFunc)(LPSHELLEXECUTEINFOW) = NULL;
1730
1731   GET_FUNC(shell32, "ShellExecuteExW", FALSE);
1732   return pfnFunc(lpExecInfo);
1733 }
1734
1735 /*************************************************************************
1736  *      @       [SHLWAPI.336]
1737  *
1738  * Late bound call to shell32.SHFileOperationW.
1739  */
1740 DWORD WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
1741 {
1742   static HICON (WINAPI *pfnFunc)(LPSHFILEOPSTRUCTW) = NULL;
1743
1744   GET_FUNC(shell32, "SHFileOperationW", 0);
1745   return pfnFunc(lpFileOp);
1746 }
1747
1748 /*************************************************************************
1749  *      @       [SHLWAPI.337]
1750  *
1751  * Late bound call to shell32.ExtractIconExW.
1752  */
1753 HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
1754                          HICON *phiconSmall, UINT nIcons)
1755 {
1756   static HICON (WINAPI *pfnFunc)(LPCWSTR, INT,HICON *,HICON *, UINT) = NULL;
1757
1758   GET_FUNC(shell32, "ExtractIconExW", (HICON)0);
1759   return pfnFunc(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
1760 }
1761
1762 /*************************************************************************
1763  *      @       [SHLWAPI.342]
1764  *
1765  */
1766 DWORD WINAPI SHLWAPI_342 (
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]
1778  */
1779 DWORD WINAPI SHLWAPI_346 (
1780         LPCWSTR src,
1781         LPWSTR dest,
1782         int len)
1783 {
1784         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
1785         lstrcpynW(dest, src, len);
1786         return lstrlenW(dest)+1;
1787 }
1788
1789 /*************************************************************************
1790  *      @       [SHLWAPI.356]
1791  */
1792 DWORD 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]
1803  *
1804  * Late bound call to shell32.SHGetNewLinkInfoW
1805  */
1806 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
1807                         BOOL *pfMustCopy, UINT uFlags)
1808 {
1809   static BOOL (WINAPI *pfnFunc)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT) = NULL;
1810
1811   GET_FUNC(shell32, "SHGetNewLinkInfoW", FALSE);
1812   return pfnFunc(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
1813 }
1814
1815 /*************************************************************************
1816  *      @       [SHLWAPI.358]
1817  *
1818  * Late bound call to shell32.SHDefExtractIconW
1819  */
1820 DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
1821                          LPVOID arg5, LPVOID arg6)
1822 {
1823   /* FIXME: Correct args */
1824   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
1825
1826   GET_FUNC(shell32, "SHDefExtractIconW", 0);
1827   return pfnFunc(arg1, arg2, arg3, arg4, arg5, arg6);
1828 }
1829
1830 /*************************************************************************
1831  *      @       [SHLWAPI.364]
1832  *
1833  * Wrapper for lstrcpynA with src and dst swapped.
1834  */
1835 DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
1836 {
1837   lstrcpynA(dst, src, n);
1838   return TRUE;
1839 }
1840
1841 /*************************************************************************
1842  *      @       [SHLWAPI.370]
1843  *
1844  * Late bound call to shell32.ExtractIconW
1845  */
1846 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
1847                          UINT nIconIndex)
1848 {
1849   static HICON (WINAPI *pfnFunc)(HINSTANCE, LPCWSTR, UINT) = NULL;
1850
1851   GET_FUNC(shell32, "ExtractIconW", (HICON)0);
1852   return pfnFunc(hInstance, lpszExeFileName, nIconIndex);
1853 }
1854
1855 /*************************************************************************
1856  *      @       [SHLWAPI.376]
1857  */
1858 LANGID 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  */
1888 DWORD 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
1907  */
1908 DWORD WINAPI SHLWAPI_378 (
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]
1928  *
1929  * Late bound call to comdlg32.GetSaveFileNameW
1930  */
1931 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
1932 {
1933   static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
1934
1935   GET_FUNC(comdlg32, "GetSaveFileNameW", FALSE);
1936   return pfnFunc(ofn);
1937 }
1938
1939 /*************************************************************************
1940  *      @       [SHLWAPI.390]
1941  *
1942  * Late bound call to mpr.WNetRestoreConnectionW
1943  */
1944 DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
1945 {
1946   /* FIXME: Correct args */
1947   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID) = NULL;
1948
1949   GET_FUNC(mpr, "WNetRestoreConnectionW", 0);
1950   return pfnFunc(arg1, arg2);
1951 }
1952
1953 /*************************************************************************
1954  *      @       [SHLWAPI.391]
1955  *
1956  * Late bound call to mpr.WNetGetLastErrorW
1957  */
1958 DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
1959                          LPVOID arg5)
1960 {
1961   /* FIXME: Correct args */
1962   static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
1963
1964   GET_FUNC(mpr, "WNetGetLastErrorW", 0);
1965   return pfnFunc(arg1, arg2, arg3, arg4, arg5);
1966 }
1967
1968 /*************************************************************************
1969  *      @       [SHLWAPI.401]
1970  *
1971  * Late bound call to comdlg32.PageSetupDlgW
1972  */
1973 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
1974 {
1975   static BOOL (WINAPI *pfnFunc)(LPPAGESETUPDLGW) = NULL;
1976
1977   GET_FUNC(comdlg32, "PageSetupDlgW", FALSE);
1978   return pfnFunc(pagedlg);
1979 }
1980
1981 /*************************************************************************
1982  *      @       [SHLWAPI.402]
1983  *
1984  * Late bound call to comdlg32.PrintDlgW
1985  */
1986 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
1987 {
1988   static BOOL (WINAPI *pfnFunc)(LPPRINTDLGW) = NULL;
1989
1990   GET_FUNC(comdlg32, "PrintDlgW", FALSE);
1991   return pfnFunc(printdlg);
1992 }
1993
1994 /*************************************************************************
1995  *      @       [SHLWAPI.403]
1996  *
1997  * Late bound call to comdlg32.GetOpenFileNameW
1998  */
1999 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
2000 {
2001   static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
2002
2003   GET_FUNC(comdlg32, "GetOpenFileNameW", FALSE);
2004   return pfnFunc(ofn);
2005 }
2006
2007 /* INTERNAL: Map from HLS color space to RGB */
2008 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
2009 {
2010   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
2011
2012   if (wHue > 160)
2013     return wMid1;
2014   else if (wHue > 120)
2015     wHue = 160 - wHue;
2016   else if (wHue > 40)
2017     return wMid2;
2018
2019   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
2020 }
2021
2022 /* Convert to RGB and scale into RGB range (0..255) */
2023 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
2024
2025 /*************************************************************************
2026  *      ColorHLSToRGB   [SHLWAPI.404]
2027  *
2028  * Convert from HLS color space into an RGB COLORREF.
2029  *
2030  * NOTES
2031  * Input HLS values are constrained to the range (0..240).
2032  */
2033 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
2034 {
2035   WORD wRed;
2036
2037   if (wSaturation)
2038   {
2039     WORD wGreen, wBlue, wMid1, wMid2;
2040
2041     if (wLuminosity > 120)
2042       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
2043     else
2044       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
2045
2046     wMid1 = wLuminosity * 2 - wMid2;
2047
2048     wRed   = GET_RGB(wHue + 80);
2049     wGreen = GET_RGB(wHue);
2050     wBlue  = GET_RGB(wHue - 80);
2051
2052     return RGB(wRed, wGreen, wBlue);
2053   }
2054
2055   wRed = wLuminosity * 255 / 240;
2056   return RGB(wRed, wRed, wRed);
2057 }
2058
2059 /*************************************************************************
2060  *      @       [SHLWAPI.413]
2061  *
2062  * Function unknown seems to always to return 0
2063  */
2064 DWORD WINAPI SHLWAPI_413 (DWORD x)
2065 {
2066         FIXME("(0x%08lx)stub\n", x);
2067         return 0;
2068 }
2069
2070 /*************************************************************************
2071  *      @       [SHLWAPI.431]
2072  */
2073 DWORD WINAPI SHLWAPI_431 (DWORD x)
2074 {
2075         FIXME("(0x%08lx)stub\n", x);
2076         return 0xabba1247;
2077 }
2078
2079 /*************************************************************************
2080  *      @       [SHLWAPI.437]
2081  *
2082  * NOTES
2083  *  In the real shlwapi, One time initialisation calls GetVersionEx and reads
2084  *  the registry to determine what O/S & Service Pack level is running, and
2085  *  therefore which functions are available. Currently we always run as NT,
2086  *  since this means that we don't need extra code to emulate Unicode calls,
2087  *  they are forwarded directly to the appropriate API call instead.
2088  *  Since the flags for whether to call or emulate Unicode are internal to
2089  *  the dll, this function does not need a full implementation.
2090  */
2091 DWORD WINAPI SHLWAPI_437 (DWORD functionToCall)
2092 {
2093         FIXME("(0x%08lx)stub\n", functionToCall);
2094         return /* 0xabba1247 */ 0;
2095 }
2096
2097 /*************************************************************************
2098  *      ColorRGBToHLS   [SHLWAPI.445]
2099  *
2100  * Convert from RGB COLORREF into the HLS color space.
2101  *
2102  * NOTES
2103  * Input HLS values are constrained to the range (0..240).
2104  */
2105 VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue, 
2106                           LPWORD wLuminance, LPWORD pwSaturation)
2107 {
2108     FIXME("stub\n");
2109     return;
2110 }
2111
2112 /*************************************************************************
2113  *      SHCreateShellPalette    [SHLWAPI.@]
2114  */
2115 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
2116 {
2117         FIXME("stub\n");
2118         return CreateHalftonePalette(hdc);
2119 }
2120
2121 /*************************************************************************
2122  *      SHGetInverseCMAP (SHLWAPI.@)
2123  */
2124 DWORD WINAPI SHGetInverseCMAP (LPVOID x, DWORD why)
2125 {
2126         FIXME("(%p, %#lx)stub\n", x, why);
2127         return 0;
2128 }
2129
2130 /*************************************************************************
2131  *      SHIsLowMemoryMachine    [SHLWAPI.@]
2132  */
2133 DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
2134 {
2135         FIXME("0x%08lx\n", x);
2136         return 0;
2137 }
2138
2139 /*************************************************************************
2140  *      GetMenuPosFromID        [SHLWAPI.@]
2141  */
2142 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
2143 {
2144  MENUITEMINFOA mi;
2145  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
2146
2147  while (nIter < nCount)
2148  {
2149    mi.wID = 0;
2150    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
2151      return nIter;
2152    nIter++;
2153  }
2154  return -1;
2155 }
2156
2157 /*************************************************************************
2158  *      _SHGetInstanceExplorer@4        [SHLWAPI.@]
2159  *
2160  * Late bound call to shell32.SHGetInstanceExplorer.
2161  */
2162 HRESULT WINAPI _SHGetInstanceExplorer (LPUNKNOWN *lpUnknown)
2163 {
2164   static HRESULT (WINAPI *pfnFunc)(LPUNKNOWN *) = NULL;
2165
2166   GET_FUNC(shell32, "SHGetInstanceExplorer", E_FAIL);
2167   return pfnFunc(lpUnknown);
2168 }