Initial port of shlwapi.dll from Wine that doesn't compile yet. I don't want to keep it private, but there is still one file that doesn't compile. If anyone wants to go and fix it, feel free to do so.

svn path=/trunk/; revision=6928
This commit is contained in:
Filip Navara 2003-12-09 16:50:53 +00:00
parent 8615f19c50
commit f420913748
14 changed files with 19088 additions and 0 deletions

699
reactos/lib/shlwapi/assoc.c Normal file
View file

@ -0,0 +1,699 @@
/*
* IQueryAssociations object and helper functions
*
* Copyright 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#ifdef __REACTOS__
#include "wine/icom.h"
#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winreg.h"
#include "objbase.h"
#include "shlguid.h"
#include "shlwapi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/**************************************************************************
* IQueryAssociations {SHLWAPI}
*
* DESCRIPTION
* This object provides a layer of abstraction over the system registry in
* order to simplify the process of parsing associations between files.
* Associations in this context means the registry entries that link (for
* example) the extension of a file with its description, list of
* applications to open the file with, and actions that can be performed on it
* (the shell displays such information in the context menu of explorer
* when you right-click on a file).
*
* HELPERS
* You can use this object tranparently by calling the helper functions
* AssocQueryKeyA(), AssocQueryStringA() and AssocQueryStringByKeyA(). These
* create an IQueryAssociations object, perform the requested actions
* and then dispose of the object. Alternatively, you can create an instance
* of the object using AssocCreate() and call the following methods on it:
*
* METHODS
*/
/* Default IQueryAssociations::Init() flags */
#define SHLWAPI_DEF_ASSOCF (ASSOCF_INIT_BYEXENAME|ASSOCF_INIT_DEFAULTTOSTAR| \
ASSOCF_INIT_DEFAULTTOFOLDER)
typedef struct
{
ICOM_VFIELD(IQueryAssociations);
LONG ref;
HKEY hkeySource;
HKEY hkeyProgID;
} IQueryAssociationsImpl;
static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl;
/**************************************************************************
* IQueryAssociations_Constructor [internal]
*
* Construct a new IQueryAssociations object.
*/
static IQueryAssociations* IQueryAssociations_Constructor(void)
{
IQueryAssociationsImpl* iface;
iface =(IQueryAssociationsImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IQueryAssociationsImpl));
iface->lpVtbl = &IQueryAssociations_vtbl;
iface->ref = 1;
iface->hkeySource = NULL;
iface->hkeyProgID = NULL;
TRACE("Returning IQueryAssociations* %p\n", iface);
return (IQueryAssociations*)iface;
}
/*************************************************************************
* SHLWAPI_ParamAToW
*
* Internal helper function: Convert ASCII parameter to Unicode.
*/
static BOOL SHLWAPI_ParamAToW(LPCSTR lpszParam, LPWSTR lpszBuff, DWORD dwLen,
LPWSTR* lpszOut)
{
if (lpszParam)
{
DWORD dwStrLen = lstrlenA(lpszParam);
if (dwStrLen < dwLen)
{
*lpszOut = lpszBuff; /* Use Buffer, it is big enough */
}
else
{
/* Create a new buffer big enough for the string */
*lpszOut = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
(dwStrLen + 1) * sizeof(WCHAR));
if (!*lpszOut)
return FALSE;
}
MultiByteToWideChar(0, 0, lpszParam, -1, *lpszOut, -1);
}
else
*lpszOut = NULL;
return TRUE;
}
/*************************************************************************
* AssocCreate [SHLWAPI.@]
*
* Create a new IQueryAssociations object.
*
* PARAMS
* clsid [I] CLSID of object
* refiid [I] REFIID of interface
* lpInterface [O] Destination for the created IQueryAssociations object
*
* RETURNS
* Success: S_OK. lpInterface contains the new object.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* refiid must be equal to IID_IQueryAssociations, or this function will fail.
*/
HRESULT WINAPI AssocCreate(CLSID clsid, REFIID refiid, void **lpInterface)
{
HRESULT hRet;
IQueryAssociations* lpAssoc;
TRACE("(%s,%s,%p)\n", debugstr_guid(&clsid), debugstr_guid(refiid),
lpInterface);
if (!lpInterface)
return E_INVALIDARG;
*(DWORD*)lpInterface = 0;
if (!IsEqualGUID(&clsid, &IID_IQueryAssociations))
return E_NOTIMPL;
lpAssoc = IQueryAssociations_Constructor();
if (!lpAssoc)
return E_OUTOFMEMORY;
hRet = IQueryAssociations_QueryInterface(lpAssoc, refiid, lpInterface);
IQueryAssociations_Release(lpAssoc);
return hRet;
}
/*************************************************************************
* AssocQueryKeyW [SHLWAPI.@]
*
* See AssocQueryKeyA.
*/
HRESULT WINAPI AssocQueryKeyW(ASSOCF cfFlags, ASSOCKEY assockey, LPCWSTR pszAssoc,
LPCWSTR pszExtra, HKEY *phkeyOut)
{
HRESULT hRet;
IQueryAssociations* lpAssoc;
TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_w(pszAssoc),
debugstr_w(pszExtra), phkeyOut);
lpAssoc = IQueryAssociations_Constructor();
if (!lpAssoc)
return E_OUTOFMEMORY;
cfFlags &= SHLWAPI_DEF_ASSOCF;
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, pszAssoc, NULL, NULL);
if (SUCCEEDED(hRet))
hRet = IQueryAssociations_GetKey(lpAssoc, cfFlags, assockey, pszExtra, phkeyOut);
IQueryAssociations_Release(lpAssoc);
return hRet;
}
/*************************************************************************
* AssocQueryKeyA [SHLWAPI.@]
*
* Get a file association key from the registry.
*
* PARAMS
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assockey [I] Type of key to get
* pszAssoc [I] Key name to search below
* pszExtra [I] Extra information about the key location
* phkeyOut [O] Destination for the association key
*
* RETURNS
* Success: S_OK. phkeyOut contains the key.
* Failure: An HRESULT error code indicating the error.
*/
HRESULT WINAPI AssocQueryKeyA(ASSOCF cfFlags, ASSOCKEY assockey, LPCSTR pszAssoc,
LPCSTR pszExtra, HKEY *phkeyOut)
{
WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
HRESULT hRet = E_OUTOFMEMORY;
TRACE("(0x%8lx,0x%8x,%s,%s,%p)\n", cfFlags, assockey, debugstr_a(pszAssoc),
debugstr_a(pszExtra), phkeyOut);
if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
{
hRet = AssocQueryKeyW(cfFlags, assockey, lpszAssocW, lpszExtraW, phkeyOut);
}
if (lpszAssocW && lpszAssocW != szAssocW)
HeapFree(GetProcessHeap(), 0, lpszAssocW);
if (lpszExtraW && lpszExtraW != szExtraW)
HeapFree(GetProcessHeap(), 0, lpszExtraW);
return hRet;
}
/*************************************************************************
* AssocQueryStringW [SHLWAPI.@]
*
* See AssocQueryStringA.
*/
HRESULT WINAPI AssocQueryStringW(ASSOCF cfFlags, ASSOCSTR str, LPCWSTR pszAssoc,
LPCWSTR pszExtra, LPWSTR pszOut, DWORD *pcchOut)
{
HRESULT hRet;
IQueryAssociations* lpAssoc;
TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_w(pszAssoc),
debugstr_w(pszExtra), pszOut, pcchOut);
if (!pcchOut)
return E_INVALIDARG;
lpAssoc = IQueryAssociations_Constructor();
if (!lpAssoc)
return E_OUTOFMEMORY;
hRet = IQueryAssociations_Init(lpAssoc, cfFlags & SHLWAPI_DEF_ASSOCF,
pszAssoc, NULL, NULL);
if (SUCCEEDED(hRet))
hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
pszOut, pcchOut);
IQueryAssociations_Release(lpAssoc);
return hRet;
}
/*************************************************************************
* AssocQueryStringA [SHLWAPI.@]
*
* Get a file association string from the registry.
*
* PARAMS
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
* pszAssoc [I] Key name to search below
* pszExtra [I] Extra information about the string location
* pszOut [O] Destination for the association string
* pcchOut [O] Length of pszOut
*
* RETURNS
* Success: S_OK. pszOut contains the string, pcchOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
HRESULT WINAPI AssocQueryStringA(ASSOCF cfFlags, ASSOCSTR str, LPCSTR pszAssoc,
LPCSTR pszExtra, LPSTR pszOut, DWORD *pcchOut)
{
WCHAR szAssocW[MAX_PATH], *lpszAssocW = NULL;
WCHAR szExtraW[MAX_PATH], *lpszExtraW = NULL;
HRESULT hRet = E_OUTOFMEMORY;
TRACE("(0x%8lx,0x%8x,%s,%s,%p,%p)\n", cfFlags, str, debugstr_a(pszAssoc),
debugstr_a(pszExtra), pszOut, pcchOut);
if (!pcchOut)
hRet = E_INVALIDARG;
else if (SHLWAPI_ParamAToW(pszAssoc, szAssocW, MAX_PATH, &lpszAssocW) &&
SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
{
WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
DWORD dwLenOut = *pcchOut;
if (dwLenOut >= MAX_PATH)
lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
(dwLenOut + 1) * sizeof(WCHAR));
if (!lpszReturnW)
hRet = E_OUTOFMEMORY;
else
{
hRet = AssocQueryStringW(cfFlags, str, lpszAssocW, lpszExtraW,
lpszReturnW, &dwLenOut);
if (SUCCEEDED(hRet))
WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
*pcchOut = dwLenOut;
if (lpszReturnW && lpszReturnW != szReturnW)
HeapFree(GetProcessHeap(), 0, lpszReturnW);
}
}
if (lpszAssocW && lpszAssocW != szAssocW)
HeapFree(GetProcessHeap(), 0, lpszAssocW);
if (lpszExtraW && lpszExtraW != szExtraW)
HeapFree(GetProcessHeap(), 0, lpszExtraW);
return hRet;
}
/*************************************************************************
* AssocQueryStringByKeyW [SHLWAPI.@]
*
* See AssocQueryStringByKeyA.
*/
HRESULT WINAPI AssocQueryStringByKeyW(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
LPCWSTR pszExtra, LPWSTR pszOut,
DWORD *pcchOut)
{
HRESULT hRet;
IQueryAssociations* lpAssoc;
TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
debugstr_w(pszExtra), pszOut, pcchOut);
lpAssoc = IQueryAssociations_Constructor();
if (!lpAssoc)
return E_OUTOFMEMORY;
cfFlags &= SHLWAPI_DEF_ASSOCF;
hRet = IQueryAssociations_Init(lpAssoc, cfFlags, 0, hkAssoc, NULL);
if (SUCCEEDED(hRet))
hRet = IQueryAssociations_GetString(lpAssoc, cfFlags, str, pszExtra,
pszOut, pcchOut);
IQueryAssociations_Release(lpAssoc);
return hRet;
}
/*************************************************************************
* AssocQueryStringByKeyA [SHLWAPI.@]
*
* Get a file association string from the registry, given a starting key.
*
* PARAMS
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* str [I] Type of string to get
* hkAssoc [I] Key to search below
* pszExtra [I] Extra information about the string location
* pszOut [O] Destination for the association string
* pcchOut [O] Length of pszOut
*
* RETURNS
* Success: S_OK. pszOut contains the string, pcchOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
HRESULT WINAPI AssocQueryStringByKeyA(ASSOCF cfFlags, ASSOCSTR str, HKEY hkAssoc,
LPCSTR pszExtra, LPSTR pszOut,
DWORD *pcchOut)
{
WCHAR szExtraW[MAX_PATH], *lpszExtraW;
WCHAR szReturnW[MAX_PATH], *lpszReturnW = szReturnW;
HRESULT hRet = E_OUTOFMEMORY;
TRACE("(0x%8lx,0x%8x,%p,%s,%p,%p)\n", cfFlags, str, hkAssoc,
debugstr_a(pszExtra), pszOut, pcchOut);
if (!pcchOut)
hRet = E_INVALIDARG;
else if (SHLWAPI_ParamAToW(pszExtra, szExtraW, MAX_PATH, &lpszExtraW))
{
DWORD dwLenOut = *pcchOut;
if (dwLenOut >= MAX_PATH)
lpszReturnW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0,
(dwLenOut + 1) * sizeof(WCHAR));
if (lpszReturnW)
{
hRet = AssocQueryStringByKeyW(cfFlags, str, hkAssoc, lpszExtraW,
lpszReturnW, &dwLenOut);
if (SUCCEEDED(hRet))
WideCharToMultiByte(CP_ACP,0,szReturnW,-1,pszOut,dwLenOut,0,0);
*pcchOut = dwLenOut;
if (lpszReturnW != szReturnW)
HeapFree(GetProcessHeap(), 0, lpszReturnW);
}
}
if (lpszExtraW && lpszExtraW != szExtraW)
HeapFree(GetProcessHeap(), 0, lpszExtraW);
return hRet;
}
/**************************************************************************
* AssocIsDangerous (SHLWAPI.@)
*/
HRESULT WINAPI AssocIsDangerous( ASSOCSTR str )
{
FIXME("%08x\n", str);
return S_FALSE;
}
/**************************************************************************
* IQueryAssociations_QueryInterface {SHLWAPI}
*
* See IUnknown_QueryInterface.
*/
static HRESULT WINAPI IQueryAssociations_fnQueryInterface(
IQueryAssociations* iface,
REFIID riid,
LPVOID *ppvObj)
{
ICOM_THIS(IQueryAssociationsImpl, iface);
TRACE("(%p,%s,%p)\n",This, debugstr_guid(riid), ppvObj);
*ppvObj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IQueryAssociations))
{
*ppvObj = (IQueryAssociations*)This;
IQueryAssociations_AddRef((IQueryAssociations*)*ppvObj);
TRACE("Returning IQueryAssociations (%p)\n", *ppvObj);
return S_OK;
}
TRACE("Returning E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IQueryAssociations_AddRef {SHLWAPI}
*
* See IUnknown_AddRef.
*/
static ULONG WINAPI IQueryAssociations_fnAddRef(IQueryAssociations *iface)
{
ICOM_THIS(IQueryAssociationsImpl,iface);
TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
return InterlockedIncrement(&This->ref);
}
/**************************************************************************
* IQueryAssociations_Release {SHLWAPI}
*
* See IUnknown_Release.
*/
static ULONG WINAPI IQueryAssociations_fnRelease(IQueryAssociations *iface)
{
ICOM_THIS(IQueryAssociationsImpl,iface);
ULONG ulRet;
TRACE("(%p)->(ref before=%lu)\n",This, This->ref);
if (!(ulRet = InterlockedDecrement(&This->ref)))
{
TRACE("Destroying IQueryAssociations (%p)\n", This);
HeapFree(GetProcessHeap(), 0, This);
}
return ulRet;
}
/**************************************************************************
* IQueryAssociations_Init {SHLWAPI}
*
* Initialise an IQueryAssociations object.
*
* PARAMS
* iface [I] IQueryAssociations interface to initialise
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* pszAssoc [I] String for the root key name, or NULL if hkProgid is given
* hkeyProgid [I] Handle for the root key, or NULL if pszAssoc is given
* hWnd [I] Reserved, must be NULL.
*
* RETURNS
* Success: S_OK. iface is initialised with the parameters given.
* Failure: An HRESULT error code indicating the error.
*/
static HRESULT WINAPI IQueryAssociations_fnInit(
IQueryAssociations *iface,
ASSOCF cfFlags,
LPCWSTR pszAssoc,
HKEY hkeyProgid,
HWND hWnd)
{
static const WCHAR szProgID[] = {'P','r','o','g','I','D',0};
ICOM_THIS(IQueryAssociationsImpl,iface);
HRESULT hr;
TRACE("(%p)->(%ld,%s,%p,%p)\n", iface,
cfFlags,
debugstr_w(pszAssoc),
hkeyProgid,
hWnd);
if (hWnd != NULL)
FIXME("hwnd != NULL not supported\n");
if (cfFlags != 0)
FIXME("unsupported flags: %lx\n", cfFlags);
if (pszAssoc != NULL)
{
hr = RegOpenKeyExW(HKEY_CLASSES_ROOT,
pszAssoc,
0,
KEY_READ,
&This->hkeySource);
if (FAILED(hr))
return HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION);
/* if this is not a prog id */
if ((*pszAssoc == '.') || (*pszAssoc == '{'))
{
hr = RegOpenKeyExW(This->hkeySource,
szProgID,
0,
KEY_READ,
&This->hkeyProgID);
if (FAILED(hr))
FIXME("Don't know what to return\n");
}
else
This->hkeyProgID = This->hkeySource;
return S_OK;
}
else if (hkeyProgid != NULL)
{
This->hkeyProgID = hkeyProgid;
return S_OK;
}
else
return E_FAIL;
}
/**************************************************************************
* IQueryAssociations_GetString {SHLWAPI}
*
* Get a file association string from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* str [I] Type of string to get (ASSOCSTR enum from "shlwapi.h")
* pszExtra [I] Extra information about the string location
* pszOut [O] Destination for the association string
* pcchOut [I/O] Length of pszOut
*
* RETURNS
* Success: S_OK. pszOut contains the string, pcchOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static HRESULT WINAPI IQueryAssociations_fnGetString(
IQueryAssociations *iface,
ASSOCF cfFlags,
ASSOCSTR str,
LPCWSTR pszExtra,
LPWSTR pszOut,
DWORD *pcchOut)
{
ICOM_THIS(IQueryAssociationsImpl, iface);
FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, str,
debugstr_w(pszExtra), pszOut, pcchOut);
return E_NOTIMPL;
}
/**************************************************************************
* IQueryAssociations_GetKey {SHLWAPI}
*
* Get a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assockey [I] Type of key to get (ASSOCKEY enum from "shlwapi.h")
* pszExtra [I] Extra information about the key location
* phkeyOut [O] Destination for the association key
*
* RETURNS
* Success: S_OK. phkeyOut contains a handle to the key.
* Failure: An HRESULT error code indicating the error.
*/
static HRESULT WINAPI IQueryAssociations_fnGetKey(
IQueryAssociations *iface,
ASSOCF cfFlags,
ASSOCKEY assockey,
LPCWSTR pszExtra,
HKEY *phkeyOut)
{
ICOM_THIS(IQueryAssociationsImpl, iface);
FIXME("(%p,0x%8lx,0x%8x,%s,%p)-stub!\n", This, cfFlags, assockey,
debugstr_w(pszExtra), phkeyOut);
return E_NOTIMPL;
}
/**************************************************************************
* IQueryAssociations_GetData {SHLWAPI}
*
* Get the data for a file association key from the registry.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocdata [I] Type of data to get (ASSOCDATA enum from "shlwapi.h")
* pszExtra [I] Extra information about the data location
* pvOut [O] Destination for the association key
* pcbOut [I/O] Size of pvOut
*
* RETURNS
* Success: S_OK. pszOut contains the data, pcbOut contains its length.
* Failure: An HRESULT error code indicating the error.
*/
static HRESULT WINAPI IQueryAssociations_fnGetData(
IQueryAssociations *iface,
ASSOCF cfFlags,
ASSOCDATA assocdata,
LPCWSTR pszExtra,
LPVOID pvOut,
DWORD *pcbOut)
{
ICOM_THIS(IQueryAssociationsImpl, iface);
FIXME("(%p,0x%8lx,0x%8x,%s,%p,%p)-stub!\n", This, cfFlags, assocdata,
debugstr_w(pszExtra), pvOut, pcbOut);
return E_NOTIMPL;
}
/**************************************************************************
* IQueryAssociations_GetEnum {SHLWAPI}
*
* Not yet implemented in native Win32.
*
* PARAMS
* iface [I] IQueryAssociations interface to query
* cfFlags [I] ASSOCF_ flags from "shlwapi.h"
* assocenum [I] Type of enum to get (ASSOCENUM enum from "shlwapi.h")
* pszExtra [I] Extra information about the enum location
* riid [I] REFIID to look for
* ppvOut [O] Destination for the interface.
*
* RETURNS
* Success: S_OK.
* Failure: An HRESULT error code indicating the error.
*
* NOTES
* Presumably this function returns an enumerator object.
*/
static HRESULT WINAPI IQueryAssociations_fnGetEnum(
IQueryAssociations *iface,
ASSOCF cfFlags,
ASSOCENUM assocenum,
LPCWSTR pszExtra,
REFIID riid,
LPVOID *ppvOut)
{
ICOM_THIS(IQueryAssociationsImpl, iface);
FIXME("(%p,0x%8lx,0x%8x,%s,%s,%p)-stub!\n", This, cfFlags, assocenum,
debugstr_w(pszExtra), debugstr_guid(riid), ppvOut);
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IQueryAssociations) IQueryAssociations_vtbl =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IQueryAssociations_fnQueryInterface,
IQueryAssociations_fnAddRef,
IQueryAssociations_fnRelease,
IQueryAssociations_fnInit,
IQueryAssociations_fnGetString,
IQueryAssociations_fnGetKey,
IQueryAssociations_fnGetData,
IQueryAssociations_fnGetEnum
};

