2410 lines
64 KiB
C
2410 lines
64 KiB
C
/*
|
|
* SHLWAPI ordinal functions
|
|
*
|
|
* Copyright 1997 Marcus Meissner
|
|
* 1998 Jürgen Schmied
|
|
* 2001 Jon Griffiths
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "windef.h"
|
|
#include "winnls.h"
|
|
#include "winbase.h"
|
|
#include "ddeml.h"
|
|
#include "shlobj.h"
|
|
#include "shellapi.h"
|
|
#include "commdlg.h"
|
|
#include "wine/unicode.h"
|
|
#include "wine/obj_base.h"
|
|
#include "wine/obj_inplace.h"
|
|
#include "wine/obj_serviceprovider.h"
|
|
#include "wingdi.h"
|
|
#include "winreg.h"
|
|
#include "winuser.h"
|
|
#include "debugtools.h"
|
|
#include "ordinal.h"
|
|
#include "shlwapi.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(shell);
|
|
|
|
extern HINSTANCE shlwapi_hInstance;
|
|
extern HMODULE SHLWAPI_hshell32;
|
|
extern HMODULE SHLWAPI_hwinmm;
|
|
extern HMODULE SHLWAPI_hcomdlg32;
|
|
extern HMODULE SHLWAPI_hmpr;
|
|
extern HMODULE SHLWAPI_hmlang;
|
|
extern HMODULE SHLWAPI_hversion;
|
|
|
|
extern DWORD SHLWAPI_ThreadRef_index;
|
|
|
|
typedef HANDLE HSHARED; /* Shared memory */
|
|
|
|
/* following is GUID for IObjectWithSite::SetSite -- see _174 */
|
|
static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
|
|
/* following is GUID for IPersistMoniker::GetClassID -- see _174 */
|
|
static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
|
|
|
|
/* The following schemes were identified in the native version of
|
|
* SHLWAPI.DLL version 5.50
|
|
*/
|
|
typedef enum {
|
|
URL_SCHEME_INVALID = -1,
|
|
URL_SCHEME_UNKNOWN = 0,
|
|
URL_SCHEME_FTP,
|
|
URL_SCHEME_HTTP,
|
|
URL_SCHEME_GOPHER,
|
|
URL_SCHEME_MAILTO,
|
|
URL_SCHEME_NEWS,
|
|
URL_SCHEME_NNTP,
|
|
URL_SCHEME_TELNET,
|
|
URL_SCHEME_WAIS,
|
|
URL_SCHEME_FILE,
|
|
URL_SCHEME_MK,
|
|
URL_SCHEME_HTTPS,
|
|
URL_SCHEME_SHELL,
|
|
URL_SCHEME_SNEWS,
|
|
URL_SCHEME_LOCAL,
|
|
URL_SCHEME_JAVASCRIPT,
|
|
URL_SCHEME_VBSCRIPT,
|
|
URL_SCHEME_ABOUT,
|
|
URL_SCHEME_RES,
|
|
URL_SCHEME_MAXVALUE
|
|
} URL_SCHEME;
|
|
|
|
typedef struct {
|
|
URL_SCHEME scheme_number;
|
|
LPCSTR scheme_name;
|
|
} SHL_2_inet_scheme;
|
|
|
|
static const SHL_2_inet_scheme shlwapi_schemes[] = {
|
|
{URL_SCHEME_FTP, "ftp"},
|
|
{URL_SCHEME_HTTP, "http"},
|
|
{URL_SCHEME_GOPHER, "gopher"},
|
|
{URL_SCHEME_MAILTO, "mailto"},
|
|
{URL_SCHEME_NEWS, "news"},
|
|
{URL_SCHEME_NNTP, "nntp"},
|
|
{URL_SCHEME_TELNET, "telnet"},
|
|
{URL_SCHEME_WAIS, "wais"},
|
|
{URL_SCHEME_FILE, "file"},
|
|
{URL_SCHEME_MK, "mk"},
|
|
{URL_SCHEME_HTTPS, "https"},
|
|
{URL_SCHEME_SHELL, "shell"},
|
|
{URL_SCHEME_SNEWS, "snews"},
|
|
{URL_SCHEME_LOCAL, "local"},
|
|
{URL_SCHEME_JAVASCRIPT, "javascript"},
|
|
{URL_SCHEME_VBSCRIPT, "vbscript"},
|
|
{URL_SCHEME_ABOUT, "about"},
|
|
{URL_SCHEME_RES, "res"},
|
|
{0, 0}
|
|
};
|
|
|
|
/* Macro to get function pointer for a module*/
|
|
#define GET_FUNC(module, name, fail) \
|
|
if (!SHLWAPI_h##module) SHLWAPI_h##module = LoadLibraryA(#module ".dll"); \
|
|
if (!SHLWAPI_h##module) return fail; \
|
|
if (!pfnFunc) pfnFunc = (void*)GetProcAddress(SHLWAPI_h##module, name); \
|
|
if (!pfnFunc) return fail
|
|
|
|
/*
|
|
NOTES: Most functions exported by ordinal seem to be superflous.
|
|
The reason for these functions to be there is to provide a wraper
|
|
for unicode functions to provide these functions on systems without
|
|
unicode functions eg. win95/win98. Since we have such functions we just
|
|
call these. If running Wine with native DLL's, some late bound calls may
|
|
fail. However, its better to implement the functions in the forward DLL
|
|
and recommend the builtin rather than reimplementing the calls here!
|
|
*/
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.1]
|
|
*
|
|
* Identifies the Internet "scheme" in the passed string. ASCII based.
|
|
* Also determines start and length of item after the ':'
|
|
*/
|
|
DWORD WINAPI SHLWAPI_1 (LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
|
|
{
|
|
DWORD cnt;
|
|
const SHL_2_inet_scheme *inet_pro;
|
|
|
|
if (y->size != 0x18) return E_INVALIDARG;
|
|
/* FIXME: leading white space generates error of 0x80041001 which
|
|
* is undefined
|
|
*/
|
|
if (*x <= ' ') return 0x80041001;
|
|
cnt = 0;
|
|
y->sizep1 = 0;
|
|
y->ap1 = x;
|
|
while (*x) {
|
|
if (*x == ':') {
|
|
y->sizep1 = cnt;
|
|
cnt = -1;
|
|
y->ap2 = x+1;
|
|
break;
|
|
}
|
|
x++;
|
|
cnt++;
|
|
}
|
|
|
|
/* check for no scheme in string start */
|
|
/* (apparently schemes *must* be larger than a single character) */
|
|
if ((*x == '\0') || (y->sizep1 <= 1)) {
|
|
y->ap1 = 0;
|
|
return 0x80041001;
|
|
}
|
|
|
|
/* found scheme, set length of remainder */
|
|
y->sizep2 = lstrlenA(y->ap2);
|
|
|
|
/* see if known scheme and return indicator number */
|
|
y->fcncde = URL_SCHEME_UNKNOWN;
|
|
inet_pro = shlwapi_schemes;
|
|
while (inet_pro->scheme_name) {
|
|
if (!strncasecmp(inet_pro->scheme_name, y->ap1,
|
|
min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
|
|
y->fcncde = inet_pro->scheme_number;
|
|
break;
|
|
}
|
|
inet_pro++;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.2]
|
|
*
|
|
* Identifies the Internet "scheme" in the passed string. UNICODE based.
|
|
* Also determines start and length of item after the ':'
|
|
*/
|
|
DWORD WINAPI SHLWAPI_2 (LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
|
|
{
|
|
DWORD cnt;
|
|
const SHL_2_inet_scheme *inet_pro;
|
|
LPSTR cmpstr;
|
|
INT len;
|
|
|
|
if (y->size != 0x18) return E_INVALIDARG;
|
|
/* FIXME: leading white space generates error of 0x80041001 which
|
|
* is undefined
|
|
*/
|
|
if (*x <= L' ') return 0x80041001;
|
|
cnt = 0;
|
|
y->sizep1 = 0;
|
|
y->ap1 = x;
|
|
while (*x) {
|
|
if (*x == L':') {
|
|
y->sizep1 = cnt;
|
|
cnt = -1;
|
|
y->ap2 = x+1;
|
|
break;
|
|
}
|
|
x++;
|
|
cnt++;
|
|
}
|
|
|
|
/* check for no scheme in string start */
|
|
/* (apparently schemes *must* be larger than a single character) */
|
|
if ((*x == L'\0') || (y->sizep1 <= 1)) {
|
|
y->ap1 = 0;
|
|
return 0x80041001;
|
|
}
|
|
|
|
/* found scheme, set length of remainder */
|
|
y->sizep2 = lstrlenW(y->ap2);
|
|
|
|
/* see if known scheme and return indicator number */
|
|
len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
|
|
cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len+1);
|
|
WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len+1, 0, 0);
|
|
y->fcncde = URL_SCHEME_UNKNOWN;
|
|
inet_pro = shlwapi_schemes;
|
|
while (inet_pro->scheme_name) {
|
|
if (!strncasecmp(inet_pro->scheme_name, cmpstr,
|
|
min(len, lstrlenA(inet_pro->scheme_name)))) {
|
|
y->fcncde = inet_pro->scheme_number;
|
|
break;
|
|
}
|
|
inet_pro++;
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, cmpstr);
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHLWAPI_DupSharedHandle
|
|
*
|
|
* Internal implemetation of SHLWAPI_11.
|
|
*/
|
|
static
|
|
HSHARED WINAPI SHLWAPI_DupSharedHandle(HSHARED hShared, DWORD dwDstProcId,
|
|
DWORD dwSrcProcId, DWORD dwAccess,
|
|
DWORD dwOptions)
|
|
{
|
|
HANDLE hDst, hSrc;
|
|
DWORD dwMyProcId = GetCurrentProcessId();
|
|
HSHARED hRet = (HSHARED)NULL;
|
|
|
|
TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", (PVOID)hShared, dwDstProcId, dwSrcProcId,
|
|
dwAccess, dwOptions);
|
|
|
|
/* Get dest process handle */
|
|
if (dwDstProcId == dwMyProcId)
|
|
hDst = GetCurrentProcess();
|
|
else
|
|
hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
|
|
|
|
if (hDst)
|
|
{
|
|
/* Get src process handle */
|
|
if (dwSrcProcId == dwMyProcId)
|
|
hSrc = GetCurrentProcess();
|
|
else
|
|
hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
|
|
|
|
if (hSrc)
|
|
{
|
|
/* Make handle available to dest process */
|
|
if (!DuplicateHandle(hDst, (HANDLE)hShared, hSrc, &hRet,
|
|
dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
|
|
hRet = (HSHARED)NULL;
|
|
|
|
if (dwSrcProcId != dwMyProcId)
|
|
CloseHandle(hSrc);
|
|
}
|
|
|
|
if (dwDstProcId != dwMyProcId)
|
|
CloseHandle(hDst);
|
|
}
|
|
|
|
TRACE("Returning handle %p\n", (PVOID)hRet);
|
|
return hRet;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.7]
|
|
*
|
|
* Create a block of sharable memory and initialise it with data.
|
|
*
|
|
* PARAMS
|
|
* dwProcId [I] ID of process owning data
|
|
* lpvData [I] Pointer to data to write
|
|
* dwSize [I] Size of data
|
|
*
|
|
* RETURNS
|
|
* Success: A shared memory handle
|
|
* Failure: NULL
|
|
*
|
|
* NOTES
|
|
* Ordinals 7-11 provide a set of calls to create shared memory between a
|
|
* group of processes. The shared memory is treated opaquely in that its size
|
|
* is not exposed to clients who map it. This is accomplished by storing
|
|
* the size of the map as the first DWORD of mapped data, and then offsetting
|
|
* the view pointer returned by this size.
|
|
*
|
|
* SHLWAPI_7/SHLWAPI_10 - Create/Destroy the shared memory handle
|
|
* SHLWAPI_8/SHLWAPI_9 - Get/Release a pointer to the shared data
|
|
* SHLWAPI_11 - Helper function; Duplicate cross-process handles
|
|
*/
|
|
HSHARED WINAPI SHLWAPI_7 (DWORD dwProcId, DWORD dwSize, LPCVOID lpvData)
|
|
{
|
|
HANDLE hMap;
|
|
LPVOID pMapped;
|
|
HSHARED hRet = (HSHARED)NULL;
|
|
|
|
TRACE("(%ld,%p,%ld)\n", dwProcId, lpvData, dwSize);
|
|
|
|
/* Create file mapping of the correct length */
|
|
hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
|
|
dwSize + sizeof(dwSize), NULL);
|
|
if (!hMap)
|
|
return hRet;
|
|
|
|
/* Get a view in our process address space */
|
|
pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
|
|
|
if (pMapped)
|
|
{
|
|
/* Write size of data, followed by the data, to the view */
|
|
*((DWORD*)pMapped) = dwSize;
|
|
if (dwSize)
|
|
memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
|
|
|
|
/* Release view. All further views mapped will be opaque */
|
|
UnmapViewOfFile(pMapped);
|
|
hRet = SHLWAPI_DupSharedHandle((HSHARED)hMap, dwProcId,
|
|
GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
|
|
DUPLICATE_SAME_ACCESS);
|
|
}
|
|
|
|
CloseHandle(hMap);
|
|
return hRet;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.8]
|
|
*
|
|
* Get a pointer to a block of shared memory from a shared memory handle.
|
|
*
|
|
* PARAMS
|
|
* hShared [I] Shared memory handle
|
|
* dwProcId [I] ID of process owning hShared
|
|
*
|
|
* RETURNS
|
|
* Success: A pointer to the shared memory
|
|
* Failure: NULL
|
|
*
|
|
* NOTES
|
|
* See SHLWAPI_7.
|
|
*/
|
|
PVOID WINAPI SHLWAPI_8 (HSHARED hShared, DWORD dwProcId)
|
|
{
|
|
HSHARED hDup;
|
|
LPVOID pMapped;
|
|
|
|
TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
|
|
|
|
/* Get handle to shared memory for current process */
|
|
hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
|
|
FILE_MAP_ALL_ACCESS, 0);
|
|
/* Get View */
|
|
pMapped = MapViewOfFile((HANDLE)hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
|
CloseHandle(hDup);
|
|
|
|
if (pMapped)
|
|
return (char *) pMapped + sizeof(DWORD); /* Hide size */
|
|
return NULL;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.9]
|
|
*
|
|
* Release a pointer to a block of shared memory.
|
|
*
|
|
* PARAMS
|
|
* lpView [I] Shared memory pointer
|
|
*
|
|
* RETURNS
|
|
* Success: TRUE
|
|
* Failure: FALSE
|
|
*
|
|
* NOTES
|
|
* See SHLWAPI_7.
|
|
*/
|
|
BOOL WINAPI SHLWAPI_9 (LPVOID lpView)
|
|
{
|
|
TRACE("(%p)\n", lpView);
|
|
return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.10]
|
|
*
|
|
* Destroy a block of sharable memory.
|
|
*
|
|
* PARAMS
|
|
* hShared [I] Shared memory handle
|
|
* dwProcId [I] ID of process owning hShared
|
|
*
|
|
* RETURNS
|
|
* Success: TRUE
|
|
* Failure: FALSE
|
|
*
|
|
* NOTES
|
|
* See SHLWAPI_7.
|
|
*/
|
|
BOOL WINAPI SHLWAPI_10 (HSHARED hShared, DWORD dwProcId)
|
|
{
|
|
HSHARED hClose;
|
|
|
|
TRACE("(%p %ld)\n", (PVOID)hShared, dwProcId);
|
|
|
|
/* Get a copy of the handle for our process, closing the source handle */
|
|
hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
|
|
FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
|
|
/* Close local copy */
|
|
return CloseHandle((HANDLE)hClose);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.11]
|
|
*
|
|
* Copy a sharable memory handle from one process to another.
|
|
*
|
|
* PARAMS
|
|
* hShared [I] Shared memory handle to duplicate
|
|
* dwDstProcId [I] ID of the process wanting the duplicated handle
|
|
* dwSrcProcId [I] ID of the process owning hShared
|
|
* dwAccess [I] Desired DuplicateHandle access
|
|
* dwOptions [I] Desired DuplicateHandle options
|
|
*
|
|
* RETURNS
|
|
* Success: A handle suitable for use by the dwDstProcId process.
|
|
* Failure: A NULL handle.
|
|
*
|
|
* NOTES
|
|
* See SHLWAPI_7.
|
|
*/
|
|
HSHARED WINAPI SHLWAPI_11(HSHARED hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
|
|
DWORD dwAccess, DWORD dwOptions)
|
|
{
|
|
HSHARED hRet;
|
|
|
|
hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
|
|
dwAccess, dwOptions);
|
|
return hRet;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.13]
|
|
* (Used by IE4 during startup)
|
|
*/
|
|
HRESULT WINAPI SHLWAPI_13 (
|
|
LPVOID w,
|
|
LPVOID x)
|
|
{
|
|
FIXME("(%p %p)stub\n",w,x);
|
|
return 1;
|
|
#if 0
|
|
/* pseudo code extracted from relay trace */
|
|
RegOpenKeyA(HKLM, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Aceepted Documents", &newkey);
|
|
ret = 0;
|
|
i = 0;
|
|
size = 0;
|
|
while(!ret) {
|
|
ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, 0, 0);
|
|
size += ???;
|
|
i++;
|
|
}
|
|
b1 = LocalAlloc(0x40, size);
|
|
ret = 0;
|
|
i = 0;
|
|
while(!ret) {
|
|
ret = RegEnumValueA(newkey, i, a1, a2, 0, a3, a4, a5);
|
|
RegisterClipBoardFormatA(a4);
|
|
i++;
|
|
}
|
|
hwnd1 = GetModuleHandleA("URLMON.DLL");
|
|
proc = GetProcAddress(hwnd1, "CreateFormatEnumerator");
|
|
HeapAlloc(??, 0, 0x14);
|
|
HeapAlloc(??, 0, 0x50);
|
|
LocalAlloc(0x40, 0x78);
|
|
/* FIXME: bad string below */
|
|
lstrlenW(L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
|
|
StrCpyW(a6, L"{D0FCA420-D3F5-11CF-B211-00AA004AE837}");
|
|
|
|
GetTickCount();
|
|
IsBadReadPtr(c1 = 0x403fd210,4);
|
|
InterlockedIncrement(c1+4);
|
|
LocalFree(b1);
|
|
RegCloseKey(newkey);
|
|
IsBadReadPtr(c1 = 0x403fd210,4);
|
|
InterlockedIncrement(c1+4);
|
|
|
|
HeapAlloc(40350000,00000000,00000014) retval=403fd0a8;
|
|
HeapAlloc(40350000,00000000,00000050) retval=403feb44;
|
|
hwnd1 = GetModuleHandleA("URLMON.DLL");
|
|
proc = GetProcAddress(hwnd1, "RegisterFormatEnumerator");
|
|
/* 0x1a40c88c is in URLMON.DLL just before above proc
|
|
* content is L"_EnumFORMATETC_"
|
|
* label is d1
|
|
*/
|
|
IsBadReadPtr(d1 = 0x1a40c88c,00000002);
|
|
lstrlenW(d1);
|
|
lstrlenW(d1);
|
|
HeapAlloc(40350000,00000000,0000001e) retval=403fed44;
|
|
IsBadReadPtr(d2 = 0x403fd0a8,00000004);
|
|
InterlockedIncrement(d2+4);
|
|
IsBadReadPtr(d2 = 0x403fd0a8,00000004);
|
|
InterlockedDecrement(d2+4);
|
|
IsBadReadPtr(c1,00000004);
|
|
InterlockedDecrement(c1+4);
|
|
IsBadReadPtr(c1,00000004);
|
|
InterlockedDecrement(c1+4);
|
|
|
|
#endif
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.14]
|
|
*
|
|
* Function:
|
|
* Retrieves IE "AcceptLanguage" value from registry. ASCII mode.
|
|
*
|
|
*/
|
|
HRESULT WINAPI SHLWAPI_14 (
|
|
LPSTR langbuf,
|
|
LPDWORD buflen)
|
|
{
|
|
CHAR *mystr;
|
|
DWORD mystrlen, mytype;
|
|
HKEY mykey;
|
|
LCID mylcid;
|
|
|
|
mystrlen = (*buflen > 6) ? *buflen : 6;
|
|
mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY, mystrlen);
|
|
RegOpenKeyA(HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Internet Explorer\\International",
|
|
&mykey);
|
|
if (RegQueryValueExA(mykey, "AcceptLanguage",
|
|
0, &mytype, mystr, &mystrlen)) {
|
|
/* Did not find value */
|
|
mylcid = GetUserDefaultLCID();
|
|
/* somehow the mylcid translates into "en-us"
|
|
* this is similar to "LOCALE_SABBREVLANGNAME"
|
|
* which could be gotten via GetLocaleInfo.
|
|
* The only problem is LOCALE_SABBREVLANGUAGE" is
|
|
* a 3 char string (first 2 are country code and third is
|
|
* letter for "sublanguage", which does not come close to
|
|
* "en-us"
|
|
*/
|
|
lstrcpyA(mystr, "en-us");
|
|
mystrlen = lstrlenA(mystr);
|
|
}
|
|
else {
|
|
/* handle returned string */
|
|
FIXME("missing code\n");
|
|
}
|
|
if (mystrlen > *buflen)
|
|
lstrcpynA(langbuf, mystr, *buflen);
|
|
else {
|
|
lstrcpyA(langbuf, mystr);
|
|
*buflen = lstrlenA(langbuf);
|
|
}
|
|
RegCloseKey(mykey);
|
|
HeapFree(GetProcessHeap(), 0, mystr);
|
|
TRACE("language is %s\n", debugstr_a(langbuf));
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.15]
|
|
*
|
|
* Function:
|
|
* Retrieves IE "AcceptLanguage" value from registry. UNICODE mode.
|
|
*
|
|
*/
|
|
HRESULT WINAPI SHLWAPI_15 (
|
|
LPWSTR langbuf,
|
|
LPDWORD buflen)
|
|
{
|
|
CHAR *mystr;
|
|
DWORD mystrlen, mytype;
|
|
HKEY mykey;
|
|
LCID mylcid;
|
|
|
|
mystrlen = (*buflen > 6) ? *buflen : 6;
|
|
mystr = (CHAR*)HeapAlloc(GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY, mystrlen);
|
|
RegOpenKeyA(HKEY_CURRENT_USER,
|
|
"Software\\Microsoft\\Internet Explorer\\International",
|
|
&mykey);
|
|
if (RegQueryValueExA(mykey, "AcceptLanguage",
|
|
0, &mytype, mystr, &mystrlen)) {
|
|
/* Did not find value */
|
|
mylcid = GetUserDefaultLCID();
|
|
/* somehow the mylcid translates into "en-us"
|
|
* this is similar to "LOCALE_SABBREVLANGNAME"
|
|
* which could be gotten via GetLocaleInfo.
|
|
* The only problem is LOCALE_SABBREVLANGUAGE" is
|
|
* a 3 char string (first 2 are country code and third is
|
|
* letter for "sublanguage", which does not come close to
|
|
* "en-us"
|
|
*/
|
|
lstrcpyA(mystr, "en-us");
|
|
mystrlen = lstrlenA(mystr);
|
|
}
|
|
else {
|
|
/* handle returned string */
|
|
FIXME("missing code\n");
|
|
}
|
|
RegCloseKey(mykey);
|
|
*buflen = MultiByteToWideChar(0, 0, mystr, -1, langbuf, (*buflen)-1);
|
|
HeapFree(GetProcessHeap(), 0, mystr);
|
|
TRACE("language is %s\n", debugstr_w(langbuf));
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.16]
|
|
*/
|
|
HRESULT WINAPI SHLWAPI_16 (
|
|
LPVOID w,
|
|
LPVOID x,
|
|
LPVOID y,
|
|
LPWSTR z)
|
|
{
|
|
FIXME("(%p %p %p %p)stub\n",w,x,y,z);
|
|
return 0xabba1252;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.18]
|
|
*
|
|
* w is pointer to address of callback routine
|
|
* x is pointer to LPVOID to receive address of locally allocated
|
|
* space size 0x14
|
|
* return is 0 (unless out of memory???)
|
|
*
|
|
* related to _19, _21 and _22 below
|
|
* only seen invoked by SHDOCVW
|
|
*/
|
|
LONG WINAPI SHLWAPI_18 (
|
|
LPVOID *w,
|
|
LPVOID x)
|
|
{
|
|
FIXME("(%p %p)stub\n",w,x);
|
|
*((LPDWORD)x) = 0;
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.19]
|
|
*
|
|
* w is address of allocated memory from _21
|
|
* return is 0 (unless out of memory???)
|
|
*
|
|
* related to _18, _21 and _22 below
|
|
* only seen invoked by SHDOCVW
|
|
*/
|
|
LONG WINAPI SHLWAPI_19 (
|
|
LPVOID w)
|
|
{
|
|
FIXME("(%p) stub\n",w);
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.21]
|
|
*
|
|
* w points to space allocated via .18 above
|
|
* LocalSize is done on it (retrieves 18)
|
|
* LocalReAlloc is done on it to size 8 with LMEM_MOVEABLE & LMEM_ZEROINIT
|
|
* x values seen 0xa0000005
|
|
* returns 1
|
|
*
|
|
* relates to _18, _19 and _22 above and below
|
|
* only seen invoked by SHDOCVW
|
|
*/
|
|
LONG WINAPI SHLWAPI_21 (
|
|
LPVOID w,
|
|
DWORD x)
|
|
{
|
|
FIXME("(%p %lx)stub\n",w,x);
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.22]
|
|
*
|
|
* return is 'w' value seen in x is 0xa0000005
|
|
*
|
|
* relates to _18, _19 and _21 above
|
|
* only seen invoked by SHDOCVW
|
|
*/
|
|
LPVOID WINAPI SHLWAPI_22 (
|
|
LPVOID w,
|
|
DWORD x)
|
|
{
|
|
FIXME("(%p %lx)stub\n",w,x);
|
|
return w;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.23]
|
|
*
|
|
* NOTES
|
|
* converts a guid to a string
|
|
* returns strlen(str)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_23 (
|
|
REFGUID guid, /* [in] clsid */
|
|
LPSTR str, /* [out] buffer */
|
|
INT cmax) /* [in] size of buffer */
|
|
{
|
|
char xguid[40];
|
|
|
|
sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
|
guid->Data1, guid->Data2, guid->Data3,
|
|
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
|
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
|
|
TRACE("(%s %p 0x%08x)stub\n", xguid, str, cmax);
|
|
if (strlen(xguid)>=cmax) return 0;
|
|
strcpy(str,xguid);
|
|
return strlen(xguid) + 1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.24]
|
|
*
|
|
* NOTES
|
|
* converts a guid to a string
|
|
* returns strlen(str)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_24 (
|
|
REFGUID guid, /* [in] clsid */
|
|
LPWSTR str, /* [out] buffer */
|
|
INT cmax) /* [in] size of buffer */
|
|
{
|
|
char xguid[40];
|
|
|
|
sprintf( xguid, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
|
guid->Data1, guid->Data2, guid->Data3,
|
|
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
|
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
|
|
return MultiByteToWideChar( CP_ACP, 0, xguid, -1, str, cmax );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.25]
|
|
*
|
|
* Seems to be iswalpha
|
|
*/
|
|
BOOL WINAPI SHLWAPI_25(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_ALPHA) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.26]
|
|
*
|
|
* Seems to be iswupper
|
|
*/
|
|
BOOL WINAPI SHLWAPI_26(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_UPPER) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.27]
|
|
*
|
|
* Seems to be iswlower
|
|
*/
|
|
BOOL WINAPI SHLWAPI_27(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_LOWER) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.28]
|
|
*
|
|
* Seems to be iswalnum
|
|
*/
|
|
BOOL WINAPI SHLWAPI_28(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.29]
|
|
*
|
|
* Seems to be iswspace
|
|
*/
|
|
BOOL WINAPI SHLWAPI_29(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_SPACE) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.30]
|
|
*
|
|
* Seems to be iswblank
|
|
*/
|
|
BOOL WINAPI SHLWAPI_30(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_BLANK) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.31]
|
|
*
|
|
* Seems to be iswpunct
|
|
*/
|
|
BOOL WINAPI SHLWAPI_31(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_PUNCT) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.32]
|
|
*
|
|
* Seems to be iswcntrl
|
|
*/
|
|
BOOL WINAPI SHLWAPI_32(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_CNTRL) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.33]
|
|
*
|
|
* Seems to be iswdigit
|
|
*/
|
|
BOOL WINAPI SHLWAPI_33(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_DIGIT) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.34]
|
|
*
|
|
* Seems to be iswxdigit
|
|
*/
|
|
BOOL WINAPI SHLWAPI_34(WCHAR wc)
|
|
{
|
|
return (get_char_typeW(wc) & C1_XDIGIT) != 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.35]
|
|
*
|
|
*/
|
|
BOOL WINAPI SHLWAPI_35(LPVOID p1, DWORD dw2, LPVOID p3)
|
|
{
|
|
FIXME("(%p, 0x%08lx, %p): stub\n", p1, dw2, p3);
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.36]
|
|
*
|
|
*/
|
|
BOOL WINAPI SHLWAPI_36(HMENU h1, UINT ui2, UINT h3, LPCWSTR p4)
|
|
{
|
|
TRACE("(0x%08x, 0x%08x, 0x%08x, %s): stub\n",
|
|
h1, ui2, h3, debugstr_w(p4));
|
|
return AppendMenuW(h1, ui2, h3, p4);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.74]
|
|
*
|
|
* Get the text from a given dialog item.
|
|
*/
|
|
INT WINAPI SHLWAPI_74(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
|
|
{
|
|
HWND hItem = GetDlgItem(hWnd, nItem);
|
|
|
|
if (hItem)
|
|
return GetWindowTextW(hItem, lpsDest, nDestLen);
|
|
if (nDestLen)
|
|
*lpsDest = (WCHAR)'\0';
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.151]
|
|
* Function: Compare two ASCII strings for "len" bytes.
|
|
* Returns: *str1-*str2 (case sensitive)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_151(LPSTR str1, LPSTR str2, INT len)
|
|
{
|
|
return strncmp( str1, str2, len );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.152]
|
|
*
|
|
* Function: Compare two WIDE strings for "len" bytes.
|
|
* Returns: *str1-*str2 (case sensitive)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_152(LPWSTR str1, LPWSTR str2, INT len)
|
|
{
|
|
return strncmpW( str1, str2, len );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.153]
|
|
* Function: Compare two ASCII strings for "len" bytes via caseless compare.
|
|
* Returns: *str1-*str2 (case insensitive)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_153(LPSTR str1, LPSTR str2, DWORD len)
|
|
{
|
|
return strncasecmp( str1, str2, len );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.154]
|
|
*
|
|
* Function: Compare two WIDE strings for "len" bytes via caseless compare.
|
|
* Returns: *str1-*str2 (case insensitive)
|
|
*/
|
|
DWORD WINAPI SHLWAPI_154(LPWSTR str1, LPWSTR str2, DWORD len)
|
|
{
|
|
return strncmpiW( str1, str2, len );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.155]
|
|
*
|
|
* Case sensitive string compare (ASCII). Does not SetLastError().
|
|
*/
|
|
DWORD WINAPI SHLWAPI_155 ( LPSTR str1, LPSTR str2)
|
|
{
|
|
return strcmp(str1, str2);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.156]
|
|
*
|
|
* Case sensitive string compare. Does not SetLastError().
|
|
*/
|
|
DWORD WINAPI SHLWAPI_156 ( LPWSTR str1, LPWSTR str2)
|
|
{
|
|
return strcmpW( str1, str2 );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.158]
|
|
*
|
|
* Case insensitive string compare. Does not SetLastError(). ??
|
|
*/
|
|
DWORD WINAPI SHLWAPI_158 ( LPWSTR str1, LPWSTR str2)
|
|
{
|
|
return strcmpiW( str1, str2 );
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.162]
|
|
*
|
|
* Ensure a multibyte character string doesn't end in a hanging lead byte.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_162(LPSTR lpStr, DWORD size)
|
|
{
|
|
if (lpStr && size)
|
|
{
|
|
LPSTR lastByte = lpStr + size - 1;
|
|
|
|
while(lpStr < lastByte)
|
|
lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1;
|
|
|
|
if(lpStr == lastByte && IsDBCSLeadByte(*lpStr))
|
|
{
|
|
*lpStr = '\0';
|
|
size--;
|
|
}
|
|
return size;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.164]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_164 (
|
|
LPVOID u,
|
|
LPVOID v,
|
|
LPVOID w,
|
|
LPVOID x,
|
|
LPVOID y,
|
|
LPVOID z)
|
|
{
|
|
TRACE("(%p %p %p %p %p %p) stub\n",u,v,w,x,y,z);
|
|
return 0x80004002; /* E_NOINTERFACE */
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.165]
|
|
*
|
|
* SetWindowLongA with mask.
|
|
*/
|
|
LONG WINAPI SHLWAPI_165(HWND hwnd, INT offset, UINT wFlags, UINT wMask)
|
|
{
|
|
LONG ret = GetWindowLongA(hwnd, offset);
|
|
UINT newFlags = (wFlags & wMask) | (ret & ~wFlags);
|
|
|
|
if (newFlags != ret)
|
|
ret = SetWindowLongA(hwnd, offset, newFlags);
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.169]
|
|
*
|
|
* Do IUnknown::Release on passed object.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_169 (IUnknown ** lpUnknown)
|
|
{
|
|
IUnknown *temp;
|
|
|
|
TRACE("(%p)\n",lpUnknown);
|
|
if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
|
|
temp = *lpUnknown;
|
|
*lpUnknown = NULL;
|
|
TRACE("doing Release\n");
|
|
return IUnknown_Release(temp);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.170]
|
|
*
|
|
* Skip URL '//' sequence.
|
|
*/
|
|
LPCSTR WINAPI SHLWAPI_170(LPCSTR lpszSrc)
|
|
{
|
|
if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
|
|
lpszSrc += 2;
|
|
return lpszSrc;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.172]
|
|
* Get window handle of OLE object
|
|
*/
|
|
DWORD WINAPI SHLWAPI_172 (
|
|
IUnknown *y, /* [in] OLE object interface */
|
|
LPHWND z) /* [out] location to put window handle */
|
|
{
|
|
DWORD ret;
|
|
IUnknown *pv;
|
|
|
|
TRACE("(%p %p)\n",y,z);
|
|
if (!y) return E_FAIL;
|
|
|
|
if ((ret = IUnknown_QueryInterface(y, &IID_IOleWindow,(LPVOID *)&pv)) < 0) {
|
|
/* error */
|
|
return ret;
|
|
}
|
|
ret = IOleWindow_GetWindow((IOleWindow *)pv, z);
|
|
IUnknown_Release(pv);
|
|
TRACE("result hwnd=%08x\n", *z);
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.174]
|
|
*
|
|
* Seems to do call either IObjectWithSite::SetSite or
|
|
* IPersistMoniker::GetClassID. But since we do not implement either
|
|
* of those classes in our headers, we will fake it out.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_174(
|
|
IUnknown *p1, /* [in] OLE object */
|
|
LPVOID *p2) /* [out] ptr to result of either GetClassID
|
|
or SetSite call. */
|
|
{
|
|
DWORD ret, aa;
|
|
|
|
if (!p1) return E_FAIL;
|
|
|
|
/* see if SetSite interface exists for IObjectWithSite object */
|
|
ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
|
|
TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
|
|
if (ret) {
|
|
|
|
/* see if GetClassId interface exists for IPersistMoniker object */
|
|
ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
|
|
TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
|
|
if (ret) return ret;
|
|
|
|
/* fake a GetClassId call */
|
|
ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
|
|
TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
|
|
*(LPDWORD)p2);
|
|
IUnknown_Release((IUnknown *)aa);
|
|
}
|
|
else {
|
|
/* fake a SetSite call */
|
|
ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
|
|
TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
|
|
*(LPDWORD)p2);
|
|
IUnknown_Release((IUnknown *)p1);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.176]
|
|
*
|
|
* Function appears to be interface to IServiceProvider::QueryService
|
|
*
|
|
* NOTE:
|
|
* returns E_NOINTERFACE
|
|
* E_FAIL if w == 0
|
|
* S_OK if _219 called successfully
|
|
*/
|
|
DWORD WINAPI SHLWAPI_176 (
|
|
IUnknown* unk, /* [in] object to give Service Provider */
|
|
REFGUID sid, /* [in] Service ID */
|
|
REFIID riid, /* [in] Function requested */
|
|
LPVOID *z) /* [out] place to save interface pointer */
|
|
{
|
|
DWORD ret;
|
|
LPVOID aa;
|
|
*z = 0;
|
|
if (!unk) return E_FAIL;
|
|
ret = IUnknown_QueryInterface(unk, &IID_IServiceProvider, &aa);
|
|
TRACE("did IU_QI retval=%08lx, aa=%p\n", ret, aa);
|
|
if (ret) return ret;
|
|
ret = IServiceProvider_QueryService((IServiceProvider *)aa, sid, riid,
|
|
(void **)z);
|
|
TRACE("did ISP_QS retval=%08lx, *z=%p\n", ret, (LPVOID)*z);
|
|
IUnknown_Release((IUnknown*)aa);
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.181]
|
|
*
|
|
* Enable or disable a menu item.
|
|
*/
|
|
UINT WINAPI SHLWAPI_181(HMENU hMenu, UINT wItemID, BOOL bEnable)
|
|
{
|
|
return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.183]
|
|
*
|
|
* Register a window class if it isn't already.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_183(WNDCLASSA *wndclass)
|
|
{
|
|
WNDCLASSA wca;
|
|
if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
|
|
return TRUE;
|
|
return (DWORD)RegisterClassA(wndclass);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.193]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_193 ()
|
|
{
|
|
HDC hdc;
|
|
DWORD ret;
|
|
|
|
TRACE("()\n");
|
|
|
|
hdc = GetDC(0);
|
|
ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
|
|
ReleaseDC(0, hdc);
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.199]
|
|
*
|
|
* Copy interface pointer
|
|
*/
|
|
DWORD WINAPI SHLWAPI_199 (
|
|
IUnknown **dest, /* [out] pointer to copy of interface ptr */
|
|
IUnknown *src) /* [in] interface pointer */
|
|
{
|
|
TRACE("(%p %p)\n",dest,src);
|
|
if (*dest != src) {
|
|
if (*dest)
|
|
IUnknown_Release(*dest);
|
|
if (src) {
|
|
IUnknown_AddRef(src);
|
|
*dest = src;
|
|
}
|
|
}
|
|
return 4;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.208]
|
|
*
|
|
* Some sort of memory management process - associated with _210
|
|
*/
|
|
DWORD WINAPI SHLWAPI_208 (
|
|
DWORD a,
|
|
DWORD b,
|
|
LPVOID c,
|
|
LPVOID d,
|
|
DWORD e)
|
|
{
|
|
FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
|
|
a, b, c, d, e);
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.209]
|
|
*
|
|
* Some sort of memory management process - associated with _208
|
|
*/
|
|
DWORD WINAPI SHLWAPI_209 (
|
|
LPVOID a)
|
|
{
|
|
FIXME("(%p) stub\n",
|
|
a);
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.210]
|
|
*
|
|
* Some sort of memory management process - associated with _208
|
|
*/
|
|
DWORD WINAPI SHLWAPI_210 (
|
|
LPVOID a,
|
|
DWORD b,
|
|
LPVOID c)
|
|
{
|
|
FIXME("(%p 0x%08lx %p) stub\n",
|
|
a, b, c);
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.211]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_211 (
|
|
LPVOID a,
|
|
DWORD b)
|
|
{
|
|
FIXME("(%p 0x%08lx) stub\n",
|
|
a, b);
|
|
return 1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.215]
|
|
*
|
|
* NOTES
|
|
* check me!
|
|
*/
|
|
DWORD WINAPI SHLWAPI_215 (
|
|
LPCSTR lpStrSrc,
|
|
LPWSTR lpwStrDest,
|
|
int len)
|
|
{
|
|
INT len_a, ret;
|
|
|
|
len_a = lstrlenA(lpStrSrc);
|
|
ret = MultiByteToWideChar(0, 0, lpStrSrc, len_a, lpwStrDest, len);
|
|
TRACE("%s %s %d, ret=%d\n",
|
|
debugstr_a(lpStrSrc), debugstr_w(lpwStrDest), len, ret);
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.218]
|
|
*
|
|
* WideCharToMultiByte with multi language support.
|
|
*/
|
|
INT WINAPI SHLWAPI_218(UINT CodePage, LPCWSTR lpSrcStr, LPSTR lpDstStr,
|
|
LPINT lpnMultiCharCount)
|
|
{
|
|
static HRESULT (WINAPI *pfnFunc)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
|
|
WCHAR emptyW[] = { '\0' };
|
|
int len , reqLen;
|
|
LPSTR mem;
|
|
|
|
if (!lpDstStr || !lpnMultiCharCount)
|
|
return 0;
|
|
|
|
if (!lpSrcStr)
|
|
lpSrcStr = emptyW;
|
|
|
|
*lpDstStr = '\0';
|
|
|
|
len = strlenW(lpSrcStr) + 1;
|
|
|
|
switch (CodePage)
|
|
{
|
|
case CP_WINUNICODE:
|
|
CodePage = CP_UTF8; /* Fall through... */
|
|
case 0x0000C350: /* FIXME: CP_ #define */
|
|
case CP_UTF7:
|
|
case CP_UTF8:
|
|
{
|
|
DWORD dwMode = 0;
|
|
INT nWideCharCount = len - 1;
|
|
|
|
GET_FUNC(mlang, "ConvertINetUnicodeToMultiByte", 0);
|
|
if (!pfnFunc(&dwMode, CodePage, lpSrcStr, &nWideCharCount, lpDstStr,
|
|
lpnMultiCharCount))
|
|
return 0;
|
|
|
|
if (nWideCharCount < len - 1)
|
|
{
|
|
mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, *lpnMultiCharCount);
|
|
if (!mem)
|
|
return 0;
|
|
|
|
*lpnMultiCharCount = 0;
|
|
|
|
if (pfnFunc(&dwMode, CodePage, lpSrcStr, &len, mem, lpnMultiCharCount))
|
|
{
|
|
SHLWAPI_162 (mem, *lpnMultiCharCount);
|
|
lstrcpynA(lpDstStr, mem, *lpnMultiCharCount + 1);
|
|
return *lpnMultiCharCount + 1;
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, mem);
|
|
return *lpnMultiCharCount;
|
|
}
|
|
lpDstStr[*lpnMultiCharCount] = '\0';
|
|
return *lpnMultiCharCount;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, lpDstStr,
|
|
*lpnMultiCharCount, NULL, NULL);
|
|
|
|
if (!reqLen && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, NULL, 0, NULL, NULL);
|
|
if (reqLen)
|
|
{
|
|
mem = (LPSTR)HeapAlloc(GetProcessHeap(), 0, reqLen);
|
|
if (mem)
|
|
{
|
|
reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
|
|
reqLen, NULL, NULL);
|
|
|
|
reqLen = SHLWAPI_162(mem, *lpnMultiCharCount);
|
|
reqLen++;
|
|
|
|
lstrcpynA(lpDstStr, mem, *lpnMultiCharCount);
|
|
|
|
HeapFree(GetProcessHeap(), 0, mem);
|
|
}
|
|
}
|
|
}
|
|
return reqLen;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.217]
|
|
*
|
|
* Hmm, some program used lpnMultiCharCount == 0x3 (and lpSrcStr was "C")
|
|
* --> Crash. Something wrong here.
|
|
*
|
|
* It seems from OE v5 that the third param is the count. (GA 11/2001)
|
|
*/
|
|
INT WINAPI SHLWAPI_217(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT MultiCharCount)
|
|
{
|
|
INT myint = MultiCharCount;
|
|
|
|
return SHLWAPI_218(CP_ACP, lpSrcStr, lpDstStr, &myint);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.219]
|
|
*
|
|
* Seems to be "super" QueryInterface. Supplied with at table of interfaces
|
|
* and an array of IIDs and offsets into the table.
|
|
*
|
|
* NOTES
|
|
* error codes: E_POINTER, E_NOINTERFACE
|
|
*/
|
|
typedef struct {
|
|
REFIID refid;
|
|
DWORD indx;
|
|
} IFACE_INDEX_TBL;
|
|
|
|
HRESULT WINAPI SHLWAPI_219 (
|
|
LPVOID w, /* [in] table of interfaces */
|
|
IFACE_INDEX_TBL *x, /* [in] array of REFIIDs and indexes to above */
|
|
REFIID riid, /* [in] REFIID to get interface for */
|
|
LPVOID *z) /* [out] location to get interface pointer */
|
|
{
|
|
HRESULT ret;
|
|
IUnknown *a_vtbl;
|
|
IFACE_INDEX_TBL *xmove;
|
|
|
|
TRACE("(%p %p %s %p)\n",
|
|
w,x,debugstr_guid(riid),z);
|
|
if (z) {
|
|
xmove = x;
|
|
while (xmove->refid) {
|
|
TRACE("trying (indx %ld) %s\n", xmove->indx,
|
|
debugstr_guid(xmove->refid));
|
|
if (IsEqualIID(riid, xmove->refid)) {
|
|
a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
|
|
TRACE("matched, returning (%p)\n", a_vtbl);
|
|
*z = (LPVOID)a_vtbl;
|
|
IUnknown_AddRef(a_vtbl);
|
|
return S_OK;
|
|
}
|
|
xmove++;
|
|
}
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown)) {
|
|
a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
|
|
TRACE("returning first for IUnknown (%p)\n", a_vtbl);
|
|
*z = (LPVOID)a_vtbl;
|
|
IUnknown_AddRef(a_vtbl);
|
|
return S_OK;
|
|
}
|
|
*z = 0;
|
|
ret = E_NOINTERFACE;
|
|
} else
|
|
ret = E_POINTER;
|
|
return ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.222]
|
|
*
|
|
* NOTES
|
|
* securityattributes missing
|
|
*/
|
|
HANDLE WINAPI SHLWAPI_222 (LPCLSID guid)
|
|
{
|
|
char lpstrName[80];
|
|
|
|
sprintf( lpstrName, "shell.{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
|
guid->Data1, guid->Data2, guid->Data3,
|
|
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
|
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
|
|
FIXME("(%s) stub\n", lpstrName);
|
|
return CreateSemaphoreA(NULL,0, 0x7fffffff, lpstrName);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.223]
|
|
*
|
|
* NOTES
|
|
* get the count of the semaphore
|
|
*/
|
|
DWORD WINAPI SHLWAPI_223 (HANDLE handle)
|
|
{
|
|
DWORD oldCount;
|
|
|
|
FIXME("(0x%08x) stub\n",handle);
|
|
|
|
ReleaseSemaphore( handle, 1, &oldCount); /* +1 */
|
|
WaitForSingleObject( handle, 0 ); /* -1 */
|
|
return oldCount;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.236]
|
|
*/
|
|
HMODULE WINAPI SHLWAPI_236 (REFIID lpUnknown)
|
|
{
|
|
HKEY newkey;
|
|
DWORD type, count;
|
|
CHAR value[MAX_PATH], string[MAX_PATH];
|
|
|
|
strcpy(string, "CLSID\\");
|
|
strcat(string, debugstr_guid(lpUnknown));
|
|
strcat(string, "\\InProcServer32");
|
|
|
|
count = MAX_PATH;
|
|
RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
|
|
RegQueryValueExA(newkey, 0, 0, &type, value, &count);
|
|
RegCloseKey(newkey);
|
|
return LoadLibraryExA(value, 0, 0);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.237]
|
|
*
|
|
* Unicode version of SHLWAPI_183.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_237 (WNDCLASSW * lpWndClass)
|
|
{
|
|
WNDCLASSW WndClass;
|
|
|
|
TRACE("(0x%08x %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
|
|
|
|
if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
|
|
return TRUE;
|
|
return RegisterClassW(lpWndClass);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.239]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_239(HINSTANCE hInstance, LPVOID p2, DWORD dw3)
|
|
{
|
|
FIXME("(0x%08x %p 0x%08lx) stub\n",
|
|
hInstance, p2, dw3);
|
|
return 0;
|
|
#if 0
|
|
/* pseudo code from relay trace */
|
|
WideCharToMultiByte(0, 0, L"Shell DocObject View", -1, &aa, 0x0207, 0, 0);
|
|
GetClassInfoA(70fe0000,405868ec "Shell DocObject View",40586b14);
|
|
/* above pair repeated for:
|
|
TridentThicketUrlDlClass
|
|
Shell Embedding
|
|
CIESplashScreen
|
|
Inet Notify_Hidden
|
|
OCHost
|
|
*/
|
|
#endif
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.240]
|
|
*
|
|
* Calls ASCII or Unicode WindowProc for the given window.
|
|
*/
|
|
LRESULT CALLBACK SHLWAPI_240(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (IsWindowUnicode(hWnd))
|
|
return DefWindowProcW(hWnd, uMessage, wParam, lParam);
|
|
return DefWindowProcA(hWnd, uMessage, wParam, lParam);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.241]
|
|
*
|
|
*/
|
|
DWORD WINAPI SHLWAPI_241 ()
|
|
{
|
|
FIXME("()stub\n");
|
|
return /* 0xabba1243 */ 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.266]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_266 (
|
|
LPVOID w,
|
|
LPVOID x,
|
|
LPVOID y,
|
|
LPVOID z)
|
|
{
|
|
FIXME("(%p %p %p %p)stub\n",w,x,y,z);
|
|
return 0xabba1248;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.267]
|
|
*/
|
|
HRESULT WINAPI SHLWAPI_267 (
|
|
LPVOID w, /* [???] NOTE: same as 1th parameter of SHLWAPI_219 */
|
|
LPVOID x, /* [???] NOTE: same as 2nd parameter of SHLWAPI_219 */
|
|
LPVOID y,
|
|
LPVOID z)
|
|
{
|
|
FIXME("(%p %p %p %p)stub\n",w,x,y,z);
|
|
*((LPDWORD)z) = 0xabba1200;
|
|
return 0xabba1254;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.268]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_268 (
|
|
LPVOID w,
|
|
LPVOID x)
|
|
{
|
|
FIXME("(%p %p)\n",w,x);
|
|
return 0xabba1251; /* 0 = failure */
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.276]
|
|
*
|
|
*/
|
|
DWORD WINAPI SHLWAPI_276 ()
|
|
{
|
|
FIXME("()stub\n");
|
|
return /* 0xabba1244 */ 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.278]
|
|
*
|
|
*/
|
|
HWND WINAPI SHLWAPI_278 (
|
|
LONG wndProc,
|
|
HWND hWndParent,
|
|
DWORD dwExStyle,
|
|
DWORD dwStyle,
|
|
HMENU hMenu,
|
|
LONG z)
|
|
{
|
|
WNDCLASSA wndclass;
|
|
HWND hwnd;
|
|
HCURSOR hCursor;
|
|
char * clsname = "WorkerA";
|
|
|
|
FIXME("(0x%08lx 0x%08x 0x%08lx 0x%08lx 0x%08x 0x%08lx) partial stub\n",
|
|
wndProc,hWndParent,dwExStyle,dwStyle,hMenu,z);
|
|
|
|
hCursor = LoadCursorA(0x00000000,IDC_ARROWA);
|
|
|
|
if(!GetClassInfoA(shlwapi_hInstance, clsname, &wndclass))
|
|
{
|
|
RtlZeroMemory(&wndclass, sizeof(WNDCLASSA));
|
|
wndclass.lpfnWndProc = DefWindowProcW;
|
|
wndclass.cbWndExtra = 4;
|
|
wndclass.hInstance = shlwapi_hInstance;
|
|
wndclass.hCursor = hCursor;
|
|
wndclass.hbrBackground = COLOR_BTNSHADOW;
|
|
wndclass.lpszMenuName = NULL;
|
|
wndclass.lpszClassName = clsname;
|
|
RegisterClassA (&wndclass);
|
|
}
|
|
hwnd = CreateWindowExA(dwExStyle, clsname, 0,dwStyle,0,0,0,0,hWndParent,
|
|
hMenu,shlwapi_hInstance,0);
|
|
SetWindowLongA(hwnd, 0, z);
|
|
SetWindowLongA(hwnd, GWL_WNDPROC, wndProc);
|
|
return hwnd;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.289]
|
|
*
|
|
* Late bound call to winmm.PlaySoundW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_289(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPCWSTR, HMODULE, DWORD) = NULL;
|
|
|
|
GET_FUNC(winmm, "PlaySoundW", FALSE);
|
|
return pfnFunc(pszSound, hmod, fdwSound);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.294]
|
|
*/
|
|
BOOL WINAPI SHLWAPI_294(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
|
|
{
|
|
/*
|
|
* str1: "I" "I" pushl esp+0x20
|
|
* str2: "U" "I" pushl 0x77c93810
|
|
* (is "I" and "U" "integer" and "unsigned" ??)
|
|
*
|
|
* pStr: "" "" pushl eax
|
|
* some_len: 0x824 0x104 pushl 0x824
|
|
* lpStr2: "%l" "%l" pushl esp+0xc
|
|
*
|
|
* shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
|
|
* LocalAlloc(0x00, some_len) -> irrelevant_var
|
|
* LocalAlloc(0x40, irrelevant_len) -> pStr
|
|
* shlwapi.294(str1, str2, pStr, some_len, lpStr2);
|
|
* shlwapi.PathRemoveBlanksW(pStr);
|
|
*/
|
|
ERR("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.313]
|
|
*
|
|
* Late bound call to shell32.SHGetFileInfoW
|
|
*/
|
|
DWORD WINAPI SHLWAPI_313(LPCWSTR path, DWORD dwFileAttributes,
|
|
SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
|
|
{
|
|
static DWORD (WINAPI *pfnFunc)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHGetFileInfoW", 0);
|
|
return pfnFunc(path, dwFileAttributes, psfi, sizeofpsfi, flags);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.318]
|
|
*
|
|
* Late bound call to shell32.DragQueryFileW
|
|
*/
|
|
UINT WINAPI SHLWAPI_318(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
|
|
{
|
|
static UINT (WINAPI *pfnFunc)(HDROP, UINT, LPWSTR, UINT) = NULL;
|
|
|
|
GET_FUNC(shell32, "DragQueryFileW", 0);
|
|
return pfnFunc(hDrop, lFile, lpszFile, lLength);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.333]
|
|
*
|
|
* Late bound call to shell32.SHBrowseForFolderW
|
|
*/
|
|
LPITEMIDLIST WINAPI SHLWAPI_333(LPBROWSEINFOW lpBi)
|
|
{
|
|
static LPITEMIDLIST (WINAPI *pfnFunc)(LPBROWSEINFOW) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHBrowseForFolderW", NULL);
|
|
return pfnFunc(lpBi);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.334]
|
|
*
|
|
* Late bound call to shell32.SHGetPathFromIDListW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_334(LPCITEMIDLIST pidl,LPWSTR pszPath)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPCITEMIDLIST, LPWSTR) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHGetPathFromIDListW", 0);
|
|
return pfnFunc(pidl, pszPath);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.335]
|
|
*
|
|
* Late bound call to shell32.ShellExecuteExW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_335(LPSHELLEXECUTEINFOW lpExecInfo)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPSHELLEXECUTEINFOW) = NULL;
|
|
|
|
GET_FUNC(shell32, "ShellExecuteExW", FALSE);
|
|
return pfnFunc(lpExecInfo);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.336]
|
|
*
|
|
* Late bound call to shell32.SHFileOperationW.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_336(LPSHFILEOPSTRUCTW lpFileOp)
|
|
{
|
|
static HICON (WINAPI *pfnFunc)(LPSHFILEOPSTRUCTW) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHFileOperationW", 0);
|
|
return pfnFunc(lpFileOp);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.337]
|
|
*
|
|
* Late bound call to shell32.ExtractIconExW.
|
|
*/
|
|
HICON WINAPI SHLWAPI_337(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
|
|
HICON *phiconSmall, UINT nIcons)
|
|
{
|
|
static HICON (WINAPI *pfnFunc)(LPCWSTR, INT,HICON *,HICON *, UINT) = NULL;
|
|
|
|
GET_FUNC(shell32, "ExtractIconExW", (HICON)0);
|
|
return pfnFunc(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.342]
|
|
*
|
|
*/
|
|
DWORD WINAPI SHLWAPI_342 (
|
|
LPDWORD w, /* [out] location to put HKEY value??? */
|
|
HKEY x, /* [in] appears to be HKEY_CURRENT_USER */
|
|
LPVOID y)
|
|
{
|
|
FIXME("(%p 0x%08x %p)stub\n", w,x,y);
|
|
*w = (DWORD)x;
|
|
return /* 0xabba1249 */ 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.346]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_346 (
|
|
LPCWSTR src,
|
|
LPWSTR dest,
|
|
int len)
|
|
{
|
|
FIXME("(%s %p 0x%08x)stub\n",debugstr_w(src),dest,len);
|
|
lstrcpynW(dest, src, len);
|
|
return lstrlenW(dest)+1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.350]
|
|
*
|
|
* seems to be W interface to GetFileVersionInfoSizeA
|
|
*/
|
|
DWORD WINAPI SHLWAPI_350 (
|
|
LPWSTR x,
|
|
LPVOID y)
|
|
{
|
|
static DWORD WINAPI (*pfnFunc)(LPCSTR,LPDWORD) = NULL;
|
|
CHAR mbpath[MAX_PATH];
|
|
DWORD ret;
|
|
|
|
GET_FUNC(version, "GetFileVersionInfoSizeA", 0);
|
|
WideCharToMultiByte(0, 0, x, -1, mbpath, MAX_PATH, 0, 0);
|
|
ret = pfnFunc(mbpath, y);
|
|
return 0x208 + ret;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.351]
|
|
*
|
|
* seems to be W interface to GetFileVersionInfoA
|
|
*/
|
|
BOOL WINAPI SHLWAPI_351 (
|
|
LPWSTR w, /* [in] path to dll */
|
|
DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
|
|
DWORD y, /* [in] return value from .350 - assume length */
|
|
LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA) */
|
|
{
|
|
static BOOL WINAPI (*pfnFunc)(LPCSTR,DWORD,DWORD,LPVOID) = NULL;
|
|
CHAR mbpath[MAX_PATH];
|
|
|
|
GET_FUNC(version, "GetFileVersionInfoA", 0);
|
|
WideCharToMultiByte(0, 0, w, -1, mbpath, MAX_PATH, 0, 0);
|
|
return pfnFunc(mbpath , x, y-0x208, z+0x208);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.352]
|
|
*
|
|
* seems to be W interface to VerQueryValueA
|
|
*/
|
|
WORD WINAPI SHLWAPI_352 (
|
|
LPVOID w, /* [in] buffer from _351 */
|
|
LPWSTR x, /* [in] value to retrieve -
|
|
converted and passed to VerQueryValueA as #2 */
|
|
LPVOID y, /* [out] ver buffer - passed to VerQueryValueA as #3 */
|
|
UINT* z) /* [in] ver length - passed to VerQueryValueA as #4 */
|
|
{
|
|
static WORD WINAPI (*pfnFunc)(LPVOID,LPCSTR,LPVOID*,UINT*) = NULL;
|
|
CHAR buf1[MAX_PATH];
|
|
WORD ret;
|
|
|
|
GET_FUNC(version, "VerQueryValueA", 0);
|
|
WideCharToMultiByte(0, 0, x, lstrlenW(x)+1, buf1, MAX_PATH, 0, 0);
|
|
ret = pfnFunc(w+0x208, buf1, y, z);
|
|
if (CompareStringA(GetThreadLocale(), NORM_IGNORECASE, buf1, 1,
|
|
"\\StringFileInfo", 15) == 2 /* CSTR_EQUAL */) {
|
|
ERR("Need to translate back to wide - should fail now\n");
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/**************************************************************************
|
|
* @ [SHLWAPI.356]
|
|
*
|
|
* mbc - this function is undocumented, The parameters are correct and
|
|
* the calls to InitializeSecurityDescriptor and
|
|
* SetSecurityDescriptorDacl are correct, but apparently some
|
|
* apps call this function with all zero parameters.
|
|
*/
|
|
|
|
DWORD WINAPI SHLWAPI_356(PACL pDacl, PSECURITY_DESCRIPTOR pSD, LPCSTR *str)
|
|
{
|
|
if(str != 0){
|
|
*str = 0;
|
|
}
|
|
|
|
if(!pDacl){
|
|
return 0;
|
|
}
|
|
|
|
if (!InitializeSecurityDescriptor(pSD, 1)) return 0;
|
|
return SetSecurityDescriptorDacl(pSD, 1, pDacl, 0);
|
|
}
|
|
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.357]
|
|
*
|
|
* Late bound call to shell32.SHGetNewLinkInfoW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_357(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
|
|
BOOL *pfMustCopy, UINT uFlags)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHGetNewLinkInfoW", FALSE);
|
|
return pfnFunc(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.358]
|
|
*
|
|
* Late bound call to shell32.SHDefExtractIconW
|
|
*/
|
|
DWORD WINAPI SHLWAPI_358(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
|
|
LPVOID arg5, LPVOID arg6)
|
|
{
|
|
/* FIXME: Correct args */
|
|
static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHDefExtractIconW", 0);
|
|
return pfnFunc(arg1, arg2, arg3, arg4, arg5, arg6);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.364]
|
|
*
|
|
* Wrapper for lstrcpynA with src and dst swapped.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_364(LPCSTR src, LPSTR dst, INT n)
|
|
{
|
|
lstrcpynA(dst, src, n);
|
|
return TRUE;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.370]
|
|
*
|
|
* Late bound call to shell32.ExtractIconW
|
|
*/
|
|
HICON WINAPI SHLWAPI_370(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
|
|
UINT nIconIndex)
|
|
{
|
|
static HICON (WINAPI *pfnFunc)(HINSTANCE, LPCWSTR, UINT) = NULL;
|
|
|
|
GET_FUNC(shell32, "ExtractIconW", (HICON)0);
|
|
return pfnFunc(hInstance, lpszExeFileName, nIconIndex);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.376]
|
|
*/
|
|
LANGID WINAPI SHLWAPI_376 ()
|
|
{
|
|
FIXME("() stub\n");
|
|
/* FIXME: This should be a forward in the .spec file to the win2k function
|
|
* kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
|
|
*/
|
|
return GetUserDefaultLangID();
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.377]
|
|
*
|
|
* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
|
|
* each call here.
|
|
* FIXME: Native shows calls to:
|
|
* SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
|
|
* CheckVersion
|
|
* RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
|
|
* RegQueryValueExA for "LPKInstalled"
|
|
* RegCloseKey
|
|
* RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
|
|
* RegQueryValueExA for "ResourceLocale"
|
|
* RegCloseKey
|
|
* RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
|
|
* RegQueryValueExA for "Locale"
|
|
* RegCloseKey
|
|
* and then tests the Locale ("en" for me).
|
|
* code below
|
|
* after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_377 (LPCSTR new_mod, HMODULE inst_hwnd, LPVOID z)
|
|
{
|
|
CHAR mod_path[2*MAX_PATH];
|
|
LPSTR ptr;
|
|
|
|
GetModuleFileNameA(inst_hwnd, mod_path, 2*MAX_PATH);
|
|
ptr = strrchr(mod_path, '\\');
|
|
if (ptr) {
|
|
strcpy(ptr+1, new_mod);
|
|
TRACE("loading %s\n", debugstr_a(mod_path));
|
|
return (DWORD)LoadLibraryA(mod_path);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.378]
|
|
*
|
|
* This is Unicode version of .377
|
|
*/
|
|
DWORD WINAPI SHLWAPI_378 (
|
|
LPCWSTR new_mod, /* [in] new module name */
|
|
HMODULE inst_hwnd, /* [in] calling module handle */
|
|
LPVOID z) /* [???] 4 */
|
|
{
|
|
WCHAR mod_path[2*MAX_PATH];
|
|
LPWSTR ptr;
|
|
|
|
GetModuleFileNameW(inst_hwnd, mod_path, 2*MAX_PATH);
|
|
ptr = strrchrW(mod_path, '\\');
|
|
if (ptr) {
|
|
strcpyW(ptr+1, new_mod);
|
|
TRACE("loading %s\n", debugstr_w(mod_path));
|
|
return (DWORD)LoadLibraryW(mod_path);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.389]
|
|
*
|
|
* Late bound call to comdlg32.GetSaveFileNameW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_389(LPOPENFILENAMEW ofn)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
|
|
|
|
GET_FUNC(comdlg32, "GetSaveFileNameW", FALSE);
|
|
return pfnFunc(ofn);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.390]
|
|
*
|
|
* Late bound call to mpr.WNetRestoreConnectionW
|
|
*/
|
|
DWORD WINAPI SHLWAPI_390(LPVOID arg1, LPVOID arg2)
|
|
{
|
|
/* FIXME: Correct args */
|
|
static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID) = NULL;
|
|
|
|
GET_FUNC(mpr, "WNetRestoreConnectionW", 0);
|
|
return pfnFunc(arg1, arg2);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.391]
|
|
*
|
|
* Late bound call to mpr.WNetGetLastErrorW
|
|
*/
|
|
DWORD WINAPI SHLWAPI_391(LPVOID arg1, LPVOID arg2, LPVOID arg3, LPVOID arg4,
|
|
LPVOID arg5)
|
|
{
|
|
/* FIXME: Correct args */
|
|
static DWORD (WINAPI *pfnFunc)(LPVOID, LPVOID, LPVOID, LPVOID, LPVOID) = NULL;
|
|
|
|
GET_FUNC(mpr, "WNetGetLastErrorW", 0);
|
|
return pfnFunc(arg1, arg2, arg3, arg4, arg5);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.401]
|
|
*
|
|
* Late bound call to comdlg32.PageSetupDlgW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_401(LPPAGESETUPDLGW pagedlg)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPPAGESETUPDLGW) = NULL;
|
|
|
|
GET_FUNC(comdlg32, "PageSetupDlgW", FALSE);
|
|
return pfnFunc(pagedlg);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.402]
|
|
*
|
|
* Late bound call to comdlg32.PrintDlgW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_402(LPPRINTDLGW printdlg)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPPRINTDLGW) = NULL;
|
|
|
|
GET_FUNC(comdlg32, "PrintDlgW", FALSE);
|
|
return pfnFunc(printdlg);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.403]
|
|
*
|
|
* Late bound call to comdlg32.GetOpenFileNameW
|
|
*/
|
|
BOOL WINAPI SHLWAPI_403(LPOPENFILENAMEW ofn)
|
|
{
|
|
static BOOL (WINAPI *pfnFunc)(LPOPENFILENAMEW) = NULL;
|
|
|
|
GET_FUNC(comdlg32, "GetOpenFileNameW", FALSE);
|
|
return pfnFunc(ofn);
|
|
}
|
|
|
|
/* INTERNAL: Map from HLS color space to RGB */
|
|
static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
|
|
{
|
|
wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
|
|
|
|
if (wHue > 160)
|
|
return wMid1;
|
|
else if (wHue > 120)
|
|
wHue = 160 - wHue;
|
|
else if (wHue > 40)
|
|
return wMid2;
|
|
|
|
return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
|
|
}
|
|
|
|
/* Convert to RGB and scale into RGB range (0..255) */
|
|
#define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
|
|
|
|
/*************************************************************************
|
|
* ColorHLSToRGB [SHLWAPI.404]
|
|
*
|
|
* Convert from HLS color space into an RGB COLORREF.
|
|
*
|
|
* NOTES
|
|
* Input HLS values are constrained to the range (0..240).
|
|
*/
|
|
COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
|
|
{
|
|
WORD wRed;
|
|
|
|
if (wSaturation)
|
|
{
|
|
WORD wGreen, wBlue, wMid1, wMid2;
|
|
|
|
if (wLuminosity > 120)
|
|
wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
|
|
else
|
|
wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
|
|
|
|
wMid1 = wLuminosity * 2 - wMid2;
|
|
|
|
wRed = GET_RGB(wHue + 80);
|
|
wGreen = GET_RGB(wHue);
|
|
wBlue = GET_RGB(wHue - 80);
|
|
|
|
return RGB(wRed, wGreen, wBlue);
|
|
}
|
|
|
|
wRed = wLuminosity * 255 / 240;
|
|
return RGB(wRed, wRed, wRed);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.413]
|
|
*
|
|
* Function unknown seems to always to return 0
|
|
*/
|
|
DWORD WINAPI SHLWAPI_413 (DWORD x)
|
|
{
|
|
FIXME("(0x%08lx)stub\n", x);
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.418]
|
|
*
|
|
* Function seems to do FreeLibrary plus other things.
|
|
*
|
|
* FIXME native shows the following calls:
|
|
* RtlEnterCriticalSection
|
|
* LocalFree
|
|
* GetProcAddress(Comctl32??, 150L)
|
|
* DPA_DeletePtr
|
|
* RtlLeaveCriticalSection
|
|
* followed by the FreeLibrary.
|
|
* The above code may be related to .377 above.
|
|
*/
|
|
BOOL WINAPI SHLWAPI_418 (HMODULE x)
|
|
{
|
|
FIXME("(0x%08lx) partial stub\n", (LONG)x);
|
|
return FreeLibrary(x);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.431]
|
|
*/
|
|
DWORD WINAPI SHLWAPI_431 (DWORD x)
|
|
{
|
|
FIXME("(0x%08lx)stub\n", x);
|
|
return 0xabba1247;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.436]
|
|
*
|
|
* This is really CLSIDFromString which is exported by ole32.dll,
|
|
* however the native shlwapi.dll does *not* import ole32. Nor does
|
|
* ole32.dll import this ordinal from shlwapi. Therefore we must conclude
|
|
* that MS duplicated the code for CLSIDFromString.
|
|
*
|
|
* This is a duplicate (with changes for UNICODE) of CLSIDFromString16
|
|
* in dlls/ole32/compobj.c
|
|
*/
|
|
DWORD WINAPI SHLWAPI_436 (LPWSTR idstr, CLSID *id)
|
|
{
|
|
LPWSTR s = idstr;
|
|
BYTE *p;
|
|
INT i;
|
|
WCHAR table[256];
|
|
|
|
if (!s) {
|
|
memset(s, 0, sizeof(CLSID));
|
|
return S_OK;
|
|
}
|
|
else { /* validate the CLSID string */
|
|
|
|
if (strlenW(s) != 38)
|
|
return CO_E_CLASSSTRING;
|
|
|
|
if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
|
|
return CO_E_CLASSSTRING;
|
|
|
|
for (i=1; i<37; i++)
|
|
{
|
|
if ((i == 9)||(i == 14)||(i == 19)||(i == 24)) continue;
|
|
if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
|
|
((s[i] >= L'a') && (s[i] <= L'f')) ||
|
|
((s[i] >= L'A') && (s[i] <= L'F')))
|
|
)
|
|
return CO_E_CLASSSTRING;
|
|
}
|
|
}
|
|
|
|
TRACE("%s -> %p\n", debugstr_w(s), id);
|
|
|
|
/* quick lookup table */
|
|
memset(table, 0, 256*sizeof(WCHAR));
|
|
|
|
for (i = 0; i < 10; i++) {
|
|
table['0' + i] = i;
|
|
}
|
|
for (i = 0; i < 6; i++) {
|
|
table['A' + i] = i+10;
|
|
table['a' + i] = i+10;
|
|
}
|
|
|
|
/* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
|
|
|
|
p = (BYTE *) id;
|
|
|
|
s++; /* skip leading brace */
|
|
for (i = 0; i < 4; i++) {
|
|
p[3 - i] = table[*s]<<4 | table[*(s+1)];
|
|
s += 2;
|
|
}
|
|
p += 4;
|
|
s++; /* skip - */
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
p[1-i] = table[*s]<<4 | table[*(s+1)];
|
|
s += 2;
|
|
}
|
|
p += 2;
|
|
s++; /* skip - */
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
p[1-i] = table[*s]<<4 | table[*(s+1)];
|
|
s += 2;
|
|
}
|
|
p += 2;
|
|
s++; /* skip - */
|
|
|
|
/* these are just sequential bytes */
|
|
for (i = 0; i < 2; i++) {
|
|
*p++ = table[*s]<<4 | table[*(s+1)];
|
|
s += 2;
|
|
}
|
|
s++; /* skip - */
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
*p++ = table[*s]<<4 | table[*(s+1)];
|
|
s += 2;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* @ [SHLWAPI.437]
|
|
*
|
|
* NOTES
|
|
* In the real shlwapi, One time initialisation calls GetVersionEx and reads
|
|
* the registry to determine what O/S & Service Pack level is running, and
|
|
* therefore which functions are available. Currently we always run as NT,
|
|
* since this means that we don't need extra code to emulate Unicode calls,
|
|
* they are forwarded directly to the appropriate API call instead.
|
|
* Since the flags for whether to call or emulate Unicode are internal to
|
|
* the dll, this function does not need a full implementation.
|
|
*/
|
|
DWORD WINAPI SHLWAPI_437 (DWORD functionToCall)
|
|
{
|
|
FIXME("(0x%08lx)stub\n", functionToCall);
|
|
return /* 0xabba1247 */ 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* ColorRGBToHLS [SHLWAPI.445]
|
|
*
|
|
* Convert from RGB COLORREF into the HLS color space.
|
|
*
|
|
* NOTES
|
|
* Input HLS values are constrained to the range (0..240).
|
|
*/
|
|
VOID WINAPI ColorRGBToHLS(COLORREF drRGB, LPWORD pwHue,
|
|
LPWORD wLuminance, LPWORD pwSaturation)
|
|
{
|
|
FIXME("stub\n");
|
|
return;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHCreateShellPalette [SHLWAPI.@]
|
|
*/
|
|
HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
|
|
{
|
|
FIXME("stub\n");
|
|
return CreateHalftonePalette(hdc);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHGetInverseCMAP (SHLWAPI.@)
|
|
*/
|
|
DWORD WINAPI SHGetInverseCMAP (LPDWORD* x, DWORD why)
|
|
{
|
|
if (why == 4) {
|
|
FIXME(" - returning bogus address for SHGetInverseCMAP\n");
|
|
*x = (LPDWORD)0xabba1249;
|
|
return 0;
|
|
}
|
|
FIXME("(%p, %#lx)stub\n", x, why);
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHIsLowMemoryMachine [SHLWAPI.@]
|
|
*/
|
|
DWORD WINAPI SHIsLowMemoryMachine (DWORD x)
|
|
{
|
|
FIXME("0x%08lx\n", x);
|
|
return 0;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* GetMenuPosFromID [SHLWAPI.@]
|
|
*/
|
|
INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
|
|
{
|
|
MENUITEMINFOA mi;
|
|
INT nCount = GetMenuItemCount(hMenu), nIter = 0;
|
|
|
|
while (nIter < nCount)
|
|
{
|
|
mi.wID = 0;
|
|
if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
|
|
return nIter;
|
|
nIter++;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* _SHGetInstanceExplorer@4 [SHLWAPI.@]
|
|
*
|
|
* Late bound call to shell32.SHGetInstanceExplorer.
|
|
*/
|
|
HRESULT WINAPI _SHGetInstanceExplorer (LPUNKNOWN *lpUnknown)
|
|
{
|
|
static HRESULT (WINAPI *pfnFunc)(LPUNKNOWN *) = NULL;
|
|
|
|
GET_FUNC(shell32, "SHGetInstanceExplorer", E_FAIL);
|
|
return pfnFunc(lpUnknown);
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHGetThreadRef [SHLWAPI.@]
|
|
*
|
|
* Retrieves the per-thread object reference set by SHSetThreadRef
|
|
* "punk" - Address of a pointer to the IUnknown interface. Returns S_OK if
|
|
* successful or E_NOINTERFACE otherwise.
|
|
*/
|
|
HRESULT WINAPI SHGetThreadRef (IUnknown ** ppunk)
|
|
{
|
|
if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
|
|
*ppunk = (IUnknown *)TlsGetValue(SHLWAPI_ThreadRef_index);
|
|
return S_OK;
|
|
}
|
|
|
|
/*************************************************************************
|
|
* SHSetThreadRef [SHLWAPI.@]
|
|
*
|
|
* Stores a per-thread reference to a COM object
|
|
* "punk" - Pointer to the IUnknown interface of the object to
|
|
* which you want to store a reference. Returns S_OK if successful
|
|
* or an OLE error value.
|
|
*/
|
|
HRESULT WINAPI SHSetThreadRef (IUnknown * punk)
|
|
{
|
|
if (SHLWAPI_ThreadRef_index < 0) return E_NOINTERFACE;
|
|
TlsSetValue(SHLWAPI_ThreadRef_index, (LPVOID) punk);
|
|
return S_OK;
|
|
}
|