ole32: Store the most recent item name in IEnumSTATSTG instead of a stack.

This commit is contained in:
Vincent Povirk 2009-12-18 19:45:36 -06:00 committed by Alexandre Julliard
parent 4492850200
commit fc50ff07d6
2 changed files with 71 additions and 187 deletions

View File

@ -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, &currentSearchNode);
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, &currentSearchNode);
/*
* Read the entry from the storage.
*/
StorageBaseImpl_ReadDirEntry(This->parentStorage,
currentSearchNode,
&currentEntry);
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 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;
This->name[0] = 0;
/*
* Read the storage entry from the top-level storage.
*/
hr = StorageBaseImpl_ReadDirEntry(
This->parentStorage,
This->storageDirEntry,
&storageEntry);
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.
*/
@ -4828,14 +4722,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.
*/

View File

@ -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);
}