From 07347bee07513c1e9f8343f264ddbde6b7e47155 Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Tue, 20 Oct 2009 14:19:22 -0500 Subject: [PATCH] ole32: Don't use IEnumSTATSTGImpl to search in CreateStorage. --- dlls/ole32/storage32.c | 164 +++++++++++++++++++++++++++++++++++++++++++---- dlls/ole32/storage32.h | 4 + 2 files changed, 154 insertions(+), 14 deletions(-) diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index 0334cd8..66cf807 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -1072,11 +1072,9 @@ static HRESULT WINAPI StorageImpl_CreateStorage( { StorageImpl* const This=(StorageImpl*)iface; - IEnumSTATSTGImpl *propertyEnumeration; - StgProperty currentProperty; StgProperty newProperty; - ULONG foundPropertyIndex; ULONG newPropertyIndex; + Dirent storageDirent; HRESULT hr; TRACE("(%p, %s, %x, %d, %d, %p)\n", @@ -1107,18 +1105,9 @@ static HRESULT WINAPI StorageImpl_CreateStorage( 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, - ¤tProperty); - IEnumSTATSTGImpl_Destroy(propertyEnumeration); + hr = Dirent_FindElement(&This->base.dirent, pwcsName, &storageDirent); - if (foundPropertyIndex != PROPERTY_NULL) + if (SUCCEEDED(hr)) { /* * An element with this name already exists @@ -2123,6 +2112,105 @@ HRESULT Dirent_Create(Dirent *dirent, const Dirent *existing, DirentData *data) return hr; } +/* Fill the given data structure based on the data in the given directory entry. + * + * Returns STG_E_FILENOTFOUND if the directory entry is NULL. + */ +HRESULT Dirent_GetData(const Dirent *dirent, DirentData *data) +{ + BYTE currentProperty[PROPSET_BLOCK_SIZE]; + HRESULT hr; + ULONG index; + + hr = StorageImpl_ReadRawDirent(dirent->storage, dirent->index, currentProperty); + + if (SUCCEEDED(hr)) + { + memcpy( + data->name, + currentProperty+OFFSET_PS_NAME, + PROPERTY_NAME_BUFFER_LEN ); + TRACE("storage name: %s\n", debugstr_w(data->name)); + + StorageUtl_ReadWord( + currentProperty, + OFFSET_PS_NAMELENGTH, + &data->sizeOfNameString); + + if (0) + { + /* This may fail if we delete an object that is open. When we handle that + * situation correctly, this should always be true. */ + assert(data->sizeOfNameString != 0); + } + + memcpy(&data->direntType, currentProperty + OFFSET_PS_PROPERTYTYPE, 1); + + StorageUtl_ReadGUID( + currentProperty, + OFFSET_PS_GUID, + &data->guid); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSS1, + &data->ctime.dwLowDateTime); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSD1, + &data->ctime.dwHighDateTime); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSS2, + &data->mtime.dwLowDateTime); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_TSD2, + &data->mtime.dwHighDateTime); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_STARTBLOCK, + &data->startingBlock); + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_SIZE, + &data->size.u.LowPart); + + data->size.u.HighPart = 0; + + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_PREVIOUSPROP, + &index); + hr = Dirent_InitFromIndex(&data->leftChild, dirent->storage, index); + + if (SUCCEEDED(hr)) + { + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_NEXTPROP, + &index); + hr = Dirent_InitFromIndex(&data->rightChild, dirent->storage, index); + } + + if (SUCCEEDED(hr)) + { + StorageUtl_ReadDWord( + currentProperty, + OFFSET_PS_DIRPROP, + &index); + hr = Dirent_InitFromIndex(&data->dirRoot, dirent->storage, index); + } + } + + return hr; +} + /* Initialize a Dirent from a top-level Storage and index. */ HRESULT Dirent_InitFromIndex(Dirent *dirent, StorageImpl *storage, ULONG index) @@ -2142,6 +2230,54 @@ void Dirent_SetNull(Dirent *dirent) dirent->index = PROPERTY_NULL; } +/* Find the child of the given storage with the given name. + * + * Returns STG_E_NOSUCHFILE if the element does not exist. + * Returns STG_E_DOCFILECORRUPT if the given directory entry is not a storage. + */ +HRESULT Dirent_FindElement(const Dirent *storage, const OLECHAR *pwcsName, + Dirent *element) +{ + Dirent currentNode; + DirentData currentData; + HRESULT hr; + + /* Get the root of the binary tree */ + hr = Dirent_GetData(storage, ¤tData); + if (SUCCEEDED(hr)) + { + if (currentData.direntType != PROPTYPE_STORAGE && + currentData.direntType != PROPTYPE_ROOT) + { + return STG_E_DOCFILECORRUPT; + } + + currentNode = currentData.dirRoot; + + hr = Dirent_GetData(¤tNode, ¤tData); + } + + /* Search the binary tree */ + while (SUCCEEDED(hr)) + { + LONG cmp = propertyNameCmp(pwcsName, currentData.name); + + if (cmp == 0) + { + *element = currentNode; + return S_OK; + } + else if (cmp < 0) + currentNode = currentData.leftChild; + else /* cmp > 0 */ + currentNode = currentData.rightChild; + + hr = Dirent_GetData(¤tNode, ¤tData); + } + + return hr; +} + /********************************************************************* * diff --git a/dlls/ole32/storage32.h b/dlls/ole32/storage32.h index bd1e17f..f8ceea1 100644 --- a/dlls/ole32/storage32.h +++ b/dlls/ole32/storage32.h @@ -183,6 +183,10 @@ HRESULT Dirent_SetData(const Dirent *dirent, DWORD fields, const DirentData *dat HRESULT Dirent_Destroy(const Dirent *dirent); HRESULT Dirent_InitFromIndex(Dirent *dirent, StorageImpl *storage, ULONG index); +/* High-level Dirent operations. */ +HRESULT Dirent_FindElement(const Dirent *storage, const OLECHAR *pwcsName, + Dirent *element); + /* Flags for Dirent_SetData */ #define DIRENT_SET_NAME 0x1 #define DIRENT_SET_TYPE 0x2 -- 1.5.4.3