NT4/private/ole32/stg/ofsstg/ofilstg.cxx
2020-09-30 17:12:29 +02:00

1117 lines
33 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: ofilstg.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 "ofsenm.hxx"
#include <iofs.h>
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::QueryInterface(REFIID iid, void **ppvObj)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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;
COfsFileStorage::AddRef();
}
else if (IsEqualIID(iid, IID_INativeFileSystem))
{
*ppvObj = (INativeFileSystem *)this;
COfsFileStorage::AddRef();
}
else
{
sc = E_NOINTERFACE;
*ppvObj = NULL;
}
ssDebugOut((DEB_TRACE, "Out COfsFileStorage::QueryInterface => %p\n",
*ppvObj));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::COfsFileStorage, public
//
// Synopsis: Empty object constructor
//
// History: 30-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
#pragma warning(disable: 4355)
COfsFileStorage::COfsFileStorage(void)
{
#pragma warning(default: 4355)
ssDebugOut((DEB_ITRACE, "In COfsFileStorage::COfsFileStorage:%p()\n",
this));
_sig = 0;
ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::COfsFileStorage\n"));
ENLIST_TRACKING(COfsFileStorage);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::InitFromPath(HANDLE hParent,
WCHAR const *pwcsName,
DWORD grfMode,
CREATEOPEN co,
LPSECURITY_ATTRIBUTES pssSecurity)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In COfsFileStorage::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 = COFSFILESTORAGE_SIG;
ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::InitFromPath\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::InitFromHandle(HANDLE h, DWORD grfMode)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In COfsFileStorage::InitFromHandle:%p("
"%p, %lX)\n", this, h, grfMode));
ssChk(ValidateMode(grfMode));
_h = h;
ssAssert(_h != NULL);
_grfMode = grfMode;
_sig = COFSFILESTORAGE_SIG;
ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::InitFromHandle\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::~COfsFileStorage, public
//
// Synopsis: Destructor
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
COfsFileStorage::~COfsFileStorage(void)
{
ssDebugOut((DEB_ITRACE, "In COfsFileStorage::~COfsFileStorage()\n"));
_sig = COFSFILESTORAGE_SIGDEL;
ssDebugOut((DEB_ITRACE, "Out COfsFileStorage::~COfsFileStorage\n"));
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::CreateStream(WCHAR const *pwcsName,
DWORD grfMode,
DWORD reserved1,
DWORD reserved2,
IStream **ppstm)
{
SCODE sc;
SafeCNtFileStream pfs;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::CreateStream:%p("
"%ws, %lX, %lu, %lu, %p)\n", this, pwcsName, grfMode,
reserved1, reserved2, ppstm));
ssChk(Validate());
if (_wcsicmp(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 COfsFileStorage::CreateStream => %p\n",
*ppstm));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::OpenStream(WCHAR const *pwcsName,
void *reserved1,
DWORD grfMode,
DWORD reserved2,
IStream **ppstm)
{
SCODE sc;
SafeCNtFileStream pfs;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::OpenStream:%p("
"%ws, %p, %lX, %lu, %p)\n", this, pwcsName, reserved1,
grfMode, reserved2, ppstm));
ssChk(Validate());
if (_wcsicmp(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 COfsFileStorage::OpenStream => %p\n", *ppstm));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::CreateStorage (
WCHAR const *pwcsName,
DWORD grfMode,
DWORD stgType,
LPSTGSECURITY pssSecurity,
IStorage **ppstg)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::CreateStorage:%p("
"%ws, %lX, %lu, %p, %p)\n", this, pwcsName, grfMode,
stgType, pssSecurity, ppstg));
return ssResult(STG_E_INVALIDFUNCTION);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::OpenStorage(WCHAR const *pwcsName,
IStorage *pstgPriority,
DWORD grfMode,
SNB snbExclude,
DWORD reserved,
IStorage **ppstg)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::OpenStorage:%p("
"%ws, %p, %lX, %p, %p, %p)\n", this, pwcsName, pstgPriority,
grfMode, snbExclude, reserved, ppstg));
return ssResult(STG_E_FILENOTFOUND);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::CopyTo(DWORD ciidExclude,
IID const *rgiidExclude,
SNB snbExclude,
IStorage *pstgDest)
{
SCODE sc;
ULONG i;
CDfName dfn;
BOOL fCopyStream = TRUE;
STATSTG stat;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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
olChk(Stat(&stat, STATFLAG_NONAME));
sc = GetScode(pstgDest->SetClass(stat.clsid));
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
olErr(EH_Err, sc);
sc = GetScode(pstgDest->SetStateBits(stat.grfStateBits, 0xffffffff));
if (FAILED(sc) && sc != STG_E_INVALIDFUNCTION)
olErr(EH_Err, sc);
// Check exclusions
dfn.Set(CONTENTS_STREAM);
if (snbExclude != NULL && NameInSNB(&dfn, snbExclude))
fCopyStream = FALSE;
for (i = 0; i < ciidExclude; i++)
if (IsEqualIID(rgiidExclude[i], IID_IStream))
{
fCopyStream = FALSE;
}
sc = S_OK;
if (fCopyStream)
{
SafeCNtFileStream pfs;
SafeIStream pstm;
ULARGE_INTEGER cb;
// 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 COfsFileStorage::CopyTo\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::MoveElementTo(WCHAR const *pwcsName,
IStorage *pstgParent,
WCHAR const *ptcsNewName,
DWORD grfFlags)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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 COfsFileStorage::MoveElementTo => %lX\n", sc));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::Commit, public
//
// Synopsis: Commits transacted changes
//
// Arguments: [dwFlags] - DFC_*
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsFileStorage::Commit(DWORD dwFlags)
{
NTSTATUS nts;
SCODE sc;
IO_STATUS_BLOCK iosb;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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 COfsFileStorage::Commit => %lX\n", sc));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::Revert, public
//
// Synopsis: Reverts transacted changes
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsFileStorage::Revert(void)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::Revert:%p()\n", this));
return NOERROR;
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::EnumElements(DWORD reserved1,
void *reserved2,
DWORD reserved3,
IEnumSTATSTG **ppenm)
{
SCODE sc;
SafeCOfsFileEnum pfe;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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 COfsFileEnum());
ssMem((COfsFileEnum *)pfe);
ssAssert(_h != NULL);
ssChk(pfe->InitFromHandle(_h, FALSE));
TRANSFER_INTERFACE(pfe, IEnumSTATSTG, ppenm);
ssDebugOut((DEB_TRACE, "Out COfsFileStorage::EnumElements => %p\n",
*ppenm));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::DestroyElement(WCHAR const *pwcsName)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::DestroyElement:%p(%ws)\n",
this, pwcsName));
if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
return ssResult(STG_E_INVALIDFUNCTION);
else
return ssResult(STG_E_FILENOTFOUND);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::RenameElement(WCHAR const *pwcsName,
WCHAR const *pwcsNewName)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::RenameElement:%p(%ws, %ws)\n",
this, pwcsName, pwcsNewName));
if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
{
if (_wcsicmp(pwcsNewName, CONTENTS_STREAM) == 0)
return ssResult(STG_E_ACCESSDENIED);
else
return ssResult(STG_E_INVALIDFUNCTION);
}
else
return ssResult(STG_E_FILENOTFOUND);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::SetElementTimes(WCHAR const *pwcsName,
FILETIME const *pctime,
FILETIME const *patime,
FILETIME const *pmtime)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::SetElementTimes:%p("
"%ws, %p, %p, %p)\n", this, pwcsName, pctime, patime, pmtime));
if (_wcsicmp(pwcsName, CONTENTS_STREAM) == 0)
return ssResult(STG_E_INVALIDFUNCTION);
else
return ssResult(STG_E_FILENOTFOUND);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::SetClass, public
//
// Synopsis: Sets storage class
//
// Arguments: [clsid] - class id
//
// Returns: Appropriate status code
//
// History: 28-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsFileStorage::SetClass(REFCLSID clsid)
{
SCODE sc;
ssDebugOut((DEB_TRACE, "In COfsFileStorage::SetClass:%p(clsid)\n", this));
sc = RtlSetClassId(_h, &clsid);
ssDebugOut((DEB_TRACE, "Out COfsFileStorage::SetClass => %lX\n", sc));
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::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 COfsFileStorage::SetStateBits(DWORD grfStateBits, DWORD grfMask)
{
ssDebugOut((DEB_TRACE, "Stb COfsFileStorage::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;
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 (iswspace(*pwcs))
pwcs++;
// pwcsMask points to the beginning of the mask
pwcsMask = pwcs;
pwcsPattern = pwcsMask;
while (*pwcsPattern && *pwcsPattern != L',')
pwcsPattern++;
ssAssert(*pwcsPattern == L',');
pwcsPattern++;
while (iswspace(*pwcsPattern))
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 (iswxdigit(*pwcsMask))
{
bMask = iswdigit(*pwcsMask) ? *pwcsMask - L'0' :
toupper(*pwcsMask) - L'A' + 10;
pwcsMask++;
if (iswxdigit(*pwcsMask))
{
bMask *= 16;
bMask += iswdigit(*pwcsMask) ? *pwcsMask - L'0' :
toupper(*pwcsMask) - L'A' + 10;
pwcsMask++;
}
}
// Get the pattern byte
ssAssert(iswxdigit(*pwcsPattern));
bPattern = iswdigit(*pwcsPattern) ? *pwcsPattern - L'0' :
toupper(*pwcsPattern) - L'A' + 10;
pwcsPattern++;
ssAssert(iswxdigit(*pwcsPattern));
bPattern *= 16;
bPattern += iswdigit(*pwcsPattern) ? *pwcsPattern - L'0' :
toupper(*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: COfsFileStorage::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
//
//----------------------------------------------------------------------------
// BUGBUG - Should be in an internal compobj header
HRESULT wCoGetClassExt(WCHAR const *pwcs, CLSID *clsid);
STDMETHODIMP COfsFileStorage::Stat(STATSTG *pstatstg, DWORD grfStatFlag)
{
SCODE sc;
STATSTG stat;
FILEDIR fd;
CLSID clsid;
WCHAR awcName[MAX_PATH];
ssDebugOut((DEB_TRACE, "In COfsFileStorage::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
clsid = stat.clsid;
if ((sc == S_FALSE) || (STATUS_NOT_FOUND == sc))
{
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 COfsFileStorage::Stat\n"));
EH_Err:
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::ValidateMode, private
//
// Synopsis: Validates a grfMode
//
// Arguments: [grfMode] - Mode
//
// Returns: Appropriate status code
//
// History: 09-Jul-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE COfsFileStorage::ValidateMode(DWORD grfMode)
{
SCODE sc;
ssDebugOut((DEB_ITRACE, "In COfsFileStorage::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 COfsFileStorage::ValidateMode => 0x%lX\n",
sc));
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::ExtValidate, private
//
// Synopsis: COfsPropSet validation routine
//
// History: 18-Aug-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE COfsFileStorage::ExtValidate(void)
{
return Validate();
}
//+---------------------------------------------------------------------------
//
// Member: COfsFileStorage::GetHandle, private
//
// Synopsis: Get the handle backing this OFS IStorage.
//
// History: 10-May-94 BillMo Created
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsFileStorage::GetHandle(HANDLE *ph)
{
SCODE sc;
ssChk(Validate());
*ph = _h;
EH_Err:
return(ssResult(sc));
}