Fix the case of product and company names.
[wine] / dlls / shlwapi / ordinal.c
1 /*
2  * SHLWAPI ordinal functions
3  *
4  * Copyright 1997 Marcus Meissner
5  *           1998 Jürgen Schmied
6  *           2001-2003 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 <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33 #include "windef.h"
34 #include "winbase.h"
35 #include "winuser.h"
36 #include "winnls.h"
37 #include "ddeml.h"
38 #include "docobj.h"
39 #include "exdisp.h"
40 #include "shlguid.h"
41 #include "wingdi.h"
42 #include "shlobj.h"
43 #include "olectl.h"
44 #include "shellapi.h"
45 #include "commdlg.h"
46 #include "wine/unicode.h"
47 #include "servprov.h"
48 #include "winreg.h"
49 #include "winuser.h"
50 #include "wine/debug.h"
51 #include "shlwapi.h"
52
53
54 WINE_DEFAULT_DEBUG_CHANNEL(shell);
55
56 /* Get a function pointer from a DLL handle */
57 #define GET_FUNC(func, module, name, fail) \
58   do { \
59     if (!func) { \
60       if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
61       func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
62       if (!func) return fail; \
63     } \
64   } while (0)
65
66 /* DLL handles for late bound calls */
67 extern HINSTANCE shlwapi_hInstance;
68 extern HMODULE SHLWAPI_hshell32;
69 extern HMODULE SHLWAPI_hwinmm;
70 extern HMODULE SHLWAPI_hcomdlg32;
71 extern HMODULE SHLWAPI_hcomctl32;
72 extern HMODULE SHLWAPI_hmpr;
73 extern HMODULE SHLWAPI_hmlang;
74 extern HMODULE SHLWAPI_hurlmon;
75 extern HMODULE SHLWAPI_hversion;
76
77 extern DWORD SHLWAPI_ThreadRef_index;
78
79 typedef HANDLE HSHARED; /* Shared memory */
80
81 /* following is GUID for IObjectWithSite::SetSite  -- see _174           */
82 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
83 /* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
84 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
85
86 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
87 typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
88 static  fnpSHBrowseForFolderW pSHBrowseForFolderW;
89 typedef HRESULT (WINAPI *fnpConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
90 static  fnpConvertINetUnicodeToMultiByte pConvertINetUnicodeToMultiByte;
91 typedef BOOL    (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
92 static  fnpPlaySoundW pPlaySoundW;
93 typedef DWORD   (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
94 static  fnpSHGetFileInfoW pSHGetFileInfoW;
95 typedef UINT    (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
96 static  fnpDragQueryFileW pDragQueryFileW;
97 typedef BOOL    (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
98 static  fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
99 typedef BOOL    (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
100 static  fnpShellExecuteExW pShellExecuteExW;
101 typedef HICON   (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
102 static  fnpSHFileOperationW pSHFileOperationW;
103 typedef UINT    (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
104 static  fnpExtractIconExW pExtractIconExW;
105 typedef BOOL    (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
106 static  fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
107 typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
108 static  fnpSHDefExtractIconW pSHDefExtractIconW;
109 typedef HICON   (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
110 static  fnpExtractIconW pExtractIconW;
111 typedef BOOL    (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
112 static  fnpGetSaveFileNameW pGetSaveFileNameW;
113 typedef DWORD   (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
114 static  fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
115 typedef DWORD   (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
116 static  fnpWNetGetLastErrorW pWNetGetLastErrorW;
117 typedef BOOL    (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
118 static  fnpPageSetupDlgW pPageSetupDlgW;
119 typedef BOOL    (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
120 static  fnpPrintDlgW pPrintDlgW;
121 typedef BOOL    (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
122 static  fnpGetOpenFileNameW pGetOpenFileNameW;
123 typedef DWORD   (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
124 static  fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
125 typedef BOOL    (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
126 static  fnpGetFileVersionInfoW pGetFileVersionInfoW;
127 typedef WORD    (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
128 static  fnpVerQueryValueW pVerQueryValueW;
129 typedef BOOL    (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
130 static  fnpCOMCTL32_417 pCOMCTL32_417;
131 typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
132 static  fnpDllGetVersion pDllGetVersion;
133 typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
134 static fnpCreateFormatEnumerator pCreateFormatEnumerator;
135 typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
136 static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
137
138 HRESULT WINAPI SHLWAPI_176(IUnknown*,REFGUID,REFIID,LPVOID*);
139 HRESULT WINAPI SHLWAPI_363(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
140 HRESULT WINAPI SHLWAPI_436(LPCWSTR,CLSID*);
141 BOOL    WINAPI SHLWAPI_161(LPWSTR,DWORD);
142
143 /*
144  NOTES: Most functions exported by ordinal seem to be superflous.
145  The reason for these functions to be there is to provide a wrapper
146  for unicode functions to provide these functions on systems without
147  unicode functions eg. win95/win98. Since we have such functions we just
148  call these. If running Wine with native DLL's, some late bound calls may
149  fail. However, its better to implement the functions in the forward DLL
150  and recommend the builtin rather than reimplementing the calls here!
151 */
152
153 /*************************************************************************
154  * SHLWAPI_DupSharedHandle
155  *
156  * Internal implemetation of SHLWAPI_11.
157  */
158 static
159 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
160                                        DWORD dwSrcProcId, DWORD dwAccess,
161                                        DWORD dwOptions)
162 {
163   HANDLE hDst, hSrc;
164   DWORD dwMyProcId = GetCurrentProcessId();
165   HSHARED hRet = (HSHARED)NULL;
166
167   TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
168         dwAccess, dwOptions);
169
170   /* Get dest process handle */
171   if (dwDstProcId == dwMyProcId)
172     hDst = GetCurrentProcess();
173   else
174     hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
175
176   if (hDst)
177   {
178     /* Get src process handle */
179     if (dwSrcProcId == dwMyProcId)
180       hSrc = GetCurrentProcess();
181     else
182       hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
183
184     if (hSrc)
185     {
186       /* Make handle available to dest process */
187       if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
188                            dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
189         hRet = (HSHARED)NULL;
190
191       if (dwSrcProcId != dwMyProcId)
192         CloseHandle(hSrc);
193     }
194
195     if (dwDstProcId != dwMyProcId)
196       CloseHandle(hDst);
197   }
198
199   TRACE("Returning handle %p\n", (PVOID)hRet);
200   return hRet;
201 }
202
203 /*************************************************************************
204  * @  [SHLWAPI.7]
205  *
206  * Create a block of sharable memory and initialise it with data.
207  *
208  * PARAMS
209  * dwProcId [I] ID of process owning data
210  * lpvData  [I] Pointer to data to write
211  * dwSize   [I] Size of data
212  *
213  * RETURNS
214  * Success: A shared memory handle
215  * Failure: NULL
216  *
217  * NOTES
218  * Ordinals 7-11 provide a set of calls to create shared memory between a
219  * group of processes. The shared memory is treated opaquely in that its size
220  * is not exposed to clients who map it. This is accomplished by storing
221  * the size of the map as the first DWORD of mapped data, and then offsetting
222  * the view pointer returned by this size.
223  *
224  * SHLWAPI_7()/SHLWAPI_10() - Create/Destroy the shared memory handle
225  * SHLWAPI_8()/SHLWAPI_9()  - Get/Release a pointer to the shared data
226  * SHLWAPI_11()           - Helper function; Duplicate cross-process handles
227    */
228 HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
229 {
230   HANDLE hMap;
231   LPVOID pMapped;
232   HSHARED hRet = (HSHARED)NULL;
233
234   TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
235
236   /* Create file mapping of the correct length */
237   hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
238                             dwSize + sizeof(dwSize), NULL);
239   if (!hMap)
240     return hRet;
241
242   /* Get a view in our process address space */
243   pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
244
245   if (pMapped)
246   {
247     /* Write size of data, followed by the data, to the view */
248     *((DWORD*)pMapped) = dwSize;
249     if (dwSize)
250       memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
251
252     /* Release view. All further views mapped will be opaque */
253     UnmapViewOfFile(pMapped);
254     hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
255                                    GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
256                                    DUPLICATE_SAME_ACCESS);
257   }
258
259   CloseHandle(hMap);
260   return hRet;
261 }
262
263 /*************************************************************************
264  * @ [SHLWAPI.8]
265  *
266  * Get a pointer to a block of shared memory from a shared memory handle.
267  *
268  * PARAMS
269  * hShared  [I] Shared memory handle
270  * dwProcId [I] ID of process owning hShared
271  *
272  * RETURNS
273  * Success: A pointer to the shared memory
274  * Failure: NULL
275  *
276  * NOTES
277  * See SHLWAPI_7.
278    */
279 PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
280   {
281   HSHARED hDup;
282   LPVOID pMapped;
283
284   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
285
286   /* Get handle to shared memory for current process */
287   hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
288                                  FILE_MAP_ALL_ACCESS, 0);
289   /* Get View */
290   pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
291   CloseHandle(hDup);
292
293   if (pMapped)
294     return (char *) pMapped + sizeof(DWORD); /* Hide size */
295   return NULL;
296 }
297
298 /*************************************************************************
299  * @ [SHLWAPI.9]
300  *
301  * Release a pointer to a block of shared memory.
302  *
303  * PARAMS
304  * lpView [I] Shared memory pointer
305  *
306  * RETURNS
307  * Success: TRUE
308  * Failure: FALSE
309  *
310  * NOTES
311  * See SHLWAPI_7.
312  */
313 BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
314 {
315   TRACE("(%p)\n", lpView);
316   return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
317 }
318
319 /*************************************************************************
320  * @ [SHLWAPI.10]
321  *
322  * Destroy a block of sharable memory.
323  *
324  * PARAMS
325  * hShared  [I] Shared memory handle
326  * dwProcId [I] ID of process owning hShared
327  *
328  * RETURNS
329  * Success: TRUE
330  * Failure: FALSE
331  *
332  * NOTES
333  * See SHLWAPI_7.
334  */
335 BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
336 {
337   HSHARED hClose;
338
339   TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
340
341   /* Get a copy of the handle for our process, closing the source handle */
342   hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
343                                    FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
344   /* Close local copy */
345   return CloseHandle((HANDLE)hClose);
346 }
347
348 /*************************************************************************
349  * @   [SHLWAPI.11]
350  *
351  * Copy a sharable memory handle from one process to another.
352  *
353  * PARAMS
354  * hShared     [I] Shared memory handle to duplicate
355  * dwDstProcId [I] ID of the process wanting the duplicated handle
356  * dwSrcProcId [I] ID of the process owning hShared
357  * dwAccess    [I] Desired DuplicateHandle() access
358  * dwOptions   [I] Desired DuplicateHandle() options
359  *
360  * RETURNS
361  * Success: A handle suitable for use by the dwDstProcId process.
362  * Failure: A NULL handle.
363  *
364  * NOTES
365  * See SHLWAPI_7.
366  */
367 HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
368                           DWORD dwAccess, DWORD dwOptions)
369 {
370   HSHARED hRet;
371
372   hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
373                                  dwAccess, dwOptions);
374   return hRet;
375 }
376
377 /*************************************************************************
378  *      @       [SHLWAPI.13]
379  *
380  * Create and register a clipboard enumerator for a web browser.
381  *
382  * PARAMS
383  *  lpBC      [I] Binding context
384  *  lpUnknown [I] An object exposing the IWebBrowserApp interface
385  *
386  * RETURNS
387  *  Success: S_OK.
388  *  Failure: An HRESULT error code.
389  *
390  * NOTES
391  *  The enumerator is stored as a property of the web browser. If it does not
392  *  yet exist, it is created and set before being registered.
393  */
394 HRESULT WINAPI SHLWAPI_13(LPBC lpBC, IUnknown *lpUnknown)
395 {
396   static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
397       '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
398       '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
399   IEnumFORMATETC* pIEnumFormatEtc = NULL;
400   VARIANTARG var;
401   HRESULT hRet;
402   IWebBrowserApp* pBrowser = NULL;
403
404   /* Get An IWebBrowserApp interface from  lpUnknown */
405   hRet = SHLWAPI_176(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
406   if (FAILED(hRet) || !pBrowser)
407     return E_NOINTERFACE;
408
409   V_VT(&var) = VT_EMPTY;
410
411   /* The property we get is the browsers clipboard enumerator */
412   hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
413   if (FAILED(hRet))
414     return hRet;
415
416   if (V_VT(&var) == VT_EMPTY)
417   {
418     /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
419     char szKeyBuff[128], szValueBuff[128];
420     DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
421     FORMATETC* formatList, *format;
422     HKEY hDocs;
423
424     TRACE("Registering formats and creating IEnumFORMATETC instance\n");
425
426     if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
427                      "Version\\Internet Settings\\Accepted Documents", &hDocs))
428       return E_FAIL;
429
430     /* Get count of values in key */
431     while (!dwRet)
432     {
433       dwKeySize = sizeof(szKeyBuff);
434       dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
435       dwCount++;
436     }
437
438     dwNumValues = dwCount;
439
440     /* Note: dwCount = number of items + 1; The extra item is the end node */
441     format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
442     if (!formatList)
443       return E_OUTOFMEMORY;
444
445     if (dwNumValues > 1)
446     {
447       dwRet = 0;
448       dwCount = 0;
449
450       dwNumValues--;
451
452       /* Register clipboard formats for the values and populate format list */
453       while(!dwRet && dwCount < dwNumValues)
454       {
455         dwKeySize = sizeof(szKeyBuff);
456         dwValueSize = sizeof(szValueBuff);
457         dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
458                               (PBYTE)szValueBuff, &dwValueSize);
459         if (!dwRet)
460           return E_FAIL;
461
462         format->cfFormat = RegisterClipboardFormatA(szValueBuff);
463         format->ptd = NULL;
464         format->dwAspect = 1;
465         format->lindex = 4;
466         format->tymed = -1;
467
468         format++;
469         dwCount++;
470       }
471     }
472
473     /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
474     format->cfFormat = 0;
475     format->ptd = NULL;
476     format->dwAspect = 1;
477     format->lindex = 4;
478     format->tymed = -1;
479
480     /* Create a clipboard enumerator */
481     GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
482     hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
483
484     if (FAILED(hRet) || !pIEnumFormatEtc)
485       return hRet;
486
487     /* Set our enumerator as the browsers property */
488     V_VT(&var) = VT_UNKNOWN;
489     V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
490
491     hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
492     if (FAILED(hRet))
493     {
494        IEnumFORMATETC_Release(pIEnumFormatEtc);
495        goto SHLWAPI_13_Exit;
496     }
497   }
498
499   if (V_VT(&var) == VT_UNKNOWN)
500   {
501     /* Our variant is holding the clipboard enumerator */
502     IUnknown* pIUnknown = V_UNKNOWN(&var);
503     IEnumFORMATETC* pClone = NULL;
504
505     TRACE("Retrieved IEnumFORMATETC property\n");
506
507     /* Get an IEnumFormatEtc interface from the variants value */
508     pIEnumFormatEtc = NULL;
509     hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
510                                    (PVOID)&pIEnumFormatEtc);
511     if (!hRet && pIEnumFormatEtc)
512     {
513       /* Clone and register the enumerator */
514       hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
515       if (!hRet && pClone)
516       {
517         GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
518         pRegisterFormatEnumerator(lpBC, pClone, 0);
519
520         IEnumFORMATETC_Release(pClone);
521       }
522
523       /* Release the IEnumFormatEtc interface */
524       IEnumFORMATETC_Release(pIUnknown);
525     }
526     IUnknown_Release(V_UNKNOWN(&var));
527   }
528
529 SHLWAPI_13_Exit:
530   IWebBrowserApp_Release(pBrowser);
531   return hRet;
532 }
533
534 /*************************************************************************
535  *      @       [SHLWAPI.14]
536  *
537  * Get Explorers "AcceptLanguage" setting.
538  *
539  * PARAMS
540  *  langbuf [O] Destination for language string
541  *  buflen  [I] Length of langbuf
542  *
543  * RETURNS
544  *  Success: S_OK.   langbuf is set to the language string found.
545  *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
546  *           does not contain the setting.
547  */
548 HRESULT WINAPI SHLWAPI_14 (
549         LPSTR langbuf,
550         LPDWORD buflen)
551 {
552         CHAR *mystr;
553         DWORD mystrlen, mytype;
554         HKEY mykey;
555         LCID mylcid;
556
557         mystrlen = (*buflen > 6) ? *buflen : 6;
558         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
559                                  HEAP_ZERO_MEMORY, mystrlen);
560         RegOpenKeyA(HKEY_CURRENT_USER,
561                     "Software\\Microsoft\\Internet Explorer\\International",
562                     &mykey);
563         if (RegQueryValueExA(mykey, "AcceptLanguage",
564                               0, &mytype, (PBYTE)mystr, &mystrlen)) {
565             /* Did not find value */
566             mylcid = GetUserDefaultLCID();
567             /* somehow the mylcid translates into "en-us"
568              *  this is similar to "LOCALE_SABBREVLANGNAME"
569              *  which could be gotten via GetLocaleInfo.
570              *  The only problem is LOCALE_SABBREVLANGUAGE" is
571              *  a 3 char string (first 2 are country code and third is
572              *  letter for "sublanguage", which does not come close to
573              *  "en-us"
574              */
575             lstrcpyA(mystr, "en-us");
576             mystrlen = lstrlenA(mystr);
577         }
578         else {
579             /* handle returned string */
580             FIXME("missing code\n");
581         }
582         if (mystrlen > *buflen)
583             lstrcpynA(langbuf, mystr, *buflen);
584         else {
585             lstrcpyA(langbuf, mystr);
586             *buflen = lstrlenA(langbuf);
587         }
588         RegCloseKey(mykey);
589         HeapFree(GetProcessHeap(), 0, mystr);
590         TRACE("language is %s\n", debugstr_a(langbuf));
591         return 0;
592 }
593
594 /*************************************************************************
595  *      @       [SHLWAPI.15]
596  *
597  * Unicode version of SHLWAPI_14.
598  */
599 HRESULT WINAPI SHLWAPI_15 (
600         LPWSTR langbuf,
601         LPDWORD buflen)
602 {
603         CHAR *mystr;
604         DWORD mystrlen, mytype;
605         HKEY mykey;
606         LCID mylcid;
607
608         mystrlen = (*buflen > 6) ? *buflen : 6;
609         mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
610                                  HEAP_ZERO_MEMORY, mystrlen);
611         RegOpenKeyA(HKEY_CURRENT_USER,
612                     "Software\\Microsoft\\Internet Explorer\\International",
613                     &mykey);
614         if (RegQueryValueExA(mykey, "AcceptLanguage",
615                               0, &mytype, (PBYTE)mystr, &mystrlen)) {
616             /* Did not find value */
617             mylcid = GetUserDefaultLCID();
618             /* somehow the mylcid translates into "en-us"
619              *  this is similar to "LOCALE_SABBREVLANGNAME"
620              *  which could be gotten via GetLocaleInfo.
621              *  The only problem is LOCALE_SABBREVLANGUAGE" is
622              *  a 3 char string (first 2 are country code and third is
623              *  letter for "sublanguage", which does not come close to
624              *  "en-us"
625              */
626             lstrcpyA(mystr, "en-us");
627             mystrlen = lstrlenA(mystr);
628         }
629         else {
630             /* handle returned string */
631             FIXME("missing code\n");
632         }
633         RegCloseKey(mykey);
634         *buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
635         HeapFree(GetProcessHeap(), 0, mystr);
636         TRACE("language is %s\n", debugstr_w(langbuf));
637         return 0;
638 }
639
640 /*************************************************************************
641  *      @       [SHLWAPI.23]
642  *
643  * Convert a GUID to a string.
644  *
645  * PARAMS
646  *  guid [I] GUID to convert
647  *  str  [O] Destination for string
648  *  cmax [I] Length of output buffer
649  *
650  * RETURNS
651  *  The length of the string created.
652  */
653 INT WINAPI SHLWAPI_23(REFGUID guid, LPSTR lpszDest, INT cchMax)
654 {
655   char xguid[40];
656   INT iLen;
657
658   TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
659
660   sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
661           guid->Data1, guid->Data2, guid->Data3,
662           guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
663           guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
664
665   iLen = strlen(xguid) + 1;
666
667   if (iLen > cchMax)
668     return 0;
669   memcpy(lpszDest, xguid, iLen);
670   return iLen;
671 }
672
673 /*************************************************************************
674  *      @       [SHLWAPI.24]
675  *
676  * Unicode version of SHLWAPI_23.
677  */
678 INT WINAPI SHLWAPI_24(REFGUID guid, LPWSTR lpszDest, INT cchMax)
679 {
680   char xguid[40];
681   INT iLen = SHLWAPI_23(guid, xguid, cchMax);
682   
683   if (iLen)
684     MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax);
685   return iLen;
686 }
687
688 /*************************************************************************
689  *      @       [SHLWAPI.25]
690  *
691  * Determine if a Unicode character is alphabetic.
692  *
693  * PARAMS
694  *  wc [I] Character to check.
695  *
696  * RETURNS
697  *  TRUE, if wc is alphabetic,
698  *  FALSE otherwise.
699  */
700 BOOL WINAPI SHLWAPI_25(WCHAR wc)
701 {
702     return (get_char_typeW(wc) & C1_ALPHA) != 0;
703 }
704
705 /*************************************************************************
706  *      @       [SHLWAPI.26]
707  *
708  * Determine if a Unicode character is upper-case.
709  *
710  * PARAMS
711  *  wc [I] Character to check.
712  *
713  * RETURNS
714  *  TRUE, if wc is upper-case,
715  *  FALSE otherwise.
716  */
717 BOOL WINAPI SHLWAPI_26(WCHAR wc)
718 {
719     return (get_char_typeW(wc) & C1_UPPER) != 0;
720 }
721
722 /*************************************************************************
723  *      @       [SHLWAPI.27]
724  *
725  * Determine if a Unicode character is lower-case.
726  *
727  * PARAMS
728  *  wc [I] Character to check.
729  *
730  * RETURNS
731  *  TRUE, if wc is lower-case,
732  *  FALSE otherwise.
733  */
734 BOOL WINAPI SHLWAPI_27(WCHAR wc)
735 {
736     return (get_char_typeW(wc) & C1_LOWER) != 0;
737 }
738
739 /*************************************************************************
740  *      @       [SHLWAPI.28]
741  *
742  * Determine if a Unicode character is alphabetic or a digit.
743  *
744  * PARAMS
745  *  wc [I] Character to check.
746  *
747  * RETURNS
748  *  TRUE, if wc is alphabetic or a digit,
749  *  FALSE otherwise.
750  */
751 BOOL WINAPI SHLWAPI_28(WCHAR wc)
752 {
753     return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
754 }
755
756 /*************************************************************************
757  *      @       [SHLWAPI.29]
758  *
759  * Determine if a Unicode character is a space.
760  *
761  * PARAMS
762  *  wc [I] Character to check.
763  *
764  * RETURNS
765  *  TRUE, if wc is a space,
766  *  FALSE otherwise.
767  */
768 BOOL WINAPI SHLWAPI_29(WCHAR wc)
769 {
770     return (get_char_typeW(wc) & C1_SPACE) != 0;
771 }
772
773 /*************************************************************************
774  *      @       [SHLWAPI.30]
775  *
776  * Determine if a Unicode character is a blank.
777  *
778  * PARAMS
779  *  wc [I] Character to check.
780  *
781  * RETURNS
782  *  TRUE, if wc is a blank,
783  *  FALSE otherwise.
784  *
785  */
786 BOOL WINAPI SHLWAPI_30(WCHAR wc)
787 {
788     return (get_char_typeW(wc) & C1_BLANK) != 0;
789 }
790
791 /*************************************************************************
792  *      @       [SHLWAPI.31]
793  *
794  * Determine if a Unicode character is punctuation.
795  *
796  * PARAMS
797  *  wc [I] Character to check.
798  *
799  * RETURNS
800  *  TRUE, if wc is punctuation,
801  *  FALSE otherwise.
802  */
803 BOOL WINAPI SHLWAPI_31(WCHAR wc)
804 {
805     return (get_char_typeW(wc) & C1_PUNCT) != 0;
806 }
807
808 /*************************************************************************
809  *      @       [SHLWAPI.32]
810  *
811  * Determine if a Unicode character is a control character.
812  *
813  * PARAMS
814  *  wc [I] Character to check.
815  *
816  * RETURNS
817  *  TRUE, if wc is a control character,
818  *  FALSE otherwise.
819  */
820 BOOL WINAPI SHLWAPI_32(WCHAR wc)
821 {
822     return (get_char_typeW(wc) & C1_CNTRL) != 0;
823 }
824
825 /*************************************************************************
826  *      @       [SHLWAPI.33]
827  *
828  * Determine if a Unicode character is a digit.
829  *
830  * PARAMS
831  *  wc [I] Character to check.
832  *
833  * RETURNS
834  *  TRUE, if wc is a digit,
835  *  FALSE otherwise.
836  */
837 BOOL WINAPI SHLWAPI_33(WCHAR wc)
838 {
839     return (get_char_typeW(wc) & C1_DIGIT) != 0;
840 }
841
842 /*************************************************************************
843  *      @       [SHLWAPI.34]
844  *
845  * Determine if a Unicode character is a hex digit.
846  *
847  * PARAMS
848  *  wc [I] Character to check.
849  *
850  * RETURNS
851  *  TRUE, if wc is a hex digit,
852  *  FALSE otherwise.
853  */
854 BOOL WINAPI SHLWAPI_34(WCHAR wc)
855 {
856     return (get_char_typeW(wc) & C1_XDIGIT) != 0;
857 }
858
859 /*************************************************************************
860  *      @       [SHLWAPI.35]
861  *
862  */
863 BOOL WINAPI SHLWAPI_35(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
864 {
865     FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
866     return TRUE;
867 }
868
869 /*************************************************************************
870  *      @       [SHLWAPI.36]
871  *
872  * Insert a bitmap menu item at the bottom of a menu.
873  *
874  * PARAMS
875  *  hMenu [I] Menu to insert into
876  *  flags [I] Flags for insertion
877  *  id    [I] Menu ID of the item
878  *  str   [I] Menu text for the item
879  *
880  * RETURNS
881  *  Success: TRUE,  the item is inserted into the menu
882  *  Failure: FALSE, if any parameter is invalid
883  */
884 BOOL WINAPI SHLWAPI_36(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
885 {
886     TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
887     return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
888 }
889
890 /*************************************************************************
891  *      @       [SHLWAPI.74]
892  *
893  * Get the text from a given dialog item.
894  *
895  * PARAMS
896  *  hWnd     [I] Handle of dialog
897  *  nItem    [I] Index of item
898  *  lpsDest  [O] Buffer for receiving window text
899  *  nDestLen [I] Length of buffer.
900  *
901  * RETURNS
902  *  Success: The length of the returned text.
903  *  Failure: 0.
904  */
905 INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
906 {
907   HWND hItem = GetDlgItem(hWnd, nItem);
908
909   if (hItem)
910     return GetWindowTextW(hItem, lpsDest, nDestLen);
911   if (nDestLen)
912     *lpsDest = (WCHAR)'\0';
913   return 0;
914 }
915
916 /*************************************************************************
917  *      @   [SHLWAPI.138]
918  *
919  * Set the text of a given dialog item.
920  *
921  * PARAMS
922  *  hWnd     [I] Handle of dialog
923  *  iItem    [I] Index of item
924  *  lpszText [O] Text to set
925  *
926  * RETURNS
927  *  Success: TRUE.  The text of the dialog is set to lpszText.
928  *  Failure: FALSE, Otherwise.
929  */
930 BOOL WINAPI SHLWAPI_138(HWND hWnd, INT iItem, LPCWSTR lpszText)
931 {
932     HWND hWndItem = GetDlgItem(hWnd, iItem);
933     if (hWndItem)
934         return SetWindowTextW(hWndItem, lpszText);
935     return FALSE;
936 }
937
938 /*************************************************************************
939  *      @       [SHLWAPI.151]
940  *
941  * Compare two Ascii strings up to a given length.
942  *
943  * PARAMS
944  *  lpszSrc [I] Source string
945  *  lpszCmp [I] String to compare to lpszSrc
946  *  len     [I] Maximum length
947  *
948  * RETURNS
949  *  A number greater than, less than or equal to 0 depending on whether
950  *  lpszSrc is greater than, less than or equal to lpszCmp.
951  */
952 DWORD WINAPI SHLWAPI_151(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
953 {
954     return strncmp(lpszSrc, lpszCmp, len);
955 }
956
957 /*************************************************************************
958  *      @       [SHLWAPI.152]
959  *
960  * Unicode version of SHLWAPI_151.
961  */
962 DWORD WINAPI SHLWAPI_152(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
963 {
964     return strncmpW(lpszSrc, lpszCmp, len);
965 }
966
967 /*************************************************************************
968  *      @       [SHLWAPI.153]
969  *
970  * Compare two Ascii strings up to a given length, ignoring case.
971  *
972  * PARAMS
973  *  lpszSrc [I] Source string
974  *  lpszCmp [I] String to compare to lpszSrc
975  *  len     [I] Maximum length
976  *
977  * RETURNS
978  *  A number greater than, less than or equal to 0 depending on whether
979  *  lpszSrc is greater than, less than or equal to lpszCmp.
980  */
981 DWORD WINAPI SHLWAPI_153(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
982 {
983     return strncasecmp(lpszSrc, lpszCmp, len);
984 }
985
986 /*************************************************************************
987  *      @       [SHLWAPI.154]
988  *
989  * Unicode version of SHLWAPI_153.
990  */
991 DWORD WINAPI SHLWAPI_154(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
992 {
993     return strncmpiW(lpszSrc, lpszCmp, len);
994 }
995
996 /*************************************************************************
997  *      @       [SHLWAPI.155]
998  *
999  * Compare two Ascii strings.
1000  *
1001  * PARAMS
1002  *  lpszSrc [I] Source string
1003  *  lpszCmp [I] String to compare to lpszSrc
1004  *
1005  * RETURNS
1006  *  A number greater than, less than or equal to 0 depending on whether
1007  *  lpszSrc is greater than, less than or equal to lpszCmp.
1008  */
1009 DWORD WINAPI SHLWAPI_155(LPCSTR lpszSrc, LPCSTR lpszCmp)
1010 {
1011     return strcmp(lpszSrc, lpszCmp);
1012 }
1013
1014 /*************************************************************************
1015  *      @       [SHLWAPI.156]
1016  *
1017  * Unicode version of SHLWAPI_155.
1018  */
1019 DWORD WINAPI SHLWAPI_156(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1020 {
1021     return strcmpW(lpszSrc, lpszCmp);
1022 }
1023
1024 /*************************************************************************
1025  *      @       [SHLWAPI.157]
1026  *
1027  * Compare two Ascii strings, ignoring case.
1028  *
1029  * PARAMS
1030  *  lpszSrc [I] Source string
1031  *  lpszCmp [I] String to compare to lpszSrc
1032  *
1033  * RETURNS
1034  *  A number greater than, less than or equal to 0 depending on whether
1035  *  lpszSrc is greater than, less than or equal to lpszCmp.
1036  */
1037 DWORD WINAPI SHLWAPI_157(LPCSTR lpszSrc, LPCSTR lpszCmp)
1038 {
1039     return strcasecmp(lpszSrc, lpszCmp);
1040 }
1041
1042 /*************************************************************************
1043  *      @       [SHLWAPI.158]
1044  *
1045  * Unicode version of SHLWAPI_157.
1046  */
1047 DWORD WINAPI SHLWAPI_158 (LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1048 {
1049     return strcmpiW(lpszSrc, lpszCmp);
1050 }
1051
1052 /*************************************************************************
1053  *      SHLWAPI_160     [SHLWAPI.160]
1054  *
1055  * Get an identification string for the OS and explorer.
1056  *
1057  * PARAMS
1058  *  lpszDest  [O] Destination for Id string
1059  *  dwDestLen [I] Length of lpszDest
1060  *
1061  * RETURNS
1062  *  TRUE,  If the string was created successfully
1063  *  FALSE, Otherwise
1064  */
1065 BOOL WINAPI SHLWAPI_160(LPSTR lpszDest, DWORD dwDestLen)
1066 {
1067   WCHAR buff[2084];
1068
1069   TRACE("(%p,%ld)", lpszDest, dwDestLen);
1070
1071   if (lpszDest && SHLWAPI_161(buff, dwDestLen))
1072   {
1073     WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1074     return TRUE;
1075   }
1076   return FALSE;
1077 }
1078
1079 /*************************************************************************
1080  *      SHLWAPI_161     [SHLWAPI.161]
1081  *
1082  * Unicode version of SHLWAPI_160.
1083  */
1084 BOOL WINAPI SHLWAPI_161(LPWSTR lpszDest, DWORD dwDestLen)
1085 {
1086   static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
1087     'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1088     ' ','E','x','p','l','o','r','e','r','\0' };
1089   static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
1090     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
1091     'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1092   static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
1093     'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1094     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1095   static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
1096     'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1097     ' ','E','x','p','l','o','r','e','r','\\',
1098     'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
1099   static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
1100   static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
1101     'V','e','r','s','i','o','n','\0' };
1102   static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
1103     'O','w','n','e','r','\0' };
1104   static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
1105     'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
1106   static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
1107   static const WCHAR szUpdate[] = { 'I','E','A','K',
1108     'U','p','d','a','t','e','U','r','l','\0' };
1109   static const WCHAR szHelp[] = { 'I','E','A','K',
1110     'H','e','l','p','S','t','r','i','n','g','\0' };
1111   WCHAR buff[2084];
1112   HKEY hReg;
1113   DWORD dwType, dwLen;
1114
1115   TRACE("(%p,%ld)", lpszDest, dwDestLen);
1116
1117   if (!lpszDest)
1118     return FALSE;
1119
1120   *lpszDest = '\0';
1121
1122   /* Try the NT key first, followed by 95/98 key */
1123   if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
1124       RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
1125     return FALSE;
1126
1127   /* OS Version */
1128   buff[0] = '\0';
1129   dwLen = 30;
1130   if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1131   {
1132     DWORD dwStrLen = strlenW(buff);
1133     dwLen = 30 - dwStrLen;
1134     SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1135                 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1136   }
1137   StrCatBuffW(lpszDest, buff, dwDestLen);
1138
1139   /* ~Registered Owner */
1140   buff[0] = '~';
1141   dwLen = 256;
1142   if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
1143     buff[1] = '\0';
1144   StrCatBuffW(lpszDest, buff, dwDestLen);
1145
1146   /* ~Registered Organization */
1147   dwLen = 256;
1148   if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
1149     buff[1] = '\0';
1150   StrCatBuffW(lpszDest, buff, dwDestLen);
1151
1152   /* FIXME: Not sure where this number comes from  */
1153   buff[0] = '~';
1154   buff[1] = '0';
1155   buff[2] = '\0';
1156   StrCatBuffW(lpszDest, buff, dwDestLen);
1157
1158   /* ~Product Id */
1159   dwLen = 256;
1160   if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1161     buff[1] = '\0';
1162   StrCatBuffW(lpszDest, buff, dwDestLen);
1163
1164   /* ~IE Update Url */
1165   dwLen = 2048;
1166   if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1167     buff[1] = '\0';
1168   StrCatBuffW(lpszDest, buff, dwDestLen);
1169
1170   /* ~IE Help String */
1171   dwLen = 256;
1172   if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1173     buff[1] = '\0';
1174   StrCatBuffW(lpszDest, buff, dwDestLen);
1175
1176   RegCloseKey(hReg);
1177   return TRUE;
1178 }
1179
1180 /*************************************************************************
1181  *      @       [SHLWAPI.162]
1182  *
1183  * Remove a hanging lead byte from the end of a string, if present.
1184  *
1185  * PARAMS
1186  *  lpStr [I] String to check for a hanging lead byte
1187  *  size  [I] Length of lpStr
1188  *
1189  * RETURNS
1190  *  Success: The new length of the string. Any hanging lead bytes are removed.
1191  *  Failure: 0, if any parameters are invalid.
1192  */
1193 DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
1194 {
1195   if (lpStr && size)
1196   {
1197     LPSTR lastByte = lpStr + size - 1;
1198
1199     while(lpStr < lastByte)
1200       lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
1201
1202     if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
1203     {
1204       *lpStr = '\0';
1205       size--;
1206     }
1207     return size;
1208   }
1209   return 0;
1210 }
1211
1212 /*************************************************************************
1213  *      @       [SHLWAPI.163]
1214  *
1215  * Call IOleCommandTarget_QueryStatus() on an object.
1216  *
1217  * PARAMS
1218  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
1219  *  pguidCmdGroup [I] GUID for the command group
1220  *  cCmds         [I]
1221  *  prgCmds       [O] Commands
1222  *  pCmdText      [O] Command text
1223  *
1224  * RETURNS
1225  *  Success: S_OK.
1226  *  Failure: E_FAIL, if lpUnknown is NULL.
1227  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1228  *           Otherwise, an error code from IOleCommandTarget_QueryStatus().
1229  */
1230 HRESULT WINAPI SHLWAPI_163(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1231                            ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1232 {
1233   HRESULT hRet = E_FAIL;
1234
1235   TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1236
1237   if (lpUnknown)
1238   {
1239     IOleCommandTarget* lpOle;
1240
1241     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1242                                    (void**)&lpOle);
1243
1244     if (SUCCEEDED(hRet) && lpOle)
1245     {
1246       hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1247                                            prgCmds, pCmdText);
1248       IOleCommandTarget_Release(lpOle);
1249     }
1250   }
1251   return hRet;
1252 }
1253
1254 /*************************************************************************
1255  *      @               [SHLWAPI.164]
1256  *
1257  * Call IOleCommandTarget_Exec() on an object.
1258  *
1259  * PARAMS
1260  *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
1261  *  pguidCmdGroup [I] GUID for the command group
1262  *
1263  * RETURNS
1264  *  Success: S_OK.
1265  *  Failure: E_FAIL, if lpUnknown is NULL.
1266  *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1267  *           Otherwise, an error code from IOleCommandTarget_Exec().
1268  */
1269 HRESULT WINAPI SHLWAPI_164(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1270                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1271                            VARIANT* pvaOut)
1272 {
1273   HRESULT hRet = E_FAIL;
1274
1275   TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1276         nCmdexecopt, pvaIn, pvaOut);
1277
1278   if (lpUnknown)
1279   {
1280     IOleCommandTarget* lpOle;
1281
1282     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1283                                    (void**)&lpOle);
1284     if (SUCCEEDED(hRet) && lpOle)
1285     {
1286       hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1287                                     nCmdexecopt, pvaIn, pvaOut);
1288       IOleCommandTarget_Release(lpOle);
1289     }
1290   }
1291   return hRet;
1292 }
1293
1294 /*************************************************************************
1295  *      @       [SHLWAPI.165]
1296  *
1297  * Retrieve, modify, and re-set a value from a window.
1298  *
1299  * PARAMS
1300  *  hWnd   [I] Window to get value from
1301  *  offset [I] Offset of value
1302  *  wMask  [I] Mask for uiFlags
1303  *  wFlags [I] Bits to set in window value
1304  *
1305  * RETURNS
1306  *  The new value as it was set, or 0 if any parameter is invalid.
1307  *
1308  * NOTES
1309  *  Any bits set in uiMask are cleared from the value, then any bits set in
1310  *  uiFlags are set in the value.
1311  */
1312 LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1313 {
1314   LONG ret = GetWindowLongA(hwnd, offset);
1315   LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1316
1317   if (newFlags != ret)
1318     ret = SetWindowLongA(hwnd, offset, newFlags);
1319   return ret;
1320 }
1321
1322 /*************************************************************************
1323  *      @       [SHLWAPI.167]
1324  *
1325  * Change a window's parent.
1326  *
1327  * PARAMS
1328  *  hWnd       [I] Window to change parent of
1329  *  hWndParent [I] New parent window
1330  *
1331  * RETURNS
1332  *  The old parent of hWnd.
1333  *
1334  * NOTES
1335  *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1336  *  If hWndParent is NOT NULL then we set the WS_CHILD style.
1337  */
1338 HWND WINAPI SHLWAPI_167(HWND hWnd, HWND hWndParent)
1339 {
1340   TRACE("%p, %p\n", hWnd, hWndParent);
1341
1342   if(GetParent(hWnd) == hWndParent)
1343     return 0;
1344
1345   if(hWndParent)
1346     SHLWAPI_165(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1347   else
1348     SHLWAPI_165(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1349
1350   return SetParent(hWnd, hWndParent);
1351 }
1352
1353 /*************************************************************************
1354  *      @       [SHLWAPI.168]
1355  *
1356  * Locate and advise a connection point in an IConnectionPointContainer object.
1357  *
1358  * PARAMS
1359  *  lpUnkSink   [I] Sink for the connection point advise call
1360  *  riid        [I] REFIID of connection point to advise
1361  *  bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1362  *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface
1363  *  lpCookie    [O] Pointer to connection point cookie
1364  *  lppCP       [O] Destination for the IConnectionPoint found
1365  *
1366  * RETURNS
1367  *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1368  *           that was advised. The caller is responsable for releasing it.
1369  *  Failure: E_FAIL, if any arguments are invalid.
1370  *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1371  *           Or an HRESULT error code if any call fails.
1372  */
1373 HRESULT WINAPI SHLWAPI_168(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1374                            IUnknown* lpUnknown, LPDWORD lpCookie,
1375                            IConnectionPoint **lppCP)
1376 {
1377   HRESULT hRet;
1378   IConnectionPointContainer* lpContainer;
1379   IConnectionPoint *lpCP;
1380
1381   if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1382     return E_FAIL;
1383
1384   if(lppCP)
1385     *lppCP = NULL;
1386
1387   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1388                                  (void**)&lpContainer);
1389   if (SUCCEEDED(hRet))
1390   {
1391     hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1392
1393     if (SUCCEEDED(hRet))
1394     {
1395       if(!bAdviseOnly)
1396         hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1397       hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1398
1399       if (FAILED(hRet))
1400         *lpCookie = 0;
1401
1402       if (lppCP && SUCCEEDED(hRet))
1403         *lppCP = lpCP; /* Caller keeps the interface */
1404       else
1405         IConnectionPoint_Release(lpCP); /* Release it */
1406     }
1407
1408     IUnknown_Release(lpContainer);
1409   }
1410   return hRet;
1411 }
1412
1413 /*************************************************************************
1414  *      @       [SHLWAPI.169]
1415  *
1416  * Release an interface.
1417  *
1418  * PARAMS
1419  *  lpUnknown [I] Object to release
1420  *
1421  * RETURNS
1422  *  Nothing.
1423  */
1424 DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
1425 {
1426         IUnknown *temp;
1427
1428         TRACE("(%p)\n",lpUnknown);
1429         if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1430         temp = *lpUnknown;
1431         *lpUnknown = NULL;
1432         TRACE("doing Release\n");
1433         return IUnknown_Release(temp);
1434 }
1435
1436 /*************************************************************************
1437  *      @       [SHLWAPI.170]
1438  *
1439  * Skip '//' if present in a string.
1440  *
1441  * PARAMS
1442  *  lpszSrc [I] String to check for '//'
1443  *
1444  * RETURNS
1445  *  Success: The next character after the '//' or the string if not present
1446  *  Failure: NULL, if lpszStr is NULL.
1447  */
1448 LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
1449 {
1450   if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1451     lpszSrc += 2;
1452   return lpszSrc;
1453 }
1454
1455 /*************************************************************************
1456  *      @               [SHLWAPI.171]
1457  *
1458  * Check if two interfaces come from the same object.
1459  *
1460  * PARAMS
1461  *   lpInt1 [I] Interface to check against lpInt2.
1462  *   lpInt2 [I] Interface to check against lpInt1.
1463  *
1464  * RETURNS
1465  *   TRUE, If the interfaces come from the same object.
1466  *   FALSE Otherwise.
1467  */
1468 BOOL WINAPI SHLWAPI_171(IUnknown* lpInt1, IUnknown* lpInt2)
1469 {
1470   LPVOID lpUnknown1, lpUnknown2;
1471
1472   TRACE("%p %p\n", lpInt1, lpInt2);
1473
1474   if (!lpInt1 || !lpInt2)
1475     return FALSE;
1476
1477   if (lpInt1 == lpInt2)
1478     return TRUE;
1479
1480   if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1481                                        (LPVOID *)&lpUnknown1)))
1482     return FALSE;
1483
1484   if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1485                                        (LPVOID *)&lpUnknown2)))
1486     return FALSE;
1487
1488   if (lpUnknown1 == lpUnknown2)
1489     return TRUE;
1490   
1491   return FALSE;
1492 }
1493
1494 /*************************************************************************
1495  *      @       [SHLWAPI.172]
1496  *
1497  * Get the window handle of an object.
1498  *
1499  * PARAMS
1500  *  lpUnknown [I] Object to get the window handle of
1501  *  lphWnd    [O] Destination for window handle
1502  *
1503  * RETURNS
1504  *  Success: S_OK. lphWnd contains the objects window handle.
1505  *  Failure: An HRESULT error code.
1506  *
1507  * NOTES
1508  *  lpUnknown is expected to support one of the following interfaces:
1509  *  IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1510  */
1511 HRESULT WINAPI SHLWAPI_172(IUnknown *lpUnknown, HWND *lphWnd)
1512 {
1513   /* FIXME: Wine has no header for this object */
1514   static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1515     0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1516   IUnknown *lpOle;
1517   HRESULT hRet = E_FAIL;
1518
1519   TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1520
1521   if (!lpUnknown)
1522     return hRet;
1523
1524   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1525
1526   if (FAILED(hRet))
1527   {
1528     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1529
1530     if (FAILED(hRet))
1531     {
1532       hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1533                                       (void**)&lpOle);
1534     }
1535   }
1536
1537   if (SUCCEEDED(hRet))
1538   {
1539     /* Lazyness here - Since GetWindow() is the first method for the above 3
1540      * interfaces, we use the same call for them all.
1541      */
1542     hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1543     IUnknown_Release(lpOle);
1544     if (lphWnd)
1545       TRACE("Returning HWND=%p\n", *lphWnd);
1546   }
1547
1548   return hRet;
1549 }
1550
1551 /*************************************************************************
1552  *      @       [SHLWAPI.173]
1553  *
1554  * Call a method on as as yet unidentified object.
1555  *
1556  * PARAMS
1557  *  pUnk [I] Object supporting the unidentified interface,
1558  *  arg  [I] Argument for the call on the object.
1559  *
1560  * RETURNS
1561  *  S_OK.
1562  */
1563 HRESULT WINAPI SHLWAPI_173(IUnknown *pUnk, ULONG arg)
1564 {
1565   static const GUID guid_173 = {
1566     0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1567   };
1568   IMalloc *pUnk2;
1569
1570   TRACE("(%p,%ld)\n", pUnk, arg);
1571
1572   /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1573    *       We use this interface as its vtable entry is compatible with the
1574    *       object in question.
1575    * FIXME: Find out what this object is and where it should be defined.
1576    */
1577   if (pUnk &&
1578       SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1579   {
1580     IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1581     IMalloc_Release(pUnk2);
1582   }
1583   return S_OK;
1584 }
1585
1586 /*************************************************************************
1587  *      @       [SHLWAPI.174]
1588  *
1589  * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
1590  * an interface.
1591  *
1592  * RETURNS
1593  *  Success: S_OK.
1594  *  Failure: E_FAIL, if p1 is NULL.
1595  *           E_NOINTERFACE If p1 does not support the IPersist interface,
1596  *           Or an HRESULT error code.
1597  */
1598 DWORD WINAPI SHLWAPI_174(
1599         IUnknown *p1,     /* [in]   OLE object                          */
1600         LPVOID *p2)       /* [out]  ptr for call results */
1601 {
1602     DWORD ret, aa;
1603
1604     if (!p1) return E_FAIL;
1605
1606     /* see if SetSite interface exists for IObjectWithSite object */
1607     ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1608     TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1609     if (ret) {
1610
1611         /* see if GetClassId interface exists for IPersistMoniker object */
1612         ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1613         TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1614         if (ret) return ret;
1615
1616         /* fake a GetClassId call */
1617         ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1618         TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1619               *(LPDWORD)p2);
1620         IUnknown_Release((IUnknown *)aa);
1621     }
1622     else {
1623         /* fake a SetSite call */
1624         ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1625         TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1626               *(LPDWORD)p2);
1627         IUnknown_Release((IUnknown *)p1);
1628     }
1629     return ret;
1630 }
1631
1632 /*************************************************************************
1633  *      @       [SHLWAPI.175]
1634  *
1635  * Call IPersist_GetClassID() on an object.
1636  *
1637  * PARAMS
1638  *  lpUnknown [I] Object supporting the IPersist interface
1639  *  lpClassId [O] Destination for Class Id
1640  *
1641  * RETURNS
1642  *  Success: S_OK. lpClassId contains the Class Id requested.
1643  *  Failure: E_FAIL, If lpUnknown is NULL,
1644  *           E_NOINTERFACE If lpUnknown does not support IPersist,
1645  *           Or an HRESULT error code.
1646  */
1647 HRESULT WINAPI SHLWAPI_175 (IUnknown *lpUnknown, CLSID* lpClassId)
1648 {
1649   IPersist* lpPersist;
1650   HRESULT hRet = E_FAIL;
1651
1652   TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1653
1654   if (lpUnknown)
1655   {
1656     hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1657     if (SUCCEEDED(hRet))
1658     {
1659       IPersist_GetClassID(lpPersist, lpClassId);
1660       IPersist_Release(lpPersist);
1661     }
1662   }
1663   return hRet;
1664 }
1665
1666 /*************************************************************************
1667  *      @       [SHLWAPI.176]
1668  *
1669  * Retrieve a Service Interface from an object.
1670  *
1671  * PARAMS
1672  *  lpUnknown [I] Object to get an IServiceProvider interface from
1673  *  sid       [I] Service ID for IServiceProvider_QueryService() call
1674  *  riid      [I] Function requested for QueryService call
1675  *  lppOut    [O] Destination for the service interface pointer
1676  *
1677  * RETURNS
1678  *  Success: S_OK. lppOut contains an object providing the requested service
1679  *  Failure: An HRESULT error code
1680  *
1681  * NOTES
1682  *  lpUnknown is expected to support the IServiceProvider interface.
1683  */
1684 HRESULT WINAPI SHLWAPI_176(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1685                            LPVOID *lppOut)
1686 {
1687   IServiceProvider* pService = NULL;
1688   HRESULT hRet;
1689
1690   if (!lppOut)
1691     return E_FAIL;
1692
1693   *lppOut = NULL;
1694
1695   if (!lpUnknown)
1696     return E_FAIL;
1697
1698   /* Get an IServiceProvider interface from the object */
1699   hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1700                                  (LPVOID*)&pService);
1701
1702   if (!hRet && pService)
1703   {
1704     TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1705
1706     /* Get a Service interface from the object */
1707     hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1708
1709     TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1710
1711     /* Release the IServiceProvider interface */
1712     IUnknown_Release(pService);
1713   }
1714   return hRet;
1715 }
1716
1717 /*************************************************************************
1718  *      @       [SHLWAPI.177]
1719  *
1720  * Destroy a menu.
1721  *
1722  * PARAMS
1723  *  hInst  [I] Instance handle
1724  *  szName [I] Menu name
1725  *
1726  * RETURNS
1727  *  Success: TRUE.
1728  *  Failure: FALSE.
1729  */
1730 BOOL WINAPI SHLWAPI_177(HINSTANCE hInst, LPCWSTR szName)
1731 {
1732   HMENU hMenu, hSubMenu;
1733
1734   if ((hMenu = LoadMenuW(hInst, szName)))
1735   {
1736     if ((hSubMenu = GetSubMenu(hMenu, 0)))
1737       RemoveMenu(hMenu, 0, MF_BYPOSITION);
1738
1739     DestroyMenu(hMenu); /* FIXME: Should be: SHLWAPI_426(hMenu); */
1740     return TRUE;
1741   }
1742   return FALSE;
1743 }
1744
1745 typedef struct _enumWndData
1746 {
1747   UINT   uiMsgId;
1748   WPARAM wParam;
1749   LPARAM lParam;
1750   LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1751 } enumWndData;
1752
1753 /* Callback for SHLWAPI_178 */
1754 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1755 {
1756   enumWndData *data = (enumWndData *)lParam;
1757
1758   TRACE("(%p,%p)\n", hWnd, data);
1759   data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1760   return TRUE;
1761 }
1762
1763 /*************************************************************************
1764  * @  [SHLWAPI.178]
1765  *
1766  * Send or post a message to every child of a window.
1767  *
1768  * PARAMS
1769  *  hWnd    [I] Window whose children will get the messages
1770  *  uiMsgId [I] Message Id
1771  *  wParam  [I] WPARAM of message
1772  *  lParam  [I] LPARAM of message
1773  *  bSend   [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1774  *
1775  * RETURNS
1776  *  Nothing.
1777  *
1778  * NOTES
1779  *  The appropriate ASCII or Unicode function is called for the window.
1780  */
1781 void WINAPI SHLWAPI_178(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1782 {
1783   enumWndData data;
1784
1785   TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1786
1787   if(hWnd)
1788   {
1789     data.uiMsgId = uiMsgId;
1790     data.wParam  = wParam;
1791     data.lParam  = lParam;
1792
1793     if (bSend)
1794       data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1795     else
1796       data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1797
1798     EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1799   }
1800 }
1801
1802 /*************************************************************************
1803  *      @       [SHLWAPI.180]
1804  *
1805  * Remove all sub-menus from a menu.
1806  *
1807  * PARAMS
1808  *  hMenu [I] Menu to remove sub-menus from
1809  *
1810  * RETURNS
1811  *  Success: 0.  All sub-menus under hMenu are removed
1812  *  Failure: -1, if any parameter is invalid
1813  */
1814 DWORD WINAPI SHLWAPI_180(HMENU hMenu)
1815 {
1816   int iItemCount = GetMenuItemCount(hMenu) - 1;
1817   while (iItemCount >= 0)
1818   {
1819     HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1820     if (hSubMenu)
1821       RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1822     iItemCount--;
1823   }
1824   return iItemCount;
1825 }
1826
1827 /*************************************************************************
1828  *      @       [SHLWAPI.181]
1829  *
1830  * Enable or disable a menu item.
1831  *
1832  * PARAMS
1833  *  hMenu   [I] Menu holding menu item
1834  *  uID     [I] ID of menu item to enable/disable
1835  *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1836  *
1837  * RETURNS
1838  *  The return code from EnableMenuItem.
1839  */
1840 UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
1841 {
1842   return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1843 }
1844
1845 /*************************************************************************
1846  * @    [SHLWAPI.182]
1847  *
1848  * Check or uncheck a menu item.
1849  *
1850  * PARAMS
1851  *  hMenu  [I] Menu holding menu item
1852  *  uID    [I] ID of menu item to check/uncheck
1853  *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1854  *
1855  * RETURNS
1856  *  The return code from CheckMenuItem.
1857  */
1858 DWORD WINAPI SHLWAPI_182(HMENU hMenu, UINT uID, BOOL bCheck)
1859 {
1860   return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1861 }
1862
1863 /*************************************************************************
1864  *      @       [SHLWAPI.183]
1865  *
1866  * Register a window class if it isn't already.
1867  *
1868  * PARAMS
1869  *  lpWndClass [I] Window class to register
1870  *
1871  * RETURNS
1872  *  The result of the RegisterClassA call.
1873  */
1874 DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
1875 {
1876   WNDCLASSA wca;
1877   if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1878     return TRUE;
1879   return (DWORD)RegisterClassA(wndclass);
1880 }
1881
1882 /*************************************************************************
1883  *      @       [SHLWAPI.187]
1884  *
1885  * Call IPersistPropertyBag_Load() on an object.
1886  *
1887  * PARAMS
1888  *  lpUnknown [I] Object supporting the IPersistPropertyBag interface
1889  *  lpPropBag [O] Destination for loaded IPropertyBag
1890  *
1891  * RETURNS
1892  *  Success: S_OK.
1893  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1894  */
1895 DWORD WINAPI SHLWAPI_187(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1896 {
1897   IPersistPropertyBag* lpPPBag;
1898   HRESULT hRet = E_FAIL;
1899
1900   TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1901
1902   if (lpUnknown)
1903   {
1904     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1905                                    (void**)&lpPPBag);
1906     if (SUCCEEDED(hRet) && lpPPBag)
1907     {
1908       hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1909       IPersistPropertyBag_Release(lpPPBag);
1910     }
1911   }
1912   return hRet;
1913 }
1914
1915 /*************************************************************************
1916  * @  [SHLWAPI.189]
1917  *
1918  * Call IOleControlSite_GetExtendedControl() on an object.
1919  *
1920  * PARAMS
1921  *  lpUnknown [I] Object supporting the IOleControlSite interface
1922  *  lppDisp   [O] Destination for resulting IDispatch.
1923  *
1924  * RETURNS
1925  *  Success: S_OK.
1926  *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1927  */
1928 DWORD WINAPI SHLWAPI_189(IUnknown *lpUnknown, IDispatch** lppDisp)
1929 {
1930   IOleControlSite* lpCSite;
1931   HRESULT hRet = E_FAIL;
1932
1933   TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1934   if (lpUnknown)
1935   {
1936     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1937                                    (void**)&lpCSite);
1938     if (SUCCEEDED(hRet) && lpCSite)
1939     {
1940       hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1941       IOleControlSite_Release(lpCSite);
1942     }
1943   }
1944   return hRet;
1945 }
1946
1947 static const WCHAR szDontShowKey[] = { 'S','o','f','t','w','a','r','e','\\',
1948   'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1949   'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
1950   'E','x','p','l','o','r','e','r','\\','D','o','n','t','S','h','o','w',
1951   'M','e','T','h','i','s','D','i','a','l','o','g','A','g','a','i','n','\0'
1952 };
1953
1954 /*************************************************************************
1955  * @    [SHLWAPI.191]
1956  *
1957  * Pop up a 'Don't show this message again' error dialog box.
1958  *
1959  * PARAMS
1960  *  hWnd      [I] Window to own the dialog box
1961  *  arg2      [I] Unknown
1962  *  arg3      [I] Unknown
1963  *  arg4      [I] Unknown
1964  *  arg5      [I] Unknown
1965  *  lpszValue [I] Registry value holding boolean show/don't show.
1966  *
1967  * RETURNS
1968  *  Nothing.
1969  */
1970 void WINAPI SHLWAPI_191(HWND hWnd, PVOID arg2, PVOID arg3, PVOID arg4, PVOID arg5, LPCWSTR lpszValue)
1971 {
1972   FIXME("(%p,%p,%p,%p,%p,%s) - stub!\n", hWnd, arg2, arg3, arg4, arg5, debugstr_w(lpszValue));
1973
1974   if (SHRegGetBoolUSValueW(szDontShowKey, lpszValue, FALSE, TRUE))
1975   {
1976     /* FIXME: Should use DialogBoxParamW to load a dialog box; its dlgproc
1977      * should accept clicks on 'Don't show' and set the reg value appropriately.
1978      */
1979   }
1980 }
1981
1982 /*************************************************************************
1983  * @    [SHLWAPI.192]
1984  *
1985  * Get a sub-menu from a menu item.
1986  *
1987  * PARAMS
1988  *  hMenu [I] Menu to get sub-menu from
1989  *  uID   [I] ID of menu item containing sub-menu
1990  *
1991  * RETURNS
1992  *  The sub-menu of the item, or a NULL handle if any parameters are invalid.
1993  */
1994 HMENU WINAPI SHLWAPI_192(HMENU hMenu, UINT uID)
1995 {
1996   MENUITEMINFOA mi;
1997
1998   TRACE("(%p,%uld)\n", hMenu, uID);
1999
2000   mi.cbSize = sizeof(MENUITEMINFOA);
2001   mi.fMask = MIIM_SUBMENU;
2002
2003   if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
2004     return (HMENU)NULL;
2005
2006   return mi.hSubMenu;
2007 }
2008
2009 /*************************************************************************
2010  *      @       [SHLWAPI.193]
2011  *
2012  * Get the color depth of the primary display.
2013  *
2014  * PARAMS
2015  *  None.
2016  *
2017  * RETURNS
2018  *  The color depth of the primary display.
2019  */
2020 DWORD WINAPI SHLWAPI_193 ()
2021 {
2022         HDC hdc;
2023         DWORD ret;
2024
2025         TRACE("()\n");
2026
2027         hdc = GetDC(0);
2028         ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
2029         ReleaseDC(0, hdc);
2030         return ret;
2031 }
2032
2033 /*************************************************************************
2034  *      @       [SHLWAPI.197]
2035  *
2036  * Blank out a region of text by drawing the background only.
2037  *
2038  * PARAMS
2039  *  hDC   [I] Device context to draw in
2040  *  pRect [I] Area to draw in
2041  *  cRef  [I] Color to draw in
2042  *
2043  * RETURNS
2044  *  Nothing.
2045  */
2046 DWORD WINAPI SHLWAPI_197(HDC hDC, LPCRECT pRect, COLORREF cRef)
2047 {
2048     COLORREF cOldColor = SetBkColor(hDC, cRef);
2049     ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2050     SetBkColor(hDC, cOldColor);
2051     return 0;
2052 }
2053
2054 /*************************************************************************
2055  *      @       [SHLWAPI.199]
2056  *
2057  * Copy an interface pointer
2058  *
2059  * PARAMS
2060  *   lppDest   [O] Destination for copy
2061  *   lpUnknown [I] Source for copy
2062  *
2063  * RETURNS
2064  *  Nothing.
2065  */
2066 VOID WINAPI SHLWAPI_199(IUnknown **lppDest, IUnknown *lpUnknown)
2067 {
2068   TRACE("(%p,%p)\n", lppDest, lpUnknown);
2069
2070   if (lppDest)
2071     SHLWAPI_169(lppDest); /* Release existing interface */
2072
2073   if (lpUnknown)
2074   {
2075     /* Copy */
2076     IUnknown_AddRef(lpUnknown);
2077     *lppDest = lpUnknown;
2078   }
2079 }
2080
2081 /*************************************************************************
2082  *      @       [SHLWAPI.201]
2083  *
2084  */
2085 HRESULT WINAPI SHLWAPI_201(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2086                            DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2087                            VARIANT* pvaOut)
2088 {
2089   FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2090         nCmdID, nCmdexecopt, pvaIn, pvaOut);
2091   return DRAGDROP_E_NOTREGISTERED;
2092 }
2093
2094 /*************************************************************************
2095  *      @       [SHLWAPI.202]
2096  *
2097  */
2098 HRESULT WINAPI SHLWAPI_202(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2099 {
2100   FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2101   return DRAGDROP_E_NOTREGISTERED;
2102 }
2103
2104 /*************************************************************************
2105  * @    [SHLWAPI.204]
2106  *
2107  * Determine if a window is not a child of another window.
2108  *
2109  * PARAMS
2110  * hParent [I] Suspected parent window
2111  * hChild  [I] Suspected child window
2112  *
2113  * RETURNS
2114  * TRUE:  If hChild is a child window of hParent
2115  * FALSE: If hChild is not a child window of hParent, or they are equal
2116  */
2117 BOOL WINAPI SHLWAPI_204(HWND hParent, HWND hChild)
2118 {
2119   TRACE("(%p,%p)\n", hParent, hChild);
2120
2121   if (!hParent || !hChild)
2122     return TRUE;
2123   else if(hParent == hChild)
2124     return FALSE;
2125   return !IsChild(hParent, hChild);
2126 }
2127
2128 /*************************************************************************
2129  *      @       [SHLWAPI.208]
2130  *
2131  * Some sort of memory management process - associated with _210
2132  */
2133 DWORD WINAPI SHLWAPI_208 (
2134         DWORD    a,
2135         DWORD    b,
2136         LPVOID   c,
2137         LPVOID   d,
2138         DWORD    e)
2139 {
2140     FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2141           a, b, c, d, e);
2142     return 1;
2143 }
2144
2145 /*************************************************************************
2146  *      @       [SHLWAPI.209]
2147  *
2148  * Some sort of memory management process - associated with _208
2149  */
2150 DWORD WINAPI SHLWAPI_209 (
2151         LPVOID   a)
2152 {
2153     FIXME("(%p) stub\n",
2154           a);
2155     return 1;
2156 }
2157
2158 /*************************************************************************
2159  *      @       [SHLWAPI.210]
2160  *
2161  * Some sort of memory management process - associated with _208
2162  */
2163 DWORD WINAPI SHLWAPI_210 (
2164         LPVOID   a,
2165         DWORD    b,
2166         LPVOID   c)
2167 {
2168     FIXME("(%p 0x%08lx %p) stub\n",
2169           a, b, c);
2170     return 0;
2171 }
2172
2173 /*************************************************************************
2174  *      @       [SHLWAPI.211]
2175  */
2176 DWORD WINAPI SHLWAPI_211 (
2177         LPVOID   a,
2178         DWORD    b)
2179 {
2180     FIXME("(%p 0x%08lx) stub\n",
2181           a, b);
2182     return 1;
2183 }
2184
2185 /*************************************************************************
2186  *      @       [SHLWAPI.215]
2187  *
2188  * NOTES
2189  *  check me!
2190  */
2191 DWORD WINAPI SHLWAPI_215 (
2192         LPCSTR lpStrSrc,
2193         LPWSTR lpwStrDest,
2194         int len)
2195 {
2196         INT len_a, ret;
2197
2198         len_a = lstrlenA(lpStrSrc);
2199         ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
2200         TRACE("%s %s %d, ret=%d\n",
2201               debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
2202         return ret;
2203 }
2204
2205 /*************************************************************************
2206  *      @       [SHLWAPI.218]
2207  *
2208  * WideCharToMultiByte with support for multiple codepages.
2209  *
2210  * PARAMS
2211  *  CodePage          [I] Code page to use for the conversion
2212  *  lpSrcStr          [I] Source Unicode string to convert
2213  *  lpDstStr          [O] Destination for converted Ascii string
2214  *  lpnMultiCharCount [O] Input length of lpDstStr/destination for length of lpDstStr
2215  *
2216  * RETURNS
2217  *  Success: The number of characters that result from the conversion.
2218  *  Failure: 0.
2219  */
2220 INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
2221                        LPINT lpnMultiCharCount)
2222 {
2223   WCHAR emptyW[] = { '\0' };
2224   int len , reqLen;
2225   LPSTR mem;
2226
2227   if (!lpDstStr || !lpnMultiCharCount)
2228     return 0;
2229
2230   if (!lpSrcStr)
2231     lpSrcStr = emptyW;
2232
2233   *lpDstStr = '\0';
2234
2235   len = strlenW(lpSrcStr) + 1;
2236
2237   switch (CodePage)
2238   {
2239   case CP_WINUNICODE:
2240     CodePage = CP_UTF8; /* Fall through... */
2241   case 0x0000C350: /* FIXME: CP_ #define */
2242   case CP_UTF7:
2243   case CP_UTF8:
2244     {
2245       DWORD dwMode = 0;
2246       INT nWideCharCount = len - 1;
2247
2248       GET_FUNC(pConvertINetUnicodeToMultiByte, mlang, "ConvertINetUnicodeToMultiByte", 0);
2249       if (!pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
2250                                           lpnMultiCharCount))
2251         return 0;
2252
2253       if (nWideCharCount < len - 1)
2254       {
2255         mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
2256         if (!mem)
2257           return 0;
2258
2259         *lpnMultiCharCount = 0;
2260
2261         if (pConvertINetUnicodeToMultiByte(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
2262         {
2263           SHLWAPI_162 (mem, *lpnMultiCharCount);
2264           lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
2265           return *lpnMultiCharCount + 1;
2266         }
2267         HeapFree(GetProcessHeap(), 0, mem);
2268         return *lpnMultiCharCount;
2269       }
2270       lpDstStr[*lpnMultiCharCount] = '\0';
2271       return *lpnMultiCharCount;
2272     }
2273     break;
2274   default:
2275     break;
2276   }
2277
2278   reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
2279                                *lpnMultiCharCount, NULL, NULL);
2280
2281   if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
2282   {
2283     reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
2284     if (reqLen)
2285     {
2286       mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
2287       if (mem)
2288       {
2289         reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
2290                                      reqLen, NULL, NULL);
2291
2292         reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
2293         reqLen++;
2294
2295         lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
2296
2297         HeapFree(GetProcessHeap(), 0, mem);
2298       }
2299     }
2300   }
2301   return reqLen;
2302 }
2303
2304 /*************************************************************************
2305  *      @       [SHLWAPI.217]
2306  *
2307  * WideCharToMultiByte with support for multiple codepages.
2308  *
2309  * PARAMS
2310  *  lpSrcStr          [I] Source Unicode string to convert
2311  *  lpDstStr          [O] Destination for converted Ascii string
2312  *  lpnMultiCharCount [O] Input length of lpDstStr/destination for length of lpDstStr
2313  *
2314  * RETURNS
2315  *  See SHLWAPI_218.
2316
2317  * NOTES
2318  *  This function simply calls SHLWAPI_218() with CodePage = CP_ACP.
2319  */
2320 INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
2321 {
2322     INT myint = MultiCharCount;
2323
2324     return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
2325 }
2326
2327 typedef struct {
2328     REFIID   refid;
2329     DWORD    indx;
2330 } IFACE_INDEX_TBL;
2331
2332 /*************************************************************************
2333  *      @       [SHLWAPI.219]
2334  *
2335  * Call IUnknown_QueryInterface() on a table of objects.
2336  *
2337  * RETURNS
2338  *  Success: S_OK.
2339  *  Failure: E_POINTER or E_NOINTERFACE.
2340  */
2341 HRESULT WINAPI SHLWAPI_219 (
2342         LPVOID w,           /* [in]   Table of interfaces */
2343         IFACE_INDEX_TBL *x, /* [in]   Array of REFIIDs and indexes into the table */
2344         REFIID riid,        /* [in]   REFIID to get interface for */
2345         LPVOID *ppv)          /* [out]  Destination for interface pointer */
2346 {
2347         HRESULT ret;
2348         IUnknown *a_vtbl;
2349         IFACE_INDEX_TBL *xmove;
2350
2351         TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2352         if (ppv) {
2353             xmove = x;
2354             while (xmove->refid) {
2355                 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2356                 if (IsEqualIID(riid, xmove->refid)) {
2357                     a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2358                     TRACE("matched, returning (%p)\n", a_vtbl);
2359                     *ppv = (LPVOID)a_vtbl;
2360                     IUnknown_AddRef(a_vtbl);
2361                     return S_OK;
2362                 }
2363                 xmove++;
2364             }
2365
2366             if (IsEqualIID(riid, &IID_IUnknown)) {
2367                 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2368                 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2369                 *ppv = (LPVOID)a_vtbl;
2370                 IUnknown_AddRef(a_vtbl);
2371                 return S_OK;
2372             }
2373             *ppv = 0;
2374             ret = E_NOINTERFACE;
2375         } else
2376             ret = E_POINTER;
2377
2378         TRACE("-- 0x%08lx\n", ret);
2379         return ret;
2380 }
2381
2382 /*************************************************************************
2383  *      @       [SHLWAPI.221]
2384  *
2385  * Remove the "PropDlgFont" property from a window.
2386  *
2387  * PARAMS
2388  *  hWnd [I] Window to remove the property from
2389  *
2390  * RETURNS
2391  *  A handle to the removed property, or NULL if it did not exist.
2392  */
2393 HANDLE WINAPI SHLWAPI_221(HWND hWnd)
2394 {
2395   HANDLE hProp;
2396
2397   TRACE("(%p)\n", hWnd);
2398
2399   hProp = GetPropA(hWnd, "PropDlgFont");
2400
2401   if(hProp)
2402   {
2403     DeleteObject(hProp);
2404     hProp = RemovePropA(hWnd, "PropDlgFont");
2405   }
2406   return hProp;
2407 }
2408
2409 /*************************************************************************
2410  *      @       [SHLWAPI.236]
2411  *
2412  * Load the in-process server of a given GUID.
2413  *
2414  * PARAMS
2415  *  refiid [I] GUID of the server to load.
2416  *
2417  * RETURNS
2418  *  Success: A handle to the loaded server dll.
2419  *  Failure: A NULL handle.
2420  */
2421 HMODULE WINAPI SHLWAPI_236(REFIID refiid)
2422 {
2423     HKEY newkey;
2424     DWORD type, count;
2425     CHAR value[MAX_PATH], string[MAX_PATH];
2426
2427     strcpy(string, "CLSID\\");
2428     SHLWAPI_23(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2429     strcat(string, "\\InProcServer32");
2430
2431     count = MAX_PATH;
2432     RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2433     RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2434     RegCloseKey(newkey);
2435     return LoadLibraryExA(value, 0, 0);
2436 }
2437
2438 /*************************************************************************
2439  *      @       [SHLWAPI.237]
2440  *
2441  * Unicode version of SHLWAPI_183.
2442  */
2443 DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
2444 {
2445         WNDCLASSW WndClass;
2446
2447         TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2448
2449         if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2450                 return TRUE;
2451         return RegisterClassW(lpWndClass);
2452 }
2453
2454 /*************************************************************************
2455  *      SHLWAPI_238     [SHLWAPI.238]
2456  *
2457  * Unregister a list of classes.
2458  *
2459  * PARAMS
2460  *  hInst      [I] Application instance that registered the classes
2461  *  lppClasses [I] List of class names
2462  *  iCount     [I] Number of names in lppClasses
2463  *
2464  * RETURNS
2465  *  Nothing.
2466  */
2467 void WINAPI SHLWAPI_238(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2468 {
2469   WNDCLASSA WndClass;
2470
2471   TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2472
2473   while (iCount > 0)
2474   {
2475     if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2476       UnregisterClassA(*lppClasses, hInst);
2477     lppClasses++;
2478     iCount--;
2479   }
2480 }
2481
2482 /*************************************************************************
2483  *      SHLWAPI_239     [SHLWAPI.239]
2484  *
2485  * Unicode version of SHLWAPI_238.
2486  */
2487 void WINAPI SHLWAPI_239(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2488 {
2489   WNDCLASSW WndClass;
2490
2491   TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2492
2493   while (iCount > 0)
2494   {
2495     if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2496       UnregisterClassW(*lppClasses, hInst);
2497     lppClasses++;
2498     iCount--;
2499   }
2500 }
2501
2502 /*************************************************************************
2503  *      @       [SHLWAPI.240]
2504  *
2505  * Call The correct (Ascii/Unicode) default window procedure for a window.
2506  *
2507  * PARAMS
2508  *  hWnd     [I] Window to call the default procedure for
2509  *  uMessage [I] Message ID
2510  *  wParam   [I] WPARAM of message
2511  *  lParam   [I] LPARAM of message
2512  *
2513  * RETURNS
2514  *  The result of calling DefWindowProcA() or DefWindowProcW().
2515  */
2516 LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2517 {
2518         if (IsWindowUnicode(hWnd))
2519                 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2520         return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2521 }
2522
2523 /*************************************************************************
2524  *      @       [SHLWAPI.241]
2525  *
2526  */
2527 DWORD WINAPI SHLWAPI_241 ()
2528 {
2529         FIXME("()stub\n");
2530         return /* 0xabba1243 */ 0;
2531 }
2532
2533 /*************************************************************************
2534  *      @       [SHLWAPI.257]
2535  *
2536  * Create a worker window using CreateWindowExA().
2537  *
2538  * PARAMS
2539  *  wndProc    [I] Window procedure
2540  *  hWndParent [I] Parent window
2541  *  dwExStyle  [I] Extra style flags
2542  *  dwStyle    [I] Style flags
2543  *  hMenu      [I] Window menu
2544  *  z          [I] Unknown
2545  *
2546  * RETURNS
2547  *  Success: The window handle of the newly created window.
2548  *  Failure: 0.
2549  */
2550 HWND WINAPI SHLWAPI_257(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2551                         DWORD dwStyle, HMENU hMenu, LONG z)
2552 {
2553   static const char* szClass = "WorkerA";
2554   WNDCLASSA wc;
2555   HWND hWnd;
2556
2557   TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2558          wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2559
2560   /* Create Window class */
2561   wc.style         = 0;
2562   wc.lpfnWndProc   = DefWindowProcA;
2563   wc.cbClsExtra    = 0;
2564   wc.cbWndExtra    = 4;
2565   wc.hInstance     = shlwapi_hInstance;
2566   wc.hIcon         = (HICON)0;
2567   wc.hCursor       = LoadCursorA((HINSTANCE)0, IDC_ARROWA);
2568   wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2569   wc.lpszMenuName  = NULL;
2570   wc.lpszClassName = szClass;
2571
2572   SHLWAPI_183(&wc); /* Register class */
2573
2574   /* FIXME: Set extra bits in dwExStyle */
2575
2576   hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2577                          hWndParent, hMenu, shlwapi_hInstance, 0);
2578   if (hWnd)
2579   {
2580     SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2581
2582     if (wndProc)
2583       SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
2584   }
2585   return hWnd;
2586 }
2587
2588 typedef struct tagPOLICYDATA
2589 {
2590   DWORD policy;        /* flags value passed to SHRestricted */
2591   LPCWSTR appstr;      /* application str such as "Explorer" */
2592   LPCWSTR keystr;      /* name of the actual registry key / policy */
2593 } POLICYDATA, *LPPOLICYDATA;
2594
2595 #define SHELL_NO_POLICY 0xffffffff
2596
2597 /* default shell policy registry key */
2598 static WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2599                                       's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2600                                       'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2601                                       '\\','P','o','l','i','c','i','e','s',0};
2602
2603 /*************************************************************************
2604  * @                          [SHLWAPI.271]
2605  *
2606  * Retrieve a policy value from the registry.
2607  *
2608  * PARAMS
2609  *  lpSubKey   [I]   registry key name
2610  *  lpSubName  [I]   subname of registry key
2611  *  lpValue    [I]   value name of registry value
2612  *
2613  * RETURNS
2614  *  the value associated with the registry key or 0 if not found
2615  */
2616 DWORD WINAPI SHLWAPI_271(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2617 {
2618         DWORD retval, datsize = 4;
2619         HKEY hKey;
2620
2621         if (!lpSubKey)
2622           lpSubKey = (LPCWSTR)strRegistryPolicyW;
2623         
2624         retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2625     if (retval != ERROR_SUCCESS)
2626           retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2627         if (retval != ERROR_SUCCESS)
2628           return 0;
2629
2630         SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2631         RegCloseKey(hKey);
2632         return retval;  
2633 }
2634
2635 /*************************************************************************
2636  * @                         [SHLWAPI.266]
2637  *
2638  * Helper function to retrieve the possibly cached value for a specific policy
2639  *
2640  * PARAMS
2641  *  policy     [I]   The policy to look for
2642  *  initial    [I]   Main registry key to open, if NULL use default
2643  *  polTable   [I]   Table of known policies, 0 terminated
2644  *  polArr     [I]   Cache array of policy values
2645  *
2646  * RETURNS
2647  *  The retrieved policy value or 0 if not successful
2648  *
2649  * NOTES
2650  *  This function is used by the native SHRestricted function to search for the
2651  *  policy and cache it once retrieved. The current Wine implementation uses a
2652  *  different POLICYDATA structure and implements a similar algorithme adapted to
2653  *  that structure.
2654  */
2655 DWORD WINAPI SHLWAPI_266 (
2656         DWORD policy,
2657         LPCWSTR initial,
2658         LPPOLICYDATA polTable,
2659         LPDWORD polArr)
2660 {
2661         TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2662
2663         if (!polTable || !polArr)
2664           return 0;
2665
2666         for (;polTable->policy; polTable++, polArr++)
2667         {
2668           if (policy == polTable->policy)
2669           {
2670             /* we have a known policy */
2671
2672             /* check if this policy has been cached */
2673                 if (*polArr == SHELL_NO_POLICY)
2674               *polArr = SHLWAPI_271(initial, polTable->appstr, polTable->keystr);
2675             return *polArr;
2676           }
2677         }
2678         /* we don't know this policy, return 0 */
2679         TRACE("unknown policy: (%08lx)\n", policy);
2680         return 0;
2681 }
2682
2683 /*************************************************************************
2684  *      @       [SHLWAPI.267]
2685  *
2686  * Get an interface from an object.
2687  *
2688  * RETURNS
2689  *  Success: S_OK. ppv contains the requested interface.
2690  *  Failure: An HRESULT error code.
2691  *
2692  * NOTES
2693  *   This QueryInterface asks the inner object for a interface. In case
2694  *   of aggregation this request would be forwarded by the inner to the
2695  *   outer object. This function asks the inner object directly for the
2696  *   interface circumventing the forwarding to the outer object.
2697  */
2698 HRESULT WINAPI SHLWAPI_267 (
2699         IUnknown * pUnk,   /* [in] Outer object */
2700         IUnknown * pInner, /* [in] Inner object */
2701         IID * riid, /* [in] Interface GUID to query for */
2702         LPVOID* ppv) /* [out] Destination for queried interface */
2703 {
2704         HRESULT hret = E_NOINTERFACE;
2705         TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2706
2707         *ppv = NULL;
2708         if(pUnk && pInner) {
2709             hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2710             if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2711         }
2712         TRACE("-- 0x%08lx\n", hret);
2713         return hret;
2714 }
2715
2716 /*************************************************************************
2717  *      @       [SHLWAPI.268]
2718  *
2719  * Move a reference from one interface to another.
2720  *
2721  * PARAMS
2722  *   lpDest     [O] Destination to receive the reference
2723  *   lppUnknown [O] Source to give up the reference to lpDest
2724  *
2725  * RETURNS
2726  *  Nothing.
2727  */
2728 VOID WINAPI SHLWAPI_268(IUnknown *lpDest, IUnknown **lppUnknown)
2729 {
2730   TRACE("(%p,%p)\n", lpDest, lppUnknown);
2731
2732   if (*lppUnknown)
2733   {
2734     /* Copy Reference*/
2735     IUnknown_AddRef(lpDest);
2736     SHLWAPI_169(lppUnknown); /* Release existing interface */
2737   }
2738 }
2739
2740 /*************************************************************************
2741  *      @       [SHLWAPI.269]
2742  *
2743  * Convert an ASCII string of a CLSID into a CLSID.
2744  *
2745  * PARAMS
2746  *  idstr [I] String representing a CLSID in registry format
2747  *  id    [O] Destination for the converted CLSID
2748  *
2749  * RETURNS
2750  *  Success: TRUE. id contains the converted CLSID.
2751  *  Failure: FALSE.
2752  */
2753 BOOL WINAPI SHLWAPI_269(LPCSTR idstr, CLSID *id)
2754 {
2755   WCHAR wClsid[40];
2756   MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2757   return SUCCEEDED(SHLWAPI_436(wClsid, id));
2758 }
2759
2760 /*************************************************************************
2761  *      @       [SHLWAPI.270]
2762  *
2763  * Unicode version of SHLWAPI_269.
2764  */
2765 BOOL WINAPI SHLWAPI_270(LPCWSTR idstr, CLSID *id)
2766 {
2767   return SUCCEEDED(SHLWAPI_436(idstr, id));
2768 }
2769
2770 /*************************************************************************
2771  *      @       [SHLWAPI.276]
2772  *
2773  * Determine if the browser is integrated into the shell, and set a registry
2774  * key accordingly.
2775  *
2776  * PARAMS
2777  *  None.
2778  *
2779  * RETURNS
2780  *  1, If the browser is not integrated.
2781  *  2, If the browser is integrated.
2782  *
2783  * NOTES
2784  *  The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2785  *  either set to TRUE, or removed depending on whether the browser is deemed
2786  *  to be integrated.
2787  */
2788 DWORD WINAPI SHLWAPI_276()
2789 {
2790   static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2791   static DWORD dwState = 0;
2792   HKEY hKey;
2793   DWORD dwRet, dwData, dwSize;
2794
2795   if (dwState)
2796     return dwState;
2797
2798   /* If shell32 exports DllGetVersion(), the browser is integrated */
2799   GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2800   dwState = pDllGetVersion ? 2 : 1;
2801
2802   /* Set or delete the key accordinly */
2803   dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2804                         "Software\\Microsoft\\Internet Explorer", 0,
2805                          KEY_ALL_ACCESS, &hKey);
2806   if (!dwRet)
2807   {
2808     dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2809                              (LPBYTE)&dwData, &dwSize);
2810
2811     if (!dwRet && dwState == 1)
2812     {
2813       /* Value exists but browser is not integrated */
2814       RegDeleteValueA(hKey, szIntegratedBrowser);
2815     }
2816     else if (dwRet && dwState == 2)
2817     {
2818       /* Browser is integrated but value does not exist */
2819       dwData = TRUE;
2820       RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2821                      (LPBYTE)&dwData, sizeof(dwData));
2822     }
2823     RegCloseKey(hKey);
2824   }
2825   return dwState;
2826 }
2827
2828 /*************************************************************************
2829  *      @       [SHLWAPI.278]
2830  *
2831  * Unicode version of SHLWAPI_257.
2832  */
2833 HWND WINAPI SHLWAPI_278(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2834                         DWORD dwStyle, HMENU hMenu, LONG z)
2835 {
2836   static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2837   WNDCLASSW wc;
2838   HWND hWnd;
2839
2840   TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2841          wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2842
2843   /* If our OS is natively ASCII, use the ASCII version */
2844   if (!(GetVersion() & 0x80000000))  /* NT */
2845     return SHLWAPI_257(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2846
2847   /* Create Window class */
2848   wc.style         = 0;
2849   wc.lpfnWndProc   = DefWindowProcW;
2850   wc.cbClsExtra    = 0;
2851   wc.cbWndExtra    = 4;
2852   wc.hInstance     = shlwapi_hInstance;
2853   wc.hIcon         = (HICON)0;
2854   wc.hCursor       = LoadCursorA((HINSTANCE)0, IDC_ARROWA);
2855   wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2856   wc.lpszMenuName  = NULL;
2857   wc.lpszClassName = szClass;
2858
2859   SHLWAPI_237(&wc); /* Register class */
2860
2861   /* FIXME: Set extra bits in dwExStyle */
2862
2863   hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2864                          hWndParent, hMenu, shlwapi_hInstance, 0);
2865   if (hWnd)
2866   {
2867     SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2868
2869     if (wndProc)
2870       SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
2871   }
2872   return hWnd;
2873 }
2874
2875 /*************************************************************************
2876  *      @       [SHLWAPI.279]
2877  *
2878  * Get and show a context menu from a shell folder.
2879  *
2880  * PARAMS
2881  *  hWnd           [I] Window displaying the shell folder
2882  *  lpFolder       [I] IShellFolder interface
2883  *  lpApidl        [I] Id for the particular folder desired
2884  *
2885  * RETURNS
2886  *  Success: S_OK.
2887  *  Failure: An HRESULT error code indicating the error.
2888  */
2889 HRESULT WINAPI SHLWAPI_279(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2890 {
2891   return SHLWAPI_363(hWnd, lpFolder, lpApidl, FALSE);
2892 }
2893
2894 /*************************************************************************
2895  *      @       [SHLWAPI.281]
2896  *
2897  * _SHPackDispParamsV
2898  */
2899 HRESULT WINAPI SHLWAPI_281(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2900 {
2901         FIXME("%p %p %p %p\n",w,x,y,z);
2902         return E_FAIL;
2903 }
2904
2905 /*************************************************************************
2906  *      @       [SHLWAPI.282]
2907  *
2908  * This function seems to be a forward to SHLWAPI.281 (whatever THAT
2909  * function does...).
2910  */
2911 HRESULT WINAPI SHLWAPI_282(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2912 {
2913   FIXME("%p %p %p %p\n", w, x, y, z);
2914   return E_FAIL;
2915 }
2916
2917 /*************************************************************************
2918  *      @       [SHLWAPI.284]
2919  *
2920  * _IConnectionPoint_SimpleInvoke
2921  */
2922 DWORD WINAPI SHLWAPI_284 (
2923         LPVOID x,
2924         LPVOID y,
2925         LPVOID z)
2926 {
2927         TRACE("(%p %p %p) stub\n",x,y,z);
2928         return 0;
2929 }
2930
2931 /*************************************************************************
2932  *      SHLWAPI_285     [SHLWAPI.285]
2933  *
2934  * Notify an IConnectionPoint object of changes.
2935  *
2936  * PARAMS
2937  *  lpCP   [I] Object to notify
2938  *  dispID [I]
2939  *
2940  * RETURNS
2941  *  Success: S_OK.
2942  *  Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2943  *           IConnectionPoint interface.
2944  */
2945 HRESULT WINAPI SHLWAPI_285(IConnectionPoint* lpCP, DISPID dispID)
2946 {
2947   IEnumConnections *lpEnum;
2948   HRESULT hRet = E_NOINTERFACE;
2949
2950   TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2951
2952   /* Get an enumerator for the connections */
2953   if (lpCP)
2954     hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2955
2956   if (SUCCEEDED(hRet))
2957   {
2958     IPropertyNotifySink *lpSink;
2959     CONNECTDATA connData;
2960     ULONG ulFetched;
2961
2962     /* Call OnChanged() for every notify sink in the connection point */
2963     while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2964     {
2965       if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2966           lpSink)
2967       {
2968         IPropertyNotifySink_OnChanged(lpSink, dispID);
2969         IPropertyNotifySink_Release(lpSink);
2970       }
2971       IUnknown_Release(connData.pUnk);
2972     }
2973
2974     IEnumConnections_Release(lpEnum);
2975   }
2976   return hRet;
2977 }
2978
2979 /*************************************************************************
2980  *      SHLWAPI_287     [SHLWAPI.287]
2981  *
2982  * Notify an IConnectionPointContainer object of changes.
2983  *
2984  * PARAMS
2985  *  lpUnknown [I] Object to notify
2986  *  dispID    [I]
2987  *
2988  * RETURNS
2989  *  Success: S_OK.
2990  *  Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2991  *           IConnectionPointContainer interface.
2992  */
2993 HRESULT WINAPI SHLWAPI_287(IUnknown *lpUnknown, DISPID dispID)
2994 {
2995   IConnectionPointContainer* lpCPC = NULL;
2996   HRESULT hRet = E_NOINTERFACE;
2997
2998   TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2999
3000   if (lpUnknown)
3001     hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3002
3003   if (SUCCEEDED(hRet))
3004   {
3005     IConnectionPoint* lpCP;
3006
3007     hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3008     IConnectionPointContainer_Release(lpCPC);
3009
3010     hRet = SHLWAPI_285(lpCP, dispID);
3011     IConnectionPoint_Release(lpCP);
3012   }
3013   return hRet;
3014 }
3015
3016 /*************************************************************************
3017  *      @       [SHLWAPI.289]
3018  *
3019  * See PlaySoundW.
3020  */
3021 BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3022 {
3023   GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
3024   return pPlaySoundW(pszSound, hmod, fdwSound);
3025 }
3026
3027 /*************************************************************************
3028  *      @       [SHLWAPI.294]
3029  */
3030 BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
3031 {
3032     /*
3033      * str1:            "I"     "I"     pushl esp+0x20
3034      * str2:            "U"     "I"     pushl 0x77c93810
3035      * (is "I" and "U" "integer" and "unsigned" ??)
3036      *
3037      * pStr:            ""      ""      pushl eax
3038      * some_len:        0x824   0x104   pushl 0x824
3039      * lpStr2:          "%l"    "%l"    pushl esp+0xc
3040      *
3041      * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
3042      * LocalAlloc(0x00, some_len) -> irrelevant_var
3043      * LocalAlloc(0x40, irrelevant_len) -> pStr
3044      * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
3045      * shlwapi.PathRemoveBlanksW(pStr);
3046      */
3047     FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
3048     return TRUE;
3049 }
3050
3051 /*************************************************************************
3052  *      @       [SHLWAPI.295]
3053  *
3054  * Called by ICQ2000b install via SHDOCVW:
3055  * str1: "InternetShortcut"
3056  * x: some unknown pointer
3057  * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3058  * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3059  *
3060  * In short: this one maybe creates a desktop link :-)
3061  */
3062 BOOL WINAPI SHLWAPI_295(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3063 {
3064     FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3065     return TRUE;
3066 }
3067
3068 /*************************************************************************
3069  *      @       [SHLWAPI.299]
3070  *
3071  * See COMCTL32_417.
3072  */
3073 BOOL WINAPI SHLWAPI_299(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
3074                          LPCWSTR str, UINT count, const INT *lpDx)
3075 {
3076     GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
3077     return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
3078 }
3079
3080 /*************************************************************************
3081  *      @       [SHLWAPI.313]
3082  *
3083  * See SHGetFileInfoW.
3084  */
3085 DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
3086                          SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3087 {
3088   GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
3089   return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3090 }
3091
3092 /*************************************************************************
3093  *      @       [SHLWAPI.318]
3094  *
3095  * See DragQueryFileW.
3096  */
3097 UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3098 {
3099   GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
3100   return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
3101 }
3102
3103 /*************************************************************************
3104  *      @       [SHLWAPI.333]
3105  *
3106  * See SHBrowseForFolderW.
3107  */
3108 LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
3109 {
3110   GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
3111   return pSHBrowseForFolderW(lpBi);
3112 }
3113
3114 /*************************************************************************
3115  *      @       [SHLWAPI.334]
3116  *
3117  * See SHGetPathFromIDListW.
3118  */
3119 BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
3120 {
3121   GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
3122   return pSHGetPathFromIDListW(pidl, pszPath);
3123 }
3124
3125 /*************************************************************************
3126  *      @       [SHLWAPI.335]
3127  *
3128  * See ShellExecuteExW.
3129  */
3130 BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
3131 {
3132   GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
3133   return pShellExecuteExW(lpExecInfo);
3134 }
3135
3136 /*************************************************************************
3137  *      @       [SHLWAPI.336]
3138  *
3139  * See SHFileOperationW.
3140  */
3141 HICON WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
3142 {
3143   GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
3144   return pSHFileOperationW(lpFileOp);
3145 }
3146
3147 /*************************************************************************
3148  *      @       [SHLWAPI.337]
3149  *
3150  * See ExtractIconExW.
3151  */
3152 UINT WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
3153                          HICON *phiconSmall, UINT nIcons)
3154 {
3155   GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
3156   return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
3157 }
3158
3159 /*************************************************************************
3160  *      @       [SHLWAPI.342]
3161  *
3162  */
3163 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3164 {
3165         return InterlockedCompareExchange(dest, xchg, compare);
3166 }
3167
3168 /*************************************************************************
3169  *      @       [SHLWAPI.346]
3170  */
3171 DWORD WINAPI SHLWAPI_346 (
3172         LPCWSTR src,
3173         LPWSTR dest,
3174         int len)
3175 {
3176         FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
3177         lstrcpynW(dest, src, len);
3178         return lstrlenW(dest)+1;
3179 }
3180
3181 /*************************************************************************
3182  *      @       [SHLWAPI.350]
3183  *
3184  * See GetFileVersionInfoSizeW.
3185  */
3186 DWORD WINAPI SHLWAPI_350 (
3187         LPWSTR x,
3188         LPVOID y)
3189 {
3190         DWORD ret;
3191
3192         GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3193         ret = pGetFileVersionInfoSizeW(x, y);
3194         return 0x208 + ret;
3195 }
3196
3197 /*************************************************************************
3198  *      @       [SHLWAPI.351]
3199  *
3200  * See GetFileVersionInfoW.
3201  */
3202 BOOL  WINAPI SHLWAPI_351 (
3203         LPWSTR w,   /* [in] path to dll */
3204         DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
3205         DWORD  y,   /* [in] return value from SHLWAPI_350() - assume length */
3206         LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3207 {
3208     GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3209     return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3210 }
3211
3212 /*************************************************************************
3213  *      @       [SHLWAPI.352]
3214  *
3215  * See VerQueryValueW.
3216  */
3217 WORD WINAPI SHLWAPI_352 (
3218         LPVOID w,   /* [in] Buffer from SHLWAPI_351() */
3219         LPWSTR x,   /* [in]   Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3220         LPVOID y,   /* [out]  Ver buffer - passed to VerQueryValueA as #3 */
3221         UINT*  z)   /* [in]   Ver length - passed to VerQueryValueA as #4 */
3222 {
3223     GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3224     return pVerQueryValueW((char*)w+0x208, x, y, z);
3225 }
3226
3227 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3228 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3229 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3230
3231 /*************************************************************************
3232  *      SHLWAPI_355     [SHLWAPI.355]
3233  *
3234  * Change the modality of a shell object.
3235  *
3236  * PARAMS
3237  *  lpUnknown [I] Object to make modeless
3238  *  bModeless [I] TRUE=Make modeless, FALSE=Make modal
3239  *
3240  * RETURNS
3241  *  Success: S_OK. The modality lpUnknown is changed.
3242  *  Failure: An HRESULT error code indicating the error.
3243  *
3244  * NOTES
3245  *  lpUnknown must support the IOleInPlaceFrame interface, the
3246  *  IInternetSecurityMgrSite interface, the IShellBrowser interface
3247  *  or the IDocHostUIHandler interface, or this call fails.
3248  */
3249 HRESULT WINAPI SHLWAPI_355(IUnknown *lpUnknown, BOOL bModeless)
3250 {
3251   IUnknown *lpObj;
3252   HRESULT hRet;
3253
3254   TRACE("(%p,%d)\n", lpUnknown, bModeless);
3255
3256   if (!lpUnknown)
3257     return E_FAIL;
3258
3259   if (IsIface(IOleInPlaceFrame))
3260     EnableModeless(IOleInPlaceFrame);
3261   else if (IsIface(IShellBrowser))
3262     EnableModeless(IShellBrowser);
3263 #if 0
3264   /* FIXME: Wine has no headers for these objects yet */
3265   else if (IsIface(IInternetSecurityMgrSite))
3266     EnableModeless(IInternetSecurityMgrSite);
3267   else if (IsIface(IDocHostUIHandler))
3268     EnableModeless(IDocHostUIHandler);
3269 #endif
3270   else
3271     return hRet;
3272
3273   IUnknown_Release(lpObj);
3274   return S_OK;
3275 }
3276
3277 /*************************************************************************
3278  *      @       [SHLWAPI.357]
3279  *
3280  * See SHGetNewLinkInfoW.
3281  */
3282 BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3283                         BOOL *pfMustCopy, UINT uFlags)
3284 {
3285   GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3286   return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3287 }
3288
3289 /*************************************************************************
3290  *      @       [SHLWAPI.358]
3291  *
3292  * See SHDefExtractIconW.
3293  */
3294 UINT WINAPI SHLWAPI_358(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3295                          HICON* phiconSmall, UINT nIconSize)
3296 {
3297   GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3298   return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3299 }
3300
3301 /*************************************************************************
3302  *      @       [SHLWAPI.363]
3303  *
3304  * Get and show a context menu from a shell folder.
3305  *
3306  * PARAMS
3307  *  hWnd           [I] Window displaying the shell folder
3308  *  lpFolder       [I] IShellFolder interface
3309  *  lpApidl        [I] Id for the particular folder desired
3310  *  bInvokeDefault [I] Whether to invoke the default menu item
3311  *
3312  * RETURNS
3313  *  Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3314  *           executed.
3315  *  Failure: An HRESULT error code indicating the error.
3316  */
3317 HRESULT WINAPI SHLWAPI_363(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3318 {
3319   IContextMenu *iContext;
3320   HRESULT hRet = E_FAIL;
3321
3322   TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3323
3324   if (!lpFolder)
3325     return hRet;
3326
3327   /* Get the context menu from the shell folder */
3328   hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3329                                     &IID_IContextMenu, 0, (void**)&iContext);
3330   if (SUCCEEDED(hRet))
3331   {
3332     HMENU hMenu;
3333     if ((hMenu = CreatePopupMenu()))
3334     {
3335       HRESULT hQuery;
3336       DWORD dwDefaultId = 0;
3337
3338       /* Add the context menu entries to the popup */
3339       hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3340                                              bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3341
3342       if (SUCCEEDED(hQuery))
3343       {
3344         if (bInvokeDefault &&
3345             (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3346         {
3347           CMINVOKECOMMANDINFO cmIci;
3348           /* Invoke the default item */
3349           memset(&cmIci,0,sizeof(cmIci));
3350           cmIci.cbSize = sizeof(cmIci);
3351           cmIci.fMask = CMIC_MASK_ASYNCOK;
3352           cmIci.hwnd = hWnd;
3353           cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3354           cmIci.nShow = SW_SCROLLCHILDREN;
3355
3356           hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3357         }
3358       }
3359       DestroyMenu(hMenu);
3360     }
3361     IContextMenu_Release(iContext);
3362   }
3363   return hRet;
3364 }
3365
3366 /*************************************************************************
3367  *      @       [SHLWAPI.364]
3368  *
3369  * Copy one string to another, up to a given length.
3370  *
3371  * PARAMS
3372  *  lpszSrc [I] Source string to copy
3373  *  lpszDst [O] Destination for copied string
3374  *  iLen    [I] Number of characters to copy
3375  *
3376  * RETURNS
3377  *  TRUE.
3378  */
3379 DWORD WINAPI SHLWAPI_364(LPCSTR lpszSrc, LPSTR lpszDst, INT iLen)
3380 {
3381   lstrcpynA(lpszDst, lpszSrc, iLen);
3382   return TRUE;
3383 }
3384
3385 /*************************************************************************
3386  *      @       [SHLWAPI.370]
3387  *
3388  * See ExtractIconW.
3389  */
3390 HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3391                          UINT nIconIndex)
3392 {
3393   GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3394   return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3395 }
3396
3397 /*************************************************************************
3398  *      @       [SHLWAPI.376]
3399  */
3400 LANGID WINAPI SHLWAPI_376 ()
3401 {
3402     FIXME("() stub\n");
3403     /* FIXME: This should be a forward in the .spec file to the win2k function
3404      * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3405      */
3406     return GetUserDefaultLangID();
3407 }
3408
3409 /*************************************************************************
3410  *      @       [SHLWAPI.377]
3411  *
3412  * Load a library from the directory of a particular process.
3413  *
3414  * PARAMS
3415  *  new_mod   [I] Library name
3416  *  inst_hwnd [I] Module whose directory is to be used
3417  *  dwFlags   [I] Flags controlling the load
3418  *
3419  * RETURNS
3420  *  Success: A handle to the loaded module
3421  *  Failure: A NULL handle.
3422  */
3423 HMODULE WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3424 {
3425   /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3426    *        each call here.
3427    * FIXME: Native shows calls to:
3428    *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3429    *                      CheckVersion
3430    *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3431    *  RegQueryValueExA for "LPKInstalled"
3432    *  RegCloseKey
3433    *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3434    *  RegQueryValueExA for "ResourceLocale"
3435    *  RegCloseKey
3436    *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3437    *  RegQueryValueExA for "Locale"
3438    *  RegCloseKey
3439    *  and then tests the Locale ("en" for me).
3440    *     code below
3441    *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3442    */
3443     CHAR mod_path[2*MAX_PATH];
3444     LPSTR ptr;
3445
3446     FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3447     GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
3448     ptr = strrchr(mod_path, '\\');
3449     if (ptr) {
3450         strcpy(ptr+1, new_mod);
3451         TRACE("loading %s\n", debugstr_a(mod_path));
3452         return LoadLibraryA(mod_path);
3453     }
3454     return NULL;
3455 }
3456
3457 /*************************************************************************
3458  *      @       [SHLWAPI.378]
3459  *
3460  * Unicode version of SHLWAPI_377
3461  */
3462 DWORD WINAPI SHLWAPI_378 (LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3463 {
3464     WCHAR mod_path[2*MAX_PATH];
3465     LPWSTR ptr;
3466
3467     FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3468     GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
3469     ptr = strrchrW(mod_path, '\\');
3470     if (ptr) {
3471         strcpyW(ptr+1, new_mod);
3472         TRACE("loading %s\n", debugstr_w(mod_path));
3473         return (DWORD)LoadLibraryW(mod_path);
3474     }
3475     return 0;
3476 }
3477
3478 /*************************************************************************
3479  * ColorAdjustLuma      [SHLWAPI.387]
3480  *
3481  * Adjust the luminosity of a color
3482  *
3483  * PARAMS
3484  *  cRGB         [I] RGB value to convert
3485  *  dwLuma       [I] Luma adjustment
3486  *  bUnknown     [I] Unknown
3487  *
3488  * RETURNS
3489  *  The adjusted RGB color.
3490  */
3491 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3492 {
3493   TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3494
3495   if (dwLuma)
3496   {
3497     WORD wH, wL, wS;
3498
3499     ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3500
3501     FIXME("Ignoring luma adjustment\n");
3502
3503     /* FIXME: The ajdustment is not linear */
3504
3505     cRGB = ColorHLSToRGB(wH, wL, wS);
3506   }
3507   return cRGB;
3508 }
3509
3510 /*************************************************************************
3511  *      @       [SHLWAPI.389]
3512  *
3513  * See GetSaveFileNameW.
3514  */
3515 BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
3516 {
3517   GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3518   return pGetSaveFileNameW(ofn);
3519 }
3520
3521 /*************************************************************************
3522  *      @       [SHLWAPI.390]
3523  *
3524  * See WNetRestoreConnectionW.
3525  */
3526 DWORD WINAPI SHLWAPI_390(HWND hwndOwner, LPWSTR lpszDevice)
3527 {
3528   GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3529   return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3530 }
3531
3532 /*************************************************************************
3533  *      @       [SHLWAPI.391]
3534  *
3535  * See WNetGetLastErrorW.
3536  */
3537 DWORD WINAPI SHLWAPI_391(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3538                          LPWSTR lpNameBuf, DWORD nNameBufSize)
3539 {
3540   GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3541   return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3542 }
3543
3544 /*************************************************************************
3545  *      @       [SHLWAPI.401]
3546  *
3547  * See PageSetupDlgW.
3548  */
3549 BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
3550 {
3551   GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3552   return pPageSetupDlgW(pagedlg);
3553 }
3554
3555 /*************************************************************************
3556  *      @       [SHLWAPI.402]
3557  *
3558  * See PrintDlgW.
3559  */
3560 BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
3561 {
3562   GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3563   return pPrintDlgW(printdlg);
3564 }
3565
3566 /*************************************************************************
3567  *      @       [SHLWAPI.403]
3568  *
3569  * See GetOpenFileNameW.
3570  */
3571 BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
3572 {
3573   GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3574   return pGetOpenFileNameW(ofn);
3575 }
3576
3577 /* INTERNAL: Map from HLS color space to RGB */
3578 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3579 {
3580   wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3581
3582   if (wHue > 160)
3583     return wMid1;
3584   else if (wHue > 120)
3585     wHue = 160 - wHue;
3586   else if (wHue > 40)
3587     return wMid2;
3588
3589   return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3590 }
3591
3592 /* Convert to RGB and scale into RGB range (0..255) */
3593 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3594
3595 /*************************************************************************
3596  *      ColorHLSToRGB   [SHLWAPI.404]
3597  *
3598  * Convert from hls color space into an rgb COLORREF.
3599  *
3600  * PARAMS
3601  *  wHue        [I] Hue amount
3602  *  wLuminosity [I] Luminosity amount
3603  *  wSaturation [I] Saturation amount
3604  *
3605  * RETURNS
3606  *  A COLORREF representing the converted color.
3607  *
3608  * NOTES
3609  *  Input hls values are constrained to the range (0..240).
3610  */
3611 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3612 {
3613   WORD wRed;
3614
3615   if (wSaturation)
3616   {
3617     WORD wGreen, wBlue, wMid1, wMid2;
3618
3619     if (wLuminosity > 120)
3620       wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3621     else
3622       wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3623
3624     wMid1 = wLuminosity * 2 - wMid2;
3625
3626     wRed   = GET_RGB(wHue + 80);
3627     wGreen = GET_RGB(wHue);
3628     wBlue  = GET_RGB(wHue - 80);
3629
3630     return RGB(wRed, wGreen, wBlue);
3631   }
3632
3633   wRed = wLuminosity * 255 / 240;
3634   return RGB(wRed, wRed, wRed);
3635 }
3636
3637 /*************************************************************************
3638  *      @       [SHLWAPI.406]
3639  */
3640 DWORD WINAPI SHLWAPI_406(LPVOID u, LPVOID v, LPVOID w, LPVOID x, LPVOID y, LPVOID z)
3641 {
3642   FIXME("%p %p %p %p %p %p\n", u, v, w, x, y, z);
3643   return 0;
3644 }
3645
3646 /*************************************************************************
3647  *      @       [SHLWAPI.413]
3648  *
3649  * Get the current docking status of the system.
3650  *
3651  * PARAMS
3652  *  dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3653  *
3654  * RETURNS
3655  *  One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3656  *  a notebook.
3657  */
3658 DWORD WINAPI SHLWAPI_413(DWORD dwFlags)
3659 {
3660   HW_PROFILE_INFOA hwInfo;
3661
3662   TRACE("(0x%08lx)\n", dwFlags);
3663
3664   GetCurrentHwProfileA(&hwInfo);
3665   switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3666   {
3667   case DOCKINFO_DOCKED:
3668   case DOCKINFO_UNDOCKED:
3669     return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3670   default:
3671     return 0;
3672   }
3673 }
3674
3675 /*************************************************************************
3676  *      @       [SHLWAPI.418]
3677  *
3678  * Function seems to do FreeLibrary plus other things.
3679  *
3680  * FIXME native shows the following calls:
3681  *   RtlEnterCriticalSection
3682  *   LocalFree
3683  *   GetProcAddress(Comctl32??, 150L)
3684  *   DPA_DeletePtr
3685  *   RtlLeaveCriticalSection
3686  *  followed by the FreeLibrary.
3687  *  The above code may be related to .377 above.
3688  */
3689 BOOL WINAPI SHLWAPI_418(HMODULE hModule)
3690 {
3691         FIXME("(%p) semi-stub\n", hModule);
3692         return FreeLibrary(hModule);
3693 }
3694
3695 /*************************************************************************
3696  *      @       [SHLWAPI.430]
3697  */
3698 DWORD WINAPI SHLWAPI_430(HINSTANCE hInst, HANDLE hHeap)
3699 {
3700         FIXME("(%p,%p) stub\n", hInst, hHeap);
3701         return E_FAIL;   /* This is what is used if shlwapi not loaded */
3702 }
3703
3704 /*************************************************************************
3705  *      @       [SHLWAPI.431]
3706  */
3707 DWORD WINAPI SHLWAPI_431 (DWORD x)
3708 {
3709         FIXME("(0x%08lx)stub\n", x);
3710         return 0xabba1247;
3711 }
3712
3713 /*************************************************************************
3714  *      @       [SHLWAPI.436]
3715  *
3716  * Convert an Unicode string CLSID into a CLSID.
3717  *
3718  * PARAMS
3719  *  idstr      [I]   string containing a CLSID in text form
3720  *  id         [O]   CLSID extracted from the string
3721  *
3722  * RETURNS
3723  *  S_OK on success or E_INVALIDARG on failure
3724  *
3725  * NOTES
3726  *  This is really CLSIDFromString() which is exported by ole32.dll,
3727  *  however the native shlwapi.dll does *not* import ole32. Nor does
3728  *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3729  *  that MS duplicated the code for CLSIDFromString(), and yes they did, only
3730  *  it returns an E_INVALIDARG error code on failure.
3731  *  This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3732  *  in "dlls/ole32/compobj.c".
3733  */
3734 HRESULT WINAPI SHLWAPI_436(LPCWSTR idstr, CLSID *id)
3735 {
3736         LPCWSTR s = idstr;
3737         BYTE *p;
3738         INT i;
3739         WCHAR table[256];
3740
3741         if (!s) {
3742           memset(id, 0, sizeof(CLSID));
3743           return S_OK;
3744         }
3745         else {  /* validate the CLSID string */
3746
3747           if (strlenW(s) != 38)
3748             return E_INVALIDARG;
3749
3750           if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3751             return E_INVALIDARG;
3752
3753           for (i=1; i<37; i++)
3754           {
3755             if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3756               continue;
3757             if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
3758                 ((s[i] >= L'a') && (s[i] <= L'f'))  ||
3759                 ((s[i] >= L'A') && (s[i] <= L'F')))
3760                )
3761               return E_INVALIDARG;
3762           }
3763         }
3764
3765     TRACE("%s -> %p\n", debugstr_w(s), id);
3766
3767   /* quick lookup table */
3768     memset(table, 0, 256*sizeof(WCHAR));
3769
3770     for (i = 0; i < 10; i++) {
3771         table['0' + i] = i;
3772     }
3773     for (i = 0; i < 6; i++) {
3774         table['A' + i] = i+10;
3775         table['a' + i] = i+10;
3776     }
3777
3778     /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3779
3780     p = (BYTE *) id;
3781
3782     s++;        /* skip leading brace  */
3783     for (i = 0; i < 4; i++) {
3784         p[3 - i] = table[*s]<<4 | table[*(s+1)];
3785         s += 2;
3786     }
3787     p += 4;
3788     s++;        /* skip - */
3789
3790     for (i = 0; i < 2; i++) {
3791         p[1-i] = table[*s]<<4 | table[*(s+1)];
3792         s += 2;
3793     }
3794     p += 2;
3795     s++;        /* skip - */
3796
3797     for (i = 0; i < 2; i++) {
3798         p[1-i] = table[*s]<<4 | table[*(s+1)];
3799         s += 2;
3800     }
3801     p += 2;
3802     s++;        /* skip - */
3803
3804     /* these are just sequential bytes */
3805     for (i = 0; i < 2; i++) {
3806         *p++ = table[*s]<<4 | table[*(s+1)];
3807         s += 2;
3808     }
3809     s++;        /* skip - */
3810
3811     for (i = 0; i < 6; i++) {
3812         *p++ = table[*s]<<4 | table[*(s+1)];
3813         s += 2;
3814     }
3815
3816     return S_OK;
3817 }
3818
3819 /*************************************************************************
3820  *      @       [SHLWAPI.437]
3821  *
3822  * Determine if the OS supports a given feature.
3823  *
3824  * PARAMS
3825  *  dwFeature [I] Feature requested (undocumented)
3826  *
3827  * RETURNS
3828  *  TRUE  If the feature is available.
3829  *  FALSE If the feature is not available.
3830  */
3831 DWORD WINAPI SHLWAPI_437 (DWORD feature)
3832 {
3833   FIXME("(0x%08lx) stub\n", feature);
3834   return FALSE;
3835 }
3836
3837 /*************************************************************************
3838  *      ColorRGBToHLS   [SHLWAPI.445]
3839  *
3840  * Convert an rgb COLORREF into the hls color space.
3841  *
3842  * PARAMS
3843  *  cRGB         [I] Source rgb value
3844  *  pwHue        [O] Destination for converted hue
3845  *  pwLuminance  [O] Destination for converted luminance
3846  *  pwSaturation [O] Destination for converted saturation
3847  *
3848  * RETURNS
3849  *  Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3850  *  values.
3851  *
3852  * NOTES
3853  *  Output HLS values are constrained to the range (0..240).
3854  *  For Achromatic conversions, Hue is set to 160.
3855  */
3856 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3857                           LPWORD pwLuminance, LPWORD pwSaturation)
3858 {
3859   int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3860
3861   TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3862
3863   wR = GetRValue(cRGB);
3864   wG = GetGValue(cRGB);
3865   wB = GetBValue(cRGB);
3866
3867   wMax = max(wR, max(wG, wB));
3868   wMin = min(wR, min(wG, wB));
3869
3870   /* Luminosity */
3871   wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3872
3873   if (wMax == wMin)
3874   {
3875     /* Achromatic case */
3876     wSaturation = 0;
3877     /* Hue is now unrepresentable, but this is what native returns... */
3878     wHue = 160;
3879   }
3880   else
3881   {
3882     /* Chromatic case */
3883     int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3884
3885     /* Saturation */
3886     if (wLuminosity <= 120)
3887       wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3888     else
3889       wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3890
3891     /* Hue */
3892     wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3893     wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
3894     wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
3895
3896     if (wR == wMax)
3897       wHue = wBNorm - wGNorm;
3898     else if (wG == wMax)
3899       wHue = 80 + wRNorm - wBNorm;
3900     else
3901       wHue = 160 + wGNorm - wRNorm;
3902     if (wHue < 0)
3903       wHue += 240;
3904     else if (wHue > 240)
3905       wHue -= 240;
3906   }
3907   if (pwHue)
3908     *pwHue = wHue;
3909   if (pwLuminance)
3910     *pwLuminance = wLuminosity;
3911   if (pwSaturation)
3912     *pwSaturation = wSaturation;
3913 }
3914
3915 /*************************************************************************
3916  *      SHCreateShellPalette    [SHLWAPI.@]
3917  */
3918 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
3919 {
3920         FIXME("stub\n");
3921         return CreateHalftonePalette(hdc);
3922 }
3923
3924 /*************************************************************************
3925  *      SHGetInverseCMAP (SHLWAPI.@)
3926  *
3927  * Get an inverse color map table.
3928  *
3929  * PARAMS
3930  *  lpCmap  [O] Destination for color map
3931  *  dwSize  [I] Size of memory pointed to by lpCmap
3932  *
3933  * RETURNS
3934  *  Success: S_OK.
3935  *  Failure: E_POINTER,    If lpCmap is invalid.
3936  *           E_INVALIDARG, If dwFlags is invalid
3937  *           E_OUTOFMEMORY, If there is no memory available
3938  *
3939  * NOTES
3940  *  dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
3941  *  If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
3942  *  internal CMap.
3943  *  If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
3944  *  this DLL's internal CMap.
3945  */
3946 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
3947 {
3948     if (dwSize == 4) {
3949         FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3950         *dest = (DWORD)0xabba1249;
3951         return 0;
3952     }
3953     FIXME("(%p, %#lx) stub\n", dest, dwSize);
3954     return 0;
3955 }
3956
3957 /*************************************************************************
3958  *      SHIsLowMemoryMachine    [SHLWAPI.@]
3959  *
3960  * Determine if the current computer has low memory.
3961  *
3962  * PARAMS
3963  *  x [I] FIXME
3964  *
3965  * RETURNS
3966  *  TRUE if the users machine has 16 Megabytes of memory or less,
3967  *  FALSE otherwise.
3968  */
3969 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
3970 {
3971   FIXME("(0x%08lx) stub\n", x);
3972   return FALSE;
3973 }
3974
3975 /*************************************************************************
3976  *      GetMenuPosFromID        [SHLWAPI.@]
3977  */
3978 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
3979 {
3980  MENUITEMINFOA mi;
3981  INT nCount = GetMenuItemCount(hMenu), nIter = 0;
3982
3983  while (nIter < nCount)
3984  {
3985    mi.wID = 0;
3986    if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
3987      return nIter;
3988    nIter++;
3989  }
3990  return -1;
3991 }
3992
3993 /*************************************************************************
3994  * SHSkipJunction       [SHLWAPI.@]
3995  *
3996  * Determine if a bind context can be bound to an object
3997  *
3998  * PARAMS
3999  *  pbc    [I] Bind context to check
4000  *  pclsid [I] CLSID of object to be bound to
4001  *
4002  * RETURNS
4003  *  TRUE: If it is safe to bind
4004  *  FALSE: If pbc is invalid or binding would not be safe
4005  *
4006  */
4007 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4008 {
4009   static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4010     'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4011   BOOL bRet = FALSE;
4012
4013   if (pbc)
4014   {
4015     IUnknown* lpUnk;
4016
4017     if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4018     {
4019       CLSID clsid;
4020
4021       if (SUCCEEDED(SHLWAPI_175(lpUnk, &clsid)) &&
4022           IsEqualGUID(pclsid, &clsid))
4023         bRet = TRUE;
4024
4025       IUnknown_Release(lpUnk);
4026     }
4027   }
4028   return bRet;
4029 }