⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 storage32.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Compound Storage (32 bit version)
 * Storage implementation
 *
 * This file contains the compound file implementation
 * of the storage interface.
 *
 * Copyright 1999 Francis Beaudet
 * Copyright 1999 Sylvain St-Germain
 * Copyright 1999 Thuy Nguyen
 * Copyright 2005 Mike McCormack
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * NOTES
 *  The compound file implementation of IStorage used for create
 *  and manage substorages and streams within a storage object
 *  residing in a compound file object.
 *
 * MSDN
 *  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/stg/stg/istorage_compound_file_implementation.asp
 */

#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winuser.h"
#include "wine/unicode.h"
#include "wine/debug.h"

#include "storage32.h"
#include "ole2.h"      /* For Write/ReadClassStm */

#include "winreg.h"
#include "wine/wingdi16.h"

WINE_DEFAULT_DEBUG_CHANNEL(storage);

/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
#define OLESTREAM_ID 0x501
#define OLESTREAM_MAX_STR_LEN 255

static const char rootPropertyName[] = "Root Entry";


/* OLESTREAM memory structure to use for Get and Put Routines */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
typedef struct
{
    DWORD dwOleID;
    DWORD dwTypeID;
    DWORD dwOleTypeNameLength;
    CHAR  strOleTypeName[OLESTREAM_MAX_STR_LEN];
    CHAR  *pstrOleObjFileName;
    DWORD dwOleObjFileNameLength;
    DWORD dwMetaFileWidth;
    DWORD dwMetaFileHeight;
    CHAR  strUnknown[8]; /* don't know what is this 8 byts information in OLE stream. */
    DWORD dwDataLength;
    BYTE *pData;
}OLECONVERT_OLESTREAM_DATA;

/* CompObj Stream structure */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
typedef struct
{
    BYTE byUnknown1[12];
    CLSID clsid;
    DWORD dwCLSIDNameLength;
    CHAR strCLSIDName[OLESTREAM_MAX_STR_LEN];
    DWORD dwOleTypeNameLength;
    CHAR strOleTypeName[OLESTREAM_MAX_STR_LEN];
    DWORD dwProgIDNameLength;
    CHAR strProgIDName[OLESTREAM_MAX_STR_LEN];
    BYTE byUnknown2[16];
}OLECONVERT_ISTORAGE_COMPOBJ;


/* Ole Presention Stream structure */
/* Used for OleConvertIStorageToOLESTREAM and OleConvertOLESTREAMToIStorage */
typedef struct
{
    BYTE byUnknown1[28];
    DWORD dwExtentX;
    DWORD dwExtentY;
    DWORD dwSize;
    BYTE *pData;
}OLECONVERT_ISTORAGE_OLEPRES;



/***********************************************************************
 * Forward declaration of internal functions used by the method DestroyElement
 */
static HRESULT deleteStorageProperty(
  StorageImpl *parentStorage,
  ULONG        foundPropertyIndexToDelete,
  StgProperty  propertyToDelete);

static HRESULT deleteStreamProperty(
  StorageImpl *parentStorage,
  ULONG         foundPropertyIndexToDelete,
  StgProperty   propertyToDelete);

static HRESULT findPlaceholder(
  StorageImpl *storage,
  ULONG         propertyIndexToStore,
  ULONG         storagePropertyIndex,
  INT         typeOfRelation);

static HRESULT adjustPropertyChain(
  StorageImpl *This,
  StgProperty   propertyToDelete,
  StgProperty   parentProperty,
  ULONG         parentPropertyId,
  INT         typeOfRelation);

/***********************************************************************
 * Declaration of the functions used to manipulate StgProperty
 */

static ULONG getFreeProperty(
  StorageImpl *storage);

static void updatePropertyChain(
  StorageImpl *storage,
  ULONG       newPropertyIndex,
  StgProperty newProperty);

static LONG propertyNameCmp(
    const OLECHAR *newProperty,
    const OLECHAR *currentProperty);


/***********************************************************************
 * Declaration of miscellaneous functions...
 */
static HRESULT validateSTGM(DWORD stgmValue);

static DWORD GetShareModeFromSTGM(DWORD stgm);
static DWORD GetAccessModeFromSTGM(DWORD stgm);
static DWORD GetCreationModeFromSTGM(DWORD stgm);

