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