Sync to Wine-20050830:

Huw Davies <huw@codeweavers.com>
- IUnknown_SetSite calls IObjectWithSite_SetSite or
  IInternetSecurityManager_SetSecuritySite.
- Fix call to GetMenuItemInfo and unicodify while we're at it.
- Implement SHLoadIndirectString.
- _CreateAllAccessSecurityAttributes takes three parameters.
- Forward ordinals 457,458 to GetLongPathNameW,A.
- Implement SHLoadRegUIStringW.
- Partial implementation of DeleteMenuWrap.
- Implement IUnknown_EnumObjects.
- Implement and add tests for the FDSA functions.
Alexandre Julliard <julliard@winehq.org>
- Don't prefix the functions DllInstall and DllGetVersion with the dll
  name so that the compiler can check the prototypes.
Vincent Beron <vberon@mecano.gme.usherb.ca>
- Correct typo in format string.
Mike McCormack <mike@codeweavers.com>
- gcc 4.0 warning fixes.
Steven Edwards <steven_ed4153@yahoo.com>
- Correct RegCreateKeyEx[A/W] prototype to match the PSDK.

svn path=/trunk/; revision=17716
This commit is contained in:
Gé van Geldorp 2005-09-07 15:52:47 +00:00
parent 0e5dde74e7
commit 5be54798fe
12 changed files with 3052 additions and 94 deletions

View file

