/*============================================================================ 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; }
/*============================================================================ 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; }
/*============================================================================ 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; }
/*============================================================================ 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; }
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; }