Beispiel #1
0
/*============================================================================
  Description: (API call) Sets the CLSID of the storage
  Arguments:   
   io_pDir - non-NULL pointer to a storage to modify
   in_pCLSID - pointer to the new CLSID for the storage.  Makes a copy.  Must 
               be non-NULL.
  Return:       
   Status code
  ==========================================================================*/
int
storageSetClass(Storage* io_pStorage,
                const SSRW_CLSID* in_pCLSID)
{
    TOC*            pTOC =      NULL;
    DirectoryEntry* pDirEntry = NULL;
    SINT4           iRet =      SSTG_OK;

    ASSERT (io_pStorage != NULL);
    ASSERT (STG_CANWRITE(io_pStorage->mode));
    if ((io_pStorage == NULL) ||
        (!STG_CANWRITE(io_pStorage->mode)))
    {
        return (int)SSTG_ERROR_ILLEGAL_CALL;
    }

    iRet = rootStorageSetDirty(io_pStorage->pRoot);
    if (iRet != SSTG_OK)
    {
        return iRet;
    }

    pTOC = rootStorageGetTOC(io_pStorage->pRoot);
    pDirEntry = tocGetEntryAtIndex(pTOC, io_pStorage->ulDirIndex);
    return (int)directorySetClass(pDirEntry, in_pCLSID);
}
/*============================================================================
 Description: (API Call) Creates new structured storage and compound file and
   attaches them one to another, on an existing AAF OMRawStorage
 Arguments:
   in_pRaw -         OMRawStorage to which the library will connect
   in_accessMode -   Must be STG_WRITE or STG_RW.
   out_ppRoot -      on success, will be filled with a pointer to a new
                     RootStorage structure representing a new structured 
                     storage file.
   in_ulSectorSize - size, in bytes, of sectors in the new file.  Passing 0 
                     will cause a default sector size to be used.  The sector 
                     size must be a power of 2 if it is not 0.
 Return:
   Status code
 ==========================================================================*/
int createStructuredStorageInOMRawStorageEx (
      const OMRawStorage* in_pRaw,
      StgMode in_accessMode,
      RootStorage** out_ppRoot,
      unsigned long in_ulSectorSize)
{
    SSRWIS* pIS =   NULL;
    SINT4   iRet =  SSTG_OK;

    ASSERT (in_pRaw != NULL);
    ASSERT (STG_CANWRITE(in_accessMode));
    ASSERT (out_ppRoot != NULL);
    ASSERT (((in_ulSectorSize - 1) & in_ulSectorSize) == 0);
    if ((in_pRaw == NULL) ||
        (out_ppRoot == NULL) ||
        (((in_ulSectorSize - 1) & in_ulSectorSize) != 0))
    {
        return SSTG_ERROR_ILLEGAL_CALL;
    }

    if (!STG_CANWRITE(in_accessMode))
    {
        return SSTG_ERROR_ILLEGAL_ACCESS;
    }

    pIS = SsrwConnectToOMRaw(in_pRaw);
    if (pIS == NULL)
    {
        return SSTG_ERROR_FILEIO;
    }
	 iRet = createStructuredStorageInSource(pIS,
                                           in_accessMode,
                                           out_ppRoot,
                                           (UINT4)in_ulSectorSize);
/*
    iRet = createStructuredStorageInternal(pIS,
                                           in_accessMode,
                                           out_ppRoot,
                                           SSRW_FALSE,
                                           (UINT4)in_ulSectorSize);
										   */
    if (iRet != SSTG_OK)
    {
        SsrwDisconnect(pIS);
    }

    return iRet;
}
Beispiel #3
0
/*============================================================================
  Description: (API call) Removes a given storage or stream from the 
               structured storage file.
  Arguments:   
   io_pParent - storage containing the item to destroy
   in_pName -   name of item to destroy
  Return:       
   Status code
  ==========================================================================*/
