Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2021
- 83 participants
- 2758 messages
Re: RFC: Reparse Point/NT Symlink Support [3]
by Alexandre Julliard
"Erich E. Hoover" <erich.e.hoover(a)gmail.com> writes:
> If this doesn't sound too crazy then I can put together the
> modifications to make this happen. As part of that I'd like to
> introduce a tool (command 'wineprefix'?) that configures the Unix
> environment properly for Linux/BSD to allow the shell to function with
> this variadic symlink so that users like Martin Storsjö (and myself)
> can just run the tool to be dropped into a shell where ${WINEPREFIX}
> inside a symlink will be treated appropriately. (Part of why it's
> taken me a while to respond to this thread has been putting together a
> "proof of concept" of this tool to make sure that the idea works,
> which I can now confirm.) Please let me know what you guys think,
> hopefully this sounds better to folks.
You are still trying too hard to shoehorn the complexity of reparse
points into working Unix symlinks, which makes it necessary to depend on
all kinds of exotic non-portable functionality.
You should forget about making these transparent at the Unix
level. Focus on implementing the full semantics of reparse points,
including arbitrary tags and data, in a generic, easily extendable way,
using only standard Posix APIs.
Once you have this working for a range of different tags, with tests to
confirm compatibility, we can think about what subset of reparse points
would make sense as pure Unix symlinks, and add a special case for
these.
--
Alexandre Julliard
julliard(a)winehq.org
Sept. 30, 2021
[PATCH 5/5] ole32: Use public function to get file extension in GetClassFile().
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/Makefile.in | 2 +-
dlls/ole32/filemoniker.c | 161 +++++++++++++++++++--------------------
dlls/ole32/moniker.c | 31 ++------
dlls/ole32/moniker.h | 3 -
4 files changed, 85 insertions(+), 112 deletions(-)
diff --git a/dlls/ole32/Makefile.in b/dlls/ole32/Makefile.in
index 84694e1538d..340ffdbded2 100644
--- a/dlls/ole32/Makefile.in
+++ b/dlls/ole32/Makefile.in
@@ -1,6 +1,6 @@
MODULE = ole32.dll
IMPORTLIB = ole32
-IMPORTS = uuid advapi32 user32 gdi32 combase rpcrt4
+IMPORTS = uuid advapi32 user32 gdi32 combase rpcrt4 kernelbase
DELAYIMPORTS = oleaut32
EXTRADEFS = -D_OLE32_
diff --git a/dlls/ole32/filemoniker.c b/dlls/ole32/filemoniker.c
index 213971ea96b..794b4507942 100644
--- a/dlls/ole32/filemoniker.c
+++ b/dlls/ole32/filemoniker.c
@@ -631,6 +631,85 @@ static void free_stringtable(LPOLESTR *stringTable)
CoTaskMemFree(stringTable);
}
+static int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
+{
+ LPOLESTR word;
+ int i=0,j,tabIndex=0, ret=0;
+ LPOLESTR *strgtable ;
+
+ int len=lstrlenW(str);
+
+ TRACE("%s, %p\n", debugstr_w(str), *stringTable);
+
+ strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
+
+ if (strgtable==NULL)
+ return E_OUTOFMEMORY;
+
+ word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
+
+ if (word==NULL)
+ {
+ ret = E_OUTOFMEMORY;
+ goto lend;
+ }
+
+ while(str[i]!=0){
+
+ if (str[i] == L'\\')
+ {
+
+ strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
+
+ if (strgtable[tabIndex]==NULL)
+ {
+ ret = E_OUTOFMEMORY;
+ goto lend;
+ }
+
+ lstrcpyW(strgtable[tabIndex++], L"\\");
+
+ i++;
+
+ }
+ else {
+
+ for (j = 0; str[i] && str[i] != L'\\'; i++, j++)
+ word[j]=str[i];
+
+ word[j]=0;
+
+ strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
+
+ if (strgtable[tabIndex]==NULL)
+ {
+ ret = E_OUTOFMEMORY;
+ goto lend;
+ }
+
+ lstrcpyW(strgtable[tabIndex++],word);
+ }
+ }
+ strgtable[tabIndex]=NULL;
+
+ *stringTable=strgtable;
+
+ ret = tabIndex;
+
+lend:
+ if (ret < 0)
+ {
+ for (i = 0; i < tabIndex; i++)
+ CoTaskMemFree(strgtable[i]);
+
+ CoTaskMemFree(strgtable);
+ }
+
+ CoTaskMemFree(word);
+
+ return ret;
+}
+
/******************************************************************************
* FileMoniker_ComposeWith
*/
@@ -970,88 +1049,6 @@ failed:
return ret;
}
-/******************************************************************************
- * DecomposePath (local function)
- */
-int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable)
-{
- LPOLESTR word;
- int i=0,j,tabIndex=0, ret=0;
- LPOLESTR *strgtable ;
-
- int len=lstrlenW(str);
-
- TRACE("%s, %p\n", debugstr_w(str), *stringTable);
-
- strgtable = CoTaskMemAlloc((len + 1)*sizeof(*strgtable));
-
- if (strgtable==NULL)
- return E_OUTOFMEMORY;
-
- word = CoTaskMemAlloc((len + 1)*sizeof(WCHAR));
-
- if (word==NULL)
- {
- ret = E_OUTOFMEMORY;
- goto lend;
- }
-
- while(str[i]!=0){
-
- if (str[i] == L'\\')
- {
-
- strgtable[tabIndex]=CoTaskMemAlloc(2*sizeof(WCHAR));
-
- if (strgtable[tabIndex]==NULL)
- {
- ret = E_OUTOFMEMORY;
- goto lend;
- }
-
- lstrcpyW(strgtable[tabIndex++], L"\\");
-
- i++;
-
- }
- else {
-
- for (j = 0; str[i] && str[i] != L'\\'; i++, j++)
- word[j]=str[i];
-
- word[j]=0;
-
- strgtable[tabIndex]=CoTaskMemAlloc(sizeof(WCHAR)*(j+1));
-
- if (strgtable[tabIndex]==NULL)
- {
- ret = E_OUTOFMEMORY;
- goto lend;
- }
-
- lstrcpyW(strgtable[tabIndex++],word);
- }
- }
- strgtable[tabIndex]=NULL;
-
- *stringTable=strgtable;
-
- ret = tabIndex;
-
-lend:
- if (ret < 0)
- {
- for (i = 0; i < tabIndex; i++)
- CoTaskMemFree(strgtable[i]);
-
- CoTaskMemFree(strgtable);
- }
-
- CoTaskMemFree(word);
-
- return ret;
-}
-
/******************************************************************************
* FileMoniker_RelativePathTo
*/
diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c
index aed491d406f..ac47f5528c8 100644
--- a/dlls/ole32/moniker.c
+++ b/dlls/ole32/moniker.c
@@ -32,6 +32,7 @@
#include "compobj_private.h"
#include "moniker.h"
#include "irot.h"
+#include "pathcch.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -910,10 +911,9 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
{
IStorage *pstg=0;
HRESULT res;
- int nbElm, length, i;
LONG sizeProgId, ret;
- LPOLESTR *pathDec=0,absFile=0,progId=0;
- LPWSTR extension;
+ LPOLESTR progId=0;
+ const WCHAR *extension;
TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
@@ -954,26 +954,9 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
/* if the above strategies fail then search for the extension key in the registry */
- /* get the last element (absolute file) in the path name */
- nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
- absFile=pathDec[nbElm-1];
-
- /* failed if the path represents a directory and not an absolute file name*/
- if (!wcscmp(absFile, L"\\")) {
- CoTaskMemFree(pathDec);
+ res = PathCchFindExtension(filePathName, PATHCCH_MAX_CCH, &extension);
+ if (FAILED(res) || !extension || !*extension || !wcscmp(extension, L"."))
return MK_E_INVALIDEXTENSION;
- }
-
- /* get the extension of the file */
- extension = NULL;
- length=lstrlenW(absFile);
- for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--)
- /* nothing */;
-
- if (!extension || !wcscmp(extension, L".")) {
- CoTaskMemFree(pathDec);
- return MK_E_INVALIDEXTENSION;
- }
ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
if (!ret) {
@@ -990,10 +973,6 @@ HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
else
res = HRESULT_FROM_WIN32(ret);
- for(i=0; pathDec[i]!=NULL;i++)
- CoTaskMemFree(pathDec[i]);
- CoTaskMemFree(pathDec);
-
return res != S_OK ? MK_E_INVALIDEXTENSION : res;
}
diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h
index 995e0459e5e..8549bd46c1e 100644
--- a/dlls/ole32/moniker.h
+++ b/dlls/ole32/moniker.h
@@ -38,9 +38,6 @@ HRESULT WINAPI ClassMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk,
HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI ComCat_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
-/* This function decomposes a String path to a String Table containing all the elements ("\" or "subDirectory" or "Directory" or "FileName") of the path */
-int FileMonikerImpl_DecomposePath(LPCOLESTR str, LPOLESTR** stringTable) DECLSPEC_HIDDEN;
-
HRESULT FileMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
LPDWORD pchEaten, LPMONIKER *ppmk) DECLSPEC_HIDDEN;
HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
--
2.33.0
Sept. 30, 2021
[PATCH 4/5] ole32/composite: Cleanup enumerator methods.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/compositemoniker.c | 137 +++++++++++++---------------------
1 file changed, 52 insertions(+), 85 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index 652962e1a87..a94e4734f45 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -72,13 +72,13 @@ static inline CompositeMonikerImpl *impl_from_IMarshal(IMarshal *iface)
return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMarshal_iface);
}
-/* EnumMoniker data structure */
-typedef struct EnumMonikerImpl{
+typedef struct EnumMonikerImpl
+{
IEnumMoniker IEnumMoniker_iface;
LONG ref;
- IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
- ULONG tabSize; /* size of tabMoniker */
- ULONG currentPos; /* index pointer on the current moniker */
+ IMoniker **monikers;
+ unsigned int count;
+ unsigned int pos;
} EnumMonikerImpl;
static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
@@ -86,7 +86,7 @@ static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
}
-static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRight,IEnumMoniker ** ppmk);
+static HRESULT create_enumerator(IMoniker **components, unsigned int count, BOOL forward, IEnumMoniker **ret);
static HRESULT composite_get_rightmost(CompositeMonikerImpl *composite, IMoniker **left, IMoniker **rightmost);
static HRESULT composite_get_leftmost(CompositeMonikerImpl *composite, IMoniker **leftmost);
@@ -492,21 +492,21 @@ static HRESULT composite_get_components_alloc(IMoniker *iface, unsigned int *cou
return S_OK;
}
-static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **ppenumMoniker)
+static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **ret_enum)
{
IMoniker **monikers;
unsigned int count;
HRESULT hr;
- TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
+ TRACE("%p, %d, %p\n", iface, forward, ret_enum);
- if (!ppenumMoniker)
+ if (!ret_enum)
return E_INVALIDARG;
if (FAILED(hr = composite_get_components_alloc(iface, &count, &monikers)))
return hr;
- hr = EnumMonikerImpl_CreateEnumMoniker(monikers, count, 0, forward, ppenumMoniker);
+ hr = create_enumerator(monikers, count, forward, ret_enum);
heap_free(monikers);
return hr;
@@ -1280,36 +1280,30 @@ EnumMonikerImpl_AddRef(IEnumMoniker* iface)
}
-/******************************************************************************
- * EnumMonikerImpl_Release
- ******************************************************************************/
-static ULONG WINAPI
-EnumMonikerImpl_Release(IEnumMoniker* iface)
+static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker *iface)
{
- EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
- ULONG i;
- ULONG ref;
- TRACE("(%p)\n",This);
-
- ref = InterlockedDecrement(&This->ref);
-
- /* destroy the object if there are no more references to it */
- if (ref == 0) {
+ EnumMonikerImpl *e = impl_from_IEnumMoniker(iface);
+ ULONG refcount = InterlockedDecrement(&e->ref);
+ unsigned int i;
- for(i=0;i<This->tabSize;i++)
- IMoniker_Release(This->tabMoniker[i]);
+ TRACE("%p, refcount %d.\n", iface, refcount);
- HeapFree(GetProcessHeap(),0,This->tabMoniker);
- HeapFree(GetProcessHeap(),0,This);
+ if (!refcount)
+ {
+ for (i = 0; i < e->count; ++i)
+ IMoniker_Release(e->monikers[i]);
+ heap_free(e->monikers);
+ heap_free(e);
}
- return ref;
+
+ return refcount;
}
static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker *iface, ULONG count,
IMoniker **m, ULONG *fetched)
{
- EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
- ULONG i;
+ EnumMonikerImpl *e = impl_from_IEnumMoniker(iface);
+ unsigned int i;
TRACE("%p, %u, %p, %p.\n", iface, count, m, fetched);
@@ -1319,9 +1313,9 @@ static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker *iface, ULONG count,
*m = NULL;
/* retrieve the requested number of moniker from the current position */
- for(i=0;((This->currentPos < This->tabSize) && (i < count));i++)
+ for (i = 0; (e->pos < e->count) && (i < count); ++i)
{
- m[i] = This->tabMoniker[This->currentPos++];
+ m[i] = e->monikers[e->pos++];
IMoniker_AddRef(m[i]);
}
@@ -1333,30 +1327,28 @@ static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker *iface, ULONG count,
static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker *iface, ULONG count)
{
- EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
+ EnumMonikerImpl *e = impl_from_IEnumMoniker(iface);
TRACE("%p, %u.\n", iface, count);
if (!count)
return S_OK;
- if ((This->currentPos + count) >= This->tabSize)
+ if ((e->pos + count) >= e->count)
return S_FALSE;
- This->currentPos += count;
+ e->pos += count;
return S_OK;
}
-/******************************************************************************
- * EnumMonikerImpl_Reset
- ******************************************************************************/
-static HRESULT WINAPI
-EnumMonikerImpl_Reset(IEnumMoniker* iface)
+static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
{
- EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
+ EnumMonikerImpl *e = impl_from_IEnumMoniker(iface);
- This->currentPos=0;
+ TRACE("%p.\n", iface);
+
+ e->pos = 0;
return S_OK;
}
@@ -1384,60 +1376,35 @@ static const IEnumMonikerVtbl VT_EnumMonikerImpl =
EnumMonikerImpl_Clone
};
-/******************************************************************************
- * EnumMonikerImpl_CreateEnumMoniker
- ******************************************************************************/
-static HRESULT
-EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
- ULONG currentPos, BOOL leftToRight, IEnumMoniker ** ppmk)
+static HRESULT create_enumerator(IMoniker **components, unsigned int count, BOOL forward, IEnumMoniker **ret)
{
- EnumMonikerImpl* newEnumMoniker;
- ULONG i;
-
- if (currentPos > tabSize)
- return E_INVALIDARG;
-
- newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
-
- if (newEnumMoniker == 0)
- return STG_E_INSUFFICIENTMEMORY;
-
- /* Initialize the virtual function table. */
- newEnumMoniker->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
- newEnumMoniker->ref = 1;
+ EnumMonikerImpl *object;
+ unsigned int i;
- newEnumMoniker->tabSize=tabSize;
- newEnumMoniker->currentPos=currentPos;
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
- newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(newEnumMoniker->tabMoniker[0]));
+ object->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
+ object->ref = 1;
+ object->count = count;
- if (newEnumMoniker->tabMoniker==NULL) {
- HeapFree(GetProcessHeap(), 0, newEnumMoniker);
+ if (!(object->monikers = heap_calloc(count, sizeof(*object->monikers))))
+ {
+ heap_free(object);
return E_OUTOFMEMORY;
}
- if (leftToRight)
- for (i=0;i<tabSize;i++){
-
- newEnumMoniker->tabMoniker[i]=tabMoniker[i];
- IMoniker_AddRef(tabMoniker[i]);
- }
- else
- for (i = tabSize; i > 0; i--){
-
- newEnumMoniker->tabMoniker[tabSize-i]=tabMoniker[i - 1];
- IMoniker_AddRef(tabMoniker[i - 1]);
- }
+ for (i = 0; i < count; ++i)
+ {
+ object->monikers[i] = forward ? components[i] : components[count - i - 1];
+ IMoniker_AddRef(object->monikers[i]);
+ }
- *ppmk=&newEnumMoniker->IEnumMoniker_iface;
+ *ret = &object->IEnumMoniker_iface;
return S_OK;
}
-/********************************************************************************/
-/* Virtual function table for the CompositeMonikerImpl class which includes */
-/* IPersist, IPersistStream and IMoniker functions. */
-
static const IMonikerVtbl VT_CompositeMonikerImpl =
{
CompositeMonikerImpl_QueryInterface,
--
2.33.0
Sept. 30, 2021
[PATCH 3/5] ole32/composite: Disable cloning of enumerator instances.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/compositemoniker.c | 6 +++---
dlls/ole32/tests/moniker.c | 12 ++++--------
2 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index cde3f1762f0..652962e1a87 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -1363,14 +1363,14 @@ EnumMonikerImpl_Reset(IEnumMoniker* iface)
static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker *iface, IEnumMoniker **ret)
{
- EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
-
TRACE("%p, %p.\n", iface, ret);
if (!ret)
return E_INVALIDARG;
- return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ret);
+ *ret = NULL;
+
+ return E_NOTIMPL;
}
static const IEnumMonikerVtbl VT_EnumMonikerImpl =
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index a60472951f7..abd17c9961f 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -3699,10 +3699,9 @@ todo_wine {
enummoniker2 = (void *)0xdeadbeef;
hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
-todo_wine {
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
ok(!enummoniker2, "Unexpected pointer.\n");
-}
+
hr = IEnumMoniker_Reset(enummoniker);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -3718,10 +3717,9 @@ todo_wine {
enummoniker2 = (void *)0xdeadbeef;
hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
-todo_wine {
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
ok(!enummoniker2, "Unexpected pointer.\n");
-}
+
IEnumMoniker_Release(enummoniker);
/* Backward direction */
@@ -3783,10 +3781,9 @@ todo_wine {
enummoniker2 = (void *)0xdeadbeef;
hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
-todo_wine {
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
ok(!enummoniker2, "Unexpected pointer.\n");
-}
+
hr = IEnumMoniker_Reset(enummoniker);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
@@ -3802,10 +3799,9 @@ todo_wine {
enummoniker2 = (void *)0xdeadbeef;
hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
-todo_wine {
ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
ok(!enummoniker2, "Unexpected pointer.\n");
-}
+
IEnumMoniker_Release(enummoniker);
IMoniker_Release(moniker);
--
2.33.0
Sept. 30, 2021
[PATCH 2/5] ole32/composite: Do not use enumerators and antimoniker composition in RelativePathTo().
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/compositemoniker.c | 233 ++++++++++++++--------------------
dlls/ole32/tests/moniker.c | 12 ++
2 files changed, 108 insertions(+), 137 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index e5437c8880f..cde3f1762f0 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -473,23 +473,29 @@ static void composite_get_components(IMoniker *moniker, IMoniker **components, u
}
}
-static HRESULT composite_get_components_alloc(CompositeMonikerImpl *moniker, IMoniker ***components)
+static HRESULT composite_get_components_alloc(IMoniker *iface, unsigned int *count, IMoniker ***components)
{
+ CompositeMonikerImpl *moniker;
unsigned int index;
- if (!(*components = heap_alloc(moniker->comp_count * sizeof(**components))))
+ if ((moniker = unsafe_impl_from_IMoniker(iface)))
+ *count = moniker->comp_count;
+ else
+ *count = 1;
+
+ if (!(*components = heap_alloc(*count * sizeof(**components))))
return E_OUTOFMEMORY;
index = 0;
- composite_get_components(&moniker->IMoniker_iface, *components, &index);
+ composite_get_components(iface, *components, &index);
return S_OK;
}
static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **ppenumMoniker)
{
- CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
IMoniker **monikers;
+ unsigned int count;
HRESULT hr;
TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
@@ -497,10 +503,10 @@ static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, I
if (!ppenumMoniker)
return E_INVALIDARG;
- if (FAILED(hr = composite_get_components_alloc(moniker, &monikers)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &monikers)))
return hr;
- hr = EnumMonikerImpl_CreateEnumMoniker(monikers, moniker->comp_count, 0, forward, ppenumMoniker);
+ hr = EnumMonikerImpl_CreateEnumMoniker(monikers, count, 0, forward, ppenumMoniker);
heap_free(monikers);
return hr;
@@ -510,7 +516,7 @@ static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker *iface, IMoniker *ot
{
CompositeMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
IMoniker **components, **other_components;
- unsigned int i;
+ unsigned int i, count;
HRESULT hr;
TRACE("%p, %p.\n", iface, other);
@@ -524,8 +530,8 @@ static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker *iface, IMoniker *ot
if (moniker->comp_count != other_moniker->comp_count)
return S_FALSE;
- if (FAILED(hr = composite_get_components_alloc(moniker, &components))) return hr;
- if (FAILED(hr = composite_get_components_alloc(other_moniker, &other_components)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &count, &other_components)))
{
heap_free(components);
return hr;
@@ -715,8 +721,8 @@ static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMo
IMoniker **components, **other_components, **prefix_components;
IMoniker *last, *c;
- if (FAILED(hr = composite_get_components_alloc(moniker, &components))) return hr;
- if (FAILED(hr = composite_get_components_alloc(other_moniker, &other_components)))
+ if (FAILED(hr = composite_get_components_alloc(iface, &count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &count, &other_components)))
{
heap_free(components);
return hr;
@@ -788,156 +794,109 @@ static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker *iface, IMo
return hr;
}
-/***************************************************************************************************
- * GetAfterCommonPrefix (local function)
- * This function returns a moniker that consist of the remainder when the common prefix is removed
- ***************************************************************************************************/
-static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
+static HRESULT composite_compose_components(IMoniker **comp, unsigned int count, IMoniker **ret)
{
- IMoniker *tempMk,*tempMk1,*tempMk2;
- IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
- ULONG nbRestMk=0;
- DWORD mkSys;
- HRESULT res1,res2;
-
- *restMk=0;
-
- /* to create an enumerator for pGenMk with current position pointed on the first element after common */
- /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
- /* on the first difference. */
- IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
-
- IMoniker_IsSystemMoniker(commonMk,&mkSys);
-
- if (mkSys==MKSYS_GENERICCOMPOSITE){
-
- IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
- while(1){
-
- res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
- res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
-
- if ((res1==S_FALSE)||(res2==S_FALSE)){
-
- if (res1==S_OK)
-
- nbRestMk++;
+ IMoniker *last, *c;
+ HRESULT hr = S_OK;
+ unsigned int i;
- IMoniker_Release(tempMk1);
- IMoniker_Release(tempMk2);
+ last = comp[0];
+ IMoniker_AddRef(last);
- break;
- }
- IMoniker_Release(tempMk1);
- IMoniker_Release(tempMk2);
- }
- }
- else{
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
- IMoniker_Release(tempMk1);
+ for (i = 1; i < count; ++i)
+ {
+ hr = CreateGenericComposite(last, comp[i], &c);
+ IMoniker_Release(last);
+ if (FAILED(hr)) break;
+ last = c;
}
- /* count the number of elements in the enumerator after the common prefix */
- IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
+ *ret = SUCCEEDED(hr) ? last : NULL;
- for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
+ return hr;
+}
- IMoniker_Release(tempMk);
+static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *other,
+ IMoniker **relpath)
+{
+ unsigned int count, this_count, other_count, prefix_len = 0;
+ IMoniker *inv, *tail = NULL, *other_tail = NULL, *rel = NULL;
+ IMoniker **components, **other_components;
+ unsigned int start = 0, other_start = 0;
+ HRESULT hr;
- if (nbRestMk==0)
- return;
+ TRACE("%p, %p, %p.\n", iface, other, relpath);
- /* create a generic composite moniker with monikers located after the common prefix */
- IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
+ if (!relpath)
+ return E_INVALIDARG;
- if (nbRestMk==1){
+ *relpath = NULL;
- *restMk= tempMk1;
- return;
+ if (FAILED(hr = composite_get_components_alloc(iface, &this_count, &components))) return hr;
+ if (FAILED(hr = composite_get_components_alloc(other, &other_count, &other_components)))
+ {
+ heap_free(components);
+ return hr;
}
- else {
-
- IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
-
- CreateGenericComposite(tempMk1,tempMk2,restMk);
- IMoniker_Release(tempMk1);
-
- IMoniker_Release(tempMk2);
-
- while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
-
- CreateGenericComposite(*restMk,tempMk1,&tempMk2);
+ /* Skip common prefix of equal components */
+ count = min(other_count, this_count);
+ while (IMoniker_IsEqual(components[prefix_len], other_components[prefix_len]) == S_OK)
+ {
+ if (++prefix_len == count) break;
+ }
- IMoniker_Release(tempMk1);
+ if (prefix_len)
+ {
+ this_count -= prefix_len;
+ other_count -= prefix_len;
+ other_start += prefix_len;
+ start += prefix_len;
+ }
+ else
+ {
+ /* Replace first component of the other tail with relative path */
+ if (SUCCEEDED(hr = IMoniker_RelativePathTo(*components, *other_components, &rel)))
+ *other_components = rel;
- IMoniker_Release(*restMk);
+ this_count--;
+ start++;
+ }
- *restMk=tempMk2;
+ /* Invert left side tail */
+ if (this_count && SUCCEEDED(hr))
+ {
+ if (SUCCEEDED(hr = composite_compose_components(&components[start], this_count, &tail)))
+ {
+ hr = IMoniker_Inverse(tail, &inv);
+ IMoniker_Release(tail);
+ tail = inv;
}
}
-}
-
-/******************************************************************************
- * CompositeMoniker_RelativePathTo
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
- IMoniker** ppmkRelPath)
-{
- HRESULT res;
- IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
-
- TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
-
- if (ppmkRelPath==NULL)
- return E_POINTER;
-
- *ppmkRelPath=0;
- /* This method finds the common prefix of the two monikers and creates two monikers that consist */
- /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
- /* of this moniker and composes the remainder of the other moniker on the right of it. */
+ if (other_count && SUCCEEDED(hr))
+ hr = composite_compose_components(&other_components[other_start], other_count, &other_tail);
- /* finds the common prefix of the two monikers */
- res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
-
- /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
- if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
-
- *ppmkRelPath=pmkOther;
- IMoniker_AddRef(pmkOther);
- return MK_S_HIM;
+ if (tail || other_tail)
+ hr = CreateGenericComposite(tail, other_tail, relpath);
+ else if (SUCCEEDED(hr))
+ {
+ *relpath = other;
+ IMoniker_AddRef(*relpath);
+ hr = MK_S_HIM;
}
- GetAfterCommonPrefix(iface,commonMk,&restThisMk);
- GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
-
- /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
- /* moniker when the common prefix is removed */
- if (res==MK_S_HIM){
+ if (rel)
+ IMoniker_Release(rel);
+ if (tail)
+ IMoniker_Release(tail);
+ if (other_tail)
+ IMoniker_Release(other_tail);
- IMoniker_Inverse(restThisMk,ppmkRelPath);
- IMoniker_Release(restThisMk);
- }
- /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
- /* when the common prefix is removed */
- else if (res==MK_S_ME){
-
- *ppmkRelPath=restOtherMk;
- IMoniker_AddRef(restOtherMk);
- }
- /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
- /* moniker on the right of it. */
- else if (res==S_OK){
+ heap_free(other_components);
+ heap_free(components);
- IMoniker_Inverse(restThisMk,&invRestThisMk);
- IMoniker_Release(restThisMk);
- CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
- IMoniker_Release(invRestThisMk);
- IMoniker_Release(restOtherMk);
- }
- return S_OK;
+ return hr;
}
static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index ed2accff6a9..a60472951f7 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -3810,6 +3810,18 @@ todo_wine {
IMoniker_Release(moniker);
+ /* RelativePathTo() */
+ hr = create_moniker_from_desc("CI1I2", &moniker1);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = create_moniker_from_desc("CI2I3", &moniker2);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_RelativePathTo(moniker1, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+ hr = IMoniker_RelativePathTo(moniker1, moniker2, &moniker3);
+ ok(hr == MK_E_NOTBINDABLE, "Unexpected hr %#x.\n", hr);
+
IBindCtx_Release(bindctx);
}
--
2.33.0
Sept. 30, 2021
[PATCH 1/5] ole32/composite: Fix argument handling in component enumerator methods.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/ole32/compositemoniker.c | 60 ++++++-----
dlls/ole32/tests/moniker.c | 192 +++++++++++++++++++++++++++++++---
2 files changed, 209 insertions(+), 43 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index 80a1a675766..e5437c8880f 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -495,7 +495,7 @@ static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, I
TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
if (!ppenumMoniker)
- return E_POINTER;
+ return E_INVALIDARG;
if (FAILED(hr = composite_get_components_alloc(moniker, &monikers)))
return hr;
@@ -1346,44 +1346,45 @@ EnumMonikerImpl_Release(IEnumMoniker* iface)
return ref;
}
-/******************************************************************************
- * EnumMonikerImpl_Next
- ******************************************************************************/
-static HRESULT WINAPI
-EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
- ULONG* pceltFethed)
+static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker *iface, ULONG count,
+ IMoniker **m, ULONG *fetched)
{
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
ULONG i;
+ TRACE("%p, %u, %p, %p.\n", iface, count, m, fetched);
+
+ if (!m)
+ return E_INVALIDARG;
+
+ *m = NULL;
+
/* retrieve the requested number of moniker from the current position */
- for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
+ for(i=0;((This->currentPos < This->tabSize) && (i < count));i++)
{
- rgelt[i]=This->tabMoniker[This->currentPos++];
- IMoniker_AddRef(rgelt[i]);
+ m[i] = This->tabMoniker[This->currentPos++];
+ IMoniker_AddRef(m[i]);
}
- if (pceltFethed!=NULL)
- *pceltFethed= i;
+ if (fetched)
+ *fetched = i;
- if (i==celt)
- return S_OK;
- else
- return S_FALSE;
+ return i == count ? S_OK : S_FALSE;
}
-/******************************************************************************
- * EnumMonikerImpl_Skip
- ******************************************************************************/
-static HRESULT WINAPI
-EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
+static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker *iface, ULONG count)
{
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
- if ((This->currentPos+celt) >= This->tabSize)
+ TRACE("%p, %u.\n", iface, count);
+
+ if (!count)
+ return S_OK;
+
+ if ((This->currentPos + count) >= This->tabSize)
return S_FALSE;
- This->currentPos+=celt;
+ This->currentPos += count;
return S_OK;
}
@@ -1401,15 +1402,16 @@ EnumMonikerImpl_Reset(IEnumMoniker* iface)
return S_OK;
}
-/******************************************************************************
- * EnumMonikerImpl_Clone
- ******************************************************************************/
-static HRESULT WINAPI
-EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
+static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker *iface, IEnumMoniker **ret)
{
EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
- return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
+ TRACE("%p, %p.\n", iface, ret);
+
+ if (!ret)
+ return E_INVALIDARG;
+
+ return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ret);
}
static const IEnumMonikerVtbl VT_EnumMonikerImpl =
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index 7e4a42a0ee6..ed2accff6a9 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -3163,8 +3163,8 @@ static void test_generic_composite_moniker(void)
{ "CI1I3", "CA1I2", MKSYS_GENERICCOMPOSITE, L"!I1!I2" },
};
IMoniker *moniker, *inverse, *moniker1, *moniker2, *moniker3, *moniker4;
+ IEnumMoniker *enummoniker, *enummoniker2;
struct test_moniker *m, *m2;
- IEnumMoniker *enummoniker;
IRunningObjectTable *rot;
DWORD hash, cookie;
HRESULT hr;
@@ -3293,19 +3293,6 @@ todo_wine
TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE);
IMoniker_Release(inverse);
- /* Enum() */
- hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
- ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
- IEnumMoniker_Release(enummoniker);
-
- hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
- ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
- IEnumMoniker_Release(enummoniker);
-
- hr = IMoniker_Enum(moniker, FALSE, NULL);
-todo_wine
- ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
-
/* BindToObject() */
hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
@@ -3646,6 +3633,183 @@ todo_wine {
IMoniker_Release(moniker);
+ /* Enum() */
+ hr = create_moniker_from_desc("CI1CI2I3", &moniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_Enum(moniker, FALSE, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ /* Forward direction */
+ hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Next(enummoniker, 0, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ moniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Next(enummoniker, 0, &moniker2, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!moniker2, "Unexpected pointer.\n");
+
+ len = 1;
+ moniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Next(enummoniker, 0, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!len, "Unexpected count %u.\n", len);
+ ok(!moniker2, "Unexpected pointer.\n");
+
+ hr = IEnumMoniker_Skip(enummoniker, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I1");
+ IMoniker_Release(moniker2);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I2");
+ IMoniker_Release(moniker2);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I3");
+ IMoniker_Release(moniker2);
+
+ len = 1;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(!len, "Unexpected count %u.\n", len);
+
+ hr = IEnumMoniker_Skip(enummoniker, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Skip(enummoniker, 1);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Clone(enummoniker, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ enummoniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
+todo_wine {
+ ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+ ok(!enummoniker2, "Unexpected pointer.\n");
+}
+ hr = IEnumMoniker_Reset(enummoniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Skip(enummoniker, 2);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I3");
+ IMoniker_Release(moniker2);
+
+ enummoniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
+todo_wine {
+ ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+ ok(!enummoniker2, "Unexpected pointer.\n");
+}
+ IEnumMoniker_Release(enummoniker);
+
+ /* Backward direction */
+ hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
+ ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Next(enummoniker, 0, NULL, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ moniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Next(enummoniker, 0, &moniker2, NULL);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!moniker2, "Unexpected pointer.\n");
+
+ len = 1;
+ moniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Next(enummoniker, 0, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(!len, "Unexpected count %u.\n", len);
+ ok(!moniker2, "Unexpected pointer.\n");
+
+ hr = IEnumMoniker_Skip(enummoniker, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I3");
+ IMoniker_Release(moniker2);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I2");
+ IMoniker_Release(moniker2);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I1");
+ IMoniker_Release(moniker2);
+
+ len = 1;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+ ok(!len, "Unexpected count %u.\n", len);
+
+ hr = IEnumMoniker_Skip(enummoniker, 0);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Skip(enummoniker, 1);
+ ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Clone(enummoniker, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ enummoniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
+todo_wine {
+ ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+ ok(!enummoniker2, "Unexpected pointer.\n");
+}
+ hr = IEnumMoniker_Reset(enummoniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = IEnumMoniker_Skip(enummoniker, 2);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ len = 0;
+ hr = IEnumMoniker_Next(enummoniker, 1, &moniker2, &len);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ ok(len == 1, "Unexpected count %u.\n", len);
+ TEST_DISPLAY_NAME(moniker2, L"!I1");
+ IMoniker_Release(moniker2);
+
+ enummoniker2 = (void *)0xdeadbeef;
+ hr = IEnumMoniker_Clone(enummoniker, &enummoniker2);
+todo_wine {
+ ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
+ ok(!enummoniker2, "Unexpected pointer.\n");
+}
+ IEnumMoniker_Release(enummoniker);
+
+ IMoniker_Release(moniker);
+
IBindCtx_Release(bindctx);
}
--
2.33.0
Sept. 30, 2021
[PATCH] d2d1/tests: Add tests for crop effect.
by Ziqing Hui
Signed-off-by: Ziqing Hui <zhui(a)codeweavers.com>
---
dlls/d2d1/tests/d2d1.c | 90 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 90 insertions(+)
diff --git a/dlls/d2d1/tests/d2d1.c b/dlls/d2d1/tests/d2d1.c
index 4beba7c963a..cf37efdc7e8 100644
--- a/dlls/d2d1/tests/d2d1.c
+++ b/dlls/d2d1/tests/d2d1.c
@@ -10045,6 +10045,95 @@ static void test_effect_2d_affine(BOOL d3d11)
release_test_context(&ctx);
}
+static void test_effect_crop(BOOL d3d11)
+{
+ D2D1_BITMAP_PROPERTIES1 bitmap_desc;
+ struct d2d1_test_context ctx;
+ ID2D1DeviceContext *context;
+ D2D_RECT_F output_bounds;
+ D2D1_SIZE_U input_size;
+ ID2D1Factory1 *factory;
+ ID2D1Bitmap1 *bitmap;
+ DWORD image[16 * 16];
+ ID2D1Effect *effect;
+ ID2D1Image *output;
+ unsigned int i;
+ HRESULT hr;
+
+ const struct crop_effect_test
+ {
+ D2D_VECTOR_4F crop_rect; /* {x: left, y: top, z: right, w: bottom} */
+ D2D_RECT_F bounds;
+ }
+ crop_effect_tests[] =
+ {
+ {{0.0f, 0.0f, 8.0f, 8.0f}, {0.0f, 0.0f, 8.0f, 8.0f}},
+ {{4.0f, 4.0f, 8.0f, 8.0f}, {4.0f, 4.0f, 8.0f, 8.0f}},
+ {{10.0f, 10.0f, 20.0f, 20.0f}, {10.0f, 10.0f, 16.0f, 16.0f}},
+ {{-10.0f, 10.0f, 20.0f, 12.0f}, {0.0f, 10.0f, 16.0f, 12.0f}},
+ {{3.0f, -2.0f, 5.0f, 1.0f}, {3.0f, 0.0f, 5.0f, 1.0f}},
+ {{-1.0f, -1.0f, 20.0f, 20.0f}, {0.0f, 0.0f, 16.0f, 16.0f}},
+ {{-5.0f, -5.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 0.0f, 0.0f}},
+ };
+ memset(image, 0xff, sizeof(image));
+
+ if (!init_test_context(&ctx, d3d11))
+ return;
+
+ if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &IID_ID2D1Factory1, NULL, (void **)&factory)))
+ {
+ win_skip("ID2D1Factory1 is not supported.\n");
+ release_test_context(&ctx);
+ return;
+ }
+
+ hr = ID2D1RenderTarget_QueryInterface(ctx.rt, &IID_ID2D1DeviceContext, (void **)&context);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ hr = ID2D1DeviceContext_CreateEffect(context, &CLSID_D2D1Crop, &effect);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(crop_effect_tests); ++i)
+ {
+ const struct crop_effect_test *test = &crop_effect_tests[i];
+ winetest_push_context("Test %u", i);
+
+ set_size_u(&input_size, 16, 16);
+ bitmap_desc.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ bitmap_desc.pixelFormat.alphaMode = D2D1_ALPHA_MODE_IGNORE;
+ bitmap_desc.dpiX = 96.0f;
+ bitmap_desc.dpiY = 96.0f;
+ bitmap_desc.bitmapOptions = D2D1_BITMAP_OPTIONS_NONE;
+ bitmap_desc.colorContext = NULL;
+ hr = ID2D1DeviceContext_CreateBitmap(context, input_size, image,
+ sizeof(*image) * 16, &bitmap_desc, &bitmap);
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+
+ ID2D1Effect_SetInput(effect, 0, (ID2D1Image *)bitmap, FALSE);
+ hr = ID2D1Effect_SetValue(effect, D2D1_CROP_PROP_RECT, D2D1_PROPERTY_TYPE_VECTOR4,
+ (const BYTE *)&test->crop_rect, sizeof(test->crop_rect));
+ ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
+ ID2D1Effect_GetOutput(effect, &output);
+
+ set_rect(&output_bounds, -1.0f, -1.0f, -1.0f, -1.0f);
+ ID2D1DeviceContext_GetImageLocalBounds(context, output, &output_bounds);
+ todo_wine
+ ok(compare_rect(&output_bounds, test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom, 0),
+ "Got unexpected output bounds {%.8e, %.8e, %.8e, %.8e}, expected {%.8e, %.8e, %.8e, %.8e}.\n",
+ output_bounds.left, output_bounds.top, output_bounds.right, output_bounds.bottom,
+ test->bounds.left, test->bounds.top, test->bounds.right, test->bounds.bottom);
+
+ ID2D1Image_Release(output);
+ ID2D1Bitmap1_Release(bitmap);
+ winetest_pop_context();
+ }
+
+ ID2D1Effect_Release(effect);
+ ID2D1DeviceContext_Release(context);
+ ID2D1Factory1_Release(factory);
+ release_test_context(&ctx);
+}
+
START_TEST(d2d1)
{
HMODULE d2d1_dll = GetModuleHandleA("d2d1.dll");
@@ -10108,6 +10197,7 @@ START_TEST(d2d1)
queue_test(test_mt_factory);
queue_test(test_effect);
queue_test(test_effect_2d_affine);
+ queue_test(test_effect_crop);
run_queued_tests();
}
--
2.25.1
Sept. 30, 2021
Re: [PATCH v2] riched20: Fix saving to disk first-indent and left-indent (\fi and \li)
by Marvin
Hi,
While running your changed tests, I think I found new failures.
Being a bot and all I'm not very good at pattern recognition, so I might be
wrong, but could you please double-check?
Full results can be found at:
https://testbot.winehq.org/JobDetails.pl?Key=99107
Your paranoid android.
=== debiant2 (build log) ===
error: corrupt patch at line 11
Task: Patch failed to apply
=== debiant2 (build log) ===
error: corrupt patch at line 11
Task: Patch failed to apply
Sept. 30, 2021
[PATCH v2] riched20: Fix saving to disk first-indent and left-indent (\fi and \li)
by Philip Hardin
Signed-off-by: Philip Hardin <phoss(a)tutanota.com>
---
dlls/riched20/writer.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/riched20/writer.c b/dlls/riched20/writer.c
index 7c7e648f107..2477dda7407 100644
--- a/dlls/riched20/writer.c
+++ b/dlls/riched20/writer.c
@@ -662,10 +662,12 @@ static BOOL stream_out_para_props( ME_TextEditor *editor, ME_OutStream *pStream,
if (!(editor->bEmulateVersion10 && /* v1.0 - 3.0 */
fmt->dwMask & PFM_TABLE && fmt->wEffects & PFE_TABLE))
{
- if (fmt->dxOffset)
- sprintf(props + strlen(props), "\\li%d", fmt->dxOffset);
- if (fmt->dxStartIndent)
- sprintf(props + strlen(props), "\\fi%d", fmt->dxStartIndent);
+ int first_indent = -fmt->dxOffset;
+ int left_indent = fmt->dxStartIndent + fmt->dxOffset;
+ if (first_indent)
+ sprintf(props + strlen(props), "\\fi%d", first_indent);
+ if (left_indent)
+ sprintf(props + strlen(props), "\\li%d", left_indent);
if (fmt->dxRightIndent)
sprintf(props + strlen(props), "\\ri%d", fmt->dxRightIndent);
if (fmt->dwMask & PFM_TABSTOPS) {
--
2.25.1
Sept. 30, 2021
[PATCH vkd3d v2] vkd3d: Only disable raster based on SO stream if SO is used.
by Conor McCarthy
Fixes the black screen problem in Diablo 2: Resurrected.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51105
From: Robin Kertels <robin.kertels(a)gmail.com>
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
v2: Remove spurious FIXME_ONCE change (my bad).
---
libs/vkd3d/state.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libs/vkd3d/state.c b/libs/vkd3d/state.c
index 9e554b44..73c78d06 100644
--- a/libs/vkd3d/state.c
+++ b/libs/vkd3d/state.c
@@ -2629,7 +2629,7 @@ static HRESULT d3d12_pipeline_state_init_graphics(struct d3d12_pipeline_state *s
rs_desc_from_d3d12(&graphics->rs_desc, &desc->RasterizerState);
have_attachment = graphics->rt_count || graphics->dsv_format || is_dsv_format_unknown;
if ((!have_attachment && !(desc->PS.pShaderBytecode && desc->PS.BytecodeLength))
- || so_desc->RasterizedStream == D3D12_SO_NO_RASTERIZED_STREAM)
+ || (so_desc->NumEntries != 0 && so_desc->RasterizedStream == D3D12_SO_NO_RASTERIZED_STREAM))
graphics->rs_desc.rasterizerDiscardEnable = VK_TRUE;
rs_stream_info_from_d3d12(&graphics->rs_stream_info, &graphics->rs_desc, so_desc, vk_info);
--
2.32.0
Sept. 30, 2021