Don't define BEGIN_INTERFACE in unknwn.h.
[wine/multimedia.git] / dlls / shlwapi / ordinal.c
blobe4cdd7a1868a853bc31f21461c8ebfd5d90467de
1 /*
2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
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.
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.
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
23 #define COM_NO_WINDOWS_H
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
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 "olectl.h"
46 #include "shellapi.h"
47 #include "commdlg.h"
48 #include "wine/unicode.h"
49 #include "servprov.h"
50 #include "winreg.h"
51 #include "wine/debug.h"
52 #include "shlwapi.h"
53 #include "winnt.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell);
58 /* Get a function pointer from a DLL handle */
59 #define GET_FUNC(func, module, name, fail) \
60 do { \
61 if (!func) { \
62 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
63 func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
64 if (!func) return fail; \
65 } \
66 } while (0)
68 /* DLL handles for late bound calls */
69 extern HINSTANCE shlwapi_hInstance;
70 extern HMODULE SHLWAPI_hshell32;
71 extern HMODULE SHLWAPI_hwinmm;
72 extern HMODULE SHLWAPI_hcomdlg32;
73 extern HMODULE SHLWAPI_hcomctl32;
74 extern HMODULE SHLWAPI_hmpr;
75 extern HMODULE SHLWAPI_hurlmon;
76 extern HMODULE SHLWAPI_hversion;
78 extern DWORD SHLWAPI_ThreadRef_index;
80 typedef HANDLE HSHARED; /* Shared memory */
82 /* following is GUID for IObjectWithSite::SetSite -- see _174 */
83 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
84 /* following is GUID for IPersistMoniker::GetClassID -- see _174 */
85 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
87 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
88 typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
89 static fnpSHBrowseForFolderW pSHBrowseForFolderW;
90 typedef BOOL (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
91 static fnpPlaySoundW pPlaySoundW;
92 typedef DWORD (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
93 static fnpSHGetFileInfoW pSHGetFileInfoW;
94 typedef UINT (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
95 static fnpDragQueryFileW pDragQueryFileW;
96 typedef BOOL (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
97 static fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
98 typedef BOOL (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
99 static fnpShellExecuteExW pShellExecuteExW;
100 typedef HICON (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
101 static fnpSHFileOperationW pSHFileOperationW;
102 typedef UINT (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
103 static fnpExtractIconExW pExtractIconExW;
104 typedef BOOL (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
105 static fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
106 typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
107 static fnpSHDefExtractIconW pSHDefExtractIconW;
108 typedef HICON (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
109 static fnpExtractIconW pExtractIconW;
110 typedef BOOL (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
111 static fnpGetSaveFileNameW pGetSaveFileNameW;
112 typedef DWORD (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
113 static fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
114 typedef DWORD (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
115 static fnpWNetGetLastErrorW pWNetGetLastErrorW;
116 typedef BOOL (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
117 static fnpPageSetupDlgW pPageSetupDlgW;
118 typedef BOOL (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
119 static fnpPrintDlgW pPrintDlgW;
120 typedef BOOL (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
121 static fnpGetOpenFileNameW pGetOpenFileNameW;
122 typedef DWORD (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
123 static fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
124 typedef BOOL (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
125 static fnpGetFileVersionInfoW pGetFileVersionInfoW;
126 typedef WORD (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
127 static fnpVerQueryValueW pVerQueryValueW;
128 typedef BOOL (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
129 static fnpCOMCTL32_417 pCOMCTL32_417;
130 typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
131 static fnpDllGetVersion pDllGetVersion;
132 typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
133 static fnpCreateFormatEnumerator pCreateFormatEnumerator;
134 typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
135 static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
137 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
138 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
139 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);
140 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
143 NOTES: Most functions exported by ordinal seem to be superflous.
144 The reason for these functions to be there is to provide a wrapper
145 for unicode functions to provide these functions on systems without
146 unicode functions eg. win95/win98. Since we have such functions we just
147 call these. If running Wine with native DLL's, some late bound calls may
148 fail. However, its better to implement the functions in the forward DLL
149 and recommend the builtin rather than reimplementing the calls here!
152 /*************************************************************************
153 * SHLWAPI_DupSharedHandle
155 * Internal implemetation of SHLWAPI_11.
157 static
158 HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
159 DWORD dwSrcProcId, DWORD dwAccess,
160 DWORD dwOptions)
162 HANDLE hDst, hSrc;
163 DWORD dwMyProcId = GetCurrentProcessId();
164 HSHARED hRet = (HSHARED)NULL;
166 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
167 dwAccess, dwOptions);
169 /* Get dest process handle */
170 if (dwDstProcId == dwMyProcId)
171 hDst = GetCurrentProcess();
172 else
173 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
175 if (hDst)
177 /* Get src process handle */
178 if (dwSrcProcId == dwMyProcId)
179 hSrc = GetCurrentProcess();
180 else
181 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
183 if (hSrc)
185 /* Make handle available to dest process */
186 if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
187 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
188 hRet = (HSHARED)NULL;
190 if (dwSrcProcId != dwMyProcId)
191 CloseHandle(hSrc);
194 if (dwDstProcId != dwMyProcId)
195 CloseHandle(hDst);
198 TRACE("Returning handle %p\n", (PVOID)hRet);
199 return hRet;
202 /*************************************************************************
203 * @ [SHLWAPI.7]
205 * Create a block of sharable memory and initialise it with data.
207 * PARAMS
208 * dwProcId [I] ID of process owning data
209 * lpvData [I] Pointer to data to write
210 * dwSize [I] Size of data
212 * RETURNS
213 * Success: A shared memory handle
214 * Failure: NULL
216 * NOTES
217 * Ordinals 7-11 provide a set of calls to create shared memory between a
218 * group of processes. The shared memory is treated opaquely in that its size
219 * is not exposed to clients who map it. This is accomplished by storing
220 * the size of the map as the first DWORD of mapped data, and then offsetting
221 * the view pointer returned by this size.
224 HSHARED WINAPI SHAllocShared(DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
226 HANDLE hMap;
227 LPVOID pMapped;
228 HSHARED hRet = (HSHARED)NULL;
230 TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
232 /* Create file mapping of the correct length */
233 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
234 dwSize + sizeof(dwSize), NULL);
235 if (!hMap)
236 return hRet;
238 /* Get a view in our process address space */
239 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
241 if (pMapped)
243 /* Write size of data, followed by the data, to the view */
244 *((DWORD*)pMapped) = dwSize;
245 if (dwSize)
246 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
248 /* Release view. All further views mapped will be opaque */
249 UnmapViewOfFile(pMapped);
250 hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
251 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
252 DUPLICATE_SAME_ACCESS);
255 CloseHandle(hMap);
256 return hRet;
259 /*************************************************************************
260 * @ [SHLWAPI.8]
262 * Get a pointer to a block of shared memory from a shared memory handle.
264 * PARAMS
265 * hShared [I] Shared memory handle
266 * dwProcId [I] ID of process owning hShared
268 * RETURNS
269 * Success: A pointer to the shared memory
270 * Failure: NULL
273 PVOID WINAPI SHLockShared(HSHARED hShared, DWORD dwProcId)
275 HSHARED hDup;
276 LPVOID pMapped;
278 TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
280 /* Get handle to shared memory for current process */
281 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
282 FILE_MAP_ALL_ACCESS, 0);
283 /* Get View */
284 pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
285 CloseHandle(hDup);
287 if (pMapped)
288 return (char *) pMapped + sizeof(DWORD); /* Hide size */
289 return NULL;
292 /*************************************************************************
293 * @ [SHLWAPI.9]
295 * Release a pointer to a block of shared memory.
297 * PARAMS
298 * lpView [I] Shared memory pointer
300 * RETURNS
301 * Success: TRUE
302 * Failure: FALSE
305 BOOL WINAPI SHUnlockShared(LPVOID lpView)
307 TRACE("(%p)\n", lpView);
308 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
311 /*************************************************************************
312 * @ [SHLWAPI.10]
314 * Destroy a block of sharable memory.
316 * PARAMS
317 * hShared [I] Shared memory handle
318 * dwProcId [I] ID of process owning hShared
320 * RETURNS
321 * Success: TRUE
322 * Failure: FALSE
325 BOOL WINAPI SHFreeShared(HSHARED hShared, DWORD dwProcId)
327 HSHARED hClose;
329 TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
331 /* Get a copy of the handle for our process, closing the source handle */
332 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
333 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
334 /* Close local copy */
335 return CloseHandle((HANDLE)hClose);
338 /*************************************************************************
339 * @ [SHLWAPI.11]
341 * Copy a sharable memory handle from one process to another.
343 * PARAMS
344 * hShared [I] Shared memory handle to duplicate
345 * dwDstProcId [I] ID of the process wanting the duplicated handle
346 * dwSrcProcId [I] ID of the process owning hShared
347 * dwAccess [I] Desired DuplicateHandle() access
348 * dwOptions [I] Desired DuplicateHandle() options
350 * RETURNS
351 * Success: A handle suitable for use by the dwDstProcId process.
352 * Failure: A NULL handle.
355 HSHARED WINAPI SHMapHandle(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
356 DWORD dwAccess, DWORD dwOptions)
358 HSHARED hRet;
360 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
361 dwAccess, dwOptions);
362 return hRet;
365 /*************************************************************************
366 * @ [SHLWAPI.13]
368 * Create and register a clipboard enumerator for a web browser.
370 * PARAMS
371 * lpBC [I] Binding context
372 * lpUnknown [I] An object exposing the IWebBrowserApp interface
374 * RETURNS
375 * Success: S_OK.
376 * Failure: An HRESULT error code.
378 * NOTES
379 * The enumerator is stored as a property of the web browser. If it does not
380 * yet exist, it is created and set before being registered.
382 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
384 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
385 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
386 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
387 IEnumFORMATETC* pIEnumFormatEtc = NULL;
388 VARIANTARG var;
389 HRESULT hRet;
390 IWebBrowserApp* pBrowser = NULL;
392 TRACE("(%p, %p)\n", lpBC, lpUnknown);
394 /* Get An IWebBrowserApp interface from lpUnknown */
395 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
396 if (FAILED(hRet) || !pBrowser)
397 return E_NOINTERFACE;
399 V_VT(&var) = VT_EMPTY;
401 /* The property we get is the browsers clipboard enumerator */
402 hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
403 if (FAILED(hRet))
404 return hRet;
406 if (V_VT(&var) == VT_EMPTY)
408 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
409 char szKeyBuff[128], szValueBuff[128];
410 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
411 FORMATETC* formatList, *format;
412 HKEY hDocs;
414 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
416 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
417 "Version\\Internet Settings\\Accepted Documents", &hDocs))
418 return E_FAIL;
420 /* Get count of values in key */
421 while (!dwRet)
423 dwKeySize = sizeof(szKeyBuff);
424 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
425 dwCount++;
428 dwNumValues = dwCount;
430 /* Note: dwCount = number of items + 1; The extra item is the end node */
431 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
432 if (!formatList)
433 return E_OUTOFMEMORY;
435 if (dwNumValues > 1)
437 dwRet = 0;
438 dwCount = 0;
440 dwNumValues--;
442 /* Register clipboard formats for the values and populate format list */
443 while(!dwRet && dwCount < dwNumValues)
445 dwKeySize = sizeof(szKeyBuff);
446 dwValueSize = sizeof(szValueBuff);
447 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
448 (PBYTE)szValueBuff, &dwValueSize);
449 if (!dwRet)
450 return E_FAIL;
452 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
453 format->ptd = NULL;
454 format->dwAspect = 1;
455 format->lindex = 4;
456 format->tymed = -1;
458 format++;
459 dwCount++;
463 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
464 format->cfFormat = 0;
465 format->ptd = NULL;
466 format->dwAspect = 1;
467 format->lindex = 4;
468 format->tymed = -1;
470 /* Create a clipboard enumerator */
471 GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
472 hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
474 if (FAILED(hRet) || !pIEnumFormatEtc)
475 return hRet;
477 /* Set our enumerator as the browsers property */
478 V_VT(&var) = VT_UNKNOWN;
479 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
481 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
482 if (FAILED(hRet))
484 IEnumFORMATETC_Release(pIEnumFormatEtc);
485 goto RegisterDefaultAcceptHeaders_Exit;
489 if (V_VT(&var) == VT_UNKNOWN)
491 /* Our variant is holding the clipboard enumerator */
492 IUnknown* pIUnknown = V_UNKNOWN(&var);
493 IEnumFORMATETC* pClone = NULL;
495 TRACE("Retrieved IEnumFORMATETC property\n");
497 /* Get an IEnumFormatEtc interface from the variants value */
498 pIEnumFormatEtc = NULL;
499 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
500 (PVOID)&pIEnumFormatEtc);
501 if (!hRet && pIEnumFormatEtc)
503 /* Clone and register the enumerator */
504 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
505 if (!hRet && pClone)
507 GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
508 pRegisterFormatEnumerator(lpBC, pClone, 0);
510 IEnumFORMATETC_Release(pClone);
513 /* Release the IEnumFormatEtc interface */
514 IEnumFORMATETC_Release(pIUnknown);
516 IUnknown_Release(V_UNKNOWN(&var));
519 RegisterDefaultAcceptHeaders_Exit:
520 IWebBrowserApp_Release(pBrowser);
521 return hRet;
524 /*************************************************************************
525 * @ [SHLWAPI.15]
527 * Get Explorers "AcceptLanguage" setting.
529 * PARAMS
530 * langbuf [O] Destination for language string
531 * buflen [I] Length of langbuf
532 * [0] Success: used length of langbuf
534 * RETURNS
535 * Success: S_OK. langbuf is set to the language string found.
536 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
537 * does not contain the setting.
538 * E_INVALIDARG, If the buffer is not big enough
540 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
542 static const WCHAR szkeyW[] = {
543 'S','o','f','t','w','a','r','e','\\',
544 'M','i','c','r','o','s','o','f','t','\\',
545 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
546 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
547 static const WCHAR valueW[] = {
548 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
549 static const WCHAR enusW[] = {'e','n','-','u','s',0};
550 DWORD mystrlen, mytype;
551 HKEY mykey;
552 HRESULT retval;
553 LCID mylcid;
554 WCHAR *mystr;
556 if(!langbuf || !buflen || !*buflen)
557 return E_FAIL;
559 mystrlen = (*buflen > 20) ? *buflen : 20 ;
560 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
561 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
562 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
563 /* Did not find value */
564 mylcid = GetUserDefaultLCID();
565 /* somehow the mylcid translates into "en-us"
566 * this is similar to "LOCALE_SABBREVLANGNAME"
567 * which could be gotten via GetLocaleInfo.
568 * The only problem is LOCALE_SABBREVLANGUAGE" is
569 * a 3 char string (first 2 are country code and third is
570 * letter for "sublanguage", which does not come close to
571 * "en-us"
573 lstrcpyW(mystr, enusW);
574 mystrlen = lstrlenW(mystr);
575 } else {
576 /* handle returned string */
577 FIXME("missing code\n");
579 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
581 if(*buflen > lstrlenW(mystr)) {
582 *buflen = lstrlenW(mystr);
583 retval = S_OK;
584 } else {
585 *buflen = 0;
586 retval = E_INVALIDARG;
587 SetLastError(ERROR_INSUFFICIENT_BUFFER);
589 RegCloseKey(mykey);
590 HeapFree(GetProcessHeap(), 0, mystr);
591 return retval;
594 /*************************************************************************
595 * @ [SHLWAPI.14]
597 * Ascii version of GetAcceptLanguagesW.
599 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
601 WCHAR *langbufW;
602 DWORD buflenW, convlen;
603 HRESULT retval;
605 if(!langbuf || !buflen || !*buflen) return E_FAIL;
607 buflenW = *buflen;
608 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
609 retval = GetAcceptLanguagesW(langbufW, &buflenW);
611 /* FIXME: this is wrong, the string may not be null-terminated */
612 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,
613 *buflen, NULL, NULL);
614 *buflen = buflenW ? convlen : 0;
616 if(langbufW) HeapFree(GetProcessHeap(), 0, langbufW);
617 return retval;
620 /*************************************************************************
621 * @ [SHLWAPI.23]
623 * Convert a GUID to a string.
625 * PARAMS
626 * guid [I] GUID to convert
627 * str [O] Destination for string
628 * cmax [I] Length of output buffer
630 * RETURNS
631 * The length of the string created.
633 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
635 char xguid[40];
636 INT iLen;
638 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
640 sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
641 guid->Data1, guid->Data2, guid->Data3,
642 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
643 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
645 iLen = strlen(xguid) + 1;
647 if (iLen > cchMax)
648 return 0;
649 memcpy(lpszDest, xguid, iLen);
650 return iLen;
653 /*************************************************************************
654 * @ [SHLWAPI.24]
656 * Unicode version of SHStringFromGUIDA.
658 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
660 char xguid[40];
661 INT iLen = SHStringFromGUIDA(guid, xguid, cchMax);
663 if (iLen)
664 MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax);
665 return iLen;
668 /*************************************************************************
669 * @ [SHLWAPI.25]
671 * Determine if a Unicode character is alphabetic.
673 * PARAMS
674 * wc [I] Character to check.
676 * RETURNS
677 * TRUE, if wc is alphabetic,
678 * FALSE otherwise.
680 BOOL WINAPI IsCharAlphaWrapW(WCHAR wc)
682 return (get_char_typeW(wc) & C1_ALPHA) != 0;
685 /*************************************************************************
686 * @ [SHLWAPI.26]
688 * Determine if a Unicode character is upper-case.
690 * PARAMS
691 * wc [I] Character to check.
693 * RETURNS
694 * TRUE, if wc is upper-case,
695 * FALSE otherwise.
697 BOOL WINAPI IsCharUpperWrapW(WCHAR wc)
699 return (get_char_typeW(wc) & C1_UPPER) != 0;
702 /*************************************************************************
703 * @ [SHLWAPI.27]
705 * Determine if a Unicode character is lower-case.
707 * PARAMS
708 * wc [I] Character to check.
710 * RETURNS
711 * TRUE, if wc is lower-case,
712 * FALSE otherwise.
714 BOOL WINAPI IsCharLowerWrapW(WCHAR wc)
716 return (get_char_typeW(wc) & C1_LOWER) != 0;
719 /*************************************************************************
720 * @ [SHLWAPI.28]
722 * Determine if a Unicode character is alphabetic or a digit.
724 * PARAMS
725 * wc [I] Character to check.
727 * RETURNS
728 * TRUE, if wc is alphabetic or a digit,
729 * FALSE otherwise.
731 BOOL WINAPI IsCharAlphaNumericWrapW(WCHAR wc)
733 return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
736 /*************************************************************************
737 * @ [SHLWAPI.29]
739 * Determine if a Unicode character is a space.
741 * PARAMS
742 * wc [I] Character to check.
744 * RETURNS
745 * TRUE, if wc is a space,
746 * FALSE otherwise.
748 BOOL WINAPI IsCharSpaceW(WCHAR wc)
750 return (get_char_typeW(wc) & C1_SPACE) != 0;
753 /*************************************************************************
754 * @ [SHLWAPI.30]
756 * Determine if a Unicode character is a blank.
758 * PARAMS
759 * wc [I] Character to check.
761 * RETURNS
762 * TRUE, if wc is a blank,
763 * FALSE otherwise.
766 BOOL WINAPI IsCharBlankW(WCHAR wc)
768 return (get_char_typeW(wc) & C1_BLANK) != 0;
771 /*************************************************************************
772 * @ [SHLWAPI.31]
774 * Determine if a Unicode character is punctuation.
776 * PARAMS
777 * wc [I] Character to check.
779 * RETURNS
780 * TRUE, if wc is punctuation,
781 * FALSE otherwise.
783 BOOL WINAPI IsCharPunctW(WCHAR wc)
785 return (get_char_typeW(wc) & C1_PUNCT) != 0;
788 /*************************************************************************
789 * @ [SHLWAPI.32]
791 * Determine if a Unicode character is a control character.
793 * PARAMS
794 * wc [I] Character to check.
796 * RETURNS
797 * TRUE, if wc is a control character,
798 * FALSE otherwise.
800 BOOL WINAPI IsCharCntrlW(WCHAR wc)
802 return (get_char_typeW(wc) & C1_CNTRL) != 0;
805 /*************************************************************************
806 * @ [SHLWAPI.33]
808 * Determine if a Unicode character is a digit.
810 * PARAMS
811 * wc [I] Character to check.
813 * RETURNS
814 * TRUE, if wc is a digit,
815 * FALSE otherwise.
817 BOOL WINAPI IsCharDigitW(WCHAR wc)
819 return (get_char_typeW(wc) & C1_DIGIT) != 0;
822 /*************************************************************************
823 * @ [SHLWAPI.34]
825 * Determine if a Unicode character is a hex digit.
827 * PARAMS
828 * wc [I] Character to check.
830 * RETURNS
831 * TRUE, if wc is a hex digit,
832 * FALSE otherwise.
834 BOOL WINAPI IsCharXDigitW(WCHAR wc)
836 return (get_char_typeW(wc) & C1_XDIGIT) != 0;
839 /*************************************************************************
840 * @ [SHLWAPI.35]
843 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
845 FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
846 return TRUE;
849 /*************************************************************************
850 * @ [SHLWAPI.36]
852 * Insert a bitmap menu item at the bottom of a menu.
854 * PARAMS
855 * hMenu [I] Menu to insert into
856 * flags [I] Flags for insertion
857 * id [I] Menu ID of the item
858 * str [I] Menu text for the item
860 * RETURNS
861 * Success: TRUE, the item is inserted into the menu
862 * Failure: FALSE, if any parameter is invalid
864 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
866 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
867 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
870 /*************************************************************************
871 * @ [SHLWAPI.74]
873 * Get the text from a given dialog item.
875 * PARAMS
876 * hWnd [I] Handle of dialog
877 * nItem [I] Index of item
878 * lpsDest [O] Buffer for receiving window text
879 * nDestLen [I] Length of buffer.
881 * RETURNS
882 * Success: The length of the returned text.
883 * Failure: 0.
885 INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
887 HWND hItem = GetDlgItem(hWnd, nItem);
889 if (hItem)
890 return GetWindowTextW(hItem, lpsDest, nDestLen);
891 if (nDestLen)
892 *lpsDest = (WCHAR)'\0';
893 return 0;
896 /*************************************************************************
897 * @ [SHLWAPI.138]
899 * Set the text of a given dialog item.
901 * PARAMS
902 * hWnd [I] Handle of dialog
903 * iItem [I] Index of item
904 * lpszText [O] Text to set
906 * RETURNS
907 * Success: TRUE. The text of the dialog is set to lpszText.
908 * Failure: FALSE, Otherwise.
910 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
912 HWND hWndItem = GetDlgItem(hWnd, iItem);
913 if (hWndItem)
914 return SetWindowTextW(hWndItem, lpszText);
915 return FALSE;
918 /*************************************************************************
919 * @ [SHLWAPI.151]
921 * Compare two Ascii strings up to a given length.
923 * PARAMS
924 * lpszSrc [I] Source string
925 * lpszCmp [I] String to compare to lpszSrc
926 * len [I] Maximum length
928 * RETURNS
929 * A number greater than, less than or equal to 0 depending on whether
930 * lpszSrc is greater than, less than or equal to lpszCmp.
932 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
934 return strncmp(lpszSrc, lpszCmp, len);
937 /*************************************************************************
938 * @ [SHLWAPI.152]
940 * Unicode version of StrCmpNCA.
942 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
944 return strncmpW(lpszSrc, lpszCmp, len);
947 /*************************************************************************
948 * @ [SHLWAPI.153]
950 * Compare two Ascii strings up to a given length, ignoring case.
952 * PARAMS
953 * lpszSrc [I] Source string
954 * lpszCmp [I] String to compare to lpszSrc
955 * len [I] Maximum length
957 * RETURNS
958 * A number greater than, less than or equal to 0 depending on whether
959 * lpszSrc is greater than, less than or equal to lpszCmp.
961 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
963 return strncasecmp(lpszSrc, lpszCmp, len);
966 /*************************************************************************
967 * @ [SHLWAPI.154]
969 * Unicode version of StrCmpNICA.
971 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
973 return strncmpiW(lpszSrc, lpszCmp, len);
976 /*************************************************************************
977 * @ [SHLWAPI.155]
979 * Compare two Ascii strings.
981 * PARAMS
982 * lpszSrc [I] Source string
983 * lpszCmp [I] String to compare to lpszSrc
985 * RETURNS
986 * A number greater than, less than or equal to 0 depending on whether
987 * lpszSrc is greater than, less than or equal to lpszCmp.
989 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
991 return strcmp(lpszSrc, lpszCmp);
994 /*************************************************************************
995 * @ [SHLWAPI.156]
997 * Unicode version of StrCmpCA.
999 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1001 return strcmpW(lpszSrc, lpszCmp);
1004 /*************************************************************************
1005 * @ [SHLWAPI.157]
1007 * Compare two Ascii strings, ignoring case.
1009 * PARAMS
1010 * lpszSrc [I] Source string
1011 * lpszCmp [I] String to compare to lpszSrc
1013 * RETURNS
1014 * A number greater than, less than or equal to 0 depending on whether
1015 * lpszSrc is greater than, less than or equal to lpszCmp.
1017 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
1019 return strcasecmp(lpszSrc, lpszCmp);
1022 /*************************************************************************
1023 * @ [SHLWAPI.158]
1025 * Unicode version of StrCmpICA.
1027 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1029 return strcmpiW(lpszSrc, lpszCmp);
1032 /*************************************************************************
1033 * @ [SHLWAPI.160]
1035 * Get an identification string for the OS and explorer.
1037 * PARAMS
1038 * lpszDest [O] Destination for Id string
1039 * dwDestLen [I] Length of lpszDest
1041 * RETURNS
1042 * TRUE, If the string was created successfully
1043 * FALSE, Otherwise
1045 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
1047 WCHAR buff[2084];
1049 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1051 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
1053 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1054 return TRUE;
1056 return FALSE;
1059 /*************************************************************************
1060 * @ [SHLWAPI.161]
1062 * Unicode version of SHAboutInfoA.
1064 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
1066 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
1067 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1068 ' ','E','x','p','l','o','r','e','r','\0' };
1069 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
1070 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
1071 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1072 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
1073 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1074 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1075 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
1076 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1077 ' ','E','x','p','l','o','r','e','r','\\',
1078 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
1079 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
1080 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
1081 'V','e','r','s','i','o','n','\0' };
1082 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
1083 'O','w','n','e','r','\0' };
1084 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
1085 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
1086 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
1087 static const WCHAR szUpdate[] = { 'I','E','A','K',
1088 'U','p','d','a','t','e','U','r','l','\0' };
1089 static const WCHAR szHelp[] = { 'I','E','A','K',
1090 'H','e','l','p','S','t','r','i','n','g','\0' };
1091 WCHAR buff[2084];
1092 HKEY hReg;
1093 DWORD dwType, dwLen;
1095 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1097 if (!lpszDest)
1098 return FALSE;
1100 *lpszDest = '\0';
1102 /* Try the NT key first, followed by 95/98 key */
1103 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
1104 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
1105 return FALSE;
1107 /* OS Version */
1108 buff[0] = '\0';
1109 dwLen = 30;
1110 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1112 DWORD dwStrLen = strlenW(buff);
1113 dwLen = 30 - dwStrLen;
1114 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1115 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1117 StrCatBuffW(lpszDest, buff, dwDestLen);
1119 /* ~Registered Owner */
1120 buff[0] = '~';
1121 dwLen = 256;
1122 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
1123 buff[1] = '\0';
1124 StrCatBuffW(lpszDest, buff, dwDestLen);
1126 /* ~Registered Organization */
1127 dwLen = 256;
1128 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
1129 buff[1] = '\0';
1130 StrCatBuffW(lpszDest, buff, dwDestLen);
1132 /* FIXME: Not sure where this number comes from */
1133 buff[0] = '~';
1134 buff[1] = '0';
1135 buff[2] = '\0';
1136 StrCatBuffW(lpszDest, buff, dwDestLen);
1138 /* ~Product Id */
1139 dwLen = 256;
1140 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1141 buff[1] = '\0';
1142 StrCatBuffW(lpszDest, buff, dwDestLen);
1144 /* ~IE Update Url */
1145 dwLen = 2048;
1146 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1147 buff[1] = '\0';
1148 StrCatBuffW(lpszDest, buff, dwDestLen);
1150 /* ~IE Help String */
1151 dwLen = 256;
1152 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1153 buff[1] = '\0';
1154 StrCatBuffW(lpszDest, buff, dwDestLen);
1156 RegCloseKey(hReg);
1157 return TRUE;
1160 /*************************************************************************
1161 * @ [SHLWAPI.163]
1163 * Call IOleCommandTarget_QueryStatus() on an object.
1165 * PARAMS
1166 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1167 * pguidCmdGroup [I] GUID for the command group
1168 * cCmds [I]
1169 * prgCmds [O] Commands
1170 * pCmdText [O] Command text
1172 * RETURNS
1173 * Success: S_OK.
1174 * Failure: E_FAIL, if lpUnknown is NULL.
1175 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1176 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1178 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1179 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1181 HRESULT hRet = E_FAIL;
1183 TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1185 if (lpUnknown)
1187 IOleCommandTarget* lpOle;
1189 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1190 (void**)&lpOle);
1192 if (SUCCEEDED(hRet) && lpOle)
1194 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1195 prgCmds, pCmdText);
1196 IOleCommandTarget_Release(lpOle);
1199 return hRet;
1202 /*************************************************************************
1203 * @ [SHLWAPI.164]
1205 * Call IOleCommandTarget_Exec() on an object.
1207 * PARAMS
1208 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1209 * pguidCmdGroup [I] GUID for the command group
1211 * RETURNS
1212 * Success: S_OK.
1213 * Failure: E_FAIL, if lpUnknown is NULL.
1214 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1215 * Otherwise, an error code from IOleCommandTarget_Exec().
1217 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1218 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1219 VARIANT* pvaOut)
1221 HRESULT hRet = E_FAIL;
1223 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1224 nCmdexecopt, pvaIn, pvaOut);
1226 if (lpUnknown)
1228 IOleCommandTarget* lpOle;
1230 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1231 (void**)&lpOle);
1232 if (SUCCEEDED(hRet) && lpOle)
1234 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1235 nCmdexecopt, pvaIn, pvaOut);
1236 IOleCommandTarget_Release(lpOle);
1239 return hRet;
1242 /*************************************************************************
1243 * @ [SHLWAPI.165]
1245 * Retrieve, modify, and re-set a value from a window.
1247 * PARAMS
1248 * hWnd [I] Window to get value from
1249 * offset [I] Offset of value
1250 * wMask [I] Mask for uiFlags
1251 * wFlags [I] Bits to set in window value
1253 * RETURNS
1254 * The new value as it was set, or 0 if any parameter is invalid.
1256 * NOTES
1257 * Any bits set in uiMask are cleared from the value, then any bits set in
1258 * uiFlags are set in the value.
1260 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1262 LONG ret = GetWindowLongA(hwnd, offset);
1263 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1265 if (newFlags != ret)
1266 ret = SetWindowLongA(hwnd, offset, newFlags);
1267 return ret;
1270 /*************************************************************************
1271 * @ [SHLWAPI.167]
1273 * Change a window's parent.
1275 * PARAMS
1276 * hWnd [I] Window to change parent of
1277 * hWndParent [I] New parent window
1279 * RETURNS
1280 * The old parent of hWnd.
1282 * NOTES
1283 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1284 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1286 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1288 TRACE("%p, %p\n", hWnd, hWndParent);
1290 if(GetParent(hWnd) == hWndParent)
1291 return 0;
1293 if(hWndParent)
1294 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1295 else
1296 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1298 return SetParent(hWnd, hWndParent);
1301 /*************************************************************************
1302 * @ [SHLWAPI.168]
1304 * Locate and advise a connection point in an IConnectionPointContainer object.
1306 * PARAMS
1307 * lpUnkSink [I] Sink for the connection point advise call
1308 * riid [I] REFIID of connection point to advise
1309 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1310 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1311 * lpCookie [O] Pointer to connection point cookie
1312 * lppCP [O] Destination for the IConnectionPoint found
1314 * RETURNS
1315 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1316 * that was advised. The caller is responsable for releasing it.
1317 * Failure: E_FAIL, if any arguments are invalid.
1318 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1319 * Or an HRESULT error code if any call fails.
1321 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1322 IUnknown* lpUnknown, LPDWORD lpCookie,
1323 IConnectionPoint **lppCP)
1325 HRESULT hRet;
1326 IConnectionPointContainer* lpContainer;
1327 IConnectionPoint *lpCP;
1329 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1330 return E_FAIL;
1332 if(lppCP)
1333 *lppCP = NULL;
1335 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1336 (void**)&lpContainer);
1337 if (SUCCEEDED(hRet))
1339 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1341 if (SUCCEEDED(hRet))
1343 if(!bAdviseOnly)
1344 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1345 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1347 if (FAILED(hRet))
1348 *lpCookie = 0;
1350 if (lppCP && SUCCEEDED(hRet))
1351 *lppCP = lpCP; /* Caller keeps the interface */
1352 else
1353 IConnectionPoint_Release(lpCP); /* Release it */
1356 IUnknown_Release(lpContainer);
1358 return hRet;
1361 /*************************************************************************
1362 * @ [SHLWAPI.169]
1364 * Release an interface.
1366 * PARAMS
1367 * lpUnknown [I] Object to release
1369 * RETURNS
1370 * Nothing.
1372 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1374 IUnknown *temp;
1376 TRACE("(%p)\n",lpUnknown);
1378 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1379 temp = *lpUnknown;
1380 *lpUnknown = NULL;
1382 TRACE("doing Release\n");
1384 return IUnknown_Release(temp);
1387 /*************************************************************************
1388 * @ [SHLWAPI.170]
1390 * Skip '//' if present in a string.
1392 * PARAMS
1393 * lpszSrc [I] String to check for '//'
1395 * RETURNS
1396 * Success: The next character after the '//' or the string if not present
1397 * Failure: NULL, if lpszStr is NULL.
1399 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1401 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1402 lpszSrc += 2;
1403 return lpszSrc;
1406 /*************************************************************************
1407 * @ [SHLWAPI.171]
1409 * Check if two interfaces come from the same object.
1411 * PARAMS
1412 * lpInt1 [I] Interface to check against lpInt2.
1413 * lpInt2 [I] Interface to check against lpInt1.
1415 * RETURNS
1416 * TRUE, If the interfaces come from the same object.
1417 * FALSE Otherwise.
1419 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1421 LPVOID lpUnknown1, lpUnknown2;
1423 TRACE("%p %p\n", lpInt1, lpInt2);
1425 if (!lpInt1 || !lpInt2)
1426 return FALSE;
1428 if (lpInt1 == lpInt2)
1429 return TRUE;
1431 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1432 (LPVOID *)&lpUnknown1)))
1433 return FALSE;
1435 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1436 (LPVOID *)&lpUnknown2)))
1437 return FALSE;
1439 if (lpUnknown1 == lpUnknown2)
1440 return TRUE;
1442 return FALSE;
1445 /*************************************************************************
1446 * @ [SHLWAPI.172]
1448 * Get the window handle of an object.
1450 * PARAMS
1451 * lpUnknown [I] Object to get the window handle of
1452 * lphWnd [O] Destination for window handle
1454 * RETURNS
1455 * Success: S_OK. lphWnd contains the objects window handle.
1456 * Failure: An HRESULT error code.
1458 * NOTES
1459 * lpUnknown is expected to support one of the following interfaces:
1460 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1462 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1464 /* FIXME: Wine has no header for this object */
1465 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1466 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1467 IUnknown *lpOle;
1468 HRESULT hRet = E_FAIL;
1470 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1472 if (!lpUnknown)
1473 return hRet;
1475 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1477 if (FAILED(hRet))
1479 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1481 if (FAILED(hRet))
1483 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1484 (void**)&lpOle);
1488 if (SUCCEEDED(hRet))
1490 /* Lazyness here - Since GetWindow() is the first method for the above 3
1491 * interfaces, we use the same call for them all.
1493 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1494 IUnknown_Release(lpOle);
1495 if (lphWnd)
1496 TRACE("Returning HWND=%p\n", *lphWnd);
1499 return hRet;
1502 /*************************************************************************
1503 * @ [SHLWAPI.173]
1505 * Call a method on as as yet unidentified object.
1507 * PARAMS
1508 * pUnk [I] Object supporting the unidentified interface,
1509 * arg [I] Argument for the call on the object.
1511 * RETURNS
1512 * S_OK.
1514 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1516 static const GUID guid_173 = {
1517 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1519 IMalloc *pUnk2;
1521 TRACE("(%p,%ld)\n", pUnk, arg);
1523 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1524 * We use this interface as its vtable entry is compatible with the
1525 * object in question.
1526 * FIXME: Find out what this object is and where it should be defined.
1528 if (pUnk &&
1529 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1531 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1532 IMalloc_Release(pUnk2);
1534 return S_OK;
1537 /*************************************************************************
1538 * @ [SHLWAPI.174]
1540 * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
1541 * an interface.
1543 * RETURNS
1544 * Success: S_OK.
1545 * Failure: E_FAIL, if p1 is NULL.
1546 * E_NOINTERFACE If p1 does not support the IPersist interface,
1547 * Or an HRESULT error code.
1549 DWORD WINAPI IUnknown_SetSite(
1550 IUnknown *p1, /* [in] OLE object */
1551 LPVOID *p2) /* [out] ptr for call results */
1553 DWORD ret, aa;
1555 if (!p1) return E_FAIL;
1557 /* see if SetSite interface exists for IObjectWithSite object */
1558 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1559 TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1560 if (ret) {
1562 /* see if GetClassId interface exists for IPersistMoniker object */
1563 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1564 TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1565 if (ret) return ret;
1567 /* fake a GetClassId call */
1568 ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1569 TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1570 *(LPDWORD)p2);
1571 IUnknown_Release((IUnknown *)aa);
1573 else {
1574 /* fake a SetSite call */
1575 ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1576 TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1577 *(LPDWORD)p2);
1578 IUnknown_Release((IUnknown *)p1);
1580 return ret;
1583 /*************************************************************************
1584 * @ [SHLWAPI.175]
1586 * Call IPersist_GetClassID() on an object.
1588 * PARAMS
1589 * lpUnknown [I] Object supporting the IPersist interface
1590 * lpClassId [O] Destination for Class Id
1592 * RETURNS
1593 * Success: S_OK. lpClassId contains the Class Id requested.
1594 * Failure: E_FAIL, If lpUnknown is NULL,
1595 * E_NOINTERFACE If lpUnknown does not support IPersist,
1596 * Or an HRESULT error code.
1598 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1600 IPersist* lpPersist;
1601 HRESULT hRet = E_FAIL;
1603 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1605 if (lpUnknown)
1607 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1608 if (SUCCEEDED(hRet))
1610 IPersist_GetClassID(lpPersist, lpClassId);
1611 IPersist_Release(lpPersist);
1614 return hRet;
1617 /*************************************************************************
1618 * @ [SHLWAPI.176]
1620 * Retrieve a Service Interface from an object.
1622 * PARAMS
1623 * lpUnknown [I] Object to get an IServiceProvider interface from
1624 * sid [I] Service ID for IServiceProvider_QueryService() call
1625 * riid [I] Function requested for QueryService call
1626 * lppOut [O] Destination for the service interface pointer
1628 * RETURNS
1629 * Success: S_OK. lppOut contains an object providing the requested service
1630 * Failure: An HRESULT error code
1632 * NOTES
1633 * lpUnknown is expected to support the IServiceProvider interface.
1635 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1636 LPVOID *lppOut)
1638 IServiceProvider* pService = NULL;
1639 HRESULT hRet;
1641 if (!lppOut)
1642 return E_FAIL;
1644 *lppOut = NULL;
1646 if (!lpUnknown)
1647 return E_FAIL;
1649 /* Get an IServiceProvider interface from the object */
1650 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1651 (LPVOID*)&pService);
1653 if (!hRet && pService)
1655 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1657 /* Get a Service interface from the object */
1658 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1660 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1662 /* Release the IServiceProvider interface */
1663 IUnknown_Release(pService);
1665 return hRet;
1668 /*************************************************************************
1669 * @ [SHLWAPI.177]
1671 * Loads a popup menu.
1673 * PARAMS
1674 * hInst [I] Instance handle
1675 * szName [I] Menu name
1677 * RETURNS
1678 * Success: TRUE.
1679 * Failure: FALSE.
1681 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1683 HMENU hMenu, hSubMenu;
1685 if ((hMenu = LoadMenuW(hInst, szName)))
1687 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1688 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1690 DestroyMenu(hMenu);
1691 return TRUE;
1693 return FALSE;
1696 typedef struct _enumWndData
1698 UINT uiMsgId;
1699 WPARAM wParam;
1700 LPARAM lParam;
1701 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1702 } enumWndData;
1704 /* Callback for SHLWAPI_178 */
1705 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1707 enumWndData *data = (enumWndData *)lParam;
1709 TRACE("(%p,%p)\n", hWnd, data);
1710 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1711 return TRUE;
1714 /*************************************************************************
1715 * @ [SHLWAPI.178]
1717 * Send or post a message to every child of a window.
1719 * PARAMS
1720 * hWnd [I] Window whose children will get the messages
1721 * uiMsgId [I] Message Id
1722 * wParam [I] WPARAM of message
1723 * lParam [I] LPARAM of message
1724 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1726 * RETURNS
1727 * Nothing.
1729 * NOTES
1730 * The appropriate ASCII or Unicode function is called for the window.
1732 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1734 enumWndData data;
1736 TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1738 if(hWnd)
1740 data.uiMsgId = uiMsgId;
1741 data.wParam = wParam;
1742 data.lParam = lParam;
1744 if (bSend)
1745 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1746 else
1747 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1749 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1753 /*************************************************************************
1754 * @ [SHLWAPI.180]
1756 * Remove all sub-menus from a menu.
1758 * PARAMS
1759 * hMenu [I] Menu to remove sub-menus from
1761 * RETURNS
1762 * Success: 0. All sub-menus under hMenu are removed
1763 * Failure: -1, if any parameter is invalid
1765 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1767 int iItemCount = GetMenuItemCount(hMenu) - 1;
1768 while (iItemCount >= 0)
1770 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1771 if (hSubMenu)
1772 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1773 iItemCount--;
1775 return iItemCount;
1778 /*************************************************************************
1779 * @ [SHLWAPI.181]
1781 * Enable or disable a menu item.
1783 * PARAMS
1784 * hMenu [I] Menu holding menu item
1785 * uID [I] ID of menu item to enable/disable
1786 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1788 * RETURNS
1789 * The return code from EnableMenuItem.
1791 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1793 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1796 /*************************************************************************
1797 * @ [SHLWAPI.182]
1799 * Check or uncheck a menu item.
1801 * PARAMS
1802 * hMenu [I] Menu holding menu item
1803 * uID [I] ID of menu item to check/uncheck
1804 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1806 * RETURNS
1807 * The return code from CheckMenuItem.
1809 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1811 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1814 /*************************************************************************
1815 * @ [SHLWAPI.183]
1817 * Register a window class if it isn't already.
1819 * PARAMS
1820 * lpWndClass [I] Window class to register
1822 * RETURNS
1823 * The result of the RegisterClassA call.
1825 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1827 WNDCLASSA wca;
1828 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1829 return TRUE;
1830 return (DWORD)RegisterClassA(wndclass);
1833 /*************************************************************************
1834 * @ [SHLWAPI.187]
1836 * Call IPersistPropertyBag_Load() on an object.
1838 * PARAMS
1839 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1840 * lpPropBag [O] Destination for loaded IPropertyBag
1842 * RETURNS
1843 * Success: S_OK.
1844 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1846 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1848 IPersistPropertyBag* lpPPBag;
1849 HRESULT hRet = E_FAIL;
1851 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1853 if (lpUnknown)
1855 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1856 (void**)&lpPPBag);
1857 if (SUCCEEDED(hRet) && lpPPBag)
1859 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1860 IPersistPropertyBag_Release(lpPPBag);
1863 return hRet;
1866 /*************************************************************************
1867 * @ [SHLWAPI.189]
1869 * Call IOleControlSite_GetExtendedControl() on an object.
1871 * PARAMS
1872 * lpUnknown [I] Object supporting the IOleControlSite interface
1873 * lppDisp [O] Destination for resulting IDispatch.
1875 * RETURNS
1876 * Success: S_OK.
1877 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1879 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1881 IOleControlSite* lpCSite;
1882 HRESULT hRet = E_FAIL;
1884 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1885 if (lpUnknown)
1887 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1888 (void**)&lpCSite);
1889 if (SUCCEEDED(hRet) && lpCSite)
1891 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1892 IOleControlSite_Release(lpCSite);
1895 return hRet;
1898 /*************************************************************************
1899 * @ [SHLWAPI.192]
1901 * Get a sub-menu from a menu item.
1903 * PARAMS
1904 * hMenu [I] Menu to get sub-menu from
1905 * uID [I] ID of menu item containing sub-menu
1907 * RETURNS
1908 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1910 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1912 MENUITEMINFOA mi;
1914 TRACE("(%p,%uld)\n", hMenu, uID);
1916 mi.cbSize = sizeof(MENUITEMINFOA);
1917 mi.fMask = MIIM_SUBMENU;
1919 if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
1920 return (HMENU)NULL;
1922 return mi.hSubMenu;
1925 /*************************************************************************
1926 * @ [SHLWAPI.193]
1928 * Get the color depth of the primary display.
1930 * PARAMS
1931 * None.
1933 * RETURNS
1934 * The color depth of the primary display.
1936 DWORD WINAPI SHGetCurColorRes()
1938 HDC hdc;
1939 DWORD ret;
1941 TRACE("()\n");
1943 hdc = GetDC(0);
1944 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1945 ReleaseDC(0, hdc);
1946 return ret;
1949 /*************************************************************************
1950 * @ [SHLWAPI.194]
1952 * Wait for a message to arrive, with a timeout.
1954 * PARAMS
1955 * hand [I] Handle to query
1956 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1958 * RETURNS
1959 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1960 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1961 * message is available.
1963 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1965 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1966 DWORD dwRet;
1968 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1970 MSG msg;
1972 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1974 if (dwTimeout != INFINITE)
1976 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1977 return WAIT_TIMEOUT;
1981 return dwRet;
1984 /*************************************************************************
1985 * @ [SHLWAPI.197]
1987 * Blank out a region of text by drawing the background only.
1989 * PARAMS
1990 * hDC [I] Device context to draw in
1991 * pRect [I] Area to draw in
1992 * cRef [I] Color to draw in
1994 * RETURNS
1995 * Nothing.
1997 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
1999 COLORREF cOldColor = SetBkColor(hDC, cRef);
2000 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2001 SetBkColor(hDC, cOldColor);
2002 return 0;
2005 /*************************************************************************
2006 * @ [SHLWAPI.198]
2008 * Return the value asociated with a key in a map.
2010 * PARAMS
2011 * lpKeys [I] A list of keys of length iLen
2012 * lpValues [I] A list of values associated with lpKeys, of length iLen
2013 * iLen [I] Length of both lpKeys and lpValues
2014 * iKey [I] The key value to look up in lpKeys
2016 * RETURNS
2017 * The value in lpValues associated with iKey, or -1 if iKey is not
2018 * found in lpKeys.
2020 * NOTES
2021 * - If two elements in the map share the same key, this function returns
2022 * the value closest to the start of the map
2023 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2025 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2027 if (lpKeys && lpValues)
2029 int i = 0;
2031 while (i < iLen)
2033 if (lpKeys[i] == iKey)
2034 return lpValues[i]; /* Found */
2035 i++;
2038 return -1; /* Not found */
2042 /*************************************************************************
2043 * @ [SHLWAPI.199]
2045 * Copy an interface pointer
2047 * PARAMS
2048 * lppDest [O] Destination for copy
2049 * lpUnknown [I] Source for copy
2051 * RETURNS
2052 * Nothing.
2054 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2056 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2058 if (lppDest)
2059 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2061 if (lpUnknown)
2063 /* Copy */
2064 IUnknown_AddRef(lpUnknown);
2065 *lppDest = lpUnknown;
2069 /*************************************************************************
2070 * @ [SHLWAPI.201]
2073 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2074 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2075 VARIANT* pvaOut)
2077 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2078 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2079 return DRAGDROP_E_NOTREGISTERED;
2082 /*************************************************************************
2083 * @ [SHLWAPI.202]
2086 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2088 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2089 return DRAGDROP_E_NOTREGISTERED;
2092 /*************************************************************************
2093 * @ [SHLWAPI.204]
2095 * Determine if a window is not a child of another window.
2097 * PARAMS
2098 * hParent [I] Suspected parent window
2099 * hChild [I] Suspected child window
2101 * RETURNS
2102 * TRUE: If hChild is a child window of hParent
2103 * FALSE: If hChild is not a child window of hParent, or they are equal
2105 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2107 TRACE("(%p,%p)\n", hParent, hChild);
2109 if (!hParent || !hChild)
2110 return TRUE;
2111 else if(hParent == hChild)
2112 return FALSE;
2113 return !IsChild(hParent, hChild);
2116 /*************************************************************************
2117 * @ [SHLWAPI.208]
2119 * Some sort of memory management process.
2121 DWORD WINAPI FDSA_Initialize(
2122 DWORD a,
2123 DWORD b,
2124 LPVOID c,
2125 LPVOID d,
2126 DWORD e)
2128 FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2129 a, b, c, d, e);
2130 return 1;
2133 /*************************************************************************
2134 * @ [SHLWAPI.209]
2136 * Some sort of memory management process.
2138 DWORD WINAPI FDSA_Destroy(
2139 LPVOID a)
2141 FIXME("(%p) stub\n",
2143 return 1;
2146 /*************************************************************************
2147 * @ [SHLWAPI.210]
2149 * Some sort of memory management process.
2151 DWORD WINAPI FDSA_InsertItem(
2152 LPVOID a,
2153 DWORD b,
2154 LPVOID c)
2156 FIXME("(%p 0x%08lx %p) stub\n",
2157 a, b, c);
2158 return 0;
2161 /*************************************************************************
2162 * @ [SHLWAPI.211]
2164 DWORD WINAPI FDSA_DeleteItem(
2165 LPVOID a,
2166 DWORD b)
2168 FIXME("(%p 0x%08lx) stub\n",
2169 a, b);
2170 return 1;
2173 typedef struct {
2174 REFIID refid;
2175 DWORD indx;
2176 } IFACE_INDEX_TBL;
2178 /*************************************************************************
2179 * @ [SHLWAPI.219]
2181 * Call IUnknown_QueryInterface() on a table of objects.
2183 * RETURNS
2184 * Success: S_OK.
2185 * Failure: E_POINTER or E_NOINTERFACE.
2187 HRESULT WINAPI QISearch(
2188 LPVOID w, /* [in] Table of interfaces */
2189 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2190 REFIID riid, /* [in] REFIID to get interface for */
2191 LPVOID *ppv) /* [out] Destination for interface pointer */
2193 HRESULT ret;
2194 IUnknown *a_vtbl;
2195 IFACE_INDEX_TBL *xmove;
2197 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2198 if (ppv) {
2199 xmove = x;
2200 while (xmove->refid) {
2201 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2202 if (IsEqualIID(riid, xmove->refid)) {
2203 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2204 TRACE("matched, returning (%p)\n", a_vtbl);
2205 *ppv = (LPVOID)a_vtbl;
2206 IUnknown_AddRef(a_vtbl);
2207 return S_OK;
2209 xmove++;
2212 if (IsEqualIID(riid, &IID_IUnknown)) {
2213 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2214 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2215 *ppv = (LPVOID)a_vtbl;
2216 IUnknown_AddRef(a_vtbl);
2217 return S_OK;
2219 *ppv = 0;
2220 ret = E_NOINTERFACE;
2221 } else
2222 ret = E_POINTER;
2224 TRACE("-- 0x%08lx\n", ret);
2225 return ret;
2228 /*************************************************************************
2229 * @ [SHLWAPI.221]
2231 * Remove the "PropDlgFont" property from a window.
2233 * PARAMS
2234 * hWnd [I] Window to remove the property from
2236 * RETURNS
2237 * A handle to the removed property, or NULL if it did not exist.
2239 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2241 HANDLE hProp;
2243 TRACE("(%p)\n", hWnd);
2245 hProp = GetPropA(hWnd, "PropDlgFont");
2247 if(hProp)
2249 DeleteObject(hProp);
2250 hProp = RemovePropA(hWnd, "PropDlgFont");
2252 return hProp;
2255 /*************************************************************************
2256 * @ [SHLWAPI.236]
2258 * Load the in-process server of a given GUID.
2260 * PARAMS
2261 * refiid [I] GUID of the server to load.
2263 * RETURNS
2264 * Success: A handle to the loaded server dll.
2265 * Failure: A NULL handle.
2267 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2269 HKEY newkey;
2270 DWORD type, count;
2271 CHAR value[MAX_PATH], string[MAX_PATH];
2273 strcpy(string, "CLSID\\");
2274 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2275 strcat(string, "\\InProcServer32");
2277 count = MAX_PATH;
2278 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2279 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2280 RegCloseKey(newkey);
2281 return LoadLibraryExA(value, 0, 0);
2284 /*************************************************************************
2285 * @ [SHLWAPI.237]
2287 * Unicode version of SHLWAPI_183.
2289 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2291 WNDCLASSW WndClass;
2293 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2295 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2296 return TRUE;
2297 return RegisterClassW(lpWndClass);
2300 /*************************************************************************
2301 * @ [SHLWAPI.238]
2303 * Unregister a list of classes.
2305 * PARAMS
2306 * hInst [I] Application instance that registered the classes
2307 * lppClasses [I] List of class names
2308 * iCount [I] Number of names in lppClasses
2310 * RETURNS
2311 * Nothing.
2313 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2315 WNDCLASSA WndClass;
2317 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2319 while (iCount > 0)
2321 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2322 UnregisterClassA(*lppClasses, hInst);
2323 lppClasses++;
2324 iCount--;
2328 /*************************************************************************
2329 * @ [SHLWAPI.239]
2331 * Unicode version of SHUnregisterClassesA.
2333 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2335 WNDCLASSW WndClass;
2337 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2339 while (iCount > 0)
2341 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2342 UnregisterClassW(*lppClasses, hInst);
2343 lppClasses++;
2344 iCount--;
2348 /*************************************************************************
2349 * @ [SHLWAPI.240]
2351 * Call The correct (Ascii/Unicode) default window procedure for a window.
2353 * PARAMS
2354 * hWnd [I] Window to call the default procedure for
2355 * uMessage [I] Message ID
2356 * wParam [I] WPARAM of message
2357 * lParam [I] LPARAM of message
2359 * RETURNS
2360 * The result of calling DefWindowProcA() or DefWindowProcW().
2362 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2364 if (IsWindowUnicode(hWnd))
2365 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2366 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2369 /*************************************************************************
2370 * @ [SHLWAPI.257]
2372 * Create a worker window using CreateWindowExA().
2374 * PARAMS
2375 * wndProc [I] Window procedure
2376 * hWndParent [I] Parent window
2377 * dwExStyle [I] Extra style flags
2378 * dwStyle [I] Style flags
2379 * hMenu [I] Window menu
2380 * z [I] Unknown
2382 * RETURNS
2383 * Success: The window handle of the newly created window.
2384 * Failure: 0.
2386 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2387 DWORD dwStyle, HMENU hMenu, LONG z)
2389 static const char* szClass = "WorkerA";
2390 WNDCLASSA wc;
2391 HWND hWnd;
2393 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2394 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2396 /* Create Window class */
2397 wc.style = 0;
2398 wc.lpfnWndProc = DefWindowProcA;
2399 wc.cbClsExtra = 0;
2400 wc.cbWndExtra = 4;
2401 wc.hInstance = shlwapi_hInstance;
2402 wc.hIcon = (HICON)0;
2403 wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
2404 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2405 wc.lpszMenuName = NULL;
2406 wc.lpszClassName = szClass;
2408 SHRegisterClassA(&wc); /* Register class */
2410 /* FIXME: Set extra bits in dwExStyle */
2412 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2413 hWndParent, hMenu, shlwapi_hInstance, 0);
2414 if (hWnd)
2416 SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2418 if (wndProc)
2419 SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
2421 return hWnd;
2424 typedef struct tagPOLICYDATA
2426 DWORD policy; /* flags value passed to SHRestricted */
2427 LPCWSTR appstr; /* application str such as "Explorer" */
2428 LPCWSTR keystr; /* name of the actual registry key / policy */
2429 } POLICYDATA, *LPPOLICYDATA;
2431 #define SHELL_NO_POLICY 0xffffffff
2433 /* default shell policy registry key */
2434 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2435 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2436 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2437 '\\','P','o','l','i','c','i','e','s',0};
2439 /*************************************************************************
2440 * @ [SHLWAPI.271]
2442 * Retrieve a policy value from the registry.
2444 * PARAMS
2445 * lpSubKey [I] registry key name
2446 * lpSubName [I] subname of registry key
2447 * lpValue [I] value name of registry value
2449 * RETURNS
2450 * the value associated with the registry key or 0 if not found
2452 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2454 DWORD retval, datsize = sizeof(retval);
2455 HKEY hKey;
2457 if (!lpSubKey)
2458 lpSubKey = strRegistryPolicyW;
2460 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2461 if (retval != ERROR_SUCCESS)
2462 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2463 if (retval != ERROR_SUCCESS)
2464 return 0;
2466 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2467 RegCloseKey(hKey);
2468 return retval;
2471 /*************************************************************************
2472 * @ [SHLWAPI.266]
2474 * Helper function to retrieve the possibly cached value for a specific policy
2476 * PARAMS
2477 * policy [I] The policy to look for
2478 * initial [I] Main registry key to open, if NULL use default
2479 * polTable [I] Table of known policies, 0 terminated
2480 * polArr [I] Cache array of policy values
2482 * RETURNS
2483 * The retrieved policy value or 0 if not successful
2485 * NOTES
2486 * This function is used by the native SHRestricted function to search for the
2487 * policy and cache it once retrieved. The current Wine implementation uses a
2488 * different POLICYDATA structure and implements a similar algorithme adapted to
2489 * that structure.
2491 DWORD WINAPI SHRestrictionLookup(
2492 DWORD policy,
2493 LPCWSTR initial,
2494 LPPOLICYDATA polTable,
2495 LPDWORD polArr)
2497 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2499 if (!polTable || !polArr)
2500 return 0;
2502 for (;polTable->policy; polTable++, polArr++)
2504 if (policy == polTable->policy)
2506 /* we have a known policy */
2508 /* check if this policy has been cached */
2509 if (*polArr == SHELL_NO_POLICY)
2510 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2511 return *polArr;
2514 /* we don't know this policy, return 0 */
2515 TRACE("unknown policy: (%08lx)\n", policy);
2516 return 0;
2519 /*************************************************************************
2520 * @ [SHLWAPI.267]
2522 * Get an interface from an object.
2524 * RETURNS
2525 * Success: S_OK. ppv contains the requested interface.
2526 * Failure: An HRESULT error code.
2528 * NOTES
2529 * This QueryInterface asks the inner object for a interface. In case
2530 * of aggregation this request would be forwarded by the inner to the
2531 * outer object. This function asks the inner object directly for the
2532 * interface circumventing the forwarding to the outer object.
2534 HRESULT WINAPI SHWeakQueryInterface(
2535 IUnknown * pUnk, /* [in] Outer object */
2536 IUnknown * pInner, /* [in] Inner object */
2537 IID * riid, /* [in] Interface GUID to query for */
2538 LPVOID* ppv) /* [out] Destination for queried interface */
2540 HRESULT hret = E_NOINTERFACE;
2541 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2543 *ppv = NULL;
2544 if(pUnk && pInner) {
2545 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2546 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2548 TRACE("-- 0x%08lx\n", hret);
2549 return hret;
2552 /*************************************************************************
2553 * @ [SHLWAPI.268]
2555 * Move a reference from one interface to another.
2557 * PARAMS
2558 * lpDest [O] Destination to receive the reference
2559 * lppUnknown [O] Source to give up the reference to lpDest
2561 * RETURNS
2562 * Nothing.
2564 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2566 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2568 if (*lppUnknown)
2570 /* Copy Reference*/
2571 IUnknown_AddRef(lpDest);
2572 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2576 /*************************************************************************
2577 * @ [SHLWAPI.269]
2579 * Convert an ASCII string of a CLSID into a CLSID.
2581 * PARAMS
2582 * idstr [I] String representing a CLSID in registry format
2583 * id [O] Destination for the converted CLSID
2585 * RETURNS
2586 * Success: TRUE. id contains the converted CLSID.
2587 * Failure: FALSE.
2589 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2591 WCHAR wClsid[40];
2592 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2593 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2596 /*************************************************************************
2597 * @ [SHLWAPI.270]
2599 * Unicode version of GUIDFromStringA.
2601 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2603 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2606 /*************************************************************************
2607 * @ [SHLWAPI.276]
2609 * Determine if the browser is integrated into the shell, and set a registry
2610 * key accordingly.
2612 * PARAMS
2613 * None.
2615 * RETURNS
2616 * 1, If the browser is not integrated.
2617 * 2, If the browser is integrated.
2619 * NOTES
2620 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2621 * either set to TRUE, or removed depending on whether the browser is deemed
2622 * to be integrated.
2624 DWORD WINAPI WhichPlatform()
2626 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2627 static DWORD dwState = 0;
2628 HKEY hKey;
2629 DWORD dwRet, dwData, dwSize;
2631 if (dwState)
2632 return dwState;
2634 /* If shell32 exports DllGetVersion(), the browser is integrated */
2635 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2636 dwState = pDllGetVersion ? 2 : 1;
2638 /* Set or delete the key accordingly */
2639 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2640 "Software\\Microsoft\\Internet Explorer", 0,
2641 KEY_ALL_ACCESS, &hKey);
2642 if (!dwRet)
2644 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2645 (LPBYTE)&dwData, &dwSize);
2647 if (!dwRet && dwState == 1)
2649 /* Value exists but browser is not integrated */
2650 RegDeleteValueA(hKey, szIntegratedBrowser);
2652 else if (dwRet && dwState == 2)
2654 /* Browser is integrated but value does not exist */
2655 dwData = TRUE;
2656 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2657 (LPBYTE)&dwData, sizeof(dwData));
2659 RegCloseKey(hKey);
2661 return dwState;
2664 /*************************************************************************
2665 * @ [SHLWAPI.278]
2667 * Unicode version of SHCreateWorkerWindowA.
2669 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2670 DWORD dwStyle, HMENU hMenu, LONG z)
2672 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2673 WNDCLASSW wc;
2674 HWND hWnd;
2676 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2677 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2679 /* If our OS is natively ASCII, use the ASCII version */
2680 if (!(GetVersion() & 0x80000000)) /* NT */
2681 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2683 /* Create Window class */
2684 wc.style = 0;
2685 wc.lpfnWndProc = DefWindowProcW;
2686 wc.cbClsExtra = 0;
2687 wc.cbWndExtra = 4;
2688 wc.hInstance = shlwapi_hInstance;
2689 wc.hIcon = (HICON)0;
2690 wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
2691 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2692 wc.lpszMenuName = NULL;
2693 wc.lpszClassName = szClass;
2695 SHRegisterClassW(&wc); /* Register class */
2697 /* FIXME: Set extra bits in dwExStyle */
2699 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2700 hWndParent, hMenu, shlwapi_hInstance, 0);
2701 if (hWnd)
2703 SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2705 if (wndProc)
2706 SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
2708 return hWnd;
2711 /*************************************************************************
2712 * @ [SHLWAPI.279]
2714 * Get and show a context menu from a shell folder.
2716 * PARAMS
2717 * hWnd [I] Window displaying the shell folder
2718 * lpFolder [I] IShellFolder interface
2719 * lpApidl [I] Id for the particular folder desired
2721 * RETURNS
2722 * Success: S_OK.
2723 * Failure: An HRESULT error code indicating the error.
2725 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2727 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2730 /*************************************************************************
2731 * @ [SHLWAPI.281]
2733 * _SHPackDispParamsV
2735 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2737 FIXME("%p %p %p %p\n",w,x,y,z);
2738 return E_FAIL;
2741 /*************************************************************************
2742 * @ [SHLWAPI.282]
2744 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2745 * function does...).
2747 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2749 FIXME("%p %p %p %p\n", w, x, y, z);
2750 return E_FAIL;
2753 /*************************************************************************
2754 * @ [SHLWAPI.284]
2756 * _IConnectionPoint_SimpleInvoke
2758 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2759 LPVOID x,
2760 LPVOID y,
2761 LPVOID z)
2763 FIXME("(%p %p %p) stub\n",x,y,z);
2764 return 0;
2767 /*************************************************************************
2768 * @ [SHLWAPI.285]
2770 * Notify an IConnectionPoint object of changes.
2772 * PARAMS
2773 * lpCP [I] Object to notify
2774 * dispID [I]
2776 * RETURNS
2777 * Success: S_OK.
2778 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2779 * IConnectionPoint interface.
2781 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2783 IEnumConnections *lpEnum;
2784 HRESULT hRet = E_NOINTERFACE;
2786 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2788 /* Get an enumerator for the connections */
2789 if (lpCP)
2790 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2792 if (SUCCEEDED(hRet))
2794 IPropertyNotifySink *lpSink;
2795 CONNECTDATA connData;
2796 ULONG ulFetched;
2798 /* Call OnChanged() for every notify sink in the connection point */
2799 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2801 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2802 lpSink)
2804 IPropertyNotifySink_OnChanged(lpSink, dispID);
2805 IPropertyNotifySink_Release(lpSink);
2807 IUnknown_Release(connData.pUnk);
2810 IEnumConnections_Release(lpEnum);
2812 return hRet;
2815 /*************************************************************************
2816 * @ [SHLWAPI.287]
2818 * Notify an IConnectionPointContainer object of changes.
2820 * PARAMS
2821 * lpUnknown [I] Object to notify
2822 * dispID [I]
2824 * RETURNS
2825 * Success: S_OK.
2826 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2827 * IConnectionPointContainer interface.
2829 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
2831 IConnectionPointContainer* lpCPC = NULL;
2832 HRESULT hRet = E_NOINTERFACE;
2834 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2836 if (lpUnknown)
2837 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
2839 if (SUCCEEDED(hRet))
2841 IConnectionPoint* lpCP;
2843 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
2844 IConnectionPointContainer_Release(lpCPC);
2846 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
2847 IConnectionPoint_Release(lpCP);
2849 return hRet;
2852 /*************************************************************************
2853 * @ [SHLWAPI.289]
2855 * See PlaySoundW.
2857 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2859 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2860 return pPlaySoundW(pszSound, hmod, fdwSound);
2863 /*************************************************************************
2864 * @ [SHLWAPI.294]
2866 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
2869 * str1: "I" "I" pushl esp+0x20
2870 * str2: "U" "I" pushl 0x77c93810
2871 * (is "I" and "U" "integer" and "unsigned" ??)
2873 * pStr: "" "" pushl eax
2874 * some_len: 0x824 0x104 pushl 0x824
2875 * lpStr2: "%l" "%l" pushl esp+0xc
2877 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2878 * LocalAlloc(0x00, some_len) -> irrelevant_var
2879 * LocalAlloc(0x40, irrelevant_len) -> pStr
2880 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2881 * shlwapi.PathRemoveBlanksW(pStr);
2883 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2884 return TRUE;
2887 /*************************************************************************
2888 * @ [SHLWAPI.295]
2890 * Called by ICQ2000b install via SHDOCVW:
2891 * str1: "InternetShortcut"
2892 * x: some unknown pointer
2893 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2894 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2896 * In short: this one maybe creates a desktop link :-)
2898 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2900 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2901 return TRUE;
2904 /*************************************************************************
2905 * @ [SHLWAPI.299]
2907 * See COMCTL32_417.
2909 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2910 LPCWSTR str, UINT count, const INT *lpDx)
2912 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2913 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2916 /*************************************************************************
2917 * @ [SHLWAPI.313]
2919 * See SHGetFileInfoW.
2921 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
2922 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2924 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2925 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2928 /*************************************************************************
2929 * @ [SHLWAPI.318]
2931 * See DragQueryFileW.
2933 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2935 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2936 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2939 /*************************************************************************
2940 * @ [SHLWAPI.333]
2942 * See SHBrowseForFolderW.
2944 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
2946 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2947 return pSHBrowseForFolderW(lpBi);
2950 /*************************************************************************
2951 * @ [SHLWAPI.334]
2953 * See SHGetPathFromIDListW.
2955 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
2957 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2958 return pSHGetPathFromIDListW(pidl, pszPath);
2961 /*************************************************************************
2962 * @ [SHLWAPI.335]
2964 * See ShellExecuteExW.
2966 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
2968 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
2969 return pShellExecuteExW(lpExecInfo);
2972 /*************************************************************************
2973 * @ [SHLWAPI.336]
2975 * See SHFileOperationW.
2977 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
2979 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
2980 return pSHFileOperationW(lpFileOp);
2983 /*************************************************************************
2984 * @ [SHLWAPI.337]
2986 * See ExtractIconExW.
2988 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
2989 HICON *phiconSmall, UINT nIcons)
2991 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
2992 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
2995 /*************************************************************************
2996 * @ [SHLWAPI.342]
2999 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3001 return InterlockedCompareExchange(dest, xchg, compare);
3004 /*************************************************************************
3005 * @ [SHLWAPI.346]
3007 DWORD WINAPI SHUnicodeToUnicode(
3008 LPCWSTR src,
3009 LPWSTR dest,
3010 int len)
3012 FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
3013 lstrcpynW(dest, src, len);
3014 return lstrlenW(dest)+1;
3017 /*************************************************************************
3018 * @ [SHLWAPI.350]
3020 * See GetFileVersionInfoSizeW.
3022 DWORD WINAPI GetFileVersionInfoSizeWrapW(
3023 LPWSTR x,
3024 LPVOID y)
3026 DWORD ret;
3028 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3029 ret = pGetFileVersionInfoSizeW(x, y);
3030 return 0x208 + ret;
3033 /*************************************************************************
3034 * @ [SHLWAPI.351]
3036 * See GetFileVersionInfoW.
3038 BOOL WINAPI GetFileVersionInfoWrapW(
3039 LPWSTR w, /* [in] path to dll */
3040 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3041 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3042 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3044 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3045 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3048 /*************************************************************************
3049 * @ [SHLWAPI.352]
3051 * See VerQueryValueW.
3053 WORD WINAPI VerQueryValueWrapW(
3054 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3055 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3056 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3057 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3059 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3060 return pVerQueryValueW((char*)w+0x208, x, y, z);
3063 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3064 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3065 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3067 /*************************************************************************
3068 * @ [SHLWAPI.355]
3070 * Change the modality of a shell object.
3072 * PARAMS
3073 * lpUnknown [I] Object to make modeless
3074 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3076 * RETURNS
3077 * Success: S_OK. The modality lpUnknown is changed.
3078 * Failure: An HRESULT error code indicating the error.
3080 * NOTES
3081 * lpUnknown must support the IOleInPlaceFrame interface, the
3082 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3083 * or the IDocHostUIHandler interface, or this call fails.
3085 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3087 IUnknown *lpObj;
3088 HRESULT hRet;
3090 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3092 if (!lpUnknown)
3093 return E_FAIL;
3095 if (IsIface(IOleInPlaceFrame))
3096 EnableModeless(IOleInPlaceFrame);
3097 else if (IsIface(IShellBrowser))
3098 EnableModeless(IShellBrowser);
3099 #if 0
3100 /* FIXME: Wine has no headers for these objects yet */
3101 else if (IsIface(IInternetSecurityMgrSite))
3102 EnableModeless(IInternetSecurityMgrSite);
3103 else if (IsIface(IDocHostUIHandler))
3104 EnableModeless(IDocHostUIHandler);
3105 #endif
3106 else
3107 return hRet;
3109 IUnknown_Release(lpObj);
3110 return S_OK;
3113 /*************************************************************************
3114 * @ [SHLWAPI.357]
3116 * See SHGetNewLinkInfoW.
3118 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3119 BOOL *pfMustCopy, UINT uFlags)
3121 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3122 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3125 /*************************************************************************
3126 * @ [SHLWAPI.358]
3128 * See SHDefExtractIconW.
3130 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3131 HICON* phiconSmall, UINT nIconSize)
3133 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3134 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3137 /*************************************************************************
3138 * @ [SHLWAPI.363]
3140 * Get and show a context menu from a shell folder.
3142 * PARAMS
3143 * hWnd [I] Window displaying the shell folder
3144 * lpFolder [I] IShellFolder interface
3145 * lpApidl [I] Id for the particular folder desired
3146 * bInvokeDefault [I] Whether to invoke the default menu item
3148 * RETURNS
3149 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3150 * executed.
3151 * Failure: An HRESULT error code indicating the error.
3153 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3155 IContextMenu *iContext;
3156 HRESULT hRet = E_FAIL;
3158 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3160 if (!lpFolder)
3161 return hRet;
3163 /* Get the context menu from the shell folder */
3164 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3165 &IID_IContextMenu, 0, (void**)&iContext);
3166 if (SUCCEEDED(hRet))
3168 HMENU hMenu;
3169 if ((hMenu = CreatePopupMenu()))
3171 HRESULT hQuery;
3172 DWORD dwDefaultId = 0;
3174 /* Add the context menu entries to the popup */
3175 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3176 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3178 if (SUCCEEDED(hQuery))
3180 if (bInvokeDefault &&
3181 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3183 CMINVOKECOMMANDINFO cmIci;
3184 /* Invoke the default item */
3185 memset(&cmIci,0,sizeof(cmIci));
3186 cmIci.cbSize = sizeof(cmIci);
3187 cmIci.fMask = CMIC_MASK_ASYNCOK;
3188 cmIci.hwnd = hWnd;
3189 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3190 cmIci.nShow = SW_SCROLLCHILDREN;
3192 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3195 DestroyMenu(hMenu);
3197 IContextMenu_Release(iContext);
3199 return hRet;
3202 /*************************************************************************
3203 * @ [SHLWAPI.370]
3205 * See ExtractIconW.
3207 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3208 UINT nIconIndex)
3210 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3211 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3214 /*************************************************************************
3215 * @ [SHLWAPI.376]
3217 LANGID WINAPI MLGetUILanguage()
3219 FIXME("() stub\n");
3220 /* FIXME: This should be a forward in the .spec file to the win2k function
3221 * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3223 return GetUserDefaultLangID();
3226 /*************************************************************************
3227 * @ [SHLWAPI.377]
3229 * Load a library from the directory of a particular process.
3231 * PARAMS
3232 * new_mod [I] Library name
3233 * inst_hwnd [I] Module whose directory is to be used
3234 * dwFlags [I] Flags controlling the load
3236 * RETURNS
3237 * Success: A handle to the loaded module
3238 * Failure: A NULL handle.
3240 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3242 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3243 * each call here.
3244 * FIXME: Native shows calls to:
3245 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3246 * CheckVersion
3247 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3248 * RegQueryValueExA for "LPKInstalled"
3249 * RegCloseKey
3250 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3251 * RegQueryValueExA for "ResourceLocale"
3252 * RegCloseKey
3253 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3254 * RegQueryValueExA for "Locale"
3255 * RegCloseKey
3256 * and then tests the Locale ("en" for me).
3257 * code below
3258 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3260 CHAR mod_path[2*MAX_PATH];
3261 LPSTR ptr;
3262 DWORD len;
3264 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3265 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3266 if (!len || len >= sizeof(mod_path)) return NULL;
3268 ptr = strrchr(mod_path, '\\');
3269 if (ptr) {
3270 strcpy(ptr+1, new_mod);
3271 TRACE("loading %s\n", debugstr_a(mod_path));
3272 return LoadLibraryA(mod_path);
3274 return NULL;
3277 /*************************************************************************
3278 * @ [SHLWAPI.378]
3280 * Unicode version of MLLoadLibraryA.
3282 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3284 WCHAR mod_path[2*MAX_PATH];
3285 LPWSTR ptr;
3286 DWORD len;
3288 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3289 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3290 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3292 ptr = strrchrW(mod_path, '\\');
3293 if (ptr) {
3294 strcpyW(ptr+1, new_mod);
3295 TRACE("loading %s\n", debugstr_w(mod_path));
3296 return LoadLibraryW(mod_path);
3298 return NULL;
3301 /*************************************************************************
3302 * ColorAdjustLuma [SHLWAPI.@]
3304 * Adjust the luminosity of a color
3306 * PARAMS
3307 * cRGB [I] RGB value to convert
3308 * dwLuma [I] Luma adjustment
3309 * bUnknown [I] Unknown
3311 * RETURNS
3312 * The adjusted RGB color.
3314 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3316 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3318 if (dwLuma)
3320 WORD wH, wL, wS;
3322 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3324 FIXME("Ignoring luma adjustment\n");
3326 /* FIXME: The ajdustment is not linear */
3328 cRGB = ColorHLSToRGB(wH, wL, wS);
3330 return cRGB;
3333 /*************************************************************************
3334 * @ [SHLWAPI.389]
3336 * See GetSaveFileNameW.
3338 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3340 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3341 return pGetSaveFileNameW(ofn);
3344 /*************************************************************************
3345 * @ [SHLWAPI.390]
3347 * See WNetRestoreConnectionW.
3349 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3351 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3352 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3355 /*************************************************************************
3356 * @ [SHLWAPI.391]
3358 * See WNetGetLastErrorW.
3360 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3361 LPWSTR lpNameBuf, DWORD nNameBufSize)
3363 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3364 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3367 /*************************************************************************
3368 * @ [SHLWAPI.401]
3370 * See PageSetupDlgW.
3372 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3374 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3375 return pPageSetupDlgW(pagedlg);
3378 /*************************************************************************
3379 * @ [SHLWAPI.402]
3381 * See PrintDlgW.
3383 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3385 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3386 return pPrintDlgW(printdlg);
3389 /*************************************************************************
3390 * @ [SHLWAPI.403]
3392 * See GetOpenFileNameW.
3394 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3396 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3397 return pGetOpenFileNameW(ofn);
3400 /* INTERNAL: Map from HLS color space to RGB */
3401 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3403 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3405 if (wHue > 160)
3406 return wMid1;
3407 else if (wHue > 120)
3408 wHue = 160 - wHue;
3409 else if (wHue > 40)
3410 return wMid2;
3412 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3415 /* Convert to RGB and scale into RGB range (0..255) */
3416 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3418 /*************************************************************************
3419 * ColorHLSToRGB [SHLWAPI.@]
3421 * Convert from hls color space into an rgb COLORREF.
3423 * PARAMS
3424 * wHue [I] Hue amount
3425 * wLuminosity [I] Luminosity amount
3426 * wSaturation [I] Saturation amount
3428 * RETURNS
3429 * A COLORREF representing the converted color.
3431 * NOTES
3432 * Input hls values are constrained to the range (0..240).
3434 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3436 WORD wRed;
3438 if (wSaturation)
3440 WORD wGreen, wBlue, wMid1, wMid2;
3442 if (wLuminosity > 120)
3443 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3444 else
3445 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3447 wMid1 = wLuminosity * 2 - wMid2;
3449 wRed = GET_RGB(wHue + 80);
3450 wGreen = GET_RGB(wHue);
3451 wBlue = GET_RGB(wHue - 80);
3453 return RGB(wRed, wGreen, wBlue);
3456 wRed = wLuminosity * 255 / 240;
3457 return RGB(wRed, wRed, wRed);
3460 /*************************************************************************
3461 * @ [SHLWAPI.413]
3463 * Get the current docking status of the system.
3465 * PARAMS
3466 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3468 * RETURNS
3469 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3470 * a notebook.
3472 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3474 HW_PROFILE_INFOA hwInfo;
3476 TRACE("(0x%08lx)\n", dwFlags);
3478 GetCurrentHwProfileA(&hwInfo);
3479 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3481 case DOCKINFO_DOCKED:
3482 case DOCKINFO_UNDOCKED:
3483 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3484 default:
3485 return 0;
3489 /*************************************************************************
3490 * @ [SHLWAPI.418]
3492 * Function seems to do FreeLibrary plus other things.
3494 * FIXME native shows the following calls:
3495 * RtlEnterCriticalSection
3496 * LocalFree
3497 * GetProcAddress(Comctl32??, 150L)
3498 * DPA_DeletePtr
3499 * RtlLeaveCriticalSection
3500 * followed by the FreeLibrary.
3501 * The above code may be related to .377 above.
3503 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3505 FIXME("(%p) semi-stub\n", hModule);
3506 return FreeLibrary(hModule);
3509 /*************************************************************************
3510 * @ [SHLWAPI.419]
3512 BOOL WINAPI SHFlushSFCacheWrap(void) {
3513 FIXME(": stub\n");
3514 return TRUE;
3517 /*************************************************************************
3518 * @ [SHLWAPI.429]
3519 * FIXME I have no idea what this function does or what its arguments are.
3521 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3523 FIXME("(%p) stub\n", hInst);
3524 return FALSE;
3528 /*************************************************************************
3529 * @ [SHLWAPI.430]
3531 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3533 FIXME("(%p,%p) stub\n", hInst, hHeap);
3534 return E_FAIL; /* This is what is used if shlwapi not loaded */
3537 /*************************************************************************
3538 * @ [SHLWAPI.431]
3540 DWORD WINAPI MLClearMLHInstance(DWORD x)
3542 FIXME("(0x%08lx)stub\n", x);
3543 return 0xabba1247;
3546 /*************************************************************************
3547 * @ [SHLWAPI.436]
3549 * Convert an Unicode string CLSID into a CLSID.
3551 * PARAMS
3552 * idstr [I] string containing a CLSID in text form
3553 * id [O] CLSID extracted from the string
3555 * RETURNS
3556 * S_OK on success or E_INVALIDARG on failure
3558 * NOTES
3559 * This is really CLSIDFromString() which is exported by ole32.dll,
3560 * however the native shlwapi.dll does *not* import ole32. Nor does
3561 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3562 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3563 * it returns an E_INVALIDARG error code on failure.
3564 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3565 * in "dlls/ole32/compobj.c".
3567 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3569 LPCWSTR s = idstr;
3570 BYTE *p;
3571 INT i;
3572 WCHAR table[256];
3574 if (!s) {
3575 memset(id, 0, sizeof(CLSID));
3576 return S_OK;
3578 else { /* validate the CLSID string */
3580 if (strlenW(s) != 38)
3581 return E_INVALIDARG;
3583 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3584 return E_INVALIDARG;
3586 for (i=1; i<37; i++)
3588 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3589 continue;
3590 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3591 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3592 ((s[i] >= L'A') && (s[i] <= L'F')))
3594 return E_INVALIDARG;
3598 TRACE("%s -> %p\n", debugstr_w(s), id);
3600 /* quick lookup table */
3601 memset(table, 0, 256*sizeof(WCHAR));
3603 for (i = 0; i < 10; i++) {
3604 table['0' + i] = i;
3606 for (i = 0; i < 6; i++) {
3607 table['A' + i] = i+10;
3608 table['a' + i] = i+10;
3611 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3613 p = (BYTE *) id;
3615 s++; /* skip leading brace */
3616 for (i = 0; i < 4; i++) {
3617 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3618 s += 2;
3620 p += 4;
3621 s++; /* skip - */
3623 for (i = 0; i < 2; i++) {
3624 p[1-i] = table[*s]<<4 | table[*(s+1)];
3625 s += 2;
3627 p += 2;
3628 s++; /* skip - */
3630 for (i = 0; i < 2; i++) {
3631 p[1-i] = table[*s]<<4 | table[*(s+1)];
3632 s += 2;
3634 p += 2;
3635 s++; /* skip - */
3637 /* these are just sequential bytes */
3638 for (i = 0; i < 2; i++) {
3639 *p++ = table[*s]<<4 | table[*(s+1)];
3640 s += 2;
3642 s++; /* skip - */
3644 for (i = 0; i < 6; i++) {
3645 *p++ = table[*s]<<4 | table[*(s+1)];
3646 s += 2;
3649 return S_OK;
3652 /*************************************************************************
3653 * @ [SHLWAPI.437]
3655 * Determine if the OS supports a given feature.
3657 * PARAMS
3658 * dwFeature [I] Feature requested (undocumented)
3660 * RETURNS
3661 * TRUE If the feature is available.
3662 * FALSE If the feature is not available.
3664 BOOL WINAPI IsOS(DWORD feature)
3666 OSVERSIONINFOA osvi;
3667 DWORD platform, majorv, minorv;
3669 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3670 if(!GetVersionExA(&osvi)) {
3671 ERR("GetVersionEx failed");
3672 return FALSE;
3675 majorv = osvi.dwMajorVersion;
3676 minorv = osvi.dwMinorVersion;
3677 platform = osvi.dwPlatformId;
3679 #define ISOS_RETURN(x) \
3680 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3681 return (x);
3683 switch(feature) {
3684 case OS_WIN32SORGREATER:
3685 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3686 || platform == VER_PLATFORM_WIN32_WINDOWS)
3687 case OS_NT:
3688 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3689 case OS_WIN95ORGREATER:
3690 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3691 case OS_NT4ORGREATER:
3692 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3693 case OS_WIN2000ORGREATER_ALT:
3694 case OS_WIN2000ORGREATER:
3695 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3696 case OS_WIN98ORGREATER:
3697 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3698 case OS_WIN98_GOLD:
3699 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3700 case OS_WIN2000PRO:
3701 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3702 case OS_WIN2000SERVER:
3703 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3704 case OS_WIN2000ADVSERVER:
3705 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3706 case OS_WIN2000DATACENTER:
3707 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3708 case OS_WIN2000TERMINAL:
3709 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3710 case OS_EMBEDDED:
3711 FIXME("(OS_EMBEDDED) What should we return here?\n");
3712 return FALSE;
3713 case OS_TERMINALCLIENT:
3714 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3715 return FALSE;
3716 case OS_TERMINALREMOTEADMIN:
3717 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3718 return FALSE;
3719 case OS_WIN95_GOLD:
3720 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3721 case OS_MEORGREATER:
3722 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3723 case OS_XPORGREATER:
3724 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3725 case OS_HOME:
3726 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3727 case OS_PROFESSIONAL:
3728 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3729 case OS_DATACENTER:
3730 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3731 case OS_ADVSERVER:
3732 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3733 case OS_SERVER:
3734 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3735 case OS_TERMINALSERVER:
3736 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3737 case OS_PERSONALTERMINALSERVER:
3738 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3739 case OS_FASTUSERSWITCHING:
3740 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3741 return TRUE;
3742 case OS_WELCOMELOGONUI:
3743 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3744 return FALSE;
3745 case OS_DOMAINMEMBER:
3746 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3747 return TRUE;
3748 case OS_ANYSERVER:
3749 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3750 case OS_WOW6432:
3751 FIXME("(OS_WOW6432) Should we check this?\n");
3752 return FALSE;
3753 case OS_WEBSERVER:
3754 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3755 case OS_SMALLBUSINESSSERVER:
3756 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3757 case OS_TABLETPC:
3758 FIXME("(OS_TABLEPC) What should we return here?\n");
3759 return FALSE;
3760 case OS_SERVERADMINUI:
3761 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3762 return FALSE;
3763 case OS_MEDIACENTER:
3764 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3765 return FALSE;
3766 case OS_APPLIANCE:
3767 FIXME("(OS_APPLIANCE) What should we return here?\n");
3768 return FALSE;
3771 #undef ISOS_RETURN
3773 WARN("(0x%lx) unknown parameter\n",feature);
3775 return FALSE;
3778 /*************************************************************************
3779 * ColorRGBToHLS [SHLWAPI.@]
3781 * Convert an rgb COLORREF into the hls color space.
3783 * PARAMS
3784 * cRGB [I] Source rgb value
3785 * pwHue [O] Destination for converted hue
3786 * pwLuminance [O] Destination for converted luminance
3787 * pwSaturation [O] Destination for converted saturation
3789 * RETURNS
3790 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3791 * values.
3793 * NOTES
3794 * Output HLS values are constrained to the range (0..240).
3795 * For Achromatic conversions, Hue is set to 160.
3797 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3798 LPWORD pwLuminance, LPWORD pwSaturation)
3800 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3802 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3804 wR = GetRValue(cRGB);
3805 wG = GetGValue(cRGB);
3806 wB = GetBValue(cRGB);
3808 wMax = max(wR, max(wG, wB));
3809 wMin = min(wR, min(wG, wB));
3811 /* Luminosity */
3812 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3814 if (wMax == wMin)
3816 /* Achromatic case */
3817 wSaturation = 0;
3818 /* Hue is now unrepresentable, but this is what native returns... */
3819 wHue = 160;
3821 else
3823 /* Chromatic case */
3824 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3826 /* Saturation */
3827 if (wLuminosity <= 120)
3828 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3829 else
3830 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3832 /* Hue */
3833 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3834 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
3835 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
3837 if (wR == wMax)
3838 wHue = wBNorm - wGNorm;
3839 else if (wG == wMax)
3840 wHue = 80 + wRNorm - wBNorm;
3841 else
3842 wHue = 160 + wGNorm - wRNorm;
3843 if (wHue < 0)
3844 wHue += 240;
3845 else if (wHue > 240)
3846 wHue -= 240;
3848 if (pwHue)
3849 *pwHue = wHue;
3850 if (pwLuminance)
3851 *pwLuminance = wLuminosity;
3852 if (pwSaturation)
3853 *pwSaturation = wSaturation;
3856 /*************************************************************************
3857 * SHCreateShellPalette [SHLWAPI.@]
3859 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
3861 FIXME("stub\n");
3862 return CreateHalftonePalette(hdc);
3865 /*************************************************************************
3866 * SHGetInverseCMAP (SHLWAPI.@)
3868 * Get an inverse color map table.
3870 * PARAMS
3871 * lpCmap [O] Destination for color map
3872 * dwSize [I] Size of memory pointed to by lpCmap
3874 * RETURNS
3875 * Success: S_OK.
3876 * Failure: E_POINTER, If lpCmap is invalid.
3877 * E_INVALIDARG, If dwFlags is invalid
3878 * E_OUTOFMEMORY, If there is no memory available
3880 * NOTES
3881 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
3882 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
3883 * internal CMap.
3884 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
3885 * this DLL's internal CMap.
3887 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
3889 if (dwSize == 4) {
3890 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3891 *dest = (DWORD)0xabba1249;
3892 return 0;
3894 FIXME("(%p, %#lx) stub\n", dest, dwSize);
3895 return 0;
3898 /*************************************************************************
3899 * SHIsLowMemoryMachine [SHLWAPI.@]
3901 * Determine if the current computer has low memory.
3903 * PARAMS
3904 * x [I] FIXME
3906 * RETURNS
3907 * TRUE if the users machine has 16 Megabytes of memory or less,
3908 * FALSE otherwise.
3910 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
3912 FIXME("(0x%08lx) stub\n", x);
3913 return FALSE;
3916 /*************************************************************************
3917 * GetMenuPosFromID [SHLWAPI.@]
3919 * Return the position of a menu item from its Id.
3921 * PARAMS
3922 * hMenu [I] Menu containing the item
3923 * wID [I] Id of the menu item
3925 * RETURNS
3926 * Success: The index of the menu item in hMenu.
3927 * Failure: -1, If the item is not found.
3929 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
3931 MENUITEMINFOA mi;
3932 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
3934 while (nIter < nCount)
3936 mi.wID = 0;
3937 if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
3938 return nIter;
3939 nIter++;
3941 return -1;
3944 /*************************************************************************
3945 * @ [SHLWAPI.179]
3947 * Same as SHLWAPI.GetMenuPosFromID
3949 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
3951 return GetMenuPosFromID(hMenu, uID);
3955 /*************************************************************************
3956 * @ [SHLWAPI.448]
3958 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
3960 while (*lpwstr)
3962 if (*lpwstr == '/')
3963 *lpwstr = '\\';
3964 lpwstr++;
3969 /*************************************************************************
3970 * @ [SHLWAPI.461]
3972 DWORD WINAPI SHGetAppCompatFlags()
3974 FIXME("stub\n");
3975 return 0;
3979 /*************************************************************************
3980 * @ [SHLWAPI.549]
3982 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
3983 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
3985 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
3988 /*************************************************************************
3989 * SHSkipJunction [SHLWAPI.@]
3991 * Determine if a bind context can be bound to an object
3993 * PARAMS
3994 * pbc [I] Bind context to check
3995 * pclsid [I] CLSID of object to be bound to
3997 * RETURNS
3998 * TRUE: If it is safe to bind
3999 * FALSE: If pbc is invalid or binding would not be safe
4002 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4004 static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4005 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4006 BOOL bRet = FALSE;
4008 if (pbc)
4010 IUnknown* lpUnk;
4012 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4014 CLSID clsid;
4016 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4017 IsEqualGUID(pclsid, &clsid))
4018 bRet = TRUE;
4020 IUnknown_Release(lpUnk);
4023 return bRet;
4026 /***********************************************************************
4027 * SHGetShellKey (SHLWAPI.@)
4029 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4031 FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
4032 return 0x50;
4035 /***********************************************************************
4036 * SHQueueUserWorkItem (SHLWAPI.@)
4038 HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
4040 FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
4041 return E_FAIL;
4044 /***********************************************************************
4045 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4047 DWORD WINAPI IUnknown_OnFocusChangeIS(IUnknown * pUnk, IUnknown * pFocusObject, BOOL bChange)
4049 FIXME("(%p, %p, %s)\n", pUnk, pFocusObject, bChange ? "TRUE" : "FALSE");
4052 IInputObjectSite * pIOS = NULL;
4053 if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IInputObjectSite, (void **)&pIOS))
4054 IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bChange);
4057 return 0;
4060 /***********************************************************************
4061 * SHGetValueW (SHLWAPI.@)
4063 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4065 FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4066 return E_FAIL;
4069 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4071 /***********************************************************************
4072 * GetUIVersion (SHLWAPI.452)
4074 DWORD WINAPI GetUIVersion(void)
4076 static DWORD version;
4078 if (!version)
4080 DllGetVersion_func pDllGetVersion;
4081 HMODULE dll = LoadLibraryA("shell32.dll");
4082 if (!dll) return 0;
4084 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4085 if (pDllGetVersion)
4087 DLLVERSIONINFO dvi;
4088 dvi.cbSize = sizeof(DLLVERSIONINFO);
4089 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4091 FreeLibrary( dll );
4092 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4094 return version;