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

📄 storage32.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
 * This method will create a stream object within this storage
 *
 * See Windows documentation for more details on IStorage methods.
 */
static HRESULT WINAPI StorageBaseImpl_CreateStream(
            IStorage*        iface,
            const OLECHAR*   pwcsName,  /* [string][in] */
            DWORD            grfMode,   /* [in] */
            DWORD            reserved1, /* [in] */
            DWORD            reserved2, /* [in] */
            IStream**        ppstm)     /* [out] */
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  IEnumSTATSTGImpl* propertyEnumeration;
  StgStreamImpl*    newStream;
  StgProperty       currentProperty, newStreamProperty;
  ULONG             foundPropertyIndex, newPropertyIndex;

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

  /*
   * Validate parameters
   */
  if (ppstm == 0)
    return STG_E_INVALIDPOINTER;

  if (pwcsName == 0)
    return STG_E_INVALIDNAME;

  if (reserved1 || reserved2)
    return STG_E_INVALIDPARAMETER;

  /*
   * Validate the STGM flags
   */
  if ( FAILED( validateSTGM(grfMode) ))
    return STG_E_INVALIDFLAG;

  if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE) 
    return STG_E_INVALIDFLAG;

  /*
   * As documented.
   */
  if ((grfMode & STGM_DELETEONRELEASE) ||
      (grfMode & STGM_TRANSACTED))
    return STG_E_INVALIDFUNCTION;

  /*
   * Check that we're compatible with the parent's storage mode
   * if not in transacted mode
   */
  if(!(This->ancestorStorage->base.openFlags & STGM_TRANSACTED)) {
    if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( This->openFlags ) )
      return STG_E_ACCESSDENIED;
  }

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

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

  foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
                                                     pwcsName,
                                                     &currentProperty);

  IEnumSTATSTGImpl_Destroy(propertyEnumeration);

  if (foundPropertyIndex != PROPERTY_NULL)
  {
    /*
     * An element with this name already exists
     */
    if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
    {
      IStorage_DestroyElement(iface, pwcsName);
    }
    else
      return STG_E_FILEALREADYEXISTS;
  }
  else if (STGM_ACCESS_MODE(This->openFlags) == STGM_READ)
  {
    WARN("read-only storage\n");
    return STG_E_ACCESSDENIED;
  }

  /*
   * memset the empty property
   */
  memset(&newStreamProperty, 0, sizeof(StgProperty));

  newStreamProperty.sizeOfNameString =
      ( lstrlenW(pwcsName)+1 ) * sizeof(WCHAR);

  if (newStreamProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
    return STG_E_INVALIDNAME;

  strcpyW(newStreamProperty.name, pwcsName);

  newStreamProperty.propertyType  = PROPTYPE_STREAM;
  newStreamProperty.startingBlock = BLOCK_END_OF_CHAIN;
  newStreamProperty.size.u.LowPart  = 0;
  newStreamProperty.size.u.HighPart = 0;

  newStreamProperty.previousProperty = PROPERTY_NULL;
  newStreamProperty.nextProperty     = PROPERTY_NULL;
  newStreamProperty.dirProperty      = PROPERTY_NULL;

  /* call CoFileTime to get the current time
  newStreamProperty.timeStampS1
  newStreamProperty.timeStampD1
  newStreamProperty.timeStampS2
  newStreamProperty.timeStampD2
  */

  /*  newStreamProperty.propertyUniqueID */

  /*
   * Get a free property or create a new one
   */
  newPropertyIndex = getFreeProperty(This->ancestorStorage);

  /*
   * Save the new property into the new property spot
   */
  StorageImpl_WriteProperty(
    This->ancestorStorage,
    newPropertyIndex,
    &newStreamProperty);

  /*
   * Find a spot in the property chain for our newly created property.
   */
  updatePropertyChain(
    (StorageImpl*)This,
    newPropertyIndex,
    newStreamProperty);

  /*
   * Open the stream to return it.
   */
  newStream = StgStreamImpl_Construct(This, grfMode, newPropertyIndex);

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

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

  return S_OK;
}