453
reactos/lib/shlwapi/clist.c Normal file
View file

@ -0,0 +1,453 @@
/*
* SHLWAPI DataBlock List functions
*
* Copyright 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* DataBlock list element (ordinals 17-22) */
typedef struct tagSHLWAPI_CLIST
{
ULONG ulSize; /* Size of this list element and its data */
ULONG ulId; /* If 0xFFFFFFFF, The real element follows */
/* Item data (or a contained SHLWAPI_CLIST) follows... */
} SHLWAPI_CLIST, *LPSHLWAPI_CLIST;
typedef const SHLWAPI_CLIST* LPCSHLWAPI_CLIST;
/* ulId for contained SHLWAPI_CLIST items */
#define CLIST_ID_CONTAINER (~0UL)
HRESULT WINAPI SHAddDataBlock(LPSHLWAPI_CLIST*,LPCSHLWAPI_CLIST);
/*************************************************************************
* NextItem
*
* Internal helper: move a DataBlock pointer to the next item.
*/
inline static LPSHLWAPI_CLIST NextItem(LPCSHLWAPI_CLIST lpList)
{
const char* address = (char*)lpList;
address += lpList->ulSize;
return (LPSHLWAPI_CLIST)address;
}
/*************************************************************************
* @ [SHLWAPI.17]
*
* Write a DataBlock list to an IStream object.
*
* PARAMS
* lpStream [I] IStream object to write the list to
* lpList [I] List of items to write
*
* RETURNS
* Success: S_OK. The object is written to the stream.
* Failure: An HRESULT error code
*
* NOTES
* Ordinals 17,18,19,20,21 and 22 are related and together provide a compact
* list structure (a "DataBlock List"), which may be stored and retrieved from
* an IStream object.
*
* The exposed API consists of:
*
* - SHWriteDataBlockList() - Write a DataBlock list to a stream,
* - SHReadDataBlockList() - Read and create a list from a stream,
* - SHFreeDataBlockList() - Free a list,
* - SHAddDataBlock() - Insert a new item into a list,
* - SHRemoveDataBlock() - Remove an item from a list,
* - SHFindDataBlock() - Find an item in a list.
*
* The DataBlock list is stored packed into a memory array. Each element has a
* size and an associated ID. Elements must be less than 64k if the list is
* to be subsequently read from a stream.
*
* Elements are aligned on DWORD boundaries. If an elements data size is not
* a DWORD size multiple, the element is wrapped by inserting a surrounding
* element with an Id of 0xFFFFFFFF, and size sufficient to pad to a DWORD boundary.
*
* These functions are slow for large objects and long lists.
*/
HRESULT WINAPI SHWriteDataBlockList(IStream* lpStream, LPSHLWAPI_CLIST lpList)
{
ULONG ulSize;
HRESULT hRet = E_FAIL;
TRACE("(%p,%p)\n", lpStream, lpList);
if(lpList)
{
while (lpList->ulSize)
{
LPSHLWAPI_CLIST lpItem = lpList;
if(lpList->ulId == CLIST_ID_CONTAINER)
lpItem++;
hRet = IStream_Write(lpStream,lpItem,lpItem->ulSize,&ulSize);
if (FAILED(hRet))
return hRet;
if(lpItem->ulSize != ulSize)
return STG_E_MEDIUMFULL;
lpList = NextItem(lpList);
}
}
if(SUCCEEDED(hRet))
{
ULONG ulDummy;
ulSize = 0;
/* Write a terminating list entry with zero size */
hRet = IStream_Write(lpStream, &ulSize,sizeof(ulSize),&ulDummy);
}
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.18]
*
* Read and create a DataBlock list from an IStream object.
*
* PARAMS
* lpStream [I] Stream to read the list from
* lppList [0] Pointer to receive the new List
*
* RETURNS
* Success: S_OK
* Failure: An HRESULT error code
*
* NOTES
* When read from a file, list objects are limited in size to 64k.
* See SHWriteDataBlockList.
*/
HRESULT WINAPI SHReadDataBlockList(IStream* lpStream, LPSHLWAPI_CLIST* lppList)
{
SHLWAPI_CLIST bBuff[128]; /* Temporary storage for new list item */
ULONG ulBuffSize = sizeof(bBuff);
LPSHLWAPI_CLIST pItem = bBuff;
ULONG ulRead, ulSize;
HRESULT hRet = S_OK;
TRACE("(%p,%p)\n", lpStream, lppList);
if(*lppList)
{
/* Free any existing list */
LocalFree((HLOCAL)*lppList);
*lppList = NULL;
}
do
{
/* Read the size of the next item */
hRet = IStream_Read(lpStream, &ulSize,sizeof(ulSize),&ulRead);
if(FAILED(hRet) || ulRead != sizeof(ulSize) || !ulSize)
break; /* Read failed or read zero size (the end of the list) */
if(ulSize > 0xFFFF)
{
LARGE_INTEGER liZero;
ULARGE_INTEGER ulPos;
liZero.QuadPart = 0;
/* Back the stream up; this object is too big for the list */
if(SUCCEEDED(IStream_Seek(lpStream, liZero, STREAM_SEEK_CUR, &ulPos)))
{
liZero.QuadPart = ulPos.QuadPart - sizeof(ULONG);
IStream_Seek(lpStream, liZero, STREAM_SEEK_SET, NULL);
}
break;
}
else if (ulSize >= sizeof(SHLWAPI_CLIST))
{
/* Add this new item to the list */
if(ulSize > ulBuffSize)
{
/* We need more buffer space, allocate it */
LPSHLWAPI_CLIST lpTemp;
if (pItem == bBuff)
lpTemp = (LPSHLWAPI_CLIST)LocalAlloc(LMEM_ZEROINIT, ulSize);
else
lpTemp = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)pItem, ulSize,
LMEM_ZEROINIT|LMEM_MOVEABLE);
if(!lpTemp)
{
hRet = E_OUTOFMEMORY;
break;
}
ulBuffSize = ulSize;
pItem = lpTemp;
}
pItem->ulSize = ulSize;
ulSize -= sizeof(pItem->ulSize); /* already read this member */
/* Read the item Id and data */
hRet = IStream_Read(lpStream, &pItem->ulId, ulSize, &ulRead);
if(FAILED(hRet) || ulRead != ulSize)
break;
SHAddDataBlock(lppList, pItem); /* Insert Item */
}
} while(1);
/* If we allocated space, free it */
if(pItem != bBuff)
LocalFree((HLOCAL)pItem);
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.19]
*
* Free a DataBlock list.
*
* PARAMS
* lpList [I] List to free
*
* RETURNS
* Nothing.
*
* NOTES
* See SHWriteDataBlockList.
*/
VOID WINAPI SHFreeDataBlockList(LPSHLWAPI_CLIST lpList)
{
TRACE("(%p)\n", lpList);
if (lpList)
LocalFree((HLOCAL)lpList);
}
/*************************************************************************
* @ [SHLWAPI.20]
*
* Insert a new item into a DataBlock list.
*
* PARAMS
* lppList [0] Pointer to the List
* lpNewItem [I] The new item to add to the list
*
* RETURNS
* Success: S_OK. The item is added to the list.
* Failure: An HRESULT error code.
*
* NOTES
* If the size of the element to be inserted is less than the size of a
* SHLWAPI_CLIST node, or the Id for the item is CLIST_ID_CONTAINER,
* the call returns S_OK but does not actually add the element.
* See SHWriteDataBlockList.
*/
HRESULT WINAPI SHAddDataBlock(LPSHLWAPI_CLIST* lppList, LPCSHLWAPI_CLIST lpNewItem)
{
LPSHLWAPI_CLIST lpInsertAt = NULL;
ULONG ulSize;
TRACE("(%p,%p)\n", lppList, lpNewItem);
if(!lppList || !lpNewItem )
return E_INVALIDARG;
if (lpNewItem->ulSize < sizeof(SHLWAPI_CLIST) ||
lpNewItem->ulId == CLIST_ID_CONTAINER)
return S_OK;
ulSize = lpNewItem->ulSize;
if(ulSize & 0x3)
{
/* Tune size to a ULONG boundary, add space for container element */
ulSize = ((ulSize + 0x3) & 0xFFFFFFFC) + sizeof(SHLWAPI_CLIST);
TRACE("Creating container item, new size = %ld\n", ulSize);
}
if(!*lppList)
{
/* An empty list. Allocate space for terminal ulSize also */
*lppList = (LPSHLWAPI_CLIST)LocalAlloc(LMEM_ZEROINIT,
ulSize + sizeof(ULONG));
lpInsertAt = *lppList;
}
else
{
/* Append to the end of the list */
ULONG ulTotalSize = 0;
LPSHLWAPI_CLIST lpIter = *lppList;
/* Iterate to the end of the list, calculating the total size */
while (lpIter->ulSize)
{
ulTotalSize += lpIter->ulSize;
lpIter = NextItem(lpIter);
}
/* Increase the size of the list */
lpIter = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)*lppList,
ulTotalSize + ulSize+sizeof(ULONG),
LMEM_ZEROINIT | LMEM_MOVEABLE);
if(lpIter)
{
*lppList = lpIter;
lpInsertAt = (LPSHLWAPI_CLIST)((char*)lpIter + ulTotalSize); /* At end */
}
}
if(lpInsertAt)
{
/* Copy in the new item */
LPSHLWAPI_CLIST lpDest = lpInsertAt;
if(ulSize != lpNewItem->ulSize)
{
lpInsertAt->ulSize = ulSize;
lpInsertAt->ulId = CLIST_ID_CONTAINER;
lpDest++;
}
memcpy(lpDest, lpNewItem, lpNewItem->ulSize);
/* Terminate the list */
lpInsertAt = NextItem(lpInsertAt);
lpInsertAt->ulSize = 0;
return lpNewItem->ulSize;
}
return S_OK;
}
/*************************************************************************
* @ [SHLWAPI.21]
*
* Remove an item from a DataBlock list.
*
* PARAMS
* lppList [O] List to remove the item from
* ulId [I] Id of item to remove
*
* RETURNS
* Success: TRUE.
* Failure: FALSE, If any parameters are invalid, or the item was not found.
*
* NOTES
* See SHWriteDataBlockList.
*/
BOOL WINAPI SHRemoveDataBlock(LPSHLWAPI_CLIST* lppList, ULONG ulId)
{
LPSHLWAPI_CLIST lpList = 0;
LPSHLWAPI_CLIST lpItem = NULL;
LPSHLWAPI_CLIST lpNext;
ULONG ulNewSize;
TRACE("(%p,%ld)\n", lppList, ulId);
if(lppList && (lpList = *lppList))
{
/* Search for item in list */
while (lpList->ulSize)
{
if(lpList->ulId == ulId ||
(lpList->ulId == CLIST_ID_CONTAINER && lpList[1].ulId == ulId))
{
lpItem = lpList; /* Found */
break;
}
lpList = NextItem(lpList);
}
}
if(!lpItem)
return FALSE;
lpList = lpNext = NextItem(lpItem);
/* Locate the end of the list */
while (lpList->ulSize)
lpList = NextItem(lpList);
/* Resize the list */
ulNewSize = LocalSize((HLOCAL)*lppList) - lpItem->ulSize;
/* Copy following elements over lpItem */
memmove(lpItem, lpNext, (char *)lpList - (char *)lpNext + sizeof(ULONG));
if(ulNewSize <= sizeof(ULONG))
{
LocalFree((HLOCAL)*lppList);
*lppList = NULL; /* Removed the last element */
}
else
{
lpList = (LPSHLWAPI_CLIST)LocalReAlloc((HLOCAL)*lppList, ulNewSize,
LMEM_ZEROINIT|LMEM_MOVEABLE);
if(lpList)
*lppList = lpList;
}
return TRUE;
}
/*************************************************************************
* @ [SHLWAPI.22]
*
* Find an item in a DataBlock list.
*
* PARAMS
* lpList [I] List to search
* ulId [I] Id of item to find
*
* RETURNS
* Success: A pointer to the list item found
* Failure: NULL
*
* NOTES
* See SHWriteDataBlockList.
*/
LPSHLWAPI_CLIST WINAPI SHFindDataBlock(LPSHLWAPI_CLIST lpList, ULONG ulId)
{
TRACE("(%p,%ld)\n", lpList, ulId);
if(lpList)
{
while(lpList->ulSize)
{
if(lpList->ulId == ulId)
return lpList; /* Matched */
else if(lpList->ulId == CLIST_ID_CONTAINER && lpList[1].ulId == ulId)
return lpList + 1; /* Contained item matches */
lpList = NextItem(lpList);
}
}
return NULL;
}

