COM provides a set of services collectively called structured storage. Among the benefits of these services is the reduction of performance penalties and overhead associated with storing separate objects in a flat file. Instead of a flat file, COM stores the separate objects in a single, structured file consisting of two main elements: storage objects and stream objects. Together, they function like a file system within a file.
Structured storage solves performance problems by eliminating the need to totally rewrite a file to storage whenever a new object is added to a compound file, or an existing object increases in size. The new data is written to the next available location in permanent storage, and the storage object updates the table of pointers it maintains to track the locations of its storage objects and stream objects. At the same time, structured storage enables end users to interact and manage a compound file as if it were a single file rather than a nested hierarchy of separate objects.
Structured storage also has other benefits:
Incremental access. If a user needs access to an object within a compound file, the user can load and save only that object, rather than the entire file.
Multiple use. More than one end user or application can concurrently read and write information in the same compound file.
Transaction processing. Users can read or write to COM compound files in transacted mode, where changes made to the file are buffered and can subsequently either be committed to the file or reversed.
Low-memory saves. Structured storage provides facilities for saving files in low-memory situations.
http://msdn.microsoft.com/en-us/library/aa378871(VS.85).aspx
The following example creates an stream on global memory, writes a couple of lines, and reads and displays them.
' ########################################################################################
' Creates an stream on global memory, writes a couple of lines, and reads and displays them.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%USESTREAMWRAPPERS = 1
#INCLUDE ONCE "OLE2UTILS.INC"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN ()
LOCAL pStream AS IStream
LOCAL strText AS STRING
CreateStreamOnHGlobal(%NULL, %TRUE, pStream)
IF ISNOTHING(pStream) THEN EXIT FUNCTION
IStream_WriteLine(pStream, "Line 1")
IStream_WriteLine(pStream, "Line 2")
strText = IStream_ReadText(pStream, -1)
pStream = NOTHING
MSGBOX strText
END FUNCTION
' ========================================================================================
The following example creates an stream file inside an storage file.
' ########################################################################################
' Creates an stream file inside an storage file.
' Minimum operating system: Windows 2000.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%USESTREAMWRAPPERS = 1
#INCLUDE ONCE "OLE2UTILS.INC"
' ========================================================================================
SUB TestCreateStorage
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pStream AS IStream
LOCAL wszName AS STRING
wszName = UCODE$("MyStorage.stg")
hr = StgCreateStorageEx(STRPTR(wszName), %STGM_CREATE OR %STGM_DIRECT OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
%STGFMT_STORAGE, 0, BYVAL %NULL, %NULL, $IID_IStorage, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgCreateStorageEx failure: " & HEX$(hr)
EXIT SUB
END IF
wszName = UCODE$("MyStream")
hr = pStorage.CreateStream(STRPTR(wszName), _
%STGM_DIRECT OR %STGM_CREATE OR %STGM_READWRITE OR %STGM_SHARE_EXCLUSIVE, _
0, 0, pStream)
IF FAILED(hr) THEN
MSGBOX "IStorage.CreateStream failure"
EXIT SUB
END IF
IStream_WriteText pStream, "http://www.powerbasic.com/"
IStream_WriteText pStream, "José Roca - http://jose.it-berater.org/"
MSGBOX "Storage created"
pStream = NOTHING
pStorage = NOTHING
END SUB
' ========================================================================================
' ========================================================================================
SUB TestOpenStorage
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pStream AS IStream
LOCAL wszName AS STRING
wszName = UCODE$("MyStorage.stg")
hr = StgOpenStorageEx(STRPTR(wszName), %STGM_DIRECT OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
%STGFMT_STORAGE, 0, BYVAL %NULL, %NULL, $IID_IStorage, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorageEx failure: " & HEX$(hr)
EXIT SUB
END IF
wszName = UCODE$("MyStream")
hr = pStorage.OpenStream(STRPTR(wszName), %NULL, _
%STGM_DIRECT OR %STGM_READWRITE OR %STGM_SHARE_EXCLUSIVE, _
%NULL, pStream)
IF FAILED(hr) THEN
MSGBOX "IStorage,OpenStream failure: " & HEX$(hr)
EXIT SUB
END IF
IStream_SeekAtEndOfFile(pStream)
IStream_WriteText(pStream, "New line")
IStream_ResetSeekPosition(pStream)
MSGBOX IStream_ReadText(pStream, 26)
MSGBOX IStream_ReadText(pStream, 39)
MSGBOX IStream_ReadText(pStream, 10)
pStream = NOTHING
pStorage = NOTHING
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
TestCreateStorage
TestOpenStorage
END FUNCTION
' ========================================================================================
The following version works with Windows 98:
' ########################################################################################
' Creates an stream file inside an storage file.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%USESTREAMWRAPPERS = 1
#INCLUDE ONCE "OLE2UTILS.INC"
' ========================================================================================
SUB TestCreateStorage
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pStream AS IStream
LOCAL wszName AS STRING
wszName = UCODE$("MyStorage.stg")
hr = StgCreateDocFile(STRPTR(wszName), _
%STGM_CREATE OR %STGM_DIRECT OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
%NULL, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgCreateDocFile failure: " & HEX$(hr)
EXIT SUB
END IF
wszName = UCODE$("MyStream")
hr = pStorage.CreateStream(STRPTR(wszName), _
%STGM_DIRECT OR %STGM_CREATE OR %STGM_READWRITE OR %STGM_SHARE_EXCLUSIVE, _
0, 0, pStream)
IF FAILED(hr) THEN
MSGBOX "IStorage_CreateStream failure"
EXIT SUB
END IF
IStream_WriteText pStream, "http://www.powerbasic.com/"
IStream_WriteText pStream, "José Roca - http://jose.it-berater.org/"
MSGBOX "Storage created"
pStream = NOTHING
pStorage = NOTHING
END SUB
' ========================================================================================
' ========================================================================================
SUB TestOpenStorage
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pStream AS IStream
LOCAL wszName AS STRING
wszName = UCODE$("MyStorage.stg")
hr = StgOpenStorage(STRPTR(wszName), _
NOTHING, %STGM_DIRECT OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
0, %NULL, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorage failure: " & HEX$(hr)
EXIT SUB
END IF
wszName = UCODE$("MyStream")
hr = pStorage.OpenStream(STRPTR(wszName), %NULL, _
%STGM_DIRECT OR %STGM_READWRITE OR %STGM_SHARE_EXCLUSIVE, _
%NULL, pStream)
IF FAILED(hr) THEN
MSGBOX "IStorage.OpenStream failure: " & HEX$(hr)
EXIT SUB
END IF
IStream_SeekAtEndOfFile(pStream)
IStream_WriteText(pStream, "New line")
IStream_ResetSeekPosition(pStream)
MSGBOX IStream_ReadText(pStream, 26)
MSGBOX IStream_ReadText(pStream, 39)
MSGBOX IStream_ReadText(pStream, 10)
pStream = NOTHING
pStorage = NOTHING
END SUB
' ========================================================================================
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
TestCreateStorage
TestOpenStorage
END FUNCTION
' ========================================================================================
The following example Creates a property set, writes a property, closes and reopens the property set, and reads back the property. This sample application creates the file "WriteRead.stg" in the current directory. It creates property sets in a structure storage file, but a one-line change causes it to create NTFS file system property sets.
It is a is a translation of the Microsoft C++ WriteRead.cpp example: http://msdn.microsoft.com/en-us/library/aa380387(VS.85).aspx
Minimum operating system: Windows 2000.
C++ version
//+===================================================================
//
// To build:
// cl /GX WriteRead.cpp
//
//+===================================================================
#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE
#include <stdio.h>
#include <windows.h>
#include <ole2.h>
// Implicitly link ole32.dll
#pragma comment( lib, "ole32.lib" )
// From uuidgen.exe:
const FMTID fmtid = { /* d170df2e-1117-11d2-aa01-00805ffe11b8 */
0xd170df2e,
0x1117,
0x11d2,
{0xaa, 0x01, 0x00, 0x80, 0x5f, 0xfe, 0x11, 0xb8}
};
EXTERN_C void wmain()
{
HRESULT hr = S_OK;
IPropertySetStorage *pPropSetStg = NULL;
IPropertyStorage *pPropStg = NULL;
WCHAR *pwszError = L"";
PROPSPEC propspec;
PROPVARIANT propvarWrite;
PROPVARIANT propvarRead;
try
{
// Create a file and a property set within it.
hr = StgCreateStorageEx( L"WriteRead.stg",
STGM_CREATE|STGM_SHARE_EXCLUSIVE|STGM_READWRITE,
STGFMT_STORAGE,
// STGFMT_STORAGE => Structured Storage
// property sets
// STGFMT_FILE => NTFS file system
// property sets
0, NULL, NULL,
IID_IPropertySetStorage,
reinterpret_cast<void**>(&pPropSetStg) );
if( FAILED(hr) ) throw L"Failed StgCreateStorageEx";
hr = pPropSetStg->Create( fmtid, NULL, PROPSETFLAG_DEFAULT,
STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,
&pPropStg );
if( FAILED(hr) ) throw L"Failed IPropertySetStorage::Create";
// Write a Unicode string property to the property set
propspec.ulKind = PRSPEC_LPWSTR;
propspec.lpwstr = L"Property Name";
propvarWrite.vt = VT_LPWSTR;
propvarWrite.pwszVal = L"Property Value";
hr = pPropStg->WriteMultiple( 1, &propspec, &propvarWrite,
PID_FIRST_USABLE );
if( FAILED(hr) )
throw L"Failed IPropertyStorage::WriteMultiple";
// Not required, but give the property set a friendly
// name.
PROPID propidDictionary = PID_DICTIONARY;
WCHAR *pwszFriendlyName =
L"Write/Read Properties Sample Property Set";
hr = pPropStg->WritePropertyNames( 1, &propidDictionary,
&pwszFriendlyName );
if( FAILED(hr) )
throw L"Failed IPropertyStorage::WritePropertyNames";
// Commit changes to the property set.
hr = pPropStg->Commit(STGC_DEFAULT);
if( FAILED(hr) )
throw L"Failed IPropertyStorage::Commit";
// Close and reopen everything.
// By using the STGFMT_ANY flag in the StgOpenStorageEx call,
// it does not matter if this is a Structured Storage
// property set or an NTFS file system property set
// (for more information see the StgCreateStorageEx
// call above).
pPropStg->Release(); pPropStg = NULL;
pPropSetStg->Release(); pPropSetStg = NULL;
hr = StgOpenStorageEx( L"WriteRead.stg",
STGM_READ|STGM_SHARE_DENY_WRITE,
STGFMT_ANY,
0, NULL, NULL,
IID_IPropertySetStorage,
reinterpret_cast<void**>(&pPropSetStg) );
if( FAILED(hr) )
throw L"Failed StgOpenStorageEx";
hr = pPropSetStg->Open( fmtid, STGM_READ|STGM_SHARE_EXCLUSIVE,
&pPropStg );
if( FAILED(hr) )
throw L"Failed IPropertySetStorage::Open";
// Read the property back and validate it
hr = pPropStg->ReadMultiple( 1, &propspec, &propvarRead );
if( FAILED(hr) )
throw L"Failed IPropertyStorage::ReadMultiple";
if( S_FALSE == hr )
throw L"Property didn't exist after reopening the
property set";
else if( propvarWrite.vt != propvarRead.vt )
throw L"Property types didn't match after reopening the
property set";
else if( 0 != wcscmp( propvarWrite.pwszVal,
propvarRead.pwszVal ))
throw L"Property values didn't match after reopening the
property set";
else
wprintf( L"Success\n" );
}
catch( const WCHAR *pwszError )
{
wprintf( L"Error: %s (hr=%08x)\n", pwszError, hr );
}
PropVariantClear( &propvarRead );
if( pPropStg ) pPropStg->Release();
if( pPropSetStg ) pPropSetStg->Release();
}
PowerBASIC version
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "propidl.inc"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN () AS LONG
' To generate a new GUID, use fmtid = GUID$()
LOCAL fmtid AS GUID
fmtid = GUID$("{d170df2e-1117-11d2-aa01-00805ffe11b8}")
LOCAL hr AS LONG ' // HRESULT
LOCAL pPropSetStg AS IPropertySetStorage ' // Property Set Storage interface
LOCAL pPropStg AS IPropertyStorage ' // Property Storage interface
LOCAL tPropSpec AS PROPSPEC ' // PROPSPEC structure
LOCAL strPropName AS STRING ' // Property name
LOCAL propvarWrite AS PROPVARIANT ' // PROPVARIANT structure
LOCAL strPropValue AS STRING ' // Property value
LOCAL propidDictionary AS LONG ' // PROPID
LOCAL strFriendlyName AS STRING ' // Friendly name
LOCAL pFriendlyName AS DWORD ' // Friendly name pointer
LOCAL propvarRead AS PROPVARIANT ' // PROPVARIANT structure
LOCAL bstrlen AS LONG ' // Unicode string length
LOCAL strText AS STRING ' // General purpose variable
LOCAL wszName AS STRING ' // File name
' Create a file and a property set within it.
' Note: Use %STGFMT_FILE instead of %STGFMT_STORAGE if you want to create
' NTFS file system property sets instead of Storage property sets.
wszName = UCODE$("WriteRead.stg")
hr = StgCreateStorageEx(STRPTR(wszName), %STGM_CREATE OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
%STGFMT_STORAGE, 0, BYVAL %NULL, %NULL, $IID_IPropertySetStorage, pPropSetStg)
IF FAILED(hr) THEN
MSGBOX "StgCreateStorageEx failed " & HEX$(hr)
EXIT FUNCTION
END IF
hr = pPropSetStg.Create(fmtid, BYVAL %NULL, %PROPSETFLAG_DEFAULT, _
%STGM_CREATE OR %STGM_READWRITE OR %STGM_SHARE_EXCLUSIVE, pPropStg)
IF FAILED(hr) THEN
MSGBOX "IPropertySetStorage.Create failed " & HEX$(hr)
EXIT FUNCTION
END IF
' Write an Unicode string property to the property set
strPropName = UCODE$("Property Name")
tPropSpec.ulKind = %PRSPEC_LPWSTR
tPropSpec.lpwstr = STRPTR(strPropName)
strPropValue = UCODE$("Property Value")
propvarWrite.vt = %VT_LPWSTR
propvarWrite.pwszVal = STRPTR(strPropValue)
hr = pPropStg.WriteMultiple(1, tPropSpec, propvarWrite, %PID_FIRST_USABLE)
IF FAILED(hr) THEN
MSGBOX "IPropertyStorage.WriteMultiple failed: " & HEX$(hr)
EXIT FUNCTION
END IF
' Not required, but give the property set a friendly name
propidDictionary = %PID_DICTIONARY
strFriendlyName = UCODE$("Write/Read Properties Sample Property Set")
pFriendlyName = STRPTR(strFriendlyName)
hr = pPropStg.WritePropertyNames(1, propidDictionary, pFriendlyName)
IF FAILED(hr) THEN
MSGBOX "IPropertyStorage.WritePropertyNames failed: " & HEX$(hr)
EXIT FUNCTION
END IF
' Release the interfaces
pPropSetStg = NOTHING
pPropStg = NOTHING
' Open the file.
' By using the STGFMT_ANY flag in the StgOpenStorageEx call,
' it does not matter if this is a Structured Storage property
' set or an NTFS file system property set.
hr = StgOpenStorageEx(STRPTR(wszName), %STGM_READ OR %STGM_SHARE_DENY_WRITE, _
%STGFMT_ANY, 0, BYVAL %NULL, %NULL, $IID_IPropertySetStorage, pPropSetStg)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorageEx failed: " & HEX$(hr)
EXIT FUNCTION
END IF
hr = pPropSetStg.Open(fmtid, %STGM_READ OR %STGM_SHARE_EXCLUSIVE, pPropStg)
IF FAILED(hr) THEN
MSGBOX "IPropertySetStorage.Open failed: " & HEX$(hr)
EXIT FUNCTION
END IF
' Read the property and validate it
hr = pPropStg.ReadMultiple(1, tPropSpec, propvarRead)
IF FAILED(hr) THEN
MSGBOX "IPropertyStorage.ReadMultiple failed: " & HEX$(hr)
EXIT FUNCTION
END IF
IF hr = %S_FALSE THEN
MSGBOX "Property didn't exist after reopening the property set"
ELSEIF propvarWrite.vt <> propvarRead.vt THEN
MSGBOX "Property types didn't match after reopening the property set"
ELSE
' If valid pointer...
IF propvarRead.pwszVal THEN
' Get the length of the Unicode string
bstrlen = lstrlenW(BYVAL propvarRead.pwszVal)
IF bstrlen THEN
' Peek bstrlen * 2 bytes (Unicode is a two-byte encoding)
strText = ACODE$(PEEK$(propvarRead.pwszVal, bstrlen * 2))
MSGBOX strText
END IF
END IF
END IF
' Clear the PROPVARIANT
PropVariantClear propvarRead
' ------------------------------------------------------------
' Not included in the C++ example
' Retrieves the name for the %PID_DICTIONARY property
' ------------------------------------------------------------
LOCAL pName AS DWORD
LOCAL buffer AS STRING
hr = pPropStg.ReadPropertyNames(1, propidDictionary, pName)
IF SUCCEEDED(hr) THEN
IF pName THEN
bstrlen = lstrlenW(BYVAL pName)
IF ISTRUE bstrlen THEN
buffer = PEEK$(pName, bstrlen * 2)
MSGBOX ACODE$(buffer)
END IF
' Free the string
CoTaskMemFree pName
END IF
END IF
' ------------------------------------------------------------
' Cleanup
pPropSetStg = NOTHING
pPropStg = NOTHING
END FUNCTION
' ========================================================================================
The following example demonstrates how to enumerate the streams contained in an storage compound file.
' ########################################################################################
' Demonstrates how to enumerate the streams contained in an storage compound file.
' ########################################################################################
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "propidl.inc"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pEnum AS IEnumSTATSTG
LOCAL pceltFetched AS DWORD
LOCAL tStatStg AS STATSTG
LOCAL wszName AS STRING
LOCAL bstrlen AS LONG
LOCAL strName AS STRING
LOCAL strText AS STRING
wszName = UCODE$("MyStorage.stg")
hr = StgOpenStorage(STRPTR(wszName), NOTHING, _
%STGM_DIRECT OR %STGM_SHARE_EXCLUSIVE OR %STGM_READWRITE, _
0, %NULL, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorage failure: " & HEX$(hr)
EXIT FUNCTION
END IF
' Retrieve a reference to the IEnumSTATSTG enumerator
hr = pStorage.EnumElements(0, 0, 0, pEnum)
IF FAILED(hr) THEN
MSGBOX "IStorage.EnumElements failure: " & HEX$(hr)
EXIT FUNCTION
END IF
DO
hr = pEnum.Next(1, tStatStg, pceltFetched)
IF pceltFetched = 0 THEN EXIT DO
' Retrieve the name (unicode string)
bstrlen = lstrlenW(BYVAL tStatStg.pwcsName)
IF bstrlen THEN strName = PEEK$(tStatStg.pwcsName, bstrlen * 2)
' Free the string
CoTaskMemFree tStatStg.pwcsName
strText = "Name: " & ACODE$(strName) & $CRLF & _
"Size: " & STR$(tStatStg.cbsize) & " bytes"
MSGBOX strText
LOOP
pEnum = NOTHING
pStorage = NOTHING
END FUNCTION
' ========================================================================================
The following example demonstrates how to enumerate the properties stored in a property set storage file.
' ########################################################################################
' Demonstrates how to enumerate the properties stored in a property set storage file.
' ########################################################################################
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "propidl.inc"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
LOCAL hr AS LONG
LOCAL pPropSetStg AS IPropertySetStorage
LOCAL pPropStg AS IPropertyStorage
LOCAL pEnum AS IEnumSTATPROPSTG
LOCAL pceltFetched AS DWORD
LOCAL tStatPropStg AS STATPROPSTG
LOCAL wszName AS STRING
LOCAL bstrlen AS LONG
LOCAL strName AS STRING
LOCAL strText AS STRING
LOCAL fmtid AS GUID
fmtid = GUID$("{d170df2e-1117-11d2-aa01-00805ffe11b8}")
wszName = UCODE$("WriteRead.stg")
hr = StgOpenStorageEx(STRPTR(wszName), %STGM_READ OR %STGM_SHARE_DENY_WRITE, _
%STGFMT_ANY, 0, BYVAL %NULL, %NULL, $IID_IPropertySetStorage, pPropSetStg)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorageEx failed: " & HEX$(hr)
EXIT FUNCTION
END IF
hr = pPropSetStg.Open(fmtid, %STGM_READ OR %STGM_SHARE_EXCLUSIVE, pPropStg)
IF FAILED(hr) THEN
MSGBOX "IPropertySetStorage.Open failed: " & HEX$(hr)
EXIT FUNCTION
END IF
' Retrieve a reference to the IEnumSTATPROPSTG enumerator
hr = pPropStg.Enum(pEnum)
IF FAILED(hr) THEN
MSGBOX "IPropertyStorage.Enum failure: " & HEX$(hr)
EXIT FUNCTION
END IF
DO
hr = pEnum.Next(1, tStatPropStg, pceltFetched)
IF pceltFetched = 0 THEN EXIT DO
' Retrieve the name (unicode string)
bstrlen = lstrlenW(BYVAL tStatPropStg.lpwstrName)
IF bstrlen THEN strName = PEEK$(tStatPropStg.lpwstrName, bstrlen * 2)
' Free the string
CoTaskMemFree tStatPropStg.lpwstrName
' Display the information
strText = "Name: " & ACODE$(strName) & $CRLF & _
"PropId: " & STR$(tStatPropStg.propid) & $CRLF & _
"Type: " & STR$(tStatPropStg.vt)
MSGBOX strText
LOOP
pEnum = NOTHING
pPropStg = NOTHING
pPropSetStg = NOTHING
END FUNCTION
' ****************************************************************************************
The following example demonstrates how to enumerate the property sets stored in a property set storage file. The returned FMTID is a guid used by the IPropertySetStorage.Open function.
' ########################################################################################
' Demonstrates how to enumerate the property sets stored in a property set storage file.
' The returned FMTID is a guid used in the IPropertySetStorage.Open function.
' ########################################################################################
#COMPILE EXE
#DIM ALL
#INCLUDE ONCE "propidl.inc"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
LOCAL hr AS LONG
LOCAL pPropSetStg AS IPropertySetStorage
LOCAL pEnum AS IEnumSTATPROPSETSTG
LOCAL pceltFetched AS DWORD
LOCAL tStatPropSetStg AS STATPROPSETSTG
LOCAL wszName AS STRING
LOCAL strText AS STRING
' Open the storage
wszName = UCODE$("WriteRead.stg")
hr = StgOpenStorageEx(STRPTR(wszName), %STGM_READ OR %STGM_SHARE_DENY_WRITE, _
%STGFMT_ANY, 0, BYVAL %NULL, %NULL, $IID_IPropertySetStorage, pPropSetStg)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorageEx failed: " & HEX$(hr)
EXIT FUNCTION
END IF
' Retrieve a reference to the IEnumSTATPROPSTG enumerator
hr = pPropSetStg.Enum(pEnum)
IF FAILED(hr) THEN
MSGBOX "IPropertyStorage.Enum failure: " & HEX$(hr)
EXIT FUNCTION
END IF
DO
hr = pEnum.Next(1, tStatPropSetStg, pceltFetched)
IF pceltFetched = 0 THEN EXIT DO
strText = "fmtid: " & GUIDTXT$(tStatPropSetStg.fmtid)
MSGBOX strText
LOOP
pEnum = NOTHING
pPropSetStg = NOTHING
END FUNCTION
' ========================================================================================
The following example opens an excel file and retrieves some information about the Workbook.
' ########################################################################################
' Opens an excel file and retrieves some information about the Workbook.
' ########################################################################################
#COMPILE EXE
#DIM ALL
%USESTREAMWRAPPERS = 1
#INCLUDE ONCE "OLE2UTILS.INC"
' ========================================================================================
' Main
' ========================================================================================
FUNCTION PBMAIN
LOCAL hr AS LONG
LOCAL pStorage AS IStorage
LOCAL pStream AS IStream
LOCAL wszName AS STRING
LOCAL qNewPos AS QUAD
LOCAL iBuild AS INTEGER
LOCAL iYear AS INTEGER
LOCAL cbRead AS DWORD
wszName = UCODE$("Test.xls")
hr = StgOpenStorage(STRPTR(wszName), NOTHING, _
%STGM_READ OR %STGM_SHARE_EXCLUSIVE, _
0, %NULL, pStorage)
IF FAILED(hr) THEN
MSGBOX "StgOpenStorage failure: " & HEX$(hr)
EXIT FUNCTION
END IF
wszName = UCODE$("Workbook")
hr = pStorage.OpenStream(STRPTR(wszName), 0, %STGM_READ OR %STGM_SHARE_EXCLUSIVE, 0, pStream)
IF FAILED(hr) THEN
MSGBOX "IStorage.OpenStream failure: " & HEX$(hr)
EXIT FUNCTION
END IF
hr = pStream.Seek(8, %STREAM_SEEK_SET, qNewPos)
IF FAILED(hr) THEN
MSGBOX "IStream.Seek failure: " & HEX$(hr)
EXIT FUNCTION
END IF
hr = pStream.Read(VARPTR(iBuild), SIZEOF(iBuild), cbRead)
hr = pStream.Read(VARPTR(iYear), SIZEOF(iYear), cbRead)
MSGBOX "Build: " & FORMAT$(iBuild) & " - Year: " & FORMAT$(iYear)
pStream = NOTHING
pStorage = NOTHING
END FUNCTION
' ========================================================================================