/************************************************************************
 * Storage32BaseImpl_SetClass (IStorage)
 *
 * This method will write the specified CLSID in the property of this
 * storage.
 *
 * See Windows documentation for more details on IStorage methods.
 */
static HRESULT WINAPI StorageBaseImpl_SetClass(
  IStorage*        iface,
  REFCLSID         clsid) /* [in] */
{
  StorageBaseImpl *This = (StorageBaseImpl *)iface;
  HRESULT hRes = E_FAIL;
  StgProperty curProperty;
  BOOL success;

  TRACE("(%p, %p)\n", iface, clsid);

  success = StorageImpl_ReadProperty(This->ancestorStorage,
                                       This->rootPropertySetIndex,
                                       &curProperty);
  if (success)
  {
    curProperty.propertyUniqueID = *clsid;

    success =  StorageImpl_WriteProperty(This->ancestorStorage,
                                           This->rootPropertySetIndex,
                                           &curProperty);
    if (success)
      hRes = S_OK;
  }

  return hRes;
}

/************************************************************************
** Storage32Impl implementation
*/

/************************************************************************
 * Storage32Impl_CreateStorage (IStorage)
 *
 * This method will create the storage object within the provided storage.
 *
 * See Windows documentation for more details on IStorage methods.
 */
static HRESULT WINAPI StorageImpl_CreateStorage(
  IStorage*      iface,
  const OLECHAR  *pwcsName, /* [string][in] */
  DWORD            grfMode,   /* [in] */
  DWORD            reserved1, /* [in] */
  DWORD            reserved2, /* [in] */
  IStorage       **ppstg)   /* [out] */
{
  StorageImpl* const This=(StorageImpl*)iface;

  IEnumSTATSTGImpl *propertyEnumeration;
  StgProperty      currentProperty;
  StgProperty      newProperty;
  ULONG            foundPropertyIndex;
  ULONG            newPropertyIndex;
  HRESULT          hr;

  TRACE("(%p, %s, %x, %d, %d, %p)\n",
	iface, debugstr_w(pwcsName), grfMode,
	reserved1, reserved2, ppstg);

  /*
   * Validate parameters
   */
  if (ppstg == 0)
    return STG_E_INVALIDPOINTER;

  if (pwcsName == 0)
    return STG_E_INVALIDNAME;

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

  /*
   * Validate the STGM flags
   */
  if ( FAILED( validateSTGM(grfMode) ) ||
       (grfMode & STGM_DELETEONRELEASE) )
  {
    WARN("bad grfMode: 0x%x\n", grfMode);
    return STG_E_INVALIDFLAG;
  }

  /*
   * Check that we're compatible with the parent's storage mode
   */
  if ( STGM_ACCESS_MODE( grfMode ) > STGM_ACCESS_MODE( This->base.openFlags ) )
  {
    WARN("access denied\n");
    return STG_E_ACCESSDENIED;
  }

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

  foundPropertyIndex = IEnumSTATSTGImpl_FindProperty(propertyEnumeration,
                                                     pwcsName,
                                                     &currentProperty);
  IEnumSTATSTGImpl_Destroy(propertyEnumeration);

  if (foundPropertyIndex != PROPERTY_NULL)
  {
    /*
     * An element with this name already exists
     */
    if (STGM_CREATE_MODE(grfMode) == STGM_CREATE)
      IStorage_DestroyElement(iface, pwcsName);
    else
    {
      WARN("file already exists\n");
      return STG_E_FILEALREADYEXISTS;
    }
  }
  else if (STGM_ACCESS_MODE(This->base.openFlags) == STGM_READ)
  {
    WARN("read-only storage\n");
    return STG_E_ACCESSDENIED;
  }

  /*
   * memset the empty property
   */
  memset(&newProperty, 0, sizeof(StgProperty));

  newProperty.sizeOfNameString = (lstrlenW(pwcsName)+1)*sizeof(WCHAR);

  if (newProperty.sizeOfNameString > PROPERTY_NAME_BUFFER_LEN)
  {
    FIXME("name too long\n");
    return STG_E_INVALIDNAME;
  }

  strcpyW(newProperty.name, pwcsName);

  newProperty.propertyType  = PROPTYPE_STORAGE;
  newProperty.startingBlock = BLOCK_END_OF_CHAIN;
  newProperty.size.u.LowPart  = 0;
  newProperty.size.u.HighPart = 0;

  newProperty.previousProperty = PROPERTY_NULL;
  newProperty.nextProperty     = PROPERTY_NULL;
  newProperty.dirProperty      = PROPERTY_NULL;

  /* call CoFileTime to get the current time
  newProperty.timeStampS1
  newProperty.timeStampD1
  newProperty.timeStampS2
  newProperty.timeStampD2
  */

  /*  newStorageProperty.propertyUniqueID */

  /*
   * Obtain a free property in the property chain
   */
  newPropertyIndex = getFreeProperty(This->base.ancestorStorage);

  /*
   * Save the new property into the new property spot
   */
  StorageImpl_WriteProperty(
    This->base.ancestorStorage,
    newPropertyIndex,
    &newProperty);

  /*
   * Find a spot in the property chain for our newly created property.
   */
  updatePropertyChain(
    This,
    newPropertyIndex,
    newProperty);

  /*
   * Open it to get a pointer to return.
   */
  hr = IStorage_OpenStorage(
         iface,
         (const OLECHAR*)pwcsName,
         0,
         grfMode,
         0,
         0,
         ppstg);

  if( (hr != S_OK) || (*ppstg == NULL))
  {
    return hr;
  }


  return S_OK;
}


