From e24c236081fe57058cd8da5d586bd5b46ac4267d Mon Sep 17 00:00:00 2001 From: Vincent Povirk Date: Fri, 18 Dec 2009 19:45:36 -0600 Subject: [PATCH 3/3] ole32: Store the most recent item name in IEnumSTATSTG instead of a stack. --- dlls/ole32/storage32.c | 246 +++++++++++------------------------------ dlls/ole32/tests/storage32.c | 12 +-- 2 files changed, 71 insertions(+), 187 deletions(-) diff --git a/dlls/ole32/storage32.c b/dlls/ole32/storage32.c index e21acf1..ef71e6f 100644 --- a/dlls/ole32/storage32.c +++ b/dlls/ole32/storage32.c @@ -258,23 +258,12 @@ struct IEnumSTATSTGImpl StorageBaseImpl* parentStorage; /* Reference to the parent storage */ DirRef storageDirEntry; /* Directory entry of the storage to enumerate */ - /* - * The current implementation of the IEnumSTATSTGImpl class uses a stack - * to walk the directory entries to get the content of a storage. This stack - * is implemented by the following 3 data members - */ - ULONG stackSize; - ULONG stackMaxSize; - DirRef* stackToVisit; - -#define ENUMSTATSGT_SIZE_INCREMENT 10 + WCHAR name[DIRENTRY_NAME_MAX_LEN]; /* The most recent name visited */ }; static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(StorageBaseImpl* This, DirRef storageDirEntry); static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This); -static void IEnumSTATSTGImpl_PushSearchNode(IEnumSTATSTGImpl* This, DirRef nodeToPush); -static DirRef IEnumSTATSTGImpl_PopSearchNode(IEnumSTATSTGImpl* This, BOOL remove); /************************************************************************ ** Block Functions @@ -4446,7 +4435,6 @@ static HRESULT WINAPI StorageInternalImpl_Revert( static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This) { IStorage_Release((IStorage*)This->parentStorage); - HeapFree(GetProcessHeap(), 0, This->stackToVisit); HeapFree(GetProcessHeap(), 0, This); } @@ -4497,6 +4485,51 @@ static ULONG WINAPI IEnumSTATSTGImpl_Release( return newRef; } +static HRESULT IEnumSTATSTGImpl_GetNextRef( + IEnumSTATSTGImpl* This, + DirRef *ref) +{ + DirRef result = DIRENTRY_NULL; + DirRef searchNode; + DirEntry entry; + HRESULT hr; + WCHAR result_name[DIRENTRY_NAME_MAX_LEN]; + + hr = StorageBaseImpl_ReadDirEntry(This->parentStorage, + This->parentStorage->storageDirEntry, &entry); + searchNode = entry.dirRootEntry; + + while (SUCCEEDED(hr) && searchNode != DIRENTRY_NULL) + { + hr = StorageBaseImpl_ReadDirEntry(This->parentStorage, searchNode, &entry); + + if (SUCCEEDED(hr)) + { + LONG diff = entryNameCmp( entry.name, This->name); + + if (diff <= 0) + { + searchNode = entry.rightChild; + } + else + { + result = searchNode; + memcpy(result_name, entry.name, sizeof(result_name)); + searchNode = entry.leftChild; + } + } + } + + if (SUCCEEDED(hr)) + { + *ref = result; + if (result != DIRENTRY_NULL) + memcpy(This->name, result_name, sizeof(result_name)); + } + + return hr; +} + static HRESULT WINAPI IEnumSTATSTGImpl_Next( IEnumSTATSTG* iface, ULONG celt, @@ -4509,6 +4542,7 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next( STATSTG* currentReturnStruct = rgelt; ULONG objectFetched = 0; DirRef currentSearchNode; + HRESULT hr=S_OK; if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) ) return E_INVALIDARG; @@ -4529,18 +4563,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next( */ *pceltFetched = 0; - /* - * Start with the node at the top of the stack. - */ - currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); - - while ( ( *pceltFetched < celt) && - ( currentSearchNode!=DIRENTRY_NULL) ) + while ( *pceltFetched < celt ) { - /* - * Remove the top node from the stack - */ - IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + hr = IEnumSTATSTGImpl_GetNextRef(This, ¤tSearchNode); + + if (FAILED(hr) || currentSearchNode == DIRENTRY_NULL) + break; /* * Read the entry from the storage. @@ -4562,22 +4590,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next( */ (*pceltFetched)++; currentReturnStruct++; - - /* - * Push the next search node in the search stack. - */ - IEnumSTATSTGImpl_PushSearchNode(This, currentEntry.rightChild); - - /* - * continue the iteration. - */ - currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); } - if (*pceltFetched == celt) - return S_OK; + if (SUCCEEDED(hr) && *pceltFetched != celt) + hr = S_FALSE; - return S_FALSE; + return hr; } @@ -4587,53 +4605,27 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Skip( { IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; - DirEntry currentEntry; ULONG objectFetched = 0; DirRef currentSearchNode; + HRESULT hr=S_OK; if (This->parentStorage->reverted) return STG_E_REVERTED; - /* - * Start with the node at the top of the stack. - */ - currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); - - while ( (objectFetched < celt) && - (currentSearchNode!=DIRENTRY_NULL) ) + while ( (objectFetched < celt) ) { - /* - * Remove the top node from the stack - */ - IEnumSTATSTGImpl_PopSearchNode(This, TRUE); + hr = IEnumSTATSTGImpl_GetNextRef(This, ¤tSearchNode); - /* - * Read the entry from the storage. - */ - StorageBaseImpl_ReadDirEntry(This->parentStorage, - currentSearchNode, - ¤tEntry); + if (FAILED(hr) || currentSearchNode == DIRENTRY_NULL) + break; - /* - * Step to the next item in the iteration - */ objectFetched++; - - /* - * Push the next search node in the search stack. - */ - IEnumSTATSTGImpl_PushSearchNode(This, currentEntry.rightChild); - - /* - * continue the iteration. - */ - currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE); } - if (objectFetched == celt) - return S_OK; + if (SUCCEEDED(hr) && objectFetched != celt) + return S_FALSE; - return S_FALSE; + return hr; } static HRESULT WINAPI IEnumSTATSTGImpl_Reset( @@ -4641,36 +4633,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Reset( { IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface; - DirEntry storageEntry; - HRESULT hr; - if (This->parentStorage->reverted) return STG_E_REVERTED; - /* - * Re-initialize the search stack to an empty stack - */ - This->stackSize = 0; - - /* - * Read the storage entry from the top-level storage. - */ - hr = StorageBaseImpl_ReadDirEntry( - This->parentStorage, - This->storageDirEntry, - &storageEntry); + This->name[0] = 0; - if (SUCCEEDED(hr)) - { - assert(storageEntry.sizeOfNameString!=0); - - /* - * Push the search node in the search stack. - */ - IEnumSTATSTGImpl_PushSearchNode(This, storageEntry.dirRootEntry); - } - - return hr; + return S_OK; } static HRESULT WINAPI IEnumSTATSTGImpl_Clone( @@ -4698,15 +4666,7 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Clone( * The new clone enumeration must point to the same current node as * the ole one. */ - newClone->stackSize = This->stackSize ; - newClone->stackMaxSize = This->stackMaxSize ; - newClone->stackToVisit = - HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG) * newClone->stackMaxSize); - - memcpy( - newClone->stackToVisit, - This->stackToVisit, - sizeof(DirRef) * newClone->stackSize); + memcpy(newClone->name, This->name, sizeof(newClone->name)); *ppenum = (IEnumSTATSTG*)newClone; @@ -4719,72 +4679,6 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Clone( return S_OK; } -static void IEnumSTATSTGImpl_PushSearchNode( - IEnumSTATSTGImpl* This, - DirRef nodeToPush) -{ - DirEntry storageEntry; - HRESULT hr; - - /* - * First, make sure we're not trying to push an unexisting node. - */ - if (nodeToPush==DIRENTRY_NULL) - return; - - /* - * First push the node to the stack - */ - if (This->stackSize == This->stackMaxSize) - { - This->stackMaxSize += ENUMSTATSGT_SIZE_INCREMENT; - - This->stackToVisit = HeapReAlloc( - GetProcessHeap(), - 0, - This->stackToVisit, - sizeof(DirRef) * This->stackMaxSize); - } - - This->stackToVisit[This->stackSize] = nodeToPush; - This->stackSize++; - - /* - * Read the storage entry from the top-level storage. - */ - hr = StorageBaseImpl_ReadDirEntry( - This->parentStorage, - nodeToPush, - &storageEntry); - - if (SUCCEEDED(hr)) - { - assert(storageEntry.sizeOfNameString!=0); - - /* - * Push the previous search node in the search stack. - */ - IEnumSTATSTGImpl_PushSearchNode(This, storageEntry.leftChild); - } -} - -static DirRef IEnumSTATSTGImpl_PopSearchNode( - IEnumSTATSTGImpl* This, - BOOL remove) -{ - DirRef topNode; - - if (This->stackSize == 0) - return DIRENTRY_NULL; - - topNode = This->stackToVisit[This->stackSize-1]; - - if (remove) - This->stackSize--; - - return topNode; -} - /* * Virtual function table for the IEnumSTATSTGImpl class. */ @@ -4829,14 +4723,6 @@ static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct( newEnumeration->storageDirEntry = storageDirEntry; /* - * Initialize the search stack - */ - newEnumeration->stackSize = 0; - newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT; - newEnumeration->stackToVisit = - HeapAlloc(GetProcessHeap(), 0, sizeof(DirRef)*ENUMSTATSGT_SIZE_INCREMENT); - - /* * Make sure the current node of the iterator is the first one. */ IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration); diff --git a/dlls/ole32/tests/storage32.c b/dlls/ole32/tests/storage32.c index 4199d5f..a1a4da4 100644 --- a/dlls/ole32/tests/storage32.c +++ b/dlls/ole32/tests/storage32.c @@ -891,12 +891,10 @@ static void test_streamenum(void) r = IStorage_DestroyElement(stg, stmname); ok(r==S_OK, "IStorage->DestroyElement failed\n"); - todo_wine { count = 0xf00; r = IEnumSTATSTG_Next(ee, 1, &stat, &count); ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n"); ok(count == 0, "count wrong\n"); - } /* reset and try again */ r = IEnumSTATSTG_Reset(ee); @@ -918,8 +916,8 @@ static void test_streamenum(void) count = 0xf00; r = IEnumSTATSTG_Next(ee, 1, &stat, &count); - todo_wine ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); - todo_wine ok(count == 1, "count wrong\n"); + ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); + ok(count == 1, "count wrong\n"); if (r == S_OK) { @@ -934,8 +932,8 @@ static void test_streamenum(void) count = 0xf00; r = IEnumSTATSTG_Next(ee, 1, &stat, &count); - todo_wine ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); - todo_wine ok(count == 1, "count wrong\n"); + ok(r==S_OK, "IEnumSTATSTG->Next failed\n"); + ok(count == 1, "count wrong\n"); if (r == S_OK) { @@ -976,7 +974,7 @@ static void test_streamenum(void) if (r == S_OK) { - todo_wine ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName)); + ok(lstrcmpiW(stat.pwcsName, stmname3) == 0, "expected ABCDEFGHIJ, got %s\n", wine_dbgstr_w(stat.pwcsName)); CoTaskMemFree(stat.pwcsName); } -- 1.6.3.3