int 
destroy( Storage* io_pParent, const wchar_t* in_pName)
{
    SINT4           iRet =         SSTG_OK;
    TOC*            pTOC =         NULL;
    DirectoryEntry* pParentEntry = NULL;
    DirectoryEntry* pChildEntry =  NULL;
    StgInfo*        pStgChildren = NULL;
    SINT4           childCount =   0;
    SINT4           i =            0;
    Storage*        pStorage =     0;
    Header*         pHeader =      NULL;
    Fat*            pRegFat =      NULL;
    Fat*            pSmallFat =    NULL;
    
    ASSERT(io_pParent != NULL);
    ASSERT(in_pName != NULL);
    ASSERT(STG_CANWRITE(io_pParent->mode));

    if ((io_pParent == NULL) || (in_pName == NULL))
    {
        return SSTG_ERROR_ILLEGAL_CALL;
    }
    if (!STG_CANWRITE(io_pParent->mode))
    {
        return SSTG_ERROR_ILLEGAL_ACCESS;
    }

    pRegFat = rootStorageGetFat(io_pParent->pRoot);
    pSmallFat = rootStorageGetSmallFat(io_pParent->pRoot);

    /* Get parent storage's directory entry */
    pTOC = rootStorageGetTOC(io_pParent->pRoot);
    pParentEntry = tocGetEntryAtIndex(pTOC, io_pParent->ulDirIndex);
    if (pParentEntry == NULL)
    {
        return (int)SSTG_ERROR_CHILD_NOT_FOUND;
    }

    /* Find specified stream's directory entry */
    iRet = tocFindChildEntry (pTOC,
                              pParentEntry,
                              in_pName,
                              &pChildEntry);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

    /* Ensure that the deletion operation is legal */
    if ((directoryGetType(pChildEntry) != DIR_STREAM) &&
        (directoryGetType(pChildEntry) != DIR_STORAGE))
    {
        return SSTG_ERROR_ILLEGAL_ACCESS;
    }

    /* From this point on, any failures will cause an incomplete state in
     * the structured storage file.  */

    /* Mark all metadata as being dirty so it will be rewritten later */
    iRet = rootStorageSetDirty(io_pParent->pRoot);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

    if (directoryGetType(pChildEntry) == DIR_STREAM)
    {
        pHeader = rootStorageGetHeader(io_pParent->pRoot);
        if (directoryGetStreamLength(pChildEntry) < 
            headerGetSmallStreamCutoff(pHeader))
        {
            /* Merge the sectors of the stream into the free chain */
            iRet = fatFreeChain(pSmallFat,
                                directoryGetStartSector(pChildEntry));
            if (iRet != SSTG_OK)
            {
                return iRet;
            }

            /* Recover as many sectors as possible from the small FAT's free 
             * chain */
            iRet = fatRecoverMiniFatFreeSectors(pSmallFat, pRegFat);
            if (iRet != SSTG_OK)
            {
                return iRet;
            }
        }
        else
        {
            /* Merge the sectors of the stream into the free chain */
            iRet = fatFreeChain(pRegFat, directoryGetStartSector(pChildEntry));
            if (iRet != SSTG_OK)
            {
                return iRet;
            }
        }
    }
    else if (directoryGetType(pChildEntry) == DIR_STORAGE)
    {
        /* Non-empty storages should be removed recursively */
        iRet = openStorage(io_pParent, in_pName, &pStorage);
        if (iRet != SSTG_OK)
        {
            return iRet;
        }

        iRet = getChildrenInfo(pStorage, &pStgChildren, (int*)(void*)&childCount);
        if (iRet != SSTG_OK)
        {
            return iRet;
        }
        for (i = 0; i < childCount; i++)
        {
            iRet = destroy(pStorage, pStgChildren[i].sName);
            if (iRet != SSTG_OK)
            {
                return iRet;
            }
        }

        if (childCount > 0)
        {
            iRet = freeInfo(&pStgChildren, childCount);
            if (iRet != SSTG_OK)
            {
                return iRet;
            }
        }

        iRet = closeStorage(&pStorage);
        if (iRet != SSTG_OK)
        {
            return iRet;
        }
    }

    /* Remove the corresponding entry from the TOC */
    iRet = tocRemoveEntry(pTOC, pParentEntry, pChildEntry);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

#ifdef DEBUG
    assertMiniStreamIntegrity(io_pParent->pRoot);
#endif /* DEBUG */

    return (int) iRet;
}
Beispiel #4
0
/*============================================================================
  Description:  (API Call) Creates a new stream in a given storage.  Only 
                allowed if the parent storage is open in STG_WRITE mode.
  Arguments:    
   in_pStorage - storage in which to create a new stream
   in_wszName -  name of new stream
   out_ppChild - pointer to pointer that will, on success, point to freshly 
                 created empty stream
  Return:       
   Status code
  ==========================================================================*/
