mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
8615f19c50
commit
f420913748
14 changed files with 19088 additions and 0 deletions
699
reactos/lib/shlwapi/assoc.c
Normal file
699
reactos/lib/shlwapi/assoc.c
Normal 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
453
reactos/lib/shlwapi/clist.c
Normal 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;
|
||||||
|
}
|
683
reactos/lib/shlwapi/istream.c
Normal file
683
reactos/lib/shlwapi/istream.c
Normal 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;
|
||||||
|
}
|
66
reactos/lib/shlwapi/makefile
Normal file
66
reactos/lib/shlwapi/makefile
Normal 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
|
4065
reactos/lib/shlwapi/ordinal.c
Normal file
4065
reactos/lib/shlwapi/ordinal.c
Normal file
File diff suppressed because it is too large
Load diff
3902
reactos/lib/shlwapi/path.c
Normal file
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
2196
reactos/lib/shlwapi/reg.c
Normal file
File diff suppressed because it is too large
Load diff
573
reactos/lib/shlwapi/regstream.c
Normal file
573
reactos/lib/shlwapi/regstream.c
Normal 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;
|
||||||
|
}
|
459
reactos/lib/shlwapi/shlwapi.def
Normal file
459
reactos/lib/shlwapi/shlwapi.def
Normal 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
|
130
reactos/lib/shlwapi/shlwapi_main.c
Normal file
130
reactos/lib/shlwapi/shlwapi_main.c
Normal 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
2382
reactos/lib/shlwapi/string.c
Normal file
File diff suppressed because it is too large
Load diff
480
reactos/lib/shlwapi/thread.c
Normal file
480
reactos/lib/shlwapi/thread.c
Normal 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
2469
reactos/lib/shlwapi/url.c
Normal file
File diff suppressed because it is too large
Load diff
531
reactos/lib/shlwapi/wsprintf.c
Normal file
531
reactos/lib/shlwapi/wsprintf.c
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue