1084 lines
32 KiB
C++
1084 lines
32 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: filstg.cxx
|
|
//
|
|
// Contents: IStorage for files implementation
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "headers.cxx"
|
|
#pragma hdrstop
|
|
|
|
#include <ctype.h>
|
|
#include <stgutil.hxx>
|
|
#include <filstm.hxx>
|
|
#include "fsenm.hxx"
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::QueryInterface, public
|
|
//
|
|
// Synopsis: Returns an object for the requested interface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::QueryInterface(REFIID iid, void **ppvObj)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::QueryInterface:%p(riid, %p)\n",
|
|
this, ppvObj));
|
|
if (!IsValidIid(iid))
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
ssChk(Validate());
|
|
if (IsEqualIID(iid, IID_IStorage) || IsEqualIID(iid, IID_IUnknown))
|
|
{
|
|
*ppvObj = (IStorage *)this;
|
|
CFileStorage::AddRef();
|
|
}
|
|
else if (IsEqualIID(iid, IID_IPropertySetStorage))
|
|
{
|
|
// BUGBUG - Need storage property set
|
|
*ppvObj = NULL;
|
|
sc = STG_E_UNIMPLEMENTEDFUNCTION;
|
|
}
|
|
else if (IsEqualIID(iid, IID_INativeFileSystem))
|
|
{
|
|
*ppvObj = (INativeFileSystem *)this;
|
|
CFileStorage::AddRef();
|
|
}
|
|
else
|
|
{
|
|
sc = E_NOINTERFACE;
|
|
*ppvObj = NULL;
|
|
}
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::QueryInterface => %p\n",
|
|
*ppvObj));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::CFileStorage, public
|
|
//
|
|
// Synopsis: Empty object constructor
|
|
//
|
|
// History: 30-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CFileStorage::CFileStorage(void)
|
|
{
|
|
ssDebugOut((DEB_ITRACE, "In CFileStorage::CFileStorage:%p()\n", this));
|
|
_sig = 0;
|
|
ssDebugOut((DEB_ITRACE, "Out CFileStorage::CFileStorage\n"));
|
|
ENLIST_TRACKING(CFileStorage);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::InitFromPath, public
|
|
//
|
|
// Synopsis: Constructor
|
|
//
|
|
// Arguments: [hParent] - Handle of parent directory
|
|
// [pwcsName] - Name of directory
|
|
// [grfMode] - Mode
|
|
// [co] - Create or open
|
|
// [pssSecurity] - Security
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CFileStorage::InitFromPath(HANDLE hParent,
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
CREATEOPEN co,
|
|
LPSECURITY_ATTRIBUTES pssSecurity)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CFileStorage::InitFromPath:%p("
|
|
"%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName,
|
|
grfMode, co, pssSecurity));
|
|
|
|
ssChk(ValidateMode(grfMode));
|
|
ssChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co,
|
|
FD_FILE, pssSecurity, &_h));
|
|
|
|
_grfMode = grfMode;
|
|
_sig = CFILESTORAGE_SIG;
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CFileStorage::InitFromPath\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::InitFromHandle, public
|
|
//
|
|
// Synopsis: Initialize from a handle
|
|
//
|
|
// Arguments: [h] - Handle
|
|
// [grfMode] - Mode
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 14-Jul-93 DrewB Created
|
|
//
|
|
// Notes: Takes a new reference on the handle
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CFileStorage::InitFromHandle(HANDLE h, DWORD grfMode)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CFileStorage::InitFromHandle:%p(%p, %lX)\n",
|
|
this, h, grfMode));
|
|
|
|
ssChk(ValidateMode(grfMode));
|
|
_h = h;
|
|
ssAssert(_h != NULL);
|
|
_grfMode = grfMode;
|
|
_sig = CFILESTORAGE_SIG;
|
|
|
|
ssDebugOut((DEB_ITRACE, "Out CFileStorage::InitFromHandle\n"));
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::~CFileStorage, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CFileStorage::~CFileStorage(void)
|
|
{
|
|
ssDebugOut((DEB_ITRACE, "In CFileStorage::~CFileStorage()\n"));
|
|
_sig = CFILESTORAGE_SIGDEL;
|
|
ssDebugOut((DEB_ITRACE, "Out CFileStorage::~CFileStorage\n"));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::CreateStream, public
|
|
//
|
|
// Synopsis: Creates a stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [reserved1]
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
// Notes: Files only support the contents stream
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::CreateStream(WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD reserved1,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SafeCNtFileStream pfs;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::CreateStream:%p("
|
|
"%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
|
|
reserved1, reserved2, ppstm));
|
|
|
|
ssChk(Validate());
|
|
if (lstrcmpiW(pwcsName, CONTENTS_STREAM) != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDFUNCTION);
|
|
// Contents always exist so fail if FAILIFTHERE
|
|
if ((grfMode & (STGM_CREATE | STGM_CONVERT)) == 0)
|
|
ssErr(EH_Err, STG_E_FILEALREADYEXISTS);
|
|
if (reserved1 != 0 || reserved2 != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
|
|
pfs.Attach(new CNtFileStream());
|
|
ssMem((CNtFileStream *)pfs);
|
|
ssAssert(_h != NULL);
|
|
ssChk(pfs->InitFromHandle(_h, grfMode, CO_CREATE, NULL));
|
|
TRANSFER_INTERFACE(pfs, IStream, ppstm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::CreateStream => %p\n", *ppstm));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::OpenStream, public
|
|
//
|
|
// Synopsis: Opens an existing stream
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [reserved1]
|
|
// [grfMode] - Permissions
|
|
// [reserved2]
|
|
// [ppstm] - Stream return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstm]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::OpenStream(WCHAR const *pwcsName,
|
|
void *reserved1,
|
|
DWORD grfMode,
|
|
DWORD reserved2,
|
|
IStream **ppstm)
|
|
{
|
|
SCODE sc;
|
|
SafeCNtFileStream pfs;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::OpenStream:%p("
|
|
"%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
|
|
grfMode, reserved2, ppstm));
|
|
|
|
ssChk(Validate());
|
|
if (lstrcmpiW(pwcsName, CONTENTS_STREAM) != 0)
|
|
ssErr(EH_Err, STG_E_FILENOTFOUND);
|
|
if (reserved1 != 0 || reserved2 != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
if (grfMode & (STGM_CREATE | STGM_CONVERT))
|
|
ssErr(EH_Err, STG_E_INVALIDFLAG);
|
|
|
|
pfs.Attach(new CNtFileStream());
|
|
ssMem((CNtFileStream *)pfs);
|
|
ssAssert(_h != NULL);
|
|
ssChk(pfs->InitFromHandle(_h, grfMode, CO_OPEN, NULL));
|
|
TRANSFER_INTERFACE(pfs, IStream, ppstm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::OpenStream => %p\n", *ppstm));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::CreateStorage, public
|
|
//
|
|
// Synopsis: Creates a child storage
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [grfMode] - Permissions
|
|
// [stgType] - Type of storage to create
|
|
// [pssSecurity] - Security
|
|
// [ppstg] - New storage return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::CreateStorage (
|
|
WCHAR const *pwcsName,
|
|
DWORD grfMode,
|
|
DWORD stgType,
|
|
LPSTGSECURITY pssSecurity,
|
|
IStorage **ppstg)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::CreateStorage:%p("
|
|
"%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
|
|
stgType, (LPSTGSECURITY)pssSecurity, ppstg));
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::OpenStorage, public
|
|
//
|
|
// Synopsis: Gets an existing child storage
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pstgPriority] - Priority reopens
|
|
// [grfMode] - Permissions
|
|
// [snbExclude] - Priority reopens
|
|
// [pssSecurity] - Security
|
|
// [ppstg] - Storage return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppstg]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::OpenStorage(WCHAR const *pwcsName,
|
|
IStorage *pstgPriority,
|
|
DWORD grfMode,
|
|
SNB snbExclude,
|
|
DWORD reserved,
|
|
IStorage **ppstg)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::OpenStorage:%p("
|
|
"%ws, %p, %lX, %p, %p, %p)\n", this, pwcsName, pstgPriority,
|
|
grfMode, snbExclude, reserved, ppstg));
|
|
return ssResult(STG_E_FILENOTFOUND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::CopyTo, public
|
|
//
|
|
// Synopsis: Makes a copy of a storage
|
|
//
|
|
// Arguments: [ciidExclude] - Length of rgiid array
|
|
// [rgiidExclude] - Array of IIDs to exclude
|
|
// [snbExclude] - Names to exclude
|
|
// [pstgDest] - Parent of copy
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::CopyTo(DWORD ciidExclude,
|
|
IID const *rgiidExclude,
|
|
SNB snbExclude,
|
|
IStorage *pstgDest)
|
|
{
|
|
SCODE sc;
|
|
SafeIStream pstm;
|
|
ULARGE_INTEGER cb;
|
|
ULONG i;
|
|
CDfName dfn;
|
|
SafeCNtFileStream pfs;
|
|
STATSTG stat;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::CopyTo:%p(%lu, %p, %p, %p)\n",
|
|
this, ciidExclude, rgiidExclude, snbExclude, pstgDest));
|
|
|
|
ssChk(Validate());
|
|
|
|
// Copy class ID and state bits if the destination supports them
|
|
ssChk(Stat(&stat, STATFLAG_NONAME));
|
|
sc = GetScode(pstgDest->SetClass(stat.clsid));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
ssErr(EH_Err, sc);
|
|
sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
|
|
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
|
|
ssErr(EH_Err, sc);
|
|
|
|
// Check exclusions
|
|
dfn.Set(CONTENTS_STREAM);
|
|
if (snbExclude != NULL && NameInSNB(&dfn, snbExclude))
|
|
ssErr(EH_Err, S_OK);
|
|
for (i = 0; i < ciidExclude; i++)
|
|
if (IsEqualIID(rgiidExclude[i], IID_IStream))
|
|
ssErr(EH_Err, S_OK);
|
|
|
|
// CONTENTS_STREAM is the only thing contained by a file
|
|
// storage, so copy it
|
|
|
|
pfs.Attach(new CNtFileStream());
|
|
ssMem((CNtFileStream *)pfs);
|
|
ssAssert(_h != NULL);
|
|
ssChk(pfs->InitFromHandle(_h, STGM_DIRECT | STGM_READ |
|
|
STGM_SHARE_DENY_NONE, CO_OPEN, NULL));
|
|
|
|
ssChk(GetScode(pstgDest->CreateStream(CONTENTS_STREAM, STGM_DIRECT |
|
|
STGM_WRITE |
|
|
STGM_SHARE_EXCLUSIVE |
|
|
STGM_CREATE,
|
|
0, NULL, &pstm)));
|
|
cb.LowPart = cb.HighPart = 0xffffffff;
|
|
sc = GetScode(pfs->CopyTo(pstm, cb, NULL, NULL));
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::CopyTo\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::MoveElementTo, public
|
|
//
|
|
// Synopsis: Move an element of a storage to another storage
|
|
//
|
|
// Arguments: [pwcsName] - Current name
|
|
// [ptcsNewName] - New name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Algorithm: Open source as storage or stream (whatever works)
|
|
// Create appropriate destination
|
|
// Copy source to destination
|
|
// Set create time of destination equal to create time of source
|
|
// If appropriate, delete source
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::MoveElementTo(WCHAR const *pwcsName,
|
|
IStorage *pstgParent,
|
|
WCHAR const *ptcsNewName,
|
|
DWORD grfFlags)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::MoveElementTo:%p("
|
|
"%ws, %p, %ws, %lu)\n", this, pwcsName, pstgParent,
|
|
ptcsNewName, grfFlags));
|
|
|
|
ssChk(Validate());
|
|
ssChk(VerifyMoveFlags(grfFlags));
|
|
|
|
sc = GenericMoveElement(this, pwcsName, pstgParent, ptcsNewName, grfFlags);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::MoveElementTo => %lX\n", sc));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::Commit, public
|
|
//
|
|
// Synopsis: Commits transacted changes
|
|
//
|
|
// Arguments: [dwFlags] - DFC_*
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::Commit(DWORD dwFlags)
|
|
{
|
|
NTSTATUS nts;
|
|
SCODE sc;
|
|
IO_STATUS_BLOCK iosb;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::Commit:%p(%lX)\n",
|
|
this, dwFlags));
|
|
|
|
ssChk(VerifyCommitFlags(dwFlags));
|
|
ssChk(Validate());
|
|
|
|
ssAssert(_h != NULL);
|
|
nts = NtFlushBuffersFile(_h, &iosb);
|
|
if (!NT_SUCCESS(nts))
|
|
sc = NtStatusToScode(nts);
|
|
else
|
|
sc = S_OK;
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::Commit => %lX\n", sc));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::Revert, public
|
|
//
|
|
// Synopsis: Reverts transacted changes
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::Revert(void)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::Revert:%p()\n", this));
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::EnumElements, public
|
|
//
|
|
// Synopsis: Starts an iterator
|
|
//
|
|
// Arguments: [reserved1]
|
|
// [reserved2]
|
|
// [reserved3]
|
|
// [ppenm] - Enumerator return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppenm]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::EnumElements(DWORD reserved1,
|
|
void *reserved2,
|
|
DWORD reserved3,
|
|
IEnumSTATSTG **ppenm)
|
|
{
|
|
SCODE sc;
|
|
SafeCFileEnum pfe;
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::EnumElements:%p("
|
|
"%lu, %p, %lu, %p)\n", this, reserved1, reserved2,
|
|
reserved3, ppenm));
|
|
|
|
if (reserved1 != 0 || reserved2 != NULL || reserved3 != 0)
|
|
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
|
|
ssChk(Validate());
|
|
|
|
pfe.Attach(new CFileEnum());
|
|
ssMem((CFileEnum *)pfe);
|
|
ssAssert(_h != NULL);
|
|
ssChk(pfe->InitFromHandle(_h, FALSE));
|
|
TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::EnumElements => %p\n",
|
|
*ppenm));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::DestroyElement, public
|
|
//
|
|
// Synopsis: Permanently deletes an element of a storage
|
|
//
|
|
// Arguments: [pwcsName] - Name of element
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::DestroyElement(WCHAR const *pwcsName)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::DestroyElement:%p(%ws)\n",
|
|
this, pwcsName));
|
|
if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
else
|
|
return ssResult(STG_E_FILENOTFOUND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::RenameElement, public
|
|
//
|
|
// Synopsis: Renames an element of a storage
|
|
//
|
|
// Arguments: [pwcsName] - Current name
|
|
// [pwcsNewName] - New name
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::RenameElement(WCHAR const *pwcsName,
|
|
WCHAR const *pwcsNewName)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::RenameElement:%p(%ws, %ws)\n",
|
|
this, pwcsName, pwcsNewName));
|
|
if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
|
|
{
|
|
if (lstrcmpiW(pwcsNewName, CONTENTS_STREAM) == 0)
|
|
return ssResult(STG_E_ACCESSDENIED);
|
|
else
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
}
|
|
else
|
|
return ssResult(STG_E_FILENOTFOUND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::SetElementTimes, public
|
|
//
|
|
// Synopsis: Sets element time stamps
|
|
//
|
|
// Arguments: [pwcsName] - Name
|
|
// [pctime] - Create time
|
|
// [patime] - Access time
|
|
// [pmtime] - Modify time
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::SetElementTimes(WCHAR const *pwcsName,
|
|
FILETIME const *pctime,
|
|
FILETIME const *patime,
|
|
FILETIME const *pmtime)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetElementTimes:%p("
|
|
"%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
|
|
if (lstrcmpiW(pwcsName, CONTENTS_STREAM) == 0)
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
else
|
|
return ssResult(STG_E_FILENOTFOUND);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::SetClass, public
|
|
//
|
|
// Synopsis: Sets storage class
|
|
//
|
|
// Arguments: [clsid] - class id
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::SetClass(REFCLSID clsid)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetClass:%p(clsid)\n", this));
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::SetStateBits, public
|
|
//
|
|
// Synopsis: Sets state bits
|
|
//
|
|
// Arguments: [grfStateBits] - state bits
|
|
// [grfMask] - state bits mask
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
|
|
{
|
|
ssDebugOut((DEB_TRACE, "Stb CFileStorage::SetStateBits:%p("
|
|
"%lu, %lu)\n", this, grfStateBits, grfMask));
|
|
return ssResult(STG_E_INVALIDFUNCTION);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: StrToLong, private
|
|
//
|
|
// Synopsis: Converts a string to a long value
|
|
//
|
|
// Arguments: [pwcs] - String
|
|
//
|
|
// Returns: LONG
|
|
//
|
|
// History: 27-Jul-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
static LONG StrToLong(WCHAR *pwcs)
|
|
{
|
|
LONG l = 0;
|
|
|
|
while (*pwcs >= L'0' && *pwcs <= L'9')
|
|
{
|
|
l = l*10+(int)*pwcs-(int)L'0';
|
|
pwcs++;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: Matches, private
|
|
//
|
|
// Synopsis: Determines if a file signature matches the given pattern
|
|
//
|
|
// Arguments: [h] - File handle
|
|
// [pwcsBuf] - Pattern
|
|
// [cb] - Size of pattern
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 27-Jul-93 DrewB Created from moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
static SCODE Matches(HANDLE h, WCHAR *pwcsBuf, ULONG cb)
|
|
{
|
|
// Parse <offset>,<cb>,<mask>,<pattern>
|
|
WCHAR *pwcs = pwcsBuf;
|
|
WCHAR *pwcsMask, *pwcsPattern;
|
|
int nOffset;
|
|
WORD wCb;
|
|
WORD wCtr;
|
|
BYTE bMask;
|
|
BYTE bPattern;
|
|
SafeBytePtr pbFileContents;
|
|
IO_STATUS_BLOCK iosb;
|
|
FILE_POSITION_INFORMATION fpi;
|
|
NTSTATUS nts;
|
|
LARGE_INTEGER liOriginalPos;
|
|
SCODE sc = S_FALSE;
|
|
|
|
PUSHORT pCharTypes = _alloca (sizeof (USHORT) * cb);
|
|
if (pCharTypes == NULL || !GetStringTypeW (CT_CTYPE1, pwcs, cb, pCharTypes)) {
|
|
goto EH_Err;
|
|
|
|
nOffset = (WORD)StrToLong(pwcs);
|
|
while (*pwcs && *pwcs != L',')
|
|
pwcs++;
|
|
ssAssert(*pwcs == L',');
|
|
pwcs++;
|
|
|
|
wCb = (WORD)StrToLong(pwcs);
|
|
ssAssert(wCb > 0);
|
|
while (*pwcs && *pwcs != L',')
|
|
pwcs++;
|
|
ssAssert(*pwcs == L',');
|
|
pwcs++;
|
|
|
|
while (pCharTypes[pwcs - pwcsBuf] & C1_SPACE)
|
|
pwcs++;
|
|
|
|
// pwcsMask points to the beginning of the mask
|
|
pwcsMask = pwcs;
|
|
pwcsPattern = pwcsMask;
|
|
while (*pwcsPattern && *pwcsPattern != L',')
|
|
pwcsPattern++;
|
|
ssAssert(*pwcsPattern == L',');
|
|
pwcsPattern++;
|
|
while (pCharTypes[pwcsPattern - pwcsBuf] & C1_SPACE)
|
|
pwcsPattern++;
|
|
|
|
pbFileContents.Attach(new BYTE[wCb]);
|
|
ssMem((BYTE *)pbFileContents);
|
|
|
|
// Remember the current file position
|
|
nts = NtQueryInformationFile(h, &iosb, &fpi,
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
FilePositionInformation);
|
|
if (!NT_SUCCESS(nts))
|
|
ssErr(EH_Err, NtStatusToScode(nts));
|
|
liOriginalPos = fpi.CurrentByteOffset;
|
|
|
|
// We seek to zero if necessary since we may have read from the file before
|
|
if (nOffset >= 0)
|
|
{
|
|
fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
|
|
fpi.CurrentByteOffset.HighPart = 0;
|
|
nts = NtSetInformationFile(h, &iosb, &fpi,
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
FilePositionInformation);
|
|
if (!NT_SUCCESS(nts))
|
|
ssErr(EH_Seek, NtStatusToScode(nts));
|
|
}
|
|
else if (nOffset < 0)
|
|
{
|
|
fpi.CurrentByteOffset.HighPart = -1;
|
|
fpi.CurrentByteOffset.LowPart = (ULONG)nOffset;
|
|
fpi.CurrentByteOffset.QuadPart =
|
|
fpi.CurrentByteOffset.QuadPart + liOriginalPos.QuadPart;
|
|
nts = NtSetInformationFile(h, &iosb, &fpi,
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
FilePositionInformation);
|
|
if (!NT_SUCCESS(nts))
|
|
ssErr(EH_Seek, NtStatusToScode(nts));
|
|
}
|
|
|
|
nts = NtReadFile(h, NULL, NULL, NULL, &iosb, pbFileContents, wCb,
|
|
NULL, NULL);
|
|
if (!NT_SUCCESS(nts))
|
|
ssErr(EH_Seek, NtStatusToScode(nts));
|
|
|
|
if (wCb == iosb.Information)
|
|
{
|
|
for (wCtr = 0; wCtr < wCb; wCtr++)
|
|
{
|
|
// Get the mask byte, 0xFF is the default
|
|
bMask = 0xFF;
|
|
if (pCharTypes[pwcsMask - pwcsBuf] & C1_XDIGIT)
|
|
{
|
|
bMask = pCharTypes[pwcsMask - pwcsBuf] & C1_DIGIT ? *pwcsMask - L'0' :
|
|
(WCHAR)CharUpperW((LPWSTR)*pwcsMask) - L'A' + 10;
|
|
pwcsMask++;
|
|
if (pCharTypes[pwcsMask - pwcsBuf] & C1_XDIGIT)
|
|
{
|
|
bMask *= 16;
|
|
bMask += pCharTypes[pwcsMask - pwcsBuf] & C1_DIGIT ? *pwcsMask - L'0' :
|
|
(WCHAR)CharUpperW((LPWSTR)*pwcsMask) - L'A' + 10;
|
|
pwcsMask++;
|
|
}
|
|
}
|
|
// Get the pattern byte
|
|
ssAssert(pCharTypes[pwcsPattern - pwcsBuf] & C1_XDIGIT);
|
|
bPattern = pCharTypes[pwcsPattern - pwcsBuf] & C1_DIGIT ? *pwcsPattern - L'0' :
|
|
(WCHAR)CharUpperW((LPWSTR)*pwcsPattern) - L'A' + 10;
|
|
pwcsPattern++;
|
|
ssAssert(pCharTypes[pwcsPattern - pwcsBuf] & C1_XDIGIT);
|
|
bPattern *= 16;
|
|
bPattern += pCharTypes[pwcsPattern - pwcsBuf] & C1_DIGIT ? *pwcsPattern - L'0' :
|
|
(WCHAR)CharUpperW((LPWSTR)*pwcsPattern) - L'A' + 10;
|
|
pwcsPattern++;
|
|
|
|
if ((BYTE)(*((BYTE *)pbFileContents + wCtr) & bMask) != bPattern)
|
|
ssErr(EH_Seek, S_FALSE);
|
|
}
|
|
sc = S_OK;
|
|
}
|
|
|
|
EH_Seek:
|
|
// Can't do anything about failure
|
|
fpi.CurrentByteOffset = liOriginalPos;
|
|
NtSetInformationFile(h, &iosb, &fpi,
|
|
sizeof(FILE_POSITION_INFORMATION),
|
|
FilePositionInformation);
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DoesMatchPattern, private
|
|
//
|
|
// Synopsis: Determines whether the given file matches its registry pattern
|
|
//
|
|
// Arguments: [h] - File handle
|
|
// [pclsid] - CLSID return if successful
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 27-Jul-93 DrewB Created from moniker code
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#define CB_DEF_BUFF 80
|
|
#define CB_DEF_NUM 10
|
|
#define CB_DEF_PATTERN 1024
|
|
|
|
SAFE_HEAP_MEMPTR(SafeWcharPtr, WCHAR);
|
|
|
|
static SCODE DoesMatchPattern(HANDLE h, CLSID *pclsid)
|
|
{
|
|
DWORD dwIndexClsid;
|
|
DWORD dwIndexPattern;
|
|
HKEY hkFileType;
|
|
HKEY hkClsid;
|
|
DWORD cbBuff = CB_DEF_BUFF;
|
|
DWORD cbNum = CB_DEF_NUM;
|
|
DWORD cbPattern = CB_DEF_PATTERN;
|
|
ULONG cb;
|
|
SafeWcharPtr pwcsBuff;
|
|
SafeWcharPtr pwcsPattern;
|
|
SafeWcharPtr pwcsNum;
|
|
SCODE sc = S_FALSE;
|
|
|
|
pwcsBuff.Attach(new TCHAR[CB_DEF_BUFF]);
|
|
ssMem((WCHAR *)pwcsBuff);
|
|
pwcsPattern.Attach(new TCHAR[CB_DEF_PATTERN]);
|
|
ssMem((WCHAR *)pwcsPattern);
|
|
pwcsNum.Attach(new TCHAR[CB_DEF_NUM]);
|
|
ssMem((WCHAR *)pwcsNum);
|
|
|
|
if (RegOpenKey(HKEY_CLASSES_ROOT, L"FileType", &hkFileType) ==
|
|
ERROR_SUCCESS)
|
|
{
|
|
for (dwIndexClsid = 0;
|
|
sc == S_FALSE &&
|
|
RegEnumKey(hkFileType, dwIndexClsid, pwcsBuff, cbBuff) ==
|
|
ERROR_SUCCESS;
|
|
++dwIndexClsid)
|
|
{
|
|
if (RegOpenKey(hkFileType, pwcsBuff, &hkClsid) == ERROR_SUCCESS)
|
|
{
|
|
for (dwIndexPattern = 0;
|
|
RegEnumKey(hkClsid, dwIndexPattern, pwcsNum, cbNum) ==
|
|
ERROR_SUCCESS;
|
|
++dwIndexPattern)
|
|
{
|
|
cb = cbPattern;
|
|
if (RegQueryValue(hkClsid, pwcsNum, pwcsPattern,
|
|
(LONG *)&cb) == ERROR_SUCCESS)
|
|
{
|
|
sc = Matches(h, pwcsPattern, cbPattern);
|
|
if (sc == S_OK)
|
|
CLSIDFromString(pwcsBuff, pclsid);
|
|
if (sc != S_FALSE)
|
|
break;
|
|
}
|
|
}
|
|
RegCloseKey(hkClsid);
|
|
}
|
|
}
|
|
RegCloseKey(hkFileType);
|
|
}
|
|
EH_Err:
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::Stat, public
|
|
//
|
|
// Synopsis: Fills in a buffer of information about this object
|
|
//
|
|
// Arguments: [pstatstg] - Buffer
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [pstatstg]
|
|
//
|
|
// History: 28-Jun-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
|
|
{
|
|
SCODE sc;
|
|
STATSTG stat;
|
|
FILEDIR fd;
|
|
CLSID clsid;
|
|
WCHAR awcName[MAX_PATH];
|
|
|
|
ssDebugOut((DEB_TRACE, "In CFileStorage::Stat:%p(%p, %lX)\n",
|
|
this, pstatstg, grfStatFlag));
|
|
|
|
ssChk(VerifyStatFlag(grfStatFlag));
|
|
ssChk(Validate());
|
|
|
|
__try
|
|
{
|
|
ssAssert(_h != NULL);
|
|
sc = StatNtHandle(_h, grfStatFlag, 0, &stat, awcName, NULL, &fd);
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
// Attempt to get a CLSID for this file
|
|
sc = DoesMatchPattern(_h, &clsid);
|
|
if (sc == S_FALSE)
|
|
{
|
|
WCHAR *pwcsExt;
|
|
|
|
// No pattern matched, so look up the class by extension
|
|
pwcsExt = FindExt(awcName);
|
|
if (pwcsExt != NULL && wCoGetClassExt(pwcsExt, &clsid) == 0)
|
|
sc = S_OK;
|
|
}
|
|
if (sc == S_OK)
|
|
stat.clsid = clsid;
|
|
if (SUCCEEDED(sc))
|
|
{
|
|
stat.grfMode = _grfMode;
|
|
stat.cbSize.HighPart = stat.cbSize.LowPart = 0;
|
|
stat.STATSTG_dwStgFmt = STGFMT_FILE;
|
|
*pstatstg = stat;
|
|
sc = S_OK;
|
|
}
|
|
else if (stat.pwcsName)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
if (stat.pwcsName)
|
|
ssVerSucc(CoMemFree(stat.pwcsName));
|
|
sc = HRESULT_FROM_NT(GetExceptionCode());
|
|
}
|
|
|
|
ssDebugOut((DEB_TRACE, "Out CFileStorage::Stat\n"));
|
|
EH_Err:
|
|
return ssResult(sc);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::ValidateMode, private
|
|
//
|
|
// Synopsis: Validates a grfMode
|
|
//
|
|
// Arguments: [grfMode] - Mode
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// History: 09-Jul-93 DrewB Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
SCODE CFileStorage::ValidateMode(DWORD grfMode)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssDebugOut((DEB_ITRACE, "In CFileStorage::ValidateMode:%p(0x%lX)\n",
|
|
this, grfMode));
|
|
// BUGBUG - Can we simply ignore priority mode?
|
|
if (grfMode & (STGM_TRANSACTED | STGM_CONVERT))
|
|
sc = STG_E_INVALIDFLAG;
|
|
else
|
|
sc = S_OK;
|
|
ssDebugOut((DEB_ITRACE, "Out CFileStorage::ValidateMode => 0x%lX\n", sc));
|
|
return sc;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CFileStorage::GetHandle, private
|
|
//
|
|
// Synopsis: Get the handle backing this Storage.
|
|
//
|
|
// History: 10-May-94 BillMo Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CFileStorage::GetHandle(HANDLE *ph)
|
|
{
|
|
SCODE sc;
|
|
|
|
ssChk(Validate());
|
|
|
|
*ph = _h;
|
|
|
|
EH_Err:
|
|
return(ssResult(sc));
|
|
}
|