alex 714dd74636 Archive Library versione 2.00
git-svn-id: svn://10.65.10.50/trunk@5350 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-10-09 16:09:54 +00:00

1133 lines
30 KiB
C++
Executable File

//
// MEMWIN.CPP
//
// Source file for ArchiveLib 2.0
//
// Copyright (c) Greenleaf Software, Inc. 1994-1996
// All Rights Reserved
//
// CONTENTS
//
// ALWinMemory::operator new()
// ALWinMemory::ALWinMemory()
// newALWinMemory()
// newALWinMemoryVB32()
// ALWinMemory::~ALWinMemory()
// ALWinMemory::_LoadBuffer( long address )
// ALWinMemory::Delete()
// ALWinMemory::GrowUserBuffer()
// ALWinMemory::_FlushBuffer( long address )
// ALWinMemory::Close()
// ALWinMemory::Create()
// ALWinMemory::Open()
// ALWinMemory::Clone()
// ALWinMemoryCopyBufferVB()
//
// DESCRIPTION
//
// This file contains all the code for ALWinMemory. This works hand
// in hand with ALMemoryBase.
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
#include "arclib.h"
#if !defined( AL_IBM )
#pragma hdrstop
#endif
#if defined( AL_VB )
#include "_vbutil.h"
#endif
//
// Problem here with PowerPack and others that use the NT
// API, but don't support the whole thing
//
#ifdef IsBadWritePtr
#undef IsBadWritePtr
#endif
#include <windows.h>
#include "memstore.h"
//
// NAME
//
// ALWinMemory::operator new()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Memory allocator used when ArchiveLib resides in a 16 bit DLL.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// void * ALWinMemory::operator new( size_t size )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// size : The number of bytes that the compiler has decided will be
// necessary to construct a new ALWinMemory object.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// NOTE!!!: Don't get confused about one thing. This function isn't
// allocating the buffer that's going to hold the data you
// write using functions such as WriteChar(). It is just
// allocating the space for the object itself!
//
// RETURNS
//
// A pointer to some memory that should have been pulled out of the
// heap for the DLL.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO
ALWinMemory::operator new( size_t size ) /* Tag protected function */
{
return ::new char[ size ];
}
#endif
//
// NAME
//
// ALWinMemory::ALWinMemory()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Create a Windows based memory object
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// ALWinMemory::ALWinMemory( const char *buffer_name = "",
// char *user_buffer = 0,
// DWORD user_buffer_size = 0,
// ALCase name_case = AL_MIXED );
//
// C SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// hALStorage newALWinMemory( char *buffer_name,
// char *user_buffer,
// DWORD user_buffer_size );
//
// VB SYNOPSIS
//
// Declare Function newALWinMemory Lib "AL20LW"
// (ByVal buffer_name$, ByVal user_buffer$, ByVal user_buffer_size&) As Long
//
// DELPHI SYNOPSIS
//
// function newALWinMemory( buffer_name : PChar;
// user_buffer : PChar;
// user_buffer_size : LongInt ) : hALStorage;
//
// ARGUMENTS
//
// buffer_name : An arbitrary name assigned to the buffer. Buffer
// names don't have to be unique, because buffers aren't
// named at the operating system level. But if you are
// going to insert the storage object into an archive, the
// name needs to be unique so that you will be able to
// extract it properly.
//
// user_buffer : If you want the ALMemory class to automatically allocate
// a buffer for you, and grow it as necessary, just leave
// this pointer set to 0. If you want to use your own buffer,
// which won't have the ability to grow, pass a pointer to
// it in this parameter. Note that under Windows 16 this
// is a huge pointer, meaning it can span segments, and
// access potentially 16 Mbytes of memory.
//
// user_buffer_size : If you are passing a pointer to your own buffer,
// you need to indicate how large it is here.
//
// name_case : This decides whether you want the file name to be
// case sensitive when making comparisons. MS-DOS
// file names are case-insensitive. You can make memory
// buffers either mixed case, forced upper, or forced
// lower. The default of mixed case means that comparisons
// will be case sensitive, which is fine. Note that I
// force C/VB/Delphi users to take the default of AL_MIXED.
//
// DESCRIPTION
//
// This constructor calls the base class constructor in an initializer
// list, which takes care of most of the dirty work right away. After that
// is done, all the constructor has to do is initialize a few data members.
// That should be self-explanatory. Remember that if the user doesn't
// supply a buffer, we are going to allocate it for her, but not until
// there is actually a demand for memory.
//
// RETURNS
//
// Under C/VB/Delphi, it returns a pointer to a newly constructed ALWinMemory
// object. Ditto if called via new under C++. O/W, returns nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
AL_PROTO ALWinMemory::ALWinMemory( /* Tag public function */
const char AL_DLL_FAR *buffer_name /* = "" */,
char AL_HUGE *user_buffer /* = 0 */,
DWORD user_buffer_size /* = 0 */,
ALCase name_case /* = AL_MIXED */ )
: ALMemoryBase( buffer_name, name_case )
{
#if 0
char buf[ 128 ];
wsprintf( buf,
"buffer_name = %s "
"user_buffer = %lx "
"user_buffer_size = %ld "
"name_case = %d",
buffer_name,
user_buffer,
user_buffer_size,
name_case );
MessageBox( 0, buf, "Title", MB_OK );
#endif
if ( user_buffer != 0 ) {
#if 0
strncpy( buf, user_buffer, 40 );
buf[ 40 ] = '\0';
MessageBox( 0, buf, "Preview", MB_OK );
#endif
mpcUserBuffer = user_buffer;
mfUserOwnsBuffer = 1;
mlUserBufferSize = user_buffer_size;
} else {
mfUserOwnsBuffer = 0;
mpcUserBuffer = 0;
mlUserBufferSize = 0;
}
mhUserMemoryHandle = 0;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE hALStorage AL_FUNCTION
newALWinMemory( char AL_DLL_FAR *buffer_name, /* Tag public function */
char AL_HUGE *user_buffer,
DWORD user_buffer_size )
{
if ( user_buffer_size == 0 )
return (hALStorage) new ALWinMemory( buffer_name );
else
return (hALStorage) new ALWinMemory( buffer_name, user_buffer, user_buffer_size );
}
#endif
//
// Note that things are a little different here for VB32.
// Instead of *using* the buffer passed here, we just
// make a copy of it.
//
#if defined( AL_VB32 )
extern "C" AL_LINKAGE hALStorage AL_FUNCTION
newALWinMemoryVB32( char AL_DLL_FAR *buffer_name, /* Tag public function */
LPSAFEARRAY *ppsa,
size_t user_buffer_size )
{
if ( user_buffer_size == 0 )
return (hALStorage) new ALWinMemory( buffer_name );
//
// I have to allocate some space, then do a copy into it.
//
ALWinMemory *m = new ALWinMemory( buffer_name, 0, 0 );
m->mhUserMemoryHandle = GlobalAlloc( GMEM_MOVEABLE, user_buffer_size );
if ( m->mhUserMemoryHandle ) {
m->mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) m->mhUserMemoryHandle );
m->mlUserBufferSize = user_buffer_size;
unsigned char *p;
SafeArrayAccessData( *ppsa, (void **) &p );
memcpy( m->mpcUserBuffer, p, user_buffer_size );
SafeArrayUnaccessData( *ppsa );
} else {
delete m;
return 0;
}
return (hALStorage) m;
}
#endif
//
// NAME
//
// ALWinMemory::~ALWinMemory()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// The destructor for ALWinMemory objects.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// ALWinMemory::~ALWinMemory()
//
// C SYNOPSIS
//
// None, C programs have to call the base class dtor, deleteALStorage().
//
// VB SYNOPSIS
//
// None, VB programs have to call the base class dtor, deleteALStorage().
//
// DELPHI SYNOPSIS
//
// None, Delphi programs have to call the base class dtor, deleteALStorage().
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// The destructor has just one thing it has to do before this object
// goes away. If the buffer that it has been using all along doesn't
// belong to the user, then it is the class's responsibility to get
// rid of it.
//
// Note also that we check the GoodTag() function when in Debug mode.
// That will help catch really bad mistakes, such as trying to delete
// an object that is not even an ALMemory object, maybe a beer can.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
AL_PROTO
ALWinMemory::~ALWinMemory() /* Tag public function */
{
AL_ASSERT( GoodTag(), "~ALWinMemory: attempting to delete invalid object" );
if ( !mfUserOwnsBuffer ) {
if ( mpcUserBuffer ) {
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
GlobalFree( (HGLOBAL) mhUserMemoryHandle );
mhUserMemoryHandle= 0;
mpcUserBuffer = 0;
}
}
AL_ASSERT( GoodTag(), "~ALWinMemory: attempting to delete invalid object" );
}
//
// NAME
//
// ALWinMemory::_LoadBuffer()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Read memory from the big buffer into the local I/O buffer.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// void ALWinMemory::_LoadBuffer( long address );
//
// C SYNOPSIS
//
// None, internal protected function.
//
// VB SYNOPSIS
//
// None, internal protected function.
//
// DELPHI SYNOPSIS
//
// None, internal protected functoin.
//
// ARGUMENTS
//
// address : The offset in the memory object that is going to be
// loaded.
//
// DESCRIPTION
//
// External users of an ALStorage class perform all of their access via
// a local I/O buffer. Functions such as ReadChar() and WriteChar() look
// at a thing called mpcBuffer for their data. When reading from
// mpcBuffer, you are going to run out of data from time to time. When
// this happens, you will generate a call to the virtual function
// LoadBuffer().
//
// As it happens, all of the ALMemory objects share a common version
// of LoadBuffer(). LoadBuffer() still has to call something a little
// more specialized though, and that's where this version of _LoadBuffer()
// comes into play. It just performs a memcpy() routine to actually move
// data out of the big memory buffer and into the local I/O buffer
// used by ReadChar() et. al.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
void AL_PROTO
ALWinMemory::_LoadBuffer( long address ) /* Tag protected function */
{
//
// Some problems passing huge arrays to memcpy, got to do it inline instead
// I think Microsoft says memcpy() will work with huge pointers as long
// as you don't try to use the inline optimizations, but I say why take
// chances...
//
// Another note: AL_HUGE is _huge for win16, but blank for win32.
//
char AL_HUGE *temp = mpcUserBuffer + address;
for ( unsigned int i = 0 ; i < muBufferValidData ; i++ )
mpcBuffer[ i ] = *temp++;
// memcpy( mpcBuffer, mpcUserBuffer + address, muBufferValidData );
}
//
// NAME
//
// ALWinMemory::Delete()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Delete the underlying buffer for the memory object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// int ALWinMemory::Delete();
//
// C SYNOPSIS
//
// None, C programs use the base class function deleteALStorage().
//
// VB SYNOPSIS
//
// None, VB programs use the base class function deleteALStorage().
//
// DELPHI SYNOPSIS
//
// None, Delphi programs use the base class function deleteALStorage().
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// This function is analogous to the unlink() RTL function for files. It
// has to close the file, and get rid of its big buffer. This is fairly
// easy with memory buffers, we just call GlobalFree() to delete the buffer.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALWinMemory::Delete() /* Tag public function */
{
if ( !mfUserOwnsBuffer ) {
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
GlobalFree( (HGLOBAL) mhUserMemoryHandle );
mhUserMemoryHandle= 0;
mpcUserBuffer = 0;
}
return AL_SUCCESS;
}
//
// NAME
//
// ALWinMemory::GrowUserBuffer()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Enlarge the user buffer.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// int ALWinMemory::GrowUserBuffer( long minimum_new_size );
//
// C SYNOPSIS
//
// None, this is an internal protected C++ function.
//
// VB SYNOPSIS
//
// None, this is an internal protected C++ function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal protected C++ function.
//
// ARGUMENTS
//
// minimum_new_size : This is the size that the caller absolutely must
// have to successfully perform a write. Anything
// less than this won't do.
//
// DESCRIPTION
//
// Sometimes a write to a memory object goes past the current end of the
// buffer. When this happens, code in the base class calls this
// function to attempt to enlarge the buffer.
//
// Enlarging the buffer is tricky, because you have to allocate new space,
// then copy the old buffer into the new buffer. This means you
// temporarily need a boot-load of space. If you are lucky, GlobalReallcoc()
// might be able to attempt to avoid this situation.
//
// We try to enlarge things by a fixed amount, large enough to prevent
// thrashing. But if that doesn't fly, we can fall back and try to
// enlarge to the minimum acceptable size.
//
// RETURNS
//
// AL_SUCCESS if all went well, some error code < AL_SUCCESS if not.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALWinMemory::GrowUserBuffer( long minimum_new_size ) /* Tag protected function */
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mfUserOwnsBuffer )
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Attempt to write past the end of a "
"user owned buffer for ALWinMemory "
"%s",
mName.GetSafeName() );
long trial_size = mlUserBufferSize + 16384;
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
HGLOBAL new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, trial_size, GMEM_MOVEABLE );
if ( new_handle == 0 ) {
trial_size = minimum_new_size;
new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, trial_size, GMEM_MOVEABLE );
}
if ( new_handle == 0 ) {
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"allocate a buffer "
"of %ld bytes for ALMemoryBase "
"%s",
minimum_new_size,
mName.GetSafeName() );
}
mpcUserBuffer = (char AL_HUGE *) GlobalLock( new_handle );
mhUserMemoryHandle = new_handle;
mlUserBufferSize = trial_size;
return AL_SUCCESS;
}
//
// NAME
//
// ALWinMemory::_FlushBuffer()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Flush data to the big buffer.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// void ALWinMemory::_FlushBuffer( long address )
//
// C SYNOPSIS
//
// None, internal protected C++ function.
//
// VB SYNOPSIS
//
// None, internal protected C++ function.
//
// DELPHI SYNOPSIS
//
// None, internal protected C++ function.
//
// ARGUMENTS
//
// address : The address in the big buffer where the flush should write
// to.
//
// DESCRIPTION
//
// When performing WriteChar() or WriteBuffer() operations, ALStorage
// causes output to be directed to a small I/O buffer. When this I/O
// buffer gets full, a call to ALFlushBuffer() is generated, which is
// supposed to dump that memory to a physical device.
//
// When ALMemoryBase gets a call to FlushBuffer(), it handles almost
// everything on its own. The one thing it can't handle, however, is
// the routine to copy the I/O buffer out to the big memory object.
// It has to really on this dinky virtual function to do the job.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
void AL_PROTO
ALWinMemory::_FlushBuffer( long address ) /* Tag protected function */
{
//
// Can't use memcpy with huge pointers, at least not with the optimized
// versions.
//
char AL_HUGE *temp = mpcUserBuffer + address;
for ( unsigned int i = 0 ; i < muWriteIndex ; i++ )
*temp++ = mpcBuffer[ i ];
// memcpy( mpcUserBuffer + mlFilePointer, mpcBuffer, muWriteIndex );
}
//
// NAME
//
// ALWinMemory::Close()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Close an open big memory buffer object
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// int ALWinMemory::Close()
//
// C SYNOPSIS
//
// C programs should use the base class function ALStorageClose().
//
// VB SYNOPSIS
//
// VB programs should use the base class function ALStorageClose().
//
// DELPHI SYNOPSIS
//
// Delphi programs should use the base class function ALStorageClose().
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// Close() is supposed to do the same thing to a memory buffer as fclose()
// in the RTL does to a file. The most important thing we are concerned
// about is that the I/O buffer gets freed up by the base class, so this
// suddenly might not be a giant heavyweight object any more.
//
// After freeing things up in the base class, we check to see if
// we have allocated more space than we really need. If so, we do
// a GlobalRealloc() of some sort to give space back to the O/S.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALWinMemory::Close() /* Tag public function */
{
ALMemoryBase::Close();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( !mfUserOwnsBuffer && mlSize < mlUserBufferSize ) {
GlobalUnlock( (HGLOBAL) mhUserMemoryHandle );
HGLOBAL new_handle = GlobalReAlloc( (HGLOBAL) mhUserMemoryHandle, mlSize, GMEM_MOVEABLE );
if ( new_handle != 0 )
mhUserMemoryHandle = new_handle;
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
mlUserBufferSize = mlSize;
}
return mStatus;
}
//
// NAME
//
// ALWinMemory::Create()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Create the memory storage object big buffer.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// int ALWinMemory::Create( long init_size );
//
// C SYNOPSIS
//
// C programs should use the base class function ALStorageCreate().
//
// VB SYNOPSIS
//
// VB programs should use the base class function ALStorageCreate().
//
// DELPHI SYNOPSIS
//
// Delphi programs should use the base class function ALStorageCreate().
//
// ARGUMENTS
//
// init_size : When you create an ALMemory object of any kind, you can
// write out data to it at your own pace, without having any
// idea how much space you will need. The storage object
// tries to increase its size every time you fill up
// the current huge buffer. Well, if you know in advance how
// much space you are going to need, you can allocate the
// whole buffer at once, and avoid all that extra work. So
// some calls to Create() now pass on an initial size using
// this argument.
//
// DESCRIPTION
//
// This is like creating a new file. If there isn't a memory buffer
// already assigned to this object, we create one, with an initial
// allocation of 16Kbytes, or more if requested.
//
// RETURNS
//
// Either AL_SUCCESS, or an unfriendly error code.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALWinMemory::Create( long init_size ) /* Tag public function */
{
ALMemoryBase::Create();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mpcUserBuffer )
return AL_SUCCESS; //If a buffer was already created somewhere down the
//line, we won't do it again.
if ( init_size == -1L )
init_size = 16384;
mhUserMemoryHandle = GlobalAlloc( GMEM_MOVEABLE, init_size );
if ( mhUserMemoryHandle ) {
mpcUserBuffer = (char AL_HUGE *) GlobalLock( (HGLOBAL) mhUserMemoryHandle );
mlUserBufferSize = init_size;
} else {
mpcUserBuffer = 0;
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Allocation failure when attempting to "
"create a buffer "
"of %ld bytes for ALWinMemory "
"%s in Create()",
init_size,
mName.GetSafeName() );
}
return mStatus;
}
//
// NAME
//
// ALWinMemory::Open()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Open an existing memory storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// int ALWinMemory::Open();
//
// C SYNOPSIS
//
// C programs should use the base class function ALStorageOpen().
//
// VB SYNOPSIS
//
// VB programs should use the base class function ALStorageOpen().
//
// DELPHI SYNOPSIS
//
// Delphi programs should use the base class function ALStorageOpen().
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// This is like opening an existing file. Since there is supposed to be
// an existing memory buffer already, we gripe if we can't find one.
//
// RETURNS
//
// Either AL_SUCCESS, or an unfriendly error code.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALWinMemory::Open() /* Tag public function */
{
ALMemoryBase::Open();
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( mpcUserBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_FILE,
"Attempt to open ALWinMemory %s "
"with no buffer allocated",
mName.GetSafeName() );
else
mlSize = mlUserBufferSize;
return AL_SUCCESS;
}
//
// NAME
//
// ALWinMemory::Clone()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// C++
//
// SHORT DESCRIPTION
//
// Clone this memory based storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "memstore.h"
//
// ALStorage ALWinMemory::Clone( const char *name,
// int object_type ) const;
//
// C SYNOPSIS
//
// None, this is an internal C++ function
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// name : The desired name of the new object. Usually this will
// be a name found in an Archive directory.
//
// object_type : The type of object we want to create. Only
// AL_STORAGE_DEFAULT and AL_MEMORY_OBJECT will cause this
// function to succeed.
//
// DESCRIPTION
//
// The virtual Clone() function is used by archiving programs to act
// as a virtual constructor. When preparing to create storage objects
// based on the contents of an Archive directory, the archiving code can
// call Clone() for all the storage objects in its toolkit until it finds
// one that responds to its object type.
//
// For example, if an archive contained an AL_MEMORY object, and we were
// extracting, and an ALFile object was in the toolkit, it would call
// ALFile::Clone() from the toolkit object, with an object type of
// AL_MEMORY_OBJECT. This Clone() function would fail. Hopefully, there
// would be a memory based storage object in the toolkit that would
// respond properly to the Clone() call.
//
// Another object in the same archive might have an AL_FILE_OBJECT type.
// When the archiving code called Clone() again with that object type,
// we would successfully create the new File object in Clone().
//
// RETURNS
//
// Either a pointer to a newly constructed ALHugeMemory object, or a zero
// in case of error.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
ALStorage AL_DLL_FAR *
ALWinMemory::Clone( const char AL_DLL_FAR *name, /* Tag public function */
int object_type ) const
{
switch ( object_type ) {
case AL_STORAGE_DEFAULT :
case AL_MEMORY_OBJECT :
return new ALMemory( name );
}
return 0;
}
//
// NAME
//
// ALWinMemoryCopyBufferVB()
//
// PLATFORMS/ENVIRONMENTS
//
// Windows
// VB
//
// SHORT DESCRIPTION
//
// Copy the contents of an ALWinMemory object to a VB string.
//
// C++ SYNOPSIS
//
// None, only useful to VB programs.
//
// C SYNOPSIS
//
// None, only useful to VB programs.
//
// VB SYNOPSIS
//
// Declare Function ALWinMemoryCopyBufferVB Lib "AL20LW"
// (ByVal this_object&) As String
//
// DELPHI SYNOPSIS
//
// None, only useful to VB programs.
//
// ARGUMENTS
//
// this_object : A handle for (pointer to) an ALWinMemory object.
//
// DESCRIPTION
//
// This VB translation function provides access to the data stored
// in the buffer of an ALWinMemory object. It does this by creating a
// VB string with a copy of the data. We don't do any checking here,
// so it is possible to abort VB if the string is too large.
//
// This function was sort of a missing link in our ability to handle
// memory objects in VB. It was always easy to convert a VB string to
// an ALWinMemory object, but we didn't have any good way to make the
// reverse trip.
//
// RETURNS
//
// A VB string that contains the contents of the memory object.
// Note that the memory object is still there, unchanged, but now
// you can easily get at its data using VB.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
#if defined( AL_VB )
extern "C" long AL_FUNCTION
ALWinMemoryCopyBufferVB( hALStorage this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALWinMemory, "ALWinMemoryCopyBufferVB" );
( (ALWinMemory *) this_object )->FlushBuffer();
return ALCreateVBString( (char _far *) ( (ALWinMemory *) this_object )->mpcUserBuffer,
(unsigned short int) ( (ALWinMemory *) this_object )->GetSize() );
}
#endif