2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
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
25 #include "wine/port.h"
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
47 #include "wine/unicode.h"
49 #include "wine/debug.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
55 /* Get a function pointer from a DLL handle */
56 #define GET_FUNC(func, module, name, fail) \
59 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
60 func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
61 if (!func) return fail; \
65 /* DLL handles for late bound calls */
66 extern HINSTANCE shlwapi_hInstance;
67 extern HMODULE SHLWAPI_hshell32;
68 extern HMODULE SHLWAPI_hwinmm;
69 extern HMODULE SHLWAPI_hcomdlg32;
70 extern HMODULE SHLWAPI_hcomctl32;
71 extern HMODULE SHLWAPI_hmpr;
72 extern HMODULE SHLWAPI_hurlmon;
73 extern HMODULE SHLWAPI_hversion;
75 extern DWORD SHLWAPI_ThreadRef_index;
77 /* following is GUID for IObjectWithSite::SetSite -- see _174 */
78 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
79 /* following is GUID for IPersistMoniker::GetClassID -- see _174 */
80 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
82 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
83 typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
84 static fnpSHBrowseForFolderW pSHBrowseForFolderW;
85 typedef BOOL (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
86 static fnpPlaySoundW pPlaySoundW;
87 typedef DWORD (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
88 static fnpSHGetFileInfoW pSHGetFileInfoW;
89 typedef UINT (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
90 static fnpDragQueryFileW pDragQueryFileW;
91 typedef BOOL (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
92 static fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
93 typedef BOOL (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
94 static fnpShellExecuteExW pShellExecuteExW;
95 typedef HICON (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
96 static fnpSHFileOperationW pSHFileOperationW;
97 typedef UINT (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
98 static fnpExtractIconExW pExtractIconExW;
99 typedef BOOL (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
100 static fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
101 typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
102 static fnpSHDefExtractIconW pSHDefExtractIconW;
103 typedef HICON (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
104 static fnpExtractIconW pExtractIconW;
105 typedef BOOL (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
106 static fnpGetSaveFileNameW pGetSaveFileNameW;
107 typedef DWORD (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
108 static fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
109 typedef DWORD (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
110 static fnpWNetGetLastErrorW pWNetGetLastErrorW;
111 typedef BOOL (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
112 static fnpPageSetupDlgW pPageSetupDlgW;
113 typedef BOOL (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
114 static fnpPrintDlgW pPrintDlgW;
115 typedef BOOL (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
116 static fnpGetOpenFileNameW pGetOpenFileNameW;
117 typedef DWORD (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
118 static fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
119 typedef BOOL (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
120 static fnpGetFileVersionInfoW pGetFileVersionInfoW;
121 typedef WORD (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
122 static fnpVerQueryValueW pVerQueryValueW;
123 typedef BOOL (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
124 static fnpCOMCTL32_417 pCOMCTL32_417;
125 typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
126 static fnpDllGetVersion pDllGetVersion;
127 typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
128 static fnpCreateFormatEnumerator pCreateFormatEnumerator;
129 typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
130 static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
132 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
133 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
134 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);
135 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
138 NOTES: Most functions exported by ordinal seem to be superflous.
139 The reason for these functions to be there is to provide a wrapper
140 for unicode functions to provide these functions on systems without
141 unicode functions eg. win95/win98. Since we have such functions we just
142 call these. If running Wine with native DLL's, some late bound calls may
143 fail. However, it is better to implement the functions in the forward DLL
144 and recommend the builtin rather than reimplementing the calls here!
147 /*************************************************************************
148 * SHLWAPI_DupSharedHandle
150 * Internal implemetation of SHLWAPI_11.
153 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
154 DWORD dwSrcProcId, DWORD dwAccess,
158 DWORD dwMyProcId = GetCurrentProcessId();
161 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
162 dwAccess, dwOptions);
164 /* Get dest process handle */
165 if (dwDstProcId == dwMyProcId)
166 hDst = GetCurrentProcess();
168 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
172 /* Get src process handle */
173 if (dwSrcProcId == dwMyProcId)
174 hSrc = GetCurrentProcess();
176 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
180 /* Make handle available to dest process */
181 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
182 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
185 if (dwSrcProcId != dwMyProcId)
189 if (dwDstProcId != dwMyProcId)
193 TRACE("Returning handle %p\n", hRet);
197 /*************************************************************************
200 * Create a block of sharable memory and initialise it with data.
203 * lpvData [I] Pointer to data to write
204 * dwSize [I] Size of data
205 * dwProcId [I] ID of process owning data
208 * Success: A shared memory handle
212 * Ordinals 7-11 provide a set of calls to create shared memory between a
213 * group of processes. The shared memory is treated opaquely in that its size
214 * is not exposed to clients who map it. This is accomplished by storing
215 * the size of the map as the first DWORD of mapped data, and then offsetting
216 * the view pointer returned by this size.
219 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
225 TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
227 /* Create file mapping of the correct length */
228 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
229 dwSize + sizeof(dwSize), NULL);
233 /* Get a view in our process address space */
234 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
238 /* Write size of data, followed by the data, to the view */
239 *((DWORD*)pMapped) = dwSize;
241 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
243 /* Release view. All further views mapped will be opaque */
244 UnmapViewOfFile(pMapped);
245 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
246 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
247 DUPLICATE_SAME_ACCESS);
254 /*************************************************************************
257 * Get a pointer to a block of shared memory from a shared memory handle.
260 * hShared [I] Shared memory handle
261 * dwProcId [I] ID of process owning hShared
264 * Success: A pointer to the shared memory
268 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
273 TRACE("(%p %ld)\n", hShared, dwProcId);
275 /* Get handle to shared memory for current process */
276 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
277 FILE_MAP_ALL_ACCESS, 0);
279 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
283 return (char *) pMapped + sizeof(DWORD); /* Hide size */
287 /*************************************************************************
290 * Release a pointer to a block of shared memory.
293 * lpView [I] Shared memory pointer
300 BOOL WINAPI SHUnlockShared(LPVOID lpView)
302 TRACE("(%p)\n", lpView);
303 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
306 /*************************************************************************
309 * Destroy a block of sharable memory.
312 * hShared [I] Shared memory handle
313 * dwProcId [I] ID of process owning hShared
320 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
324 TRACE("(%p %ld)\n", hShared, dwProcId);
326 /* Get a copy of the handle for our process, closing the source handle */
327 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
328 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
329 /* Close local copy */
330 return CloseHandle(hClose);
333 /*************************************************************************
336 * Copy a sharable memory handle from one process to another.
339 * hShared [I] Shared memory handle to duplicate
340 * dwDstProcId [I] ID of the process wanting the duplicated handle
341 * dwSrcProcId [I] ID of the process owning hShared
342 * dwAccess [I] Desired DuplicateHandle() access
343 * dwOptions [I] Desired DuplicateHandle() options
346 * Success: A handle suitable for use by the dwDstProcId process.
347 * Failure: A NULL handle.
350 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
351 DWORD dwAccess, DWORD dwOptions)
355 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
356 dwAccess, dwOptions);
360 /*************************************************************************
363 * Create and register a clipboard enumerator for a web browser.
366 * lpBC [I] Binding context
367 * lpUnknown [I] An object exposing the IWebBrowserApp interface
371 * Failure: An HRESULT error code.
374 * The enumerator is stored as a property of the web browser. If it does not
375 * yet exist, it is created and set before being registered.
377 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
379 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
380 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
381 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
382 IEnumFORMATETC* pIEnumFormatEtc = NULL;
385 IWebBrowserApp* pBrowser = NULL;
387 TRACE("(%p, %p)\n", lpBC, lpUnknown);
389 /* Get An IWebBrowserApp interface from lpUnknown */
390 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
391 if (FAILED(hRet) || !pBrowser)
392 return E_NOINTERFACE;
394 V_VT(&var) = VT_EMPTY;
396 /* The property we get is the browsers clipboard enumerator */
397 hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
401 if (V_VT(&var) == VT_EMPTY)
403 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
404 char szKeyBuff[128], szValueBuff[128];
405 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
406 FORMATETC* formatList, *format;
409 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
411 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
412 "Version\\Internet Settings\\Accepted Documents", &hDocs))
415 /* Get count of values in key */
418 dwKeySize = sizeof(szKeyBuff);
419 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
423 dwNumValues = dwCount;
425 /* Note: dwCount = number of items + 1; The extra item is the end node */
426 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
428 return E_OUTOFMEMORY;
437 /* Register clipboard formats for the values and populate format list */
438 while(!dwRet && dwCount < dwNumValues)
440 dwKeySize = sizeof(szKeyBuff);
441 dwValueSize = sizeof(szValueBuff);
442 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
443 (PBYTE)szValueBuff, &dwValueSize);
447 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
449 format->dwAspect = 1;
458 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
459 format->cfFormat = 0;
461 format->dwAspect = 1;
465 /* Create a clipboard enumerator */
466 GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
467 hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
469 if (FAILED(hRet) || !pIEnumFormatEtc)
472 /* Set our enumerator as the browsers property */
473 V_VT(&var) = VT_UNKNOWN;
474 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
476 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
479 IEnumFORMATETC_Release(pIEnumFormatEtc);
480 goto RegisterDefaultAcceptHeaders_Exit;
484 if (V_VT(&var) == VT_UNKNOWN)
486 /* Our variant is holding the clipboard enumerator */
487 IUnknown* pIUnknown = V_UNKNOWN(&var);
488 IEnumFORMATETC* pClone = NULL;
490 TRACE("Retrieved IEnumFORMATETC property\n");
492 /* Get an IEnumFormatEtc interface from the variants value */
493 pIEnumFormatEtc = NULL;
494 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
495 (PVOID)&pIEnumFormatEtc);
496 if (!hRet && pIEnumFormatEtc)
498 /* Clone and register the enumerator */
499 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
502 GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
503 pRegisterFormatEnumerator(lpBC, pClone, 0);
505 IEnumFORMATETC_Release(pClone);
508 /* Release the IEnumFormatEtc interface */
509 IEnumFORMATETC_Release(pIUnknown);
511 IUnknown_Release(V_UNKNOWN(&var));
514 RegisterDefaultAcceptHeaders_Exit:
515 IWebBrowserApp_Release(pBrowser);
519 /*************************************************************************
522 * Get Explorers "AcceptLanguage" setting.
525 * langbuf [O] Destination for language string
526 * buflen [I] Length of langbuf
527 * [0] Success: used length of langbuf
530 * Success: S_OK. langbuf is set to the language string found.
531 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
532 * does not contain the setting.
533 * E_INVALIDARG, If the buffer is not big enough
535 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
537 static const WCHAR szkeyW[] = {
538 'S','o','f','t','w','a','r','e','\\',
539 'M','i','c','r','o','s','o','f','t','\\',
540 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
541 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
542 static const WCHAR valueW[] = {
543 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
544 static const WCHAR enusW[] = {'e','n','-','u','s',0};
545 DWORD mystrlen, mytype;
551 if(!langbuf || !buflen || !*buflen)
554 mystrlen = (*buflen > 20) ? *buflen : 20 ;
555 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
556 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
557 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
558 /* Did not find value */
559 mylcid = GetUserDefaultLCID();
560 /* somehow the mylcid translates into "en-us"
561 * this is similar to "LOCALE_SABBREVLANGNAME"
562 * which could be gotten via GetLocaleInfo.
563 * The only problem is LOCALE_SABBREVLANGUAGE" is
564 * a 3 char string (first 2 are country code and third is
565 * letter for "sublanguage", which does not come close to
568 lstrcpyW(mystr, enusW);
569 mystrlen = lstrlenW(mystr);
571 /* handle returned string */
572 FIXME("missing code\n");
574 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
576 if(*buflen > strlenW(mystr)) {
577 *buflen = strlenW(mystr);
581 retval = E_INVALIDARG;
582 SetLastError(ERROR_INSUFFICIENT_BUFFER);
585 HeapFree(GetProcessHeap(), 0, mystr);
589 /*************************************************************************
592 * Ascii version of GetAcceptLanguagesW.
594 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
597 DWORD buflenW, convlen;
600 if(!langbuf || !buflen || !*buflen) return E_FAIL;
603 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
604 retval = GetAcceptLanguagesW(langbufW, &buflenW);
606 /* FIXME: this is wrong, the string may not be null-terminated */
607 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,
608 *buflen, NULL, NULL);
609 *buflen = buflenW ? convlen : 0;
611 HeapFree(GetProcessHeap(), 0, langbufW);
615 /*************************************************************************
618 * Convert a GUID to a string.
621 * guid [I] GUID to convert
622 * lpszDest [O] Destination for string
623 * cchMax [I] Length of output buffer
626 * The length of the string created.
628 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
633 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
635 sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
636 guid->Data1, guid->Data2, guid->Data3,
637 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
638 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
640 iLen = strlen(xguid) + 1;
644 memcpy(lpszDest, xguid, iLen);
648 /*************************************************************************
651 * Convert a GUID to a string.
654 * guid [I] GUID to convert
655 * str [O] Destination for string
656 * cmax [I] Length of output buffer
659 * The length of the string created.
661 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
665 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
666 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
667 'X','%','0','2','X','%','0','2','X','}',0};
669 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
671 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
672 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
673 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
675 iLen = strlenW(xguid) + 1;
679 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
683 /*************************************************************************
686 * Determine if a Unicode character is alphabetic.
689 * wc [I] Character to check.
692 * TRUE, if wc is alphabetic,
695 BOOL WINAPI IsCharAlphaWrapW(WCHAR wc)
697 return (get_char_typeW(wc) & C1_ALPHA) != 0;
700 /*************************************************************************
703 * Determine if a Unicode character is upper-case.
706 * wc [I] Character to check.
709 * TRUE, if wc is upper-case,
712 BOOL WINAPI IsCharUpperWrapW(WCHAR wc)
714 return (get_char_typeW(wc) & C1_UPPER) != 0;
717 /*************************************************************************
720 * Determine if a Unicode character is lower-case.
723 * wc [I] Character to check.
726 * TRUE, if wc is lower-case,
729 BOOL WINAPI IsCharLowerWrapW(WCHAR wc)
731 return (get_char_typeW(wc) & C1_LOWER) != 0;
734 /*************************************************************************
737 * Determine if a Unicode character is alphabetic or a digit.
740 * wc [I] Character to check.
743 * TRUE, if wc is alphabetic or a digit,
746 BOOL WINAPI IsCharAlphaNumericWrapW(WCHAR wc)
748 return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
751 /*************************************************************************
754 * Determine if a Unicode character is a space.
757 * wc [I] Character to check.
760 * TRUE, if wc is a space,
763 BOOL WINAPI IsCharSpaceW(WCHAR wc)
765 return (get_char_typeW(wc) & C1_SPACE) != 0;
768 /*************************************************************************
771 * Determine if a Unicode character is a blank.
774 * wc [I] Character to check.
777 * TRUE, if wc is a blank,
781 BOOL WINAPI IsCharBlankW(WCHAR wc)
783 return (get_char_typeW(wc) & C1_BLANK) != 0;
786 /*************************************************************************
789 * Determine if a Unicode character is punctuation.
792 * wc [I] Character to check.
795 * TRUE, if wc is punctuation,
798 BOOL WINAPI IsCharPunctW(WCHAR wc)
800 return (get_char_typeW(wc) & C1_PUNCT) != 0;
803 /*************************************************************************
806 * Determine if a Unicode character is a control character.
809 * wc [I] Character to check.
812 * TRUE, if wc is a control character,
815 BOOL WINAPI IsCharCntrlW(WCHAR wc)
817 return (get_char_typeW(wc) & C1_CNTRL) != 0;
820 /*************************************************************************
823 * Determine if a Unicode character is a digit.
826 * wc [I] Character to check.
829 * TRUE, if wc is a digit,
832 BOOL WINAPI IsCharDigitW(WCHAR wc)
834 return (get_char_typeW(wc) & C1_DIGIT) != 0;
837 /*************************************************************************
840 * Determine if a Unicode character is a hex digit.
843 * wc [I] Character to check.
846 * TRUE, if wc is a hex digit,
849 BOOL WINAPI IsCharXDigitW(WCHAR wc)
851 return (get_char_typeW(wc) & C1_XDIGIT) != 0;
854 /*************************************************************************
858 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
860 FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
864 /*************************************************************************
867 * Insert a bitmap menu item at the bottom of a menu.
870 * hMenu [I] Menu to insert into
871 * flags [I] Flags for insertion
872 * id [I] Menu ID of the item
873 * str [I] Menu text for the item
876 * Success: TRUE, the item is inserted into the menu
877 * Failure: FALSE, if any parameter is invalid
879 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
881 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
882 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
885 /*************************************************************************
888 * Get the text from a given dialog item.
891 * hWnd [I] Handle of dialog
892 * nItem [I] Index of item
893 * lpsDest [O] Buffer for receiving window text
894 * nDestLen [I] Length of buffer.
897 * Success: The length of the returned text.
900 INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
902 HWND hItem = GetDlgItem(hWnd, nItem);
905 return GetWindowTextW(hItem, lpsDest, nDestLen);
907 *lpsDest = (WCHAR)'\0';
911 /*************************************************************************
914 * Set the text of a given dialog item.
917 * hWnd [I] Handle of dialog
918 * iItem [I] Index of item
919 * lpszText [O] Text to set
922 * Success: TRUE. The text of the dialog is set to lpszText.
923 * Failure: FALSE, Otherwise.
925 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
927 HWND hWndItem = GetDlgItem(hWnd, iItem);
929 return SetWindowTextW(hWndItem, lpszText);
933 /*************************************************************************
936 * Compare two Ascii strings up to a given length.
939 * lpszSrc [I] Source string
940 * lpszCmp [I] String to compare to lpszSrc
941 * len [I] Maximum length
944 * A number greater than, less than or equal to 0 depending on whether
945 * lpszSrc is greater than, less than or equal to lpszCmp.
947 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
949 return strncmp(lpszSrc, lpszCmp, len);
952 /*************************************************************************
955 * Unicode version of StrCmpNCA.
957 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
959 return strncmpW(lpszSrc, lpszCmp, len);
962 /*************************************************************************
965 * Compare two Ascii strings up to a given length, ignoring case.
968 * lpszSrc [I] Source string
969 * lpszCmp [I] String to compare to lpszSrc
970 * len [I] Maximum length
973 * A number greater than, less than or equal to 0 depending on whether
974 * lpszSrc is greater than, less than or equal to lpszCmp.
976 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
978 return strncasecmp(lpszSrc, lpszCmp, len);
981 /*************************************************************************
984 * Unicode version of StrCmpNICA.
986 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
988 return strncmpiW(lpszSrc, lpszCmp, len);
991 /*************************************************************************
994 * Compare two Ascii strings.
997 * lpszSrc [I] Source string
998 * lpszCmp [I] String to compare to lpszSrc
1001 * A number greater than, less than or equal to 0 depending on whether
1002 * lpszSrc is greater than, less than or equal to lpszCmp.
1004 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
1006 return strcmp(lpszSrc, lpszCmp);
1009 /*************************************************************************
1012 * Unicode version of StrCmpCA.
1014 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1016 return strcmpW(lpszSrc, lpszCmp);
1019 /*************************************************************************
1022 * Compare two Ascii strings, ignoring case.
1025 * lpszSrc [I] Source string
1026 * lpszCmp [I] String to compare to lpszSrc
1029 * A number greater than, less than or equal to 0 depending on whether
1030 * lpszSrc is greater than, less than or equal to lpszCmp.
1032 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
1034 return strcasecmp(lpszSrc, lpszCmp);
1037 /*************************************************************************
1040 * Unicode version of StrCmpICA.
1042 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1044 return strcmpiW(lpszSrc, lpszCmp);
1047 /*************************************************************************
1050 * Get an identification string for the OS and explorer.
1053 * lpszDest [O] Destination for Id string
1054 * dwDestLen [I] Length of lpszDest
1057 * TRUE, If the string was created successfully
1060 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
1064 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1066 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
1068 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1074 /*************************************************************************
1077 * Unicode version of SHAboutInfoA.
1079 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
1081 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
1082 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1083 ' ','E','x','p','l','o','r','e','r','\0' };
1084 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
1085 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
1086 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1087 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
1088 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1089 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1090 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
1091 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1092 ' ','E','x','p','l','o','r','e','r','\\',
1093 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
1094 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
1095 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
1096 'V','e','r','s','i','o','n','\0' };
1097 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
1098 'O','w','n','e','r','\0' };
1099 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
1100 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
1101 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
1102 static const WCHAR szUpdate[] = { 'I','E','A','K',
1103 'U','p','d','a','t','e','U','r','l','\0' };
1104 static const WCHAR szHelp[] = { 'I','E','A','K',
1105 'H','e','l','p','S','t','r','i','n','g','\0' };
1108 DWORD dwType, dwLen;
1110 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1117 /* Try the NT key first, followed by 95/98 key */
1118 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
1119 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
1125 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1127 DWORD dwStrLen = strlenW(buff);
1128 dwLen = 30 - dwStrLen;
1129 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1130 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1132 StrCatBuffW(lpszDest, buff, dwDestLen);
1134 /* ~Registered Owner */
1137 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
1139 StrCatBuffW(lpszDest, buff, dwDestLen);
1141 /* ~Registered Organization */
1143 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
1145 StrCatBuffW(lpszDest, buff, dwDestLen);
1147 /* FIXME: Not sure where this number comes from */
1151 StrCatBuffW(lpszDest, buff, dwDestLen);
1155 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1157 StrCatBuffW(lpszDest, buff, dwDestLen);
1159 /* ~IE Update Url */
1161 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1163 StrCatBuffW(lpszDest, buff, dwDestLen);
1165 /* ~IE Help String */
1167 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1169 StrCatBuffW(lpszDest, buff, dwDestLen);
1175 /*************************************************************************
1178 * Call IOleCommandTarget_QueryStatus() on an object.
1181 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1182 * pguidCmdGroup [I] GUID for the command group
1184 * prgCmds [O] Commands
1185 * pCmdText [O] Command text
1189 * Failure: E_FAIL, if lpUnknown is NULL.
1190 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1191 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1193 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1194 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1196 HRESULT hRet = E_FAIL;
1198 TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1202 IOleCommandTarget* lpOle;
1204 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1207 if (SUCCEEDED(hRet) && lpOle)
1209 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1211 IOleCommandTarget_Release(lpOle);
1217 /*************************************************************************
1220 * Call IOleCommandTarget_Exec() on an object.
1223 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1224 * pguidCmdGroup [I] GUID for the command group
1228 * Failure: E_FAIL, if lpUnknown is NULL.
1229 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1230 * Otherwise, an error code from IOleCommandTarget_Exec().
1232 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1233 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1236 HRESULT hRet = E_FAIL;
1238 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1239 nCmdexecopt, pvaIn, pvaOut);
1243 IOleCommandTarget* lpOle;
1245 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1247 if (SUCCEEDED(hRet) && lpOle)
1249 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1250 nCmdexecopt, pvaIn, pvaOut);
1251 IOleCommandTarget_Release(lpOle);
1257 /*************************************************************************
1260 * Retrieve, modify, and re-set a value from a window.
1263 * hWnd [I] Window to get value from
1264 * offset [I] Offset of value
1265 * wMask [I] Mask for uiFlags
1266 * wFlags [I] Bits to set in window value
1269 * The new value as it was set, or 0 if any parameter is invalid.
1272 * Any bits set in uiMask are cleared from the value, then any bits set in
1273 * uiFlags are set in the value.
1275 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1277 LONG ret = GetWindowLongA(hwnd, offset);
1278 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1280 if (newFlags != ret)
1281 ret = SetWindowLongA(hwnd, offset, newFlags);
1285 /*************************************************************************
1288 * Change a window's parent.
1291 * hWnd [I] Window to change parent of
1292 * hWndParent [I] New parent window
1295 * The old parent of hWnd.
1298 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1299 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1301 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1303 TRACE("%p, %p\n", hWnd, hWndParent);
1305 if(GetParent(hWnd) == hWndParent)
1309 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1311 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1313 return SetParent(hWnd, hWndParent);
1316 /*************************************************************************
1319 * Locate and advise a connection point in an IConnectionPointContainer object.
1322 * lpUnkSink [I] Sink for the connection point advise call
1323 * riid [I] REFIID of connection point to advise
1324 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1325 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1326 * lpCookie [O] Pointer to connection point cookie
1327 * lppCP [O] Destination for the IConnectionPoint found
1330 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1331 * that was advised. The caller is responsable for releasing it.
1332 * Failure: E_FAIL, if any arguments are invalid.
1333 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1334 * Or an HRESULT error code if any call fails.
1336 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1337 IUnknown* lpUnknown, LPDWORD lpCookie,
1338 IConnectionPoint **lppCP)
1341 IConnectionPointContainer* lpContainer;
1342 IConnectionPoint *lpCP;
1344 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1350 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1351 (void**)&lpContainer);
1352 if (SUCCEEDED(hRet))
1354 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1356 if (SUCCEEDED(hRet))
1359 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1360 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1365 if (lppCP && SUCCEEDED(hRet))
1366 *lppCP = lpCP; /* Caller keeps the interface */
1368 IConnectionPoint_Release(lpCP); /* Release it */
1371 IUnknown_Release(lpContainer);
1376 /*************************************************************************
1379 * Release an interface.
1382 * lpUnknown [I] Object to release
1387 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1391 TRACE("(%p)\n",lpUnknown);
1393 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1397 TRACE("doing Release\n");
1399 return IUnknown_Release(temp);
1402 /*************************************************************************
1405 * Skip '//' if present in a string.
1408 * lpszSrc [I] String to check for '//'
1411 * Success: The next character after the '//' or the string if not present
1412 * Failure: NULL, if lpszStr is NULL.
1414 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1416 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1421 /*************************************************************************
1424 * Check if two interfaces come from the same object.
1427 * lpInt1 [I] Interface to check against lpInt2.
1428 * lpInt2 [I] Interface to check against lpInt1.
1431 * TRUE, If the interfaces come from the same object.
1434 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1436 LPVOID lpUnknown1, lpUnknown2;
1438 TRACE("%p %p\n", lpInt1, lpInt2);
1440 if (!lpInt1 || !lpInt2)
1443 if (lpInt1 == lpInt2)
1446 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1447 (LPVOID *)&lpUnknown1)))
1450 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1451 (LPVOID *)&lpUnknown2)))
1454 if (lpUnknown1 == lpUnknown2)
1460 /*************************************************************************
1463 * Get the window handle of an object.
1466 * lpUnknown [I] Object to get the window handle of
1467 * lphWnd [O] Destination for window handle
1470 * Success: S_OK. lphWnd contains the objects window handle.
1471 * Failure: An HRESULT error code.
1474 * lpUnknown is expected to support one of the following interfaces:
1475 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1477 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1479 /* FIXME: Wine has no header for this object */
1480 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1481 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1483 HRESULT hRet = E_FAIL;
1485 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1490 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1494 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1498 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1503 if (SUCCEEDED(hRet))
1505 /* Lazyness here - Since GetWindow() is the first method for the above 3
1506 * interfaces, we use the same call for them all.
1508 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1509 IUnknown_Release(lpOle);
1511 TRACE("Returning HWND=%p\n", *lphWnd);
1517 /*************************************************************************
1520 * Call a method on as as yet unidentified object.
1523 * pUnk [I] Object supporting the unidentified interface,
1524 * arg [I] Argument for the call on the object.
1529 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1531 static const GUID guid_173 = {
1532 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1536 TRACE("(%p,%ld)\n", pUnk, arg);
1538 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1539 * We use this interface as its vtable entry is compatible with the
1540 * object in question.
1541 * FIXME: Find out what this object is and where it should be defined.
1544 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1546 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1547 IMalloc_Release(pUnk2);
1552 /*************************************************************************
1555 * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
1560 * Failure: E_FAIL, if p1 is NULL.
1561 * E_NOINTERFACE If p1 does not support the IPersist interface,
1562 * Or an HRESULT error code.
1564 DWORD WINAPI IUnknown_SetSite(
1565 IUnknown *p1, /* [in] OLE object */
1566 LPVOID *p2) /* [out] ptr for call results */
1570 if (!p1) return E_FAIL;
1572 /* see if SetSite interface exists for IObjectWithSite object */
1573 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1574 TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1577 /* see if GetClassId interface exists for IPersistMoniker object */
1578 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1579 TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1580 if (ret) return ret;
1582 /* fake a GetClassId call */
1583 ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1584 TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1586 IUnknown_Release((IUnknown *)aa);
1589 /* fake a SetSite call */
1590 ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1591 TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1593 IUnknown_Release((IUnknown *)p1);
1598 /*************************************************************************
1601 * Call IPersist_GetClassID() on an object.
1604 * lpUnknown [I] Object supporting the IPersist interface
1605 * lpClassId [O] Destination for Class Id
1608 * Success: S_OK. lpClassId contains the Class Id requested.
1609 * Failure: E_FAIL, If lpUnknown is NULL,
1610 * E_NOINTERFACE If lpUnknown does not support IPersist,
1611 * Or an HRESULT error code.
1613 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1615 IPersist* lpPersist;
1616 HRESULT hRet = E_FAIL;
1618 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1622 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1623 if (SUCCEEDED(hRet))
1625 IPersist_GetClassID(lpPersist, lpClassId);
1626 IPersist_Release(lpPersist);
1632 /*************************************************************************
1635 * Retrieve a Service Interface from an object.
1638 * lpUnknown [I] Object to get an IServiceProvider interface from
1639 * sid [I] Service ID for IServiceProvider_QueryService() call
1640 * riid [I] Function requested for QueryService call
1641 * lppOut [O] Destination for the service interface pointer
1644 * Success: S_OK. lppOut contains an object providing the requested service
1645 * Failure: An HRESULT error code
1648 * lpUnknown is expected to support the IServiceProvider interface.
1650 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1653 IServiceProvider* pService = NULL;
1664 /* Get an IServiceProvider interface from the object */
1665 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1666 (LPVOID*)&pService);
1668 if (!hRet && pService)
1670 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1672 /* Get a Service interface from the object */
1673 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1675 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1677 /* Release the IServiceProvider interface */
1678 IUnknown_Release(pService);
1683 /*************************************************************************
1686 * Loads a popup menu.
1689 * hInst [I] Instance handle
1690 * szName [I] Menu name
1696 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1698 HMENU hMenu, hSubMenu;
1700 if ((hMenu = LoadMenuW(hInst, szName)))
1702 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1703 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1711 typedef struct _enumWndData
1716 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1719 /* Callback for SHLWAPI_178 */
1720 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1722 enumWndData *data = (enumWndData *)lParam;
1724 TRACE("(%p,%p)\n", hWnd, data);
1725 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1729 /*************************************************************************
1732 * Send or post a message to every child of a window.
1735 * hWnd [I] Window whose children will get the messages
1736 * uiMsgId [I] Message Id
1737 * wParam [I] WPARAM of message
1738 * lParam [I] LPARAM of message
1739 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1745 * The appropriate ASCII or Unicode function is called for the window.
1747 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1751 TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1755 data.uiMsgId = uiMsgId;
1756 data.wParam = wParam;
1757 data.lParam = lParam;
1760 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1762 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1764 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1768 /*************************************************************************
1771 * Remove all sub-menus from a menu.
1774 * hMenu [I] Menu to remove sub-menus from
1777 * Success: 0. All sub-menus under hMenu are removed
1778 * Failure: -1, if any parameter is invalid
1780 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1782 int iItemCount = GetMenuItemCount(hMenu) - 1;
1783 while (iItemCount >= 0)
1785 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1787 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1793 /*************************************************************************
1796 * Enable or disable a menu item.
1799 * hMenu [I] Menu holding menu item
1800 * uID [I] ID of menu item to enable/disable
1801 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1804 * The return code from EnableMenuItem.
1806 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1808 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1811 /*************************************************************************
1814 * Check or uncheck a menu item.
1817 * hMenu [I] Menu holding menu item
1818 * uID [I] ID of menu item to check/uncheck
1819 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1822 * The return code from CheckMenuItem.
1824 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1826 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1829 /*************************************************************************
1832 * Register a window class if it isn't already.
1835 * lpWndClass [I] Window class to register
1838 * The result of the RegisterClassA call.
1840 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1843 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1845 return (DWORD)RegisterClassA(wndclass);
1848 /*************************************************************************
1851 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1852 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1854 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1855 POINTL pt = { 0, 0 };
1861 pdwEffect = &dwEffect;
1863 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1866 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1868 IDropTarget_DragLeave(pDrop);
1872 /*************************************************************************
1875 * Call IPersistPropertyBag_Load() on an object.
1878 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1879 * lpPropBag [O] Destination for loaded IPropertyBag
1883 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1885 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1887 IPersistPropertyBag* lpPPBag;
1888 HRESULT hRet = E_FAIL;
1890 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1894 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1896 if (SUCCEEDED(hRet) && lpPPBag)
1898 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1899 IPersistPropertyBag_Release(lpPPBag);
1905 /*************************************************************************
1908 * Call IOleControlSite_GetExtendedControl() on an object.
1911 * lpUnknown [I] Object supporting the IOleControlSite interface
1912 * lppDisp [O] Destination for resulting IDispatch.
1916 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1918 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1920 IOleControlSite* lpCSite;
1921 HRESULT hRet = E_FAIL;
1923 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1926 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1928 if (SUCCEEDED(hRet) && lpCSite)
1930 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1931 IOleControlSite_Release(lpCSite);
1937 /*************************************************************************
1940 * Get a sub-menu from a menu item.
1943 * hMenu [I] Menu to get sub-menu from
1944 * uID [I] ID of menu item containing sub-menu
1947 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1949 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1953 TRACE("(%p,%uld)\n", hMenu, uID);
1955 mi.cbSize = sizeof(MENUITEMINFOA);
1956 mi.fMask = MIIM_SUBMENU;
1958 if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
1964 /*************************************************************************
1967 * Get the color depth of the primary display.
1973 * The color depth of the primary display.
1975 DWORD WINAPI SHGetCurColorRes()
1983 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1988 /*************************************************************************
1991 * Wait for a message to arrive, with a timeout.
1994 * hand [I] Handle to query
1995 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1998 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1999 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2000 * message is available.
2002 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2004 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2007 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2011 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2013 if (dwTimeout != INFINITE)
2015 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2016 return WAIT_TIMEOUT;
2023 /*************************************************************************
2026 * Blank out a region of text by drawing the background only.
2029 * hDC [I] Device context to draw in
2030 * pRect [I] Area to draw in
2031 * cRef [I] Color to draw in
2036 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2038 COLORREF cOldColor = SetBkColor(hDC, cRef);
2039 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2040 SetBkColor(hDC, cOldColor);
2044 /*************************************************************************
2047 * Return the value asociated with a key in a map.
2050 * lpKeys [I] A list of keys of length iLen
2051 * lpValues [I] A list of values associated with lpKeys, of length iLen
2052 * iLen [I] Length of both lpKeys and lpValues
2053 * iKey [I] The key value to look up in lpKeys
2056 * The value in lpValues associated with iKey, or -1 if iKey is not
2060 * - If two elements in the map share the same key, this function returns
2061 * the value closest to the start of the map
2062 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2064 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2066 if (lpKeys && lpValues)
2072 if (lpKeys[i] == iKey)
2073 return lpValues[i]; /* Found */
2077 return -1; /* Not found */
2081 /*************************************************************************
2084 * Copy an interface pointer
2087 * lppDest [O] Destination for copy
2088 * lpUnknown [I] Source for copy
2093 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2095 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2098 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2103 IUnknown_AddRef(lpUnknown);
2104 *lppDest = lpUnknown;
2108 /*************************************************************************
2112 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2113 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2116 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2117 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2118 return DRAGDROP_E_NOTREGISTERED;
2121 /*************************************************************************
2125 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2127 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2128 return DRAGDROP_E_NOTREGISTERED;
2131 /*************************************************************************
2134 * Determine if a window is not a child of another window.
2137 * hParent [I] Suspected parent window
2138 * hChild [I] Suspected child window
2141 * TRUE: If hChild is a child window of hParent
2142 * FALSE: If hChild is not a child window of hParent, or they are equal
2144 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2146 TRACE("(%p,%p)\n", hParent, hChild);
2148 if (!hParent || !hChild)
2150 else if(hParent == hChild)
2152 return !IsChild(hParent, hChild);
2155 /*************************************************************************
2158 * Some sort of memory management process.
2160 DWORD WINAPI FDSA_Initialize(
2167 FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2172 /*************************************************************************
2175 * Some sort of memory management process.
2177 DWORD WINAPI FDSA_Destroy(
2180 FIXME("(%p) stub\n",
2185 /*************************************************************************
2188 * Some sort of memory management process.
2190 DWORD WINAPI FDSA_InsertItem(
2195 FIXME("(%p 0x%08lx %p) stub\n",
2200 /*************************************************************************
2203 DWORD WINAPI FDSA_DeleteItem(
2207 FIXME("(%p 0x%08lx) stub\n",
2217 /*************************************************************************
2220 * Call IUnknown_QueryInterface() on a table of objects.
2224 * Failure: E_POINTER or E_NOINTERFACE.
2226 HRESULT WINAPI QISearch(
2227 LPVOID w, /* [in] Table of interfaces */
2228 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2229 REFIID riid, /* [in] REFIID to get interface for */
2230 LPVOID *ppv) /* [out] Destination for interface pointer */
2234 IFACE_INDEX_TBL *xmove;
2236 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2239 while (xmove->refid) {
2240 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2241 if (IsEqualIID(riid, xmove->refid)) {
2242 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2243 TRACE("matched, returning (%p)\n", a_vtbl);
2244 *ppv = (LPVOID)a_vtbl;
2245 IUnknown_AddRef(a_vtbl);
2251 if (IsEqualIID(riid, &IID_IUnknown)) {
2252 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2253 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2254 *ppv = (LPVOID)a_vtbl;
2255 IUnknown_AddRef(a_vtbl);
2259 ret = E_NOINTERFACE;
2263 TRACE("-- 0x%08lx\n", ret);
2267 /*************************************************************************
2270 * Remove the "PropDlgFont" property from a window.
2273 * hWnd [I] Window to remove the property from
2276 * A handle to the removed property, or NULL if it did not exist.
2278 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2282 TRACE("(%p)\n", hWnd);
2284 hProp = GetPropA(hWnd, "PropDlgFont");
2288 DeleteObject(hProp);
2289 hProp = RemovePropA(hWnd, "PropDlgFont");
2294 /*************************************************************************
2297 * Load the in-process server of a given GUID.
2300 * refiid [I] GUID of the server to load.
2303 * Success: A handle to the loaded server dll.
2304 * Failure: A NULL handle.
2306 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2310 CHAR value[MAX_PATH], string[MAX_PATH];
2312 strcpy(string, "CLSID\\");
2313 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2314 strcat(string, "\\InProcServer32");
2317 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2318 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2319 RegCloseKey(newkey);
2320 return LoadLibraryExA(value, 0, 0);
2323 /*************************************************************************
2326 * Unicode version of SHLWAPI_183.
2328 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2332 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2334 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2336 return RegisterClassW(lpWndClass);
2339 /*************************************************************************
2342 * Unregister a list of classes.
2345 * hInst [I] Application instance that registered the classes
2346 * lppClasses [I] List of class names
2347 * iCount [I] Number of names in lppClasses
2352 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2356 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2360 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2361 UnregisterClassA(*lppClasses, hInst);
2367 /*************************************************************************
2370 * Unicode version of SHUnregisterClassesA.
2372 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2376 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2380 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2381 UnregisterClassW(*lppClasses, hInst);
2387 /*************************************************************************
2390 * Call The correct (Ascii/Unicode) default window procedure for a window.
2393 * hWnd [I] Window to call the default procedure for
2394 * uMessage [I] Message ID
2395 * wParam [I] WPARAM of message
2396 * lParam [I] LPARAM of message
2399 * The result of calling DefWindowProcA() or DefWindowProcW().
2401 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2403 if (IsWindowUnicode(hWnd))
2404 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2405 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2408 /*************************************************************************
2411 * Create a worker window using CreateWindowExA().
2414 * wndProc [I] Window procedure
2415 * hWndParent [I] Parent window
2416 * dwExStyle [I] Extra style flags
2417 * dwStyle [I] Style flags
2418 * hMenu [I] Window menu
2422 * Success: The window handle of the newly created window.
2425 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2426 DWORD dwStyle, HMENU hMenu, LONG z)
2428 static const char* szClass = "WorkerA";
2432 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2433 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2435 /* Create Window class */
2437 wc.lpfnWndProc = DefWindowProcA;
2440 wc.hInstance = shlwapi_hInstance;
2442 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2443 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2444 wc.lpszMenuName = NULL;
2445 wc.lpszClassName = szClass;
2447 SHRegisterClassA(&wc); /* Register class */
2449 /* FIXME: Set extra bits in dwExStyle */
2451 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2452 hWndParent, hMenu, shlwapi_hInstance, 0);
2455 SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2458 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2463 typedef struct tagPOLICYDATA
2465 DWORD policy; /* flags value passed to SHRestricted */
2466 LPCWSTR appstr; /* application str such as "Explorer" */
2467 LPCWSTR keystr; /* name of the actual registry key / policy */
2468 } POLICYDATA, *LPPOLICYDATA;
2470 #define SHELL_NO_POLICY 0xffffffff
2472 /* default shell policy registry key */
2473 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2474 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2475 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2476 '\\','P','o','l','i','c','i','e','s',0};
2478 /*************************************************************************
2481 * Retrieve a policy value from the registry.
2484 * lpSubKey [I] registry key name
2485 * lpSubName [I] subname of registry key
2486 * lpValue [I] value name of registry value
2489 * the value associated with the registry key or 0 if not found
2491 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2493 DWORD retval, datsize = sizeof(retval);
2497 lpSubKey = strRegistryPolicyW;
2499 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2500 if (retval != ERROR_SUCCESS)
2501 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2502 if (retval != ERROR_SUCCESS)
2505 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2510 /*************************************************************************
2513 * Helper function to retrieve the possibly cached value for a specific policy
2516 * policy [I] The policy to look for
2517 * initial [I] Main registry key to open, if NULL use default
2518 * polTable [I] Table of known policies, 0 terminated
2519 * polArr [I] Cache array of policy values
2522 * The retrieved policy value or 0 if not successful
2525 * This function is used by the native SHRestricted function to search for the
2526 * policy and cache it once retrieved. The current Wine implementation uses a
2527 * different POLICYDATA structure and implements a similar algorithme adapted to
2530 DWORD WINAPI SHRestrictionLookup(
2533 LPPOLICYDATA polTable,
2536 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2538 if (!polTable || !polArr)
2541 for (;polTable->policy; polTable++, polArr++)
2543 if (policy == polTable->policy)
2545 /* we have a known policy */
2547 /* check if this policy has been cached */
2548 if (*polArr == SHELL_NO_POLICY)
2549 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2553 /* we don't know this policy, return 0 */
2554 TRACE("unknown policy: (%08lx)\n", policy);
2558 /*************************************************************************
2561 * Get an interface from an object.
2564 * Success: S_OK. ppv contains the requested interface.
2565 * Failure: An HRESULT error code.
2568 * This QueryInterface asks the inner object for a interface. In case
2569 * of aggregation this request would be forwarded by the inner to the
2570 * outer object. This function asks the inner object directly for the
2571 * interface circumventing the forwarding to the outer object.
2573 HRESULT WINAPI SHWeakQueryInterface(
2574 IUnknown * pUnk, /* [in] Outer object */
2575 IUnknown * pInner, /* [in] Inner object */
2576 IID * riid, /* [in] Interface GUID to query for */
2577 LPVOID* ppv) /* [out] Destination for queried interface */
2579 HRESULT hret = E_NOINTERFACE;
2580 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2583 if(pUnk && pInner) {
2584 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2585 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2587 TRACE("-- 0x%08lx\n", hret);
2591 /*************************************************************************
2594 * Move a reference from one interface to another.
2597 * lpDest [O] Destination to receive the reference
2598 * lppUnknown [O] Source to give up the reference to lpDest
2603 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2605 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2610 IUnknown_AddRef(lpDest);
2611 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2615 /*************************************************************************
2618 * Convert an ASCII string of a CLSID into a CLSID.
2621 * idstr [I] String representing a CLSID in registry format
2622 * id [O] Destination for the converted CLSID
2625 * Success: TRUE. id contains the converted CLSID.
2628 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2631 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2632 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2635 /*************************************************************************
2638 * Unicode version of GUIDFromStringA.
2640 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2642 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2645 /*************************************************************************
2648 * Determine if the browser is integrated into the shell, and set a registry
2655 * 1, If the browser is not integrated.
2656 * 2, If the browser is integrated.
2659 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2660 * either set to TRUE, or removed depending on whether the browser is deemed
2663 DWORD WINAPI WhichPlatform()
2665 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2666 static DWORD dwState = 0;
2668 DWORD dwRet, dwData, dwSize;
2673 /* If shell32 exports DllGetVersion(), the browser is integrated */
2674 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2675 dwState = pDllGetVersion ? 2 : 1;
2677 /* Set or delete the key accordingly */
2678 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2679 "Software\\Microsoft\\Internet Explorer", 0,
2680 KEY_ALL_ACCESS, &hKey);
2683 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2684 (LPBYTE)&dwData, &dwSize);
2686 if (!dwRet && dwState == 1)
2688 /* Value exists but browser is not integrated */
2689 RegDeleteValueA(hKey, szIntegratedBrowser);
2691 else if (dwRet && dwState == 2)
2693 /* Browser is integrated but value does not exist */
2695 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2696 (LPBYTE)&dwData, sizeof(dwData));
2703 /*************************************************************************
2706 * Unicode version of SHCreateWorkerWindowA.
2708 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2709 DWORD dwStyle, HMENU hMenu, LONG z)
2711 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2715 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2716 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2718 /* If our OS is natively ASCII, use the ASCII version */
2719 if (!(GetVersion() & 0x80000000)) /* NT */
2720 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2722 /* Create Window class */
2724 wc.lpfnWndProc = DefWindowProcW;
2727 wc.hInstance = shlwapi_hInstance;
2729 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2730 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2731 wc.lpszMenuName = NULL;
2732 wc.lpszClassName = szClass;
2734 SHRegisterClassW(&wc); /* Register class */
2736 /* FIXME: Set extra bits in dwExStyle */
2738 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2739 hWndParent, hMenu, shlwapi_hInstance, 0);
2742 SetWindowLongW(hWnd, DWL_MSGRESULT, z);
2745 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2750 /*************************************************************************
2753 * Get and show a context menu from a shell folder.
2756 * hWnd [I] Window displaying the shell folder
2757 * lpFolder [I] IShellFolder interface
2758 * lpApidl [I] Id for the particular folder desired
2762 * Failure: An HRESULT error code indicating the error.
2764 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2766 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2769 /*************************************************************************
2772 * _SHPackDispParamsV
2774 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2776 FIXME("%p %p %p %p\n",w,x,y,z);
2780 /*************************************************************************
2783 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2784 * function does...).
2786 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2788 FIXME("%p %p %p %p\n", w, x, y, z);
2792 /*************************************************************************
2795 * _IConnectionPoint_SimpleInvoke
2797 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2802 FIXME("(%p %p %p) stub\n",x,y,z);
2806 /*************************************************************************
2809 * Notify an IConnectionPoint object of changes.
2812 * lpCP [I] Object to notify
2817 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2818 * IConnectionPoint interface.
2820 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2822 IEnumConnections *lpEnum;
2823 HRESULT hRet = E_NOINTERFACE;
2825 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2827 /* Get an enumerator for the connections */
2829 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2831 if (SUCCEEDED(hRet))
2833 IPropertyNotifySink *lpSink;
2834 CONNECTDATA connData;
2837 /* Call OnChanged() for every notify sink in the connection point */
2838 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2840 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2843 IPropertyNotifySink_OnChanged(lpSink, dispID);
2844 IPropertyNotifySink_Release(lpSink);
2846 IUnknown_Release(connData.pUnk);
2849 IEnumConnections_Release(lpEnum);
2854 /*************************************************************************
2857 * Notify an IConnectionPointContainer object of changes.
2860 * lpUnknown [I] Object to notify
2865 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2866 * IConnectionPointContainer interface.
2868 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
2870 IConnectionPointContainer* lpCPC = NULL;
2871 HRESULT hRet = E_NOINTERFACE;
2873 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2876 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
2878 if (SUCCEEDED(hRet))
2880 IConnectionPoint* lpCP;
2882 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
2883 IConnectionPointContainer_Release(lpCPC);
2885 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
2886 IConnectionPoint_Release(lpCP);
2891 /*************************************************************************
2896 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2898 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2899 return pPlaySoundW(pszSound, hmod, fdwSound);
2902 /*************************************************************************
2905 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
2908 * str1: "I" "I" pushl esp+0x20
2909 * str2: "U" "I" pushl 0x77c93810
2910 * (is "I" and "U" "integer" and "unsigned" ??)
2912 * pStr: "" "" pushl eax
2913 * some_len: 0x824 0x104 pushl 0x824
2914 * lpStr2: "%l" "%l" pushl esp+0xc
2916 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2917 * LocalAlloc(0x00, some_len) -> irrelevant_var
2918 * LocalAlloc(0x40, irrelevant_len) -> pStr
2919 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2920 * shlwapi.PathRemoveBlanksW(pStr);
2922 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2926 /*************************************************************************
2929 * Called by ICQ2000b install via SHDOCVW:
2930 * str1: "InternetShortcut"
2931 * x: some unknown pointer
2932 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2933 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2935 * In short: this one maybe creates a desktop link :-)
2937 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2939 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2943 /*************************************************************************
2948 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2949 LPCWSTR str, UINT count, const INT *lpDx)
2951 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2952 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2955 /*************************************************************************
2958 * See SHGetFileInfoW.
2960 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
2961 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2963 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2964 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2967 /*************************************************************************
2970 * See DragQueryFileW.
2972 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2974 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2975 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2978 /*************************************************************************
2981 * See SHBrowseForFolderW.
2983 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
2985 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2986 return pSHBrowseForFolderW(lpBi);
2989 /*************************************************************************
2992 * See SHGetPathFromIDListW.
2994 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
2996 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2997 return pSHGetPathFromIDListW(pidl, pszPath);
3000 /*************************************************************************
3003 * See ShellExecuteExW.
3005 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3007 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
3008 return pShellExecuteExW(lpExecInfo);
3011 /*************************************************************************
3014 * See SHFileOperationW.
3016 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3018 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
3019 return pSHFileOperationW(lpFileOp);
3022 /*************************************************************************
3025 * See ExtractIconExW.
3027 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
3028 HICON *phiconSmall, UINT nIcons)
3030 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
3031 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
3034 /*************************************************************************
3038 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3040 return InterlockedCompareExchange(dest, xchg, compare);
3043 /*************************************************************************
3046 * See GetFileVersionInfoSizeW.
3048 DWORD WINAPI GetFileVersionInfoSizeWrapW(
3054 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3055 ret = pGetFileVersionInfoSizeW(x, y);
3059 /*************************************************************************
3062 * See GetFileVersionInfoW.
3064 BOOL WINAPI GetFileVersionInfoWrapW(
3065 LPWSTR w, /* [in] path to dll */
3066 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3067 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3068 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3070 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3071 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3074 /*************************************************************************
3077 * See VerQueryValueW.
3079 WORD WINAPI VerQueryValueWrapW(
3080 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3081 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3082 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3083 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3085 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3086 return pVerQueryValueW((char*)w+0x208, x, y, z);
3089 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3090 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3091 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3093 /*************************************************************************
3096 * Change the modality of a shell object.
3099 * lpUnknown [I] Object to make modeless
3100 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3103 * Success: S_OK. The modality lpUnknown is changed.
3104 * Failure: An HRESULT error code indicating the error.
3107 * lpUnknown must support the IOleInPlaceFrame interface, the
3108 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3109 * or the IDocHostUIHandler interface, or this call fails.
3111 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3116 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3121 if (IsIface(IOleInPlaceFrame))
3122 EnableModeless(IOleInPlaceFrame);
3123 else if (IsIface(IShellBrowser))
3124 EnableModeless(IShellBrowser);
3126 /* FIXME: Wine has no headers for these objects yet */
3127 else if (IsIface(IInternetSecurityMgrSite))
3128 EnableModeless(IInternetSecurityMgrSite);
3129 else if (IsIface(IDocHostUIHandler))
3130 EnableModeless(IDocHostUIHandler);
3135 IUnknown_Release(lpObj);
3139 /*************************************************************************
3142 * See SHGetNewLinkInfoW.
3144 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3145 BOOL *pfMustCopy, UINT uFlags)
3147 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3148 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3151 /*************************************************************************
3154 * See SHDefExtractIconW.
3156 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3157 HICON* phiconSmall, UINT nIconSize)
3159 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3160 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3163 /*************************************************************************
3166 * Get and show a context menu from a shell folder.
3169 * hWnd [I] Window displaying the shell folder
3170 * lpFolder [I] IShellFolder interface
3171 * lpApidl [I] Id for the particular folder desired
3172 * bInvokeDefault [I] Whether to invoke the default menu item
3175 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3177 * Failure: An HRESULT error code indicating the error.
3179 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3181 IContextMenu *iContext;
3182 HRESULT hRet = E_FAIL;
3184 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3189 /* Get the context menu from the shell folder */
3190 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3191 &IID_IContextMenu, 0, (void**)&iContext);
3192 if (SUCCEEDED(hRet))
3195 if ((hMenu = CreatePopupMenu()))
3198 DWORD dwDefaultId = 0;
3200 /* Add the context menu entries to the popup */
3201 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3202 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3204 if (SUCCEEDED(hQuery))
3206 if (bInvokeDefault &&
3207 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3209 CMINVOKECOMMANDINFO cmIci;
3210 /* Invoke the default item */
3211 memset(&cmIci,0,sizeof(cmIci));
3212 cmIci.cbSize = sizeof(cmIci);
3213 cmIci.fMask = CMIC_MASK_ASYNCOK;
3215 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3216 cmIci.nShow = SW_SCROLLCHILDREN;
3218 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3223 IContextMenu_Release(iContext);
3228 /*************************************************************************
3233 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3236 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3237 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3240 /*************************************************************************
3243 LANGID WINAPI MLGetUILanguage()
3246 /* FIXME: This should be a forward in the .spec file to the win2k function
3247 * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3249 return GetUserDefaultLangID();
3252 /*************************************************************************
3255 * Load a library from the directory of a particular process.
3258 * new_mod [I] Library name
3259 * inst_hwnd [I] Module whose directory is to be used
3260 * dwFlags [I] Flags controlling the load
3263 * Success: A handle to the loaded module
3264 * Failure: A NULL handle.
3266 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3268 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3270 * FIXME: Native shows calls to:
3271 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3273 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3274 * RegQueryValueExA for "LPKInstalled"
3276 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3277 * RegQueryValueExA for "ResourceLocale"
3279 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3280 * RegQueryValueExA for "Locale"
3282 * and then tests the Locale ("en" for me).
3284 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3286 CHAR mod_path[2*MAX_PATH];
3290 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3291 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3292 if (!len || len >= sizeof(mod_path)) return NULL;
3294 ptr = strrchr(mod_path, '\\');
3296 strcpy(ptr+1, new_mod);
3297 TRACE("loading %s\n", debugstr_a(mod_path));
3298 return LoadLibraryA(mod_path);
3303 /*************************************************************************
3306 * Unicode version of MLLoadLibraryA.
3308 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3310 WCHAR mod_path[2*MAX_PATH];
3314 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3315 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3316 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3318 ptr = strrchrW(mod_path, '\\');
3320 strcpyW(ptr+1, new_mod);
3321 TRACE("loading %s\n", debugstr_w(mod_path));
3322 return LoadLibraryW(mod_path);
3327 /*************************************************************************
3328 * ColorAdjustLuma [SHLWAPI.@]
3330 * Adjust the luminosity of a color
3333 * cRGB [I] RGB value to convert
3334 * dwLuma [I] Luma adjustment
3335 * bUnknown [I] Unknown
3338 * The adjusted RGB color.
3340 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3342 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3348 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3350 FIXME("Ignoring luma adjustment\n");
3352 /* FIXME: The ajdustment is not linear */
3354 cRGB = ColorHLSToRGB(wH, wL, wS);
3359 /*************************************************************************
3362 * See GetSaveFileNameW.
3364 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3366 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3367 return pGetSaveFileNameW(ofn);
3370 /*************************************************************************
3373 * See WNetRestoreConnectionW.
3375 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3377 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3378 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3381 /*************************************************************************
3384 * See WNetGetLastErrorW.
3386 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3387 LPWSTR lpNameBuf, DWORD nNameBufSize)
3389 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3390 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3393 /*************************************************************************
3396 * See PageSetupDlgW.
3398 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3400 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3401 return pPageSetupDlgW(pagedlg);
3404 /*************************************************************************
3409 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3411 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3412 return pPrintDlgW(printdlg);
3415 /*************************************************************************
3418 * See GetOpenFileNameW.
3420 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3422 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3423 return pGetOpenFileNameW(ofn);
3426 /* INTERNAL: Map from HLS color space to RGB */
3427 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3429 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3433 else if (wHue > 120)
3438 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3441 /* Convert to RGB and scale into RGB range (0..255) */
3442 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3444 /*************************************************************************
3445 * ColorHLSToRGB [SHLWAPI.@]
3447 * Convert from hls color space into an rgb COLORREF.
3450 * wHue [I] Hue amount
3451 * wLuminosity [I] Luminosity amount
3452 * wSaturation [I] Saturation amount
3455 * A COLORREF representing the converted color.
3458 * Input hls values are constrained to the range (0..240).
3460 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3466 WORD wGreen, wBlue, wMid1, wMid2;
3468 if (wLuminosity > 120)
3469 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3471 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3473 wMid1 = wLuminosity * 2 - wMid2;
3475 wRed = GET_RGB(wHue + 80);
3476 wGreen = GET_RGB(wHue);
3477 wBlue = GET_RGB(wHue - 80);
3479 return RGB(wRed, wGreen, wBlue);
3482 wRed = wLuminosity * 255 / 240;
3483 return RGB(wRed, wRed, wRed);
3486 /*************************************************************************
3489 * Get the current docking status of the system.
3492 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3495 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3498 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3500 HW_PROFILE_INFOA hwInfo;
3502 TRACE("(0x%08lx)\n", dwFlags);
3504 GetCurrentHwProfileA(&hwInfo);
3505 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3507 case DOCKINFO_DOCKED:
3508 case DOCKINFO_UNDOCKED:
3509 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3515 /*************************************************************************
3518 * Function seems to do FreeLibrary plus other things.
3520 * FIXME native shows the following calls:
3521 * RtlEnterCriticalSection
3523 * GetProcAddress(Comctl32??, 150L)
3525 * RtlLeaveCriticalSection
3526 * followed by the FreeLibrary.
3527 * The above code may be related to .377 above.
3529 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3531 FIXME("(%p) semi-stub\n", hModule);
3532 return FreeLibrary(hModule);
3535 /*************************************************************************
3538 BOOL WINAPI SHFlushSFCacheWrap(void) {
3543 /*************************************************************************
3545 * FIXME I have no idea what this function does or what its arguments are.
3547 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3549 FIXME("(%p) stub\n", hInst);
3554 /*************************************************************************
3557 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3559 FIXME("(%p,%p) stub\n", hInst, hHeap);
3560 return E_FAIL; /* This is what is used if shlwapi not loaded */
3563 /*************************************************************************
3566 DWORD WINAPI MLClearMLHInstance(DWORD x)
3568 FIXME("(0x%08lx)stub\n", x);
3572 /*************************************************************************
3575 * Convert an Unicode string CLSID into a CLSID.
3578 * idstr [I] string containing a CLSID in text form
3579 * id [O] CLSID extracted from the string
3582 * S_OK on success or E_INVALIDARG on failure
3585 * This is really CLSIDFromString() which is exported by ole32.dll,
3586 * however the native shlwapi.dll does *not* import ole32. Nor does
3587 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3588 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3589 * it returns an E_INVALIDARG error code on failure.
3590 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3591 * in "dlls/ole32/compobj.c".
3593 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3601 memset(id, 0, sizeof(CLSID));
3604 else { /* validate the CLSID string */
3606 if (strlenW(s) != 38)
3607 return E_INVALIDARG;
3609 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3610 return E_INVALIDARG;
3612 for (i=1; i<37; i++)
3614 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3616 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3617 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3618 ((s[i] >= L'A') && (s[i] <= L'F')))
3620 return E_INVALIDARG;
3624 TRACE("%s -> %p\n", debugstr_w(s), id);
3626 /* quick lookup table */
3627 memset(table, 0, 256*sizeof(WCHAR));
3629 for (i = 0; i < 10; i++) {
3632 for (i = 0; i < 6; i++) {
3633 table['A' + i] = i+10;
3634 table['a' + i] = i+10;
3637 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3641 s++; /* skip leading brace */
3642 for (i = 0; i < 4; i++) {
3643 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3649 for (i = 0; i < 2; i++) {
3650 p[1-i] = table[*s]<<4 | table[*(s+1)];
3656 for (i = 0; i < 2; i++) {
3657 p[1-i] = table[*s]<<4 | table[*(s+1)];
3663 /* these are just sequential bytes */
3664 for (i = 0; i < 2; i++) {
3665 *p++ = table[*s]<<4 | table[*(s+1)];
3670 for (i = 0; i < 6; i++) {
3671 *p++ = table[*s]<<4 | table[*(s+1)];
3678 /*************************************************************************
3681 * Determine if the OS supports a given feature.
3684 * dwFeature [I] Feature requested (undocumented)
3687 * TRUE If the feature is available.
3688 * FALSE If the feature is not available.
3690 BOOL WINAPI IsOS(DWORD feature)
3692 OSVERSIONINFOA osvi;
3693 DWORD platform, majorv, minorv;
3695 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3696 if(!GetVersionExA(&osvi)) {
3697 ERR("GetVersionEx failed");
3701 majorv = osvi.dwMajorVersion;
3702 minorv = osvi.dwMinorVersion;
3703 platform = osvi.dwPlatformId;
3705 #define ISOS_RETURN(x) \
3706 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3710 case OS_WIN32SORGREATER:
3711 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3712 || platform == VER_PLATFORM_WIN32_WINDOWS)
3714 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3715 case OS_WIN95ORGREATER:
3716 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3717 case OS_NT4ORGREATER:
3718 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3719 case OS_WIN2000ORGREATER_ALT:
3720 case OS_WIN2000ORGREATER:
3721 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3722 case OS_WIN98ORGREATER:
3723 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3725 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3727 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3728 case OS_WIN2000SERVER:
3729 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3730 case OS_WIN2000ADVSERVER:
3731 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3732 case OS_WIN2000DATACENTER:
3733 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3734 case OS_WIN2000TERMINAL:
3735 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3737 FIXME("(OS_EMBEDDED) What should we return here?\n");
3739 case OS_TERMINALCLIENT:
3740 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3742 case OS_TERMINALREMOTEADMIN:
3743 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3746 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3747 case OS_MEORGREATER:
3748 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3749 case OS_XPORGREATER:
3750 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3752 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3753 case OS_PROFESSIONAL:
3754 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3756 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3758 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3760 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3761 case OS_TERMINALSERVER:
3762 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3763 case OS_PERSONALTERMINALSERVER:
3764 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3765 case OS_FASTUSERSWITCHING:
3766 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3768 case OS_WELCOMELOGONUI:
3769 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3771 case OS_DOMAINMEMBER:
3772 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3775 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3777 FIXME("(OS_WOW6432) Should we check this?\n");
3780 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3781 case OS_SMALLBUSINESSSERVER:
3782 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3784 FIXME("(OS_TABLEPC) What should we return here?\n");
3786 case OS_SERVERADMINUI:
3787 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3789 case OS_MEDIACENTER:
3790 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3793 FIXME("(OS_APPLIANCE) What should we return here?\n");
3799 WARN("(0x%lx) unknown parameter\n",feature);
3804 /*************************************************************************
3805 * ColorRGBToHLS [SHLWAPI.@]
3807 * Convert an rgb COLORREF into the hls color space.
3810 * cRGB [I] Source rgb value
3811 * pwHue [O] Destination for converted hue
3812 * pwLuminance [O] Destination for converted luminance
3813 * pwSaturation [O] Destination for converted saturation
3816 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3820 * Output HLS values are constrained to the range (0..240).
3821 * For Achromatic conversions, Hue is set to 160.
3823 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3824 LPWORD pwLuminance, LPWORD pwSaturation)
3826 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3828 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3830 wR = GetRValue(cRGB);
3831 wG = GetGValue(cRGB);
3832 wB = GetBValue(cRGB);
3834 wMax = max(wR, max(wG, wB));
3835 wMin = min(wR, min(wG, wB));
3838 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3842 /* Achromatic case */
3844 /* Hue is now unrepresentable, but this is what native returns... */
3849 /* Chromatic case */
3850 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3853 if (wLuminosity <= 120)
3854 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3856 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3859 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3860 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
3861 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
3864 wHue = wBNorm - wGNorm;
3865 else if (wG == wMax)
3866 wHue = 80 + wRNorm - wBNorm;
3868 wHue = 160 + wGNorm - wRNorm;
3871 else if (wHue > 240)
3877 *pwLuminance = wLuminosity;
3879 *pwSaturation = wSaturation;
3882 /*************************************************************************
3883 * SHCreateShellPalette [SHLWAPI.@]
3885 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
3888 return CreateHalftonePalette(hdc);
3891 /*************************************************************************
3892 * SHGetInverseCMAP (SHLWAPI.@)
3894 * Get an inverse color map table.
3897 * lpCmap [O] Destination for color map
3898 * dwSize [I] Size of memory pointed to by lpCmap
3902 * Failure: E_POINTER, If lpCmap is invalid.
3903 * E_INVALIDARG, If dwFlags is invalid
3904 * E_OUTOFMEMORY, If there is no memory available
3907 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
3908 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
3910 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
3911 * this DLL's internal CMap.
3913 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
3916 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3917 *dest = (DWORD)0xabba1249;
3920 FIXME("(%p, %#lx) stub\n", dest, dwSize);
3924 /*************************************************************************
3925 * SHIsLowMemoryMachine [SHLWAPI.@]
3927 * Determine if the current computer has low memory.
3933 * TRUE if the users machine has 16 Megabytes of memory or less,
3936 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
3938 FIXME("(0x%08lx) stub\n", x);
3942 /*************************************************************************
3943 * GetMenuPosFromID [SHLWAPI.@]
3945 * Return the position of a menu item from its Id.
3948 * hMenu [I] Menu containing the item
3949 * wID [I] Id of the menu item
3952 * Success: The index of the menu item in hMenu.
3953 * Failure: -1, If the item is not found.
3955 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
3958 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
3960 while (nIter < nCount)
3963 if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
3970 /*************************************************************************
3973 * Same as SHLWAPI.GetMenuPosFromID
3975 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
3977 return GetMenuPosFromID(hMenu, uID);
3981 /*************************************************************************
3984 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
3995 /*************************************************************************
3998 DWORD WINAPI SHGetAppCompatFlags(DWORD Unknown)
4005 /*************************************************************************
4008 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4009 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4011 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4014 /*************************************************************************
4015 * SHSkipJunction [SHLWAPI.@]
4017 * Determine if a bind context can be bound to an object
4020 * pbc [I] Bind context to check
4021 * pclsid [I] CLSID of object to be bound to
4024 * TRUE: If it is safe to bind
4025 * FALSE: If pbc is invalid or binding would not be safe
4028 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4030 static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4031 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4038 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4042 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4043 IsEqualGUID(pclsid, &clsid))
4046 IUnknown_Release(lpUnk);
4052 /***********************************************************************
4053 * SHGetShellKey (SHLWAPI.@)
4055 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4057 FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
4061 /***********************************************************************
4062 * SHQueueUserWorkItem (SHLWAPI.@)
4064 HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
4066 FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
4070 /***********************************************************************
4071 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4073 DWORD WINAPI IUnknown_OnFocusChangeIS(IUnknown * pUnk, IUnknown * pFocusObject, BOOL bChange)
4075 FIXME("(%p, %p, %s)\n", pUnk, pFocusObject, bChange ? "TRUE" : "FALSE");
4078 IInputObjectSite * pIOS = NULL;
4079 if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IInputObjectSite, (void **)&pIOS))
4080 IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bChange);
4086 /***********************************************************************
4087 * SHGetValueW (SHLWAPI.@)
4089 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4091 FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4095 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4097 /***********************************************************************
4098 * GetUIVersion (SHLWAPI.452)
4100 DWORD WINAPI GetUIVersion(void)
4102 static DWORD version;
4106 DllGetVersion_func pDllGetVersion;
4107 HMODULE dll = LoadLibraryA("shell32.dll");
4110 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4114 dvi.cbSize = sizeof(DLLVERSIONINFO);
4115 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4118 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */