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

📄 storage32.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
    }
  }

  return newPropertyIndex;
}

/****************************************************************************
 *
 * Internal Method
 *
 * Case insensitive comparaison of StgProperty.name by first considering
 * their size.
 *
 * Returns <0 when newPrpoerty < currentProperty
 *         >0 when newPrpoerty > currentProperty
 *          0 when newPrpoerty == currentProperty
 */
static LONG propertyNameCmp(
    const OLECHAR *newProperty,
    const OLECHAR *currentProperty)
{
  LONG diff      = lstrlenW(newProperty) - lstrlenW(currentProperty);

  if (diff == 0)
  {
    /*
     * We compare the string themselves only when they are of the same length
     */
    diff = lstrcmpiW( newProperty, currentProperty);
  }

  return diff;
}

/****************************************************************************
 *
 * Internal Method
 *
 * Properly link this new element in the property chain.
 */
static void updatePropertyChain(
  StorageImpl *storage,
  ULONG         newPropertyIndex,
  StgProperty   newProperty)
{
  StgProperty currentProperty;

  /*
   * Read the root property
   */
  StorageImpl_ReadProperty(storage->base.ancestorStorage,
                             storage->base.rootPropertySetIndex,
                             &currentProperty);

  if (currentProperty.dirProperty != PROPERTY_NULL)
  {
    /*
     * The root storage contains some element, therefore, start the research
     * for the appropriate location.
     */
    BOOL found = 0;
    ULONG  current, next, previous, currentPropertyId;

    /*
     * Keep the StgProperty sequence number of the storage first property
     */
    currentPropertyId = currentProperty.dirProperty;

    /*
     * Read
     */
    StorageImpl_ReadProperty(storage->base.ancestorStorage,
                               currentProperty.dirProperty,
                               &currentProperty);

    previous = currentProperty.previousProperty;
    next     = currentProperty.nextProperty;
    current  = currentPropertyId;

    while (found == 0)
    {
      LONG diff = propertyNameCmp( newProperty.name, currentProperty.name);

      if (diff < 0)
      {
        if (previous != PROPERTY_NULL)
        {
          StorageImpl_ReadProperty(storage->base.ancestorStorage,
                                     previous,
                                     &currentProperty);
          current = previous;
        }
        else
        {
          currentProperty.previousProperty = newPropertyIndex;
          StorageImpl_WriteProperty(storage->base.ancestorStorage,
                                      current,
                                      &currentProperty);
          found = 1;
        }
      }
      else if (diff > 0)
      {
        if (next != PROPERTY_NULL)
        {
          StorageImpl_ReadProperty(storage->base.ancestorStorage,
                                     next,
                                     &currentProperty);
          current = next;
        }
        else
        {
          currentProperty.nextProperty = newPropertyIndex;
          StorageImpl_WriteProperty(storage->base.ancestorStorage,
                                      current,
                                      &currentProperty);
          found = 1;
        }
      }
      else
      {
	/*
	 * Trying to insert an item with the same name in the
	 * subtree structure.
	 */
	assert(FALSE);
      }

      previous = currentProperty.previousProperty;
      next     = currentProperty.nextProperty;
    }
  }
  else
  {
    /*
     * The root storage is empty, link the new property to its dir property
     */
    currentProperty.dirProperty = newPropertyIndex;
    StorageImpl_WriteProperty(storage->base.ancestorStorage,
                                storage->base.rootPropertySetIndex,
                                &currentProperty);
  }
}


/*************************************************************************
 * CopyTo (IStorage)
 */
static HRESULT WINAPI StorageImpl_CopyTo(
  IStorage*   iface,
  DWORD       ciidExclude,  /* [in] */
  const IID*  rgiidExclude, /* [size_is][unique][in] */
  SNB         snbExclude,   /* [unique][in] */
  IStorage*   pstgDest)     /* [unique][in] */
{
  IEnumSTATSTG *elements     = 0;
  STATSTG      curElement, strStat;
  HRESULT      hr;
  IStorage     *pstgTmp, *pstgChild;
  IStream      *pstrTmp, *pstrChild;

  if ((ciidExclude != 0) || (rgiidExclude != NULL) || (snbExclude != NULL))
    FIXME("Exclude option not implemented\n");

  TRACE("(%p, %d, %p, %p, %p)\n",
	iface, ciidExclude, rgiidExclude,
	snbExclude, pstgDest);

  /*
   * Perform a sanity check
   */
  if ( pstgDest == 0 )
    return STG_E_INVALIDPOINTER;

  /*
   * Enumerate the elements
   */
  hr = IStorage_EnumElements( iface, 0, 0, 0, &elements );

  if ( hr != S_OK )
    return hr;

  /*
   * set the class ID
   */
  IStorage_Stat( iface, &curElement, STATFLAG_NONAME);
  IStorage_SetClass( pstgDest, &curElement.clsid );

  do
  {
    /*
     * Obtain the next element
     */
    hr = IEnumSTATSTG_Next( elements, 1, &curElement, NULL );

    if ( hr == S_FALSE )
    {
      hr = S_OK;   /* done, every element has been copied */
      break;
    }

    if (curElement.type == STGTY_STORAGE)
    {
      /*
       * open child source storage
       */
      hr = IStorage_OpenStorage( iface, curElement.pwcsName, NULL,
				 STGM_READ|STGM_SHARE_EXCLUSIVE,
				 NULL, 0, &pstgChild );

      if (hr != S_OK)
        break;

      /*
       * Check if destination storage is not a child of the source
       * storage, which will cause an infinite loop
       */
      if (pstgChild == pstgDest)
      {
	IEnumSTATSTG_Release(elements);

	return STG_E_ACCESSDENIED;
      }

      /*
       * create a new storage in destination storage
       */
      hr = IStorage_CreateStorage( pstgDest, curElement.pwcsName,
                                   STGM_FAILIFTHERE|STGM_WRITE|STGM_SHARE_EXCLUSIVE,
				   0, 0,
                                   &pstgTmp );
      /*
       * if it already exist, don't create a new one use this one
       */
      if (hr == STG_E_FILEALREADYEXISTS)
      {
        hr = IStorage_OpenStorage( pstgDest, curElement.pwcsName, NULL,
                                   STGM_WRITE|STGM_SHARE_EXCLUSIVE,
                                   NULL, 0, &pstgTmp );
      }

      if (hr != S_OK)
        break;


      /*
       * do the copy recursively
       */
      hr = IStorage_CopyTo( pstgChild, ciidExclude, rgiidExclude,
                               snbExclude, pstgTmp );

      IStorage_Release( pstgTmp );
      IStorage_Release( pstgChild );
    }
    else if (curElement.type == STGTY_STREAM)
    {
      /*
       * create a new stream in destination storage. If the stream already
       * exist, it will be deleted and a new one will be created.
       */
      hr = IStorage_CreateStream( pstgDest, curElement.pwcsName,
                                  STGM_CREATE|STGM_WRITE|STGM_SHARE_EXCLUSIVE,
                                  0, 0, &pstrTmp );

      if (hr != S_OK)
        break;

      /*
       * open child stream storage
       */
      hr = IStorage_OpenStream( iface, curElement.pwcsName, NULL,
				STGM_READ|STGM_SHARE_EXCLUSIVE,
				0, &pstrChild );

      if (hr != S_OK)
        break;

      /*
       * Get the size of the source stream
       */
      IStream_Stat( pstrChild, &strStat, STATFLAG_NONAME );

      /*
       * Set the size of the destination stream.
       */
      IStream_SetSize(pstrTmp, strStat.cbSize);

      /*
       * do the copy
       */
      hr = IStream_CopyTo( pstrChild, pstrTmp, strStat.cbSize,
                           NULL, NULL );

      IStream_Release( pstrTmp );
      IStream_Release( pstrChild );
    }
    else
    {
      WARN("unknown element type: %d\n", curElement.type);
    }

  } while (hr == S_OK);

  /*
   * Clean-up
   */
  IEnumSTATSTG_Release(elements);

  return hr;
}

/*************************************************************************
 * MoveElementTo (IStorage)
 */
static HRESULT WINAPI StorageImpl_MoveElementTo(
  IStorage*     iface,
  const OLECHAR *pwcsName,   /* [string][in] */
  IStorage      *pstgDest,   /* [unique][in] */
  const OLECHAR *pwcsNewName,/* [string][in] */
  DWORD           grfFlags)    /* [in] */
{
  FIXME("(%p %s %p %s %u): stub\n", iface,
         debugstr_w(pwcsName), pstgDest,
         debugstr_w(pwcsNewName), grfFlags);
  return E_NOTIMPL;
}