@ -43,7 +43,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
typedef struct
{
const IStreamVtbl *lpVtbl;
ULONG ref;
LONG ref;
HANDLE hFile;
DWORD dwMode;
LPOLESTR lpszPath;

View file

@ -74,11 +74,6 @@ extern HMODULE SHLWAPI_hversion;
extern DWORD SHLWAPI_ThreadRef_index;
/* 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};
/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
static fnpSHBrowseForFolderW pSHBrowseForFolderW;
@ -1496,48 +1491,39 @@ HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
/*************************************************************************
* @ [SHLWAPI.174]
*
* Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
* an interface.
* Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
* an object.
*
* RETURNS
* Success: S_OK.
* Failure: E_FAIL, if p1 is NULL.
* E_NOINTERFACE If p1 does not support the IPersist interface,
* Or an HRESULT error code.
*/
DWORD WINAPI IUnknown_SetSite(
IUnknown *p1, /* [in] OLE object */
LPVOID *p2) /* [out] ptr for call results */
HRESULT WINAPI IUnknown_SetSite(
IUnknown *obj, /* [in] OLE object */
IUnknown *site) /* [in] Site interface */
{
DWORD ret, aa;
IUnknown *iobjectwithsite;
HRESULT hr;
IObjectWithSite *iobjwithsite;
IInternetSecurityManager *isecmgr;
if (!p1) return E_FAIL;
if (!obj) return E_FAIL;
/* see if SetSite interface exists for IObjectWithSite object */
ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);
TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);
if (ret) {
/* see if GetClassId interface exists for IPersistMoniker object */
ret = IUnknown_QueryInterface(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);
hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
TRACE("IID_IObjectWithSite QI ret=%08lx, %p\n", hr, iobjwithsite);
if (SUCCEEDED(hr))
{
hr = IObjectWithSite_SetSite(iobjwithsite, site);
TRACE("done IObjectWithSite_SetSite ret=%08lx\n", hr);
IUnknown_Release(iobjwithsite);
}
else {
/* fake a SetSite call */
ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);
TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
*(LPDWORD)p2);
IUnknown_Release((IUnknown *)iobjectwithsite);
else
{
hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
TRACE("IID_IInternetSecurityManager QI ret=%08lx, %p\n", hr, isecmgr);
if (FAILED(hr)) return hr;
hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08lx\n", hr);
IUnknown_Release(isecmgr);
}
return ret;
return hr;
}
/*************************************************************************
@ -1962,14 +1948,14 @@ HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
*/
HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
{
MENUITEMINFOA mi;
MENUITEMINFOW mi;
TRACE("(%p,%uld)\n", hMenu, uID);
TRACE("(%p,%u)\n", hMenu, uID);
mi.cbSize = sizeof(MENUITEMINFOA);
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_SUBMENU;
if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
return NULL;
return mi.hSubMenu;
@ -2230,63 +2216,129 @@ BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
return !IsChild(hParent, hChild);
}
/*************************************************************************
* FDSA functions. Manage a dynamic array of fixed size memory blocks.
*/
typedef struct
{
DWORD num_items; /* Number of elements inserted */
void *mem; /* Ptr to array */
DWORD blocks_alloced; /* Number of elements allocated */
BYTE inc; /* Number of elements to grow by when we need to expand */
BYTE block_size; /* Size in bytes of an element */
BYTE flags; /* Flags */
} FDSA_info;
#define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
/*************************************************************************
* @ [SHLWAPI.208]
*
* Some sort of memory management process.
* Initialize an FDSA arrary.
*/
DWORD WINAPI FDSA_Initialize(
DWORD a,
DWORD b,
LPVOID c,
LPVOID d,
DWORD e)
BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
DWORD init_blocks)
{
FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
a, b, c, d, e);
return 1;
TRACE("(0x%08lx 0x%08lx %p %p 0x%08lx)\n", block_size, inc, info, mem, init_blocks);
if(inc == 0)
inc = 1;
if(mem)
memset(mem, 0, block_size * init_blocks);
info->num_items = 0;
info->inc = inc;
info->mem = mem;
info->blocks_alloced = init_blocks;
info->block_size = block_size;
info->flags = 0;
return TRUE;
}
/*************************************************************************
* @ [SHLWAPI.209]
*
* Some sort of memory management process.
* Destroy an FDSA array
*/
DWORD WINAPI FDSA_Destroy(
LPVOID a)
BOOL WINAPI FDSA_Destroy(FDSA_info *info)
{
FIXME("(%p) stub\n",
a);
return 1;
TRACE("(%p)\n", info);
if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
{
HeapFree(GetProcessHeap(), 0, info->mem);
return FALSE;
}
return TRUE;
}
/*************************************************************************
* @ [SHLWAPI.210]
*
* Some sort of memory management process.
* Insert element into an FDSA array
*/
DWORD WINAPI FDSA_InsertItem(
LPVOID a,
DWORD b,
LPVOID c)
DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, void *block)
{
FIXME("(%p 0x%08lx %p) stub\n",
a, b, c);
return 0;
TRACE("(%p 0x%08lx %p)\n", info, where, block);
if(where > info->num_items)
where = info->num_items;
if(info->num_items >= info->blocks_alloced)
{
DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
if(info->flags & 0x1)
info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
else
{
void *old_mem = info->mem;
info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
}
info->blocks_alloced += info->inc;
info->flags |= 0x1;
}
if(where < info->num_items)
{
memmove((char*)info->mem + (where + 1) * info->block_size,
(char*)info->mem + where * info->block_size,
(info->num_items - where) * info->block_size);
}
memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
info->num_items++;
return where;
}
/*************************************************************************
* @ [SHLWAPI.211]
*
* Delete an element from an FDSA array.
*/
DWORD WINAPI FDSA_DeleteItem(
LPVOID a,
DWORD b)
BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
{
FIXME("(%p 0x%08lx) stub\n",
a, b);
return 1;
TRACE("(%p 0x%08lx)\n", info, where);
if(where >= info->num_items)
return FALSE;
if(where < info->num_items - 1)
{
memmove((char*)info->mem + where * info->block_size,
(char*)info->mem + (where + 1) * info->block_size,
(info->num_items - where - 1) * info->block_size);
}
memset((char*)info->mem + (info->num_items - 1) * info->block_size,
0, info->block_size);
info->num_items--;
return TRUE;
}
typedef struct {
REFIID refid;
DWORD indx;
@ -3527,6 +3579,31 @@ BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
return pGetOpenFileNameW(ofn);
}
/*************************************************************************
* @ [SHLWAPI.404]
*/
HRESULT WINAPI IUnknown_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
{
IPersist *persist;
HRESULT hr;
hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
if(SUCCEEDED(hr))
{
CLSID clsid;
hr = IPersist_GetClassID(persist, &clsid);
if(SUCCEEDED(hr))
{
if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
else
hr = E_FAIL;
}
IPersist_Release(persist);
}
return hr;
}
/* INTERNAL: Map from HLS color space to RGB */
static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
{
@ -3644,6 +3721,16 @@ BOOL WINAPI SHFlushSFCacheWrap(void) {
return TRUE;
}
/*************************************************************************
* @ [SHLWAPI.425]
*/
BOOL WINAPI DeleteMenuWrap(HMENU hmenu, UINT pos, UINT flags)
{
/* FIXME: This should do more than simply call DeleteMenu */
FIXME("%p %08x %08x): semi-stub\n", hmenu, pos, flags);
return DeleteMenu(hmenu, pos, flags);
}
/*************************************************************************
* @ [SHLWAPI.429]
* FIXME I have no idea what this function does or what its arguments are.
@ -3905,6 +3992,19 @@ BOOL WINAPI IsOS(DWORD feature)
return FALSE;
}
/*************************************************************************
* @ [SHLWAPI.439]
*/
HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
{
DWORD type, sz = size;
if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
return E_FAIL;
return SHLoadIndirectString(buf, buf, size, NULL);
}
/*************************************************************************
* @ [SHLWAPI.478]
*
@ -4122,13 +4222,14 @@ BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
*/
INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
{
MENUITEMINFOA mi;
MENUITEMINFOW mi;
INT nCount = GetMenuItemCount(hMenu), nIter = 0;
while (nIter < nCount)
{
mi.wID = 0;
if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
mi.cbSize = sizeof(mi);
mi.fMask = MIIM_ID;
if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
return nIter;
nIter++;
}

View file

@ -1191,13 +1191,12 @@ DWORD WINAPI SHSetValueA(HKEY hKey, LPCSTR lpszSubKey, LPCSTR lpszValue,
{
DWORD dwRet = ERROR_SUCCESS, dwDummy;
HKEY hSubKey;
static const char szEmpty[] = { '\0' };
TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_a(lpszSubKey),
debugstr_a(lpszValue), dwType, pvData, cbData);
if (lpszSubKey && *lpszSubKey)
dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, (LPSTR)szEmpty,
dwRet = RegCreateKeyExA(hKey, lpszSubKey, 0, NULL,
0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
else
hSubKey = hKey;
@ -1220,13 +1219,12 @@ DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue,
{
DWORD dwRet = ERROR_SUCCESS, dwDummy;
HKEY hSubKey;
static const WCHAR szEmpty[] = { '\0' };
TRACE("(hkey=%p,%s,%s,%ld,%p,%ld)\n", hKey, debugstr_w(lpszSubKey),
debugstr_w(lpszValue), dwType, pvData, cbData);
if (lpszSubKey && *lpszSubKey)
dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, (LPWSTR)szEmpty,
dwRet = RegCreateKeyExW(hKey, lpszSubKey, 0, NULL,
0, KEY_SET_VALUE, NULL, &hSubKey, &dwDummy);
else
hSubKey = hKey;

View file

@ -37,7 +37,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(shell);
typedef struct
{
const IStreamVtbl *lpVtbl;
DWORD ref;
LONG ref;
HKEY hKey;
LPBYTE pbBuffer;
DWORD dwLength;

View file

@ -353,7 +353,7 @@
353 stub -noname SHFormatDateTimeA
354 stub -noname SHFormatDateTimeW
355 stdcall -noname IUnknown_EnableModeless(ptr long)
356 stdcall -noname _CreateAllAccessSecurityAttributes(ptr ptr)
356 stdcall -noname _CreateAllAccessSecurityAttributes(ptr ptr long)
357 stdcall -noname SHGetNewLinkInfoWrapW(wstr wstr wstr long long)
358 stdcall -noname SHDefExtractIconWrapW(wstr long long ptr ptr long)
359 stdcall @(long long wstr) kernel32.OpenEventW
@ -401,7 +401,7 @@
401 stdcall -noname PageSetupDlgWrapW(ptr)
402 stdcall -noname PrintDlgWrapW(ptr)
403 stdcall -noname GetOpenFileNameWrapW(ptr)
404 stub -noname IShellFolder_EnumObjects
404 stdcall -noname IUnknown_EnumObjects(ptr ptr long ptr)
405 stdcall -noname MLBuildResURLA(str ptr long str ptr long)
406 stdcall -noname MLBuildResURLW(wstr ptr long wstr ptr long)
407 stub -noname AssocMakeProgid
@ -422,7 +422,7 @@
422 stdcall -noname _SHGlobalCounterCreateNamedA(str long)
423 stdcall -noname _SHGlobalCounterCreateNamedW(wstr long)
424 stdcall -noname _SHGlobalCounterDecrement(long)
425 stub -noname DeleteMenuWrap
425 stdcall -noname DeleteMenuWrap(ptr long long)
426 stub -noname DestroyMenuWrap
427 stub -noname TrackPopupMenuWrap
428 stdcall @(long long long long long ptr) user32.TrackPopupMenuEx
@ -436,7 +436,7 @@
436 stdcall -noname CLSIDFromStringWrap(wstr ptr)
437 stdcall -noname IsOS(long)
438 stub -noname SHLoadRegUIStringA
439 stub -noname SHLoadRegUIStringW
439 stdcall -noname SHLoadRegUIStringW(ptr wstr ptr long)
440 stdcall -noname SHGetWebFolderFilePathA(str ptr long)
441 stdcall -noname SHGetWebFolderFilePathW(wstr ptr long)
442 stdcall @(wstr ptr long) kernel32.GetEnvironmentVariableW
@ -454,8 +454,8 @@
454 stub -noname CharLowerNoDBCSW
455 stdcall -noname PathIsValidCharA(long long)
456 stdcall -noname PathIsValidCharW(long long)
457 stub -noname GetLongPathNameWrapW
458 stub -noname GetLongPathNameWrapA
457 stdcall @(wstr ptr long) kernel32.GetLongPathNameW
458 stdcall @(str ptr long) kernel32.GetLongPathNameA
459 stdcall -noname SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA
460 stdcall -noname SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW
461 stdcall -noname SHGetAppCompatFlags(long)
@ -559,7 +559,7 @@
@ stdcall ColorAdjustLuma(long long long)
@ stdcall ColorHLSToRGB(long long long)
@ stdcall ColorRGBToHLS(long ptr ptr ptr)
@ stdcall DllGetVersion (ptr) SHLWAPI_DllGetVersion
@ stdcall -private DllGetVersion(ptr)
@ stdcall GetMenuPosFromID(ptr long)
@ stdcall HashData (ptr long ptr long)
@ stdcall IntlStrEqWorkerA(long str str long) StrIsIntlEqualA
@ -699,6 +699,7 @@
@ stdcall SHGetValueA ( long str str ptr ptr ptr )
@ stdcall SHGetValueW ( long wstr wstr ptr ptr ptr )
@ stdcall SHIsLowMemoryMachine(long)
@ stdcall SHLoadIndirectString(wstr ptr long ptr)
@ stdcall SHOpenRegStream2A(long str str long)
@ stdcall SHOpenRegStream2W(long wstr str long)
@ stdcall SHOpenRegStreamA(long str str long)

View file

@ -105,7 +105,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
* as pdvi, provided that the size is set correctly.
* Returns version as shlwapi.dll from IE5.01.
*/
HRESULT WINAPI SHLWAPI_DllGetVersion (DLLVERSIONINFO *pdvi)
HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
{
DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2*)pdvi;

View file

@ -2699,3 +2699,58 @@ BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen)
SHAnsiToUnicode(lpDst, szBuff, MAX_PATH);
return !strcmpW(lpSrcStr, szBuff);
}
/*************************************************************************
* SHLoadIndirectString [SHLWAPI.@]
*
* If passed a string that begins with a '@' extract the string from the
* appropriate resource, otherwise do a straight copy.
*
*/
HRESULT WINAPI SHLoadIndirectString(LPCWSTR src, LPWSTR dst, UINT dst_len, void **reserved)
{
WCHAR *dllname = NULL;
HMODULE hmod = NULL;
HRESULT hr = E_FAIL;
TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved);
if(src[0] == '@')
{
WCHAR *index_str;
int index;
dst[0] = 0;
dllname = StrDupW(src + 1);
index_str = strchrW(dllname, ',');
if(!index_str) goto end;
*index_str = 0;
index_str++;
index = atoiW(index_str);
hmod = LoadLibraryW(dllname);
if(!hmod) goto end;
if(index < 0)
{
if(LoadStringW(hmod, -index, dst, dst_len))
hr = S_OK;
}
else
FIXME("can't handle non-negative indicies (%d)\n", index);
}
else
{
if(dst != src)
lstrcpynW(dst, src, dst_len);
hr = S_OK;
}
TRACE("returing %s\n", debugstr_w(dst));
end:
if(hmod) FreeLibrary(hmod);
HeapFree(GetProcessHeap(), 0, dllname);
return hr;
}

View file

@ -75,12 +75,13 @@ DWORD WINAPI SHStringFromGUIDA(REFGUID,LPSTR,INT);
*/
LPSECURITY_ATTRIBUTES WINAPI _CreateAllAccessSecurityAttributes(
LPSECURITY_ATTRIBUTES lpAttr,
PSECURITY_DESCRIPTOR lpSec)
PSECURITY_DESCRIPTOR lpSec,
DWORD p3)
{
/* This function is used within SHLWAPI only to create security attributes
* for shell semaphores. */
TRACE("(%p,%p)\n", lpAttr, lpSec);
TRACE("(%p,%p,%08lx)\n", lpAttr, lpSec, p3);
if (!(GetVersion() & 0x80000000)) /* NT */
{
@ -426,7 +427,7 @@ HANDLE WINAPI _SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial)
StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen);
/* Initialise security attributes */
pSecAttr = _CreateAllAccessSecurityAttributes(&sAttr, &sd);
pSecAttr = _CreateAllAccessSecurityAttributes(&sAttr, &sd, 0);
if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff)))
hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff);

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@ extern "C" {
#endif
#include <ole2.h>
#include <urlmon.h>
typedef interface IErrorLog *LPERRORLOG;
typedef interface IPropertyBag *LPPROPERTYBAG;

View file

@ -259,6 +259,7 @@ WINSHLWAPI BOOL WINAPI ChrCmpIW(WCHAR,WCHAR);
WINSHLWAPI BOOL WINAPI IntlStrEqWorkerA(BOOL,LPCSTR,LPCSTR,int);
WINSHLWAPI BOOL WINAPI IntlStrEqWorkerW(BOOL,LPCWSTR,LPCWSTR,int);
WINSHLWAPI BOOL WINAPI IsOS(DWORD);
WINSHLWAPI HRESULT WINAPI SHLoadIndirectString(LPCWSTR,LPWSTR,UINT,PVOID*);
WINSHLWAPI HRESULT WINAPI SHStrDupA(LPCSTR,LPWSTR*);
WINSHLWAPI HRESULT WINAPI SHStrDupW(LPCWSTR,LPWSTR*);
WINSHLWAPI LPSTR WINAPI StrCatA(LPSTR,LPCSTR);