View file

@ -0,0 +1,683 @@
/*
* SHLWAPI IStream functions
*
* Copyright 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#ifdef __REACTOS__
#include "wine/icom.h"
#endif
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "winnls.h"
#define NO_SHLWAPI_REG
#define NO_SHLWAPI_PATH
#include "shlwapi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* Layout of ISHFileStream object */
typedef struct
{
ICOM_VFIELD(IStream);
ULONG ref;
HANDLE hFile;
DWORD dwMode;
LPOLESTR lpszPath;
DWORD type;
DWORD grfStateBits;
} ISHFileStream;
static HRESULT WINAPI IStream_fnCommit(IStream*,DWORD);
/**************************************************************************
* IStream_fnQueryInterface
*/
static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
{
ICOM_THIS(ISHFileStream, iface);
TRACE("(%p,%s,%p)\n", This, debugstr_guid(riid), ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IStream))
{
*ppvObj = This;
IStream_AddRef((IStream*)*ppvObj);
return S_OK;
}
return E_NOINTERFACE;
}
/**************************************************************************
* IStream_fnAddRef
*/
static ULONG WINAPI IStream_fnAddRef(IStream *iface)
{
ICOM_THIS(ISHFileStream, iface);
TRACE("(%p)\n", This);
return InterlockedIncrement(&This->ref);
}
/**************************************************************************
* IStream_fnRelease
*/
static ULONG WINAPI IStream_fnRelease(IStream *iface)
{
ICOM_THIS(ISHFileStream, iface);
ULONG ulRet;
TRACE("(%p)\n", This);
if (!(ulRet = InterlockedDecrement(&This->ref)))
{
IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */
LocalFree((HLOCAL)This->lpszPath);
CloseHandle(This->hFile);
HeapFree(GetProcessHeap(), 0, This);
}
return ulRet;
}
/**************************************************************************
* IStream_fnRead
*/
static HRESULT WINAPI IStream_fnRead(IStream *iface, void* pv, ULONG cb, ULONG* pcbRead)
{
ICOM_THIS(ISHFileStream, iface);
HRESULT hRet = S_OK;
DWORD dwRead = 0;
TRACE("(%p,%p,0x%08lx,%p)\n", This, pv, cb, pcbRead);
if (!pv)
hRet = STG_E_INVALIDPOINTER;
else if (!ReadFile(This->hFile, pv, cb, &dwRead, NULL))
{
hRet = (HRESULT)GetLastError();
if(hRet > 0)
hRet = HRESULT_FROM_WIN32(hRet);
}
if (pcbRead)
*pcbRead = dwRead;
return hRet;
}
/**************************************************************************
* IStream_fnWrite
*/
static HRESULT WINAPI IStream_fnWrite(IStream *iface, const void* pv, ULONG cb, ULONG* pcbWritten)
{
ICOM_THIS(ISHFileStream, iface);
HRESULT hRet = S_OK;
DWORD dwWritten = 0;
TRACE("(%p,%p,0x%08lx,%p)\n", This, pv, cb, pcbWritten);
if (!pv)
hRet = STG_E_INVALIDPOINTER;
else if (!(This->dwMode & STGM_WRITE))
hRet = E_FAIL;
else if (!WriteFile(This->hFile, pv, cb, &dwWritten, NULL))
{
hRet = (HRESULT)GetLastError();
if(hRet > 0)
hRet = HRESULT_FROM_WIN32(hRet);
}
if (pcbWritten)
*pcbWritten = dwWritten;
return hRet;
}
/**************************************************************************
* IStream_fnSeek
*/
static HRESULT WINAPI IStream_fnSeek(IStream *iface, LARGE_INTEGER dlibMove,
DWORD dwOrigin, ULARGE_INTEGER* pNewPos)
{
ICOM_THIS(ISHFileStream, iface);
DWORD dwPos;
TRACE("(%p,%ld,%ld,%p)\n", This, dlibMove.u.LowPart, dwOrigin, pNewPos);
IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */
dwPos = SetFilePointer(This->hFile, dlibMove.u.LowPart, NULL, dwOrigin);
if (pNewPos)
{
pNewPos->u.HighPart = 0;
pNewPos->u.LowPart = dwPos;
}
return S_OK;
}
/**************************************************************************
* IStream_fnSetSize
*/
static HRESULT WINAPI IStream_fnSetSize(IStream *iface, ULARGE_INTEGER libNewSize)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p,%ld)\n", This, libNewSize.s.LowPart);
IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnCopyTo
*/
static HRESULT WINAPI IStream_fnCopyTo(IStream *iface, IStream* pstm, ULARGE_INTEGER cb,
ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
char copyBuff[1024];
ULONGLONG ulSize;
HRESULT hRet = S_OK;
TRACE("(%p,%p,%ld,%p,%p)\n", This, pstm, cb.s.LowPart, pcbRead, pcbWritten);
if (pcbRead)
pcbRead->QuadPart = 0;
if (pcbWritten)
pcbWritten->QuadPart = 0;
if (!pstm)
return STG_E_INVALIDPOINTER;
IStream_fnCommit(iface, 0); /* If ever buffered, this will be needed */
/* Copy data */
ulSize = cb.QuadPart;
while (ulSize)
{
ULONG ulLeft, ulAmt;
ulLeft = ulSize > sizeof(copyBuff) ? sizeof(copyBuff) : ulSize;
/* Read */
hRet = IStream_fnRead(iface, copyBuff, ulLeft, &ulAmt);
if (pcbRead)
pcbRead->QuadPart += ulAmt;
if (FAILED(hRet) || ulAmt != ulLeft)
break;
/* Write */
hRet = IStream_fnWrite(pstm, copyBuff, ulLeft, &ulAmt);
if (pcbWritten)
pcbWritten->QuadPart += ulAmt;
if (FAILED(hRet) || ulAmt != ulLeft)
break;
ulSize -= ulLeft;
}
return hRet;
}
/**************************************************************************
* IStream_fnCommit
*/
static HRESULT WINAPI IStream_fnCommit(IStream *iface, DWORD grfCommitFlags)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p,%ld)\n", This, grfCommitFlags);
/* Currently unbuffered: This function is not needed */
return S_OK;
}
/**************************************************************************
* IStream_fnRevert
*/
static HRESULT WINAPI IStream_fnRevert(IStream *iface)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p)\n", This);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnLockUnlockRegion
*/
static HRESULT WINAPI IStream_fnLockUnlockRegion(IStream *iface, ULARGE_INTEGER libOffset,
ULARGE_INTEGER cb, DWORD dwLockType)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p,%ld,%ld,%ld)\n", This, libOffset.s.LowPart, cb.s.LowPart, dwLockType);
return E_NOTIMPL;
}
/*************************************************************************
* IStream_fnStat
*/
static HRESULT WINAPI IStream_fnStat(IStream *iface, STATSTG* lpStat,
DWORD grfStatFlag)
{
ICOM_THIS(ISHFileStream, iface);
BY_HANDLE_FILE_INFORMATION fi;
HRESULT hRet = S_OK;
TRACE("(%p,%p,%ld)\n", This, lpStat, grfStatFlag);
if (!grfStatFlag)
hRet = STG_E_INVALIDPOINTER;
else
{
memset(&fi, 0, sizeof(fi));
GetFileInformationByHandle(This->hFile, &fi);
if (grfStatFlag & STATFLAG_NONAME)
lpStat->pwcsName = NULL;
else
lpStat->pwcsName = StrDupW(This->lpszPath);
lpStat->type = This->type;
lpStat->cbSize.u.LowPart = fi.nFileSizeLow;
lpStat->cbSize.u.HighPart = fi.nFileSizeHigh;
lpStat->mtime = fi.ftLastWriteTime;
lpStat->ctime = fi.ftCreationTime;
lpStat->atime = fi.ftLastAccessTime;
lpStat->grfMode = This->dwMode;
lpStat->grfLocksSupported = 0;
memcpy(&lpStat->clsid, &IID_IStream, sizeof(CLSID));
lpStat->grfStateBits = This->grfStateBits;
lpStat->reserved = 0;
}
return hRet;
}
/*************************************************************************
* IStream_fnClone
*/
static HRESULT WINAPI IStream_fnClone(IStream *iface, IStream** ppstm)
{
#ifndef NDEBUG
ICOM_THIS(ISHFileStream, iface);
#endif
TRACE("(%p)\n",This);
if (ppstm)
*ppstm = NULL;
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IStream) SHLWAPI_fsVTable =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IStream_fnQueryInterface,
IStream_fnAddRef,
IStream_fnRelease,
IStream_fnRead,
IStream_fnWrite,
IStream_fnSeek,
IStream_fnSetSize,
IStream_fnCopyTo,
IStream_fnCommit,
IStream_fnRevert,
IStream_fnLockUnlockRegion,
IStream_fnLockUnlockRegion,
IStream_fnStat,
IStream_fnClone
};
/**************************************************************************
* IStream_Create
*
* Internal helper: Create and initialise a new file stream object.
*/
static IStream *IStream_Create(LPCWSTR lpszPath, HANDLE hFile, DWORD dwMode)
{
ISHFileStream* fileStream;
fileStream = (ISHFileStream*)HeapAlloc(GetProcessHeap(), 0, sizeof(ISHFileStream));
if (fileStream)
{
fileStream->lpVtbl = &SHLWAPI_fsVTable;
fileStream->ref = 1;
fileStream->hFile = hFile;
fileStream->dwMode = dwMode;
fileStream->lpszPath = StrDupW(lpszPath);
fileStream->type = 0; /* FIXME */
fileStream->grfStateBits = 0; /* FIXME */
}
TRACE ("Returning %p\n", fileStream);
return (IStream *)fileStream;
}
/*************************************************************************
* SHCreateStreamOnFileEx [SHLWAPI.@]
*
* Create a stream on a file.
*
* PARAMS
* lpszPath [I] Path of file to create stream on
* dwMode [I] Mode to create stream in
* dwAttributes [I] Attributes of the file
* bCreate [I] Whether to create the file if it doesn't exist
* lpTemplate [I] Reserved, must be NULL
* lppStream [O] Destination for created stream
*
* RETURNS
* Success: S_OK. lppStream contains the new stream object
* Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
*
* NOTES
* This function is available in Unicode only.
*/
HRESULT WINAPI SHCreateStreamOnFileEx(LPCWSTR lpszPath, DWORD dwMode,
DWORD dwAttributes, BOOL bCreate,
IStream *lpTemplate, IStream **lppStream)
{
DWORD dwAccess, dwShare, dwCreate;
HANDLE hFile;
TRACE("(%s,%ld,0x%08lX,%d,%p,%p)\n", debugstr_w(lpszPath), dwMode,
dwAttributes, bCreate, lpTemplate, lppStream);
if (!lpszPath || !lppStream || lpTemplate)
return E_INVALIDARG;
*lppStream = NULL;
if (dwMode & ~(STGM_WRITE|STGM_READWRITE|STGM_SHARE_DENY_NONE|STGM_SHARE_DENY_READ|STGM_CREATE))
{
WARN("Invalid mode 0x%08lX\n", dwMode);
return E_INVALIDARG;
}
/* Access */
switch (dwMode & (STGM_WRITE|STGM_READWRITE))
{
case STGM_READWRITE|STGM_WRITE:
case STGM_READWRITE:
dwAccess = GENERIC_READ|GENERIC_WRITE;
break;
case STGM_WRITE:
dwAccess = GENERIC_WRITE;
break;
default:
dwAccess = GENERIC_READ;
break;
}
/* Sharing */
switch (dwMode & STGM_SHARE_DENY_READ)
{
case STGM_SHARE_DENY_READ:
dwShare = FILE_SHARE_WRITE;
break;
case STGM_SHARE_DENY_WRITE:
dwShare = FILE_SHARE_READ;
break;
case STGM_SHARE_EXCLUSIVE:
dwShare = 0;
break;
default:
dwShare = FILE_SHARE_READ|FILE_SHARE_WRITE;
}
/* FIXME: Creation Flags, MSDN is fuzzy on the mapping... */
if (dwMode == STGM_FAILIFTHERE)
dwCreate = bCreate ? CREATE_NEW : OPEN_EXISTING;
else if (dwMode & STGM_CREATE)
dwCreate = CREATE_ALWAYS;
else
dwCreate = OPEN_ALWAYS;
/* Open HANDLE to file */
hFile = CreateFileW(lpszPath, dwAccess, dwShare, NULL, dwCreate,
dwAttributes, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
HRESULT hRet = (HRESULT)GetLastError();
if(hRet > 0)
hRet = HRESULT_FROM_WIN32(hRet);
return hRet;
}
*lppStream = IStream_Create(lpszPath, hFile, dwMode);
if(!*lppStream)
{
CloseHandle(hFile);
return E_OUTOFMEMORY;
}
return S_OK;
}
/*************************************************************************
* SHCreateStreamOnFileW [SHLWAPI.@]
*
* See SHCreateStreamOnFileA.
*/
HRESULT WINAPI SHCreateStreamOnFileW(LPCWSTR lpszPath, DWORD dwMode,
IStream **lppStream)
{
DWORD dwAttr;
TRACE("(%s,%ld,%p)\n", debugstr_w(lpszPath), dwMode, lppStream);
if (!lpszPath || !lppStream)
return E_INVALIDARG;
dwAttr = GetFileAttributesW(lpszPath);
if (dwAttr == INVALID_FILE_ATTRIBUTES)
dwAttr = 0;
return SHCreateStreamOnFileEx(lpszPath, dwMode|STGM_WRITE, dwAttr,
TRUE, NULL, lppStream);
}
/*************************************************************************
* SHCreateStreamOnFileA [SHLWAPI.@]
*
* Create a stream on a file.
*
* PARAMS
* lpszPath [I] Path of file to create stream on
* dwMode [I] Mode to create stream in
* lppStream [O] Destination for created IStream object
*
* RETURNS
* Success: S_OK. lppStream contains the new IStream object
* Failure: E_INVALIDARG if any parameter is invalid, or an HRESULT error code
*/
HRESULT WINAPI SHCreateStreamOnFileA(LPCSTR lpszPath, DWORD dwMode,
IStream **lppStream)
{
WCHAR szPath[MAX_PATH];
TRACE("(%s,%ld,%p)\n", debugstr_a(lpszPath), dwMode, lppStream);
if (!lpszPath)
return E_INVALIDARG;
MultiByteToWideChar(0, 0, lpszPath, -1, szPath, MAX_PATH);
return SHCreateStreamOnFileW(szPath, dwMode, lppStream);
}
/*************************************************************************
* @ [SHLWAPI.184]
*
* Call IStream_Read() on a stream.
*
* PARAMS
* lpStream [I] IStream object
* lpvDest [O] Destination for data read
* ulSize [I] Size of data to read
*
* RETURNS
* Success: S_OK. ulSize bytes have been read from the stream into lpvDest.
* Failure: An HRESULT error code, or E_FAIL if the read succeeded but the
* number of bytes read does not match.
*/
HRESULT WINAPI SHLWAPI_184(IStream *lpStream, LPVOID lpvDest, ULONG ulSize)
{
ULONG ulRead;
HRESULT hRet;
TRACE("(%p,%p,%ld)\n", lpStream, lpvDest, ulSize);
hRet = IStream_Read(lpStream, lpvDest, ulSize, &ulRead);
if (SUCCEEDED(hRet) && ulRead != ulSize)
hRet = E_FAIL;
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.166]
*
* Determine if a stream has 0 length.
*
* PARAMS
* lpStream [I] IStream object
*
* RETURNS
* TRUE: If the stream has 0 length
* FALSE: Otherwise.
*/
BOOL WINAPI SHIsEmptyStream(IStream *lpStream)
{
STATSTG statstg;
BOOL bRet = TRUE;
TRACE("(%p)\n", lpStream);
memset(&statstg, 0, sizeof(statstg));
if(SUCCEEDED(IStream_Stat(lpStream, &statstg, 1)))
{
if(statstg.cbSize.QuadPart)
bRet = FALSE; /* Non-Zero */
}
else
{
DWORD dwDummy;
/* Try to read from the stream */
if(SUCCEEDED(SHLWAPI_184(lpStream, &dwDummy, sizeof(dwDummy))))
{
LARGE_INTEGER zero;
zero.QuadPart = 0;
IStream_Seek(lpStream, zero, 0, NULL);
bRet = FALSE; /* Non-Zero */
}
}
return bRet;
}
/*************************************************************************
* @ [SHLWAPI.212]
*
* Call IStream_Write() on a stream.
*
* PARAMS
* lpStream [I] IStream object
* lpvSrc [I] Source for data to write
* ulSize [I] Size of data
*
* RETURNS
* Success: S_OK. ulSize bytes have been written to the stream from lpvSrc.
* Failure: An HRESULT error code, or E_FAIL if the write succeeded but the
* number of bytes written does not match.
*/
HRESULT WINAPI SHLWAPI_212(IStream *lpStream, LPCVOID lpvSrc, ULONG ulSize)
{
ULONG ulWritten;
HRESULT hRet;
TRACE("(%p,%p,%ld)\n", lpStream, lpvSrc, ulSize);
hRet = IStream_Write(lpStream, lpvSrc, ulSize, &ulWritten);
if (SUCCEEDED(hRet) && ulWritten != ulSize)
hRet = E_FAIL;
return hRet;
}
/*************************************************************************
* @ [SHLWAPI.213]
*
* Seek to the start of a stream.
*
* PARAMS
* lpStream [I] IStream object
*
* RETURNS
* Success: S_OK. The current position within the stream is updated
* Failure: An HRESULT error code.
*/
HRESULT WINAPI IStream_Reset(IStream *lpStream)
{
LARGE_INTEGER zero;
TRACE("(%p)\n", lpStream);
zero.QuadPart = 0;
return IStream_Seek(lpStream, zero, 0, NULL);
}
/*************************************************************************
* @ [SHLWAPI.214]
*
* Get the size of a stream.
*
* PARAMS
* lpStream [I] IStream object
* lpulSize [O] Destination for size
*
* RETURNS
* Success: S_OK. lpulSize contains the size of the stream.
* Failure: An HRESULT error code.
*/
HRESULT WINAPI IStream_Size(IStream *lpStream, ULARGE_INTEGER* lpulSize)
{
STATSTG statstg;
HRESULT hRet;
TRACE("(%p,%p)\n", lpStream, lpulSize);
memset(&statstg, 0, sizeof(statstg));
hRet = IStream_Stat(lpStream, &statstg, 1);
if (SUCCEEDED(hRet) && lpulSize)
*lpulSize = statstg.cbSize;
return hRet;
}

View file

@ -0,0 +1,66 @@
PATH_TO_TOP = ../..
TARGET_TYPE = dynlink
TARGET_NAME = shlwapi
TARGET_CFLAGS = \
-Wall \
-fno-builtin
# Compile definitions usage:
# __USE_W32API - Compilation with w32api headers
# __REACTOS__ - Compilation of Wine sources for ReactOS
# _WIN32_IE=0x600 - Internet Explorer 6 compatible defintions
# WINVER=0x501 - Windows XP definitions
# __need_offsetof - Force definition of macro offsetof in stddef.h
#
DEFINES = \
-D_DISABLE_TIDENTS \
-D__USE_W32API \
-D__REACTOS__ \
-D_WIN32_IE=0x600 \
-D_WIN32_WINNT=0x501 \
-DWINVER=0x501 \
-DCOBJMACROS \
-D__need_offsetof
TARGET_CFLAGS += \
$(DEFINES) \
-I$(PATH_TO_TOP)/include/wine
TARGET_RCFLAGS += -D__REACTOS__ -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x501
TARGET_LFLAGS = -nostartfiles -nostdlib
TARGET_SDKLIBS = libwine.a
TARGET_BASE = 0x76120000
TARGET_NORC = yes
TARGET_DEFONLY = yes
TARGET_OBJECTS = \
assoc.o \
clist.o \
istream.o \
path.o \
reg.o \
regstream.o \
shlwapi_main.o \
string.o \
thread.o \
url.o \
wsprintf.o \
ordinal.o
DEP_OBJECTS = $(TARGET_OBJECTS)
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
include $(TOOLS_PATH)/config.mk
# include $(TOOLS_PATH)/depend.mk

File diff suppressed because it is too large Load diff

3902
reactos/lib/shlwapi/path.c Normal file

File diff suppressed because it is too large Load diff

