diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index aca36c1428e..45b672648c9 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -74,6 +74,26 @@ static RunningObjectTableImpl* runningObjectTableInstance = NULL; static HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl*,DWORD,IMoniker*,DWORD *); +/* define the EnumMonikerImpl structure */ +typedef struct EnumMonikerImpl{ + + IEnumMonikerVtbl *lpVtbl; + ULONG ref; + + RunObject* TabMoniker; /* pointer to the first object in the table */ + DWORD TabSize; /* current table size */ + DWORD TabLastIndx; /* last used index element in the table. */ + DWORD TabCurrentPos; /* enum position in the list */ + +} EnumMonikerImpl; + + +/* IEnumMoniker Local functions*/ +static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* runObjTab, + ULONG TabSize, + ULONG TabLastIndx, + ULONG TabCurrentPos, + IEnumMoniker ** ppenumMoniker); /*********************************************************************** * RunningObjectTable_QueryInterface */ @@ -401,8 +421,18 @@ static HRESULT WINAPI RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface, IEnumMoniker **ppenumMoniker) { - FIXME("(%p,%p) needs the IEnumMoniker implementation \n",iface,ppenumMoniker); - return E_NOTIMPL; + /* create the unique instance of the EnumMonkikerImpl structure + * and copy the Monikers referenced in the ROT so that they can be + * enumerated by the Enum interface + */ + HRESULT rc = 0; + RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface; + + rc=EnumMonikerImpl_CreateEnumROTMoniker(This->runObjTab, + This->runObjTabSize, + This->runObjTabLastIndx, 0, + ppenumMoniker); + return rc; } /*********************************************************************** @@ -570,3 +600,207 @@ HRESULT WINAPI RunningObjectTableImpl_UnInitialize() return S_OK; } + +/*********************************************************************** + * EnumMoniker_QueryInterface + */ +static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p,%p,%p)\n",This,riid,ppvObject); + + /* validate arguments */ + if (ppvObject == NULL) + return E_INVALIDARG; + + *ppvObject = NULL; + + if (IsEqualIID(&IID_IUnknown, riid)) + *ppvObject = (IEnumMoniker*)This; + else + if (IsEqualIID(&IID_IEnumMoniker, riid)) + *ppvObject = (IEnumMoniker*)This; + + if ((*ppvObject)==NULL) + return E_NOINTERFACE; + + IEnumMoniker_AddRef(iface); + + return S_OK; +} + +/*********************************************************************** + * EnumMoniker_AddRef + */ +static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + return InterlockedIncrement(&This->ref); +} + +/*********************************************************************** + * EnumMoniker_release + */ +static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface) +{ + DWORD i; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + ULONG ref; + + TRACE("(%p)\n",This); + + ref = InterlockedDecrement(&This->ref); + + /* unitialize rot structure if there's no more reference to it*/ + if (ref == 0) { + + /* release all registered objects in Moniker list */ + for(i=0; i < This->TabLastIndx ;i++) + { + IMoniker_Release(This->TabMoniker[i].pmkObj); + } + + /* there're no more elements in the table */ + + TRACE("(%p) Deleting\n",This); + HeapFree (GetProcessHeap(), 0, This->TabMoniker); /* free Moniker list */ + HeapFree (GetProcessHeap(), 0, This); /* free Enum Instance */ + + } + + return ref; +} +/*********************************************************************** + * EnmumMoniker_Next + */ +static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched) +{ + ULONG i; + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n",This, This->TabCurrentPos, This->TabLastIndx); + + /* retrieve the requested number of moniker from the current position */ + for(i=0; (This->TabCurrentPos < This->TabLastIndx) && (i < celt); i++) + rgelt[i]=(IMoniker*)This->TabMoniker[This->TabCurrentPos++].pmkObj; + + if (pceltFetched!=NULL) + *pceltFetched= i; + + if (i==celt) + return S_OK; + else + return S_FALSE; + +} + +/*********************************************************************** + * EnmumMoniker_Skip + */ +static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p)\n",This); + + if (This->TabCurrentPos+celt >= This->TabLastIndx) + return S_FALSE; + + This->TabCurrentPos+=celt; + + return S_OK; +} + +/*********************************************************************** + * EnmumMoniker_Reset + */ +static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + This->TabCurrentPos = 0; /* set back to start of list */ + + TRACE("(%p)\n",This); + + return S_OK; +} + +/*********************************************************************** + * EnmumMoniker_Clone + */ +static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum) +{ + EnumMonikerImpl *This = (EnumMonikerImpl *)iface; + + TRACE("(%p)\n",This); + /* copy the enum structure */ + return EnumMonikerImpl_CreateEnumROTMoniker(This->TabMoniker, This->TabSize, + This->TabLastIndx, This->TabCurrentPos, + ppenum); +} + +/* Virtual function table for the IEnumMoniker class. */ +static IEnumMonikerVtbl VT_EnumMonikerImpl = +{ + EnumMonikerImpl_QueryInterface, + EnumMonikerImpl_AddRef, + EnumMonikerImpl_Release, + EnumMonikerImpl_Next, + EnumMonikerImpl_Skip, + EnumMonikerImpl_Reset, + EnumMonikerImpl_Clone +}; + +/*********************************************************************** + * EnumMonikerImpl_CreateEnumROTMoniker + * Used by EnumRunning to create the structure and EnumClone + * to copy the structure + */ +HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker, + ULONG TabSize, + ULONG TabLastIndx, + ULONG TabCurrentPos, + IEnumMoniker ** ppenumMoniker) +{ + int i; + EnumMonikerImpl* This = NULL; + + if (TabCurrentPos > TabSize) + return E_INVALIDARG; + + if (ppenumMoniker == NULL) + return E_INVALIDARG; + + This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl)); + + if (!ppenumMoniker) return E_OUTOFMEMORY; + + TRACE("(%p)\n", This); + + /* initialize the virtual table function */ + This->lpVtbl = &VT_EnumMonikerImpl; + + /* the initial reference is set to "1" */ + This->ref = 1; /* set the ref count to one */ + This->TabCurrentPos=0; /* Set the list start posn to start */ + This->TabSize=TabSize; /* Need the same size table as ROT */ + This->TabLastIndx=TabLastIndx; /* end element */ + This->TabMoniker=HeapAlloc(GetProcessHeap(),0,This->TabSize*sizeof(RunObject)); + + if (This->TabMoniker==NULL) { + HeapFree(GetProcessHeap(), 0, This); + return E_OUTOFMEMORY; + } + for (i=0; i < This->TabLastIndx; i++){ + + This->TabMoniker[i]=TabMoniker[i]; + IMoniker_AddRef(TabMoniker[i].pmkObj); + } + + *ppenumMoniker = (IEnumMoniker*)This; + + return S_OK; +} diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 21302f673de..03f96d0bb3c 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -36,12 +36,32 @@ static void test_MkParseDisplayName() { IBindCtx * pbc = NULL; HRESULT hr; - IMoniker * pmk = NULL; + IMoniker * pmk = NULL; + IMoniker * pmk1 = NULL; + IMoniker * pmk2 = NULL; + IMoniker * ppmk = NULL; + IMoniker * spMoniker; ULONG eaten; + int monCnt; IUnknown * object = NULL; + + IUnknown *lpEM1; + + IEnumMoniker *spEM1 = NULL; + IEnumMoniker *spEM2 = NULL; + IEnumMoniker *spEM3 = NULL; + + DWORD pdwReg1=0; + DWORD grflags=0; + DWORD pdwReg2=0; + IRunningObjectTable * pprot=NULL; + /* CLSID of My Computer */ static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':', '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D',':',0}; + static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0}; + static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0}; + WCHAR * szDisplayn; hr = CreateBindCtx(0, &pbc); ok_ole_success(hr, CreateBindCtx); @@ -57,6 +77,103 @@ static void test_MkParseDisplayName() IUnknown_Release(object); } IBindCtx_Release(pbc); + + /* Test the EnumMoniker interface */ + hr = CreateBindCtx(0, &pbc); + ok_ole_success(hr, CreateBindCtx); + + hr = CreateFileMoniker(wszFileName1, &pmk1); + ok(hr==0, "CreateFileMoniker for file hr=%08lx\n", hr); + hr = CreateFileMoniker(wszFileName2, &pmk2); + ok(hr==0, "CreateFileMoniker for file hr=%08lx\n", hr); + hr = IBindCtx_GetRunningObjectTable(pbc, &pprot); + ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08lx\n", hr); + + /* Check EnumMoniker before registering */ + hr = IRunningObjectTable_EnumRunning(pprot, &spEM1); + ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08lx\n", hr); + hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1); + /* Register a couple of Monikers and check is ok */ + ok(hr==0, "IEnumMoniker_QueryInterface hr %08lx %p\n", hr, lpEM1); + hr = MK_E_NOOBJECT; + monCnt = 0; + while ((IEnumMoniker_Next(spEM1, 1, &spMoniker, NULL)==S_OK) && + (ppmk ==NULL)) + { + monCnt++; + szDisplayn=NULL; + hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, + (LPOLESTR*) &szDisplayn); + /* szDisplayn needs to be freed by + * IMalloc_Free hence the use of + * CoGetMalloc */ + if (SUCCEEDED(hr)) + { + CoTaskMemFree(szDisplayn); + } + } + ok(monCnt==0, "Number of monikers should be equal to 0 not %i\n", monCnt); grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE; + hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1); + ok(hr==0, "IRunningObjectTable_Register hr=%08lx %p %08lx %p %p %ld\n", + hr, pprot, grflags, lpEM1, pmk1, pdwReg1); + + grflags=0; + grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE; + hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2); + ok(hr==0, "IRunningObjectTable_Register hr=%08lx %p %08lx %p %p %ld\n", hr, + pprot, grflags, lpEM1, pmk2, pdwReg2); + + hr = IRunningObjectTable_EnumRunning(pprot, &spEM2); + ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08lx\n", hr); + + monCnt=0; + while ((IEnumMoniker_Next(spEM2, 1, &spMoniker, NULL)==S_OK) && + (ppmk ==NULL)) + { + WCHAR *szDisplayn=NULL; + monCnt++; + hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, + (LPOLESTR*) &szDisplayn); + /* szDisplayn needs to be freed by + * IMalloc_Free hence the use of + * CoGetMalloc */ + if (SUCCEEDED(hr)) + { + CoTaskMemFree(szDisplayn); + } + } + ok(monCnt==2, "Number of monikers should be equal to 2 not %i\n", monCnt); + + IEnumMoniker_Clone(spEM2, &spEM3); + monCnt=0; + while ((IEnumMoniker_Next(spEM3, 1, &spMoniker, NULL)==S_OK) && + (ppmk ==NULL)) + { + WCHAR *szDisplayn=NULL; + monCnt++; + hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, + (LPOLESTR*) &szDisplayn); + /* szDisplayn needs to be freed by + * IMalloc_Free hence the use of + * CoGetMalloc */ + if (SUCCEEDED(hr)) + { + CoTaskMemFree(szDisplayn); + } + } + ok(monCnt==2, "Number of monikers should be equal to 2 not %i\n", monCnt); + IRunningObjectTable_Revoke(pprot,pdwReg1); + IRunningObjectTable_Revoke(pprot,pdwReg2); + IEnumMoniker_Release(spEM1); + IEnumMoniker_Release(spEM1); + IEnumMoniker_Release(spEM2); + IEnumMoniker_Release(spEM3); + IMoniker_Release(pmk1); + IMoniker_Release(pmk2); + IRunningObjectTable_Release(pprot); + + IBindCtx_Release(pbc); + /* Finished testing EnumMoniker */ } static const BYTE expected_moniker_data[] =