int
createStream (Storage* in_pStorage,
              const wchar_t* in_wszName,
              Stream** out_ppChild)
{
    DirectoryEntry* pEntry =    NULL;
    SINT4           iRet =      SSTG_OK;
    TOC*            pTOC =      NULL;

    ASSERT(in_pStorage != NULL &&
           in_wszName != NULL &&
           *in_wszName != 0 &&
           out_ppChild != NULL &&
           STG_CANWRITE(in_pStorage->mode));
    if (in_pStorage == NULL ||
            in_wszName == NULL ||
            *in_wszName == 0 ||
            out_ppChild == NULL ||
            (!STG_CANWRITE(in_pStorage->mode)))
    {
        return SSTG_ERROR_ILLEGAL_CALL;
    }

    *out_ppChild = NULL;
    /* Mark all metadata as being dirty so it will be rewritten later */
    iRet = rootStorageSetDirty(in_pStorage->pRoot);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

    /* create a directory entry for the stream */
    pTOC = rootStorageGetTOC (in_pStorage->pRoot);
    iRet =  tocAddEntry(pTOC, &pEntry);
    if (iRet != SSTG_OK)
    {
        streamDestroy(out_ppChild);
        return iRet;
    }

    iRet = directoryInitEntry (pEntry,
                               in_wszName,
                               DIR_STREAM,
                               in_pStorage->pRoot);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        return iRet;
    }

    /* Make the new entry the child of its parent */
    iRet = tocInsertChild(pTOC,
                          tocGetEntryAtIndex (pTOC,
                                              in_pStorage->ulDirIndex),
                          pEntry);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        return iRet;
    }

    /* Construct the stream structure itself */
    iRet = streamConstruct (in_pStorage->pRoot, 
                            in_pStorage, 
                            pEntry, 
                            in_pStorage->mode,
                            out_ppChild);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

    _KABOOM3;

    /* If the stream is read/writable and is a small stream, upgrade it 
     * immediately to a full-size stream.  If it is still smaller than the 
     * cutoff when it is closed, it will be demoted again.  This is to avoid 
     * having two implementations of all the writing and rewriting code. 
     * 
     * There is a special high-performance case for write-only files, so we
     * don't have to upgrade the stream in that case. */
    if (STG_CANWRITE(in_pStorage->mode) && STG_CANREAD(in_pStorage->mode))
    {
        /* This call returns success if the stream is already a regular stream 
         */
        iRet = streamUpgradeMiniToRegular(*out_ppChild);
        if (iRet != SSTG_OK)
        {
            tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
            streamDestroy(out_ppChild);
            return iRet;
        }
    }

    /* Add this stream to its parent storage's list of open streams and
     * storages */
    iRet = openListAppend (in_pStorage->pOpenList, STREAM, *out_ppChild);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        streamDestroy(out_ppChild);
        return iRet;
    }

    return iRet;
}
Beispiel #5
0
/*============================================================================
  Description:  Opens a given stream in a given storage for reading.

                This is valid in all modes, although STG_WRITE is only allowed
                because it is necessary for streamResize().

  Arguments: 
   in_pStorage - parent of stream to open
   in_wszName -  name of stream to open
   out_ppChild - on success, will point to a newly created Stream structure
  Return: 
   Status code
  ==========================================================================*/
SINT4
openStreamInternal (Storage* in_pStorage,
                    const wchar_t* in_wszName,
                    Stream** out_ppChild)
{
    DirectoryEntry* pChildEntry =   NULL;
    DirectoryEntry* pParentEntry =  NULL;
    SINT4           iRet =          SSTG_OK;
    TOC*            pTOC =          NULL;

    TCHECK1;

    ASSERT((in_pStorage != NULL) &&
           (in_pStorage->pRoot != NULL) &&
           (in_wszName != NULL) &&
           (*in_wszName != 0) &&
           (out_ppChild != NULL));
    if ((in_pStorage == NULL) ||
        (in_pStorage->pRoot == NULL) ||
        (in_wszName == NULL) ||
        (*in_wszName == 0) ||
        (out_ppChild == NULL))
    {
        return SSTG_ERROR_ILLEGAL_CALL;
    }

    /* Get parent storage's directory entry */
    pTOC = rootStorageGetTOC(in_pStorage->pRoot);
    pParentEntry = tocGetEntryAtIndex(pTOC, in_pStorage->ulDirIndex);
    if (pParentEntry == NULL)
    {
        return SSTG_ERROR_CHILD_NOT_FOUND;
    }

    /* Find specified stream's directory entry */
    iRet = tocFindChildEntry (pTOC, pParentEntry, in_wszName, &pChildEntry);
    if (iRet != SSTG_OK)
    {
        return iRet;
    }

    /* Construct the actual stream structure */
    iRet = streamConstruct (in_pStorage->pRoot,
                            in_pStorage,
                            pChildEntry,
                            in_pStorage->mode,
                            out_ppChild);
    if (iRet != SSTG_OK)
    {
        return iRet;
    }

    KABOOM1;

    /* If the stream is writable and is a small stream, upgrade it immediately
     * to a full-size stream.  If it is still smaller than the cutoff when
     * it is closed, it will be demoted again.  This is to avoid having two
     * implementations of all the writing and rewriting code. */
#if UPGRADE_MINI_STREAM
    if (STG_CANWRITE(in_pStorage->mode))
    {
        /* This call returns success if the stream is already a regular stream 
         */
        iRet = streamUpgradeMiniToRegular(*out_ppChild);
        if (iRet != SSTG_OK)
        {
            streamDestroy(out_ppChild);
            return iRet;
        }
    }
#endif
    
    /* Add the newly opened stream to its parent storage's list of open
     * children */
    iRet = openListAppend (in_pStorage->pOpenList, STREAM, *out_ppChild);
    if (iRet != SSTG_OK)
    {
        streamDestroy(out_ppChild);
        return iRet;
    }

    return iRet;
}
Beispiel #6
0
int
createStorage (Storage* in_pStorage,
               const wchar_t* in_wszName,
               Storage** out_ppChild)
{
    Storage*        pNewStorage =   NULL;
    DirectoryEntry* pEntry =        NULL;
    SINT4           iRet =          SSTG_OK;
    TOC*            pTOC =          NULL;


    ASSERT (in_pStorage != NULL &&
            in_wszName != NULL &&
            *in_wszName != 0 &&
            out_ppChild != NULL &&
            STG_CANWRITE(in_pStorage->mode));
    if (in_pStorage == NULL ||
        in_wszName == NULL ||
        *in_wszName == 0 ||
        out_ppChild == NULL ||
        !STG_CANWRITE(in_pStorage->mode))
    {
        return SSTG_ERROR_ILLEGAL_CALL;
    }

    /* Mark all metadata as being dirty so it will be rewritten later */
    iRet = rootStorageSetDirty(in_pStorage->pRoot);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }

    iRet = storageConstruct (out_ppChild);
    if (iRet != SSTG_OK)
    {
        return (int)iRet;
    }
    pNewStorage = *out_ppChild;

    pNewStorage->pRoot = in_pStorage->pRoot;
    pNewStorage->pParent = in_pStorage;

    /* create a directory entry for the storage */
    pTOC = rootStorageGetTOC(in_pStorage->pRoot);
    iRet =  tocAddEntry(pTOC, &pEntry);
    if (iRet != SSTG_OK)
    {
        storageDestroy(out_ppChild);
        return iRet;
    }

    iRet = directoryInitEntry (pEntry,
                               in_wszName,
                               DIR_STORAGE,
                               in_pStorage->pRoot);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        storageDestroy(out_ppChild);
        return iRet;
    }
    iRet = directorySetCurrentCreationTime(pEntry);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        storageDestroy(out_ppChild);
        return iRet;
    }

    /* Make the new entry the child of its parent */
    iRet = tocInsertChild(pTOC,
                          tocGetEntryAtIndex (pTOC, in_pStorage->ulDirIndex),
                          pEntry);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        storageDestroy(out_ppChild);
        return iRet;
    }

    _TCHECK;

    pNewStorage->ulDirIndex = directoryGetIndex(pEntry);
    pNewStorage->mode = in_pStorage->mode;

    iRet = openListAppend (in_pStorage->pOpenList, STORAGE, *out_ppChild);
    if (iRet != SSTG_OK)
    {
        tocInvalidateEntry (pTOC, directoryGetIndex(pEntry));
        storageDestroy(out_ppChild);
        return iRet;
    }

    return iRet;
}