// ---------------------------------------------------------------------------- // MODULE : OLECore.cpp // LANGUAGE : C++ // AUTHOR : Yue Zhang // DATE : Tuesday, Janurary 23, 1996 // DESCRIPTION : This file defines an object which is common to all enhanced // OLE objects // COMMENT : Enhanced OLE objects which are platform independent // SCCSID : @(#)olecore.cpp 1.5 10:45:11 12 Sep 1997 // ---------------------------------------------------------------------------- // Copyright (c) 1999 Digital Imaging Group, Inc. // For conditions of distribution and use, see copyright notice // in Flashpix.h // Includes // -------- #ifndef Debug_h #include "debug.h" #endif #if defined(_WINDOWS) #include "b_error.h" #endif #ifndef OLECommun_h #include "olecomm.h" #endif #ifndef OLECore_h #include "olecore.h" #endif #ifndef OLEProperties_h #include "oleprop.h" #endif // Constants // --------- // These strings are used to print the types of the properties in the test code static const char* variantName[] = { "VT_EMPTY", // 0 "VT_NULL", "VT_I2", "VT_I4", "VT_R4", "VT_R8", // 5 "VT_CY", "VT_DATE", "VT_BSTR", "VT_DISPATCH", "VT_ERROR", // 10 "VT_BOOL", "VT_VARIANT", "VT_UNKNOWN", "?", "?", // 15 "VT_I1", "VT_UI1", "VT_UI2", "VT_UI4", "VT_I8", // 20 "VT_UI8", "VT_INT", "VT_UINT", "VT_VOID", "VT_HRESULT", // 25 "VT_PTR", "VT_SAFEARRAY", "VT_CARRAY", "VT_USERDEFINED", "VT_LPSTR", // 30 "VT_LPWSTR", "?", "?", "?", "?", // 35 "?", "?", "?", "?", "?", // 40 "?", "?", "?", "?", "?", // 45 "?", "?", "?", "?", "?", // 50 "?", "?", "?", "?", "?", // 55 "?", "?", "?", "?", "?", // 60 "?", "?", "?", "VT_FILETIME", // 64 "VT_BLOB", "VT_STREAM", "VT_STORAGE", "VT_STREAMED_OBJECT", "VT_STORED_OBJECT", "VT_BLOB_OBJECT", // 70 "VT_CF", "VT_CLSID", "VT_VECTOR", "VT_ARRAY" }; // ---------------------------------------------------------------------------- // Global variables // ---------------- List * openRootStorageList = NULL; // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Methods of OLECore // ---------------------------------------------------------------------------- OLECore::OLECore( ) { lastError = noErr; fpxStatus = FPX_OK; userCount = 1; } OLECore::~OLECore( ) { } void OLECore::AddRef() { userCount++; } void OLECore::Release() { userCount--; } FPXStatus OLECore::OLEtoFPXError(HRESULT err) { FPXStatus terr; unsigned short errCode, errFac, errSev; SCODE sCode = GetScode(err); errSev = SCODE_SEVERITY(sCode); errCode = SCODE_CODE(sCode); errFac = SCODE_FACILITY(sCode); switch (sCode) { case S_OK: terr = FPX_OK; break; case STG_E_INVALIDFUNCTION: terr = FPX_OLE_FILE_ERROR; break; case STG_E_FILENOTFOUND: terr = FPX_FILE_NOT_FOUND; break; case STG_E_PATHNOTFOUND: terr = FPX_FILE_NOT_FOUND; break; case STG_E_TOOMANYOPENFILES: terr = FPX_FILE_SYSTEM_FULL; break; case STG_E_ACCESSDENIED: terr = FPX_FILE_WRITE_ERROR; break; case STG_E_INVALIDHANDLE: terr = FPX_OLE_FILE_ERROR; break; case STG_E_INSUFFICIENTMEMORY: terr = FPX_MEMORY_ALLOCATION_FAILED; break; case STG_E_INVALIDPOINTER: terr = FPX_OLE_FILE_ERROR; break; case STG_E_NOMOREFILES: terr = FPX_FILE_SYSTEM_FULL; break; case STG_E_DISKISWRITEPROTECTED: terr = FPX_ERROR; break; case STG_E_SEEKERROR: terr = FPX_OLE_FILE_ERROR; break; case STG_E_WRITEFAULT: terr = FPX_FILE_WRITE_ERROR; break; case STG_E_READFAULT: terr = FPX_FILE_READ_ERROR; break; case STG_E_SHAREVIOLATION: terr = FPX_FILE_IN_USE; break; case STG_E_LOCKVIOLATION: terr = FPX_FILE_IN_USE; break; case STG_E_FILEALREADYEXISTS: terr = FPX_INVALID_FORMAT_ERROR; break; case STG_E_INVALIDPARAMETER: terr = FPX_OLE_FILE_ERROR; break; case STG_E_MEDIUMFULL: terr = FPX_FILE_SYSTEM_FULL; break; case STG_E_ABNORMALAPIEXIT: terr = FPX_OLE_FILE_ERROR; break; case STG_E_INVALIDHEADER: terr = FPX_INVALID_FORMAT_ERROR; break; case STG_E_INVALIDNAME: terr = FPX_INVALID_FORMAT_ERROR; break; case STG_E_UNKNOWN: terr = FPX_OLE_FILE_ERROR; break; case STG_E_UNIMPLEMENTEDFUNCTION: terr = FPX_OLE_FILE_ERROR; break; case STG_E_INVALIDFLAG: terr = FPX_OLE_FILE_ERROR; break; case STG_E_INUSE: terr = FPX_FILE_IN_USE; break; case STG_E_NOTCURRENT: terr = FPX_FILE_NOT_OPEN_ERROR; break; case STG_E_REVERTED: terr = FPX_OLE_FILE_ERROR; break; case STG_E_CANTSAVE: terr = FPX_OLE_FILE_ERROR; break; case STG_E_OLDFORMAT: terr = FPX_INVALID_FORMAT_ERROR; break; case STG_E_OLDDLL: terr = FPX_INVALID_FORMAT_ERROR; break; case STG_E_SHAREREQUIRED: terr = FPX_FILE_IN_USE; break; case STG_E_NOTFILEBASEDSTORAGE: terr = FPX_OLE_FILE_ERROR; break; case STG_E_EXTANTMARSHALLINGS: terr = FPX_OLE_FILE_ERROR; break; case E_UNEXPECTED: terr = FPX_OLE_FILE_ERROR; break; case E_NOTIMPL: terr = FPX_UNIMPLEMENTED_FUNCTION; break; case E_OUTOFMEMORY: terr = FPX_MEMORY_ALLOCATION_FAILED; break; case E_INVALIDARG: terr = FPX_OLE_FILE_ERROR; break; case E_NOINTERFACE: terr = FPX_OLE_FILE_ERROR; break; case E_POINTER: terr = FPX_OLE_FILE_ERROR; break; case E_HANDLE: terr = FPX_OLE_FILE_ERROR; break; case E_ABORT: terr = FPX_OLE_FILE_ERROR; break; case E_FAIL: terr = FPX_OLE_FILE_ERROR; break; case E_ACCESSDENIED: terr = FPX_FILE_WRITE_ERROR; break; case OLE_E_OLEVERB: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_ADVF: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_ENUM_NOMORE: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_ADVISENOTSUPPORTED: terr = FPX_UNIMPLEMENTED_FUNCTION; break; case OLE_E_NOCONNECTION: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_NOTRUNNING: terr = FPX_SEVER_INIT_ERROR; break; case OLE_E_NOCACHE: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_BLANK: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_CLASSDIFF: terr = FPX_INVALID_FORMAT_ERROR; break; case OLE_E_CANT_GETMONIKER: terr = FPX_INVALID_FORMAT_ERROR; break; case OLE_E_CANT_BINDTOSOURCE: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_STATIC: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_PROMPTSAVECANCELLED: terr = FPX_USER_ABORT; break; case OLE_E_INVALIDRECT: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_WRONGCOMPOBJ: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_INVALIDHWND: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_NOT_INPLACEACTIVE: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_CANTCONVERT: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_NOSTORAGE: terr = FPX_FILE_NOT_OPEN_ERROR; break; #ifdef macintosh // Mac specific errors from ole2.h case OLE_E_NOEXTENSION: terr = FPX_SEVER_INIT_ERROR; break; case OLE_E_VERSEXTENSION: terr = FPX_SEVER_INIT_ERROR; break; case OLE_E_IPBUSY: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_NOT_FRONT_PROCESS: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_WRONG_MENU: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_MENU_NOT_PATCHED: terr = FPX_OLE_FILE_ERROR; break; case OLE_E_MENUID_NOT_HASHED: terr = FPX_OLE_FILE_ERROR; break; #endif // macintosh default: terr = FPX_OLE_FILE_ERROR; break; } return terr; } // This function translates the error in form of scode to normal error code OSErr OLECore::TranslateOLEError(HRESULT err) { OSErr terr; // DAG unsigned short errCode, errFac, errSev; SCODE sCode = GetScode(err); errSev = SCODE_SEVERITY(sCode); errCode = SCODE_CODE(sCode); errFac = SCODE_FACILITY(sCode); // end DAG switch (sCode) { case S_OK: terr = noErr; break; case STG_E_INVALIDFUNCTION: terr = SEVERITY_ERROR; break; case STG_E_FILENOTFOUND: terr = SEVERITY_ERROR; break; case STG_E_PATHNOTFOUND: terr = SEVERITY_ERROR; break; case STG_E_TOOMANYOPENFILES: terr = SEVERITY_ERROR; break; case STG_E_ACCESSDENIED: terr = SEVERITY_ERROR; break; case STG_E_INVALIDHANDLE: terr = SEVERITY_ERROR; break; case STG_E_INSUFFICIENTMEMORY: terr = SEVERITY_ERROR; break; case STG_E_INVALIDPOINTER: terr = -1; break; case STG_E_NOMOREFILES: terr = -1; break; case STG_E_DISKISWRITEPROTECTED: terr = -1; break; case STG_E_SEEKERROR: terr = -1; break; case STG_E_WRITEFAULT: terr = -1; break; case STG_E_READFAULT: terr = -1; break; case STG_E_SHAREVIOLATION: terr = -1; break; case STG_E_LOCKVIOLATION: terr = -1; break; case STG_E_FILEALREADYEXISTS: terr = -1; break; case STG_E_INVALIDPARAMETER: terr = -1; break; case STG_E_MEDIUMFULL: terr = -1; break; case STG_E_ABNORMALAPIEXIT: terr = -1; break; case STG_E_INVALIDHEADER: terr = -1; break; case STG_E_INVALIDNAME: terr = -1; break; case STG_E_UNKNOWN: terr = -1; break; case STG_E_UNIMPLEMENTEDFUNCTION: terr = -1; break; case STG_E_INVALIDFLAG: terr = -1; break; case STG_E_INUSE: terr = -1; break; case STG_E_NOTCURRENT: terr = -1; break; case STG_E_REVERTED: terr = -1; break; case STG_E_CANTSAVE: terr = -1; break; case STG_E_OLDFORMAT: terr = -1; break; case STG_E_OLDDLL: terr = -1; break; case STG_E_SHAREREQUIRED: terr = -1; break; case STG_E_NOTFILEBASEDSTORAGE: terr = -1; break; case STG_E_EXTANTMARSHALLINGS: terr = -1; break; case E_UNEXPECTED: terr = -1; break; case E_NOTIMPL: terr = -1; break; case E_OUTOFMEMORY: terr = -1; break; case E_INVALIDARG: terr = -1; break; case E_NOINTERFACE: terr = -1; break; case E_POINTER: terr = -1; break; case E_HANDLE: terr = -1; break; case E_ABORT: terr = -1; break; case E_FAIL: terr = -1; break; case E_ACCESSDENIED: terr = -1; break; case OLE_E_OLEVERB: terr = -1; break; case OLE_E_ADVF: terr = -1; break; case OLE_E_ENUM_NOMORE: terr = -1; break; case OLE_E_ADVISENOTSUPPORTED: terr = -1; break; case OLE_E_NOCONNECTION: terr = -1; break; case OLE_E_NOTRUNNING: terr = -1; break; case OLE_E_NOCACHE: terr = -1; break; case OLE_E_BLANK: terr = -1; break; case OLE_E_CLASSDIFF: terr = -1; break; case OLE_E_CANT_GETMONIKER: terr = -1; break; case OLE_E_CANT_BINDTOSOURCE: terr = -1; break; case OLE_E_STATIC: terr = -1; break; case OLE_E_PROMPTSAVECANCELLED: terr = -1; break; case OLE_E_INVALIDRECT: terr = -1; break; case OLE_E_WRONGCOMPOBJ: terr = -1; break; case OLE_E_INVALIDHWND: terr = -1; break; case OLE_E_NOT_INPLACEACTIVE: terr = -1; break; case OLE_E_CANTCONVERT: terr = -1; break; case OLE_E_NOSTORAGE: terr = -1; break; #ifdef macintosh // Mac specific errors from ole2.h case OLE_E_NOEXTENSION: terr = -1; break; case OLE_E_VERSEXTENSION: terr = -1; break; case OLE_E_IPBUSY: terr = -1; break; case OLE_E_NOT_FRONT_PROCESS: terr = -1; break; case OLE_E_WRONG_MENU: terr = -1; break; case OLE_E_MENU_NOT_PATCHED: terr = -1; break; case OLE_E_MENUID_NOT_HASHED: terr = -1; break; #endif // macintosh default: terr = -1; break; } return terr; } //------------------------------------------------------------------------------------------- // OLEBlob functions //------------------------------------------------------------------------------------------- // Create a blob by default size OLEBlob::OLEBlob() { // Set size and allocate memory for blob blob.cbSize = 0; buffer = NULL; blob.pBlobData = buffer; // Set the pointer to the beginning of blob data ResetPointer(); } // Create a blob by size OLEBlob::OLEBlob(const unsigned long size) { // Set size and allocate memory for blob blob.cbSize = size; buffer = new BYTE[size]; if (buffer==NULL) { blob.cbSize=0; } blob.pBlobData = buffer; // Set the pointer to the beginning of blob data ResetPointer(); } // Create a blob from another blob OLEBlob::OLEBlob(const BLOB* inputBlob) { // Set size and allocate memory for blob blob.cbSize = inputBlob->cbSize; buffer = new BYTE[blob.cbSize]; if (buffer==NULL) { blob.cbSize=0; } else { // Copy memory memcpy(buffer, inputBlob->pBlobData, inputBlob->cbSize); } blob.pBlobData = buffer; // Set the pointer to the beginning of blob data ResetPointer(); } OLEBlob::~OLEBlob() { if (blob.cbSize) delete[] buffer; } // Assign a blob Boolean OLEBlob::operator=(BLOB* inputBlob) { // Check the validity of input blob if ( !inputBlob) return false; if (blob.cbSize) delete buffer; // Set size and allocate memory for blob blob.cbSize = inputBlob->cbSize; buffer = new BYTE[blob.cbSize]; if ( !buffer) return false; // Copy memory memcpy(buffer, inputBlob->pBlobData, inputBlob->cbSize); blob.pBlobData = buffer; // Set the pointer to the beginning of blob data ResetPointer(); return true; } // Generic read function for blob Boolean OLEBlob::Read(void *dataPtr, const long size) { if ((long)(bufPtr + size - buffer) > (long)blob.cbSize) return false; // Read the data from the blob buffer referenced by bufPtr memcpy(dataPtr, bufPtr, size); bufPtr += size; return true; } // Read a unsigned char type from blob. Return the total bytes read, which is 1 bytes ( char ) DWORD OLEBlob::ReadVT_I1(BYTE *pb) { // Read a unsigned char type from the blob buffer referenced by bufPtr if ( !Read(pb, sizeof(char)) ) return false; return sizeof(char); } // Read a short type from blob. Return the total bytes read, which is 2 bytes ( short ) DWORD OLEBlob::ReadVT_I2(WORD *pw) { // Read a short type from the blob buffer referenced by bufPtr if ( !Read(pw, sizeof(*pw)) ) return false; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)pw, sizeof(*pw)); #endif return sizeof(*pw); } // Read a long type from blob. Return the total bytes read, which is 4 bytes ( long ) DWORD OLEBlob::ReadVT_I4(DWORD *pdw) { // Read a long type from the blob buffer referenced by bufPtr if ( !Read(pdw, sizeof(*pdw)) ) return false; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)pdw, sizeof(*pdw)); #endif return sizeof(*pdw); } // Read a float type from blob. Return the total bytes read, which is 4 bytes ( float ) DWORD OLEBlob::ReadVT_R4(float *pflt) { // Read a float type from the blob buffer referenced by bufPtr if ( !Read(pflt, sizeof(float)) ) return false; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)pflt, sizeof(float)); #endif return sizeof(float); } // Read a double type from blob. Return the total bytes read, which is 8 bytes ( double ) DWORD OLEBlob::ReadVT_R8(double *pdbl) { // Read a double type from the blob buffer referenced by bufPtr if ( !Read(pdbl, sizeof(double)) ) return false; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)pdbl, sizeof(double)); #endif return sizeof(double); } // Read a byte array from blob. Return the total array length DWORD OLEBlob::ReadVT_VECTOR(BYTE **ppByte) { // Allocating memory for string *ppByte = new BYTE[blob.cbSize]; if (*ppByte==NULL) { return false; } // Read the string if ( !Read(*ppByte, blob.cbSize) ) return false; return blob.cbSize; } // Read a string from blob. Return the total string length DWORD OLEBlob::ReadVT_LPSTR(char **ppsz) { DWORD dwLength; // Read the string length first including the terminating NULL if ( !ReadVT_I4(&dwLength) ) return false; // Allocating memory for string *ppsz = new char[dwLength]; if (*ppsz==NULL) { return false; } // Read the string if ( !Read(*ppsz, dwLength) ) return false; return dwLength; } // Read a wide string from blob. Return the total length ( bytes count ) DWORD OLEBlob::ReadVT_LPWSTR(WCHAR **ppwsz) { DWORD dwLength; // Read the WCHAR count first including the terminating NULL if ( !ReadVT_I4(&dwLength) ) return false; // Allocating memory for LPWSTR *ppwsz = new WCHAR[dwLength]; if (*ppwsz==NULL) { return false; } // Read the LPWSTR if ( !Read(*ppwsz, dwLength * sizeof(WCHAR)) ) return false; return dwLength * sizeof(WCHAR); } // Generic write function for blob Boolean OLEBlob::Write(const void *dataPtr, const long size) { // Get the already used buffer length DWORD usedSize = bufPtr - buffer; // If current allocate memory is not enough for new data, reallocate memory if (( usedSize + size ) > blob.cbSize) { // Allocate memory for new length BYTE *tempBuf = new BYTE[usedSize + size]; if ( !tempBuf) return false; // Copy the old buffer to new one and delete it memcpy(tempBuf, buffer, usedSize * sizeof(char)); if ( buffer ) delete buffer; // Reset the buffer and buffer pointer buffer = tempBuf; bufPtr = buffer + usedSize; // Reset the blob size and buffer blob.cbSize = usedSize + size; blob.pBlobData = buffer; } // Write the data to the blob buffer referenced by bufPtr memcpy(bufPtr, dataPtr, size); bufPtr += size; return true; } // Write a unsigned char type to blob. Return the total bytes write, which is 1 bytes ( char ) DWORD OLEBlob::WriteVT_I1(BYTE b) { // Write a unsigned char type to the blob buffer referenced by bufPtr if ( !Write(&b, sizeof(char)) ) return false; return sizeof(char); } // Write a short type to blob. Return the total bytes write, which is 2 bytes ( short ) DWORD OLEBlob::WriteVT_I2(WORD pw) { WORD w = pw; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)&w, sizeof(pw)); #endif // Write a short type to the blob buffer referenced by bufPtr if ( !Write(&w, sizeof(pw)) ) return false; return sizeof(pw); } // Write a long type to blob. Return the total bytes write, which is 4 bytes ( long ) DWORD OLEBlob::WriteVT_I4(DWORD pdw) { DWORD dw = pdw; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)&dw, sizeof(pdw)); #endif // Write a long type to the blob buffer referenced by bufPtr if ( !Write(&dw, sizeof(pdw)) ) return false; return sizeof(pdw); } // Write a float type to blob. Return the total bytes write, which is 4 bytes ( float ) DWORD OLEBlob::WriteVT_R4(float pflt) { float flt = pflt; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)&flt, sizeof(float)); #endif // Write a float type to the blob buffer referenced by bufPtr if ( !Write(&flt, sizeof(float)) ) return false; return sizeof(float); } // Write a double type to blob. Return the total bytes write, which is 8 bytes ( double ) DWORD OLEBlob::WriteVT_R8(double pdbl) { double dbl = pdbl; // Swap bytes if necessary #ifdef IN_BIG_ENDIAN SwapBytes((BYTE *)&dbl, sizeof(double)); #endif // Write a double type to the blob buffer referenced by bufPtr if ( !Write(&dbl, sizeof(double)) ) return false; return sizeof(double); } // Write a byte array to blob. Return the total array length DWORD OLEBlob::WriteVT_VECTOR(BYTE *pbyte, DWORD veclen) { // Write the byte array to the blob buffer referenced by bufPtr if ( !Write(pbyte, veclen * sizeof(char)) ) return false; return veclen * sizeof(char); } // Write a string to blob. Return the total string length DWORD OLEBlob::WriteVT_LPSTR(char *psz) { DWORD dwLength = strlen(psz) + 1; // Count includes terminating zero // Write the string length, including terminating NULL if ( !WriteVT_I4(dwLength) ) return false; // Write the string to the blob buffer referenced by bufPtr if ( !Write(psz, dwLength * sizeof(char)) ) return false; return dwLength * sizeof(char); } // Write a wide string to blob. Return the total length in bytes DWORD OLEBlob::WriteVT_LPWSTR(WCHAR *pwsz) { DWORD wcount; wcount = wcslen(pwsz) + 1; // Get the WCHAR count // Write the WCHAR count, including terminating NULL if ( !WriteVT_I4(wcount) ) return false; // Write the wide string to the blob buffer referenced by bufPtr if ( !Write(pwsz, wcount * sizeof(WCHAR)) ) return false; return wcount * sizeof(WCHAR); } // ---------------------------------------------------------------------------- // Methods of List // ---------------------------------------------------------------------------- // Create a list. This constructor should be used only for the list root List::List() { // Set the initial reference count to one userCount = 1; // Set the initial pointer to null name = DuplicateStr(""); ptr = NULL; next = NULL; } // Create a new record in the list List::List(void* thePtr, const char *theName, Boolean _freeme) { // Set the initial reference count to one userCount = 1; // Set the initial pointer to the passed values name = DuplicateStr(theName); ptr = thePtr; next = NULL; freeme = _freeme; } // Delete a list List::~List() { List *pl = next, *nextpl; assert(userCount >= 0); delete[] name; if (userCount == 0) /* we are already dead */ return; while (pl) { nextpl = pl->next; pl->Release(); if (pl->userCount == 0) delete pl; pl = nextpl; } } void List::AddRef() { userCount++; } void List::Release() { assert(userCount > 0); userCount--; if ( userCount <= 0 ) { delete[] name; name = NULL; /* * XXX This is a TERRIBLE hack. We presume, the ptr marked by * XXX freeme is coming from the OLEStorage::OpenPropertySet(), * XXX where it is of type LPSTREAM*. This is true at the moment, * XXX but should anyone begin to develop this horrible code * XXX further, the assumption is likely to break... * * -mi, Oct 9, 2007 */ if (freeme) delete (LPSTREAM *)ptr; ptr = NULL; userCount = 0; } } // Add an ole object to the list Boolean List::Add(void* thePtr, const char *theName, Boolean _freeme) { // Add the ole object to the list only if it is not in the list yet. if ( !Search(theName) ) { // Add the ole object to the end of list List* pl = GetEndOfList(); pl->next = new List(thePtr, theName, _freeme); if ( pl->next == NULL ) return FALSE; } return TRUE; } // Delete an ole object in the list Boolean List::Delete(const char *theName) { List* pl = NULL; // Delete the ole object to the list only if it is in the list. if ( (pl = Locate(theName)) != NULL ) { // Store the next list pointer in a temporary place List* tmp = pl->next->next; // Delete current list pointer delete pl->next; // Save the next list pointer pl->next = tmp; } else { return FALSE; } return TRUE; } // Locate a List object in the list. // Return the address of the List object immediately BEFORE the searched object. // TRICK: this works ONLY because there is ALWAYS a dummy record at the beginning of the list. List* List::Locate(const char *theName) { if (next == NULL) return NULL; else if ( !strcmp(next->name, theName) ) return this; else return next->Locate (theName); } // Search an ole object in the list. Return NULL if none found void* List::Search(const char *theName) { if ( !strcmp (name, theName) ) return ptr; else if (next) return next->Search(theName); else return NULL; } // Find the last element in the list List* List::GetEndOfList() { if (next) return next->GetEndOfList(); else return this; } // ---------------------------------------------------------------------------- // Global Functions // ---------------------------------------------------------------------------- // This function replaces substring with another one in a specified string, return NULL // if failed char* strrep(const char* s1, const char *t1, const char *t2, char *s2) { const char *ptr; char *newstr; // If the substring don't exist, return NULL if ( !(ptr=strstr(s1, t1))) return NULL; newstr = new char[strlen(s1)+strlen(t2)+1]; if (newstr==NULL) { return NULL; } strcpy(newstr, s1); newstr[ptr-s1]= '\0'; strcat(newstr, t2); newstr[ptr-s1 + strlen(t2)]= '\0'; strcpy(s2, newstr); delete newstr; return s2; } // This function duplicate a string. Notice: the returned string is allocated and should be deleted // after use. Return null if fails char* DuplicateStr(const char* s) { char *str = new char[strlen(s) + 1]; if ( !str ) return NULL; strcpy(str, s); return str; } // This function duplicate a wide char string. Notice: the returned string is allocated and should be deleted // after use. Return null if fails WCHAR* DuplicateWideStr(const WCHAR* ws) { WCHAR *wstr = new WCHAR[wcslen(ws) + 1]; if ( !wstr ) return NULL; memcpy(wstr, ws, sizeof(WCHAR) * (wcslen(ws) + 1)); return wstr; } // This function duplicate a blob. Notice: the returned blob is allocated and should be deleted // after use. Return null if fails BLOB* DuplicateBLOB(const BLOB* pblob) { BLOB *pb = NULL; if ( pblob ) { pb = new BLOB; pb->cbSize = pblob->cbSize; pb->pBlobData= new BYTE [pb->cbSize]; if ( !pb->pBlobData ) return NULL; memcpy(pb->pBlobData, pblob->pBlobData, pb->cbSize); } else return NULL; return pb; } // This function delete a blob void DeleteBLOB(BLOB* pblob) { if ( pblob ) { if ( pblob->pBlobData ) { delete[] pblob->pBlobData; pblob->cbSize = 0; } delete pblob; } } // This function duplicate a clipdata. Notice: the returned clipdata is allocated and should be deleted // after use. Return null if fails CLIPDATA* DuplicateCF(const CLIPDATA* pClipData) { CLIPDATA *pcf = NULL; if ( pClipData ) { pcf = new CLIPDATA; pcf->cbSize = pClipData->cbSize; pcf->pClipData= new BYTE [pcf->cbSize]; if ( !pcf->pClipData ) return NULL; memcpy(pcf->pClipData, pClipData->pClipData, pcf->cbSize); } else return NULL; return pcf; } // This function delete a clipdata void DeleteCF(CLIPDATA* pcf) { if ( pcf ) { if ( pcf->pClipData ) { delete[] pcf->pClipData; pcf->cbSize = 0; } delete pcf; } } // This function allocate memory for vector. Notice: the returned vector is allocated and should be deleted // after use. Return null if fails VECTOR* AllocVECTOR(long type, long elemCount) { VECTOR *pvec = new VECTOR; if ( !pvec ) return NULL; pvec->cElements = elemCount; // Erase the VT_VECTOR bit, so remaining is the data type in vector if (type & VT_VECTOR) type ^= VT_VECTOR; switch (type) { // If the subtype is char/unsigned char, use BYTE *prgb case VT_I1: case VT_UI1: { pvec->prgb = new BYTE[pvec->cElements * sizeof(char)]; if ( !pvec->prgb ) return NULL; break; } // If the subtype is short/unsigned short, use WORD *prgw case VT_I2: case VT_UI2: case VT_BOOL: { pvec->prgw = new WORD [pvec->cElements]; if ( !pvec->prgw ) return NULL; break; } // If the subtype is long/unsigned long, use DWORD *prgdw case VT_I4: case VT_UI4: case VT_ERROR: { pvec->prgdw = new DWORD [pvec->cElements]; if ( !pvec->prgdw ) return NULL; break; } // If the subtype is float, use float *prgflt case VT_R4: { pvec->prgflt = new float [pvec->cElements]; if ( !pvec->prgflt ) return NULL; break; } // If the subtype is double, use double *prgdbl case VT_R8: { pvec->prgdbl = new double [pvec->cElements]; if ( !pvec->prgdbl ) return NULL; break; } // If the subtype is LPSTR, use char **prgpsz case VT_LPSTR: { pvec->prgpsz = new char* [pvec->cElements]; if (pvec->prgpsz==NULL) return NULL; break; } // If the subtype is LPSTR/BSTR, use char **prgpwz case VT_LPWSTR: case VT_BSTR: { pvec->prgpwz = new WCHAR* [pvec->cElements]; if (pvec->prgpwz==NULL) return NULL; break; } // If the subtype is BLOB, use BLOB **prgblob case VT_BLOB: { pvec->prgblob = new BLOB* [pvec->cElements]; if ( !pvec->prgblob ) return NULL; break; } // If the subtype is CLIPDATA, use CLIPDATA **pcd case VT_CF: { pvec->pcd = new CLIPDATA* [pvec->cElements]; if ( !pvec->pcd ) return NULL; break; } // If the subtype is CLSID, use CLSID *pclsid case VT_CLSID: { pvec->pclsid = new CLSID [pvec->cElements]; if ( !pvec->pclsid ) return NULL; break; } // If the subtype is VARIANT, use VARIANT *pvar case VT_VARIANT: { pvec->pvar = new VARIANT [pvec->cElements]; if ( !pvec->pvar ) return NULL; break; } default: return NULL; } return pvec; } // This function duplicate a vector. Notice: the returned vector is allocated and should be deleted // after use. Return null if fails VECTOR* DuplicateVECTOR(const VECTOR* pvector, long type) { DWORD len; // If original vector is invalid, return false if ( !pvector ) return NULL; // Allocate the memory for a new vector VECTOR* pvec = AllocVECTOR(type, pvector->cElements); if ( !pvec ) return NULL; // Erase the VT_VECTOR bit, so remaining is the data type in vector if (type & VT_VECTOR) type ^= VT_VECTOR; // Duplicate the vector according to its type switch (type) { // If the subtype is char/unsigned char, use BYTE *prgb case VT_I1: case VT_UI1: { memcpy(pvec->prgb, pvector->prgb, pvec->cElements * sizeof(char)); // Set the size of vector len = pvec->cElements * sizeof(char) + sizeof(DWORD); break; } // If the subtype is short/unsigned short, use WORD *prgw case VT_I2: case VT_UI2: case VT_BOOL: { memcpy(pvec->prgw, pvector->prgw, pvec->cElements * 2); // Set the size of vector len = pvec->cElements * sizeof(short) + sizeof(DWORD); break; } // If the subtype is long/unsigned long, use DWORD *prgdw case VT_I4: case VT_UI4: case VT_ERROR: { memcpy(pvec->prgdw, pvector->prgdw, pvec->cElements * 4); // Set the size of vector len = pvec->cElements * 4 + sizeof(DWORD); break; } // If the subtype is float, use float *prgflt case VT_R4: { memcpy(pvec->prgflt, pvector->prgflt, pvec->cElements * sizeof(float)); // Set the size of vector len = pvec->cElements * sizeof(float) + sizeof(DWORD); break; } // If the subtype is double, use double *prgdbl case VT_R8: { memcpy(pvec->prgdbl, pvector->prgdbl, pvec->cElements * sizeof(double)); // Set the size of vector len = pvec->cElements * sizeof(double) + sizeof(DWORD); break; } // If the subtype is LPSTR/BSTR, use char **prgpsz case VT_LPSTR: { for ( DWORD i = 0; i < pvec->cElements; i++ ) { // Duplicate each string in the array if ( !(pvec->prgpsz[i] = DuplicateStr(pvector->prgpsz[i])) ) { pvec->cElements = i - 1; break; } } break; } // If the subtype is LPWSTR, use char **prgpwz case VT_LPWSTR: case VT_BSTR: { for ( DWORD i = 0; i < pvec->cElements; i++ ) { // Duplicate each wide string in the array if ( !(pvec->prgpwz[i] = DuplicateWideStr(pvector->prgpwz[i])) ) { pvec->cElements = i - 1; break; } } break; } // If the subtype is BLOB, use BLOB **prgblob case VT_BLOB: { for ( DWORD i = 0; i < pvec->cElements; i++ ) { // Duplicate each BLOB in the array if ( !(pvec->prgblob[i] = DuplicateBLOB(pvector->prgblob[i])) ) { pvec->cElements = i - 1; break; } } break; } // If the subtype is CLIPDATA, use CLIPDATA **pcd case VT_CF: { for ( DWORD i = 0; i < pvec->cElements; i++ ) { // Duplicate each CLIPDATA in the array if ( !(pvec->pcd[i] = DuplicateCF(pvector->pcd[i])) ) { pvec->cElements = i - 1; break; } } break; } // If the subtype is CLSID, use CLSID *pclsid case VT_CLSID: { memcpy(pvec->pclsid, pvector->pclsid, sizeof(CLSID) * pvec->cElements); break; } // If the subtype is VARIANT, use VARIANT *pvar case VT_VARIANT: { memcpy(pvec->pvar, pvector->pvar, pvec->cElements * sizeof(VARIANT)); // Copy the variable length elements in the vector for ( DWORD i = 0; i < pvec->cElements; i++ ) { // If variant type is vector, recursively duplicate vector if ( pvec->pvar[i].vt & VT_VECTOR ) { VECTOR *pv = (VECTOR *)V_BYREF(&pvector->pvar[i]); len = VTtoVariant(&pvec->pvar[i], pv); continue; } // Duplicate according to type in variant switch(pvec->pvar[i].vt) { case VT_LPSTR: len = VTtoVariant(&pvec->pvar[i], (char*)V_UI1REF(&pvector->pvar[i])); break; case VT_LPWSTR: len = VTtoVariant(&pvec->pvar[i], (LPWSTR)V_BYREF(&pvector->pvar[i])); break; case VT_BLOB: len = VTtoVariant(&pvec->pvar[i], (BLOB *)V_BYREF(&pvector->pvar[i])); break; case VT_CF: len = VTtoVariant(&pvec->pvar[i], (CLIPDATA *)V_BYREF(&pvector->pvar[i])); break; case VT_CLSID: VTtoVariant(&pvec->pvar[i], (CLSID *)V_BYREF(&pvector->pvar[i])); break; } if ( !len ) { pvec->cElements = i - 1; break; } } break; } default: return NULL; } return pvec; } // This function delete a vector void DeleteVECTOR(VECTOR* pvec, long type) { // Erase the VT_VECTOR bit, so remaining is the data type in vector if (type & VT_VECTOR) type ^= VT_VECTOR; if ( !pvec ) return; switch(type) { case VT_I1: case VT_UI1: { if (pvec->cElements) delete [] pvec->prgb; break; } case VT_I2: case VT_UI2: case VT_BOOL: { if (pvec->cElements) delete [] pvec->prgw; break; } case VT_I4: case VT_UI4: case VT_ERROR: { if (pvec->cElements) delete [] pvec->prgdw; break; } case VT_R4: { if (pvec->cElements) delete [] pvec->prgflt; break; } case VT_R8: { if (pvec->cElements) delete [] pvec->prgdbl; break; } case VT_LPSTR: { for ( DWORD i = 0; i < pvec->cElements; i++ ) delete [] pvec->prgpsz[i]; if (pvec->cElements) delete [] pvec->prgpsz; break; } case VT_LPWSTR: case VT_BSTR: { for ( DWORD i = 0; i < pvec->cElements; i++ ) delete [] pvec->prgpwz[i]; if (pvec->cElements) delete [] pvec->prgpwz; break; } case VT_BLOB: { for ( DWORD i = 0; i < pvec->cElements; i++ ) DeleteBLOB(pvec->prgblob[i]); if (pvec->cElements) delete pvec->prgblob; break; } case VT_CF: { for ( DWORD i = 0; i < pvec->cElements; i++ ) DeleteCF(pvec->pcd[i]); if (pvec->cElements) delete pvec->pcd; break; } case VT_CLSID: { if (pvec->cElements) delete [] pvec->pclsid; break; } case VT_VARIANT: { if (pvec->cElements) delete [] pvec->pvar; break; } } if ( pvec ) delete pvec; } // FIX_DICT_PROP - Added allocator and deallocator for dictionary property content. // This function allocate memory for dictionary. An array of entries is allocated. // each entry is initialized to null. The caller must allocate the strings for the // entries and fill-in the entries. // Returns pointer to allocated & initialized dictionary (or null) DICTIONARY* AllocDICTIONARY(long elemCount) { // Allocate/construct the property DICTIONARY *pDict = new DICTIONARY; if ( !pDict ) return NULL; // Allocate the array of entries and then initialize it. pDict->rgEntry = new ENTRY [elemCount]; if ( !pDict->rgEntry ) { delete pDict; return NULL; } pDict->cbEntries = elemCount; // Initialize the array of entries. for(unsigned long i = 0; i < pDict->cbEntries; i++) { pDict->rgEntry[i].dwPropID = 0; pDict->rgEntry[i].cb = 0; pDict->rgEntry[i].sz = 0; } return pDict; } // This function deletes a dictionary property -- including all of it's contents void DeleteDICTIONARY(DICTIONARY* pDict) { if ( !pDict ) return; if (pDict->rgEntry) { // Deallocate all of the strings contained in the array of entries for(unsigned long i = 0; i < pDict->cbEntries; i++) if( pDict->rgEntry[i].sz ) delete [] pDict->rgEntry[i].sz; // Deallocate the array of entries delete pDict->rgEntry; } delete pDict; // Delete the dictonary } #ifndef USE_UNICODE // WideCharToMultiByte() // Generic routine for converting UniCode string to ASCII string. Return the ASCII string, // NULL if failed. The ASCII string is allocated, so should be deleted after use char* WideCharToMultiByte(const WCHAR * pwchar) { // Determine the length of wide char string DWORD wcharlen = wcslen(pwchar); // Allocate memory including terminating NULL char *pchar = new char[wcharlen + 1]; // Return if fails if ( !pchar ) return NULL; for (DWORD i = 0; i < wcharlen; i++ ) { // Only low byte of Unicode is used pchar[i] = pwchar[i] & 0x00FF; } // Add a '\0' to the end of string pchar[wcharlen] = '\0'; return pchar; } // MultiByteToWideChar() // Generic routine for converting ASCII string to Unicode string. Returned the wide char // string, NULL if fails. The wide char string is allocated, and so should be deleted after use LPWSTR MultiByteToWideChar(const char * pchar) { // Determine the length of string DWORD charlen = strlen(pchar); // Allocate memory including terminating NULLs LPWSTR pwchar = new WCHAR[charlen+1]; // Return if fails if ( !pwchar ) return NULL; for (DWORD i = 0; i < charlen; i++ ) { // Unicode's high byte is set to 0, and low byte same as the string byte pwchar[i] = pchar[i] | 0x00 << 8; } // Last wide character is set to zero pwchar[charlen] = 0; return pwchar; } // This function calculates the length of Unicode string which is terminated by two consecutive NULLs // DWORD wcslen(const WCHAR * pwchar) // { // DWORD i= 0; // while (pwchar[i] != 0) // i++; // return i; // } #endif // This function returns the name string of a variant type, return NULL if no match // given type const char * VariantName(VARTYPE vtType) { if ( vtType & VT_VECTOR ) return (char *)variantName[73]; if ( vtType & VT_ARRAY ) return (char *)variantName[74]; return variantName[vtType]; } // SwapBytes() // Generic routine for switching endian order in an arbitrary data type. void SwapBytes(unsigned char *pbData, short cBytes) { unsigned char bSwap; if (cBytes < 2) return; for (short ib = cBytes - 1; ib >= 1; ib -= 2) { bSwap = pbData[cBytes - 1 - ib]; pbData[cBytes - 1 - ib] = pbData[ib]; pbData[ib] = bSwap; } } HRESULT OLEInit() { HRESULT res = S_OK; #ifdef macintosh #ifndef powerc // If Code Warrior 68k res = InitOleManager(OLEMGR_BIND_NORMAL); if(res != S_OK) res = InitOleManager(OLEMGR_BIND_NORMAL); if (res == S_OK) #endif // powerc #endif // macintosh #ifdef _WINDOWS res = OleInitialize(NULL); #endif // on UNIX, for now, there is no need for OleInitialize return res; } //This function uninitializes the OLE library Boolean OLEUninit() { #ifdef macintosh #ifndef powerc UninitOleManager(); #endif // powerc #endif // macintosh #ifdef _WINDOWS OleUninitialize(); #endif return true; }