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

382 lines
9.6 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: reserved.cxx
//
// Contents: Class that implements reserved memory for properties.
// This implementation is in the form of two derivations
// of the CReservedMemory class.
//
// Classes: CWin32ReservedMemory
// CWin31ReservedMemory
//
// History: 1-Mar-95 BillMo Created.
// 29-Aug-96 MikeHill Split CReservedMemory into CWin31 & CWin32
//
// Notes:
//
// Codework:
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#include "reserved.hxx"
#ifdef _MAC_NODOC
ASSERTDATA // File-specific data for FnAssert
#endif
// Instantiate the appropriate object.
#ifdef _MAC
CWin31ReservedMemory g_ReservedMemory;
#else
CWin32ReservedMemory g_ReservedMemory;
#endif
//+----------------------------------------------------------------------------
//
// Method: CWin32ReservedMemory::_Init
//
// Synopsis: Prepare as much as possible during initialization, in order
// to be able to provide memory in LockMemory.
//
// Inputs: None.
//
// Returns: None.
//
//+----------------------------------------------------------------------------
#ifndef _MAC
HRESULT
CWin32ReservedMemory::_Init(VOID)
{
HRESULT hr = E_FAIL;
SID_IDENTIFIER_AUTHORITY Sa = SECURITY_CREATOR_SID_AUTHORITY;
ULONG cInits;
// Ensure this method is called once and only once. This
// is necessary since this class is implemented as a global
// variable.
cInits = InterlockedIncrement( &_cInits );
if( 1 < cInits )
{
// We've already been initialized (probably simultaneously
// in another thread). NOTE: This leaves one small race where
// this thread really needs to use the reserved memory before
// the other thread has finished initializing it. If that window
// is hit, it won't cause a corruption, but will cause an out-of-mem
// error to occur.
InterlockedDecrement( &_cInits );
hr = S_OK;
goto Exit;
}
// Create a creator/owner SID. We'll give the creator/owner
// full access to the temp file.
if( !AllocateAndInitializeSid( &Sa, // Top-level authority
1,
SECURITY_CREATOR_OWNER_RID,
0, 0, 0, 0, 0, 0, 0,
&_pCreatorOwner ))
{
hr = HRESULT_FROM_WIN32( GetLastError() );
_pCreatorOwner = NULL;
goto Exit;
}
// Create a DACL that just gives the Creator/Owner full access.
if (!InitializeAcl( &_DaclBuffer.acl, sizeof(_DaclBuffer), ACL_REVISION))
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Exit;
}
if (!AddAccessAllowedAce( &_DaclBuffer.acl,
ACL_REVISION,
STANDARD_RIGHTS_ALL | GENERIC_ALL,
_pCreatorOwner
))
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Exit;
}
// Set up the security descriptor with that DACL in it.
InitializeSecurityDescriptor( &_sd, SECURITY_DESCRIPTOR_REVISION );
if( !SetSecurityDescriptorDacl( &_sd, TRUE, &_DaclBuffer.acl, FALSE ))
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Exit;
}
// Put the security descriptor into the security attributes.
memset( &_secattr, 0, sizeof(_secattr) );
_secattr.nLength = sizeof(SECURITY_ATTRIBUTES);
_secattr.lpSecurityDescriptor = &_sd;
_secattr.bInheritHandle = FALSE;
// Initialize the critical section.
__try
{
InitializeCriticalSection( &_critsec );
_fInitialized = TRUE;
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
hr = HRESULT_FROM_WIN32( GetExceptionCode() );
goto Exit;
}
hr = S_OK;
Exit:
return hr;
}
#endif // #ifndef _MAC
//+----------------------------------------------------------------------------
//
// Method: CWin32ReservedMemory::~CWin32ReservedMemory
//
// Inputs: N/A
//
// Returns: N/A
//
//+----------------------------------------------------------------------------
#ifndef _MAC
CWin32ReservedMemory::~CWin32ReservedMemory()
{
if( _fInitialized )
DeleteCriticalSection( &_critsec );
if( NULL != _pCreatorOwner )
FreeSid( _pCreatorOwner );
FreeResources();
}
//+----------------------------------------------------------------------------
//
// Method: CWin32ReservedMemory::FreeResources
//
// Inputs: N/A
//
// Returns: Void
//
// Synopsis: Free the view, the mapping, and the file.
//
//+----------------------------------------------------------------------------
void
CWin32ReservedMemory::FreeResources()
{
if( NULL != _pb )
{
UnmapViewOfFile( _pb );
_pb = NULL;
}
if( NULL != _hMapping )
{
CloseHandle( _hMapping );
_hMapping = NULL;
}
if( INVALID_HANDLE_VALUE != _hFile )
{
CloseHandle( _hFile );
_hFile = INVALID_HANDLE_VALUE;
}
}
#endif // #ifndef _MAC
//+----------------------------------------------------------------------------
//
// Method: CWin32ReservedMemory::LockMemory
//
// Synopsis: Use a temporary file to get enough memory to hold the
// largest possible property set and return a pointer to
// that mapping.
//
// Inputs: None.
//
// Returns: Lock() returns a pointer to the locked memory.
//
//+----------------------------------------------------------------------------
#ifndef _MAC
BYTE * CWin32ReservedMemory::LockMemory(VOID)
{
WCHAR wszTempFileName[ MAX_PATH + 64 ];
ULONG cchPath = 0;
// If for some reason initialization failed, there's nothing we can do,
// we'll return NULL.
if( !_fInitialized )
goto Exit;
// Lock down this class until the caller has completed.
// This isn't really necessary, since this class could be
// a member variable instead of a global, but that is too
// much of a change for NT5.
EnterCriticalSection( &_critsec );
// Get the temp directory.
cchPath = GetTempPath( MAX_PATH + 1, wszTempFileName );
if( 0 == cchPath || cchPath > MAX_PATH + 1 )
goto Exit;
// Create a temporary file. We can't use GetTempFileName, because it creates
// the file, and consequently the DACL we pass in on CreateFile gets ignored.
SYSTEMTIME st;
FILETIME ft;
GetSystemTime( &st );
SystemTimeToFileTime( &st, &ft );
wsprintf( &wszTempFileName[cchPath], L"OLEPROPSTG_%08x%08x.tmp",
ft.dwHighDateTime, ft.dwLowDateTime );
_hFile = CreateFile( wszTempFileName,
GENERIC_WRITE|GENERIC_READ|DELETE,
0,
&_secattr,
CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
INVALID_HANDLE_VALUE );
if( INVALID_HANDLE_VALUE == _hFile )
goto Exit;
// Map the temporary file.
_hMapping = CreateFileMappingA(_hFile, // handle of file to map
NULL, // optional security attributes
PAGE_READWRITE, // protection for mapping object
0, // high-order 32 bits of object size
CBMAXPROPSETSTREAM, // low-order 32 bits of object size
NULL); // name of file-mapping object
if( NULL == _hMapping )
goto Exit;
// Map a view.
_pb = (BYTE*)MapViewOfFile(_hMapping, // file-mapping object to map into address space
FILE_MAP_WRITE, // access mode
0, // high-order 32 bits of file offset
0, // low-order 32 bits of file offset
0); // number of bytes to map
if( NULL == _pb )
goto Exit;
Exit:
// If there was an error, free everything.
if( NULL == _pb )
{
FreeResources();
LeaveCriticalSection( &_critsec );
}
return _pb;
}
//+----------------------------------------------------------------------------
//
// Method: CWin32ReservedMemory
//
// Synopsis: Free the temp file and its mapping, and leave the critical
// section.
//
//+----------------------------------------------------------------------------
VOID CWin32ReservedMemory::UnlockMemory(VOID)
{
FreeResources();
LeaveCriticalSection( &_critsec );
}
#endif // #ifndef _MAC
//+----------------------------------------------------------------------------
//
// Method: CWin31ReservedMemory::LockMemory/UnlockMemory
//
// Synopsis: This derivation of the CReservedMemory does not provide
// a locking mechanism, so no locking is performed. The Lock
// method simply returns the shared memory buffer.
//
// Inputs: None.
//
// Returns: Nothing
//
//+----------------------------------------------------------------------------
#ifdef _MAC
BYTE * CWin31ReservedMemory::LockMemory(VOID)
{
DfpAssert( !_fLocked );
#if DBG==1
_fLocked = TRUE;
#endif
return (BYTE*) g_pbPropSetReserved;
}
VOID CWin31ReservedMemory::UnlockMemory(VOID)
{
// No locking required on the Mac.
DfpAssert( _fLocked );
#if DBG==1
_fLocked = FALSE;
#endif
}
#endif // #ifdef _MAC