ole32: Store the most recent item name in IEnumSTATSTG instead of a stack.
This commit is contained in:
parent
4492850200
commit
fc50ff07d6
|
@ -258,23 +258,12 @@ struct IEnumSTATSTGImpl
|
||||||
StorageBaseImpl* parentStorage; /* Reference to the parent storage */
|
StorageBaseImpl* parentStorage; /* Reference to the parent storage */
|
||||||
DirRef storageDirEntry; /* Directory entry of the storage to enumerate */
|
DirRef storageDirEntry; /* Directory entry of the storage to enumerate */
|
||||||
|
|
||||||
/*
|
WCHAR name[DIRENTRY_NAME_MAX_LEN]; /* The most recent name visited */
|
||||||
* 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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(StorageBaseImpl* This, DirRef storageDirEntry);
|
static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(StorageBaseImpl* This, DirRef storageDirEntry);
|
||||||
static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This);
|
static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This);
|
||||||
static void IEnumSTATSTGImpl_PushSearchNode(IEnumSTATSTGImpl* This, DirRef nodeToPush);
|
|
||||||
static DirRef IEnumSTATSTGImpl_PopSearchNode(IEnumSTATSTGImpl* This, BOOL remove);
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
** Block Functions
|
** Block Functions
|
||||||
|
@ -4446,7 +4435,6 @@ static HRESULT WINAPI StorageInternalImpl_Revert(
|
||||||
static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This)
|
static void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This)
|
||||||
{
|
{
|
||||||
IStorage_Release((IStorage*)This->parentStorage);
|
IStorage_Release((IStorage*)This->parentStorage);
|
||||||
HeapFree(GetProcessHeap(), 0, This->stackToVisit);
|
|
||||||
HeapFree(GetProcessHeap(), 0, This);
|
HeapFree(GetProcessHeap(), 0, This);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4497,6 +4485,51 @@ static ULONG WINAPI IEnumSTATSTGImpl_Release(
|
||||||
return newRef;
|
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(
|
static HRESULT WINAPI IEnumSTATSTGImpl_Next(
|
||||||
IEnumSTATSTG* iface,
|
IEnumSTATSTG* iface,
|
||||||
ULONG celt,
|
ULONG celt,
|
||||||
|
@ -4509,6 +4542,7 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
|
||||||
STATSTG* currentReturnStruct = rgelt;
|
STATSTG* currentReturnStruct = rgelt;
|
||||||
ULONG objectFetched = 0;
|
ULONG objectFetched = 0;
|
||||||
DirRef currentSearchNode;
|
DirRef currentSearchNode;
|
||||||
|
HRESULT hr=S_OK;
|
||||||
|
|
||||||
if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) )
|
if ( (rgelt==0) || ( (celt!=1) && (pceltFetched==0) ) )
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -4529,18 +4563,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
|
||||||
*/
|
*/
|
||||||
*pceltFetched = 0;
|
*pceltFetched = 0;
|
||||||
|
|
||||||
/*
|
while ( *pceltFetched < celt )
|
||||||
* Start with the node at the top of the stack.
|
|
||||||
*/
|
|
||||||
currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE);
|
|
||||||
|
|
||||||
while ( ( *pceltFetched < celt) &&
|
|
||||||
( currentSearchNode!=DIRENTRY_NULL) )
|
|
||||||
{
|
{
|
||||||
/*
|
hr = IEnumSTATSTGImpl_GetNextRef(This, ¤tSearchNode);
|
||||||
* Remove the top node from the stack
|
|
||||||
*/
|
if (FAILED(hr) || currentSearchNode == DIRENTRY_NULL)
|
||||||
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the entry from the storage.
|
* Read the entry from the storage.
|
||||||
|
@ -4562,22 +4590,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Next(
|
||||||
*/
|
*/
|
||||||
(*pceltFetched)++;
|
(*pceltFetched)++;
|
||||||
currentReturnStruct++;
|
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)
|
if (SUCCEEDED(hr) && *pceltFetched != celt)
|
||||||
return S_OK;
|
hr = S_FALSE;
|
||||||
|
|
||||||
return S_FALSE;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4587,53 +4605,27 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Skip(
|
||||||
{
|
{
|
||||||
IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface;
|
IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface;
|
||||||
|
|
||||||
DirEntry currentEntry;
|
|
||||||
ULONG objectFetched = 0;
|
ULONG objectFetched = 0;
|
||||||
DirRef currentSearchNode;
|
DirRef currentSearchNode;
|
||||||
|
HRESULT hr=S_OK;
|
||||||
|
|
||||||
if (This->parentStorage->reverted)
|
if (This->parentStorage->reverted)
|
||||||
return STG_E_REVERTED;
|
return STG_E_REVERTED;
|
||||||
|
|
||||||
/*
|
while ( (objectFetched < celt) )
|
||||||
* Start with the node at the top of the stack.
|
|
||||||
*/
|
|
||||||
currentSearchNode = IEnumSTATSTGImpl_PopSearchNode(This, FALSE);
|
|
||||||
|
|
||||||
while ( (objectFetched < celt) &&
|
|
||||||
(currentSearchNode!=DIRENTRY_NULL) )
|
|
||||||
{
|
{
|
||||||
/*
|
hr = IEnumSTATSTGImpl_GetNextRef(This, ¤tSearchNode);
|
||||||
* Remove the top node from the stack
|
|
||||||
*/
|
|
||||||
IEnumSTATSTGImpl_PopSearchNode(This, TRUE);
|
|
||||||
|
|
||||||
/*
|
if (FAILED(hr) || currentSearchNode == DIRENTRY_NULL)
|
||||||
* Read the entry from the storage.
|
break;
|
||||||
*/
|
|
||||||
StorageBaseImpl_ReadDirEntry(This->parentStorage,
|
|
||||||
currentSearchNode,
|
|
||||||
¤tEntry);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Step to the next item in the iteration
|
|
||||||
*/
|
|
||||||
objectFetched++;
|
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)
|
if (SUCCEEDED(hr) && objectFetched != celt)
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IEnumSTATSTGImpl_Reset(
|
static HRESULT WINAPI IEnumSTATSTGImpl_Reset(
|
||||||
|
@ -4641,36 +4633,12 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Reset(
|
||||||
{
|
{
|
||||||
IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface;
|
IEnumSTATSTGImpl* const This=(IEnumSTATSTGImpl*)iface;
|
||||||
|
|
||||||
DirEntry storageEntry;
|
|
||||||
HRESULT hr;
|
|
||||||
|
|
||||||
if (This->parentStorage->reverted)
|
if (This->parentStorage->reverted)
|
||||||
return STG_E_REVERTED;
|
return STG_E_REVERTED;
|
||||||
|
|
||||||
/*
|
This->name[0] = 0;
|
||||||
* Re-initialize the search stack to an empty stack
|
|
||||||
*/
|
|
||||||
This->stackSize = 0;
|
|
||||||
|
|
||||||
/*
|
return S_OK;
|
||||||
* 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI IEnumSTATSTGImpl_Clone(
|
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 new clone enumeration must point to the same current node as
|
||||||
* the ole one.
|
* the ole one.
|
||||||
*/
|
*/
|
||||||
newClone->stackSize = This->stackSize ;
|
memcpy(newClone->name, This->name, sizeof(newClone->name));
|
||||||
newClone->stackMaxSize = This->stackMaxSize ;
|
|
||||||
newClone->stackToVisit =
|
|
||||||
HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG) * newClone->stackMaxSize);
|
|
||||||
|
|
||||||
memcpy(
|
|
||||||
newClone->stackToVisit,
|
|
||||||
This->stackToVisit,
|
|
||||||
sizeof(DirRef) * newClone->stackSize);
|
|
||||||
|
|
||||||
*ppenum = (IEnumSTATSTG*)newClone;
|
*ppenum = (IEnumSTATSTG*)newClone;
|
||||||
|
|
||||||
|
@ -4719,72 +4679,6 @@ static HRESULT WINAPI IEnumSTATSTGImpl_Clone(
|
||||||
return S_OK;
|
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.
|
* Virtual function table for the IEnumSTATSTGImpl class.
|
||||||
*/
|
*/
|
||||||
|
@ -4828,14 +4722,6 @@ static IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(
|
||||||
|
|
||||||
newEnumeration->storageDirEntry = storageDirEntry;
|
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.
|
* Make sure the current node of the iterator is the first one.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -891,12 +891,10 @@ static void test_streamenum(void)
|
||||||
r = IStorage_DestroyElement(stg, stmname);
|
r = IStorage_DestroyElement(stg, stmname);
|
||||||
ok(r==S_OK, "IStorage->DestroyElement failed\n");
|
ok(r==S_OK, "IStorage->DestroyElement failed\n");
|
||||||
|
|
||||||
todo_wine {
|
|
||||||
count = 0xf00;
|
count = 0xf00;
|
||||||
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
||||||
ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
|
ok(r==S_FALSE, "IEnumSTATSTG->Next failed\n");
|
||||||
ok(count == 0, "count wrong\n");
|
ok(count == 0, "count wrong\n");
|
||||||
}
|
|
||||||
|
|
||||||
/* reset and try again */
|
/* reset and try again */
|
||||||
r = IEnumSTATSTG_Reset(ee);
|
r = IEnumSTATSTG_Reset(ee);
|
||||||
|
@ -918,8 +916,8 @@ static void test_streamenum(void)
|
||||||
|
|
||||||
count = 0xf00;
|
count = 0xf00;
|
||||||
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
||||||
todo_wine ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
|
ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
|
||||||
todo_wine ok(count == 1, "count wrong\n");
|
ok(count == 1, "count wrong\n");
|
||||||
|
|
||||||
if (r == S_OK)
|
if (r == S_OK)
|
||||||
{
|
{
|
||||||
|
@ -934,8 +932,8 @@ static void test_streamenum(void)
|
||||||
|
|
||||||
count = 0xf00;
|
count = 0xf00;
|
||||||
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
r = IEnumSTATSTG_Next(ee, 1, &stat, &count);
|
||||||
todo_wine ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
|
ok(r==S_OK, "IEnumSTATSTG->Next failed\n");
|
||||||
todo_wine ok(count == 1, "count wrong\n");
|
ok(count == 1, "count wrong\n");
|
||||||
|
|
||||||
if (r == S_OK)
|
if (r == S_OK)
|
||||||
{
|
{
|
||||||
|
@ -976,7 +974,7 @@ static void test_streamenum(void)
|
||||||
|
|
||||||
if (r == S_OK)
|
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);
|
CoTaskMemFree(stat.pwcsName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue