Wine-Devel
Threads by month
- ----- 2026 -----
- 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
- 8 participants
- 84547 discussions
[PATCH 03/12] winecoreaudio: Move midi_init and midi_release to the unixlib.
by Huw Davies Nov. 26, 2021
by Huw Davies Nov. 26, 2021
Nov. 26, 2021
midi_init temporarily returns unix-side info, which will eventually
be removed.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/coreaudio.c | 2 +
dlls/winecoreaudio.drv/coremidi.c | 233 +++++++++++++++++++++++++----
dlls/winecoreaudio.drv/coremidi.h | 28 +++-
dlls/winecoreaudio.drv/midi.c | 153 ++++---------------
dlls/winecoreaudio.drv/unixlib.h | 13 ++
5 files changed, 276 insertions(+), 153 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coreaudio.c b/dlls/winecoreaudio.drv/coreaudio.c
index fd32a2a99ac..9476b6baf6f 100644
--- a/dlls/winecoreaudio.drv/coreaudio.c
+++ b/dlls/winecoreaudio.drv/coreaudio.c
@@ -1629,4 +1629,6 @@ unixlib_entry_t __wine_unix_call_funcs[] =
get_frequency,
is_started,
set_volumes,
+ midi_init,
+ midi_release,
};
diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
index 92f52c972d3..dedfa0aa9ee 100644
--- a/dlls/winecoreaudio.drv/coremidi.c
+++ b/dlls/winecoreaudio.drv/coremidi.c
@@ -21,46 +21,90 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-
+#if 0
+#pragma makedep unix
+#endif
#include "config.h"
-#include <CoreMIDI/CoreMIDI.h>
+#define ULONG __carbon_ULONG
+#define E_INVALIDARG __carbon_E_INVALIDARG
+#define E_OUTOFMEMORY __carbon_E_OUTOFMEMORY
+#define E_HANDLE __carbon_E_HANDLE
+#define E_ACCESSDENIED __carbon_E_ACCESSDENIED
+#define E_UNEXPECTED __carbon_E_UNEXPECTED
+#define E_FAIL __carbon_E_FAIL
+#define E_ABORT __carbon_E_ABORT
+#define E_POINTER __carbon_E_POINTER
+#define E_NOINTERFACE __carbon_E_NOINTERFACE
+#define E_NOTIMPL __carbon_E_NOTIMPL
+#define S_FALSE __carbon_S_FALSE
+#define S_OK __carbon_S_OK
+#define HRESULT_FACILITY __carbon_HRESULT_FACILITY
+#define IS_ERROR __carbon_IS_ERROR
+#define FAILED __carbon_FAILED
+#define SUCCEEDED __carbon_SUCCEEDED
+#define MAKE_HRESULT __carbon_MAKE_HRESULT
+#define HRESULT __carbon_HRESULT
+#define STDMETHODCALLTYPE __carbon_STDMETHODCALLT
#include <mach/mach_time.h>
+#include <CoreMIDI/CoreMIDI.h>
+#include <AudioUnit/AudioUnit.h>
+#include <AudioToolbox/AudioToolbox.h>
+#undef ULONG
+#undef E_INVALIDARG
+#undef E_OUTOFMEMORY
+#undef E_HANDLE
+#undef E_ACCESSDENIED
+#undef E_UNEXPECTED
+#undef E_FAIL
+#undef E_ABORT
+#undef E_POINTER
+#undef E_NOINTERFACE
+#undef E_NOTIMPL
+#undef S_FALSE
+#undef S_OK
+#undef HRESULT_FACILITY
+#undef IS_ERROR
+#undef FAILED
+#undef SUCCEEDED
+#undef MAKE_HRESULT
+#undef HRESULT
+#undef STDMETHODCALLTYPE
-#include "coremidi.h"
-
-
-MIDIClientRef CoreMIDI_CreateClient(CFStringRef name)
-{
- MIDIClientRef client = 0;
-
- if (MIDIClientCreate(name, NULL /* FIXME use notify proc */, NULL, &client) != noErr)
- return 0;
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "mmsystem.h"
+#include "mmddk.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/unixlib.h"
- return client;
-}
+#include "coremidi.h"
+#include "unixlib.h"
-void CoreMIDI_GetObjectName(MIDIObjectRef obj, char *name, int size)
-{
- OSStatus err = noErr;
- CFStringRef cfname;
+WINE_DEFAULT_DEBUG_CHANNEL(midi);
- err = MIDIObjectGetStringProperty(obj, kMIDIPropertyName, &cfname);
- if (err == noErr)
- {
- CFStringGetCString(cfname, name, size, kCFStringEncodingASCII);
- CFRelease(cfname);
- }
-}
+static MIDIClientRef midi_client;
+static MIDIPortRef midi_out_port, midi_in_port;
+static UINT num_dests, num_srcs;
+static struct midi_dest *dests;
+static struct midi_src *srcs;
+static CFStringRef midi_in_thread_port_name;
/*
* CoreMIDI IO threaded callback,
* we can't call Wine debug channels, critical section or anything using NtCurrentTeb here.
*/
-void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
+static void midi_in_read_proc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
{
- CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
+ CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, midi_in_thread_port_name);
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
CFMutableDataRef data;
MIDIMessage msg;
@@ -82,3 +126,140 @@ void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefC
}
CFRelease(msg_port);
}
+
+NTSTATUS midi_init(void *args)
+{
+ CFStringRef name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("wineMIDIClient.%d"), getpid());
+ struct midi_init_params *params = args;
+ OSStatus sc;
+ UINT i;
+
+ sc = MIDIClientCreate(name, NULL /* FIXME use notify proc */, NULL, &midi_client);
+ CFRelease(name);
+ if (sc)
+ {
+ ERR("can't create MIDI Client\n");
+ *params->err = DRV_FAILURE;
+ return STATUS_SUCCESS;
+ }
+
+ num_dests = MAX_MIDI_SYNTHS + MIDIGetNumberOfDestinations();
+ num_srcs = MIDIGetNumberOfSources();
+
+ TRACE("num_dests %d num_srcs %d\n", num_dests, num_srcs);
+
+ dests = calloc(num_dests, sizeof(*dests));
+ srcs = calloc(num_srcs, sizeof(*srcs));
+
+ if (num_srcs > 0)
+ {
+ midi_in_thread_port_name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
+ name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%u"), getpid());
+ MIDIInputPortCreate(midi_client, name, midi_in_read_proc, NULL, &midi_in_port);
+ CFRelease(name);
+ }
+
+ if (num_dests > MAX_MIDI_SYNTHS)
+ {
+ name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineOutputPort.%u"), getpid());
+ MIDIOutputPortCreate(midi_client, name, &midi_out_port);
+ CFRelease(name);
+ }
+
+ /* initialize sources */
+ for (i = 0; i < num_srcs; i++)
+ {
+ srcs[i].wDevID = i;
+ srcs[i].source = MIDIGetSource(i);
+
+ sc = MIDIObjectGetStringProperty(srcs[i].source, kMIDIPropertyName, &name);
+ if (!sc)
+ {
+ int len = min(CFStringGetLength(name), ARRAY_SIZE(srcs[i].caps.szPname) - 1);
+ CFStringGetCharacters(name, CFRangeMake(0, len), srcs[i].caps.szPname);
+ srcs[i].caps.szPname[len] = '\0';
+ }
+ MIDIPortConnectSource(midi_in_port, srcs[i].source, &srcs[i].wDevID);
+
+ srcs[i].state = 0;
+ /* FIXME */
+ srcs[i].caps.wMid = 0x00FF; /* Manufac ID */
+ srcs[i].caps.wPid = 0x0001; /* Product ID */
+ srcs[i].caps.vDriverVersion = 0x0001;
+ srcs[i].caps.dwSupport = 0;
+ }
+
+ /* initialise MIDI synths */
+ for (i = 0; i < MAX_MIDI_SYNTHS; i++)
+ {
+ static const WCHAR synth_name[] = {'C','o','r','e','A','u','d','i','o',' ','M','I','D','I',' ','S','y','n','t','h',' '};
+
+ C_ASSERT(MAX_MIDI_SYNTHS < 10);
+ memcpy(dests[i].caps.szPname, synth_name, sizeof(synth_name));
+ dests[i].caps.szPname[ARRAY_SIZE(synth_name)] = '1' + i;
+ dests[i].caps.szPname[ARRAY_SIZE(synth_name) + 1] = '\0';
+
+ dests[i].caps.wTechnology = MOD_SYNTH;
+ dests[i].caps.wChannelMask = 0xFFFF;
+
+ dests[i].caps.wMid = 0x00FF; /* Manufac ID */
+ dests[i].caps.wPid = 0x0001; /* Product ID */
+ dests[i].caps.vDriverVersion = 0x0001;
+ dests[i].caps.dwSupport = MIDICAPS_VOLUME;
+ dests[i].caps.wVoices = 16;
+ dests[i].caps.wNotes = 16;
+ }
+ /* initialise available destinations */
+ for (i = MAX_MIDI_SYNTHS; i < num_dests; i++)
+ {
+ dests[i].dest = MIDIGetDestination(i - MAX_MIDI_SYNTHS);
+
+ sc = MIDIObjectGetStringProperty(dests[i].dest, kMIDIPropertyName, &name);
+ if (!sc)
+ {
+ int len = min(CFStringGetLength(name), ARRAY_SIZE(dests[i].caps.szPname) - 1);
+ CFStringGetCharacters(name, CFRangeMake(0, len), dests[i].caps.szPname);
+ dests[i].caps.szPname[len] = '\0';
+ }
+
+ dests[i].caps.wTechnology = MOD_MIDIPORT;
+ dests[i].caps.wChannelMask = 0xFFFF;
+
+ dests[i].caps.wMid = 0x00FF; /* Manufac ID */
+ dests[i].caps.wPid = 0x0001;
+ dests[i].caps.vDriverVersion = 0x0001;
+ dests[i].caps.dwSupport = 0;
+ dests[i].caps.wVoices = 0;
+ dests[i].caps.wNotes = 0;
+ }
+
+ params->num_dests = num_dests;
+ params->num_srcs = num_srcs;
+ params->dests = dests;
+ params->srcs = srcs;
+ params->midi_out_port = (void *)midi_out_port;
+ params->midi_in_port = (void *)midi_in_port;
+
+ *params->err = DRV_SUCCESS;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS midi_release(void *args)
+{
+ CFMessagePortRef msg_port;
+
+ if (num_srcs)
+ {
+ /* Stop CFRunLoop in MIDIIn_MessageThread */
+ msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, midi_in_thread_port_name);
+ CFMessagePortSendRequest(msg_port, 1, NULL, 0.0, 0.0, NULL, NULL);
+ CFRelease(msg_port);
+ }
+
+ if (midi_client) MIDIClientDispose(midi_client); /* MIDIClientDispose will close all ports */
+
+ free(srcs);
+ free(dests);
+
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/winecoreaudio.drv/coremidi.h b/dlls/winecoreaudio.drv/coremidi.h
index 47566345b54..ca669db7db1 100644
--- a/dlls/winecoreaudio.drv/coremidi.h
+++ b/dlls/winecoreaudio.drv/coremidi.h
@@ -23,6 +23,8 @@
#include <CoreFoundation/CoreFoundation.h>
+#define MAX_MIDI_SYNTHS 1
+
#ifdef WINE_DEFINITIONS
/*
* Due to CoreMIDI headers conflict redefine some types for Wine
@@ -73,7 +75,31 @@ extern void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *c
extern void MIDIOut_Send(MIDIPortRef port, MIDIEndpointRef dest, UInt8 *buffer, unsigned length);
/* midi.c */
-extern CFStringRef MIDIInThreadPortName;
+typedef struct midi_dest
+{
+ /* graph and synth are only used for MIDI Synth */
+ AUGraph graph;
+ AudioUnit synth;
+
+ MIDIEndpointRef dest;
+
+ MIDIOUTCAPSW caps;
+ MIDIOPENDESC midiDesc;
+ WORD wFlags;
+} MIDIDestination;
+
+typedef struct midi_src
+{
+ MIDIEndpointRef source;
+
+ WORD wDevID;
+ int state; /* 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
+ MIDIINCAPSW caps;
+ MIDIOPENDESC midiDesc;
+ LPMIDIHDR lpQueueHdr;
+ WORD wFlags;
+ DWORD startTime;
+} MIDISource;
typedef struct {
UInt16 devID;
diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c
index 2c89f32b430..000c57ad98d 100644
--- a/dlls/winecoreaudio.drv/midi.c
+++ b/dlls/winecoreaudio.drv/midi.c
@@ -35,9 +35,13 @@
#include "winuser.h"
#include "winnls.h"
#include "mmddk.h"
+#include "mmdeviceapi.h"
+#include "audioclient.h"
#include "wine/unicode.h"
#include "wine/debug.h"
+#include "wine/unixlib.h"
#include "coreaudio.h"
+#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(midi);
@@ -46,45 +50,17 @@ WINE_DEFAULT_DEBUG_CHANNEL(midi);
#define WINE_DEFINITIONS
#include "coremidi.h"
-static MIDIClientRef wineMIDIClient = NULL;
-
static DWORD MIDIOut_NumDevs = 0;
static DWORD MIDIIn_NumDevs = 0;
-typedef struct tagMIDIDestination {
- /* graph and synth are only used for MIDI Synth */
- AUGraph graph;
- AudioUnit synth;
-
- MIDIEndpointRef dest;
-
- MIDIOUTCAPSW caps;
- MIDIOPENDESC midiDesc;
- WORD wFlags;
-} MIDIDestination;
-
-typedef struct tagMIDISource {
- MIDIEndpointRef source;
-
- WORD wDevID;
- int state; /* 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
- MIDIINCAPSW caps;
- MIDIOPENDESC midiDesc;
- LPMIDIHDR lpQueueHdr;
- WORD wFlags;
- DWORD startTime;
-} MIDISource;
-
static CRITICAL_SECTION midiInLock; /* Critical section for MIDI In */
-CFStringRef MIDIInThreadPortName = NULL;
+static CFStringRef MIDIInThreadPortName;
static DWORD WINAPI MIDIIn_MessageThread(LPVOID p);
static MIDIPortRef MIDIInPort = NULL;
static MIDIPortRef MIDIOutPort = NULL;
-#define MAX_MIDI_SYNTHS 1
-
MIDIDestination *destinations;
MIDISource *sources;
@@ -92,127 +68,52 @@ extern int SynthUnit_CreateDefaultSynthUnit(AUGraph *graph, AudioUnit *synth);
extern int SynthUnit_Initialize(AudioUnit synth, AUGraph graph);
extern int SynthUnit_Close(AUGraph graph);
-
-LONG CoreAudio_MIDIInit(void)
+static LONG CoreAudio_MIDIInit(void)
{
- int i;
- CHAR szPname[MAXPNAMELEN] = {0};
+ struct midi_init_params params;
+ DWORD err;
- int numDest = MIDIGetNumberOfDestinations();
- CFStringRef name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("wineMIDIClient.%d"), getpid());
+ params.err = &err;
- wineMIDIClient = CoreMIDI_CreateClient( name );
- if (wineMIDIClient == NULL)
+ UNIX_CALL(midi_init, ¶ms);
+ if (err != DRV_SUCCESS)
{
- CFRelease(name);
- ERR("can't create wineMIDIClient\n");
- return DRV_FAILURE;
+ ERR("can't create midi client\n");
+ return err;
}
- CFRelease(name);
- MIDIOut_NumDevs = MAX_MIDI_SYNTHS;
- MIDIOut_NumDevs += numDest;
-
- MIDIIn_NumDevs = MIDIGetNumberOfSources();
-
- TRACE("MIDIOut_NumDevs %d MIDIIn_NumDevs %d\n", MIDIOut_NumDevs, MIDIIn_NumDevs);
-
- destinations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIOut_NumDevs * sizeof(MIDIDestination));
- sources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIIn_NumDevs * sizeof(MIDISource));
+ MIDIOut_NumDevs = params.num_dests;
+ MIDIIn_NumDevs = params.num_srcs;
+ destinations = params.dests;
+ sources = params.srcs;
+ MIDIOutPort = params.midi_out_port;
+ MIDIInPort = params.midi_in_port;
if (MIDIIn_NumDevs > 0)
{
InitializeCriticalSection(&midiInLock);
midiInLock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": midiInLock");
+
MIDIInThreadPortName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
CloseHandle( CreateThread(NULL, 0, MIDIIn_MessageThread, NULL, 0, NULL));
-
- name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%u"), getpid());
- MIDIInputPortCreate(wineMIDIClient, name, MIDIIn_ReadProc, NULL, &MIDIInPort);
- CFRelease(name);
}
- if (numDest > 0)
- {
- name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineOutputPort.%u"), getpid());
- MIDIOutputPortCreate(wineMIDIClient, name, &MIDIOutPort);
- CFRelease(name);
- }
-
- /* initialize sources */
- for (i = 0; i < MIDIIn_NumDevs; i++)
- {
- sources[i].wDevID = i;
- sources[i].source = MIDIGetSource(i);
-
- CoreMIDI_GetObjectName(sources[i].source, szPname, sizeof(szPname));
- MultiByteToWideChar(CP_ACP, 0, szPname, -1, sources[i].caps.szPname, ARRAY_SIZE(sources[i].caps.szPname));
-
- MIDIPortConnectSource(MIDIInPort, sources[i].source, &sources[i].wDevID);
-
- sources[i].state = 0;
- /* FIXME */
- sources[i].caps.wMid = 0x00FF; /* Manufac ID */
- sources[i].caps.wPid = 0x0001; /* Product ID */
- sources[i].caps.vDriverVersion = 0x0001;
- sources[i].caps.dwSupport = 0;
- }
-
- /* initialise MIDI synths */
- for (i = 0; i < MAX_MIDI_SYNTHS; i++)
- {
- snprintf(szPname, sizeof(szPname), "CoreAudio MIDI Synth %d", i);
- MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, ARRAY_SIZE(destinations[i].caps.szPname));
-
- destinations[i].caps.wTechnology = MOD_SYNTH;
- destinations[i].caps.wChannelMask = 0xFFFF;
-
- destinations[i].caps.wMid = 0x00FF; /* Manufac ID */
- destinations[i].caps.wPid = 0x0001; /* Product ID */
- destinations[i].caps.vDriverVersion = 0x0001;
- destinations[i].caps.dwSupport = MIDICAPS_VOLUME;
- destinations[i].caps.wVoices = 16;
- destinations[i].caps.wNotes = 16;
- }
- /* initialise available destinations */
- for (i = MAX_MIDI_SYNTHS; i < numDest + MAX_MIDI_SYNTHS; i++)
- {
- destinations[i].dest = MIDIGetDestination(i - MAX_MIDI_SYNTHS);
-
- CoreMIDI_GetObjectName(destinations[i].dest, szPname, sizeof(szPname));
- MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, ARRAY_SIZE(destinations[i].caps.szPname));
-
- destinations[i].caps.wTechnology = MOD_MIDIPORT;
- destinations[i].caps.wChannelMask = 0xFFFF;
-
- destinations[i].caps.wMid = 0x00FF; /* Manufac ID */
- destinations[i].caps.wPid = 0x0001;
- destinations[i].caps.vDriverVersion = 0x0001;
- destinations[i].caps.dwSupport = 0;
- destinations[i].caps.wVoices = 0;
- destinations[i].caps.wNotes = 0;
- }
- return DRV_SUCCESS;
+ return err;
}
-LONG CoreAudio_MIDIRelease(void)
+static LONG CoreAudio_MIDIRelease(void)
{
TRACE("\n");
+
+ UNIX_CALL(midi_release, NULL);
+ sources = NULL;
+ destinations = NULL;
+
if (MIDIIn_NumDevs > 0)
{
- CFMessagePortRef messagePort;
- /* Stop CFRunLoop in MIDIIn_MessageThread */
- messagePort = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
- CFMessagePortSendRequest(messagePort, 1, NULL, 0.0, 0.0, NULL, NULL);
- CFRelease(messagePort);
-
midiInLock.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&midiInLock);
}
- if (wineMIDIClient) MIDIClientDispose(wineMIDIClient); /* MIDIClientDispose will close all ports */
-
- HeapFree(GetProcessHeap(), 0, sources);
- HeapFree(GetProcessHeap(), 0, destinations);
return DRV_SUCCESS;
}
diff --git a/dlls/winecoreaudio.drv/unixlib.h b/dlls/winecoreaudio.drv/unixlib.h
index 6f51c7877fa..6dfb68d202f 100644
--- a/dlls/winecoreaudio.drv/unixlib.h
+++ b/dlls/winecoreaudio.drv/unixlib.h
@@ -182,6 +182,14 @@ struct set_volumes_params
int channel;
};
+struct midi_init_params
+{
+ DWORD *err;
+ UINT num_dests, num_srcs;
+ void *dests, *srcs;
+ void *midi_out_port, *midi_in_port;
+};
+
enum unix_funcs
{
unix_get_endpoint_ids,
@@ -204,8 +212,13 @@ enum unix_funcs
unix_get_frequency,
unix_is_started,
unix_set_volumes,
+ unix_midi_init,
+ unix_midi_release,
};
+NTSTATUS midi_init( void * ) DECLSPEC_HIDDEN;
+NTSTATUS midi_release( void * ) DECLSPEC_HIDDEN;
+
extern unixlib_handle_t coreaudio_handle;
#define UNIX_CALL( func, params ) __wine_unix_call( coreaudio_handle, unix_ ## func, params )
--
2.23.0
2
1
[PATCH 02/12] winecoreaudio: Combine MIDIIn_SendMessage into MIDIIn_ReadProc.
by Huw Davies Nov. 26, 2021
by Huw Davies Nov. 26, 2021
Nov. 26, 2021
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/coremidi.c | 31 ++++++++++++++------
dlls/winecoreaudio.drv/coremidi.h | 8 +++++-
dlls/winecoreaudio.drv/midi.c | 48 ++++---------------------------
3 files changed, 36 insertions(+), 51 deletions(-)
diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
index 6d54d89cfac..92f52c972d3 100644
--- a/dlls/winecoreaudio.drv/coremidi.c
+++ b/dlls/winecoreaudio.drv/coremidi.c
@@ -1,7 +1,11 @@
/*
- * Wine Midi driver for Mac OS X
+ * MIDI driver for macOS (unixlib)
*
- * Copyright 2006 Emmanuel Maillard
+ * Copyright 1994 Martin Ayotte
+ * Copyright 1998 Luiz Otavio L. Zorzella
+ * Copyright 1998, 1999 Eric POUECH
+ * Copyright 2005, 2006 Emmanuel Maillard
+ * Copyright 2021 Huw Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -56,14 +60,25 @@ void CoreMIDI_GetObjectName(MIDIObjectRef obj, char *name, int size)
*/
void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon)
{
- unsigned int i;
-
+ CFMessagePortRef msg_port = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
- for (i = 0; i < pktlist->numPackets; ++i) {
- UInt16 devID = *((UInt16 *)connRefCon);
-
- MIDIIn_SendMessage(devID, packet->data, packet->length);
+ CFMutableDataRef data;
+ MIDIMessage msg;
+ unsigned int i;
+ for (i = 0; i < pktlist->numPackets; ++i)
+ {
+ msg.devID = *(UInt16 *)connRefCon;
+ msg.length = packet->length;
+ data = CFDataCreateMutable(kCFAllocatorDefault, sizeof(msg) + packet->length);
+ if (data)
+ {
+ CFDataAppendBytes(data, (UInt8 *)&msg, sizeof(msg));
+ CFDataAppendBytes(data, packet->data, packet->length);
+ CFMessagePortSendRequest(msg_port, 0, data, 0.0, 0.0, NULL, NULL);
+ CFRelease(data);
+ }
packet = MIDIPacketNext(packet);
}
+ CFRelease(msg_port);
}
diff --git a/dlls/winecoreaudio.drv/coremidi.h b/dlls/winecoreaudio.drv/coremidi.h
index 3433a1d4342..47566345b54 100644
--- a/dlls/winecoreaudio.drv/coremidi.h
+++ b/dlls/winecoreaudio.drv/coremidi.h
@@ -73,6 +73,12 @@ extern void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *c
extern void MIDIOut_Send(MIDIPortRef port, MIDIEndpointRef dest, UInt8 *buffer, unsigned length);
/* midi.c */
-void MIDIIn_SendMessage(UInt16 devID, const void *buffer, UInt16 length);
+extern CFStringRef MIDIInThreadPortName;
+
+typedef struct {
+ UInt16 devID;
+ UInt16 length;
+ Byte data[];
+} MIDIMessage;
#endif
diff --git a/dlls/winecoreaudio.drv/midi.c b/dlls/winecoreaudio.drv/midi.c
index 32826cb658c..2c89f32b430 100644
--- a/dlls/winecoreaudio.drv/midi.c
+++ b/dlls/winecoreaudio.drv/midi.c
@@ -1,14 +1,11 @@
/*
- * Sample MIDI Wine Driver for Mac OS X (based on OSS midi driver)
+ * MIDI driver for macOS (PE-side)
*
- * Copyright 1994 Martin Ayotte
- * Copyright 1998 Luiz Otavio L. Zorzella (init procedures)
- * Copyright 1998/1999 Eric POUECH :
- * 98/7 changes for making this MIDI driver work on OSS
- * current support is limited to MIDI ports of OSS systems
- * 98/9 rewriting MCI code for MIDI
- * 98/11 split in midi.c and mcimidi.c
+ * Copyright 1994 Martin Ayotte
+ * Copyright 1998 Luiz Otavio L. Zorzella
+ * Copyright 1998, 1999 Eric POUECH
* Copyright 2005, 2006 Emmanuel Maillard
+ * Copyright 2021 Huw Davies
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -78,14 +75,8 @@ typedef struct tagMIDISource {
DWORD startTime;
} MIDISource;
-typedef struct {
- UInt16 devID;
- UInt16 length;
- Byte data[];
-} MIDIMessage;
-
static CRITICAL_SECTION midiInLock; /* Critical section for MIDI In */
-static CFStringRef MIDIInThreadPortName = NULL;
+CFStringRef MIDIInThreadPortName = NULL;
static DWORD WINAPI MIDIIn_MessageThread(LPVOID p);
@@ -798,33 +789,6 @@ static DWORD MIDIIn_Reset(WORD wDevID)
/*
* MIDI In Mach message handling
*/
-
-/*
- * Call from CoreMIDI IO threaded callback,
- * we can't call Wine debug channels, critical section or anything using NtCurrentTeb here.
- */
-void MIDIIn_SendMessage(UInt16 devID, const void *buffer, UInt16 length)
-{
- MIDIMessage msg;
- CFMutableDataRef data;
-
- CFMessagePortRef messagePort;
- messagePort = CFMessagePortCreateRemote(kCFAllocatorDefault, MIDIInThreadPortName);
-
- msg.devID = devID;
- msg.length = length;
-
- data = CFDataCreateMutable(kCFAllocatorDefault, sizeof(msg) + length);
- if (data)
- {
- CFDataAppendBytes(data, (UInt8 *) &msg, sizeof(msg));
- CFDataAppendBytes(data, buffer, length);
- CFMessagePortSendRequest(messagePort, 0, data, 0.0, 0.0, NULL, NULL);
- CFRelease(data);
- }
- CFRelease(messagePort);
-}
-
static CFDataRef MIDIIn_MessageHandler(CFMessagePortRef local, SInt32 msgid, CFDataRef data, void *info)
{
MIDIMessage *msg = NULL;
--
2.23.0
2
1
[PATCH 01/12] winecoreaudio: Temporarily move MIDIOut_Send() to audiounit.c.
by Huw Davies Nov. 26, 2021
by Huw Davies Nov. 26, 2021
Nov. 26, 2021
This is to enable coremidi.c to become the unixlib, while still
enabling code on the user-side to be able to call MIDIOut_Send() for
the time being. Eventually, its equivalent will move to the unixlib
and audiounit.c will disappear.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winecoreaudio.drv/audiounit.c | 13 +++++++++++++
dlls/winecoreaudio.drv/coremidi.c | 12 ------------
2 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/dlls/winecoreaudio.drv/audiounit.c b/dlls/winecoreaudio.drv/audiounit.c
index 030ff4d090a..c91fec216bd 100644
--- a/dlls/winecoreaudio.drv/audiounit.c
+++ b/dlls/winecoreaudio.drv/audiounit.c
@@ -22,6 +22,7 @@
#define ULONG CoreFoundation_ULONG
#define HRESULT CoreFoundation_HRESULT
+#include <mach/mach_time.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioToolbox/AudioToolbox.h>
#undef ULONG
@@ -195,3 +196,15 @@ int SynthUnit_Close(AUGraph graph)
return 1;
}
+
+void MIDIOut_Send(MIDIPortRef port, MIDIEndpointRef dest, UInt8 *buffer, unsigned length)
+{
+ Byte packetBuff[512];
+ MIDIPacketList *packetList = (MIDIPacketList *)packetBuff;
+
+ MIDIPacket *packet = MIDIPacketListInit(packetList);
+
+ packet = MIDIPacketListAdd(packetList, sizeof(packetBuff), packet, mach_absolute_time(), length, buffer);
+ if (packet)
+ MIDISend(port, dest, packetList);
+}
diff --git a/dlls/winecoreaudio.drv/coremidi.c b/dlls/winecoreaudio.drv/coremidi.c
index 94761b05c4f..6d54d89cfac 100644
--- a/dlls/winecoreaudio.drv/coremidi.c
+++ b/dlls/winecoreaudio.drv/coremidi.c
@@ -67,15 +67,3 @@ void MIDIIn_ReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefC
packet = MIDIPacketNext(packet);
}
}
-
-void MIDIOut_Send(MIDIPortRef port, MIDIEndpointRef dest, UInt8 *buffer, unsigned length)
-{
- Byte packetBuff[512];
- MIDIPacketList *packetList = (MIDIPacketList *)packetBuff;
-
- MIDIPacket *packet = MIDIPacketListInit(packetList);
-
- packet = MIDIPacketListAdd(packetList, sizeof(packetBuff), packet, mach_absolute_time(), length, buffer);
- if (packet)
- MIDISend(port, dest, packetList);
-}
--
2.23.0
2
1
Enable Windows 10 msmpeg2vdec.dll to run.
Signed-off-by: Mohamad Al-Jaf <mohamadaljaf(a)gmail.com>
---
configure | 2 ++
configure.ac | 1 +
dlls/ext-ms-win-dx-ddraw-l1-1-0/Makefile.in | 1 +
dlls/ext-ms-win-dx-ddraw-l1-1-0/ext-ms-win-dx-ddraw-l1-1-0.spec | 2 ++
4 files changed, 6 insertions(+)
create mode 100644 dlls/ext-ms-win-dx-ddraw-l1-1-0/Makefile.in
create mode 100644 dlls/ext-ms-win-dx-ddraw-l1-1-0/ext-ms-win-dx-ddraw-l1-1-0.spec
diff --git a/configure b/configure
index 67bcd371525..cd1cdfdd197 100755
--- a/configure
+++ b/configure
@@ -1339,6 +1339,7 @@ enable_explorerframe
enable_ext_ms_win_authz_context_l1_1_0
enable_ext_ms_win_domainjoin_netjoin_l1_1_0
enable_ext_ms_win_dwmapi_ext_l1_1_0
+enable_ext_ms_win_dx_ddraw_l1_1_0
enable_ext_ms_win_gdi_dc_create_l1_1_0
enable_ext_ms_win_gdi_dc_create_l1_1_1
enable_ext_ms_win_gdi_dc_l1_2_0
@@ -21205,6 +21206,7 @@ wine_fn_config_makefile dlls/explorerframe/tests enable_tests
wine_fn_config_makefile dlls/ext-ms-win-authz-context-l1-1-0 enable_ext_ms_win_authz_context_l1_1_0
wine_fn_config_makefile dlls/ext-ms-win-domainjoin-netjoin-l1-1-0 enable_ext_ms_win_domainjoin_netjoin_l1_1_0
wine_fn_config_makefile dlls/ext-ms-win-dwmapi-ext-l1-1-0 enable_ext_ms_win_dwmapi_ext_l1_1_0
+wine_fn_config_makefile dlls/ext-ms-win-dx-ddraw-l1-1-0 enable_ext_ms_win_dx_ddraw_l1_1_0
wine_fn_config_makefile dlls/ext-ms-win-gdi-dc-create-l1-1-0 enable_ext_ms_win_gdi_dc_create_l1_1_0
wine_fn_config_makefile dlls/ext-ms-win-gdi-dc-create-l1-1-1 enable_ext_ms_win_gdi_dc_create_l1_1_1
wine_fn_config_makefile dlls/ext-ms-win-gdi-dc-l1-2-0 enable_ext_ms_win_gdi_dc_l1_2_0
diff --git a/configure.ac b/configure.ac
index b69f738ebca..29b17e208ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2887,6 +2887,7 @@ WINE_CONFIG_MAKEFILE(dlls/explorerframe/tests)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-authz-context-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-domainjoin-netjoin-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-dwmapi-ext-l1-1-0)
+WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-dx-ddraw-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-gdi-dc-create-l1-1-0)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-gdi-dc-create-l1-1-1)
WINE_CONFIG_MAKEFILE(dlls/ext-ms-win-gdi-dc-l1-2-0)
diff --git a/dlls/ext-ms-win-dx-ddraw-l1-1-0/Makefile.in b/dlls/ext-ms-win-dx-ddraw-l1-1-0/Makefile.in
new file mode 100644
index 00000000000..7ea9f6c0ff8
--- /dev/null
+++ b/dlls/ext-ms-win-dx-ddraw-l1-1-0/Makefile.in
@@ -0,0 +1 @@
+MODULE = ext-ms-win-dx-ddraw-l1-1-0.dll
diff --git a/dlls/ext-ms-win-dx-ddraw-l1-1-0/ext-ms-win-dx-ddraw-l1-1-0.spec b/dlls/ext-ms-win-dx-ddraw-l1-1-0/ext-ms-win-dx-ddraw-l1-1-0.spec
new file mode 100644
index 00000000000..9d64b320385
--- /dev/null
+++ b/dlls/ext-ms-win-dx-ddraw-l1-1-0/ext-ms-win-dx-ddraw-l1-1-0.spec
@@ -0,0 +1,2 @@
+@ stdcall DirectDrawCreate(ptr ptr ptr) ddraw.DirectDrawCreate
+@ stdcall DirectDrawEnumerateExA(ptr ptr long) ddraw.DirectDrawEnumerateExA
--
2.34.1
2
7
[PATCH v6 1/5] nsiproxy: Move set_reply_ip_status to a family op.
by Gabriel Ivăncescu Nov. 26, 2021
by Gabriel Ivăncescu Nov. 26, 2021
Nov. 26, 2021
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
It is returning the reply_len because it will be used also for icmp_send_echo,
which has different params struct.
dlls/nsiproxy.sys/icmp_echo.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/dlls/nsiproxy.sys/icmp_echo.c b/dlls/nsiproxy.sys/icmp_echo.c
index 955fdfd..a4ef02a 100644
--- a/dlls/nsiproxy.sys/icmp_echo.c
+++ b/dlls/nsiproxy.sys/icmp_echo.c
@@ -210,6 +210,14 @@ static unsigned short null_chksum( BYTE *data, unsigned int count )
}
#endif
+static int ipv4_set_reply_ip_status( IP_STATUS ip_status, void *out )
+{
+ struct nsiproxy_icmp_echo_reply *reply = out;
+ memset( reply, 0, sizeof(*reply) );
+ reply->status = ip_status;
+ return sizeof(*reply);
+}
+
static void ipv4_set_socket_opts( struct icmp_data *data, struct icmp_send_echo_params *params )
{
int val;
@@ -393,6 +401,7 @@ struct family_ops
int icmp_protocol;
void (*init_icmp_hdr)( struct icmp_data *data, struct icmp_hdr *icmp_hdr );
unsigned short (*chksum)( BYTE *data, unsigned int count );
+ int (*set_reply_ip_status)( IP_STATUS ip_status, void *out );
void (*set_socket_opts)( struct icmp_data *data, struct icmp_send_echo_params *params );
int (*reply_buffer_len)( int reply_len );
BOOL (*parse_ip_hdr)( struct msghdr *msg, int recvd,
@@ -407,6 +416,7 @@ static const struct family_ops ipv4 =
IPPROTO_ICMP,
ipv4_init_icmp_hdr,
chksum,
+ ipv4_set_reply_ip_status,
ipv4_set_socket_opts,
ipv4_reply_buffer_len,
ipv4_parse_ip_hdr,
@@ -421,6 +431,7 @@ static const struct family_ops ipv4_linux_ping =
IPPROTO_ICMP,
ipv4_init_icmp_hdr,
null_chksum,
+ ipv4_set_reply_ip_status,
ipv4_linux_ping_set_socket_opts,
ipv4_linux_ping_reply_buffer_len,
ipv4_linux_ping_parse_ip_hdr,
@@ -584,16 +595,6 @@ NTSTATUS icmp_send_echo( void *args )
return params->handle ? STATUS_PENDING : STATUS_NO_MEMORY;
}
-static NTSTATUS set_reply_ip_status( struct icmp_listen_params *params, IP_STATUS ip_status )
-{
- struct nsiproxy_icmp_echo_reply *reply = params->reply;
-
- memset( reply, 0, sizeof(*reply) );
- reply->status = ip_status;
- params->reply_len = sizeof(*reply);
- return STATUS_SUCCESS;
-}
-
static int get_timeout( LARGE_INTEGER start, DWORD timeout )
{
LARGE_INTEGER now, end;
@@ -647,7 +648,8 @@ static NTSTATUS recv_msg( struct icmp_data *data, struct icmp_listen_params *par
if (reply->data_size && msg.msg_flags & MSG_TRUNC)
{
free( reply_buf );
- return set_reply_ip_status( params, IP_GENERAL_FAILURE );
+ params->reply_len = data->ops->set_reply_ip_status( IP_GENERAL_FAILURE, params->reply );
+ return STATUS_SUCCESS;
}
sockaddr_to_SOCKADDR_INET( (struct sockaddr *)&addr, &reply->addr );
@@ -703,10 +705,12 @@ NTSTATUS icmp_listen( void *args )
if (!ret) /* timeout */
{
TRACE( "timeout\n" );
- return set_reply_ip_status( params, IP_REQ_TIMED_OUT );
+ params->reply_len = data->ops->set_reply_ip_status( IP_REQ_TIMED_OUT, params->reply );
+ return STATUS_SUCCESS;
}
/* ret < 0 */
- return set_reply_ip_status( params, errno_to_ip_status( errno ) );
+ params->reply_len = data->ops->set_reply_ip_status( errno_to_ip_status( errno ), params->reply );
+ return STATUS_SUCCESS;
}
NTSTATUS icmp_cancel_listen( void *args )
--
2.31.1
2
9
From: Florian Will <florian.will(a)gmail.com>
SetMapMode(.., MM_TEXT) is called a lot in common gdiplus use cases via
gdi_transform_acquire(). Querying the size and resolution can be
expensive, so skip it when its not needed.
When running the "ZusiDisplay" ET423 diagnostic display, which uses
gdiplus heavily, this change increases the "indicator blinking speed"
from 0.6 per second to 1 per second and probably hits the FPS limit now.
Also, CPU usage of the ZusiDisplay.exe process goes down from ~75% to
~42% of one core according to "top", and wineserver CPU usage goes down
from ~48% to ~3%.
Signed-off-by: Florian Will <florian.will(a)gmail.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
I'm not exactly overjoyed with this patch as we should strive
to make GetDeviceCaps() faster. However, it does make a
difference to an application and isn't too horrendous.
dlls/win32u/mapping.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/mapping.c b/dlls/win32u/mapping.c
index 6c20f50a302..6e7c42fe7cc 100644
--- a/dlls/win32u/mapping.c
+++ b/dlls/win32u/mapping.c
@@ -117,8 +117,6 @@ BOOL set_map_mode( DC *dc, int mode )
if (mode == dc->attr->map_mode && (mode == MM_ISOTROPIC || mode == MM_ANISOTROPIC))
return TRUE;
- virtual_size = get_dc_virtual_size( dc );
- virtual_res = get_dc_virtual_res( dc );
switch (mode)
{
case MM_TEXT:
@@ -129,30 +127,40 @@ BOOL set_map_mode( DC *dc, int mode )
break;
case MM_LOMETRIC:
case MM_ISOTROPIC:
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
dc->attr->wnd_ext.cx = virtual_size.cx * 10;
dc->attr->wnd_ext.cy = virtual_size.cy * 10;
dc->attr->vport_ext.cx = virtual_res.cx;
dc->attr->vport_ext.cy = -virtual_res.cy;
break;
case MM_HIMETRIC:
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
dc->attr->wnd_ext.cx = virtual_size.cx * 100;
dc->attr->wnd_ext.cy = virtual_size.cy * 100;
dc->attr->vport_ext.cx = virtual_res.cx;
dc->attr->vport_ext.cy = -virtual_res.cy;
break;
case MM_LOENGLISH:
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
dc->attr->wnd_ext.cx = muldiv(1000, virtual_size.cx, 254);
dc->attr->wnd_ext.cy = muldiv(1000, virtual_size.cy, 254);
dc->attr->vport_ext.cx = virtual_res.cx;
dc->attr->vport_ext.cy = -virtual_res.cy;
break;
case MM_HIENGLISH:
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
dc->attr->wnd_ext.cx = muldiv(10000, virtual_size.cx, 254);
dc->attr->wnd_ext.cy = muldiv(10000, virtual_size.cy, 254);
dc->attr->vport_ext.cx = virtual_res.cx;
dc->attr->vport_ext.cy = -virtual_res.cy;
break;
case MM_TWIPS:
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
dc->attr->wnd_ext.cx = muldiv(14400, virtual_size.cx, 254);
dc->attr->wnd_ext.cy = muldiv(14400, virtual_size.cy, 254);
dc->attr->vport_ext.cx = virtual_res.cx;
--
2.23.0
2
1
Nov. 26, 2021
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
Makefile.am | 2 +
libs/vkd3d-shader/hlsl.c | 4 ++
libs/vkd3d-shader/hlsl.h | 4 ++
libs/vkd3d-shader/hlsl.y | 103 +++++++++++++++++++++++++++++
libs/vkd3d-shader/hlsl_sm4.c | 56 +++++++++++++++-
tests/hlsl-gather.shader_test | 118 ++++++++++++++++++++++++++++++++++
6 files changed, 286 insertions(+), 1 deletion(-)
create mode 100644 tests/hlsl-gather.shader_test
diff --git a/Makefile.am b/Makefile.am
index 3e083b0a..1a80152a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -67,6 +67,7 @@ vkd3d_shader_tests = \
tests/hlsl-duplicate-modifiers.shader_test \
tests/hlsl-for.shader_test \
tests/hlsl-function-overload.shader_test \
+ tests/hlsl-gather.shader_test \
tests/hlsl-invalid.shader_test \
tests/hlsl-majority-pragma.shader_test \
tests/hlsl-majority-typedef.shader_test \
@@ -292,6 +293,7 @@ XFAIL_TESTS = \
tests/hlsl-duplicate-modifiers.shader_test \
tests/hlsl-for.shader_test \
tests/hlsl-function-overload.shader_test \
+ tests/hlsl-gather.shader_test \
tests/hlsl-majority-pragma.shader_test \
tests/hlsl-majority-typedef.shader_test \
tests/hlsl-nested-arrays.shader_test \
diff --git a/libs/vkd3d-shader/hlsl.c b/libs/vkd3d-shader/hlsl.c
index 1eee4278..74b78f1b 100644
--- a/libs/vkd3d-shader/hlsl.c
+++ b/libs/vkd3d-shader/hlsl.c
@@ -1250,6 +1250,10 @@ static void dump_ir_resource_load(struct vkd3d_string_buffer *buffer, const stru
{
[HLSL_RESOURCE_LOAD] = "load_resource",
[HLSL_RESOURCE_SAMPLE] = "sample",
+ [HLSL_RESOURCE_GATHER_RED] = "gather4r",
+ [HLSL_RESOURCE_GATHER_GREEN] = "gather4g",
+ [HLSL_RESOURCE_GATHER_BLUE] = "gather4b",
+ [HLSL_RESOURCE_GATHER_ALPHA] = "gather4a",
};
vkd3d_string_buffer_printf(buffer, "%s(resource = ", type_names[load->load_type]);
diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h
index 365ef980..891f671a 100644
--- a/libs/vkd3d-shader/hlsl.h
+++ b/libs/vkd3d-shader/hlsl.h
@@ -377,6 +377,10 @@ enum hlsl_resource_load_type
{
HLSL_RESOURCE_LOAD,
HLSL_RESOURCE_SAMPLE,
+ HLSL_RESOURCE_GATHER_RED,
+ HLSL_RESOURCE_GATHER_GREEN,
+ HLSL_RESOURCE_GATHER_BLUE,
+ HLSL_RESOURCE_GATHER_ALPHA,
};
struct hlsl_ir_resource_load
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index b7e0409d..440692f1 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -1852,6 +1852,109 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl
list_add_tail(instrs, &load->node.entry);
return true;
}
+ else if (!strcmp(name, "Gather") || !strcmp(name, "GatherRed") || !strcmp(name, "GatherBlue")
+ || !strcmp(name, "GatherGreen") || !strcmp(name, "GatherAlpha"))
+ {
+ const unsigned int sampler_dim = sampler_dim_count(object_type->sampler_dim);
+ enum hlsl_resource_load_type load_type;
+ const struct hlsl_type *sampler_type;
+ struct hlsl_ir_resource_load *load;
+ struct hlsl_ir_load *sampler_load;
+ struct hlsl_type *result_type;
+ struct hlsl_ir_node *coords;
+ int status_out_arg;
+ int read_channel;
+
+ if (!strcmp(name, "Gather") || !strcmp(name, "GatherRed"))
+ {
+ load_type = HLSL_RESOURCE_GATHER_RED;
+ read_channel = 0;
+ }
+ else if (!strcmp(name, "GatherGreen"))
+ {
+ load_type = HLSL_RESOURCE_GATHER_GREEN;
+ read_channel = 1;
+ }
+ else if (!strcmp(name, "GatherBlue"))
+ {
+ load_type = HLSL_RESOURCE_GATHER_BLUE;
+ read_channel = 2;
+ }
+ else if (!strcmp(name, "GatherAlpha"))
+ {
+ load_type = HLSL_RESOURCE_GATHER_ALPHA;
+ read_channel = 3;
+ }
+ else {
+ assert(!"Unexpected Gather method.");
+ }
+
+
+ if (!strcmp(name, "Gather"))
+ {
+ if (params->args_count != 2 && params->args_count != 3)
+ {
+ hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
+ "Wrong number of arguments to method 'Gather': expected 2 or 3, but got %u.", params->args_count);
+ return false;
+ }
+ }
+ else if (params->args_count < 2 || params->args_count == 5 || params->args_count > 7)
+ {
+ hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT,
+ "Wrong number of arguments to method '%s': expected 2,3,4,6 or 7, but got %u.", name, params->args_count);
+ return false;
+ }
+
+ status_out_arg = -1;
+ if (params->args_count == 4)
+ status_out_arg = 3;
+ if (params->args_count == 7)
+ status_out_arg = 6;
+ if (status_out_arg != -1)
+ FIXME("Ignoring 'status' output parameter.\n");
+
+ if (params->args_count == 3 || params->args_count == 4)
+ FIXME("Ignoring offset parameter.\n");
+ if (params->args_count == 6 || params->args_count == 7)
+ FIXME("Ignoring multiple offset parameters.\n");
+
+ sampler_type = params->args[0]->data_type;
+ if (sampler_type->type != HLSL_CLASS_OBJECT || sampler_type->base_type != HLSL_TYPE_SAMPLER
+ || sampler_type->sampler_dim != HLSL_SAMPLER_DIM_GENERIC)
+ {
+ struct vkd3d_string_buffer *string;
+
+ if ((string = hlsl_type_to_string(ctx, sampler_type)))
+ hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Wrong type for argument 0 of %s(): expected 'sampler', but got '%s'.", name, string->buffer);
+ hlsl_release_string_buffer(ctx, string);
+ return false;
+ }
+
+ if (read_channel >= object_type->e.resource_format->dimx)
+ {
+ hlsl_error(ctx, *loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE,
+ "Method %s() requires at least %d channels.", name, read_channel+1);
+ return false;
+ }
+
+ result_type = hlsl_get_vector_type(ctx, object_type->e.resource_format->base_type, 4);
+
+ /* Only HLSL_IR_LOAD can return an object. */
+ sampler_load = hlsl_ir_load(params->args[0]);
+
+ if (!(coords = add_implicit_conversion(ctx, instrs, params->args[1],
+ hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc)))
+ coords = params->args[1];
+
+ if (!(load = hlsl_new_resource_load(ctx, result_type,
+ load_type, object_load->src.var, object_load->src.offset.node,
+ sampler_load->src.var, sampler_load->src.offset.node, coords, loc)))
+ return false;
+ list_add_tail(instrs, &load->node.entry);
+ return true;
+ }
else
{
struct vkd3d_string_buffer *string;
diff --git a/libs/vkd3d-shader/hlsl_sm4.c b/libs/vkd3d-shader/hlsl_sm4.c
index a95503ee..dbb5e74e 100644
--- a/libs/vkd3d-shader/hlsl_sm4.c
+++ b/libs/vkd3d-shader/hlsl_sm4.c
@@ -753,7 +753,7 @@ struct sm4_instruction
struct sm4_register reg;
enum vkd3d_sm4_swizzle_type swizzle_type;
unsigned int swizzle;
- } srcs[2];
+ } srcs[3];
unsigned int src_count;
uint32_t idx[2];
@@ -1506,6 +1506,43 @@ static void write_sm4_loop(struct hlsl_ctx *ctx,
write_sm4_instruction(buffer, &instr);
}
+
+static void write_sm4_gather(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer,
+ const struct hlsl_type *resource_type, const struct hlsl_ir_node *dst,
+ const struct hlsl_deref *resource, const struct hlsl_deref *sampler, const struct hlsl_ir_node *coords,
+ unsigned int swizzle)
+{
+ struct sm4_instruction instr;
+ unsigned int writemask;
+
+ assert(sampler->var);
+
+ memset(&instr, 0, sizeof(instr));
+ instr.opcode = VKD3D_SM4_OP_GATHER4;
+
+ sm4_register_from_node(&instr.dsts[0].reg, &instr.dsts[0].writemask, NULL, dst);
+ instr.dst_count = 1;
+
+ sm4_register_from_node(&instr.srcs[0].reg, &writemask, &instr.srcs[0].swizzle_type, coords);
+ instr.srcs[0].swizzle = hlsl_swizzle_from_writemask(writemask);
+
+ sm4_register_from_deref(ctx, &instr.srcs[1].reg, &writemask, &instr.srcs[1].swizzle_type,
+ resource, resource_type);
+ instr.srcs[1].swizzle = hlsl_map_swizzle(hlsl_swizzle_from_writemask(writemask), instr.dsts[0].writemask);
+
+ sm4_register_from_deref(ctx, &instr.srcs[2].reg, &writemask, NULL,
+ sampler, sampler->var->data_type);
+ instr.srcs[2].reg.type = VKD3D_SM4_RT_SAMPLER;
+ instr.srcs[2].reg.dim = VKD3D_SM4_DIMENSION_VEC4;
+ instr.srcs[2].swizzle_type = VKD3D_SM4_SWIZZLE_SCALAR;
+ instr.srcs[2].swizzle = swizzle;
+
+ instr.src_count = 3;
+
+ write_sm4_instruction(buffer, &instr);
+}
+
+
static void write_sm4_resource_load(struct hlsl_ctx *ctx,
struct vkd3d_bytecode_buffer *buffer, const struct hlsl_ir_resource_load *load)
{
@@ -1527,6 +1564,23 @@ static void write_sm4_resource_load(struct hlsl_ctx *ctx,
case HLSL_RESOURCE_SAMPLE:
hlsl_fixme(ctx, load->node.loc, "Resource sample instruction.");
break;
+
+ case HLSL_RESOURCE_GATHER_RED:
+ write_sm4_gather(ctx, buffer, resource_type, &load->node, &load->resource,
+ &load->sampler, coords, HLSL_SWIZZLE(X, X, X, X));
+ break;
+ case HLSL_RESOURCE_GATHER_GREEN:
+ write_sm4_gather(ctx, buffer, resource_type, &load->node, &load->resource,
+ &load->sampler, coords, HLSL_SWIZZLE(Y, Y, Y, Y));
+ break;
+ case HLSL_RESOURCE_GATHER_BLUE:
+ write_sm4_gather(ctx, buffer, resource_type, &load->node, &load->resource,
+ &load->sampler, coords, HLSL_SWIZZLE(Z, Z, Z, Z));
+ break;
+ case HLSL_RESOURCE_GATHER_ALPHA:
+ write_sm4_gather(ctx, buffer, resource_type, &load->node, &load->resource,
+ &load->sampler, coords, HLSL_SWIZZLE(W, W, W, W));
+ break;
}
}
diff --git a/tests/hlsl-gather.shader_test b/tests/hlsl-gather.shader_test
new file mode 100644
index 00000000..2409ec8a
--- /dev/null
+++ b/tests/hlsl-gather.shader_test
@@ -0,0 +1,118 @@
+[sampler 0]
+filter linear linear linear
+address clamp clamp clamp
+
+[texture 0]
+size (3, 3)
+0.0 0.0 0.0 0.4 0.1 0.0 0.5 0.0 0.2 0.0 0.0 0.4
+0.0 0.1 0.5 0.0 0.1 0.1 0.0 0.4 0.2 0.1 0.5 0.0
+0.0 0.2 0.0 0.4 0.1 0.2 0.5 0.0 0.2 0.2 0.0 0.4
+
+
+
+[pixel shader]
+sampler s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.Gather(s, float2(0.2, 0.2));
+}
+
+[test]
+draw quad
+probe all rgba (0.0, 0.1, 0.1, 0.0)
+
+
+
+[pixel shader]
+sampler s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherRed(s, float2(0.6, 0.6), int2(0, 0));
+}
+
+[test]
+draw quad
+probe all rgba (0.1, 0.2, 0.2, 0.1)
+
+
+
+[pixel shader]
+SamplerState s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherGreen(s, float2(0.2, 0.2), int2(0, 0));
+}
+
+[test]
+draw quad
+probe all rgba (0.1, 0.1, 0.0, 0.0)
+
+
+
+[pixel shader]
+SamplerState s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherGreen(s, float2(0.8, 0.8));
+}
+
+[test]
+draw quad
+probe all rgba (0.2, 0.2, 0.1, 0.1)
+
+
+
+[pixel shader]
+SamplerState s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherGreen(s, float2(0.2, 0.2), int2(0, 0), int2(0, 0), int2(0, 0), int2(0, 0));
+}
+
+[test]
+draw quad
+probe all rgba (0.1, 0.1, 0.0, 0.0)
+
+
+
+[pixel shader]
+SamplerState s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherBlue(s, float2(0.2, 0.8), int2(0, 0));
+}
+
+[test]
+draw quad
+probe all rgba (0.0, 0.5, 0.0, 0.5)
+
+
+
+[pixel shader]
+SamplerState s;
+Texture2D t;
+
+float4 main() : sv_target
+{
+ return t.GatherAlpha(s, float2(0.2, 0.8), int2(0, 0));
+}
+
+[test]
+draw quad
+probe all rgba (0.4, 0.0, 0.4, 0.0)
+
+
+
+
--
2.25.1
2
1
Nov. 26, 2021
SetMapMode(.., MM_TEXT) is called a lot in common gdiplus use cases via
gdi_transform_acquire(). Querying the size and resolution can be
expensive, and is not needed in the MM_TEXT case, so skip it in that
case.
When running the "ZusiDisplay" ET423 diagnostic display, which uses
gdiplus heavily, this change increases the "indicator blinking speed"
from 0.6 per second to 1 per second and probably hits the FPS limit now.
Also, CPU usage of the ZusiDisplay.exe process goes down from ~75% to
~42% of one core according to "top", and wineserver CPU usage goes down
from ~48% to ~3%.
Signed-off-by: Florian Will <florian.will(a)gmail.com>
---
dlls/win32u/mapping.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/mapping.c b/dlls/win32u/mapping.c
index 6c20f50a302..b4122644dfe 100644
--- a/dlls/win32u/mapping.c
+++ b/dlls/win32u/mapping.c
@@ -117,8 +117,12 @@ BOOL set_map_mode( DC *dc, int mode )
if (mode == dc->attr->map_mode && (mode == MM_ISOTROPIC || mode == MM_ANISOTROPIC))
return TRUE;
- virtual_size = get_dc_virtual_size( dc );
- virtual_res = get_dc_virtual_res( dc );
+ if (mode != MM_TEXT)
+ {
+ virtual_size = get_dc_virtual_size( dc );
+ virtual_res = get_dc_virtual_res( dc );
+ }
+
switch (mode)
{
case MM_TEXT:
--
2.32.0
2
1
[PATCH] ole32: Add CreateObjrefMoniker() stub implementation. (Resend).
by Dmitry Timoshkov Nov. 26, 2021
by Dmitry Timoshkov Nov. 26, 2021
Nov. 26, 2021
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/ole32/moniker.h | 4 +-
dlls/ole32/ole32.spec | 2 +-
dlls/ole32/ole32_objidl.idl | 6 +
dlls/ole32/oleproxy.c | 13 ++
dlls/ole32/pointermoniker.c | 418 +++++++++++++++++++++++++++++++++++-
dlls/ole32/tests/moniker.c | 249 ++++++++++++++++++++-
include/objidl.idl | 5 +-
7 files changed, 691 insertions(+), 6 deletions(-)
diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h
index 8549bd46c1e..2106e374394 100644
--- a/dlls/ole32/moniker.h
+++ b/dlls/ole32/moniker.h
@@ -26,15 +26,17 @@
DEFINE_OLEGUID( CLSID_FileMoniker, 0x303, 0, 0 );
DEFINE_OLEGUID( CLSID_ItemMoniker, 0x304, 0, 0 );
DEFINE_OLEGUID( CLSID_AntiMoniker, 0x305, 0, 0 );
+DEFINE_OLEGUID( CLSID_PointerMoniker, 0x306, 0, 0 );
DEFINE_OLEGUID( CLSID_CompositeMoniker, 0x309, 0, 0 );
DEFINE_OLEGUID( CLSID_ClassMoniker, 0x31a, 0, 0 );
-DEFINE_OLEGUID( CLSID_PointerMoniker, 0x306, 0, 0 );
+DEFINE_OLEGUID( CLSID_ObjrefMoniker, 0x327, 0, 0 );
HRESULT WINAPI FileMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI ItemMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI CompositeMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI ClassMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
+HRESULT WINAPI ObjrefMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
HRESULT WINAPI ComCat_CreateInstance(IClassFactory *iface, IUnknown *pUnk, REFIID riid, void **ppv);
diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec
index 8e73fdd16b4..d9ffd63585c 100644
--- a/dlls/ole32/ole32.spec
+++ b/dlls/ole32/ole32.spec
@@ -103,7 +103,7 @@
@ stdcall CreateGenericComposite(ptr ptr ptr)
@ stdcall CreateILockBytesOnHGlobal(ptr long ptr)
@ stdcall CreateItemMoniker(wstr wstr ptr)
-@ stub CreateObjrefMoniker
+@ stdcall CreateObjrefMoniker(ptr ptr)
@ stdcall CreateOleAdviseHolder(ptr)
@ stdcall CreatePointerMoniker(ptr ptr)
@ stdcall CreateStreamOnHGlobal(ptr long ptr) combase.CreateStreamOnHGlobal
diff --git a/dlls/ole32/ole32_objidl.idl b/dlls/ole32/ole32_objidl.idl
index 0cc3ccea9e5..97f91224839 100644
--- a/dlls/ole32/ole32_objidl.idl
+++ b/dlls/ole32/ole32_objidl.idl
@@ -105,6 +105,12 @@ coclass ClassMoniker { interface IMoniker; }
]
coclass PSFactoryBuffer { interface IFactoryBuffer; }
+[
+ threading(both),
+ uuid(00000327-0000-0000-c000-000000000046)
+]
+coclass ObjrefMoniker { interface IMoniker; }
+
[
helpstring("Component Categories Manager"),
threading(both),
diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c
index e40e2b073e5..c429ce02b3b 100644
--- a/dlls/ole32/oleproxy.c
+++ b/dlls/ole32/oleproxy.c
@@ -137,6 +137,17 @@ static const IClassFactoryVtbl PointerMonikerCFVtbl =
static IClassFactory PointerMonikerCF = { &PointerMonikerCFVtbl };
+static const IClassFactoryVtbl ObjrefMonikerCFVtbl =
+{
+ ClassFactory_QueryInterface,
+ ClassFactory_AddRef,
+ ClassFactory_Release,
+ ObjrefMoniker_CreateInstance,
+ ClassFactory_LockServer
+};
+
+static IClassFactory ObjrefMonikerCF = { &ObjrefMonikerCFVtbl };
+
static const IClassFactoryVtbl ComCatCFVtbl =
{
ClassFactory_QueryInterface,
@@ -198,6 +209,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
return IClassFactory_QueryInterface(&CompositeMonikerCF, iid, ppv);
if (IsEqualCLSID(rclsid, &CLSID_ClassMoniker))
return IClassFactory_QueryInterface(&ClassMonikerCF, iid, ppv);
+ if (IsEqualCLSID(rclsid, &CLSID_ObjrefMoniker))
+ return IClassFactory_QueryInterface(&ObjrefMonikerCF, iid, ppv);
if (IsEqualCLSID(rclsid, &CLSID_PointerMoniker))
return IClassFactory_QueryInterface(&PointerMonikerCF, iid, ppv);
if (IsEqualGUID(rclsid, &CLSID_StdComponentCategoriesMgr))
diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c
index 051d42aca6d..c95c835e9e3 100644
--- a/dlls/ole32/pointermoniker.c
+++ b/dlls/ole32/pointermoniker.c
@@ -1,5 +1,5 @@
/*
- * Pointer Moniker Implementation
+ * Pointer and Objref Monikers Implementation
*
* Copyright 1999 Noomen Hamza
* Copyright 2008 Robert Shearman (for CodeWeavers)
@@ -641,3 +641,419 @@ HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface,
return hr;
}
+
+/* ObjrefMoniker implementation */
+
+typedef struct
+{
+ IMoniker IMoniker_iface;
+ IMarshal IMarshal_iface;
+
+ LONG refcount;
+
+ IUnknown *pObject;
+} ObjrefMonikerImpl;
+
+static inline ObjrefMonikerImpl *objref_impl_from_IMoniker(IMoniker *iface)
+{
+ return CONTAINING_RECORD(iface, ObjrefMonikerImpl, IMoniker_iface);
+}
+
+static ObjrefMonikerImpl *objref_impl_from_IMarshal(IMarshal *iface)
+{
+ return CONTAINING_RECORD(iface, ObjrefMonikerImpl, IMarshal_iface);
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_QueryInterface(IMoniker *iface, REFIID iid, void **obj)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), obj);
+
+ if (!obj)
+ return E_INVALIDARG;
+
+ *obj = 0;
+
+ if (IsEqualIID(iid, &IID_IUnknown) ||
+ IsEqualIID(iid, &IID_IPersist) ||
+ IsEqualIID(iid, &IID_IPersistStream) ||
+ IsEqualIID(iid, &IID_IMoniker) ||
+ IsEqualGUID(iid, &CLSID_ObjrefMoniker) ||
+ IsEqualGUID(iid, &CLSID_PointerMoniker))
+ {
+ *obj = iface;
+ }
+ else if (IsEqualIID(iid, &IID_IMarshal))
+ *obj = &moniker->IMarshal_iface;
+ else
+ return E_NOINTERFACE;
+
+ IMoniker_AddRef(iface);
+
+ return S_OK;
+}
+
+static ULONG WINAPI ObjrefMonikerImpl_AddRef(IMoniker *iface)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+ ULONG refcount = InterlockedIncrement(&moniker->refcount);
+
+ TRACE("%p, refcount %u\n", iface, refcount);
+
+ return refcount;
+}
+
+static ULONG WINAPI ObjrefMonikerImpl_Release(IMoniker *iface)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+ ULONG refcount = InterlockedDecrement(&moniker->refcount);
+
+ TRACE("%p, refcount %u\n", iface, refcount);
+
+ if (!refcount)
+ {
+ if (moniker->pObject) IUnknown_Release(moniker->pObject);
+ heap_free(moniker);
+ }
+
+ return refcount;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetClassID(IMoniker *iface, CLSID *clsid)
+{
+ TRACE("(%p,%p)\n", iface, clsid);
+
+ if (!clsid)
+ return E_POINTER;
+
+ *clsid = CLSID_ObjrefMoniker;
+ return S_OK;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_IsDirty(IMoniker *iface)
+{
+ FIXME("(%p): stub\n", iface);
+ return S_FALSE;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Load(IMoniker *iface, IStream *stream)
+{
+ FIXME("(%p,%p): stub\n", iface, stream);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL dirty)
+{
+ FIXME("(%p,%p,%d): stub\n", iface, stream, dirty);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *size)
+{
+ FIXME("(%p,%p): stub\n", iface, size);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+ REFIID riid, void **result)
+{
+ FIXME("(%p,%p,%p,%s,%p): stub\n", iface, pbc, left, debugstr_guid(riid), result);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+ REFIID riid, void **result)
+{
+ FIXME("(%p,%p,%p,%s,%p): stub\n", iface, pbc, left, debugstr_guid(riid), result);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD howfar,
+ IMoniker **left, IMoniker **reduced)
+{
+ FIXME("(%p,%p,%d,%p,%p): stub\n", iface, pbc, howfar, left, reduced);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_ComposeWith(IMoniker *iface, IMoniker *right,
+ BOOL only_if_not_generic, IMoniker **result)
+{
+ FIXME("(%p,%p,%d,%p): stub\n", iface, right, only_if_not_generic, result);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **enummoniker)
+{
+ TRACE("(%p,%d,%p)\n", iface, forward, enummoniker);
+
+ if (!enummoniker)
+ return E_POINTER;
+
+ *enummoniker = NULL;
+ return S_OK;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
+{
+ FIXME("(%p,%p): stub\n", iface, other);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMoniker(iface);
+
+ TRACE("(%p,%p)\n", iface, hash);
+
+ if (!hash)
+ return E_POINTER;
+
+ *hash = PtrToUlong(moniker->pObject);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *left,
+ IMoniker *running)
+{
+ FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, running);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetTimeOfLastChange(IMoniker *iface,
+ IBindCtx *pbc, IMoniker *left, FILETIME *time)
+{
+ FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, time);
+ return MK_E_UNAVAILABLE;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_Inverse(IMoniker *iface, IMoniker **moniker)
+{
+ FIXME("(%p,%p): stub\n", iface, moniker);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, other, prefix);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_RelativePathTo(IMoniker *iface, IMoniker *other, IMoniker **result)
+{
+ FIXME("(%p,%p,%p): stub\n", iface, other, result);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
+ IMoniker *left, LPOLESTR *name)
+{
+ FIXME("(%p,%p,%p,%p): stub\n", iface, pbc, left, name);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
+ IMoniker *left, LPOLESTR name, ULONG *eaten, IMoniker **out)
+{
+ FIXME("(%p,%p,%p,%p,%p,%p): stub\n", iface, pbc, left, name, eaten, out);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI ObjrefMonikerImpl_IsSystemMoniker(IMoniker *iface, DWORD *mksys)
+{
+ TRACE("(%p,%p)\n", iface, mksys);
+
+ if (!mksys)
+ return E_POINTER;
+
+ *mksys = MKSYS_OBJREFMONIKER;
+ return S_OK;
+}
+
+static const IMonikerVtbl VT_ObjrefMonikerImpl =
+{
+ ObjrefMonikerImpl_QueryInterface,
+ ObjrefMonikerImpl_AddRef,
+ ObjrefMonikerImpl_Release,
+ ObjrefMonikerImpl_GetClassID,
+ ObjrefMonikerImpl_IsDirty,
+ ObjrefMonikerImpl_Load,
+ ObjrefMonikerImpl_Save,
+ ObjrefMonikerImpl_GetSizeMax,
+ ObjrefMonikerImpl_BindToObject,
+ ObjrefMonikerImpl_BindToStorage,
+ ObjrefMonikerImpl_Reduce,
+ ObjrefMonikerImpl_ComposeWith,
+ ObjrefMonikerImpl_Enum,
+ ObjrefMonikerImpl_IsEqual,
+ ObjrefMonikerImpl_Hash,
+ ObjrefMonikerImpl_IsRunning,
+ ObjrefMonikerImpl_GetTimeOfLastChange,
+ ObjrefMonikerImpl_Inverse,
+ ObjrefMonikerImpl_CommonPrefixWith,
+ ObjrefMonikerImpl_RelativePathTo,
+ ObjrefMonikerImpl_GetDisplayName,
+ ObjrefMonikerImpl_ParseDisplayName,
+ ObjrefMonikerImpl_IsSystemMoniker
+};
+
+static HRESULT WINAPI objref_moniker_marshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
+
+ return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
+}
+
+static ULONG WINAPI objref_moniker_marshal_AddRef(IMarshal *iface)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p)\n", iface);
+
+ return IMoniker_AddRef(&moniker->IMoniker_iface);
+}
+
+static ULONG WINAPI objref_moniker_marshal_Release(IMarshal *iface)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p)\n", iface);
+
+ return IMoniker_Release(&moniker->IMoniker_iface);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
+ DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p,%s,%p,%08x,%p,%x,%p)\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
+ mshlflags, clsid);
+
+ return IMoniker_GetClassID(&moniker->IMoniker_iface, clsid);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
+ DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p,%s,%p,%08x,%p,%08x,%p)\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
+ mshlflags, size);
+
+ return CoGetMarshalSizeMax(size, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid,
+ void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+
+ TRACE("(%p,%s,%p,%08x,%p,%08x)\n", stream, debugstr_guid(riid), pv, dwDestContext, pvDestContext, mshlflags);
+
+ return CoMarshalInterface(stream, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
+ REFIID riid, void **ppv)
+{
+ ObjrefMonikerImpl *moniker = objref_impl_from_IMarshal(iface);
+ IUnknown *object;
+ HRESULT hr;
+
+ TRACE("(%p,%p,%s,%p)\n", iface, stream, debugstr_guid(riid), ppv);
+
+ hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void **)&object);
+ if (FAILED(hr))
+ {
+ ERR("Couldn't unmarshal moniker, hr = %#x.\n", hr);
+ return hr;
+ }
+
+ if (moniker->pObject)
+ IUnknown_Release(moniker->pObject);
+ moniker->pObject = object;
+
+ return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
+}
+
+static HRESULT WINAPI objref_moniker_marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
+{
+ TRACE("(%p,%p)\n", iface, stream);
+ return S_OK;
+}
+
+static HRESULT WINAPI objref_moniker_marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
+{
+ TRACE("(%p,%08x)\n", iface, reserved);
+ return S_OK;
+}
+
+static const IMarshalVtbl objref_moniker_marshal_vtbl =
+{
+ objref_moniker_marshal_QueryInterface,
+ objref_moniker_marshal_AddRef,
+ objref_moniker_marshal_Release,
+ objref_moniker_marshal_GetUnmarshalClass,
+ objref_moniker_marshal_GetMarshalSizeMax,
+ objref_moniker_marshal_MarshalInterface,
+ objref_moniker_marshal_UnmarshalInterface,
+ objref_moniker_marshal_ReleaseMarshalData,
+ objref_moniker_marshal_DisconnectObject
+};
+
+/***********************************************************************
+ * CreateObjrefMoniker (OLE32.@)
+ */
+HRESULT WINAPI CreateObjrefMoniker(IUnknown *obj, IMoniker **ret)
+{
+ ObjrefMonikerImpl *moniker;
+
+ TRACE("(%p,%p)\n", obj, ret);
+
+ if (!ret)
+ return E_INVALIDARG;
+
+ moniker = heap_alloc(sizeof(*moniker));
+ if (!moniker)
+ {
+ *ret = NULL;
+ return E_OUTOFMEMORY;
+ }
+
+ moniker->IMoniker_iface.lpVtbl = &VT_ObjrefMonikerImpl;
+ moniker->IMarshal_iface.lpVtbl = &objref_moniker_marshal_vtbl;
+ moniker->refcount = 1;
+ moniker->pObject = obj;
+ if (moniker->pObject)
+ IUnknown_AddRef(moniker->pObject);
+
+ *ret = &moniker->IMoniker_iface;
+
+ return S_OK;
+}
+
+HRESULT WINAPI ObjrefMoniker_CreateInstance(IClassFactory *iface, IUnknown *unk, REFIID iid, void **obj)
+{
+ IMoniker *moniker;
+ HRESULT hr;
+
+ TRACE("(%p,%s,%p)\n", unk, debugstr_guid(iid), obj);
+
+ *obj = NULL;
+
+ if (unk)
+ return CLASS_E_NOAGGREGATION;
+
+ hr = CreateObjrefMoniker(NULL, &moniker);
+ if (FAILED(hr))
+ return hr;
+
+ hr = IMoniker_QueryInterface(moniker, iid, obj);
+ IMoniker_Release(moniker);
+
+ return hr;
+}
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index 8d3276651bc..d2c83c173ba 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -82,9 +82,10 @@ static const CLSID CLSID_TestMoniker =
DEFINE_OLEGUID(CLSID_FileMoniker, 0x303, 0, 0);
DEFINE_OLEGUID(CLSID_ItemMoniker, 0x304, 0, 0);
DEFINE_OLEGUID(CLSID_AntiMoniker, 0x305, 0, 0);
+DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0);
DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0);
-DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
+DEFINE_OLEGUID(CLSID_ObjrefMoniker, 0x327, 0, 0);
#define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__)
#define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__)
@@ -3861,7 +3862,7 @@ todo_wine
hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid);
ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr);
- ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class.\n");
+ ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class %s.\n", wine_dbgstr_guid(&clsid));
hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size);
ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr);
@@ -4076,6 +4077,249 @@ todo_wine
IMoniker_Release(moniker);
}
+static void test_objref_moniker(void)
+{
+ IMoniker *moniker, *moniker2, *prefix, *inverse, *anti;
+ struct test_factory factory;
+ IEnumMoniker *enummoniker;
+ DWORD hash, size;
+ HRESULT hr;
+ IBindCtx *bindctx;
+ FILETIME filetime;
+ IUnknown *unknown;
+ IStream *stream;
+ IROTData *rotdata;
+ LPOLESTR display_name;
+ IMarshal *marshal;
+ LARGE_INTEGER pos;
+ CLSID clsid;
+
+ test_factory_init(&factory);
+
+ hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+ hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker);
+ ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_QueryInterface(moniker, &IID_IMoniker, NULL);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_QueryInterface(moniker, &CLSID_PointerMoniker, (void **)&unknown);
+ ok(unknown == (IUnknown *)moniker, "Unexpected interface\n");
+ IUnknown_Release(unknown);
+
+ hr = IMoniker_QueryInterface(moniker, &CLSID_ObjrefMoniker, (void **)&unknown);
+ ok(unknown == (IUnknown *)moniker, "Unexpected interface\n");
+ IUnknown_Release(unknown);
+
+ hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal);
+ ok(hr == S_OK, "Failed to get interface, hr %#x\n", hr);
+
+ hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid);
+ ok(hr == S_OK, "Failed to get class, hr %#x\n", hr);
+ ok(IsEqualGUID(&clsid, &CLSID_ObjrefMoniker), "Unexpected class %s\n", wine_dbgstr_guid(&clsid));
+
+ hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size);
+ ok(hr == S_OK, "Failed to get marshal size, hr %#x\n", hr);
+ ok(size > 0, "Unexpected size %d\n", size);
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok(hr == S_OK, "Failed to create a stream, hr %#x\n", hr);
+
+ hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok(hr == S_OK, "Failed to marshal moniker, hr %#x\n", hr);
+
+ pos.QuadPart = 0;
+ IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
+ hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker2);
+ ok(hr == S_OK, "Failed to unmarshal, hr %#x\n", hr);
+ hr = IMoniker_IsEqual(moniker, moniker2);
+todo_wine
+ ok(hr == S_OK, "Expected equal moniker, hr %#x\n", hr);
+ IMoniker_Release(moniker2);
+
+ IStream_Release(stream);
+
+ IMarshal_Release(marshal);
+
+ ok(factory.refcount > 1, "Unexpected factory refcount %u\n", factory.refcount);
+
+ /* Display Name */
+
+ hr = CreateBindCtx(0, &bindctx);
+ ok(hr == S_OK, "CreateBindCtx failed: 0x%08x\n", hr);
+
+ hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
+todo_wine
+ ok(hr == S_OK, "IMoniker_GetDisplayName failed: 0x%08x\n", hr);
+
+ IBindCtx_Release(bindctx);
+
+ hr = IMoniker_IsDirty(moniker);
+ ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
+
+ /* IROTData::GetComparisonData test */
+
+ hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
+ ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
+
+ /* Saving */
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok(hr == S_OK, "CreateStreamOnHGlobal failed: 0x%08x\n", hr);
+
+ hr = IMoniker_Save(moniker, stream, TRUE);
+todo_wine
+ ok(hr == S_OK, "IMoniker_Save failed: 0x%08x\n", hr);
+
+ IStream_Release(stream);
+
+ /* Hashing */
+ hr = IMoniker_Hash(moniker, &hash);
+ ok(hr == S_OK, "IMoniker_Hash failed: 0x%08x\n", hr);
+ ok(hash == PtrToUlong(&factory.IClassFactory_iface), "Unexpected hash value %#x\n", hash);
+
+ /* IsSystemMoniker test */
+ TEST_MONIKER_TYPE(moniker, MKSYS_OBJREFMONIKER);
+
+ hr = IMoniker_Inverse(moniker, &inverse);
+todo_wine
+ ok(hr == S_OK, "Failed to get inverse, hr %#x\n", hr);
+if (hr == S_OK)
+{
+ TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
+ IMoniker_Release(inverse);
+}
+
+ hr = CreateBindCtx(0, &bindctx);
+ ok(hr == S_OK, "CreateBindCtx failed: 0x%08x\n", hr);
+
+ /* IsRunning test */
+ hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
+todo_wine
+ ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
+
+ hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
+ ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
+
+ hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
+todo_wine
+ ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr);
+if (hr == S_OK)
+ IUnknown_Release(unknown);
+
+ hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
+todo_wine
+ ok(hr == S_OK, "IMoniker_BindToObject failed: 0x%08x\n", hr);
+if (hr == S_OK)
+ IUnknown_Release(unknown);
+
+ IMoniker_Release(moniker);
+
+todo_wine
+ ok(factory.refcount > 1, "Unexpected factory refcount %u\n", factory.refcount);
+
+ hr = CreateObjrefMoniker(NULL, &moniker);
+ ok(hr == S_OK, "CreateObjrefMoniker failed, hr %#x\n", hr);
+
+ hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
+todo_wine
+ ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
+
+ hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
+todo_wine
+ ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
+
+ IBindCtx_Release(bindctx);
+
+ /* Enum() */
+ enummoniker = (void *)0xdeadbeef;
+ hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
+ ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+ ok(enummoniker == NULL, "got %p\n", enummoniker);
+
+ enummoniker = (void *)0xdeadbeef;
+ hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
+ ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+ ok(enummoniker == NULL, "got %p\n", enummoniker);
+
+ IMoniker_Release(moniker);
+
+ /* CommonPrefixWith() */
+ hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker);
+ ok(hr == S_OK, "CreateObjrefMoniker failed: hr %#x\n", hr);
+
+ hr = CreateObjrefMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker2);
+ ok(hr == S_OK, "CreateObjrefMoniker failed: hr %#x\n", hr);
+
+ hr = IMoniker_IsEqual(moniker, NULL);
+todo_wine
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_IsEqual(moniker, moniker2);
+todo_wine
+ ok(hr == S_OK, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_CommonPrefixWith(moniker, moniker2, NULL);
+todo_wine
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_CommonPrefixWith(moniker, NULL, &prefix);
+todo_wine
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
+todo_wine
+ ok(hr == MK_S_US, "Unexpected hr %#x\n", hr);
+if (hr == S_OK)
+{
+ ok(prefix == moniker, "Unexpected pointer\n");
+ IMoniker_Release(prefix);
+}
+
+ IMoniker_Release(moniker2);
+
+ hr = CreateObjrefMoniker((IUnknown *)moniker, &moniker2);
+ ok(hr == S_OK, "Failed to create moniker, hr %#x\n", hr);
+
+ hr = IMoniker_IsEqual(moniker, moniker2);
+todo_wine
+ ok(hr == S_FALSE, "Unexpected hr %#x\n", hr);
+
+ hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
+todo_wine
+ ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x\n", hr);
+
+ IMoniker_Release(moniker2);
+
+ /* ComposeWith() */
+
+ /* P + A -> () */
+ anti = create_antimoniker(1);
+ hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
+todo_wine
+ ok(hr == S_OK, "Failed to compose, hr %#x\n", hr);
+if (hr == S_OK)
+ ok(!moniker2, "Unexpected pointer\n");
+ IMoniker_Release(anti);
+
+ /* P + A2 -> A */
+ anti = create_antimoniker(2);
+ hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
+todo_wine
+ ok(hr == S_OK, "Failed to compose, hr %#x\n", hr);
+if (hr == S_OK)
+{
+ TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
+ IMoniker_Release(moniker2);
+}
+
+ IMoniker_Release(anti);
+
+ IMoniker_Release(moniker);
+}
+
static void test_bind_context(void)
{
IRunningObjectTable *rot, *rot2;
@@ -4385,6 +4629,7 @@ START_TEST(moniker)
test_anti_moniker();
test_generic_composite_moniker();
test_pointer_moniker();
+ test_objref_moniker();
test_save_load_filemoniker();
test_MonikerCommonPrefixWith();
diff --git a/include/objidl.idl b/include/objidl.idl
index 7576a686aeb..cd11729b292 100644
--- a/include/objidl.idl
+++ b/include/objidl.idl
@@ -330,7 +330,10 @@ interface IMoniker : IPersistStream
MKSYS_ITEMMONIKER = 4,
MKSYS_POINTERMONIKER = 5,
/* MKSYS_URLMONIKER = 6, */ /* defined in urlmon.idl */
- MKSYS_CLASSMONIKER = 7
+ MKSYS_CLASSMONIKER = 7,
+ MKSYS_OBJREFMONIKER = 8,
+ MKSYS_SESSIONMONIKER = 9,
+ MKSYS_LUAMONIKER = 10
} MKSYS;
typedef [v1_enum] enum tagMKREDUCE {
--
2.31.1
2
1
Nov. 26, 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51971
Signed-off-by: Robert Wilhelm <robert.wilhelm(a)gmx.net>
---
dlls/scrrun/filesystem.c | 16 ++++++-
dlls/scrrun/tests/filesystem.c | 82 ++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 2 deletions(-)
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index e55615eb4da..c42a3155c4f 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -2522,9 +2522,21 @@ static HRESULT WINAPI folder_get_Files(IFolder *iface, IFileCollection **files)
static HRESULT WINAPI folder_CreateTextFile(IFolder *iface, BSTR filename, VARIANT_BOOL overwrite,
VARIANT_BOOL unicode, ITextStream **stream)
{
+ DWORD disposition;
+ BSTR path;
+ HRESULT hres;
+
struct folder *This = impl_from_IFolder(iface);
- FIXME("(%p)->(%s %x %x %p): stub\n", This, debugstr_w(filename), overwrite, unicode, stream);
- return E_NOTIMPL;
+
+ TRACE("%p %s %d %d %p\n", iface, debugstr_w(filename), overwrite, unicode, stream);
+
+ hres = build_path(This->path, filename, &path);
+ if (FAILED(hres)) return hres;
+
+ disposition = overwrite == VARIANT_TRUE ? CREATE_ALWAYS : CREATE_NEW;
+ hres = create_textstream(path, disposition, ForWriting, unicode ? TristateTrue : TristateFalse, stream);
+ SysFreeString(path);
+ return hres;
}
static const IFolderVtbl foldervtbl = {
diff --git a/dlls/scrrun/tests/filesystem.c b/dlls/scrrun/tests/filesystem.c
index 5c55965ce88..db93f9a75f3 100644
--- a/dlls/scrrun/tests/filesystem.c
+++ b/dlls/scrrun/tests/filesystem.c
@@ -1535,6 +1535,87 @@ static void test_CreateTextFile(void)
SysFreeString(nameW);
}
+/* shameless copy of test_CreateTextFile(void) */
+static void test_FolderCreateTextFile(void)
+{
+ WCHAR pathW[MAX_PATH], dirW[MAX_PATH], buffW[10];
+ ITextStream *stream;
+ BSTR nameW, str;
+ HANDLE file;
+ IFolder *folder;
+ HRESULT hr;
+ BOOL ret;
+
+ get_temp_filepath(testfileW, pathW, dirW);
+ nameW = SysAllocString(L"foo.txt");
+ lstrcpyW(pathW, dirW);
+ lstrcatW(pathW, nameW);
+
+ ret = CreateDirectoryW(dirW, NULL);
+ ok(ret, "got %d, %d\n", ret, GetLastError());
+
+ str = SysAllocString(dirW);
+ hr = IFileSystem3_GetFolder(fs3, str, &folder);
+ ok(ret, "got %d, %d\n", ret, GetLastError());
+ SysFreeString(str);
+
+ hr = IFolder_CreateTextFile(folder, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ test_provideclassinfo(stream, &CLSID_TextStream);
+
+ hr = ITextStream_Read(stream, 1, &str);
+ ok(hr == CTL_E_BADFILEMODE, "got 0x%08x\n", hr);
+
+ hr = ITextStream_Close(stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = ITextStream_Read(stream, 1, &str);
+ ok(hr == CTL_E_BADFILEMODE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
+
+ hr = ITextStream_Close(stream);
+ ok(hr == S_FALSE || hr == E_VAR_NOT_SET, "got 0x%08x\n", hr);
+
+ ITextStream_Release(stream);
+
+ /* check it's created */
+ file = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ ok(file != INVALID_HANDLE_VALUE, "got %p\n", file);
+ CloseHandle(file);
+
+ /* try to create again with no-overwrite mode */
+ hr = IFolder_CreateTextFile(folder, nameW, VARIANT_FALSE, VARIANT_FALSE, &stream);
+ ok(hr == CTL_E_FILEALREADYEXISTS, "got 0x%08x\n", hr);
+
+ /* now overwrite */
+ hr = IFolder_CreateTextFile(folder, nameW, VARIANT_TRUE, VARIANT_FALSE, &stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ITextStream_Release(stream);
+
+ /* overwrite in Unicode mode, check for BOM */
+ hr = IFolder_CreateTextFile(folder, nameW, VARIANT_TRUE, VARIANT_TRUE, &stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ITextStream_Release(stream);
+
+ /* File was created in Unicode mode, it contains 0xfffe BOM. Opening it in non-Unicode mode
+ treats BOM like a valuable data with appropriate CP_ACP -> WCHAR conversion. */
+ buffW[0] = 0;
+ MultiByteToWideChar(CP_ACP, 0, utf16bom, -1, buffW, ARRAY_SIZE(buffW));
+
+ str = SysAllocString(pathW);
+ hr = IFileSystem3_OpenTextFile(fs3, str, ForReading, VARIANT_FALSE, TristateFalse, &stream);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = ITextStream_ReadAll(stream, &str);
+ ok(hr == S_FALSE || broken(hr == S_OK) /* win2k */, "got 0x%08x\n", hr);
+ ok(!lstrcmpW(str, buffW), "got %s, expected %s\n", wine_dbgstr_w(str), wine_dbgstr_w(buffW));
+ SysFreeString(str);
+ ITextStream_Release(stream);
+
+ DeleteFileW(pathW);
+ RemoveDirectoryW(dirW);
+ SysFreeString(nameW);
+}
+
static void test_WriteLine(void)
{
WCHAR pathW[MAX_PATH], dirW[MAX_PATH];
@@ -2516,6 +2597,7 @@ START_TEST(filesystem)
test_FileCollection();
test_DriveCollection();
test_CreateTextFile();
+ test_FolderCreateTextFile();
test_WriteLine();
test_ReadAll();
test_Read();
--
2.31.1
3
2