extern const IPropertySetStorageVtbl IPropertySetStorage_Vtbl;



/************************************************************************
** Storage32BaseImpl implementatiion
*/

/************************************************************************
 * Storage32BaseImpl_QueryInterface (IUnknown)
 *
 * This method implements the common QueryInterface for all IStorage32
 * implementations contained in this file.
 *
 * See Windows documentation for more details on IUnknown methods.
 */
HRESULT WINAPI StorageBaseImpl_QueryInterface(
  IStorage*        iface,
  REFIID             riid,
  void**             ppvObject)
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  /*
   * Perform a sanity check on the parameters.
   */
  if ( (This==0) || (ppvObject==0) )
    return E_INVALIDARG;

  /*
   * Initialize the return parameter.
   */
  *ppvObject = 0;

  /*
   * Compare the riid with the interface IDs implemented by this object.
   */
  if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)
  {
    *ppvObject = (IStorage*)This;
  }
  else if (memcmp(&IID_IStorage, riid, sizeof(IID_IStorage)) == 0)
  {
    *ppvObject = (IStorage*)This;
  }
  else if (memcmp(&IID_IPropertySetStorage, riid, sizeof(IID_IPropertySetStorage)) == 0)
  {
    *ppvObject = (IStorage*)&This->pssVtbl;
  }

  /*
   * Check that we obtained an interface.
   */
  if ((*ppvObject)==0)
    return E_NOINTERFACE;

  /*
   * Query Interface always increases the reference count by one when it is
   * successful
   */
  IStorage_AddRef(iface);

  return S_OK;
}

/************************************************************************
 * Storage32BaseImpl_AddRef (IUnknown)
 *
 * This method implements the common AddRef for all IStorage32
 * implementations contained in this file.
 *
 * See Windows documentation for more details on IUnknown methods.
 */
ULONG WINAPI StorageBaseImpl_AddRef(
            IStorage* iface)
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  ULONG ref = InterlockedIncrement(&This->ref);

  TRACE("(%p) AddRef to %ld\n", This, ref);

  return ref;
}

/************************************************************************
 * Storage32BaseImpl_Release (IUnknown)
 *
 * This method implements the common Release for all IStorage32
 * implementations contained in this file.
 *
 * See Windows documentation for more details on IUnknown methods.
 */
ULONG WINAPI StorageBaseImpl_Release(
      IStorage* iface)
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  /*
   * Decrease the reference count on this object.
   */
  ULONG ref = InterlockedDecrement(&This->ref);

  TRACE("(%p) ReleaseRef to %ld\n", This, ref);

  /*
   * If the reference count goes down to 0, perform suicide.
   */
  if (ref == 0)
  {
    /*
     * Since we are using a system of base-classes, we want to call the
     * destructor of the appropriate derived class. To do this, we are
     * using virtual functions to implement the destructor.
     */
    This->v_destructor(This);
  }

  return ref;
}

/************************************************************************
 * Storage32BaseImpl_OpenStream (IStorage)
 *
 * This method will open the specified stream object from the current storage.
 *
 * See Windows documentation for more details on IStorage methods.
 */