2196
reactos/lib/shlwapi/reg.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,573 @@
/*
* SHLWAPI Registry Stream functions
*
* Copyright 1999 Juergen Schmied
* Copyright 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#ifdef __REACTOS__
#include "wine/icom.h"
#endif
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "winreg.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
typedef struct
{ ICOM_VFIELD(IStream);
DWORD ref;
HKEY hKey;
LPBYTE pbBuffer;
DWORD dwLength;
DWORD dwPos;
} ISHRegStream;
/**************************************************************************
* IStream_fnQueryInterface
*/
static HRESULT WINAPI IStream_fnQueryInterface(IStream *iface, REFIID riid, LPVOID *ppvObj)
{
ICOM_THIS(ISHRegStream, iface);
TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
*ppvObj = NULL;
if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
*ppvObj = This;
else if(IsEqualIID(riid, &IID_IStream)) /*IStream*/
*ppvObj = This;
if(*ppvObj)
{
IStream_AddRef((IStream*)*ppvObj);
TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
return S_OK;
}
TRACE("-- Interface: E_NOINTERFACE\n");
return E_NOINTERFACE;
}
/**************************************************************************
* IStream_fnAddRef
*/
static ULONG WINAPI IStream_fnAddRef(IStream *iface)
{
ICOM_THIS(ISHRegStream, iface);
TRACE("(%p)->(count=%lu)\n",This, This->ref);
return InterlockedIncrement(&This->ref);
}
/**************************************************************************
* IStream_fnRelease
*/
static ULONG WINAPI IStream_fnRelease(IStream *iface)
{
ICOM_THIS(ISHRegStream, iface);
TRACE("(%p)->()\n",This);
if (!InterlockedDecrement(&This->ref))
{
TRACE(" destroying SHReg IStream (%p)\n",This);
if (This->pbBuffer)
HeapFree(GetProcessHeap(),0,This->pbBuffer);
if (This->hKey)
RegCloseKey(This->hKey);
HeapFree(GetProcessHeap(),0,This);
return 0;
}
return This->ref;
}
/**************************************************************************
* IStream_fnRead
*/
static HRESULT WINAPI IStream_fnRead (IStream * iface, void* pv, ULONG cb, ULONG* pcbRead)
{
ICOM_THIS(ISHRegStream, iface);
DWORD dwBytesToRead, dwBytesLeft;
TRACE("(%p)->(%p,0x%08lx,%p)\n",This, pv, cb, pcbRead);
if (!pv)
return STG_E_INVALIDPOINTER;
dwBytesLeft = This->dwLength - This->dwPos;
if ( 0 >= dwBytesLeft ) /* end of buffer */
return S_FALSE;
dwBytesToRead = ( cb > dwBytesLeft) ? dwBytesLeft : cb;
memmove ( pv, (This->pbBuffer) + (This->dwPos), dwBytesToRead);
This->dwPos += dwBytesToRead; /* adjust pointer */
if (pcbRead)
*pcbRead = dwBytesToRead;
return S_OK;
}
/**************************************************************************
* IStream_fnWrite
*/
static HRESULT WINAPI IStream_fnWrite (IStream * iface, const void* pv, ULONG cb, ULONG* pcbWritten)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
if (pcbWritten)
*pcbWritten = 0;
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnSeek
*/
static HRESULT WINAPI IStream_fnSeek (IStream * iface, LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER* plibNewPosition)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
if (plibNewPosition)
plibNewPosition->QuadPart = 0;
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnSetSize
*/
static HRESULT WINAPI IStream_fnSetSize (IStream * iface, ULARGE_INTEGER libNewSize)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnCopyTo
*/
static HRESULT WINAPI IStream_fnCopyTo (IStream * iface, IStream* pstm, ULARGE_INTEGER cb, ULARGE_INTEGER* pcbRead, ULARGE_INTEGER* pcbWritten)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
if (pcbRead)
pcbRead->QuadPart = 0;
if (pcbWritten)
pcbWritten->QuadPart = 0;
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnCommit
*/
static HRESULT WINAPI IStream_fnCommit (IStream * iface, DWORD grfCommitFlags)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnRevert
*/
static HRESULT WINAPI IStream_fnRevert (IStream * iface)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
/**************************************************************************
* IStream_fnLockUnlockRegion
*/
static HRESULT WINAPI IStream_fnLockUnlockRegion (IStream * iface, ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
/*************************************************************************
* IStream_fnStat
*/
static HRESULT WINAPI IStream_fnStat (IStream * iface, STATSTG* pstatstg, DWORD grfStatFlag)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
return E_NOTIMPL;
}
/*************************************************************************
* IStream_fnClone
*/
static HRESULT WINAPI IStream_fnClone (IStream * iface, IStream** ppstm)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n",This);
if (ppstm)
*ppstm = NULL;
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IStream) rstvt =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IStream_fnQueryInterface,
IStream_fnAddRef,
IStream_fnRelease,
IStream_fnRead,
IStream_fnWrite,
IStream_fnSeek,
IStream_fnSetSize,
IStream_fnCopyTo,
IStream_fnCommit,
IStream_fnRevert,
IStream_fnLockUnlockRegion,
IStream_fnLockUnlockRegion,
IStream_fnStat,
IStream_fnClone
};
/* Methods overridden by the dummy stream */
/**************************************************************************
* IStream_fnAddRefDummy
*/
static ULONG WINAPI IStream_fnAddRefDummy(IStream *iface)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n", This);
return 2;
}
/**************************************************************************
* IStream_fnReleaseDummy
*/
static ULONG WINAPI IStream_fnReleaseDummy(IStream *iface)
{
#ifndef NDEBUG
ICOM_THIS(ISHRegStream, iface);
#endif
TRACE("(%p)\n", This);
return 1;
}
/**************************************************************************
* IStream_fnReadDummy
*/
static HRESULT WINAPI IStream_fnReadDummy(IStream *iface, LPVOID pv, ULONG cb, ULONG* pcbRead)
{
if (pcbRead)
*pcbRead = 0;
return E_NOTIMPL;
}
static struct ICOM_VTABLE(IStream) DummyRegStreamVTable =
{
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
IStream_fnQueryInterface,
IStream_fnAddRefDummy, /* Overridden */
IStream_fnReleaseDummy, /* Overridden */
IStream_fnReadDummy, /* Overridden */
IStream_fnWrite,
IStream_fnSeek,
IStream_fnSetSize,
IStream_fnCopyTo,
IStream_fnCommit,
IStream_fnRevert,
IStream_fnLockUnlockRegion,
IStream_fnLockUnlockRegion,
IStream_fnStat,
IStream_fnClone
};
/* Dummy registry stream object */
static ISHRegStream rsDummyRegStream =
{
&DummyRegStreamVTable,
1,
NULL,
NULL,
0,
0
};
/**************************************************************************
* IStream_Create
*
* Internal helper: Create and initialise a new registry stream object.
*/
static IStream *IStream_Create(HKEY hKey, LPBYTE pbBuffer, DWORD dwLength)
{
ISHRegStream* regStream;
regStream = (ISHRegStream*)HeapAlloc(GetProcessHeap(), 0, sizeof(ISHRegStream));
if (regStream)
{
regStream->lpVtbl = &rstvt;
regStream->ref = 1;
regStream->hKey = hKey;
regStream->pbBuffer = pbBuffer;
regStream->dwLength = dwLength;
regStream->dwPos = 0;
}
TRACE ("Returning %p\n", regStream);
return (IStream *)regStream;
}
/*************************************************************************
* SHOpenRegStream2A [SHLWAPI.@]
*
* Create a stream to read binary registry data.
*
* PARAMS
* hKey [I] Registry handle
* pszSubkey [I] The sub key name
* pszValue [I] The value name under the sub key
* dwMode [I] Unused
*
* RETURNS
* Success: An IStream interface referring to the registry data
* Failure: NULL, if the registry key could not be opened or is not binary.
*/
IStream * WINAPI SHOpenRegStream2A(HKEY hKey, LPCSTR pszSubkey,
LPCSTR pszValue,DWORD dwMode)
{
HKEY hStrKey = NULL;
LPBYTE lpBuff = NULL;
DWORD dwLength, dwType;
TRACE("(%p,%s,%s,0x%08lx)\n", hKey, pszSubkey, pszValue, dwMode);
/* Open the key, read in binary data and create stream */
if (!RegOpenKeyExA (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&
!RegQueryValueExA (hStrKey, pszValue, 0, 0, 0, &dwLength) &&
(lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&
!RegQueryValueExA (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&
dwType == REG_BINARY)
return IStream_Create(hStrKey, lpBuff, dwLength);
if (lpBuff)
HeapFree (GetProcessHeap(), 0, lpBuff);
if (hStrKey)
RegCloseKey(hStrKey);
return NULL;
}
/*************************************************************************
* SHOpenRegStream2W [SHLWAPI.@]
*
* See SHOpenRegStream2A.
*/
IStream * WINAPI SHOpenRegStream2W(HKEY hKey, LPCWSTR pszSubkey,
LPCWSTR pszValue, DWORD dwMode)
{
HKEY hStrKey = NULL;
LPBYTE lpBuff = NULL;
DWORD dwLength, dwType;
TRACE("(%p,%s,%s,0x%08lx)\n", hKey, debugstr_w(pszSubkey),
debugstr_w(pszValue), dwMode);
/* Open the key, read in binary data and create stream */
if (!RegOpenKeyExW (hKey, pszSubkey, 0, KEY_READ, &hStrKey) &&
!RegQueryValueExW (hStrKey, pszValue, 0, 0, 0, &dwLength) &&
(lpBuff = HeapAlloc (GetProcessHeap(), 0, dwLength)) &&
!RegQueryValueExW (hStrKey, pszValue, 0, &dwType, lpBuff, &dwLength) &&
dwType == REG_BINARY)
return IStream_Create(hStrKey, lpBuff, dwLength);
if (lpBuff)
HeapFree (GetProcessHeap(), 0, lpBuff);
if (hStrKey)
RegCloseKey(hStrKey);
return NULL;
}
/*************************************************************************
* SHOpenRegStreamA [SHLWAPI.@]
*
* Create a stream to read binary registry data.
*
* PARAMS
* hKey [I] Registry handle
* pszSubkey [I] The sub key name
* pszValue [I] The value name under the sub key
* dwMode [I] STGM mode for opening the file
*
* RETURNS
* Success: An IStream interface referring to the registry data
* Failure: If the registry key could not be opened or is not binary,
* A dummy (empty) IStream object is returned.
*/
IStream * WINAPI SHOpenRegStreamA(HKEY hkey, LPCSTR pszSubkey,
LPCSTR pszValue, DWORD dwMode)
{
IStream *iStream;
TRACE("(%p,%s,%s,0x%08lx)\n", hkey, pszSubkey, pszValue, dwMode);
iStream = SHOpenRegStream2A(hkey, pszSubkey, pszValue, dwMode);
return iStream ? iStream : (IStream *)&rsDummyRegStream;
}
/*************************************************************************
* SHOpenRegStreamW [SHLWAPI.@]
*
* See SHOpenRegStreamA.
*/
IStream * WINAPI SHOpenRegStreamW(HKEY hkey, LPCWSTR pszSubkey,
LPCWSTR pszValue, DWORD dwMode)
{
IStream *iStream;
TRACE("(%p,%s,%s,0x%08lx)\n", hkey, debugstr_w(pszSubkey),
debugstr_w(pszValue), dwMode);
iStream = SHOpenRegStream2W(hkey, pszSubkey, pszValue, dwMode);
return iStream ? iStream : (IStream *)&rsDummyRegStream;
}
/*************************************************************************
* @ [SHLWAPI.12]
*
* Create an IStream object on a block of memory.
*
* PARAMS
* lpbData [I] Memory block to create the IStream object on
* dwDataLen [I] Length of data block
*
* RETURNS
* Success: A pointer to the IStream object.
* Failure: NULL, if any parameters are invalid or an error occurs.
*
* NOTES
* A copy of the memory pointed to by lpbData is made, and is freed
* when the stream is released.
*/
IStream * WINAPI SHCreateMemStream(LPBYTE lpbData, DWORD dwDataLen)
{
IStream *iStrmRet = NULL;
TRACE("(%p,%ld)\n", lpbData, dwDataLen);
if (lpbData)
{
LPBYTE lpbDup = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, dwDataLen);
if (lpbDup)
{
memcpy(lpbDup, lpbData, dwDataLen);
iStrmRet = IStream_Create(NULL, lpbDup, dwDataLen);
if (!iStrmRet)
HeapFree(GetProcessHeap(), 0, lpbDup);
}
}
return iStrmRet;
}
/*************************************************************************
* SHCreateStreamWrapper [SHLWAPI.@]
*
* Create an IStream object on a block of memory.
*
* PARAMS
* lpbData [I] Memory block to create the IStream object on
* dwDataLen [I] Length of data block
* dwReserved [I] Reserved, Must be 0.
* lppStream [O] Destination for IStream object
*
* RETURNS
* Success: S_OK. lppStream contains the new IStream object.
* Failure: E_INVALIDARG, if any parameters are invalid,
* E_OUTOFMEMORY if memory allocation fails.
*
* NOTES
* The stream assumes ownership of the memory passed to it.
*/
HRESULT WINAPI SHCreateStreamWrapper(LPBYTE lpbData, DWORD dwDataLen,
DWORD dwReserved, IStream **lppStream)
{
IStream* lpStream;
if (lppStream)
*lppStream = NULL;
if(dwReserved || !lppStream)
return E_INVALIDARG;
lpStream = IStream_Create(NULL, lpbData, dwDataLen);
if(!lpStream)
return E_OUTOFMEMORY;
IStream_QueryInterface(lpStream, &IID_IStream, (void**)lppStream);
IStream_Release(lpStream);
return S_OK;
}

View file

@ -0,0 +1,459 @@
; File generated automatically from shlwapi/shlwapi.spec; do not edit!
LIBRARY shlwapi.dll
EXPORTS
ParseURLA@8 @1 NONAME
ParseURLW@8 @2 NONAME
PathFileExistsDefExtA@8 @3 NONAME
PathFileExistsDefExtW@8 @4 NONAME
PathFindOnPathExA@12 @5 NONAME
PathFindOnPathExW@12 @6 NONAME
SHAllocShared@12 @7 NONAME
SHLockShared@8 @8 NONAME
SHUnlockShared@4 @9 NONAME
SHFreeShared@8 @10 NONAME
SHMapHandle@20 @11 NONAME
SHCreateMemStream@8 @12 NONAME
RegisterDefaultAcceptHeaders@8 @13 NONAME
GetAcceptLanguagesA@8 @14 NONAME
GetAcceptLanguagesW@8 @15 NONAME
SHCreateThread@16 @16
SHWriteDataBlockList@8 @17 NONAME
SHReadDataBlockList@8 @18 NONAME
SHFreeDataBlockList@4 @19 NONAME
SHAddDataBlock@8 @20 NONAME
SHRemoveDataBlock@8 @21 NONAME
SHFindDataBlock@8 @22 NONAME
SHStringFromGUIDA@12 @23 NONAME
SHStringFromGUIDW@12 @24 NONAME
IsCharAlphaWrapW@4 @25 NONAME
IsCharUpperWrapW@4 @26 NONAME
IsCharLowerWrapW@4 @27 NONAME
IsCharAlphaNumericWrapW@4 @28 NONAME
IsCharSpaceW@4 @29 NONAME
IsCharBlankW@4 @30 NONAME
IsCharPunctW@4 @31 NONAME
IsCharCntrlW@4 @32 NONAME
IsCharDigitW@4 @33 NONAME
IsCharXDigitW@4 @34 NONAME
GetStringType3ExW@12 @35 NONAME
AppendMenuWrapW@16 @36 NONAME
GetDlgItemTextWrapW@16 @74 NONAME
SetDlgItemTextWrapW@12 @138 NONAME
StrCmpNCA@12 @151 NONAME
StrCmpNCW@12 @152 NONAME
StrCmpNICA@12 @153 NONAME
StrCmpNICW@12 @154 NONAME
StrCmpCA@8 @155 NONAME
StrCmpCW@8 @156 NONAME
StrCmpICA@8 @157 NONAME
StrCmpICW@8 @158 NONAME
SHAboutInfoA@8 @160 NONAME
SHAboutInfoW@8 @161 NONAME
SHTruncateString@8 @162 NONAME
IUnknown_QueryStatus@20 @163 NONAME
IUnknown_Exec@24 @164 NONAME
SHSetWindowBits@16 @165 NONAME
SHIsEmptyStream@4 @166 NONAME
SHSetParentHwnd@8 @167 NONAME
ConnectToConnectionPoint@24 @168 NONAME
IUnknown_AtomicRelease@4 @169 NONAME
PathSkipLeadingSlashesA@4 @170 NONAME
SHIsSameObject@8 @171 NONAME
IUnknown_GetWindow@8 @172 NONAME
IUnknown_SetOwner@8 @173 NONAME
IUnknown_SetSite@8 @174 NONAME
IUnknown_GetClassID@8 @175 NONAME
IUnknown_QueryService@16 @176 NONAME
SHLoadMenuPopup@8 @177 NONAME
SHPropagateMessage@20 @178 NONAME
SHRemoveAllSubMenus@4 @180 NONAME
SHEnableMenuItem@12 @181 NONAME
SHCheckMenuItem@12 @182 NONAME
SHRegisterClassA@4 @183 NONAME
SHLoadFromPropertyBag@8 @187 NONAME
IUnknown_OnFocusOCS@8 @189 NONAME
SHGetMenuFromID@8 @192 NONAME
SHGetCurColorRes@0 @193 NONAME
SHFillRectClr@12 @197 NONAME
IUnknown_Set@8 @199 NONAME
MayExecForward@28 @201 NONAME
IsQSForward@12 @202 NONAME
SHStripMneumonicA@4 @203 NONAME
SHIsChildOrSelf@8 @204 NONAME
SHGetValueGoodBootA@24 @205 NONAME
SHGetValueGoodBootW@24 @206 NONAME
FDSA_Initialize@20 @208 NONAME
FDSA_Destroy@4 @209 NONAME
FDSA_InsertItem@12 @210 NONAME
FDSA_DeleteItem@8 @211 NONAME
IStream_Reset@4 @213 NONAME
IStream_Size@8 @214 NONAME
SHAnsiToUnicode@12 @215 NONAME
SHUnicodeToAnsi@12 @217 NONAME
SHUnicodeToAnsiCP@16 @218 NONAME
QISearch@16 @219 NONAME
SHRemoveDefaultDialogFont@4 @221 NONAME
_SHGlobalCounterCreate@4 @222 NONAME
_SHGlobalCounterGetValue@4 @223 NONAME
_SHGlobalCounterIncrement@4 @224 NONAME
SHPinDllOfCLSID@4 @236 NONAME
SHRegisterClassW@4 @237 NONAME
SHUnregisterClassesA@12 @238 NONAME
SHUnregisterClassesW@12 @239 NONAME
SHDefWindowProc@16 @240 NONAME
StopWatchMode@0 @241 NONAME
SHCreateWorkerWindowA@24 @257 NONAME
SHQueueUserWorkItem@28 @260 NONAME
SHRestrictionLookup@16 @266 NONAME
SHWeakQueryInterface@16 @267 NONAME
SHWeakReleaseInterface@8 @268 NONAME
GUIDFromStringA@8 @269 NONAME
GUIDFromStringW@8 @270 NONAME
SHGetRestriction@12 @271 NONAME
WhichPlatform@0 @276 NONAME
SHCreateWorkerWindowW@24 @278 NONAME
SHInvokeDefaultCommand@12 @279 NONAME
SHRegGetIntW@12 @280 NONAME
SHPackDispParamsV@16 @281 NONAME
SHPackDispParams@16 @282 NONAME
IConnectionPoint_SimpleInvoke@12 @284 NONAME
IConnectionPoint_OnChanged@8 @285 NONAME
IUnknown_CPContainerOnChanged@8 @287 NONAME
PlaySoundWrapW@12 @289 NONAME
SHGetIniStringW@20 @294 NONAME
SHSetIniStringW@16 @295 NONAME
ExtTextOutWrapW@32 @299 NONAME
SHGetFileInfoWrapW@20 @313 NONAME
DragQueryFileWrapW@16 @318 NONAME
RegisterMIMETypeForExtensionA@8 @320 NONAME
RegisterMIMETypeForExtensionW@8 @321 NONAME
UnregisterMIMETypeForExtensionA@4 @322 NONAME
UnregisterMIMETypeForExtensionW@4 @323 NONAME
RegisterExtensionForMIMETypeA@8 @324 NONAME
RegisterExtensionForMIMETypeW@8 @325 NONAME
UnregisterExtensionForMIMETypeA@4 @326 NONAME
UnregisterExtensionForMIMETypeW@4 @327 NONAME
GetMIMETypeSubKeyA@12 @328 NONAME
GetMIMETypeSubKeyW@12 @329 NONAME
SHBrowseForFolderWrapW@4 @333 NONAME
SHGetPathFromIDListWrapW@8 @334 NONAME
ShellExecuteExWrapW@4 @335 NONAME
SHFileOperationWrapW@4 @336 NONAME
ExtractIconExWrapW@20 @337 NONAME
SHInterlockedCompareExchange@12 @342 NONAME
SHRegGetCLSIDKeyA@20 @343 NONAME
SHRegGetCLSIDKeyW@20 @344 NONAME
SHUnicodeToUnicode@12 @346 NONAME
GetFileVersionInfoSizeWrapW@8 @350 NONAME
GetFileVersionInfoWrapW@16 @351 NONAME
VerQueryValueWrapW@16 @352 NONAME
IUnknown_EnableModeless@8 @355 NONAME
_CreateAllAccessSecurityAttributes@8 @356 NONAME
SHGetNewLinkInfoWrapW@20 @357 NONAME
SHDefExtractIconWrapW@24 @358 NONAME
SHInvokeCommand@16 @363 NONAME
DoesStringRoundTripA@12 @364 NONAME
ExtractIconWrapW@12 @370 NONAME
MLGetUILanguage@0 @376 NONAME
MLLoadLibraryA@12 @377
MLLoadLibraryW@12 @378
GetSaveFileNameWrapW@4 @389 NONAME
WNetRestoreConnectionWrapW@8 @390 NONAME
WNetGetLastErrorWrapW@20 @391 NONAME
StrCpyNXA@12 @399 NONAME
StrCpyNXW@12 @400 NONAME
PageSetupDlgWrapW@4 @401 NONAME
PrintDlgWrapW@4 @402 NONAME
GetOpenFileNameWrapW@4 @403 NONAME
MLBuildResURLA@24 @405 NONAME
MLBuildResURLW@24 @406 NONAME
SHGetMachineInfo@4 @413 NONAME
MLFreeLibrary@4 @418 NONAME
_SHGlobalCounterCreateNamedA@8 @422 NONAME
_SHGlobalCounterCreateNamedW@8 @423 NONAME
_SHGlobalCounterDecrement@4 @424 NONAME
MLSetMLHInstance@8 @430 NONAME
MLClearMLHInstance@4 @431 NONAME
CLSIDFromStringWrap@8 @436 NONAME
IsOS@4 @437 NONAME
SHGetWebFolderFilePathA@12 @440 NONAME
SHGetWebFolderFilePathW@12 @441 NONAME
SHGetShellKey@12 @491 NONAME
IUnknown_OnFocusChangeIS@12 @509 NONAME
SKGetValueW@24 @516 NONAME
AssocCreate@24 @487
AssocQueryKeyA@20 @501
AssocQueryKeyW@20 @502
AssocQueryStringA@24 @503
AssocQueryStringByKeyA@24 @504
AssocQueryStringByKeyW@24 @515
AssocQueryStringW@24 @547
ChrCmpIA@8 @552
ChrCmpIW@8 @553
ColorAdjustLuma@12 @554
ColorHLSToRGB@12 @555
ColorRGBToHLS@16 @556
DllGetVersion@4=SHLWAPI_DllGetVersion@4 @557
GetMenuPosFromID@8 @558
HashData@16 @559
PathAddBackslashA@4 @562
PathAddBackslashW@4 @563
PathAddExtensionA@8 @564
PathAddExtensionW@8 @565
PathAppendA@8 @566
PathAppendW@8 @567
PathBuildRootA@8 @568
PathBuildRootW@8 @569
PathCanonicalizeA@8 @570
PathCanonicalizeW@8 @571
PathCombineA@12 @572
PathCombineW@12 @573
PathCommonPrefixA@12 @574
PathCommonPrefixW@12 @575
PathCompactPathA@12 @576
PathCompactPathExA@16 @577
PathCompactPathExW@16 @578
PathCompactPathW@12 @579
PathCreateFromUrlA@16 @580
PathCreateFromUrlW@16 @581
PathFileExistsA@4 @582
PathFileExistsW@4 @583
PathFindExtensionA@4 @584
PathFindExtensionW@4 @585
PathFindFileNameA@4 @586
PathFindFileNameW@4 @587
PathFindNextComponentA@4 @588
PathFindNextComponentW@4 @589
PathFindOnPathA@8 @590
PathFindOnPathW@8 @591
PathGetArgsA@4 @594
PathGetArgsW@4 @595
PathGetCharTypeA@4 @596
PathGetCharTypeW@4 @597
PathGetDriveNumberA@4 @598
PathGetDriveNumberW@4 @599
PathIsContentTypeA@8 @600
PathIsContentTypeW@8 @601
PathIsDirectoryA@4 @602
PathIsDirectoryW@4 @605
PathIsFileSpecA@4 @606
PathIsFileSpecW@4 @607
PathIsPrefixA@8 @612
PathIsPrefixW@8 @613
PathIsRelativeA@4 @614
PathIsRelativeW@4 @615
PathIsRootA@4 @616
PathIsRootW@4 @617
PathIsSameRootA@8 @618
PathIsSameRootW@8 @619
PathIsSystemFolderA@8 @620
PathIsSystemFolderW@8 @621
PathIsUNCA@4 @622
PathIsUNCServerA@4 @623
PathIsUNCServerShareA@4 @624
PathIsUNCServerShareW@4 @625
PathIsUNCServerW@4 @626
PathIsUNCW@4 @627
PathIsURLA@4 @628
PathIsURLW@4 @629
PathMakePrettyA@4 @630
PathMakePrettyW@4 @631
PathMakeSystemFolderA@4 @632
PathMakeSystemFolderW@4 @633
PathMatchSpecA@8 @634
PathMatchSpecW@8 @635
PathParseIconLocationA@4 @636
PathParseIconLocationW@4 @637
PathQuoteSpacesA@4 @638
PathQuoteSpacesW@4 @639
PathRelativePathToA@20 @640
PathRelativePathToW@20 @641
PathRemoveArgsA@4 @642
PathRemoveArgsW@4 @643
PathRemoveBackslashA@4 @644
PathRemoveBackslashW@4 @645
PathRemoveBlanksA@4 @646
PathRemoveBlanksW@4 @647
PathRemoveExtensionA@4 @648
PathRemoveExtensionW@4 @649
PathRemoveFileSpecA@4 @650
PathRemoveFileSpecW@4 @651
PathRenameExtensionA@8 @652
PathRenameExtensionW@8 @653
PathSearchAndQualifyA@12 @654
PathSearchAndQualifyW@12 @655
PathSetDlgItemPathA@12 @656
PathSetDlgItemPathW@12 @657
PathSkipRootA@4 @658
PathSkipRootW@4 @659
PathStripPathA@4 @660
PathStripPathW@4 @661
PathStripToRootA@4 @662
PathStripToRootW@4 @663
PathUnmakeSystemFolderA@4 @668
PathUnmakeSystemFolderW@4 @669
PathUnquoteSpacesA@4 @670
PathUnquoteSpacesW@4 @671
SHCreateShellPalette@4 @675
SHDeleteEmptyKeyA@8 @680
SHDeleteEmptyKeyW@8 @681
SHDeleteKeyA@8 @682
SHDeleteKeyW@8 @683
SHDeleteOrphanKeyA@8 @684
SHDeleteOrphanKeyW@8 @685
SHDeleteValueA@12 @686
SHDeleteValueW@12 @687
SHEnumKeyExA@16 @688
SHEnumKeyExW@16 @689
SHEnumValueA@28 @690
SHEnumValueW@28 @691
SHGetInverseCMAP@8 @692
SHGetValueA@24 @694
SHGetValueW@24 @695
SHIsLowMemoryMachine@4 @696
SHOpenRegStreamA@16 @699
SHOpenRegStreamW@16 @700
SHOpenRegStream2A@16 @697
SHOpenRegStream2W@16 @698
SHQueryInfoKeyA@20 @701
SHQueryInfoKeyW@20 @702
SHQueryValueExA@24 @703
SHQueryValueExW@24 @704
SHRegCloseUSKey@4 @705
SHRegEnumUSKeyA@20 @713
SHRegEnumUSKeyW@20 @714
SHRegGetBoolUSValueA@16 @717
SHRegGetBoolUSValueW@16 @718
SHRegGetUSValueA@32 @721
SHRegGetUSValueW@32 @722
SHRegOpenUSKeyA@20 @723
SHRegOpenUSKeyW@20 @724
SHRegQueryInfoUSKeyA@24 @725
SHRegQueryInfoUSKeyW@24 @726
SHRegQueryUSValueA@32 @727
SHRegQueryUSValueW@32 @728
SHRegSetUSValueA@24 @731
SHRegSetUSValueW@24 @732
SHRegWriteUSValueA@24 @733
SHRegWriteUSValueW@24 @734
SHSetValueA@24 @738
SHSetValueW@24 @739
StrCSpnA@8 @743
StrCSpnIA@8 @744
StrCSpnIW@8 @745
StrCSpnW@8 @746
StrCatBuffA@12 @747
StrCatBuffW@12 @748
StrCatW@8 @749
StrChrA@8 @750
StrChrIA@8 @751
StrChrIW@8 @752
StrChrW@8 @753
StrCmpIW@8 @754
StrCmpNA@12 @756
StrCmpNIA@12 @757
StrCmpNIW@12 @758
StrCmpNW@12 @759
StrCmpW@8 @760
StrCpyNW@12 @761
StrCpyW@8 @762
StrDupA@4 @763
StrDupW@4 @764
StrFormatByteSizeA@12 @766
StrFormatByteSizeW@16 @767
StrFromTimeIntervalA@16 @770
StrFromTimeIntervalW@16 @771
StrIsIntlEqualA@16 @772
StrIsIntlEqualW@16 @773
StrNCatA@12 @774
StrNCatW@12 @775
StrPBrkA@8 @776
StrPBrkW@8 @777
StrRChrA@12 @778
StrRChrIA@12 @779
StrRChrIW@12 @780
StrRChrW@12 @781
StrRStrIA@12 @782
StrRStrIW@12 @783
StrSpnA@8 @788
StrSpnW@8 @789
StrStrA@8 @790
StrStrIA@8 @791
StrStrIW@8 @792
StrStrW@8 @793
StrToIntA@4 @794
StrToIntExA@12 @795
StrToIntExW@12 @796
StrToIntW@4 @797
StrTrimA@8 @798
StrTrimW@8 @799
UrlApplySchemeA@16 @800
UrlApplySchemeW@16 @801
UrlCanonicalizeA@16 @802
UrlCanonicalizeW@16 @803
UrlCombineA@20 @804
UrlCombineW@20 @805
UrlCompareA@12 @806
UrlCompareW@12 @807
UrlCreateFromPathA@16 @808
UrlCreateFromPathW@16 @809
UrlEscapeA@16 @810
UrlEscapeW@16 @811
UrlGetLocationA@4 @812
UrlGetLocationW@4 @813
UrlGetPartA@20 @814
UrlGetPartW@20 @815
UrlHashA@12 @816
UrlHashW@12 @817
UrlIsA@8 @818
UrlIsNoHistoryA@4 @819
UrlIsNoHistoryW@4 @820
UrlIsOpaqueA@4 @821
UrlIsOpaqueW@4 @822
UrlIsW@8 @823
UrlUnescapeA@16 @824
UrlUnescapeW@16 @825
wnsprintfA @827
wnsprintfW @828
wvnsprintfA@16 @829
wvnsprintfW@16 @830
AssocIsDangerous@4 @500
StrRetToBufA@16 @784
StrRetToBufW@16 @785
StrRetToStrA@12 @786
StrRetToStrW@12 @787
SHRegGetPathA@20 @719
SHRegGetPathW@20 @720
PathIsDirectoryEmptyA@4 @603
PathIsDirectoryEmptyW@4 @604
PathIsNetworkPathA@4 @610
PathIsNetworkPathW@4 @611
PathIsLFNFileSpecA@4 @608
PathIsLFNFileSpecW@4 @609
PathFindSuffixArrayA@12 @592
PathFindSuffixArrayW@12 @593
_SHGetInstanceExplorer@4 @826
PathUndecorateA@4 @666
PathUndecorateW@4 @667
SHCopyKeyA@16 @673
SHCopyKeyW@16 @674
SHAutoComplete@8 @672
SHCreateStreamOnFileA@12 @676
SHCreateStreamOnFileW@12 @678
SHCreateStreamOnFileEx@24 @677
SHCreateStreamWrapper@16 @679
SHGetThreadRef@4 @693
SHRegDuplicateHKey@4 @712
SHRegSetPathA@20 @729
SHRegSetPathW@20 @730
SHSetThreadRef@4 @737
SHReleaseThreadRef@0 @736
SHSkipJunction@8 @740
SHStrDupA@8 @741
SHStrDupW@8 @742
StrFormatByteSize64A@16 @765
StrFormatKBSizeA@16 @768
StrFormatKBSizeW@16 @769
StrCmpLogicalW@8 @755

View file

@ -0,0 +1,130 @@
/*
* SHLWAPI initialisation
*
* Copyright 1998 Marcus Meissner
* Copyright 1998 Juergen Schmied (jsch)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#define NO_SHLWAPI_REG
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
HINSTANCE shlwapi_hInstance = 0;
HMODULE SHLWAPI_hshell32 = 0;
HMODULE SHLWAPI_hwinmm = 0;
HMODULE SHLWAPI_hcomdlg32 = 0;
HMODULE SHLWAPI_hcomctl32 = 0;
HMODULE SHLWAPI_hmpr = 0;
HMODULE SHLWAPI_hmlang = 0;
HMODULE SHLWAPI_hurlmon = 0;
HMODULE SHLWAPI_hversion = 0;
DWORD SHLWAPI_ThreadRef_index = TLS_OUT_OF_INDEXES;
/*************************************************************************
* SHLWAPI {SHLWAPI}
*
* The Shell Light-Weight Api dll provides a large number of utility functions
* which are commonly required by Win32 programs. Originally distributed with
* Internet Explorer as a free download, it became a core part of Windows when
* Internet Explorer was 'integrated' into the O/S with the release of Win98.
*
* All functions exported by ordinal are undocumented by MS. The vast majority
* of these are wrappers for Unicode functions that may not exist on early 16
* bit platforms. The remainder perform various small tasks and presumably were
* added to facilitate code reuse amongst the MS developers.
*/
/*************************************************************************
* SHLWAPI DllMain
*
* NOTES
* calling oleinitialize here breaks sone apps.
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
{
TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
shlwapi_hInstance = hinstDLL;
SHLWAPI_ThreadRef_index = TlsAlloc();
break;
case DLL_PROCESS_DETACH:
if (SHLWAPI_hshell32) FreeLibrary(SHLWAPI_hshell32);
if (SHLWAPI_hwinmm) FreeLibrary(SHLWAPI_hwinmm);
if (SHLWAPI_hcomdlg32) FreeLibrary(SHLWAPI_hcomdlg32);
if (SHLWAPI_hcomctl32) FreeLibrary(SHLWAPI_hcomctl32);
if (SHLWAPI_hmpr) FreeLibrary(SHLWAPI_hmpr);
if (SHLWAPI_hmlang) FreeLibrary(SHLWAPI_hmlang);
if (SHLWAPI_hurlmon) FreeLibrary(SHLWAPI_hurlmon);
if (SHLWAPI_hversion) FreeLibrary(SHLWAPI_hversion);
if (SHLWAPI_ThreadRef_index != TLS_OUT_OF_INDEXES) TlsFree(SHLWAPI_ThreadRef_index);
break;
}
return TRUE;
}
/***********************************************************************
* DllGetVersion [SHLWAPI.@]
*
* Retrieve "shlwapi.dll" version information.
*
* PARAMS
* pdvi [O] pointer to version information structure.
*
* RETURNS
* Success: S_OK. pdvi is updated with the version information
* Failure: E_INVALIDARG, if pdvi->cbSize is not set correctly.
*
* NOTES
* You may pass either a DLLVERSIONINFO of DLLVERSIONINFO2 structure
* as pdvi, provided that the size is set correctly.
* Returns version as shlwapi.dll from IE5.01.
*/
HRESULT WINAPI SHLWAPI_DllGetVersion (DLLVERSIONINFO *pdvi)
{
DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2*)pdvi;
TRACE("(%p)\n",pdvi);
switch (pdvi2->info1.cbSize)
{
case sizeof(DLLVERSIONINFO2):
pdvi2->dwFlags = 0;
pdvi2->ullVersion = MAKEDLLVERULL(5, 0, 2314, 0);
/* Fall through */
case sizeof(DLLVERSIONINFO):
pdvi2->info1.dwMajorVersion = 5;
pdvi2->info1.dwMinorVersion = 0;
pdvi2->info1.dwBuildNumber = 2314;
pdvi2->info1.dwPlatformID = 1000;
return S_OK;
}
if (pdvi)
WARN("pdvi->cbSize = %ld, unhandled\n", pdvi2->info1.cbSize);
return E_INVALIDARG;
}

2382
reactos/lib/shlwapi/string.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,480 @@
/*
* SHLWAPI thread and MT synchronisation functions
*
* Copyright 2002 Juergen Schmied
* Copyright 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "wine/debug.h"
#define NO_SHLWAPI_REG
#define NO_SHLWAPI_PATH
#define NO_SHLWAPI_GDI
#define NO_SHLWAPI_STREAM
#define NO_SHLWAPI_USER
#include "shlwapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* Get a function pointer from a DLL handle */
#define GET_FUNC(func, module, name, fail) \
do { \
if (!func) { \
if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
if (!(func = (void*)GetProcAddress(SHLWAPI_h##module, name))) return fail; \
} \
} while (0)
/* DLL handles for late bound calls */
extern HMODULE SHLWAPI_hshell32;
/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
static HRESULT (WINAPI *pSHGetInstanceExplorer)(IUnknown**);
extern DWORD SHLWAPI_ThreadRef_index; /* Initialised in shlwapi_main.c */
DWORD WINAPI SHStringFromGUIDA(REFGUID,LPSTR,INT);
/**************************************************************************
* _CreateAllAccessSecurityAttributes [SHLWAPI.356]
*
* Initialise security attributes from a security descriptor.
*
* PARAMS
* lpAttr [O] Security attributes
* lpSec [I] Security descriptor
*
* RETURNS
* Success: lpAttr, initialised using lpSec.
* Failure: NULL, if any parameters are invalid.
*
* NOTES
* This function always returns NULL if the underlying OS version
* Wine is impersonating does not use security descriptors (i.e. anything
* before Windows NT).
*/
LPSECURITY_ATTRIBUTES WINAPI _CreateAllAccessSecurityAttributes(
LPSECURITY_ATTRIBUTES lpAttr,
PSECURITY_DESCRIPTOR lpSec)
{
/* This function is used within SHLWAPI only to create security attributes
* for shell semaphores. */
TRACE("(%p,%p)\n", lpAttr, lpSec);
if (!(GetVersion() & 0x80000000)) /* NT */
{
if (!lpSec || !lpAttr)
return NULL;
if (InitializeSecurityDescriptor(lpSec, 1))
{
if (SetSecurityDescriptorDacl(lpSec, TRUE, NULL, FALSE))
{
lpAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
lpAttr->lpSecurityDescriptor = lpSec;
lpAttr->bInheritHandle = FALSE;
return lpAttr;
}
}
}
return NULL;
}
/*************************************************************************
* _SHGetInstanceExplorer [SHLWAPI.@]
*
* Get an interface to the shell explorer.
*
* PARAMS
* lppUnknown [O] Destination for explorers IUnknown interface.
*
* RETURNS
* Success: S_OK. lppUnknown contains the explorer interface.
* Failure: An HRESULT error code.
*/
HRESULT WINAPI _SHGetInstanceExplorer(IUnknown **lppUnknown)
{
/* This function is used within SHLWAPI only to hold the IE reference
* for threads created with the CTF_PROCESS_REF flag set. */
GET_FUNC(pSHGetInstanceExplorer, shell32, "SHGetInstanceExplorer", E_FAIL);
return pSHGetInstanceExplorer(lppUnknown);
}
/* Internal thread information structure */
typedef struct tagSHLWAPI_THREAD_INFO
{
LPTHREAD_START_ROUTINE pfnThreadProc; /* Thread start */
LPTHREAD_START_ROUTINE pfnCallback; /* Thread initialisation */
PVOID pData; /* Application specific data */
BOOL bInitCom; /* Initialise COM for the thread? */
HANDLE hEvent; /* Signal for creator to continue */
IUnknown *refThread; /* Reference to thread creator */
IUnknown *refIE; /* Reference to the IE process */
} SHLWAPI_THREAD_INFO, *LPSHLWAPI_THREAD_INFO;
/*************************************************************************
* SHGetThreadRef [SHLWAPI.@]
*
* Get a per-thread object reference set by SHSetThreadRef().
*
* PARAMS
* lppUnknown [O] Destination to receive object reference
*
* RETURNS
* Success: S_OK. lppUnknown is set to the object reference.
* Failure: E_NOINTERFACE, if an error occurs or lppUnknown is NULL.
*/
HRESULT WINAPI SHGetThreadRef(IUnknown **lppUnknown)
{
TRACE("(%p)\n", lppUnknown);
if (!lppUnknown || SHLWAPI_ThreadRef_index == TLS_OUT_OF_INDEXES)
return E_NOINTERFACE;
*lppUnknown = (IUnknown*)TlsGetValue(SHLWAPI_ThreadRef_index);
if (!*lppUnknown)
return E_NOINTERFACE;
/* Add a reference. Caller will Release() us when finished */
IUnknown_AddRef(*lppUnknown);
return S_OK;
}
/*************************************************************************
* SHSetThreadRef [SHLWAPI.@]
*
* Store a per-thread object reference.
*
* PARAMS
* lpUnknown [I] Object reference to store
*
* RETURNS
* Success: S_OK. lpUnknown is stored and can be retrieved by SHGetThreadRef()
* Failure: E_NOINTERFACE, if an error occurs or lpUnknown is NULL.
*/
HRESULT WINAPI SHSetThreadRef(IUnknown *lpUnknown)
{
TRACE("(%p)\n", lpUnknown);
if (!lpUnknown || SHLWAPI_ThreadRef_index == 0xffffffff)
return E_NOINTERFACE;
TlsSetValue(SHLWAPI_ThreadRef_index, lpUnknown);
return S_OK;
}
/*************************************************************************
* SHReleaseThreadRef [SHLWAPI.@]
*
* Release a per-thread object reference.
*
* PARAMS
* None.
*
* RETURNS
* Success: S_OK. The threads object reference is released.
* Failure: An HRESULT error code.
*/
HRESULT WINAPI SHReleaseThreadRef()
{
FIXME("() - stub!\n");
return S_OK;
}
/*************************************************************************
* SHLWAPI_ThreadWrapper
*
* Internal wrapper for executing user thread functions from SHCreateThread.
*/
static DWORD WINAPI SHLWAPI_ThreadWrapper(PVOID pTi)
{
SHLWAPI_THREAD_INFO ti;
HRESULT hCom = E_FAIL;
DWORD dwRet;
TRACE("(%p)", pTi);
/* We are now executing in the context of the newly created thread.
* So we copy the data passed to us (it is on the stack of the function
* that called us, which is waiting for us to signal an event before
* returning). */
memcpy(&ti, pTi, sizeof(SHLWAPI_THREAD_INFO));
/* Initialise COM for the thread, if desired */
if (ti.bInitCom)
{
hCom = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED|COINIT_DISABLE_OLE1DDE);
if (FAILED(hCom))
hCom = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
}
/* Execute the callback function before returning */
if (ti.pfnCallback)
ti.pfnCallback(ti.pData);
/* Signal the thread that created us; it can return now */
SetEvent(ti.hEvent);
/* Execute the callers start code */
dwRet = ti.pfnThreadProc(ti.pData);
/* Release references to the caller and IE process, if held */
if (ti.refThread)
IUnknown_Release(ti.refThread);
if (ti.refIE)
IUnknown_Release(ti.refIE);
if (SUCCEEDED(hCom))
CoUninitialize();
/* Return the users thread return value */
return dwRet;
}
/*************************************************************************
* SHCreateThread [SHLWAPI.16]
*
* Create a new thread.
*
* PARAMS
* pfnThreadProc [I] Function to execute in new thread
* pData [I] Application specific data passed to pfnThreadProc
* dwFlags [I] CTF_ flags from "shlwapi.h"
* pfnCallback [I] Function to execute before pfnThreadProc
*
* RETURNS
* Success: TRUE. pfnThreadProc was executed.
* Failure: FALSE. pfnThreadProc was not executed.
*
* NOTES
* If the thread cannot be created, pfnCallback is NULL, and dwFlags
* has bit CTF_INSIST set, pfnThreadProc will be executed synchronously.
*/
BOOL WINAPI SHCreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, VOID *pData,
DWORD dwFlags, LPTHREAD_START_ROUTINE pfnCallback)
{
SHLWAPI_THREAD_INFO ti;
BOOL bCalled = FALSE;
TRACE("(%p,%p,0x%lX,%p)\n", pfnThreadProc, pData, dwFlags, pfnCallback);
/* Set up data to pass to the new thread (On our stack) */
ti.pfnThreadProc = pfnThreadProc;
ti.pfnCallback = pfnCallback;
ti.pData = pData;
ti.bInitCom = dwFlags & CTF_COINIT ? TRUE : FALSE;
ti.hEvent = CreateEventA(NULL,FALSE,FALSE,NULL);
/* Hold references to the current thread and IE process, if desired */
if(dwFlags & CTF_THREAD_REF)
SHGetThreadRef(&ti.refThread);
else
ti.refThread = NULL;
if(dwFlags & CTF_PROCESS_REF)
_SHGetInstanceExplorer(&ti.refIE);
else
ti.refIE = NULL;
/* Create the thread */
if(ti.hEvent)
{
DWORD dwRetVal;
HANDLE hThread;
hThread = CreateThread(NULL, 0, SHLWAPI_ThreadWrapper, &ti, 0, &dwRetVal);
if(hThread)
{
/* Wait for the thread to signal us to continue */
WaitForSingleObject(ti.hEvent, -1);
CloseHandle(hThread);
bCalled = TRUE;
}
CloseHandle(ti.hEvent);
}
if (!bCalled)
{
if (!ti.pfnCallback && dwFlags & CTF_INSIST)
{
/* Couldn't call, call synchronously */
pfnThreadProc(pData);
bCalled = TRUE;
}
else
{
/* Free references, since thread hasn't run to do so */
if(ti.refThread)
IUnknown_Release(ti.refThread);
if(ti.refIE)
IUnknown_Release(ti.refIE);
}
}
return bCalled;
}
/*************************************************************************
* _SHGlobalCounterGetValue [SHLWAPI.223]
*
* Get the current count of a semaphore.
*
* PARAMS
* hSem [I] Semaphore handle
*
* RETURNS
* The current count of the semaphore.
*/
LONG WINAPI _SHGlobalCounterGetValue(HANDLE hSem)
{
LONG dwOldCount = 0;
TRACE("(%p)\n", hSem);
ReleaseSemaphore(hSem, 1, &dwOldCount); /* +1 */
WaitForSingleObject(hSem, 0); /* -1 */
return dwOldCount;
}
/*************************************************************************
* _SHGlobalCounterIncrement [SHLWAPI.224]
*
* Claim a semaphore.
*
* PARAMS
* hSem [I] Semaphore handle
*
* RETURNS
* The new count of the semaphore.
*/
LONG WINAPI _SHGlobalCounterIncrement(HANDLE hSem)
{
LONG dwOldCount = 0;
TRACE("(%p)\n", hSem);
ReleaseSemaphore(hSem, 1, &dwOldCount);
return dwOldCount + 1;
}
/*************************************************************************
* _SHGlobalCounterDecrement [SHLWAPI.424]
*
* Release a semaphore.
*
* PARAMS
* hSem [I] Semaphore handle
*
* RETURNS
* The new count of the semaphore.
*/
DWORD WINAPI _SHGlobalCounterDecrement(HANDLE hSem)
{
DWORD dwOldCount = 0;
TRACE("(%p)\n", hSem);
dwOldCount = _SHGlobalCounterGetValue(hSem);
WaitForSingleObject(hSem, 0);
return dwOldCount - 1;
}
/*************************************************************************
* _SHGlobalCounterCreateNamedW [SHLWAPI.423]
*
* Unicode version of _SHGlobalCounterCreateNamedA.
*/
HANDLE WINAPI _SHGlobalCounterCreateNamedW(LPCWSTR lpszName, DWORD iInitial)
{
static const WCHAR szPrefix[] = { 's', 'h', 'e', 'l', 'l', '.', '\0' };
const int iPrefixLen = 6;
WCHAR szBuff[MAX_PATH];
const int iBuffLen = sizeof(szBuff)/sizeof(WCHAR);
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sAttr, *pSecAttr;
HANDLE hRet;
TRACE("(%s,%ld)\n", debugstr_w(lpszName), iInitial);
/* Create Semaphore name */
memcpy(szBuff, szPrefix, (iPrefixLen + 1) * sizeof(WCHAR));
if (lpszName)
StrCpyNW(szBuff + iPrefixLen, lpszName, iBuffLen - iPrefixLen);
/* Initialise security attributes */
pSecAttr = _CreateAllAccessSecurityAttributes(&sAttr, &sd);
if (!(hRet = CreateSemaphoreW(pSecAttr , iInitial, MAXLONG, szBuff)))
hRet = OpenSemaphoreW(SYNCHRONIZE|SEMAPHORE_MODIFY_STATE, 0, szBuff);
return hRet;
}
/*************************************************************************
* _SHGlobalCounterCreateNamedA [SHLWAPI.422]
*
* Create a semaphore.
*
* PARAMS
* lpszName [I] Name of semaphore
* iInitial [I] Initial count for semaphore
*
* RETURNS
* A new semaphore handle.
*/
HANDLE WINAPI _SHGlobalCounterCreateNamedA(LPCSTR lpszName, DWORD iInitial)
{
WCHAR szBuff[MAX_PATH];
TRACE("(%s,%ld)\n", debugstr_a(lpszName), iInitial);
if (lpszName)
MultiByteToWideChar(0, 0, lpszName, -1, szBuff, MAX_PATH);
return _SHGlobalCounterCreateNamedW(lpszName ? szBuff : NULL, iInitial);
}
/*************************************************************************
* _SHGlobalCounterCreate [SHLWAPI.222]
*
* Create a semaphore using the name of a GUID.
*
* PARAMS
* guid [I] GUID to use as semaphore name
*
* RETURNS
* A handle to the semaphore.
*
* NOTES
* The initial count of the semaphore is set to 0.
*/
HANDLE WINAPI _SHGlobalCounterCreate (REFGUID guid)
{
char szName[40];
TRACE("(%s)\n", debugstr_guid(guid));
/* Create a named semaphore using the GUID string */
SHStringFromGUIDA(guid, szName, sizeof(szName) - 1);
return _SHGlobalCounterCreateNamedA(szName, 0);
}

2469
reactos/lib/shlwapi/url.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,531 @@
/*
* wsprintf functions
*
* Copyright 1996 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* NOTE:
* This code is duplicated in user32. If you change something here make sure
* to change it in user32 too.
*/
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(string);
#define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */
#define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */
#define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */
#define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */
#define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */
#define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */
#define WPRINTF_WIDE 0x0040 /* Wide arg ('w' prefix) */
typedef enum
{
WPR_UNKNOWN,
WPR_CHAR,
WPR_WCHAR,
WPR_STRING,
WPR_WSTRING,
WPR_SIGNED,
WPR_UNSIGNED,
WPR_HEXA
} WPRINTF_TYPE;
typedef struct
{
UINT flags;
UINT width;
UINT precision;
WPRINTF_TYPE type;
} WPRINTF_FORMAT;
typedef union {
WCHAR wchar_view;
CHAR char_view;
LPCSTR lpcstr_view;
LPCWSTR lpcwstr_view;
INT int_view;
} WPRINTF_DATA;
static const CHAR null_stringA[] = "(null)";
static const WCHAR null_stringW[] = { '(', 'n', 'u', 'l', 'l', ')', 0 };
/***********************************************************************
* WPRINTF_ParseFormatA
*
* Parse a format specification. A format specification has the form:
*
* [-][#][0][width][.precision]type
*
* Return value is the length of the format specification in characters.
*/
static INT WPRINTF_ParseFormatA( LPCSTR format, WPRINTF_FORMAT *res )
{
LPCSTR p = format;
res->flags = 0;
res->width = 0;
res->precision = 0;
if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
while ((*p >= '0') && (*p <= '9')) /* width field */
{
res->width = res->width * 10 + *p - '0';
p++;
}
if (*p == '.') /* precision field */
{
p++;
while ((*p >= '0') && (*p <= '9'))
{
res->precision = res->precision * 10 + *p - '0';
p++;
}
}
if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
switch(*p)
{
case 'c':
res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
break;
case 'C':
res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
break;
case 'd':
case 'i':
res->type = WPR_SIGNED;
break;
case 's':
res->type = (res->flags & (WPRINTF_LONG |WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
break;
case 'S':
res->type = (res->flags & (WPRINTF_SHORT|WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
break;
case 'u':
res->type = WPR_UNSIGNED;
break;
case 'X':
res->flags |= WPRINTF_UPPER_HEX;
/* fall through */
case 'x':
res->type = WPR_HEXA;
break;
default: /* unknown format char */
res->type = WPR_UNKNOWN;
p--; /* print format as normal char */
break;
}
return (INT)(p - format) + 1;
}
/***********************************************************************
* WPRINTF_ParseFormatW
*
* Parse a format specification. A format specification has the form:
*
* [-][#][0][width][.precision]type
*
* Return value is the length of the format specification in characters.
*/
static INT WPRINTF_ParseFormatW( LPCWSTR format, WPRINTF_FORMAT *res )
{
LPCWSTR p = format;
res->flags = 0;
res->width = 0;
res->precision = 0;
if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
while ((*p >= '0') && (*p <= '9')) /* width field */
{
res->width = res->width * 10 + *p - '0';
p++;
}
if (*p == '.') /* precision field */
{
p++;
while ((*p >= '0') && (*p <= '9'))
{
res->precision = res->precision * 10 + *p - '0';
p++;
}
}
if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
else if (*p == 'w') { res->flags |= WPRINTF_WIDE; p++; }
switch((CHAR)*p)
{
case 'c':
res->type = (res->flags & WPRINTF_SHORT) ? WPR_CHAR : WPR_WCHAR;
break;
case 'C':
res->type = (res->flags & WPRINTF_LONG) ? WPR_WCHAR : WPR_CHAR;
break;
case 'd':
case 'i':
res->type = WPR_SIGNED;
break;
case 's':
res->type = ((res->flags & WPRINTF_SHORT) && !(res->flags & WPRINTF_WIDE)) ? WPR_STRING : WPR_WSTRING;
break;
case 'S':
res->type = (res->flags & (WPRINTF_LONG|WPRINTF_WIDE)) ? WPR_WSTRING : WPR_STRING;
break;
case 'u':
res->type = WPR_UNSIGNED;
break;
case 'X':
res->flags |= WPRINTF_UPPER_HEX;
/* fall through */
case 'x':
res->type = WPR_HEXA;
break;
default:
res->type = WPR_UNKNOWN;
p--; /* print format as normal char */
break;
}
return (INT)(p - format) + 1;
}
/***********************************************************************
* WPRINTF_GetLen
*/
static UINT WPRINTF_GetLen( WPRINTF_FORMAT *format, WPRINTF_DATA *arg,
LPSTR number, UINT maxlen )
{
UINT len;
if (format->flags & WPRINTF_LEFTALIGN) format->flags &= ~WPRINTF_ZEROPAD;
if (format->width > maxlen) format->width = maxlen;
switch(format->type)
{
case WPR_CHAR:
case WPR_WCHAR:
return (format->precision = 1);
case WPR_STRING:
if (!arg->lpcstr_view) arg->lpcstr_view = null_stringA;
for (len = 0; !format->precision || (len < format->precision); len++)
if (!*(arg->lpcstr_view + len)) break;
if (len > maxlen) len = maxlen;
return (format->precision = len);
case WPR_WSTRING:
if (!arg->lpcwstr_view) arg->lpcwstr_view = null_stringW;
for (len = 0; !format->precision || (len < format->precision); len++)
if (!*(arg->lpcwstr_view + len)) break;
if (len > maxlen) len = maxlen;
return (format->precision = len);
case WPR_SIGNED:
len = sprintf( number, "%d", arg->int_view );
break;
case WPR_UNSIGNED:
len = sprintf( number, "%u", (UINT)arg->int_view );
break;
case WPR_HEXA:
len = sprintf( number,
(format->flags & WPRINTF_UPPER_HEX) ? "%X" : "%x",
(UINT)arg->int_view);
break;
default:
return 0;
}
if (len > maxlen) len = maxlen;
if (format->precision < len) format->precision = len;
if (format->precision > maxlen) format->precision = maxlen;
if ((format->flags & WPRINTF_ZEROPAD) && (format->width > format->precision))
format->precision = format->width;
if (format->flags & WPRINTF_PREFIX_HEX) len += 2;
return len;
}
/***********************************************************************
* wvnsprintfA (SHLWAPI.@)
*
* Print formatted output to a string, up to a maximum number of chars.
*
* PARAMS
* buffer [O] Destination for output string
* maxlen [I] Maximum number of characters to write
* spec [I] Format string
*
* RETURNS
* Success: The number of characters written.
* Failure: -1.
*/
INT WINAPI wvnsprintfA( LPSTR buffer, UINT maxlen, LPCSTR spec, va_list args )
{
WPRINTF_FORMAT format;
LPSTR p = buffer;
UINT i, len, sign;
CHAR number[20];
WPRINTF_DATA argData;
TRACE("%p %u %s\n", buffer, maxlen, debugstr_a(spec));
while (*spec && (maxlen > 1))
{
if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
spec++;
if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
spec += WPRINTF_ParseFormatA( spec, &format );
switch(format.type)
{
case WPR_WCHAR:
argData.wchar_view = (WCHAR)va_arg( args, int );
break;
case WPR_CHAR:
argData.char_view = (CHAR)va_arg( args, int );
break;
case WPR_STRING:
argData.lpcstr_view = va_arg( args, LPCSTR );
break;
case WPR_WSTRING:
argData.lpcwstr_view = va_arg( args, LPCWSTR );
break;
case WPR_HEXA:
case WPR_SIGNED:
case WPR_UNSIGNED:
argData.int_view = va_arg( args, INT );
break;
default:
argData.wchar_view = 0;
break;
}
len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
sign = 0;
if (!(format.flags & WPRINTF_LEFTALIGN))
for (i = format.precision; i < format.width; i++, maxlen--)
*p++ = ' ';
switch(format.type)
{
case WPR_WCHAR:
*p++ = argData.wchar_view;
break;
case WPR_CHAR:
*p++ = argData.char_view;
break;
case WPR_STRING:
memcpy( p, argData.lpcstr_view, len );
p += len;
break;
case WPR_WSTRING:
{
LPCWSTR ptr = argData.lpcwstr_view;
for (i = 0; i < len; i++) *p++ = (CHAR)*ptr++;
}
break;
case WPR_HEXA:
if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
{
*p++ = '0';
*p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
maxlen -= 2;
len -= 2;
}
/* fall through */
case WPR_SIGNED:
/* Transfer the sign now, just in case it will be zero-padded*/
if (number[0] == '-')
{
*p++ = '-';
sign = 1;
}
/* fall through */
case WPR_UNSIGNED:
for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
memcpy( p, number + sign, len - sign );
p += len - sign;
break;
case WPR_UNKNOWN:
continue;
}
if (format.flags & WPRINTF_LEFTALIGN)
for (i = format.precision; i < format.width; i++, maxlen--)
*p++ = ' ';
maxlen -= len;
}
*p = 0;
TRACE("%s\n",debugstr_a(buffer));
return (maxlen > 1) ? (INT)(p - buffer) : -1;
}
/***********************************************************************
* wvnsprintfW (SHLWAPI.@)
*
* See wvnsprintfA.
*/
INT WINAPI wvnsprintfW( LPWSTR buffer, UINT maxlen, LPCWSTR spec, va_list args )
{
WPRINTF_FORMAT format;
LPWSTR p = buffer;
UINT i, len, sign;
CHAR number[20];
WPRINTF_DATA argData;
TRACE("%p %u %s\n", buffer, maxlen, debugstr_w(spec));
while (*spec && (maxlen > 1))
{
if (*spec != '%') { *p++ = *spec++; maxlen--; continue; }
spec++;
if (*spec == '%') { *p++ = *spec++; maxlen--; continue; }
spec += WPRINTF_ParseFormatW( spec, &format );
switch(format.type)
{
case WPR_WCHAR:
argData.wchar_view = (WCHAR)va_arg( args, int );
break;
case WPR_CHAR:
argData.char_view = (CHAR)va_arg( args, int );
break;
case WPR_STRING:
argData.lpcstr_view = va_arg( args, LPCSTR );
break;
case WPR_WSTRING:
argData.lpcwstr_view = va_arg( args, LPCWSTR );
break;
case WPR_HEXA:
case WPR_SIGNED:
case WPR_UNSIGNED:
argData.int_view = va_arg( args, INT );
break;
default:
argData.wchar_view = 0;
break;
}
len = WPRINTF_GetLen( &format, &argData, number, maxlen - 1 );
sign = 0;
if (!(format.flags & WPRINTF_LEFTALIGN))
for (i = format.precision; i < format.width; i++, maxlen--)
*p++ = ' ';
switch(format.type)
{
case WPR_WCHAR:
*p++ = argData.wchar_view;
break;
case WPR_CHAR:
*p++ = argData.char_view;
break;
case WPR_STRING:
{
LPCSTR ptr = argData.lpcstr_view;
for (i = 0; i < len; i++) *p++ = (WCHAR)*ptr++;
}
break;
case WPR_WSTRING:
if (len) memcpy( p, argData.lpcwstr_view, len * sizeof(WCHAR) );
p += len;
break;
case WPR_HEXA:
if ((format.flags & WPRINTF_PREFIX_HEX) && (maxlen > 3))
{
*p++ = '0';
*p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
maxlen -= 2;
len -= 2;
}
/* fall through */
case WPR_SIGNED:
/* Transfer the sign now, just in case it will be zero-padded*/
if (number[0] == '-')
{
*p++ = '-';
sign = 1;
}
/* fall through */
case WPR_UNSIGNED:
for (i = len; i < format.precision; i++, maxlen--) *p++ = '0';
for (i = sign; i < len; i++) *p++ = (WCHAR)number[i];
break;
case WPR_UNKNOWN:
continue;
}
if (format.flags & WPRINTF_LEFTALIGN)
for (i = format.precision; i < format.width; i++, maxlen--)
*p++ = ' ';
maxlen -= len;
}
*p = 0;
TRACE("%s\n",debugstr_w(buffer));
return (maxlen > 1) ? (INT)(p - buffer) : -1;
}
/*************************************************************************
* wnsprintfA (SHLWAPI.@)
*
* Print formatted output to a string, up to a maximum number of chars.
*
* PARAMS
* lpOut [O] Destination for output string
* cchLimitIn [I] Maximum number of characters to write
* lpFmt [I] Format string
*
* RETURNS
* Success: The number of characters written.
* Failure: -1.
*/
int WINAPIV wnsprintfA(LPSTR lpOut, int cchLimitIn, LPCSTR lpFmt, ...)
{
va_list valist;
INT res;
va_start( valist, lpFmt );
res = wvnsprintfA( lpOut, cchLimitIn, lpFmt, valist );
va_end( valist );
return res;
}
/*************************************************************************
* wnsprintfW (SHLWAPI.@)
*
* See wnsprintfA.
*/
int WINAPIV wnsprintfW(LPWSTR lpOut, int cchLimitIn, LPCWSTR lpFmt, ...)
{
va_list valist;
INT res;
va_start( valist, lpFmt );
res = wvnsprintfW( lpOut, cchLimitIn, lpFmt, valist );
va_end( valist );
return res;
}