We can't cache the unscaled font's hfont, since the mapping mode may
[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  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "docobj.h"
30 #include "shlguid.h"
31 #include "windef.h"
32 #include "winnls.h"
33 #include "winbase.h"
34 #include "ddeml.h"
35 #include "shlobj.h"
36 #include "shellapi.h"
37 #include "commdlg.h"
38 #include "wine/unicode.h"
39 #include "wine/obj_base.h"
40 #include "wine/obj_inplace.h"
41 #include "wine/obj_serviceprovider.h"
42 #include "wine/obj_control.h"
43 #include "wine/obj_connection.h"
44 #include "wine/obj_property.h"
45 #include "wingdi.h"
46 #include "winreg.h"
47 #include "winuser.h"
48 #include "wine/debug.h"
49 #include "shlwapi.h"
50
51
52 WINE_DEFAULT_DEBUG_CHANNEL(shell);
53
54 /* Get a function pointer from a DLL handle */
55 #define GET_FUNC(func, module, name, fail) \
56   do { \
57     if (!func) { \
58       if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
59       if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
60     } \
61   } while (0)
62
63 /* DLL handles for late bound calls */
64 extern HINSTANCE shlwapi_hInstance;
65 extern HMODULE SHLWAPI_hshell32;
66 extern HMODULE SHLWAPI_hwinmm;
67 extern HMODULE SHLWAPI_hcomdlg32;
68 extern HMODULE SHLWAPI_hcomctl32;
69 extern HMODULE SHLWAPI_hmpr;
70 extern HMODULE SHLWAPI_hmlang;
71 extern HMODULE SHLWAPI_hversion;
72
73 extern DWORD SHLWAPI_ThreadRef_index;
74
75 typedef HANDLE HSHARED; /* Shared memory */
76
77 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
78 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
79 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
80 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
81
82 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
83 static LPITEMIDLIST (WINAPI *pSHBrowseForFolderW)(LPBROWSEINFOW);
84 static HRESULT (WINAPI *pConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
85 static BOOL    (WINAPI *pPlaySoundW)(LPCWSTR, HMODULE, DWORD);
86 static DWORD   (WINAPI *pSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
87 static UINT    (WINAPI *pDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
88 static BOOL    (WINAPI *pSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
89 static BOOL    (WINAPI *pShellExecuteExW)(LPSHELLEXECUTEINFOW);
90 static HICON   (WINAPI *pSHFileOperationW)(LPSHFILEOPSTRUCTW);
91 static HICON   (WINAPI *pExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
92 static BOOL    (WINAPI *pSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
93 static DWORD   (WINAPI *pSHDefExtractIconW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
94 static HICON   (WINAPI *pExtractIconW)(HINSTANCE, LPCWSTR, UINT);
95 static BOOL    (WINAPI *pGetSaveFileNameW)(LPOPENFILENAMEW);
96 static DWORD   (WINAPI *pWNetRestoreConnectionW)(LPVOID, LPVOID); /* FIXME: Correct args */
97 static DWORD   (WINAPI *pWNetGetLastErrorW)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID); /* FIXME: Correct args */
98 static BOOL    (WINAPI *pPageSetupDlgW)(LPPAGESETUPDLGW);
99 static BOOL    (WINAPI *pPrintDlgW)(LPPRINTDLGW);
100 static BOOL    (WINAPI *pGetOpenFileNameW)(LPOPENFILENAMEW);
101 static DWORD   (WINAPI *pGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
102 static BOOL    (WINAPI *pGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
103 static WORD    (WINAPI *pVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
104 static BOOL    (WINAPI *pCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
105 static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO*);
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 wrapper
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_DupSharedHandle
119  *
120  * Internal implemetation of SHLWAPI_11.
121  */
122 static
123 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
124                                        DWORD dwSrcProcId, DWORD dwAccess,
125                                        DWORD dwOptions)
126 {
127   HANDLE hDst, hSrc;
128   DWORD dwMyProcId = GetCurrentProcessId();
129   HSHARED hRet = (HSHARED)NULL;
130
131   TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
132         dwAccess, dwOptions);
133
134   /* Get dest process handle */
135   if (dwDstProcId == dwMyProcId)
136     hDst = GetCurrentProcess();
137   else
138     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
139
140   if (hDst)
141   {
142     /* Get src process handle */
143     if (dwSrcProcId == dwMyProcId)
144       hSrc = GetCurrentProcess();
145     else
146       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
147
148     if (hSrc)
149     {
150       /* Make handle available to dest process */
151       if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
152                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
153         hRet = (HSHARED)NULL;
154
155       if (dwSrcProcId != dwMyProcId)
156         CloseHandle(hSrc);
157     }
158
159     if (dwDstProcId != dwMyProcId)
160       CloseHandle(hDst);
161   }
162
163   TRACE("Returning handle %p\n", (PVOID)hRet);
164   return hRet;
165 }
166
167 /*************************************************************************
168  * @  [SHLWAPI.7]
169  *
170  * Create a block of sharable memory and initialise it with data.
171  *
172  * PARAMS
173  * dwProcId [I] ID of process owning data
174  * lpvData  [I] Pointer to data to write
175  * dwSize   [I] Size of data
176  *
177  * RETURNS
178  * Success: A shared memory handle
179  * Failure: NULL
180  *
181  * NOTES
182  * Ordinals 7-11 provide a set of calls to create shared memory between a
183  * group of processes. The shared memory is treated opaquely in that its size
184  * is not exposed to clients who map it. This is accomplished by storing
185  * the size of the map as the first DWORD of mapped data, and then offsetting
186  * the view pointer returned by this size.
187  *
188  * SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
189  * SHLWAPI_8/SHLWAPI_9  - Get/Release a pointer to the shared data
190  * SHLWAPI_11           - Helper function; Duplicate cross-process handles
191    */
192 HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
193 {
194   HANDLE hMap;
195   LPVOID pMapped;
196   HSHARED hRet = (HSHARED)NULL;
197
198   TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
199
200   /* Create file mapping of the correct length */
201   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
202                             dwSize + sizeof(dwSize), NULL);
203   if (!hMap)
204     return hRet;
205
206   /* Get a view in our process address space */
207   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
208
209   if (pMapped)
210   {
211     /* Write size of data, followed by the data, to the view */
212     *((DWORD*)pMapped) = dwSize;
213     if (dwSize)
214       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
215
216     /* Release view. All further views mapped will be opaque */
217     UnmapViewOfFile(pMapped);
218     hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
219                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
220                                    DUPLICATE_SAME_ACCESS);
221   }
222
223   CloseHandle(hMap);
224   return hRet;
225 }
226
227 /*************************************************************************
228  * @ [SHLWAPI.8]
229  *
230  * Get a pointer to a block of shared memory from a shared memory handle.
231  *
232  * PARAMS
233  * hShared  [I] Shared memory handle
234  * dwProcId [I] ID of process owning hShared
235  *
236  * RETURNS
237  * Success: A pointer to the shared memory
238  * Failure: NULL
239  *
240  * NOTES
241  * See SHLWAPI_7.
242    */
243 PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
244   {
245   HSHARED hDup;
246   LPVOID pMapped;
247
248   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
249
250   /* Get handle to shared memory for current process */
251   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
252                                  FILE_MAP_ALL_ACCESS, 0);
253   /* Get View */
254   pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
255   CloseHandle(hDup);
256
257   if (pMapped)
258     return (char *) pMapped + sizeof(DWORD); /* Hide size */
259   return NULL;
260 }
261
262 /*************************************************************************
263  * @ [SHLWAPI.9]
264  *
265  * Release a pointer to a block of shared memory.
266  *
267  * PARAMS
268  * lpView [I] Shared memory pointer
269  *
270  * RETURNS
271  * Success: TRUE
272  * Failure: FALSE
273  *
274  * NOTES
275  * See SHLWAPI_7.
276  */
277 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
278 {
279   TRACE("(%p)\n", lpView);
280   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
281 }
282
283 /*************************************************************************
284  * @ [SHLWAPI.10]
285  *
286  * Destroy a block of sharable memory.
287  *
288  * PARAMS
289  * hShared  [I] Shared memory handle
290  * dwProcId [I] ID of process owning hShared
291  *
292  * RETURNS
293  * Success: TRUE
294  * Failure: FALSE
295  *
296  * NOTES
297  * See SHLWAPI_7.
298  */
299 BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
300 {
301   HSHARED hClose;
302
303   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
304
305   /* Get a copy of the handle for our process, closing the source handle */
306   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
307                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
308   /* Close local copy */
309   return CloseHandle((HANDLE)hClose);
310 }
311
312 /*************************************************************************
313  * @   [SHLWAPI.11]
314  *
315  * Copy a sharable memory handle from one process to another.
316  *
317  * PARAMS
318  * hShared     [I] Shared memory handle to duplicate
319  * dwDstProcId [I] ID of the process wanting the duplicated handle
320  * dwSrcProcId [I] ID of the process owning hShared
321  * dwAccess    [I] Desired DuplicateHandle access
322  * dwOptions   [I] Desired DuplicateHandle options
323  *
324  * RETURNS
325  * Success: A handle suitable for use by the dwDstProcId process.
326  * Failure: A NULL handle.
327  *
328  * NOTES
329  * See SHLWAPI_7.
330  */
331 HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
332                           DWORD dwAccess, DWORD dwOptions)
333 {
334   HSHARED hRet;
335
336   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
337                                  dwAccess, dwOptions);
338   return hRet;
339 }
340
341 /*************************************************************************
342  *      @       [SHLWAPI.13]
343  *
344  * Create and register a clipboard enumerator for a web browser.
345  *
346  * PARAMS
347  *  lpBC      [I] Binding context
348  *  lpUnknown [I] An object exposing the IWebBrowserApp interface
349  *
350  * RETURNS
351  *  Success: S_OK.
352  *  Failure: An HRESULT error code.
353  *
354  * NOTES
355  *  The enumerator is stored as a property of the web browser. If it does not
356  *  yet exist, it is created and set before being registered.
357  *
358  * BUGS
359  *  Unimplemented.
360  */
361 HRESULT WINAPI SHLWAPI_13(LPBC lpBC, IUnknown *lpUnknown)
362 {
363         FIXME("(%p,%p) stub\n", lpBC, lpUnknown);
364         return 1;
365 #if 0
366         /* pseudo code extracted from relay trace */
367         RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Accepted Documents", &newkey);
368         ret = 0;
369         i = 0;
370         size = 0;
371         while(!ret) {
372             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
373             size += ???;
374             i++;
375         }
376         b1 = LocalAlloc(0x40, size);
377         ret = 0;
378         i = 0;
379         while(!ret) {
380             ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
381             RegisterClipBoardFormatA(a4);
382             i++;
383         }
384         hmod1 = GetModuleHandleA("URLMON.DLL");
385         proc = GetProcAddress(hmod1, "CreateFormatEnumerator");
386         HeapAlloc(??, 0, 0x14);
387         HeapAlloc(??, 0, 0x50);
388         LocalAlloc(0x40, 0x78);
389         /* FIXME: bad string below */
390         lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
391         StrCpyW(a6,  L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
392
393         GetTickCount();
394         IsBadReadPtr(c1 = 0x403fd210,4);
395         InterlockedIncrement(c1+4);
396         LocalFree(b1);
397         RegCloseKey(newkey);
398         IsBadReadPtr(c1 = 0x403fd210,4);
399         InterlockedIncrement(c1+4);
400
401         HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
402         HeapAlloc(40350000,00000000,00000050) retval=403feb44;
403         hmod1 = GetModuleHandleA("URLMON.DLL");
404         proc = GetProcAddress(hmod1, "RegisterFormatEnumerator");
405         /* 0x1a40c88c is in URLMON.DLL just before above proc
406          * content is L"_EnumFORMATETC_"
407          * label is d1
408          */
409         IsBadReadPtr(d1 = 0x1a40c88c,00000002);
410         lstrlenW(d1);
411         lstrlenW(d1);
412         HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
413         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
414         InterlockedIncrement(d2+4);
415         IsBadReadPtr(d2 = 0x403fd0a8,00000004);
416         InterlockedDecrement(d2+4);
417         IsBadReadPtr(c1,00000004);
418         InterlockedDecrement(c1+4);
419         IsBadReadPtr(c1,00000004);
420         InterlockedDecrement(c1+4);
421
422 #endif
423 }
424
425 /*************************************************************************
426  *      @       [SHLWAPI.14]
427  *
428  * Get Explorers "AcceptLanguage" setting.
429  *
430  * PARAMS
431  *  langbuf [O] Destination for language string
432  *  buflen  [I] Length of langbuf
433  *
434  * RETURNS
435  *  Success: S_OK.   langbuf is set to the language string found.
436  *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
437  *           does not contain the setting.
438  */
439 HRESULT WINAPI SHLWAPI_14 (
440         LPSTR langbuf,
441         LPDWORD buflen)
442 {
443         CHAR *mystr;
444         DWORD mystrlen, mytype;
445         HKEY mykey;
446         LCID mylcid;
447
448         mystrlen = (*buflen > 6) ? *buflen : 6;
449         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
450                                  HEAP_ZERO_MEMORY, mystrlen);
451         RegOpenKeyA(HKEY_CURRENT_USER,
452                     "Software\\Microsoft\\Internet Explorer\\International",
453                     &mykey);
454         if (RegQueryValueExA(mykey, "AcceptLanguage",
455                               0, &mytype, mystr, &mystrlen)) {
456             /* Did not find value */
457             mylcid = GetUserDefaultLCID();
458             /* somehow the mylcid translates into "en-us"
459              *  this is similar to "LOCALE_SABBREVLANGNAME"
460              *  which could be gotten via GetLocaleInfo.
461              *  The only problem is LOCALE_SABBREVLANGUAGE" is
462              *  a 3 char string (first 2 are country code and third is
463              *  letter for "sublanguage", which does not come close to
464              *  "en-us"
465              */
466             lstrcpyA(mystr, "en-us");
467             mystrlen = lstrlenA(mystr);
468         }
469         else {
470             /* handle returned string */
471             FIXME("missing code\n");
472         }
473         if (mystrlen > *buflen)
474             lstrcpynA(langbuf, mystr, *buflen);
475         else {
476             lstrcpyA(langbuf, mystr);
477             *buflen = lstrlenA(langbuf);
478         }
479         RegCloseKey(mykey);
480         HeapFree(GetProcessHeap(), 0, mystr);
481         TRACE("language is %s\n", debugstr_a(langbuf));
482         return 0;
483 }
484
485 /*************************************************************************
486  *      @       [SHLWAPI.15]
487  *
488  * Unicode version of SHLWAPI_14.
489  */
490 HRESULT WINAPI SHLWAPI_15 (
491         LPWSTR langbuf,
492         LPDWORD buflen)
493 {
494         CHAR *mystr;
495         DWORD mystrlen, mytype;
496         HKEY mykey;
497         LCID mylcid;
498
499         mystrlen = (*buflen > 6) ? *buflen : 6;
500         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
501                                  HEAP_ZERO_MEMORY, mystrlen);
502         RegOpenKeyA(HKEY_CURRENT_USER,
503                     "Software\\Microsoft\\Internet Explorer\\International",
504                     &mykey);
505         if (RegQueryValueExA(mykey, "AcceptLanguage",
506                               0, &mytype, mystr, &mystrlen)) {
507             /* Did not find value */
508             mylcid = GetUserDefaultLCID();
509             /* somehow the mylcid translates into "en-us"
510              *  this is similar to "LOCALE_SABBREVLANGNAME"
511              *  which could be gotten via GetLocaleInfo.
512              *  The only problem is LOCALE_SABBREVLANGUAGE" is
513              *  a 3 char string (first 2 are country code and third is
514              *  letter for "sublanguage", which does not come close to
515              *  "en-us"
516              */
517             lstrcpyA(mystr, "en-us");
518             mystrlen = lstrlenA(mystr);
519         }
520         else {
521             /* handle returned string */
522             FIXME("missing code\n");
523         }
524         RegCloseKey(mykey);
525         *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
526         HeapFree(GetProcessHeap(), 0, mystr);
527         TRACE("language is %s\n", debugstr_w(langbuf));
528         return 0;
529 }
530
531 /*************************************************************************
532  *      @       [SHLWAPI.23]
533  *
534  * NOTES
535  *      converts a guid to a string
536  *      returns strlen(str)
537  */
538 DWORD WINAPI SHLWAPI_23 (
539         REFGUID guid,   /* [in]  clsid */
540         LPSTR str,      /* [out] buffer */
541         INT cmax)       /* [in]  size of buffer */
542 {
543         char xguid[40];
544
545         sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
546                  guid->Data1, guid->Data2, guid->Data3,
547                  guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
548                  guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
549         TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
550         if (strlen(xguid)>=cmax) return 0;
551         strcpy(str,xguid);
552         return strlen(xguid) + 1;
553 }
554
555 /*************************************************************************
556  *      @       [SHLWAPI.24]
557  *
558  * NOTES
559  *      converts a guid to a string
560  *      returns strlen(str)
561  */
562 DWORD WINAPI SHLWAPI_24 (
563         REFGUID guid,   /* [in]  clsid */
564         LPWSTR str,     /* [out] buffer */
565         INT cmax)       /* [in]  size of buffer */
566 {
567     char xguid[40];
568
569     sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
570              guid->Data1, guid->Data2, guid->Data3,
571              guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
572              guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
573     return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
574 }
575
576 /*************************************************************************
577  *      @       [SHLWAPI.25]
578  *
579  * Seems to be iswalpha
580  */
581 BOOL WINAPI SHLWAPI_25(WCHAR wc)
582 {
583     return (get_char_typeW(wc) & C1_ALPHA) != 0;
584 }
585
586 /*************************************************************************
587  *      @       [SHLWAPI.26]
588  *
589  * Seems to be iswupper
590  */
591 BOOL WINAPI SHLWAPI_26(WCHAR wc)
592 {
593     return (get_char_typeW(wc) & C1_UPPER) != 0;
594 }
595
596 /*************************************************************************
597  *      @       [SHLWAPI.27]
598  *
599  * Seems to be iswlower
600  */
601 BOOL WINAPI SHLWAPI_27(WCHAR wc)
602 {
603     return (get_char_typeW(wc) & C1_LOWER) != 0;
604 }
605
606 /*************************************************************************
607  *      @       [SHLWAPI.28]
608  *
609  * Seems to be iswalnum
610  */
611 BOOL WINAPI SHLWAPI_28(WCHAR wc)
612 {
613     return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
614 }
615
616 /*************************************************************************
617  *      @       [SHLWAPI.29]
618  *
619  * Seems to be iswspace
620  */
621 BOOL WINAPI SHLWAPI_29(WCHAR wc)
622 {
623     return (get_char_typeW(wc) & C1_SPACE) != 0;
624 }
625
626 /*************************************************************************
627  *      @       [SHLWAPI.30]
628  *
629  * Seems to be iswblank
630  */
631 BOOL WINAPI SHLWAPI_30(WCHAR wc)
632 {
633     return (get_char_typeW(wc) & C1_BLANK) != 0;
634 }
635
636 /*************************************************************************
637  *      @       [SHLWAPI.31]
638  *
639  * Seems to be iswpunct
640  */
641 BOOL WINAPI SHLWAPI_31(WCHAR wc)
642 {
643     return (get_char_typeW(wc) & C1_PUNCT) != 0;
644 }
645
646 /*************************************************************************
647  *      @       [SHLWAPI.32]
648  *
649  * Seems to be iswcntrl
650  */
651 BOOL WINAPI SHLWAPI_32(WCHAR wc)
652 {
653     return (get_char_typeW(wc) & C1_CNTRL) != 0;
654 }
655
656 /*************************************************************************
657  *      @       [SHLWAPI.33]
658  *
659  * Seems to be iswdigit
660  */
661 BOOL WINAPI SHLWAPI_33(WCHAR wc)
662 {
663     return (get_char_typeW(wc) & C1_DIGIT) != 0;
664 }
665
666 /*************************************************************************
667  *      @       [SHLWAPI.34]
668  *
669  * Seems to be iswxdigit
670  */
671 BOOL WINAPI SHLWAPI_34(WCHAR wc)
672 {
673     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
674 }
675
676 /*************************************************************************
677  *      @       [SHLWAPI.35]
678  *
679  */
680 BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
681 {
682     FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
683     return TRUE;
684 }
685
686 /*************************************************************************
687  *      @       [SHLWAPI.36]
688  *
689  * Insert a bitmap menu item at the bottom of a menu.
690  *
691  * PARAMS
692  *  hMenu [I] Menu to insert into
693  *  flags [I] Flags for insertion
694  *  id    [I] Menu ID of the item
695  *  str   [I] Menu text for the item
696  *
697  * RETURNS
698  *  Success: TRUE,  the item is inserted into the menu
699  *  Failure: FALSE, if any parameter is invalid
700  */
701 BOOL WINAPI SHLWAPI_36(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
702 {
703     TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
704     return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
705 }
706
707 /*************************************************************************
708  *      @       [SHLWAPI.74]
709  *
710  * Get the text from a given dialog item.
711  *
712  * PARAMS
713  *  hWnd     [I] Handle of dialog
714  *  nItem    [I] Index of item
715  *  lpsDest  [O] Buffer for receiving window text
716  *  nDestLen [I] Length of buffer.
717  *
718  * RETURNS
719  *  Success: The length of the returned text.
720  *  Failure: 0.
721  */
722 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
723 {
724   HWND hItem = GetDlgItem(hWnd, nItem);
725
726   if (hItem)
727     return GetWindowTextW(hItem, lpsDest, nDestLen);
728   if (nDestLen)
729     *lpsDest = (WCHAR)'\0';
730   return 0;
731 }
732
733 /*************************************************************************
734  *      @   [SHLWAPI.138]
735  *
736  * Set the text of a given dialog item.
737  *
738  * PARAMS
739  *  hWnd     [I] Handle of dialog
740  *  iItem    [I] Index of item
741  *  lpszText [O] Text to set
742  *
743  * RETURNS
744  *  Success: TRUE.  The text of the dialog is set to lpszText.
745  *  Failure: FALSE, Otherwise.
746  */
747 BOOL WINAPI SHLWAPI_138(HWND hWnd, INT iItem, LPCWSTR lpszText)
748 {
749     HWND hWndItem = GetDlgItem(hWnd, iItem);
750     if (hWndItem)
751         return SetWindowTextW(hWndItem, lpszText);
752     return FALSE;
753 }
754
755 /*************************************************************************
756  *      @       [SHLWAPI.151]
757  * Function:  Compare two ASCII strings for "len" bytes.
758  * Returns:   *str1-*str2  (case sensitive)
759  */
760 DWORD WINAPI SHLWAPI_151(LPCSTR str1, LPCSTR str2, INT len)
761 {
762     return strncmp( str1, str2, len );
763 }
764
765 /*************************************************************************
766  *      @       [SHLWAPI.152]
767  *
768  * Function:  Compare two WIDE strings for "len" bytes.
769  * Returns:   *str1-*str2  (case sensitive)
770  */
771 DWORD WINAPI SHLWAPI_152(LPCWSTR str1, LPCWSTR str2, INT len)
772 {
773     return strncmpW( str1, str2, len );
774 }
775
776 /*************************************************************************
777  *      @       [SHLWAPI.153]
778  * Function:  Compare two ASCII strings for "len" bytes via caseless compare.
779  * Returns:   *str1-*str2  (case insensitive)
780  */
781 DWORD WINAPI SHLWAPI_153(LPCSTR str1, LPCSTR str2, DWORD len)
782 {
783     return strncasecmp( str1, str2, len );
784 }
785
786 /*************************************************************************
787  *      @       [SHLWAPI.154]
788  *
789  * Function:  Compare two WIDE strings for "len" bytes via caseless compare.
790  * Returns:   *str1-*str2  (case insensitive)
791  */
792 DWORD WINAPI SHLWAPI_154(LPCWSTR str1, LPCWSTR str2, DWORD len)
793 {
794     return strncmpiW( str1, str2, len );
795 }
796
797 /*************************************************************************
798  *      @       [SHLWAPI.155]
799  *
800  *      Case sensitive string compare (ASCII). Does not SetLastError().
801  */
802 DWORD WINAPI SHLWAPI_155(LPCSTR str1, LPCSTR str2)
803 {
804     return strcmp(str1, str2);
805 }
806
807 /*************************************************************************
808  *      @       [SHLWAPI.156]
809  *
810  *      Case sensitive string compare. Does not SetLastError().
811  */
812 DWORD WINAPI SHLWAPI_156(LPCWSTR str1, LPCWSTR str2)
813 {
814     return strcmpW( str1, str2 );
815 }
816
817 /*************************************************************************
818  *      @       [SHLWAPI.157]
819  *
820  *      Case insensitive string compare (ASCII). Does not SetLastError().
821  */
822 DWORD WINAPI SHLWAPI_157(LPCSTR str1, LPCSTR str2)
823 {
824     return strcasecmp(str1, str2);
825 }
826 /*************************************************************************
827  *      @       [SHLWAPI.158]
828  *
829  *      Case insensitive string compare. Does not SetLastError(). ??
830  */
831 DWORD WINAPI SHLWAPI_158 (LPCWSTR str1, LPCWSTR str2)
832 {
833     return strcmpiW( str1, str2 );
834 }
835
836 /*************************************************************************
837  *      @       [SHLWAPI.162]
838  *
839  * Remove a hanging lead byte from the end of a string, if present.
840  *
841  * PARAMS
842  *  lpStr [I] String to check for a hanging lead byte
843  *  size  [I] Length of lpszStr
844  *
845  * RETURNS
846  *  Success: The new size of the string. Any hanging lead bytes are removed.
847  *  Failure: 0, if any parameters are invalid.
848  */
849 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
850 {
851   if (lpStr && size)
852   {
853     LPSTR lastByte = lpStr + size - 1;
854
855     while(lpStr < lastByte)
856       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
857
858     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
859     {
860       *lpStr = '\0';
861       size--;
862     }
863     return size;
864   }
865   return 0;
866 }
867
868 /*************************************************************************
869  *      @       [SHLWAPI.163]
870  *
871  * Call IOleCommandTarget::QueryStatus() on an object.
872  *
873  * PARAMS
874  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
875  *  pguidCmdGroup [I] GUID for the command group
876  *  cCmds         [I]
877  *  prgCmds       [O] Commands
878  *  pCmdText      [O] Command text
879  *
880  * RETURNS
881  *  Success: S_OK.
882  *  Failure: E_FAIL, if lpUnknown is NULL.
883  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
884  *           Otherwise, an error code from IOleCommandTarget::QueryStatus().
885  */
886 HRESULT WINAPI SHLWAPI_163(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
887                            ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
888 {
889   HRESULT hRet = E_FAIL;
890
891   TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
892
893   if (lpUnknown)
894   {
895     IOleCommandTarget* lpOle;
896
897     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
898                                    (void**)&lpOle);
899
900     if (SUCCEEDED(hRet) && lpOle)
901     {
902       hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
903                                            prgCmds, pCmdText);
904       IOleCommandTarget_Release(lpOle);
905     }
906   }
907   return hRet;
908 }
909
910 /*************************************************************************
911  *      @               [SHLWAPI.164]
912  *
913  * Call IOleCommandTarget::Exec() on an object.
914  *
915  * PARAMS
916  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
917  *  pguidCmdGroup [I] GUID for the command group
918  *
919  * RETURNS
920  *  Success: S_OK.
921  *  Failure: E_FAIL, if lpUnknown is NULL.
922  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
923  *           Otherwise, an error code from IOleCommandTarget::Exec().
924  */
925 HRESULT WINAPI SHLWAPI_164(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
926                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
927                            VARIANT* pvaOut)
928 {
929   HRESULT hRet = E_FAIL;
930
931   TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
932         nCmdexecopt, pvaIn, pvaOut);
933
934   if (lpUnknown)
935   {
936     IOleCommandTarget* lpOle;
937
938     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
939                                    (void**)&lpOle);
940     if (SUCCEEDED(hRet) && lpOle)
941     {
942       hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
943                                     nCmdexecopt, pvaIn, pvaOut);
944       IOleCommandTarget_Release(lpOle);
945     }
946   }
947   return hRet;
948 }
949
950 /*************************************************************************
951  *      @       [SHLWAPI.165]
952  *
953  * Retrieve, modify, and re-set a value from a window.
954  *
955  * PARAMS
956  *  hWnd   [I] Windows to get value from
957  *  offset [I] Offset of value
958  *  wMask  [I] Mask for uiFlags
959  *  wFlags [I] Bits to set in window value
960  *
961  * RETURNS
962  *  The new value as it was set, or 0 if any parameter is invalid.
963  *
964  * NOTES
965  *  Any bits set in uiMask are cleared from the value, then any bits set in
966  *  uiFlags are set in the value.
967  */
968 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
969 {
970   LONG ret = GetWindowLongA(hwnd, offset);
971   UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
972
973   if (newFlags != ret)
974     ret = SetWindowLongA(hwnd, offset, newFlags);
975   return ret;
976 }
977
978 /*************************************************************************
979  *      @       [SHLWAPI.167]
980  *
981  * Change a windows parent.
982  *
983  * PARAMS
984  *  hWnd       [I] Window to change parent of
985  *  hWndParent [I] New parent window
986  *
987  * RETURNS
988  *  Nothing.
989  *
990  * NOTES
991  *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
992  */
993 DWORD WINAPI SHLWAPI_167(HWND hWnd, HWND hWndParent)
994 {
995         FIXME("%p,%p\n", hWnd, hWndParent);
996         return 0;
997 }
998
999 /*************************************************************************
1000  *      @       [SHLWAPI.168]
1001  *
1002  * Locate and advise a connection point in an IConnectionPointContainer.
1003  *
1004  * PARAMS
1005  *  lpUnkSink   [I] Sink for the connection point advise call
1006  *  riid        [I] REFIID of connection point to advise
1007  *  bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1008  *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface
1009  *  lpCookie    [O] Pointer to connection point cookie
1010  *  lppCP       [O] Destination for the IConnectionPoint found
1011  *
1012  * RETURNS
1013  *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1014  *           that was advised. The caller is responsable for releasing it.
1015  *  Failure: E_FAIL, if any arguments are invalid.
1016  *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1017  *           Or an HRESULT error code if any call fails.
1018  */
1019 HRESULT WINAPI SHLWAPI_168(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1020                            IUnknown* lpUnknown, LPDWORD lpCookie,
1021                            IConnectionPoint **lppCP)
1022 {
1023   HRESULT hRet;
1024   IConnectionPointContainer* lpContainer;
1025   IConnectionPoint *lpCP;
1026
1027   if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1028     return E_FAIL;
1029
1030   if(lppCP)
1031     *lppCP = NULL;
1032
1033   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1034                                  (void**)&lpContainer);
1035   if (SUCCEEDED(hRet))
1036   {
1037     hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1038
1039     if (SUCCEEDED(hRet))
1040     {
1041       if(!bAdviseOnly)
1042         hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1043       hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1044
1045       if (FAILED(hRet))
1046         *lpCookie = 0;
1047
1048       if (lppCP && SUCCEEDED(hRet))
1049         *lppCP = lpCP; /* Caller keeps the interface */
1050       else
1051         IConnectionPoint_Release(lpCP); /* Release it */
1052     }
1053
1054     IUnknown_Release(lpContainer);
1055   }
1056   return hRet;
1057 }
1058
1059 /*************************************************************************
1060  *      @       [SHLWAPI.169]
1061  *
1062  *
1063  * Release an interface.
1064  *
1065  * PARAMS
1066  *  lpUnknown [I] Object to release
1067  *
1068  * RETURNS
1069  *  Nothing.
1070  */
1071 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1072 {
1073         IUnknown *temp;
1074
1075         TRACE("(%p)\n",lpUnknown);
1076         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1077         temp = *lpUnknown;
1078         *lpUnknown = NULL;
1079         TRACE("doing Release\n");
1080         return IUnknown_Release(temp);
1081 }
1082
1083 /*************************************************************************
1084  *      @       [SHLWAPI.170]
1085  *
1086  * Skip '//' if present in a string.
1087  *
1088  * PARAMS
1089  *  lpszSrc [I] String to check for '//'
1090  *
1091  * RETURNS
1092  *  Success: The next character after the '//' or the string if not present
1093  *  Failure: NULL, if lpszStr is NULL.
1094  */
1095 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1096 {
1097   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1098     lpszSrc += 2;
1099   return lpszSrc;
1100 }
1101
1102 /*************************************************************************
1103  *      @               [SHLWAPI.171]
1104  *
1105  * _SHIsSameObject
1106  */
1107 BOOL WINAPI SHLWAPI_171(LPVOID x, LPVOID y)
1108 {
1109         FIXME("%p %p\n",x,y);
1110         return 0;
1111 }
1112
1113 /*************************************************************************
1114  *      @       [SHLWAPI.172]
1115  *
1116  * Get the window handle of an object.
1117  *
1118  * PARAMS
1119  *  lpUnknown [I] Object to get the window handle of
1120  *  lphWnd    [O] Destination for window handle
1121  *
1122  * RETURNS
1123  *  Success: S_OK. lphWnd contains the objects window handle.
1124  *  Failure: An HRESULT error code.
1125  *
1126  * NOTES
1127  *  lpUnknown is expected to support one of the following interfaces:
1128  *   IOleWindow
1129  *   IInternetSecurityMgrSite
1130  *   IShellView
1131  */
1132 HRESULT WINAPI SHLWAPI_172(IUnknown *lpUnknown, PHWND lphWnd)
1133 {
1134   /* FIXME: Wine has no header for this object */
1135   static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1136     0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1137   IUnknown *lpOle;
1138   HRESULT hRet = E_FAIL;
1139
1140   TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1141
1142   if (!lpUnknown)
1143     return hRet;
1144
1145   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1146
1147   if (FAILED(hRet))
1148   {
1149     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1150
1151     if (FAILED(hRet))
1152     {
1153       hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1154                                       (void**)&lpOle);
1155     }
1156   }
1157
1158   if (SUCCEEDED(hRet))
1159   {
1160     /* Lazyness here - Since GetWindow() is the first method for the above 3
1161      * interfaces, we use the same call for them all.
1162      */
1163     hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1164     IUnknown_Release(lpOle);
1165     if (lphWnd)
1166       TRACE("Returning HWND=%p\n", *lphWnd);
1167   }
1168
1169   return hRet;
1170 }
1171
1172 /*************************************************************************
1173  *      @       [SHLWAPI.174]
1174  *
1175  * Seems to do call either IObjectWithSite::SetSite or
1176  *   IPersistMoniker::GetClassID.  But since we do not implement either
1177  *   of those classes in our headers, we will fake it out.
1178  */
1179 DWORD WINAPI SHLWAPI_174(
1180         IUnknown *p1,     /* [in]   OLE object                          */
1181         LPVOID *p2)       /* [out]  ptr to result of either GetClassID
1182                                     or SetSite call.                    */
1183 {
1184     DWORD ret, aa;
1185
1186     if (!p1) return E_FAIL;
1187
1188     /* see if SetSite interface exists for IObjectWithSite object */
1189     ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1190     TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1191     if (ret) {
1192
1193         /* see if GetClassId interface exists for IPersistMoniker object */
1194         ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1195         TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1196         if (ret) return ret;
1197
1198         /* fake a GetClassId call */
1199         ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1200         TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1201               *(LPDWORD)p2);
1202         IUnknown_Release((IUnknown *)aa);
1203     }
1204     else {
1205         /* fake a SetSite call */
1206         ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1207         TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1208               *(LPDWORD)p2);
1209         IUnknown_Release((IUnknown *)p1);
1210     }
1211     return ret;
1212 }
1213
1214 /*************************************************************************
1215  *      @       [SHLWAPI.175]
1216  *
1217  * Call IPersist::GetClassID on an object.
1218  *
1219  * PARAMS
1220  *  lpUnknown [I] Object supporting the IPersist interface
1221  *  lpClassId [O] Destination for Class Id
1222  *
1223  * RETURNS
1224  *  Success: S_OK. lpClassId contains the Class Id requested.
1225  *  Failure: E_FAIL, If lpUnknown is NULL,
1226  *           E_NOINTERFACE If lpUnknown does not support IPersist,
1227  *           Or an HRESULT error code.
1228  */
1229 HRESULT WINAPI SHLWAPI_175 (IUnknown *lpUnknown, CLSID* lpClassId)
1230 {
1231   IPersist* lpPersist;
1232   HRESULT hRet = E_FAIL;
1233
1234   TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1235
1236   if (lpUnknown)
1237   {
1238     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1239     if (SUCCEEDED(hRet))
1240     {
1241       IPersist_GetClassID(lpPersist, lpClassId);
1242       IPersist_Release(lpPersist);
1243     }
1244   }
1245   return hRet;
1246 }
1247
1248 /*************************************************************************
1249  *      @       [SHLWAPI.176]
1250  *
1251  * Retrieve a Service Interface from an object.
1252  *
1253  * PARAMS
1254  *  lpUnknown [I] Object to get an IServiceProvider interface from
1255  *  sid       [I] Service ID for QueryService call
1256  *  riid      [I] Function requested for QueryService call
1257  *  lppOut    [O] Destination for the service interface pointer
1258  *
1259  * Function appears to be interface to IServiceProvider::QueryService
1260  *
1261  * RETURNS
1262  *  Success: S_OK. lppOut contains an object providing the requested service
1263  *  Failure: An HRESULT error code
1264  *
1265  * NOTES
1266  *  lpUnknown is expected to support the IServiceProvider interface.
1267  */
1268 HRESULT WINAPI SHLWAPI_176(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1269                            LPVOID *lppOut)
1270 {
1271   IServiceProvider* pService = NULL;
1272   HRESULT hRet;
1273
1274   if (!lppOut)
1275     return E_FAIL;
1276
1277   *lppOut = NULL;
1278
1279   if (!lpUnknown)
1280     return E_FAIL;
1281
1282   /* Get an IServiceProvider interface from the object */
1283   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1284                                  (LPVOID*)&pService);
1285
1286   if (!hRet && pService)
1287   {
1288     TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1289
1290     /* Get a Service interface from the object */
1291     hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1292
1293     TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1294
1295     /* Release the IServiceProvider interface */
1296     IUnknown_Release(pService);
1297   }
1298   return hRet;
1299 }
1300
1301 /*************************************************************************
1302  *      @       [SHLWAPI.180]
1303  *
1304  * Remove all sub-menus from a menu.
1305  *
1306  * PARAMS
1307  *  hMenu [I] Menu to remove sub-menus from
1308  *
1309  * RETURNS
1310  *  Success: 0.  All sub-menus under hMenu are removed
1311  *  Failure: -1, if any parameter is invalid
1312  */
1313 DWORD WINAPI SHLWAPI_180(HMENU hMenu)
1314 {
1315   int iItemCount = GetMenuItemCount(hMenu) - 1;
1316   while (iItemCount >= 0)
1317   {
1318     HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1319     if (hSubMenu)
1320       RemoveMenu(hMenu, iItemCount, 0x400);
1321     iItemCount--;
1322   }
1323   return iItemCount;
1324 }
1325
1326 /*************************************************************************
1327  *      @       [SHLWAPI.181]
1328  *
1329  * Enable or disable a menu item.
1330  *
1331  * PARAMS
1332  *  hMenu   [I] Menu holding menu item
1333  *  uID     [I] ID of menu item to enable/disable
1334  *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1335  *
1336  * RETURNS
1337  *  The return code from CheckMenuItem.
1338  */
1339 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1340 {
1341   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1342 }
1343
1344 /*************************************************************************
1345  * @    [SHLWAPI.182]
1346  *
1347  * Check or uncheck a menu item.
1348  *
1349  * PARAMS
1350  *  hMenu  [I] Menu holding menu item
1351  *  uID    [I] ID of menu item to check/uncheck
1352  *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1353  *
1354  * RETURNS
1355  *  The return code from CheckMenuItem.
1356  */
1357 DWORD WINAPI SHLWAPI_182(HMENU hMenu, UINT uID, BOOL bCheck)
1358 {
1359   return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : 0);
1360 }
1361
1362 /*************************************************************************
1363  *      @       [SHLWAPI.183]
1364  *
1365  * Register a window class if it isn't already.
1366  *
1367  * PARAMS
1368  *  lpWndClass [I] Window class to register
1369  *
1370  * RETURNS
1371  *  The result of the RegisterClassA call.
1372  */
1373 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1374 {
1375   WNDCLASSA wca;
1376   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1377     return TRUE;
1378   return (DWORD)RegisterClassA(wndclass);
1379 }
1380
1381 /*************************************************************************
1382  *      @       [SHLWAPI.187]
1383  *
1384  * Call IPersistPropertyBag::Load on an object.
1385  *
1386  * PARAMS
1387  *  lpUnknown [I] Object supporting the IPersistPropertyBag interface
1388  *  lpPropBag [O] Destination for loaded IPropertyBag
1389  *
1390  * RETURNS
1391  *  Success: S_OK.
1392  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1393  */
1394 DWORD WINAPI SHLWAPI_187(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1395 {
1396   IPersistPropertyBag* lpPPBag;
1397   HRESULT hRet = E_FAIL;
1398
1399   TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1400
1401   if (lpUnknown)
1402   {
1403     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1404                                    (void**)&lpPPBag);
1405     if (SUCCEEDED(hRet) && lpPPBag)
1406     {
1407       hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1408       IPersistPropertyBag_Release(lpPPBag);
1409     }
1410   }
1411   return hRet;
1412 }
1413
1414 /*************************************************************************
1415  *      @       [SHLWAPI.189]
1416  *
1417  * _IUnknown_OnFocusOCS
1418  */
1419 DWORD WINAPI SHLWAPI_189(LPVOID x, LPVOID y)
1420 {
1421         FIXME("%p %p\n", x, y);
1422         return 0;
1423 }
1424
1425 /*************************************************************************
1426  *      @       [SHLWAPI.193]
1427  *
1428  * Get the color depth of the primary display.
1429  *
1430  * PARAMS
1431  *  None.
1432  *
1433  * RETURNS
1434  *  The color depth of the primary display.
1435  */
1436 DWORD WINAPI SHLWAPI_193 ()
1437 {
1438         HDC hdc;
1439         DWORD ret;
1440
1441         TRACE("()\n");
1442
1443         hdc = GetDC(0);
1444         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1445         ReleaseDC(0, hdc);
1446         return ret;
1447 }
1448
1449 /*************************************************************************
1450  *      @       [SHLWAPI.197]
1451  *
1452  * Blank out a region of text by drawing the background only.
1453  *
1454  * PARAMS
1455  *  hDC   [I] Device context to draw in
1456  *  pRect [I] Area to draw in
1457  *  cRef  [I] Color to draw in
1458  *
1459  * RETURNS
1460  *  Nothing.
1461  */
1462 DWORD WINAPI SHLWAPI_197(HDC hDC, LPCRECT pRect, COLORREF cRef)
1463 {
1464     COLORREF cOldColor = SetBkColor(hDC, cRef);
1465     ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
1466     SetBkColor(hDC, cOldColor);
1467     return 0;
1468 }
1469
1470 /*************************************************************************
1471  *      @       [SHLWAPI.199]
1472  *
1473  * Copy interface pointer
1474  *
1475  * PARAMS
1476  *   lppDest   [O] Destination for copy
1477  *   lpUnknown [I] Source for copy
1478  *
1479  * RETURNS
1480  *  Nothing.
1481  */
1482 VOID WINAPI SHLWAPI_199(IUnknown **lppDest, IUnknown *lpUnknown)
1483 {
1484   TRACE("(%p,%p)\n", lppDest, lpUnknown);
1485
1486   if (lppDest)
1487     SHLWAPI_169(lppDest); /* Release existing interface */
1488
1489   if (lpUnknown)
1490   {
1491     /* Copy */
1492     IUnknown_AddRef(lpUnknown);
1493     *lppDest = lpUnknown;
1494   }
1495 }
1496
1497 /*************************************************************************
1498  *      @       [SHLWAPI.201]
1499  *
1500  */
1501 HRESULT WINAPI SHLWAPI_201(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
1502                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1503                            VARIANT* pvaOut)
1504 {
1505   FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
1506         nCmdID, nCmdexecopt, pvaIn, pvaOut);
1507   return DRAGDROP_E_NOTREGISTERED;
1508 }
1509
1510 /*************************************************************************
1511  *      @       [SHLWAPI.202]
1512  *
1513  */
1514 HRESULT WINAPI SHLWAPI_202(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
1515 {
1516   FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
1517   return DRAGDROP_E_NOTREGISTERED;
1518 }
1519
1520 /*************************************************************************
1521  *      @       [SHLWAPI.203]
1522  *
1523  */
1524 VOID WINAPI SHLWAPI_203(LPCSTR lpszStr)
1525 {
1526   FIXME("(%s) - stub!\n", debugstr_a(lpszStr));
1527 }
1528
1529 /*************************************************************************
1530  * @    [SHLWAPI.204]
1531  *
1532  * Determine if a window is not a child of another window.
1533  *
1534  * PARAMS
1535  * hParent [I] Suspected parent window
1536  * hChild  [I] Suspected child window
1537  *
1538  * RETURNS
1539  * TRUE:  If hChild is a child window of hParent
1540  * FALSE: If hChild is not a child window of hParent, or they are equal
1541  */
1542 BOOL WINAPI SHLWAPI_204(HWND hParent, HWND hChild)
1543 {
1544   TRACE("(%p,%p)\n", hParent, hChild);
1545
1546   if (!hParent || !hChild)
1547     return TRUE;
1548   else if(hParent == hChild)
1549     return FALSE;
1550   return !IsChild(hParent, hChild);
1551 }
1552
1553 /*************************************************************************
1554  *      @       [SHLWAPI.208]
1555  *
1556  * Some sort of memory management process - associated with _210
1557  */
1558 DWORD WINAPI SHLWAPI_208 (
1559         DWORD    a,
1560         DWORD    b,
1561         LPVOID   c,
1562         LPVOID   d,
1563         DWORD    e)
1564 {
1565     FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
1566           a, b, c, d, e);
1567     return 1;
1568 }
1569
1570 /*************************************************************************
1571  *      @       [SHLWAPI.209]
1572  *
1573  * Some sort of memory management process - associated with _208
1574  */
1575 DWORD WINAPI SHLWAPI_209 (
1576         LPVOID   a)
1577 {
1578     FIXME("(%p) stub\n",
1579           a);
1580     return 1;
1581 }
1582
1583 /*************************************************************************
1584  *      @       [SHLWAPI.210]
1585  *
1586  * Some sort of memory management process - associated with _208
1587  */
1588 DWORD WINAPI SHLWAPI_210 (
1589         LPVOID   a,
1590         DWORD    b,
1591         LPVOID   c)
1592 {
1593     FIXME("(%p 0x%08lx %p) stub\n",
1594           a, b, c);
1595     return 0;
1596 }
1597
1598 /*************************************************************************
1599  *      @       [SHLWAPI.211]
1600  */
1601 DWORD WINAPI SHLWAPI_211 (
1602         LPVOID   a,
1603         DWORD    b)
1604 {
1605     FIXME("(%p 0x%08lx) stub\n",
1606           a, b);
1607     return 1;
1608 }
1609
1610 /*************************************************************************
1611  *      @       [SHLWAPI.215]
1612  *
1613  * NOTES
1614  *  check me!
1615  */
1616 DWORD WINAPI SHLWAPI_215 (
1617         LPCSTR lpStrSrc,
1618         LPWSTR lpwStrDest,
1619         int len)
1620 {
1621         INT len_a, ret;
1622
1623         len_a = lstrlenA(lpStrSrc);
1624         ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
1625         TRACE("%s %s %d, ret=%d\n",
1626               debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
1627         return ret;
1628 }
1629
1630 /*************************************************************************
1631  *      @       [SHLWAPI.218]
1632  *
1633  * WideCharToMultiByte with multi language support.
1634  */
1635 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
1636                        LPINT lpnMultiCharCount)
1637 {
1638   WCHAR emptyW[] = { '\0' };
1639   int len , reqLen;
1640   LPSTR mem;
1641
1642   if (!lpDstStr || !lpnMultiCharCount)
1643     return 0;
1644
1645   if (!lpSrcStr)
1646     lpSrcStr = emptyW;
1647
1648   *lpDstStr = '\0';
1649
1650   len = strlenW(lpSrcStr) + 1;
1651
1652   switch (CodePage)
1653   {
1654   case CP_WINUNICODE:
1655     CodePage = CP_UTF8; /* Fall through... */
1656   case 0x0000C350: /* FIXME: CP_ #define */
1657   case CP_UTF7:
1658   case CP_UTF8:
1659     {
1660       DWORD dwMode = 0;
1661       INT nWideCharCount = len - 1;
1662
1663       GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
1664       if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
1665                                           lpnMultiCharCount))
1666         return 0;
1667
1668       if (nWideCharCount < len - 1)
1669       {
1670         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
1671         if (!mem)
1672           return 0;
1673
1674         *lpnMultiCharCount = 0;
1675
1676         if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
1677         {
1678           SHLWAPI_162 (mem, *lpnMultiCharCount);
1679           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
1680           return *lpnMultiCharCount + 1;
1681         }
1682         HeapFree(GetProcessHeap(), 0, mem);
1683         return *lpnMultiCharCount;
1684       }
1685       lpDstStr[*lpnMultiCharCount] = '\0';
1686       return *lpnMultiCharCount;
1687     }
1688     break;
1689   default:
1690     break;
1691   }
1692
1693   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
1694                                *lpnMultiCharCount, NULL, NULL);
1695
1696   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
1697   {
1698     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
1699     if (reqLen)
1700     {
1701       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
1702       if (mem)
1703       {
1704         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
1705                                      reqLen, NULL, NULL);
1706
1707         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
1708         reqLen++;
1709
1710         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
1711
1712         HeapFree(GetProcessHeap(), 0, mem);
1713       }
1714     }
1715   }
1716   return reqLen;
1717 }
1718
1719 /*************************************************************************
1720  *      @       [SHLWAPI.217]
1721  *
1722  * Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
1723  * --> Crash. Something wrong here.
1724  *
1725  * It seems from OE v5 that the third param is the count. (GA 11/2001)
1726  */
1727 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
1728 {
1729     INT myint = MultiCharCount;
1730
1731     return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
1732 }
1733
1734 /*************************************************************************
1735  *      @       [SHLWAPI.219]
1736  *
1737  * Seems to be "super" QueryInterface. Supplied with a table of interfaces
1738  * and an array of IIDs and offsets into the table.
1739  *
1740  * NOTES
1741  *  error codes: E_POINTER, E_NOINTERFACE
1742  */
1743 typedef struct {
1744     REFIID   refid;
1745     DWORD    indx;
1746 } IFACE_INDEX_TBL;
1747
1748 HRESULT WINAPI SHLWAPI_219 (
1749         LPVOID w,           /* [in]   table of interfaces                   */
1750         IFACE_INDEX_TBL *x, /* [in]   array of REFIIDs and indexes to above */
1751         REFIID riid,        /* [in]   REFIID to get interface for           */
1752         LPVOID *ppv)          /* [out]  location to get interface pointer     */
1753 {
1754         HRESULT ret;
1755         IUnknown *a_vtbl;
1756         IFACE_INDEX_TBL *xmove;
1757
1758         TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
1759         if (ppv) {
1760             xmove = x;
1761             while (xmove->refid) {
1762                 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
1763                 if (IsEqualIID(riid, xmove->refid)) {
1764                     a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
1765                     TRACE("matched, returning (%p)\n", a_vtbl);
1766                     *ppv = (LPVOID)a_vtbl;
1767                     IUnknown_AddRef(a_vtbl);
1768                     return S_OK;
1769                 }
1770                 xmove++;
1771             }
1772
1773             if (IsEqualIID(riid, &IID_IUnknown)) {
1774                 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
1775                 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
1776                 *ppv = (LPVOID)a_vtbl;
1777                 IUnknown_AddRef(a_vtbl);
1778                 return S_OK;
1779             }
1780             *ppv = 0;
1781             ret = E_NOINTERFACE;
1782         } else
1783             ret = E_POINTER;
1784
1785         TRACE("-- 0x%08lx\n", ret);
1786         return ret;
1787 }
1788
1789 /*************************************************************************
1790  *      @       [SHLWAPI.236]
1791  */
1792 HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
1793 {
1794     HKEY newkey;
1795     DWORD type, count;
1796     CHAR value[MAX_PATH], string[MAX_PATH];
1797
1798     strcpy(string, "CLSID\\");
1799     strcat(string, debugstr_guid(lpUnknown));
1800     strcat(string, "\\InProcServer32");
1801
1802     count = MAX_PATH;
1803     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
1804     RegQueryValueExA(newkey, 0, 0, &type, value, &count);
1805     RegCloseKey(newkey);
1806     return LoadLibraryExA(value, 0, 0);
1807 }
1808
1809 /*************************************************************************
1810  *      @       [SHLWAPI.237]
1811  *
1812  * Unicode version of SHLWAPI_183.
1813  */
1814 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
1815 {
1816         WNDCLASSW WndClass;
1817
1818         TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
1819
1820         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
1821                 return TRUE;
1822         return RegisterClassW(lpWndClass);
1823 }
1824
1825 /*************************************************************************
1826  *      @       [SHLWAPI.239]
1827  */
1828 DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
1829 {
1830     FIXME("(%p %p 0x%08lx) stub\n",
1831           hInstance, p2, dw3);
1832     return 0;
1833 #if 0
1834     /* pseudo code from relay trace */
1835     WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
1836     GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
1837     /* above pair repeated for:
1838            TridentThicketUrlDlClass
1839            Shell Embedding
1840            CIESplashScreen
1841            Inet Notify_Hidden
1842            OCHost
1843     */
1844 #endif
1845 }
1846
1847 /*************************************************************************
1848  *      @       [SHLWAPI.240]
1849  *
1850  * Call The correct (ASCII/Unicode) default window procedure for a window.
1851  *
1852  * PARAMS
1853  *  hWnd     [I] Window to call the default proceedure for
1854  *  uMessage [I] Message ID
1855  *  wParam   [I] WPARAM of message
1856  *  lParam   [I] LPARAM of message
1857  *
1858  * RETURNS
1859  *  The result of calling the window proceedure.
1860  */
1861 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1862 {
1863         if (IsWindowUnicode(hWnd))
1864                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1865         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
1866 }
1867
1868 /*************************************************************************
1869  *      @       [SHLWAPI.241]
1870  *
1871  */
1872 DWORD WINAPI SHLWAPI_241 ()
1873 {
1874         FIXME("()stub\n");
1875         return /* 0xabba1243 */ 0;
1876 }
1877
1878 /*************************************************************************
1879  *      @       [SHLWAPI.266]
1880  *
1881  * native does at least approximately:
1882  *     strcpyW(newstr, x);
1883  *     strcatW(newstr, "\\Restrictions");
1884  *     if (RegOpenKeyExA(80000001, newstr, 00000000,00000001,40520b78))
1885  *        return 0;
1886  *    *unknown*
1887  */
1888 DWORD WINAPI SHLWAPI_266 (
1889         LPVOID w,
1890         LPVOID x,   /* [in] partial registry key */
1891         LPVOID y,
1892         LPVOID z)
1893 {
1894         FIXME("(%p %p %p %p)stub\n",w,x,y,z);
1895         return /* 0xabba1248 */ 0;
1896 }
1897
1898 /*************************************************************************
1899  *      @       [SHLWAPI.267]
1900  *
1901  * NOTES:
1902  *   This QueryInterface asks the inner object for a interface. In case
1903  *   of aggregation this request would be forwarded by the inner to the
1904  *   outer object. This function asks the inner object directly for the
1905  *   interface circumventing the forwarding to the outer object.
1906  */
1907 HRESULT WINAPI SHLWAPI_267 (
1908         IUnknown * pUnk,   /* [in] outer object */
1909         IUnknown * pInner, /* [in] inner object */
1910         IID * riid,
1911         LPVOID* ppv)
1912 {
1913         HRESULT hret = E_NOINTERFACE;
1914         TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
1915
1916         *ppv = NULL;
1917         if(pUnk && pInner) {
1918             hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
1919             if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
1920         }
1921         TRACE("-- 0x%08lx\n", hret);
1922         return hret;
1923 }
1924
1925 /*************************************************************************
1926  *      @       [SHLWAPI.268]
1927  *
1928  * Move a reference from one interface to another.
1929  *
1930  * PARAMS
1931  *   lpDest     [O] Destination to receive the reference
1932  *   lppUnknown [O] Source to give up the reference to lpDest
1933  *
1934  * RETURNS
1935  *  Nothing.
1936  */
1937 VOID WINAPI SHLWAPI_268(IUnknown *lpDest, IUnknown **lppUnknown)
1938 {
1939   TRACE("(%p,%p)\n", lpDest, lppUnknown);
1940
1941   if (*lppUnknown)
1942   {
1943     /* Copy Reference*/
1944     IUnknown_AddRef(lpDest);
1945     SHLWAPI_169(lppUnknown); /* Release existing interface */
1946   }
1947 }
1948
1949 /*************************************************************************
1950  *      @       [SHLWAPI.276]
1951  *
1952  * Determine if the browser is integrated into the shell, and set a registry
1953  * key accordingly.
1954  *
1955  * PARAMS
1956  *  None.
1957  *
1958  * RETURNS
1959  *  1, If the browser is not integrated.
1960  *  2, If the browser is integrated.
1961  *
1962  * NOTES
1963  *  The key HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser is
1964  *  either set to TRUE, or removed depending on whether the browser is deemed
1965  *  to be integrated.
1966  */
1967 DWORD WINAPI SHLWAPI_276()
1968 {
1969   static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
1970   static DWORD dwState = 0;
1971   HKEY hKey;
1972   DWORD dwRet, dwData, dwSize;
1973
1974   if (dwState)
1975     return dwState;
1976
1977   /* If shell32 exports DllGetVersion(), the browser is integrated */
1978   GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
1979   dwState = pDllGetVersion ? 2 : 1;
1980
1981   /* Set or delete the key accordinly */
1982   dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
1983                         "Software\\Microsoft\\Internet Explorer", 0,
1984                          KEY_ALL_ACCESS, &hKey);
1985   if (!dwRet)
1986   {
1987     dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
1988                              (LPBYTE)&dwData, &dwSize);
1989
1990     if (!dwRet && dwState == 1)
1991     {
1992       /* Value exists but browser is not integrated */
1993       RegDeleteValueA(hKey, szIntegratedBrowser);
1994     }
1995     else if (dwRet && dwState == 2)
1996     {
1997       /* Browser is integrated but value does not exist */
1998       dwData = TRUE;
1999       RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2000                      (LPBYTE)&dwData, sizeof(dwData));
2001     }
2002     RegCloseKey(hKey);
2003   }
2004   return dwState;
2005 }
2006
2007 /*************************************************************************
2008  *      @       [SHLWAPI.278]
2009  *
2010  */
2011 HWND WINAPI SHLWAPI_278 (
2012         LONG wndProc,
2013         HWND hWndParent,
2014         DWORD dwExStyle,
2015         DWORD dwStyle,
2016         HMENU hMenu,
2017         LONG z)
2018 {
2019         WNDCLASSA wndclass;
2020         HWND hwnd;
2021         HCURSOR hCursor;
2022         char * clsname = "WorkerA";
2023
2024         FIXME("(0x%08lx %p 0x%08lx 0x%08lx %p 0x%08lx) partial stub\n",
2025           wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
2026
2027         hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
2028
2029         if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
2030         {
2031           RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
2032           wndclass.lpfnWndProc = DefWindowProcW;
2033           wndclass.cbWndExtra = 4;
2034           wndclass.hInstance = shlwapi_hInstance;
2035           wndclass.hCursor = hCursor;
2036           wndclass.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2037           wndclass.lpszMenuName = NULL;
2038           wndclass.lpszClassName = clsname;
2039           RegisterClassA (&wndclass);
2040         }
2041         hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
2042                 hMenu,shlwapi_hInstance,0);
2043         SetWindowLongA(hwnd, 0, z);
2044         SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
2045         return hwnd;
2046 }
2047
2048 /*************************************************************************
2049  *      @       [SHLWAPI.281]
2050  *
2051  * _SHPackDispParamsV
2052  */
2053 HRESULT WINAPI SHLWAPI_281(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2054 {
2055         FIXME("%p %p %p %p\n",w,x,y,z);
2056         return E_FAIL;
2057 }
2058
2059 /*************************************************************************
2060  *      @       [SHLWAPI.284]
2061  *
2062  * _IConnectionPoint_SimpleInvoke
2063  */
2064 DWORD WINAPI SHLWAPI_284 (
2065         LPVOID x,
2066         LPVOID y,
2067         LPVOID z)
2068 {
2069         TRACE("(%p %p %p) stub\n",x,y,z);
2070         return 0;
2071 }
2072
2073 /*************************************************************************
2074  *      @       [SHLWAPI.287]
2075  *
2076  * _IUnknown_CPContainerOnChanged
2077  */
2078 HRESULT WINAPI SHLWAPI_287(LPVOID x, LPVOID y)
2079 {
2080         FIXME("%p %p\n", x,y);
2081         return E_FAIL;
2082 }
2083
2084 /*************************************************************************
2085  *      @       [SHLWAPI.289]
2086  *
2087  * Late bound call to winmm.PlaySoundW
2088  */
2089 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2090 {
2091   GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2092   return pPlaySoundW(pszSound, hmod, fdwSound);
2093 }
2094
2095 /*************************************************************************
2096  *      @       [SHLWAPI.294]
2097  */
2098 BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
2099 {
2100     /*
2101      * str1:            "I"     "I"     pushl esp+0x20
2102      * str2:            "U"     "I"     pushl 0x77c93810
2103      * (is "I" and "U" "integer" and "unsigned" ??)
2104      *
2105      * pStr:            ""      ""      pushl eax
2106      * some_len:        0x824   0x104   pushl 0x824
2107      * lpStr2:          "%l"    "%l"    pushl esp+0xc
2108      *
2109      * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2110      * LocalAlloc(0x00, some_len) -> irrelevant_var
2111      * LocalAlloc(0x40, irrelevant_len) -> pStr
2112      * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2113      * shlwapi.PathRemoveBlanksW(pStr);
2114      */
2115     FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2116     return TRUE;
2117 }
2118
2119 /*************************************************************************
2120  *      @       [SHLWAPI.295]
2121  *
2122  * Called by ICQ2000b install via SHDOCVW:
2123  * str1: "InternetShortcut"
2124  * x: some unknown pointer
2125  * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2126  * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2127  *
2128  * In short: this one maybe creates a desktop link :-)
2129  */
2130 BOOL WINAPI SHLWAPI_295(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2131 {
2132     FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2133     return TRUE;
2134 }
2135
2136 /*************************************************************************
2137  *      @       [SHLWAPI.299]
2138  *
2139  * Late bound call to comctl32.417
2140  */
2141 BOOL WINAPI SHLWAPI_299(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2142                          LPCWSTR str, UINT count, const INT *lpDx)
2143 {
2144     GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2145     return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2146 }
2147
2148 /*************************************************************************
2149  *      @       [SHLWAPI.313]
2150  *
2151  * Late bound call to shell32.SHGetFileInfoW
2152  */
2153 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
2154                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2155 {
2156   GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2157   return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2158 }
2159
2160 /*************************************************************************
2161  *      @       [SHLWAPI.318]
2162  *
2163  * Late bound call to shell32.DragQueryFileW
2164  */
2165 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2166 {
2167   GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2168   return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2169 }
2170
2171 /*************************************************************************
2172  *      @       [SHLWAPI.333]
2173  *
2174  * Late bound call to shell32.SHBrowseForFolderW
2175  */
2176 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
2177 {
2178   GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2179   return pSHBrowseForFolderW(lpBi);
2180 }
2181
2182 /*************************************************************************
2183  *      @       [SHLWAPI.334]
2184  *
2185  * Late bound call to shell32.SHGetPathFromIDListW
2186  */
2187 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
2188 {
2189   GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2190   return pSHGetPathFromIDListW(pidl, pszPath);
2191 }
2192
2193 /*************************************************************************
2194  *      @       [SHLWAPI.335]
2195  *
2196  * Late bound call to shell32.ShellExecuteExW
2197  */
2198 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
2199 {
2200   GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
2201   return pShellExecuteExW(lpExecInfo);
2202 }
2203
2204 /*************************************************************************
2205  *      @       [SHLWAPI.336]
2206  *
2207  * Late bound call to shell32.SHFileOperationW.
2208  */
2209 HICON WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
2210 {
2211   GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
2212   return pSHFileOperationW(lpFileOp);
2213 }
2214
2215 /*************************************************************************
2216  *      @       [SHLWAPI.337]
2217  *
2218  * Late bound call to shell32.ExtractIconExW.
2219  */
2220 HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
2221                          HICON *phiconSmall, UINT nIcons)
2222 {
2223   GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", (HICON)0);
2224   return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
2225 }
2226
2227 /*************************************************************************
2228  *      @       [SHLWAPI.342]
2229  *
2230  */
2231 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
2232 {
2233         return InterlockedCompareExchange(dest, xchg, compare);
2234 }
2235
2236 /*************************************************************************
2237  *      @       [SHLWAPI.346]
2238  */
2239 DWORD WINAPI SHLWAPI_346 (
2240         LPCWSTR src,
2241         LPWSTR dest,
2242         int len)
2243 {
2244         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
2245         lstrcpynW(dest, src, len);
2246         return lstrlenW(dest)+1;
2247 }
2248
2249 /*************************************************************************
2250  *      @       [SHLWAPI.350]
2251  *
2252  * seems to be late bound call to GetFileVersionInfoSizeW
2253  */
2254 DWORD WINAPI SHLWAPI_350 (
2255         LPWSTR x,
2256         LPVOID y)
2257 {
2258         DWORD ret;
2259
2260         GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
2261         ret = pGetFileVersionInfoSizeW(x, y);
2262         return 0x208 + ret;
2263 }
2264
2265 /*************************************************************************
2266  *      @       [SHLWAPI.351]
2267  *
2268  * seems to be late bound call to GetFileVersionInfoW
2269  */
2270 BOOL  WINAPI SHLWAPI_351 (
2271         LPWSTR w,   /* [in] path to dll */
2272         DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
2273         DWORD  y,   /* [in] return value from .350 - assume length */
2274         LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA) */
2275 {
2276     GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
2277     return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
2278 }
2279
2280 /*************************************************************************
2281  *      @       [SHLWAPI.352]
2282  *
2283  * seems to be late bound call to VerQueryValueW
2284  */
2285 WORD WINAPI SHLWAPI_352 (
2286         LPVOID w,   /* [in] buffer from _351 */
2287         LPWSTR x,   /* [in]   value to retrieve -
2288                               converted and passed to VerQueryValueA as #2 */
2289         LPVOID y,   /* [out]  ver buffer - passed to VerQueryValueA as #3 */
2290         UINT*  z)   /* [in]   ver length - passed to VerQueryValueA as #4 */
2291 {
2292     GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
2293     return pVerQueryValueW((char*)w+0x208, x, y, z);
2294 }
2295
2296 /*************************************************************************
2297  *      @       [SHLWAPI.357]
2298  *
2299  * Late bound call to shell32.SHGetNewLinkInfoW
2300  */
2301 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
2302                         BOOL *pfMustCopy, UINT uFlags)
2303 {
2304   GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
2305   return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
2306 }
2307
2308 /*************************************************************************
2309  *      @       [SHLWAPI.358]
2310  *
2311  * Late bound call to shell32.SHDefExtractIconW
2312  */
2313 DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2314                          LPVOID arg5, LPVOID arg6)
2315 {
2316   GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
2317   return pSHDefExtractIconW(arg1, arg2, arg3, arg4, arg5, arg6);
2318 }
2319
2320 /*************************************************************************
2321  *      @       [SHLWAPI.364]
2322  *
2323  * Wrapper for lstrcpynA with src and dst swapped.
2324  */
2325 DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
2326 {
2327   lstrcpynA(dst, src, n);
2328   return TRUE;
2329 }
2330
2331 /*************************************************************************
2332  *      @       [SHLWAPI.370]
2333  *
2334  * Late bound call to shell32.ExtractIconW
2335  */
2336 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
2337                          UINT nIconIndex)
2338 {
2339   GET_FUNC(pExtractIconW, shell32, "ExtractIconW", (HICON)0);
2340   return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
2341 }
2342
2343 /*************************************************************************
2344  *      @       [SHLWAPI.376]
2345  */
2346 LANGID WINAPI SHLWAPI_376 ()
2347 {
2348     FIXME("() stub\n");
2349     /* FIXME: This should be a forward in the .spec file to the win2k function
2350      * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
2351      */
2352     return GetUserDefaultLangID();
2353 }
2354
2355 /*************************************************************************
2356  *      @       [SHLWAPI.377]
2357  *
2358  * FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
2359  *        each call here.
2360  * FIXME: Native shows calls to:
2361  *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
2362  *                      CheckVersion
2363  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
2364  *  RegQueryValueExA for "LPKInstalled"
2365  *  RegCloseKey
2366  *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
2367  *  RegQueryValueExA for "ResourceLocale"
2368  *  RegCloseKey
2369  *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
2370  *  RegQueryValueExA for "Locale"
2371  *  RegCloseKey
2372  *  and then tests the Locale ("en" for me).
2373  *     code below
2374  *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
2375  */
2376 DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
2377 {
2378     CHAR mod_path[2*MAX_PATH];
2379     LPSTR ptr;
2380
2381     GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
2382     ptr = strrchr(mod_path, '\\');
2383     if (ptr) {
2384         strcpy(ptr+1, new_mod);
2385         TRACE("loading %s\n", debugstr_a(mod_path));
2386         return (DWORD)LoadLibraryA(mod_path);
2387     }
2388     return 0;
2389 }
2390
2391 /*************************************************************************
2392  *      @       [SHLWAPI.378]
2393  *
2394  *  This is Unicode version of .377
2395  */
2396 DWORD WINAPI SHLWAPI_378 (
2397         LPCWSTR   new_mod,          /* [in] new module name        */
2398         HMODULE   inst_hwnd,        /* [in] calling module handle  */
2399         LPVOID z)                   /* [???] 4 */
2400 {
2401     WCHAR mod_path[2*MAX_PATH];
2402     LPWSTR ptr;
2403
2404     GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
2405     ptr = strrchrW(mod_path, '\\');
2406     if (ptr) {
2407         strcpyW(ptr+1, new_mod);
2408         TRACE("loading %s\n", debugstr_w(mod_path));
2409         return (DWORD)LoadLibraryW(mod_path);
2410     }
2411     return 0;
2412 }
2413
2414 /*************************************************************************
2415  *      @       [SHLWAPI.389]
2416  *
2417  * Late bound call to comdlg32.GetSaveFileNameW
2418  */
2419 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
2420 {
2421   GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
2422   return pGetSaveFileNameW(ofn);
2423 }
2424
2425 /*************************************************************************
2426  *      @       [SHLWAPI.390]
2427  *
2428  * Late bound call to mpr.WNetRestoreConnectionW
2429  */
2430 DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
2431 {
2432   GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
2433   return pWNetRestoreConnectionW(arg1, arg2);
2434 }
2435
2436 /*************************************************************************
2437  *      @       [SHLWAPI.391]
2438  *
2439  * Late bound call to mpr.WNetGetLastErrorW
2440  */
2441 DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
2442                          LPVOID arg5)
2443 {
2444   GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
2445   return pWNetGetLastErrorW(arg1, arg2, arg3, arg4, arg5);
2446 }
2447
2448 /*************************************************************************
2449  *      @       [SHLWAPI.401]
2450  *
2451  * Late bound call to comdlg32.PageSetupDlgW
2452  */
2453 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
2454 {
2455   GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
2456   return pPageSetupDlgW(pagedlg);
2457 }
2458
2459 /*************************************************************************
2460  *      @       [SHLWAPI.402]
2461  *
2462  * Late bound call to comdlg32.PrintDlgW
2463  */
2464 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
2465 {
2466   GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
2467   return pPrintDlgW(printdlg);
2468 }
2469
2470 /*************************************************************************
2471  *      @       [SHLWAPI.403]
2472  *
2473  * Late bound call to comdlg32.GetOpenFileNameW
2474  */
2475 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
2476 {
2477   GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
2478   return pGetOpenFileNameW(ofn);
2479 }
2480
2481 /* INTERNAL: Map from HLS color space to RGB */
2482 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
2483 {
2484   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
2485
2486   if (wHue > 160)
2487     return wMid1;
2488   else if (wHue > 120)
2489     wHue = 160 - wHue;
2490   else if (wHue > 40)
2491     return wMid2;
2492
2493   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
2494 }
2495
2496 /* Convert to RGB and scale into RGB range (0..255) */
2497 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
2498
2499 /*************************************************************************
2500  *      ColorHLSToRGB   [SHLWAPI.404]
2501  *
2502  * Convert from HLS color space into an RGB COLORREF.
2503  *
2504  * NOTES
2505  * Input HLS values are constrained to the range (0..240).
2506  */
2507 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
2508 {
2509   WORD wRed;
2510
2511   if (wSaturation)
2512   {
2513     WORD wGreen, wBlue, wMid1, wMid2;
2514
2515     if (wLuminosity > 120)
2516       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
2517     else
2518       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
2519
2520     wMid1 = wLuminosity * 2 - wMid2;
2521
2522     wRed   = GET_RGB(wHue + 80);
2523     wGreen = GET_RGB(wHue);
2524     wBlue  = GET_RGB(wHue - 80);
2525
2526     return RGB(wRed, wGreen, wBlue);
2527   }
2528
2529   wRed = wLuminosity * 255 / 240;
2530   return RGB(wRed, wRed, wRed);
2531 }
2532
2533 /*************************************************************************
2534  *      @       [SHLWAPI.413]
2535  *
2536  * Function unknown seems to always to return 0
2537  * x can be 0x3.
2538  */
2539 DWORD WINAPI SHLWAPI_413 (DWORD x)
2540 {
2541         FIXME("(0x%08lx)stub\n", x);
2542         return 0;
2543 }
2544
2545 /*************************************************************************
2546  *      @       [SHLWAPI.418]
2547  *
2548  * Function seems to do FreeLibrary plus other things.
2549  *
2550  * FIXME native shows the following calls:
2551  *   RtlEnterCriticalSection
2552  *   LocalFree
2553  *   GetProcAddress(Comctl32??, 150L)
2554  *   DPA_DeletePtr
2555  *   RtlLeaveCriticalSection
2556  *  followed by the FreeLibrary.
2557  *  The above code may be related to .377 above.
2558  */
2559 BOOL  WINAPI SHLWAPI_418 (HMODULE x)
2560 {
2561         FIXME("(0x%08lx) partial stub\n", (LONG)x);
2562         return FreeLibrary(x);
2563 }
2564
2565 /*************************************************************************
2566  *      @       [SHLWAPI.430]
2567  */
2568 DWORD WINAPI SHLWAPI_430 (HINSTANCE hModule, HANDLE heap)
2569 {
2570         FIXME("(0x%08lx 0x%08lx) stub\n", (DWORD)hModule, (DWORD)heap);
2571         return E_FAIL;   /* This is what is used if shlwapi not loaded */
2572 }
2573
2574 /*************************************************************************
2575  *      @       [SHLWAPI.431]
2576  */
2577 DWORD WINAPI SHLWAPI_431 (DWORD x)
2578 {
2579         FIXME("(0x%08lx)stub\n", x);
2580         return 0xabba1247;
2581 }
2582
2583 /*************************************************************************
2584  *      @       [SHLWAPI.436]
2585  *
2586  *  This is really CLSIDFromString which is exported by ole32.dll,
2587  *  however the native shlwapi.dll does *not* import ole32. Nor does
2588  *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
2589  *  that MS duplicated the code for CLSIDFromString.
2590  *
2591  *  This is a duplicate (with changes for UNICODE) of CLSIDFromString16
2592  *  in dlls/ole32/compobj.c
2593  */
2594 DWORD WINAPI SHLWAPI_436 (LPWSTR idstr, CLSID *id)
2595 {
2596     LPWSTR s = idstr;
2597     BYTE *p;
2598     INT i;
2599     WCHAR table[256];
2600
2601     if (!s) {
2602         memset(s, 0, sizeof(CLSID));
2603         return S_OK;
2604     }
2605     else {  /* validate the CLSID string */
2606
2607         if (strlenW(s) != 38)
2608             return CO_E_CLASSSTRING;
2609
2610         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
2611             return CO_E_CLASSSTRING;
2612
2613         for (i=1; i<37; i++)
2614             {
2615                 if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
2616                 if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
2617                       ((s[i] >= L'a') && (s[i] <= L'f'))  ||
2618                       ((s[i] >= L'A') && (s[i] <= L'F')))
2619                     )
2620                     return CO_E_CLASSSTRING;
2621             }
2622     }
2623
2624     TRACE("%s -> %p\n", debugstr_w(s), id);
2625
2626   /* quick lookup table */
2627     memset(table, 0, 256*sizeof(WCHAR));
2628
2629     for (i = 0; i < 10; i++) {
2630         table['0' + i] = i;
2631     }
2632     for (i = 0; i < 6; i++) {
2633         table['A' + i] = i+10;
2634         table['a' + i] = i+10;
2635     }
2636
2637     /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
2638
2639     p = (BYTE *) id;
2640
2641     s++;        /* skip leading brace  */
2642     for (i = 0; i < 4; i++) {
2643         p[3 - i] = table[*s]<<4 | table[*(s+1)];
2644         s += 2;
2645     }
2646     p += 4;
2647     s++;        /* skip - */
2648
2649     for (i = 0; i < 2; i++) {
2650         p[1-i] = table[*s]<<4 | table[*(s+1)];
2651         s += 2;
2652     }
2653     p += 2;
2654     s++;        /* skip - */
2655
2656     for (i = 0; i < 2; i++) {
2657         p[1-i] = table[*s]<<4 | table[*(s+1)];
2658         s += 2;
2659     }
2660     p += 2;
2661     s++;        /* skip - */
2662
2663     /* these are just sequential bytes */
2664     for (i = 0; i < 2; i++) {
2665         *p++ = table[*s]<<4 | table[*(s+1)];
2666         s += 2;
2667     }
2668     s++;        /* skip - */
2669
2670     for (i = 0; i < 6; i++) {
2671         *p++ = table[*s]<<4 | table[*(s+1)];
2672         s += 2;
2673     }
2674
2675     return S_OK;
2676 }
2677
2678 /*************************************************************************
2679  *      @       [SHLWAPI.437]
2680  *
2681  * Determine if the OS supports a given feature.
2682  *
2683  * PARAMS
2684  *  dwFeature [I] Feature requested (undocumented)
2685  *
2686  * RETURNS
2687  *  TRUE  If the feature is available.
2688  *  FALSE If the feature is not available.
2689  */
2690 DWORD WINAPI SHLWAPI_437 (DWORD feature)
2691 {
2692   FIXME("(0x%08lx) stub\n", feature);
2693   return FALSE;
2694 }
2695
2696 /*************************************************************************
2697  *      ColorRGBToHLS   [SHLWAPI.445]
2698  *
2699  * Convert from RGB COLORREF into the HLS color space.
2700  *
2701  * NOTES
2702  * Input HLS values are constrained to the range (0..240).
2703  */
2704 VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue,
2705                           LPWORD wLuminance, LPWORD pwSaturation)
2706 {
2707     FIXME("stub\n");
2708     return;
2709 }
2710
2711 /*************************************************************************
2712  *      SHCreateShellPalette    [SHLWAPI.@]
2713  */
2714 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
2715 {
2716         FIXME("stub\n");
2717         return CreateHalftonePalette(hdc);
2718 }
2719
2720 /*************************************************************************
2721  *      SHGetInverseCMAP (SHLWAPI.@)
2722  */
2723 DWORD WINAPI SHGetInverseCMAP (LPDWORD* x, DWORD why)
2724 {
2725     if (why == 4) {
2726         FIXME(" - returning bogus address for SHGetInverseCMAP\n");
2727         *x = (LPDWORD)0xabba1249;
2728         return 0;
2729     }
2730     FIXME("(%p, %#lx)stub\n", x, why);
2731     return 0;
2732 }
2733
2734 /*************************************************************************
2735  *      SHIsLowMemoryMachine    [SHLWAPI.@]
2736  */
2737 DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
2738 {
2739         FIXME("0x%08lx\n", x);
2740         return 0;
2741 }
2742
2743 /*************************************************************************
2744  *      GetMenuPosFromID        [SHLWAPI.@]
2745  */
2746 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
2747 {
2748  MENUITEMINFOA mi;
2749  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
2750
2751  while (nIter < nCount)
2752  {
2753    mi.wID = 0;
2754    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
2755      return nIter;
2756    nIter++;
2757  }
2758  return -1;
2759 }
2760
2761 /*************************************************************************
2762  * SHSkipJunction       [SHLWAPI.@]
2763  *
2764  * Determine if a bind context can be bound to an object
2765  *
2766  * PARAMS
2767  *  pbc    [I] Bind context to check
2768  *  pclsid [I] CLSID of object to be bound to
2769  *
2770  * RETURNS
2771  *  TRUE: If it is safe to bind
2772  *  FALSE: If pbc is invalid or binding would not be safe
2773  *
2774  */
2775 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
2776 {
2777   static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
2778     'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
2779   BOOL bRet = FALSE;
2780
2781   if (pbc)
2782   {
2783     IUnknown* lpUnk;
2784
2785     if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
2786     {
2787       CLSID clsid;
2788
2789       if (SUCCEEDED(SHLWAPI_175(lpUnk, &clsid)) &&
2790           IsEqualGUID(pclsid, &clsid))
2791         bRet = TRUE;
2792
2793       IUnknown_Release(lpUnk);
2794     }
2795   }
2796   return bRet;
2797 }