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