/***************************************************************************
 *
 * Internal Method
 *
 * Get a free property or create a new one.
 */
static ULONG getFreeProperty(
  StorageImpl *storage)
{
  ULONG       currentPropertyIndex = 0;
  ULONG       newPropertyIndex     = PROPERTY_NULL;
  BOOL      readSuccessful        = TRUE;
  StgProperty currentProperty;

  do
  {
    /*
     * Start by reading the root property
     */
    readSuccessful = StorageImpl_ReadProperty(storage->base.ancestorStorage,
                                               currentPropertyIndex,
                                               &currentProperty);
    if (readSuccessful)
    {
      if (currentProperty.sizeOfNameString == 0)
      {
        /*
         * The property existis and is available, we found it.
         */
        newPropertyIndex = currentPropertyIndex;
      }
    }
    else
    {
      /*
       * We exhausted the property list, we will create more space below
       */
      newPropertyIndex = currentPropertyIndex;
    }
    currentPropertyIndex++;

  } while (newPropertyIndex == PROPERTY_NULL);

  /*
   * grow the property chain
   */
  if (! readSuccessful)
  {
    StgProperty    emptyProperty;
    ULARGE_INTEGER newSize;
    ULONG          propertyIndex;
    ULONG          lastProperty  = 0;
    ULONG          blockCount    = 0;

    /*
     * obtain the new count of property blocks
     */
    blockCount = BlockChainStream_GetCount(
                   storage->base.ancestorStorage->rootBlockChain)+1;

    /*
     * initialize the size used by the property stream
     */
    newSize.u.HighPart = 0;
    newSize.u.LowPart  = storage->bigBlockSize * blockCount;

    /*
     * add a property block to the property chain
     */
    BlockChainStream_SetSize(storage->base.ancestorStorage->rootBlockChain, newSize);

    /*
     * memset the empty property in order to initialize the unused newly
     * created property
     */
    memset(&emptyProperty, 0, sizeof(StgProperty));

    /*
     * initialize them
     */
    lastProperty = storage->bigBlockSize / PROPSET_BLOCK_SIZE * blockCount;

    for(
      propertyIndex = newPropertyIndex;
      propertyIndex < lastProperty;
      propertyIndex++)
    {
      StorageImpl_WriteProperty(
        storage->base.ancestorStorage,
        propertyIndex,
        &emptyProperty);

⌨️ 快捷键说明

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