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