• Welcome to Jose's Read Only Forum 2023.
 

About Structured Storage

Started by José Roca, September 06, 2008, 07:14:05 AM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

José Roca

 
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

José Roca

#1
 
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
' ========================================================================================


José Roca

#2
 
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
' ========================================================================================


José Roca

#3
 
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
' ========================================================================================


José Roca

#4
 
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
' ========================================================================================


José Roca

#5
 
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
' ****************************************************************************************


José Roca

#6
 
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
' ========================================================================================


José Roca

#7
 
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
' ========================================================================================