HRESULT WINAPI StorageBaseImpl_OpenStream(
  IStorage*        iface,
  const OLECHAR*   pwcsName,  /* [string][in] */
  void*            reserved1, /* [unique][in] */
  DWORD            grfMode,   /* [in]  */
  DWORD            reserved2, /* [in]  */
  IStream**        ppstm)     /* [out] */
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  IEnumSTATSTGImpl* propertyEnumeration;
  StgStreamImpl*    newStream;
  StgProperty       currentProperty;
  ULONG             foundPropertyIndex;
  HRESULT           res = STG_E_UNKNOWN;
  DWORD             parent_grfMode;

  TRACE("(%p, %s, %p, %lx, %ld, %p)\n",
	iface, debugstr_w(pwcsName), reserved1, grfMode, reserved2, ppstm);

  /*
   * Perform a sanity check on the parameters.
   */
  if ( (pwcsName==NULL) || (ppstm==0) )
  {
    res = E_INVALIDARG;
    goto end;
  }

  /*
   * Initialize the out parameter
   */
  *ppstm = NULL;

  /*
   * Validate the STGM flags
   */
  if ( FAILED( validateSTGM(grfMode) ))
  {
    res = STG_E_INVALIDFLAG;
    goto end;
  }

  /*
   * As documented.
   */
  if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
        (grfMode & STGM_DELETEONRELEASE) ||
        (grfMode & STGM_TRANSACTED) )
  {
    res = STG_E_INVALIDFUNCTION;
    goto end;
  }

  /*
   * Check that we're compatible with the parent's storage mode
   */
  parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );
  if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
  {
    res = STG_E_ACCESSDENIED;
    goto end;
  }

  /*
   * Create a property enumeration to search the properties
   */
  propertyEnumeration = IEnumSTATSTGImpl_Construct(
    This->ancestorStorage,
    This->rootPropertySetIndex);

  /*
   * Search the enumeration for the property with the given name
   */
  foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(
    propertyEnumeration,
    pwcsName,
    &currentProperty);

  /*
   * Delete the property enumeration since we don't need it anymore
   */
  IEnumSTATSTGImpl_Destroy(propertyEnumeration);

  /*
   * If it was found, construct the stream object and return a pointer to it.
   */
  if ( (foundPropertyIndex!=PROPERTY_NULL) &&
       (currentProperty.propertyType==PROPTYPE_STREAM) )
  {
    newStream = StgStreamImpl_Construct(This, grfMode, foundPropertyIndex);

    if (newStream!=0)
    {
      newStream->grfMode = grfMode;
      *ppstm = (IStream*)newStream;

      /*
       * Since we are returning a pointer to the interface, we have to
       * nail down the reference.
       */
      IStream_AddRef(*ppstm);

      res = S_OK;
      goto end;
    }

    res = E_OUTOFMEMORY;
    goto end;
  }

  res = STG_E_FILENOTFOUND;

end:
  if (res == S_OK)
    TRACE("<-- IStream %p\n", *ppstm);
  TRACE("<-- %08lx\n", res);
  return res;
}

/************************************************************************
 * Storage32BaseImpl_OpenStorage (IStorage)
 *
 * This method will open a new storage object from the current storage.
 *
 * See Windows documentation for more details on IStorage methods.
 */
HRESULT WINAPI StorageBaseImpl_OpenStorage(
  IStorage*        iface,
  const OLECHAR*   pwcsName,      /* [string][unique][in] */
  IStorage*        pstgPriority,  /* [unique][in] */
  DWORD            grfMode,       /* [in] */
  SNB              snbExclude,    /* [unique][in] */
  DWORD            reserved,      /* [in] */
  IStorage**       ppstg)         /* [out] */
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  StorageInternalImpl* newStorage;
  IEnumSTATSTGImpl*      propertyEnumeration;
  StgProperty            currentProperty;
  ULONG                  foundPropertyIndex;
  HRESULT                res = STG_E_UNKNOWN;
  DWORD                  parent_grfMode;

  TRACE("(%p, %s, %p, %lx, %p, %ld, %p)\n",
	iface, debugstr_w(pwcsName), pstgPriority,
	grfMode, snbExclude, reserved, ppstg);

  /*
   * Perform a sanity check on the parameters.
   */
  if ( (This==0) || (pwcsName==NULL) || (ppstg==0) )
  {
    res = E_INVALIDARG;
    goto end;
  }

  /* as documented */
  if (snbExclude != NULL)
  {
    res = STG_E_INVALIDPARAMETER;
    goto end;
  }

  /*
   * Validate the STGM flags
   */
  if ( FAILED( validateSTGM(grfMode) ))
  {
    res = STG_E_INVALIDFLAG;
    goto end;
  }

  /*
   * As documented.
   */
  if ( STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE ||
        (grfMode & STGM_DELETEONRELEASE) ||
        (grfMode & STGM_PRIORITY) )
  {
    res = STG_E_INVALIDFUNCTION;
    goto end;
  }

  /*
   * Check that we're compatible with the parent's storage mode
   */
  parent_grfMode = STGM_ACCESS_MODE( This->ancestorStorage->base.openFlags );
  if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( parent_grfMode ) )
  {
    res = STG_E_ACCESSDENIED;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -