windows-nt/Source/XPSP1/NT/com/ole32/stg/msf/msf.cxx
2020-09-26 16:20:57 +08:00

475 lines
12 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: msf.cxx
//
// Contents: Entry points for MSF DLL
//
// Classes: None.
//
// Functions: DllMuliStreamFromStream
// DllConvertStreamToMultiStream
// DllReleaseMultiStream
// DllGetScratchMultiStream
// DllIsMultiStream
//
// History: 17-Aug-91 PhilipLa Created.
//
//--------------------------------------------------------------------------
#include "msfhead.cxx"
#pragma hdrstop
#include <handle.hxx>
#include <filelkb.hxx>
#include <ole.hxx>
#include <entry.hxx>
#include <smalloc.hxx>
//+-------------------------------------------------------------------------
//
// Function: DllMultiStreamFromStream
//
// Synopsis: Create a new multistream instance from an existing stream.
// This is used to reopen a stored multi-stream.
//
// Effects: Creates a new CMStream instance
//
// Arguments: [ppms] -- Pointer to storage for return of multistream
// [pplstStream] -- Stream to be used by multi-stream for
// reads and writes
// [dwFlags] - Startup flags
//
// Returns: STG_E_INVALIDHEADER if signature on pStream does not
// match.
// STG_E_UNKNOWN if there was a problem in setup.
// S_OK if call completed OK.
//
// Algorithm: Check the signature on the pStream and on the contents
// of the pStream. If either is a mismatch, return
// STG_E_INVALIDHEADER.
// Create a new CMStream instance and run the setup function.
// If the setup function fails, return STG_E_UNKNOWN.
// Otherwise, return S_OK.
//
// History: 17-Aug-91 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE DllMultiStreamFromStream(IMalloc *pMalloc,
CMStream **ppms,
ILockBytes **pplstStream,
DWORD dwStartFlags,
DFLAGS df)
{
SCODE sc;
CMStream *temp;
BOOL fConvert = ((dwStartFlags & RSF_CONVERT) != 0);
BOOL fDelay = ((dwStartFlags & RSF_DELAY) != 0);
BOOL fTruncate = ((dwStartFlags & RSF_TRUNCATE) != 0);
BOOL fCreate = ((dwStartFlags & RSF_CREATE) != 0);
msfDebugOut((DEB_ITRACE,"In DllMultiStreamFromStream\n"));
#ifdef USE_NOSCRATCH
msfMem(temp = new (pMalloc)
CMStream(pMalloc, pplstStream,
FALSE,
(df & ~DF_NOSCRATCH),
(dwStartFlags & RSF_SECTORSIZE_MASK) ?
(USHORT)((dwStartFlags & RSF_SECTORSIZE_MASK) >> 12) :
SECTORSHIFT512));
#else
msfMem(temp = new (pMalloc)
CMStream(pMalloc, pplstStream,
FALSE,
(dwStartFlags & RSF_SECTORSIZE_MASK) ?
(USHORT)((dwStartFlags & RSF_SECTORSIZE_MASK) >> 12) :
SECTORSHIFT512));
#endif //USE_NOSCRATCH
STATSTG stat;
HRESULT hr;
IFileLockBytes *pfl;
// ILockBytes::Stat is an expensive operation; for our own file
// stream we call our faster GetSize method.
if (SUCCEEDED((*pplstStream)->QueryInterface(IID_IFileLockBytes,
(void**) &pfl)))
{
msfAssert(pfl != NULL &&
aMsg("ILockBytes::QueryInterface succeeded but returned NULL"));
hr = pfl->GetSize(&stat.cbSize);
pfl->Release();
}
else
hr = (*pplstStream)->Stat(&stat, STATFLAG_NONAME);
msfHChk(hr);
msfDebugOut((DEB_ITRACE,"Size is: %lu\n",ULIGetLow(stat.cbSize)));
do
{
if ((stat.cbSize.QuadPart != 0) && (fConvert))
{
msfChk(temp->InitConvert(fDelay));
break;
}
if ((stat.cbSize.QuadPart == 0 && fCreate) || (fTruncate))
{
msfChk(temp->InitNew(fDelay, stat.cbSize));
break;
}
msfChk(temp->Init());
}
while (FALSE);
*ppms = temp;
msfDebugOut((DEB_ITRACE,"Leaving DllMultiStreamFromStream\n"));
if (fConvert && (stat.cbSize.QuadPart != 0) && !fDelay)
{
return STG_S_CONVERTED;
}
return S_OK;
Err:
#if !defined(MULTIHEAP)
//take the mutex here instead of in the allocator.
g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
#endif
delete temp;
#if !defined(MULTIHEAP)
g_smAllocator.GetMutex()->Release();
#endif
return sc;
}
//+-------------------------------------------------------------------------
//
// Function: DllReleaseMultiStream
//
// Synopsis: Release a CMStream instance
//
// Effects: Deletes a multi-stream instance
//
// Arguments: [pms] -- pointer to object to be deleted
//
// Returns: S_OK.
//
// Modifies: Deletes the object pointed to by pMultiStream
//
// Algorithm: Delete the passed in pointer.
//
// History: 17-Aug-91 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
void DllReleaseMultiStream(CMStream *pms)
{
msfDebugOut((DEB_ITRACE,"In DllReleaseMultiStream(%p)\n",pms));
#if !defined(MULTIHEAP)
//take the mutex here instead of in the allocator.
g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
#endif
delete pms;
#if !defined(MULTIHEAP)
g_smAllocator.GetMutex()->Release();
#endif
msfDebugOut((DEB_ITRACE,"Out DllReleaseMultiStream()\n"));
}
//+-------------------------------------------------------------------------
//
// Function: DllGetScratchMultiStream
//
// Synopsis: Get a scratch multistream for a given LStream
//
// Effects: Creates new MStream instance and new handle
//
// Arguments: [ppms] -- pointer to location in which root
// handle is to be returned.
// [pplstStream] -- pointer to LStream object to be used
// [pmsMaster] - Multistream to pattern scratch after
//
// Returns: S_OK if call completed OK.
// STG_E_UNKNOWN if there was a problem in setup.
//
// Algorithm: *Finish This*
//
// History: 08-Jan-91 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE DllGetScratchMultiStream(CMStream **ppms,
#ifdef USE_NOSCRATCH
BOOL fIsNoScratch,
#endif
ILockBytes **pplstStream,
CMStream *pmsMaster)
{
msfDebugOut((DEB_ITRACE,"In DllGetScratchMultiStream(%p,%p,%p)\n",ppms,pplstStream,pmsMaster));
SCODE sc;
ULARGE_INTEGER uliZero;
CMStream *temp = NULL;
#ifdef USE_NOSCRATCH
msfMem(temp = new (pmsMaster->GetMalloc())
CMStream(pmsMaster->GetMalloc(), pplstStream,
TRUE,
(fIsNoScratch) ? DF_NOSCRATCH : 0,
SCRATCHSECTORSHIFT));
#else
msfMem(temp = new (pmsMaster->GetMalloc())
CMStream(pmsMaster->GetMalloc(), pplstStream,
TRUE,
SCRATCHSECTORSHIFT));
#endif
ULISetHigh(uliZero, 0);
ULISetLow(uliZero, 0);
msfChk(temp->InitNew(FALSE, uliZero));
*ppms = temp;
msfDebugOut((DEB_ITRACE,"Out DllGetScratchMultiStream()\n"));
return S_OK;
Err:
#if !defined(MULTIHEAP)
//take the mutex here instead of in the allocator
g_smAllocator.GetMutex()->Take(DFM_TIMEOUT);
#endif
delete temp;
#if !defined(MULTIHEAP)
g_smAllocator.GetMutex()->Release();
#endif
return sc;
}
//+-------------------------------------------------------------------------
//
// Function: DllIsMultiStream
//
// Synopsis: Check a given Lstream to determine if it is a valid
// multistream.
//
// Arguments: [plst] -- Pointer to lstream to check
//
// Returns: S_OK if lstream is a valid multistream
// STG_E_UNKNOWN otherwise
//
// History: 20-Feb-92 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE DllIsMultiStream(ILockBytes *plst)
{
SCODE sc;
CMSFHeader *phdr;
ULONG ul;
ULONG ulSectorSize = HEADERSIZE;
IFileLockBytes *pfl;
if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
{
ulSectorSize = pfl->GetSectorSize();
pfl->Release();
}
// CMSFHeader can be larger than a sector due to its dirty flag
ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
ULONG ulTemp;
ULARGE_INTEGER ulOffset;
ULISet32(ulOffset, 0);
msfHChk(plst->ReadAt(
ulOffset,
phdr->GetData(),
ulSectorSize,
&ulTemp));
if (ulTemp != ulSectorSize)
{
msfErr(Err, STG_E_UNKNOWN);
}
msfChk(phdr->Validate());
Err:
FreeBuffer((BYTE *) phdr);
return sc;
}
//+-------------------------------------------------------------------------
//
// Function: DllSetCommitSig
//
// Synopsis: Set the commit signature on a given lstream, for use
// in OnlyIfCurrent support
//
// Arguments: [plst] -- Pointer to the LStream to modify.
// [sig] -- New signature
//
// Returns: S_OK if call completed OK.
//
// Algorithm:
//
// History: 22-Apr-92 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE DllSetCommitSig(ILockBytes *plst, DFSIGNATURE sig)
{
SCODE sc;
CMSFHeader *phdr;
ULONG ul;
ULONG ulSectorSize = HEADERSIZE;
IFileLockBytes *pfl;
if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
{
ulSectorSize = pfl->GetSectorSize();
pfl->Release();
}
// CMSFHeader can be larger than a sector due to its dirty flag
ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
ULONG ulTemp;
ULARGE_INTEGER ulOffset;
ULISet32(ulOffset, 0);
msfHChk(plst->ReadAt(
ulOffset,
phdr->GetData(),
ulSectorSize,
&ulTemp));
if (ulTemp != ulSectorSize)
{
msfErr(Err, STG_E_UNKNOWN);
}
msfChk(phdr->Validate());
phdr->SetCommitSig(sig);
msfHChk(plst->WriteAt(ulOffset,
phdr->GetData(),
ulSectorSize,
&ulTemp));
if (ulTemp != ulSectorSize)
{
msfErr(Err,STG_E_UNKNOWN);
}
Err:
FreeBuffer((BYTE *) phdr);
return sc;
}
//+-------------------------------------------------------------------------
//
// Function: DllGetCommitSig
//
// Synopsis: Get the commit signature from an lstream
//
// Arguments: [plst] -- Pointer to lstream to be operated on
// [psig] -- Storage place for signature return
//
// Returns: S_OK if call completed OK.
//
// Algorithm:
//
// History: 22-Apr-92 PhilipLa Created.
//
// Notes:
//
//--------------------------------------------------------------------------
SCODE DllGetCommitSig(ILockBytes *plst, DFSIGNATURE *psig)
{
CMSFHeader *phdr;
SCODE sc;
ULONG ul;
ULONG ulSectorSize = HEADERSIZE;
IFileLockBytes *pfl;
if (SUCCEEDED(plst->QueryInterface(IID_IFileLockBytes, (void**) &pfl)))
{
ulSectorSize = pfl->GetSectorSize();
pfl->Release();
}
// CMSFHeader can be larger than a sector due to its dirty flag
ul = ulSectorSize < sizeof(CMSFHeader) ? sizeof(CMSFHeader) : ulSectorSize;
GetSafeBuffer(ul, ul, (BYTE **) &phdr, &ul);
ULONG ulTemp;
ULARGE_INTEGER ulOffset;
ULISet32(ulOffset, 0);
msfHChk(plst->ReadAt(
ulOffset,
phdr->GetData(),
ulSectorSize,
&ulTemp));
if (ulTemp != ulSectorSize)
{
msfErr(Err, STG_E_UNKNOWN);
}
msfChk(phdr->Validate());
*psig = phdr->GetCommitSig();
Err:
FreeBuffer((BYTE *) phdr);
return sc;
}
#if DBG == 1
//The following is a private function so I can set the debug level easily.
VOID SetInfoLevel(ULONG x)
{
#if DBG == 1
msfInfoLevel=x;
_SetWin4InfoLevel(0xFFFFFFFF);
#endif
}
#endif