/*************************************************************************
 * Commit (IStorage)
 *
 * Ensures that any changes made to a storage object open in transacted mode
 * are reflected in the parent storage
 *
 * NOTES
 *  Wine doesn't implement transacted mode, which seems to be a basic
 *  optimization, so we can ignore this stub for now.
 */
static HRESULT WINAPI StorageImpl_Commit(
  IStorage*   iface,
  DWORD         grfCommitFlags)/* [in] */
{
  FIXME("(%p %d): stub\n", iface, grfCommitFlags);
  return S_OK;
}

/*************************************************************************
 * Revert (IStorage)
 *
 * Discard all changes that have been made since the last commit operation
 */
static HRESULT WINAPI StorageImpl_Revert(
  IStorage* iface)
{
  FIXME("(%p): stub\n", iface);
  return E_NOTIMPL;
}

/*************************************************************************
 * DestroyElement (IStorage)
 *
 * Strategy: This implementation is built this way for simplicity not for speed.
 *          I always delete the topmost element of the enumeration and adjust
 *          the deleted element pointer all the time.  This takes longer to
 *          do but allow to reinvoke DestroyElement whenever we encounter a
 *          storage object.  The optimisation resides in the usage of another
 *          enumeration strategy that would give all the leaves of a storage
 *          first. (postfix order)
 */
static HRESULT WINAPI StorageImpl_DestroyElement(
  IStorage*     iface,
  const OLECHAR *pwcsName)/* [string][in] */
{
  StorageImpl* const This=(StorageImpl*)iface;

  IEnumSTATSTGImpl* propertyEnumeration;
  HRESULT           hr = S_OK;
  BOOL            res;
  StgProperty       propertyToDelete;
  StgProperty       parentProperty;
  ULONG             foundPropertyIndexToDelete;
  ULONG             typeOfRelation;
  ULONG             parentPropertyId = 0;

  TRACE("(%p, %s)\n",
	iface, debugstr_w(pwcsName));

  /*
   * Perform a sanity check on the parameters.
   */
  if (pwcsName==NULL)
    return STG_E_INVALIDPOINTER;

  /*
   * Create a property enumeration to search the property with the given name
   */
  propertyEnumeration = IEnumSTATSTGImpl_Construct(
    This->base.ancestorStorage,
    This->base.rootPropertySetIndex);

  foundPropertyIndexToDelete = IEnumSTATSTGImpl_FindProperty(
    propertyEnumeration,
    pwcsName,
    &propertyToDelete);

  IEnumSTATSTGImpl_Destroy(propertyEnumeration);

  if ( foundPropertyIndexToDelete == PROPERTY_NULL )
  {
    return STG_E_FILENOTFOUND;
  }

  /*
   * Find the parent property of the property to delete (the one that
   * link to it).  If This->dirProperty == foundPropertyIndexToDelete,
   * the parent is This. Otherwise, the parent is one of its sibling...
   */

  /*
   * First, read This's StgProperty..
   */
  res = StorageImpl_ReadProperty(
          This->base.ancestorStorage,
          This->base.rootPropertySetIndex,
          &parentProperty);

  assert(res);

  /*
   * Second, check to see if by any chance the actual storage (This) is not
   * the parent of the property to delete... We never know...
   */
  if ( parentProperty.dirProperty == foundPropertyIndexToDelete )
  {
    /*
     * Set data as it would have been done in the else part...
     */
    typeOfRelation   = PROPERTY_RELATION_DIR;
    parentPropertyId = This->base.rootPropertySetIndex;
  }
  else
  {
    /*
     * Create a property enumeration to search the parent properties, and
     * delete it once done.
     */
    IEnumSTATSTGImpl* propertyEnumeration2;

    propertyEnumeration2 = IEnumSTATSTGImpl_Construct(
      This->base.ancestorStorage,
      This->base.rootPropertySetIndex);

    typeOfRelation = IEnumSTATSTGImpl_FindParentProperty(
      propertyEnumeration2,
      foundPropertyIndexToDelete,
      &parentProperty,
      &parentPropertyId);

    IEnumSTATSTGImpl_Destroy(propertyEnumeration2);
  }

  if ( propertyToDelete.propertyType == PROPTYPE_STORAGE )
  {
    hr = deleteStorageProperty(
           This,
           foundPropertyIndexToDelete,
           propertyToDelete);
  }

⌨️ 快捷键说明

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