Wine-devel
Threads by month
- ----- 2026 -----
- 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
April 2022
- 87 participants
- 938 discussions
21 Apr '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/wineoss.drv/midi.c | 39 --------------------------------------
dlls/wineoss.drv/ossmidi.c | 36 +++++++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+), 39 deletions(-)
diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index aa672e211b9..9615c9892b9 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -663,41 +663,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-/**************************************************************************
- * modPrepare [internal]
- */
-static DWORD modPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
-{
- TRACE("(%04X, %p, %d);\n", wDevID, lpMidiHdr, dwSize);
-
- if (dwSize < offsetof(MIDIHDR,dwOffset) || lpMidiHdr == 0 || lpMidiHdr->lpData == 0)
- return MMSYSERR_INVALPARAM;
- if (lpMidiHdr->dwFlags & MHDR_PREPARED)
- return MMSYSERR_NOERROR;
-
- lpMidiHdr->lpNext = 0;
- lpMidiHdr->dwFlags |= MHDR_PREPARED;
- lpMidiHdr->dwFlags &= ~(MHDR_DONE|MHDR_INQUEUE); /* flags cleared since w2k */
- return MMSYSERR_NOERROR;
-}
-
-/**************************************************************************
- * modUnprepare [internal]
- */
-static DWORD modUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
-{
- TRACE("(%04X, %p, %d);\n", wDevID, lpMidiHdr, dwSize);
-
- if (dwSize < offsetof(MIDIHDR,dwOffset) || lpMidiHdr == 0 || lpMidiHdr->lpData == 0)
- return MMSYSERR_INVALPARAM;
- if (!(lpMidiHdr->dwFlags & MHDR_PREPARED))
- return MMSYSERR_NOERROR;
- if (lpMidiHdr->dwFlags & MHDR_INQUEUE)
- return MIDIERR_STILLPLAYING;
- lpMidiHdr->dwFlags &= ~MHDR_PREPARED;
- return MMSYSERR_NOERROR;
-}
-
/**************************************************************************
* modGetVolume [internal]
*/
@@ -803,10 +768,6 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return OSS_MidiInit();
case DRVM_EXIT:
return OSS_MidiExit();
- case MODM_PREPARE:
- return modPrepare(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
- case MODM_UNPREPARE:
- return modUnprepare(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_GETDEVCAPS:
return modGetDevCaps(wDevID, (LPMIDIOUTCAPSW)dwParam1, dwParam2);
case MODM_GETNUMDEVS:
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
index 7ab78bcbfdd..b97c5159e89 100644
--- a/dlls/wineoss.drv/ossmidi.c
+++ b/dlls/wineoss.drv/ossmidi.c
@@ -1014,6 +1014,36 @@ static UINT midi_out_long_data(WORD dev_id, MIDIHDR *hdr, UINT hdr_size, struct
return MMSYSERR_NOERROR;
}
+static UINT midi_out_prepare(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
+{
+ TRACE("(%04X, %p, %d);\n", dev_id, hdr, hdr_size);
+
+ if (hdr_size < offsetof(MIDIHDR, dwOffset) || !hdr || !hdr->lpData)
+ return MMSYSERR_INVALPARAM;
+ if (hdr->dwFlags & MHDR_PREPARED)
+ return MMSYSERR_NOERROR;
+
+ hdr->lpNext = 0;
+ hdr->dwFlags |= MHDR_PREPARED;
+ hdr->dwFlags &= ~(MHDR_DONE | MHDR_INQUEUE);
+ return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_unprepare(WORD dev_id, MIDIHDR *hdr, UINT hdr_size)
+{
+ TRACE("(%04X, %p, %d);\n", dev_id, hdr, hdr_size);
+
+ if (hdr_size < offsetof(MIDIHDR, dwOffset) || !hdr || !hdr->lpData)
+ return MMSYSERR_INVALPARAM;
+ if (!(hdr->dwFlags & MHDR_PREPARED))
+ return MMSYSERR_NOERROR;
+ if (hdr->dwFlags & MHDR_INQUEUE)
+ return MIDIERR_STILLPLAYING;
+
+ hdr->dwFlags &= ~MHDR_PREPARED;
+ return MMSYSERR_NOERROR;
+}
+
NTSTATUS midi_out_message(void *args)
{
struct midi_out_message_params *params = args;
@@ -1039,6 +1069,12 @@ NTSTATUS midi_out_message(void *args)
case MODM_LONGDATA:
*params->err = midi_out_long_data(params->dev_id, (MIDIHDR *)params->param_1, params->param_2, params->notify);
break;
+ case MODM_PREPARE:
+ *params->err = midi_out_prepare(params->dev_id, (MIDIHDR *)params->param_1, params->param_2);
+ break;
+ case MODM_UNPREPARE:
+ *params->err = midi_out_unprepare(params->dev_id, (MIDIHDR *)params->param_1, params->param_2);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/wineoss.drv/midi.c | 128 -------------------------------------
dlls/wineoss.drv/ossmidi.c | 83 ++++++++++++++++++++++++
2 files changed, 83 insertions(+), 128 deletions(-)
diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index 1751af2349e..aa672e211b9 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -173,16 +173,6 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
wDevID, wMsg, dwParam1, dwParam2);
switch (wMsg) {
- case MOM_DONE:
- case MOM_POSITIONCB:
- if (wDevID > MODM_NumDevs) return;
-
- dwCallBack = MidiOutDev[wDevID].midiDesc.dwCallback;
- uFlags = MidiOutDev[wDevID].wFlags;
- hDev = MidiOutDev[wDevID].midiDesc.hMidi;
- dwInstance = MidiOutDev[wDevID].midiDesc.dwInstance;
- break;
-
case MIM_OPEN:
case MIM_CLOSE:
case MIM_DATA:
@@ -233,40 +223,6 @@ static int midiCloseSeq(int fd)
return 0;
}
-/* FIXME: this is a bad idea, it's even not static... */
-SEQ_DEFINEBUF(1024);
-
-/* FIXME: this is not reentrant, not static - because of global variable
- * _seqbuf and al.
- */
-/**************************************************************************
- * seqbuf_dump [internal]
- *
- * Used by SEQ_DUMPBUF to flush the buffer.
- *
- */
-void seqbuf_dump(void)
-{
- int fd;
-
- /* The device is already open, but there's no way to pass the
- fd to this function. Rather than rely on a global variable
- we pretend to open the seq again. */
- fd = midiOpenSeq();
- if (_seqbufptr) {
- if (write(fd, _seqbuf, _seqbufptr) == -1) {
- WARN("Can't write data to sequencer %d, errno %d (%s)!\n",
- fd, errno, strerror(errno));
- }
- /* FIXME:
- * in any case buffer is lost so that if many errors occur the buffer
- * will not overrun
- */
- _seqbufptr = 0;
- }
- midiCloseSeq(fd);
-}
-
/**************************************************************************
* midReceiveChar [internal]
*/
@@ -707,88 +663,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-/**************************************************************************
- * modLongData [internal]
- */
-static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
-{
- int count;
- LPBYTE lpData;
-
- TRACE("(%04X, %p, %08X);\n", wDevID, lpMidiHdr, dwSize);
-
- /* Note: MS doc does not say much about the dwBytesRecorded member of the MIDIHDR structure
- * but it seems to be used only for midi input.
- * Taking a look at the WAVEHDR structure (which is quite similar) confirms this assumption.
- */
-
- if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
-
- if (MidiOutDev[wDevID].fd == -1) {
- WARN("can't play !\n");
- return MIDIERR_NODEVICE;
- }
-
- lpData = (LPBYTE) lpMidiHdr->lpData;
-
- if (lpData == NULL)
- return MIDIERR_UNPREPARED;
- if (!(lpMidiHdr->dwFlags & MHDR_PREPARED))
- return MIDIERR_UNPREPARED;
- if (lpMidiHdr->dwFlags & MHDR_INQUEUE)
- return MIDIERR_STILLPLAYING;
- lpMidiHdr->dwFlags &= ~MHDR_DONE;
- lpMidiHdr->dwFlags |= MHDR_INQUEUE;
-
- /* FIXME: MS doc is not 100% clear. Will lpData only contain system exclusive
- * data, or can it also contain raw MIDI data, to be split up and sent to
- * modShortData() ?
- * If the latter is true, then the following WARNing will fire up
- */
- if (lpData[0] != 0xF0 || lpData[lpMidiHdr->dwBufferLength - 1] != 0xF7) {
- WARN("The allegedly system exclusive buffer is not correct\n\tPlease report with MIDI file\n");
- }
-
- TRACE("dwBufferLength=%u !\n", lpMidiHdr->dwBufferLength);
- TRACE(" %02X %02X %02X ... %02X %02X %02X\n",
- lpData[0], lpData[1], lpData[2], lpData[lpMidiHdr->dwBufferLength-3],
- lpData[lpMidiHdr->dwBufferLength-2], lpData[lpMidiHdr->dwBufferLength-1]);
-
- switch (MidiOutDev[wDevID].caps.wTechnology) {
- case MOD_FMSYNTH:
- /* FIXME: I don't think there is much to do here */
- break;
- case MOD_MIDIPORT:
- if (lpData[0] != 0xF0) {
- /* Send end of System Exclusive */
- SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF0);
- WARN("Adding missing 0xF0 marker at the beginning of "
- "system exclusive byte stream\n");
- }
- for (count = 0; count < lpMidiHdr->dwBufferLength; count++) {
- SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, lpData[count]);
- }
- if (lpData[count - 1] != 0xF7) {
- /* Send end of System Exclusive */
- SEQ_MIDIOUT(wDevID - MODM_NumFMSynthDevs, 0xF7);
- WARN("Adding missing 0xF7 marker at the end of "
- "system exclusive byte stream\n");
- }
- SEQ_DUMPBUF();
- break;
- default:
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
- }
-
- lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
- lpMidiHdr->dwFlags |= MHDR_DONE;
- MIDI_NotifyClient(wDevID, MOM_DONE, (DWORD_PTR)lpMidiHdr, 0L);
- return MMSYSERR_NOERROR;
-}
-
/**************************************************************************
* modPrepare [internal]
*/
@@ -929,8 +803,6 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return OSS_MidiInit();
case DRVM_EXIT:
return OSS_MidiExit();
- case MODM_LONGDATA:
- return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_PREPARE:
return modPrepare(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_UNPREPARE:
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
index ee83da8bfcd..7ab78bcbfdd 100644
--- a/dlls/wineoss.drv/ossmidi.c
+++ b/dlls/wineoss.drv/ossmidi.c
@@ -934,6 +934,86 @@ static UINT midi_out_data(WORD dev_id, UINT data)
return MMSYSERR_NOTENABLED;
}
+static UINT midi_out_long_data(WORD dev_id, MIDIHDR *hdr, UINT hdr_size, struct notify_context *notify)
+{
+ struct midi_dest *dest;
+ BYTE *data;
+ unsigned int count;
+
+ TRACE("(%04X, %p, %08X);\n", dev_id, hdr, hdr_size);
+
+ /* Note: MS doc does not say much about the dwBytesRecorded member of the MIDIHDR structure
+ * but it seems to be used only for midi input.
+ * Taking a look at the WAVEHDR structure (which is quite similar) confirms this assumption.
+ */
+
+ if (dev_id >= num_dests) return MMSYSERR_BADDEVICEID;
+ dest = dests + dev_id;
+ if (!dest->bEnabled) return MIDIERR_NODEVICE;
+
+ if (dest->fd == -1)
+ {
+ WARN("can't play !\n");
+ return MIDIERR_NODEVICE;
+ }
+
+ data = (BYTE *)hdr->lpData;
+
+ if (data == NULL)
+ return MIDIERR_UNPREPARED;
+ if (!(hdr->dwFlags & MHDR_PREPARED))
+ return MIDIERR_UNPREPARED;
+ if (hdr->dwFlags & MHDR_INQUEUE)
+ return MIDIERR_STILLPLAYING;
+ hdr->dwFlags &= ~MHDR_DONE;
+ hdr->dwFlags |= MHDR_INQUEUE;
+
+ /* FIXME: MS doc is not 100% clear. Will lpData only contain system exclusive
+ * data, or can it also contain raw MIDI data, to be split up and sent to
+ * modShortData() ?
+ * If the latter is true, then the following WARNing will fire up
+ */
+ if (data[0] != 0xF0 || data[hdr->dwBufferLength - 1] != 0xF7)
+ WARN("The allegedly system exclusive buffer is not correct\n\tPlease report with MIDI file\n");
+
+ TRACE("dwBufferLength=%u !\n", hdr->dwBufferLength);
+ TRACE(" %02X %02X %02X ... %02X %02X %02X\n",
+ data[0], data[1], data[2], data[hdr->dwBufferLength - 3],
+ data[hdr->dwBufferLength - 2], data[hdr->dwBufferLength - 1]);
+
+ switch (dest->caps.wTechnology)
+ {
+ case MOD_FMSYNTH:
+ /* FIXME: I don't think there is much to do here */
+ break;
+ case MOD_MIDIPORT:
+ if (data[0] != 0xF0)
+ {
+ /* Send end of System Exclusive */
+ SEQ_MIDIOUT(dev_id - num_synths, 0xF0);
+ WARN("Adding missing 0xF0 marker at the beginning of system exclusive byte stream\n");
+ }
+ for (count = 0; count < hdr->dwBufferLength; count++)
+ SEQ_MIDIOUT(dev_id - num_synths, data[count]);
+ if (data[count - 1] != 0xF7)
+ {
+ /* Send end of System Exclusive */
+ SEQ_MIDIOUT(dev_id - num_synths, 0xF7);
+ WARN("Adding missing 0xF7 marker at the end of system exclusive byte stream\n");
+ }
+ SEQ_DUMPBUF();
+ break;
+ default:
+ WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ hdr->dwFlags &= ~MHDR_INQUEUE;
+ hdr->dwFlags |= MHDR_DONE;
+ set_out_notify(notify, dest, dev_id, MOM_DONE, (UINT_PTR)hdr, 0);
+ return MMSYSERR_NOERROR;
+}
+
NTSTATUS midi_out_message(void *args)
{
struct midi_out_message_params *params = args;
@@ -956,6 +1036,9 @@ NTSTATUS midi_out_message(void *args)
case MODM_DATA:
*params->err = midi_out_data(params->dev_id, params->param_1);
break;
+ case MODM_LONGDATA:
+ *params->err = midi_out_long_data(params->dev_id, (MIDIHDR *)params->param_1, params->param_2, params->notify);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
--
2.25.1
2
1
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/wineoss.drv/midi.c | 338 +------------------------------------
dlls/wineoss.drv/oss.c | 1 -
dlls/wineoss.drv/ossmidi.c | 301 ++++++++++++++++++++++++++++++++-
dlls/wineoss.drv/unixlib.h | 9 -
4 files changed, 301 insertions(+), 348 deletions(-)
diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index 70bc4b7b9bd..1751af2349e 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -692,46 +692,6 @@ static DWORD midStop(WORD wDevID)
/*-----------------------------------------------------------------------*/
-typedef struct sVoice {
- int note; /* 0 means not used */
- int channel;
- unsigned cntMark : 30,
- status : 2;
-#define sVS_UNUSED 0
-#define sVS_PLAYING 1
-#define sVS_SUSTAINED 2
-} sVoice;
-
-typedef struct sChannel {
- int program;
-
- int bender;
- int benderRange;
- /* controllers */
- int bank; /* CTL_BANK_SELECT */
- int volume; /* CTL_MAIN_VOLUME */
- int balance; /* CTL_BALANCE */
- int expression; /* CTL_EXPRESSION */
- int sustain; /* CTL_SUSTAIN */
-
- unsigned char nrgPmtMSB; /* Non register Parameters */
- unsigned char nrgPmtLSB;
- unsigned char regPmtMSB; /* Non register Parameters */
- unsigned char regPmtLSB;
-} sChannel;
-
-typedef struct sFMextra {
- unsigned counter;
- int drumSetMask;
- sChannel channel[16]; /* MIDI has only 16 channels */
- sVoice voice[1]; /* dyn allocated according to sound card */
- /* do not append fields below voice[1] since the size of this structure
- * depends on the number of available voices on the FM synth...
- */
-} sFMextra;
-
-#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
-
/**************************************************************************
* modGetDevCaps [internal]
*/
@@ -747,295 +707,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-static UINT midi_out_fm_data(WORD dev_id, UINT data)
-{
- struct midi_dest *dest = MidiOutDev + dev_id;
- WORD evt = LOBYTE(LOWORD(data));
- WORD d1 = HIBYTE(LOWORD(data));
- WORD d2 = LOBYTE(HIWORD(data));
- sFMextra *extra = dest->lpExtra;
- sVoice *voice = extra->voice;
- sChannel *channel = extra->channel;
- int chn = (evt & 0x0F), i, nv;
-
- /* FIXME: chorus depth controller is not used */
-
- switch (evt & 0xF0)
- {
- case MIDI_NOTEOFF:
- for (i = 0; i < dest->caps.wVoices; i++)
- {
- /* don't stop sustained notes */
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
- {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(dev_id, i, d1, d2);
- }
- }
- break;
- case MIDI_NOTEON:
- if (d2 == 0) /* note off if velocity == 0 */
- {
- for (i = 0; i < dest->caps.wVoices; i++) /* don't stop sustained notes */
- {
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
- {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(dev_id, i, d1, 64);
- }
- }
- break;
- }
- /* finding out in this order :
- * - an empty voice
- * - if replaying the same note on the same channel
- * - the older voice (LRU)
- */
- for (i = nv = 0; i < dest->caps.wVoices; i++)
- {
- if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
- {
- nv = i;
- break;
- }
- if (voice[i].cntMark < voice[0].cntMark)
- nv = i;
- }
- TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
- nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
-
- SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
- (128 + d1) : channel[chn].program);
- SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
- SEQ_BENDER(dev_id, nv, channel[chn].bender);
- SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
- SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
- SEQ_START_NOTE(dev_id, nv, d1, d2);
- voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
- voice[nv].note = d1;
- voice[nv].channel = chn;
- voice[nv].cntMark = extra->counter++;
- break;
- case MIDI_KEY_PRESSURE:
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
- SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
- break;
- case MIDI_CTL_CHANGE:
- switch (d1)
- {
- case CTL_BANK_SELECT: channel[chn].bank = d2; break;
- case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
- case CTL_PAN: channel[chn].balance = d2; break;
- case CTL_EXPRESSION: channel[chn].expression = d2; break;
- case CTL_SUSTAIN: channel[chn].sustain = d2;
- if (d2)
- {
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
- voice[i].status = sVS_SUSTAINED;
- }
- else
- {
- for (i = 0; i < dest->caps.wVoices; i++)
- {
- if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
- {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
- }
- }
- }
- break;
- case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
- case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
- case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
- case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
- case CTL_DATA_ENTRY:
- switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
- {
- case 0x0000:
- if (channel[chn].benderRange != d2)
- {
- channel[chn].benderRange = d2;
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].channel == chn)
- SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
- }
- break;
-
- case 0x7F7F:
- channel[chn].benderRange = 2;
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].channel == chn)
- SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
- break;
- default:
- TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
- channel[chn].regPmtMSB, channel[chn].regPmtLSB,
- channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
- break;
- }
- break;
-
- case 0x78: /* all sounds off */
- /* FIXME: I don't know if I have to take care of the channel for this control? */
- for (i = 0; i < dest->caps.wVoices; i++)
- {
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
- {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
- }
- }
- break;
- case 0x7B: /* all notes off */
- /* FIXME: I don't know if I have to take care of the channel for this control? */
- for (i = 0; i < dest->caps.wVoices; i++)
- {
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
- {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
- }
- }
- break;
- default:
- TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
- break;
- }
- break;
- case MIDI_PGM_CHANGE:
- channel[chn].program = d1;
- break;
- case MIDI_CHN_PRESSURE:
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
- SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
-
- break;
- case MIDI_PITCH_BEND:
- channel[chn].bender = (d2 << 7) + d1;
- for (i = 0; i < dest->caps.wVoices; i++)
- if (voice[i].channel == chn)
- SEQ_BENDER(dev_id, i, channel[chn].bender);
- break;
- case MIDI_SYSTEM_PREFIX:
- switch (evt & 0x0F)
- {
- case 0x0F: /* Reset */
- OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)dev_id);
- break;
- default:
- WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
- }
- break;
- default:
- WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
- return MMSYSERR_NOTENABLED;
- }
-
- SEQ_DUMPBUF();
- return MMSYSERR_NOERROR;
-}
-
-static UINT midi_out_port_data(WORD dev_id, UINT data)
-{
- WORD evt = LOBYTE(LOWORD(data));
- WORD d1 = HIBYTE(LOWORD(data));
- WORD d2 = LOBYTE(HIWORD(data));
- int dev = dev_id - MODM_NumFMSynthDevs;
-
- if (dev < 0)
- {
- WARN("Internal error on devID (%u) !\n", dev_id);
- return MIDIERR_NODEVICE;
- }
-
- switch (evt & 0xF0)
- {
- case MIDI_NOTEOFF:
- case MIDI_NOTEON:
- case MIDI_KEY_PRESSURE:
- case MIDI_CTL_CHANGE:
- case MIDI_PITCH_BEND:
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- SEQ_MIDIOUT(dev, d2);
- break;
- case MIDI_PGM_CHANGE:
- case MIDI_CHN_PRESSURE:
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- break;
- case MIDI_SYSTEM_PREFIX:
- switch (evt & 0x0F)
- {
- case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
- case 0x04: /* Undefined. */
- case 0x05: /* Undefined. */
- case 0x07: /* End of Exclusive. */
- case 0x09: /* Undefined. */
- case 0x0D: /* Undefined. */
- break;
- case 0x06: /* Tune Request */
- case 0x08: /* Timing Clock. */
- case 0x0A: /* Start. */
- case 0x0B: /* Continue */
- case 0x0C: /* Stop */
- case 0x0E: /* Active Sensing. */
- SEQ_MIDIOUT(dev, evt);
- break;
- case 0x0F: /* Reset */
- SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
- SEQ_MIDIOUT(dev, 0x7e);
- SEQ_MIDIOUT(dev, 0x7f);
- SEQ_MIDIOUT(dev, 0x09);
- SEQ_MIDIOUT(dev, 0x01);
- SEQ_MIDIOUT(dev, 0xf7);
- break;
- case 0x01: /* MTC Quarter frame */
- case 0x03: /* Song Select. */
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- case 0x02: /* Song Position Pointer. */
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- SEQ_MIDIOUT(dev, d2);
- }
- break;
- }
-
- SEQ_DUMPBUF();
- return MMSYSERR_NOERROR;
-}
-
-/**************************************************************************
- * modData [internal]
- */
-static DWORD modData(WORD wDevID, DWORD dwParam)
-{
- TRACE("(%04X, %08X);\n", wDevID, dwParam);
-
- if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
- if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
-
- if (MidiOutDev[wDevID].fd == -1) {
- WARN("can't play !\n");
- return MIDIERR_NODEVICE;
- }
- switch (MidiOutDev[wDevID].caps.wTechnology) {
- case MOD_FMSYNTH:
- return midi_out_fm_data(wDevID, dwParam);
- case MOD_MIDIPORT:
- return midi_out_port_data(wDevID, dwParam);
- }
-
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
-}
-
/**************************************************************************
* modLongData [internal]
*/
@@ -1164,6 +835,9 @@ static DWORD modGetVolume(WORD wDevID, DWORD* lpdwVolume)
return (MidiOutDev[wDevID].caps.dwSupport & MIDICAPS_VOLUME) ? 0 : MMSYSERR_NOTSUPPORTED;
}
+DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
+ DWORD_PTR dwParam1, DWORD_PTR dwParam2);
+
/**************************************************************************
* modReset [internal]
*/
@@ -1182,9 +856,9 @@ static DWORD modReset(WORD wDevID)
*/
for (chn = 0; chn < 16; chn++) {
/* turn off every note */
- modData(wDevID, 0x7800 | MIDI_CTL_CHANGE | chn);
+ OSS_modMessage(wDevID, MODM_DATA, 0, 0x7800 | MIDI_CTL_CHANGE | chn, 0);
/* remove sustain on all channels */
- modData(wDevID, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn);
+ OSS_modMessage(wDevID, MODM_DATA, 0, (CTL_SUSTAIN << 8) | MIDI_CTL_CHANGE | chn, 0);
}
/* FIXME: the LongData buffers must also be returned to the app */
return MMSYSERR_NOERROR;
@@ -1255,8 +929,6 @@ DWORD WINAPI OSS_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return OSS_MidiInit();
case DRVM_EXIT:
return OSS_MidiExit();
- case MODM_DATA:
- return modData(wDevID, dwParam1);
case MODM_LONGDATA:
return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
case MODM_PREPARE:
diff --git a/dlls/wineoss.drv/oss.c b/dlls/wineoss.drv/oss.c
index 1bd5ddb5762..db2f705a0c5 100644
--- a/dlls/wineoss.drv/oss.c
+++ b/dlls/wineoss.drv/oss.c
@@ -1409,5 +1409,4 @@ unixlib_entry_t __wine_unix_call_funcs[] =
midi_out_message,
midi_seq_open,
- midi_out_fm_reset,
};
diff --git a/dlls/wineoss.drv/ossmidi.c b/dlls/wineoss.drv/ossmidi.c
index 613b070fde5..ee83da8bfcd 100644
--- a/dlls/wineoss.drv/ossmidi.c
+++ b/dlls/wineoss.drv/ossmidi.c
@@ -93,6 +93,8 @@ typedef struct sFMextra
*/
} sFMextra;
+#define IS_DRUM_CHANNEL(_xtra, _chn) ((_xtra)->drumSetMask & (1 << (_chn)))
+
WINE_DEFAULT_DEBUG_CHANNEL(midi);
static int oss_to_win_device_type(int type)
@@ -458,9 +460,8 @@ static int midi_out_fm_load(WORD dev_id, int fd)
return 0;
}
-NTSTATUS midi_out_fm_reset(void *args)
+static void midi_out_fm_reset(WORD dev_id)
{
- WORD dev_id = (WORD)(UINT_PTR)args;
struct midi_dest *dest = dests + dev_id;
sFMextra *extra = dest->lpExtra;
sVoice *voice = extra->voice;
@@ -492,8 +493,6 @@ NTSTATUS midi_out_fm_reset(void *args)
extra->counter = 0;
extra->drumSetMask = 1 << 9; /* channel 10 is normally drums, sometimes 16 also */
SEQ_DUMPBUF();
-
- return STATUS_SUCCESS;
}
static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg,
@@ -572,7 +571,7 @@ static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, stru
free(extra);
return MMSYSERR_ERROR;
}
- midi_out_fm_reset((void *)(UINT_PTR)dev_id);
+ midi_out_fm_reset(dev_id);
break;
}
case MOD_MIDIPORT:
@@ -645,6 +644,295 @@ static UINT midi_out_close(WORD dev_id, struct notify_context *notify)
return MMSYSERR_NOERROR;
}
+static UINT midi_out_fm_data(WORD dev_id, UINT data)
+{
+ struct midi_dest *dest = dests + dev_id;
+ WORD evt = LOBYTE(LOWORD(data));
+ WORD d1 = HIBYTE(LOWORD(data));
+ WORD d2 = LOBYTE(HIWORD(data));
+ sFMextra *extra = dest->lpExtra;
+ sVoice *voice = extra->voice;
+ sChannel *channel = extra->channel;
+ int chn = (evt & 0x0F), i, nv;
+
+ /* FIXME: chorus depth controller is not used */
+
+ switch (evt & 0xF0)
+ {
+ case MIDI_NOTEOFF:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ /* don't stop sustained notes */
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, d1, d2);
+ }
+ }
+ break;
+ case MIDI_NOTEON:
+ if (d2 == 0) /* note off if velocity == 0 */
+ {
+ for (i = 0; i < dest->caps.wVoices; i++) /* don't stop sustained notes */
+ {
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, d1, 64);
+ }
+ }
+ break;
+ }
+ /* finding out in this order :
+ * - an empty voice
+ * - if replaying the same note on the same channel
+ * - the older voice (LRU)
+ */
+ for (i = nv = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
+ {
+ nv = i;
+ break;
+ }
+ if (voice[i].cntMark < voice[0].cntMark)
+ nv = i;
+ }
+ TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
+ nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
+
+ SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
+ (128 + d1) : channel[chn].program);
+ SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
+ SEQ_BENDER(dev_id, nv, channel[chn].bender);
+ SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
+ SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
+ SEQ_START_NOTE(dev_id, nv, d1, d2);
+ voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
+ voice[nv].note = d1;
+ voice[nv].channel = chn;
+ voice[nv].cntMark = extra->counter++;
+ break;
+ case MIDI_KEY_PRESSURE:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
+ SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
+ break;
+ case MIDI_CTL_CHANGE:
+ switch (d1)
+ {
+ case CTL_BANK_SELECT: channel[chn].bank = d2; break;
+ case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
+ case CTL_PAN: channel[chn].balance = d2; break;
+ case CTL_EXPRESSION: channel[chn].expression = d2; break;
+ case CTL_SUSTAIN: channel[chn].sustain = d2;
+ if (d2)
+ {
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+ voice[i].status = sVS_SUSTAINED;
+ }
+ else
+ {
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ }
+ break;
+ case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
+ case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
+ case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
+ case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
+ case CTL_DATA_ENTRY:
+ switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
+ {
+ case 0x0000:
+ if (channel[chn].benderRange != d2)
+ {
+ channel[chn].benderRange = d2;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+ }
+ break;
+
+ case 0x7F7F:
+ channel[chn].benderRange = 2;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+ break;
+ default:
+ TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
+ channel[chn].regPmtMSB, channel[chn].regPmtLSB,
+ channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
+ break;
+ }
+ break;
+
+ case 0x78: /* all sounds off */
+ /* FIXME: I don't know if I have to take care of the channel for this control? */
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ break;
+ case 0x7B: /* all notes off */
+ /* FIXME: I don't know if I have to take care of the channel for this control? */
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ break;
+ default:
+ TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
+ break;
+ }
+ break;
+ case MIDI_PGM_CHANGE:
+ channel[chn].program = d1;
+ break;
+ case MIDI_CHN_PRESSURE:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+ SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
+
+ break;
+ case MIDI_PITCH_BEND:
+ channel[chn].bender = (d2 << 7) + d1;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER(dev_id, i, channel[chn].bender);
+ break;
+ case MIDI_SYSTEM_PREFIX:
+ switch (evt & 0x0F)
+ {
+ case 0x0F: /* Reset */
+ midi_out_fm_reset(dev_id);
+ break;
+ default:
+ WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
+ }
+ break;
+ default:
+ WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ SEQ_DUMPBUF();
+ return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_port_data(WORD dev_id, UINT data)
+{
+ WORD evt = LOBYTE(LOWORD(data));
+ WORD d1 = HIBYTE(LOWORD(data));
+ WORD d2 = LOBYTE(HIWORD(data));
+ int dev = dev_id - num_synths;
+
+ if (dev < 0)
+ {
+ WARN("Internal error on devID (%u) !\n", dev_id);
+ return MIDIERR_NODEVICE;
+ }
+
+ switch (evt & 0xF0)
+ {
+ case MIDI_NOTEOFF:
+ case MIDI_NOTEON:
+ case MIDI_KEY_PRESSURE:
+ case MIDI_CTL_CHANGE:
+ case MIDI_PITCH_BEND:
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ SEQ_MIDIOUT(dev, d2);
+ break;
+ case MIDI_PGM_CHANGE:
+ case MIDI_CHN_PRESSURE:
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ break;
+ case MIDI_SYSTEM_PREFIX:
+ switch (evt & 0x0F)
+ {
+ case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
+ case 0x04: /* Undefined. */
+ case 0x05: /* Undefined. */
+ case 0x07: /* End of Exclusive. */
+ case 0x09: /* Undefined. */
+ case 0x0D: /* Undefined. */
+ break;
+ case 0x06: /* Tune Request */
+ case 0x08: /* Timing Clock. */
+ case 0x0A: /* Start. */
+ case 0x0B: /* Continue */
+ case 0x0C: /* Stop */
+ case 0x0E: /* Active Sensing. */
+ SEQ_MIDIOUT(dev, evt);
+ break;
+ case 0x0F: /* Reset */
+ SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
+ SEQ_MIDIOUT(dev, 0x7e);
+ SEQ_MIDIOUT(dev, 0x7f);
+ SEQ_MIDIOUT(dev, 0x09);
+ SEQ_MIDIOUT(dev, 0x01);
+ SEQ_MIDIOUT(dev, 0xf7);
+ break;
+ case 0x01: /* MTC Quarter frame */
+ case 0x03: /* Song Select. */
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ case 0x02: /* Song Position Pointer. */
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ SEQ_MIDIOUT(dev, d2);
+ }
+ break;
+ }
+
+ SEQ_DUMPBUF();
+ return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_data(WORD dev_id, UINT data)
+{
+ struct midi_dest *dest;
+
+ TRACE("(%04X, %08X);\n", dev_id, data);
+
+ if (dev_id >= num_dests) return MMSYSERR_BADDEVICEID;
+ dest = dests + dev_id;
+ if (!dest->bEnabled) return MIDIERR_NODEVICE;
+
+ if (dest->fd == -1)
+ {
+ WARN("can't play !\n");
+ return MIDIERR_NODEVICE;
+ }
+ switch (dest->caps.wTechnology)
+ {
+ case MOD_FMSYNTH:
+ return midi_out_fm_data(dev_id, data);
+ case MOD_MIDIPORT:
+ return midi_out_port_data(dev_id, data);
+ }
+
+ WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
+}
NTSTATUS midi_out_message(void *args)
{
@@ -665,6 +953,9 @@ NTSTATUS midi_out_message(void *args)
case MODM_CLOSE:
*params->err = midi_out_close(params->dev_id, params->notify);
break;
+ case MODM_DATA:
+ *params->err = midi_out_data(params->dev_id, params->param_1);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
diff --git a/dlls/wineoss.drv/unixlib.h b/dlls/wineoss.drv/unixlib.h
index 75506d445bc..d56e11b8d23 100644
--- a/dlls/wineoss.drv/unixlib.h
+++ b/dlls/wineoss.drv/unixlib.h
@@ -276,13 +276,6 @@ struct midi_seq_open_params
int fd;
};
-struct midi_out_fm_load_params
-{
- WORD dev_id;
- int fd;
- int ret;
-};
-
enum oss_funcs
{
oss_test_connect,
@@ -312,13 +305,11 @@ enum oss_funcs
oss_midi_out_message,
oss_midi_seq_open, /* temporary */
- oss_midi_out_fm_reset,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
-NTSTATUS midi_out_fm_reset(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t oss_handle;
--
2.25.1
2
1
[PATCH 1/4] wineoss: Use separate functions to handle MODM_DATA for FM synths and ports.
by Huw Davies 21 Apr '22
by Huw Davies 21 Apr '22
21 Apr '22
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/wineoss.drv/midi.c | 538 ++++++++++++++++++++--------------------
1 file changed, 268 insertions(+), 270 deletions(-)
diff --git a/dlls/wineoss.drv/midi.c b/dlls/wineoss.drv/midi.c
index d66e926655d..70bc4b7b9bd 100644
--- a/dlls/wineoss.drv/midi.c
+++ b/dlls/wineoss.drv/midi.c
@@ -747,15 +747,274 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
+static UINT midi_out_fm_data(WORD dev_id, UINT data)
+{
+ struct midi_dest *dest = MidiOutDev + dev_id;
+ WORD evt = LOBYTE(LOWORD(data));
+ WORD d1 = HIBYTE(LOWORD(data));
+ WORD d2 = LOBYTE(HIWORD(data));
+ sFMextra *extra = dest->lpExtra;
+ sVoice *voice = extra->voice;
+ sChannel *channel = extra->channel;
+ int chn = (evt & 0x0F), i, nv;
+
+ /* FIXME: chorus depth controller is not used */
+
+ switch (evt & 0xF0)
+ {
+ case MIDI_NOTEOFF:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ /* don't stop sustained notes */
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, d1, d2);
+ }
+ }
+ break;
+ case MIDI_NOTEON:
+ if (d2 == 0) /* note off if velocity == 0 */
+ {
+ for (i = 0; i < dest->caps.wVoices; i++) /* don't stop sustained notes */
+ {
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, d1, 64);
+ }
+ }
+ break;
+ }
+ /* finding out in this order :
+ * - an empty voice
+ * - if replaying the same note on the same channel
+ * - the older voice (LRU)
+ */
+ for (i = nv = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_UNUSED || (voice[i].note == d1 && voice[i].channel == chn))
+ {
+ nv = i;
+ break;
+ }
+ if (voice[i].cntMark < voice[0].cntMark)
+ nv = i;
+ }
+ TRACE("playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, bender=0x%02X, note=0x%02X, vel=0x%02X\n",
+ nv, channel[chn].program, channel[chn].balance, channel[chn].volume, channel[chn].bender, d1, d2);
+
+ SEQ_SET_PATCH(dev_id, nv, IS_DRUM_CHANNEL(extra, chn) ?
+ (128 + d1) : channel[chn].program);
+ SEQ_BENDER_RANGE(dev_id, nv, channel[chn].benderRange * 100);
+ SEQ_BENDER(dev_id, nv, channel[chn].bender);
+ SEQ_CONTROL(dev_id, nv, CTL_PAN, channel[chn].balance);
+ SEQ_CONTROL(dev_id, nv, CTL_EXPRESSION, channel[chn].expression);
+ SEQ_START_NOTE(dev_id, nv, d1, d2);
+ voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
+ voice[nv].note = d1;
+ voice[nv].channel = chn;
+ voice[nv].cntMark = extra->counter++;
+ break;
+ case MIDI_KEY_PRESSURE:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1)
+ SEQ_KEY_PRESSURE(dev_id, i, d1, d2);
+ break;
+ case MIDI_CTL_CHANGE:
+ switch (d1)
+ {
+ case CTL_BANK_SELECT: channel[chn].bank = d2; break;
+ case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
+ case CTL_PAN: channel[chn].balance = d2; break;
+ case CTL_EXPRESSION: channel[chn].expression = d2; break;
+ case CTL_SUSTAIN: channel[chn].sustain = d2;
+ if (d2)
+ {
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+ voice[i].status = sVS_SUSTAINED;
+ }
+ else
+ {
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ }
+ break;
+ case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
+ case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
+ case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
+ case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
+ case CTL_DATA_ENTRY:
+ switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB)
+ {
+ case 0x0000:
+ if (channel[chn].benderRange != d2)
+ {
+ channel[chn].benderRange = d2;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+ }
+ break;
+
+ case 0x7F7F:
+ channel[chn].benderRange = 2;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER_RANGE(dev_id, i, channel[chn].benderRange);
+ break;
+ default:
+ TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
+ channel[chn].regPmtMSB, channel[chn].regPmtLSB,
+ channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB, d2);
+ break;
+ }
+ break;
+
+ case 0x78: /* all sounds off */
+ /* FIXME: I don't know if I have to take care of the channel for this control? */
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ break;
+ case 0x7B: /* all notes off */
+ /* FIXME: I don't know if I have to take care of the channel for this control? */
+ for (i = 0; i < dest->caps.wVoices; i++)
+ {
+ if (voice[i].status == sVS_PLAYING && voice[i].channel == chn)
+ {
+ voice[i].status = sVS_UNUSED;
+ SEQ_STOP_NOTE(dev_id, i, voice[i].note, 64);
+ }
+ }
+ break;
+ default:
+ TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n", d1, d2, chn);
+ break;
+ }
+ break;
+ case MIDI_PGM_CHANGE:
+ channel[chn].program = d1;
+ break;
+ case MIDI_CHN_PRESSURE:
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].status != sVS_UNUSED && voice[i].channel == chn)
+ SEQ_KEY_PRESSURE(dev_id, i, voice[i].note, d1);
+
+ break;
+ case MIDI_PITCH_BEND:
+ channel[chn].bender = (d2 << 7) + d1;
+ for (i = 0; i < dest->caps.wVoices; i++)
+ if (voice[i].channel == chn)
+ SEQ_BENDER(dev_id, i, channel[chn].bender);
+ break;
+ case MIDI_SYSTEM_PREFIX:
+ switch (evt & 0x0F)
+ {
+ case 0x0F: /* Reset */
+ OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)dev_id);
+ break;
+ default:
+ WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
+ }
+ break;
+ default:
+ WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ SEQ_DUMPBUF();
+ return MMSYSERR_NOERROR;
+}
+
+static UINT midi_out_port_data(WORD dev_id, UINT data)
+{
+ WORD evt = LOBYTE(LOWORD(data));
+ WORD d1 = HIBYTE(LOWORD(data));
+ WORD d2 = LOBYTE(HIWORD(data));
+ int dev = dev_id - MODM_NumFMSynthDevs;
+
+ if (dev < 0)
+ {
+ WARN("Internal error on devID (%u) !\n", dev_id);
+ return MIDIERR_NODEVICE;
+ }
+
+ switch (evt & 0xF0)
+ {
+ case MIDI_NOTEOFF:
+ case MIDI_NOTEON:
+ case MIDI_KEY_PRESSURE:
+ case MIDI_CTL_CHANGE:
+ case MIDI_PITCH_BEND:
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ SEQ_MIDIOUT(dev, d2);
+ break;
+ case MIDI_PGM_CHANGE:
+ case MIDI_CHN_PRESSURE:
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ break;
+ case MIDI_SYSTEM_PREFIX:
+ switch (evt & 0x0F)
+ {
+ case 0x00: /* System Exclusive, don't do it on MODM_DATA, should require MODM_LONGDATA */
+ case 0x04: /* Undefined. */
+ case 0x05: /* Undefined. */
+ case 0x07: /* End of Exclusive. */
+ case 0x09: /* Undefined. */
+ case 0x0D: /* Undefined. */
+ break;
+ case 0x06: /* Tune Request */
+ case 0x08: /* Timing Clock. */
+ case 0x0A: /* Start. */
+ case 0x0B: /* Continue */
+ case 0x0C: /* Stop */
+ case 0x0E: /* Active Sensing. */
+ SEQ_MIDIOUT(dev, evt);
+ break;
+ case 0x0F: /* Reset */
+ SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
+ SEQ_MIDIOUT(dev, 0x7e);
+ SEQ_MIDIOUT(dev, 0x7f);
+ SEQ_MIDIOUT(dev, 0x09);
+ SEQ_MIDIOUT(dev, 0x01);
+ SEQ_MIDIOUT(dev, 0xf7);
+ break;
+ case 0x01: /* MTC Quarter frame */
+ case 0x03: /* Song Select. */
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ case 0x02: /* Song Position Pointer. */
+ SEQ_MIDIOUT(dev, evt);
+ SEQ_MIDIOUT(dev, d1);
+ SEQ_MIDIOUT(dev, d2);
+ }
+ break;
+ }
+
+ SEQ_DUMPBUF();
+ return MMSYSERR_NOERROR;
+}
+
/**************************************************************************
* modData [internal]
*/
static DWORD modData(WORD wDevID, DWORD dwParam)
{
- WORD evt = LOBYTE(LOWORD(dwParam));
- WORD d1 = HIBYTE(LOWORD(dwParam));
- WORD d2 = LOBYTE(HIWORD(dwParam));
-
TRACE("(%04X, %08X);\n", wDevID, dwParam);
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
@@ -767,275 +1026,14 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
}
switch (MidiOutDev[wDevID].caps.wTechnology) {
case MOD_FMSYNTH:
- /* FIXME:
- * - chorus depth controller is not used
- */
- {
- sFMextra* extra = MidiOutDev[wDevID].lpExtra;
- sVoice* voice = extra->voice;
- sChannel* channel = extra->channel;
- int chn = (evt & 0x0F);
- int i, nv;
-
- switch (evt & 0xF0) {
- case MIDI_NOTEOFF:
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- /* don't stop sustained notes */
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(wDevID, i, d1, d2);
- }
- }
- break;
- case MIDI_NOTEON:
- if (d2 == 0) { /* note off if velocity == 0 */
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- /* don't stop sustained notes */
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn && voice[i].note == d1) {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(wDevID, i, d1, 64);
- }
- }
- break;
- }
- /* finding out in this order :
- * - an empty voice
- * - if replaying the same note on the same channel
- * - the older voice (LRU)
- */
- for (i = nv = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status == sVS_UNUSED ||
- (voice[i].note == d1 && voice[i].channel == chn)) {
- nv = i;
- break;
- }
- if (voice[i].cntMark < voice[0].cntMark) {
- nv = i;
- }
- }
- TRACE(
- "playing on voice=%d, pgm=%d, pan=0x%02X, vol=0x%02X, "
- "bender=0x%02X, note=0x%02X, vel=0x%02X\n",
- nv, channel[chn].program,
- channel[chn].balance,
- channel[chn].volume,
- channel[chn].bender, d1, d2);
-
- SEQ_SET_PATCH(wDevID, nv, IS_DRUM_CHANNEL(extra, chn) ?
- (128 + d1) : channel[chn].program);
- SEQ_BENDER_RANGE(wDevID, nv, channel[chn].benderRange * 100);
- SEQ_BENDER(wDevID, nv, channel[chn].bender);
- SEQ_CONTROL(wDevID, nv, CTL_PAN, channel[chn].balance);
- SEQ_CONTROL(wDevID, nv, CTL_EXPRESSION, channel[chn].expression);
-#if 0
- /* FIXME: does not really seem to work on my SB card and
- * screws everything up... so lay it down
- */
- SEQ_CONTROL(wDevID, nv, CTL_MAIN_VOLUME, channel[chn].volume);
-#endif
- SEQ_START_NOTE(wDevID, nv, d1, d2);
- voice[nv].status = channel[chn].sustain ? sVS_SUSTAINED : sVS_PLAYING;
- voice[nv].note = d1;
- voice[nv].channel = chn;
- voice[nv].cntMark = extra->counter++;
- break;
- case MIDI_KEY_PRESSURE:
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn && voice[i].note == d1) {
- SEQ_KEY_PRESSURE(wDevID, i, d1, d2);
- }
- }
- break;
- case MIDI_CTL_CHANGE:
- switch (d1) {
- case CTL_BANK_SELECT: channel[chn].bank = d2; break;
- case CTL_MAIN_VOLUME: channel[chn].volume = d2; break;
- case CTL_PAN: channel[chn].balance = d2; break;
- case CTL_EXPRESSION: channel[chn].expression = d2; break;
- case CTL_SUSTAIN: channel[chn].sustain = d2;
- if (d2) {
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) {
- voice[i].status = sVS_SUSTAINED;
- }
- }
- } else {
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status == sVS_SUSTAINED && voice[i].channel == chn) {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
- }
- }
- }
- break;
- case CTL_NONREG_PARM_NUM_LSB: channel[chn].nrgPmtLSB = d2; break;
- case CTL_NONREG_PARM_NUM_MSB: channel[chn].nrgPmtMSB = d2; break;
- case CTL_REGIST_PARM_NUM_LSB: channel[chn].regPmtLSB = d2; break;
- case CTL_REGIST_PARM_NUM_MSB: channel[chn].regPmtMSB = d2; break;
- case CTL_DATA_ENTRY:
- switch ((channel[chn].regPmtMSB << 8) | channel[chn].regPmtLSB) {
- case 0x0000:
- if (channel[chn].benderRange != d2) {
- channel[chn].benderRange = d2;
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].channel == chn) {
- SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange);
- }
- }
- }
- break;
-
- case 0x7F7F:
- channel[chn].benderRange = 2;
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].channel == chn) {
- SEQ_BENDER_RANGE(wDevID, i, channel[chn].benderRange);
- }
- }
- break;
- default:
- TRACE("Data entry: regPmt=0x%02x%02x, nrgPmt=0x%02x%02x with %x\n",
- channel[chn].regPmtMSB, channel[chn].regPmtLSB,
- channel[chn].nrgPmtMSB, channel[chn].nrgPmtLSB,
- d2);
- break;
- }
- break;
-
- case 0x78: /* all sounds off */
- /* FIXME: I don't know if I have to take care of the channel
- * for this control ?
- */
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
- }
- }
- break;
- case 0x7B: /* all notes off */
- /* FIXME: I don't know if I have to take care of the channel
- * for this control ?
- */
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status == sVS_PLAYING && voice[i].channel == chn) {
- voice[i].status = sVS_UNUSED;
- SEQ_STOP_NOTE(wDevID, i, voice[i].note, 64);
- }
- }
- break;
- default:
- TRACE("Dropping MIDI control event 0x%02x(%02x) on channel %d\n",
- d1, d2, chn);
- break;
- }
- break;
- case MIDI_PGM_CHANGE:
- channel[chn].program = d1;
- break;
- case MIDI_CHN_PRESSURE:
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].status != sVS_UNUSED && voice[i].channel == chn) {
- SEQ_KEY_PRESSURE(wDevID, i, voice[i].note, d1);
- }
- }
- break;
- case MIDI_PITCH_BEND:
- channel[chn].bender = (d2 << 7) + d1;
- for (i = 0; i < MidiOutDev[wDevID].caps.wVoices; i++) {
- if (voice[i].channel == chn) {
- SEQ_BENDER(wDevID, i, channel[chn].bender);
- }
- }
- break;
- case MIDI_SYSTEM_PREFIX:
- switch (evt & 0x0F) {
- case 0x0F: /* Reset */
- OSS_CALL(midi_out_fm_reset, (void *)(UINT_PTR)wDevID);
- break;
- default:
- WARN("Unsupported (yet) system event %02x\n", evt & 0x0F);
- }
- break;
- default:
- WARN("Internal error, shouldn't happen (event=%08x)\n", evt & 0xF0);
- return MMSYSERR_NOTENABLED;
- }
- }
- break;
+ return midi_out_fm_data(wDevID, dwParam);
case MOD_MIDIPORT:
- {
- int dev = wDevID - MODM_NumFMSynthDevs;
- if (dev < 0) {
- WARN("Internal error on devID (%u) !\n", wDevID);
- return MIDIERR_NODEVICE;
- }
-
- switch (evt & 0xF0) {
- case MIDI_NOTEOFF:
- case MIDI_NOTEON:
- case MIDI_KEY_PRESSURE:
- case MIDI_CTL_CHANGE:
- case MIDI_PITCH_BEND:
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- SEQ_MIDIOUT(dev, d2);
- break;
- case MIDI_PGM_CHANGE:
- case MIDI_CHN_PRESSURE:
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- break;
- case MIDI_SYSTEM_PREFIX:
- switch (evt & 0x0F) {
- case 0x00: /* System Exclusive, don't do it on modData,
- * should require modLongData*/
- case 0x04: /* Undefined. */
- case 0x05: /* Undefined. */
- case 0x07: /* End of Exclusive. */
- case 0x09: /* Undefined. */
- case 0x0D: /* Undefined. */
- break;
- case 0x06: /* Tune Request */
- case 0x08: /* Timing Clock. */
- case 0x0A: /* Start. */
- case 0x0B: /* Continue */
- case 0x0C: /* Stop */
- case 0x0E: /* Active Sensing. */
- SEQ_MIDIOUT(dev, evt);
- break;
- case 0x0F: /* Reset */
- /* SEQ_MIDIOUT(dev, evt);
- this other way may be better */
- SEQ_MIDIOUT(dev, MIDI_SYSTEM_PREFIX);
- SEQ_MIDIOUT(dev, 0x7e);
- SEQ_MIDIOUT(dev, 0x7f);
- SEQ_MIDIOUT(dev, 0x09);
- SEQ_MIDIOUT(dev, 0x01);
- SEQ_MIDIOUT(dev, 0xf7);
- break;
- case 0x01: /* MTC Quarter frame */
- case 0x03: /* Song Select. */
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- case 0x02: /* Song Position Pointer. */
- SEQ_MIDIOUT(dev, evt);
- SEQ_MIDIOUT(dev, d1);
- SEQ_MIDIOUT(dev, d2);
- }
- break;
- }
- }
- break;
- default:
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
+ return midi_out_port_data(wDevID, dwParam);
}
- SEQ_DUMPBUF();
-
- return MMSYSERR_NOERROR;
+ WARN("Technology not supported (yet) %d !\n",
+ MidiOutDev[wDevID].caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
}
/**************************************************************************
--
2.25.1
2
1
21 Apr '22
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
v3:
- fix compiler warning.
dlls/crypt32/tests/str.c | 331 +++++++++++++++------------------------
1 file changed, 127 insertions(+), 204 deletions(-)
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c
index a94381591c0..e10d5a4fb29 100644
--- a/dlls/crypt32/tests/str.c
+++ b/dlls/crypt32/tests/str.c
@@ -429,23 +429,31 @@ static void test_CertNameToStrA(void)
test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a\nb\"", FALSE);
}
-static void test_NameToStrConversionW(PCERT_NAME_BLOB pName, DWORD dwStrType,
- LPCWSTR expected, BOOL todo)
+#define test_NameToStrConversionW(a, b, c) test_NameToStrConversionW_(__LINE__, a, b, c)
+static void test_NameToStrConversionW_(unsigned int line, PCERT_NAME_BLOB pName, DWORD dwStrType, LPCWSTR expected)
{
- WCHAR buffer[2000] = { 0 };
- DWORD i;
+ DWORD len, retlen, expected_len;
+ WCHAR buffer[2000];
- i = CertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, NULL, 0);
- todo_wine_if (todo)
- ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenW(expected) + 1, i);
- i = CertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, buffer, ARRAY_SIZE(buffer));
- todo_wine_if (todo)
- ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenW(expected) + 1, i);
- todo_wine_if (todo)
- ok(!lstrcmpW(buffer, expected), "Expected %s, got %s\n",
- wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+ expected_len = wcslen(expected) + 1;
+ memset(buffer, 0xcc, sizeof(buffer));
+ len = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, NULL, 0);
+ ok(len == expected_len, "line %u: expected %lu chars, got %lu\n", line, expected_len, len);
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, ARRAY_SIZE(buffer));
+ ok(retlen == len, "line %u: expected %lu chars, got %lu.\n", line, len, retlen);
+ ok(!wcscmp(buffer, expected), "Expected %s, got %s\n", wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, len - 1);
+ todo_wine ok(retlen == len - 1, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen);
+ ok(!wcsncmp(buffer, expected, retlen - 1), "line %u: expected %s, got %s\n",
+ line, wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+ ok(!buffer[retlen - 1], "line %u: string is not zero terminated.\n", line);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, 0);
+ todo_wine ok(retlen == len, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen);
+ ok(buffer[0] == 0xcccc, "line %u: got %s\n", line, wine_dbgstr_w(buffer));
}
static void test_CertNameToStrW(void)
@@ -479,95 +487,79 @@ static void test_CertNameToStrW(void)
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR,
- L"US, Minnesota, Minneapolis, CodeWeavers, Wine Development, localhost, aric(a)codeweavers.com", FALSE);
+ L"US, Minnesota, Minneapolis, CodeWeavers, Wine Development, localhost, aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
- L"US; Minnesota; Minneapolis; CodeWeavers; Wine Development; localhost; aric(a)codeweavers.com", FALSE);
+ L"US; Minnesota; Minneapolis; CodeWeavers; Wine Development; localhost; aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- L"US\r\nMinnesota\r\nMinneapolis\r\nCodeWeavers\r\nWine Development\r\nlocalhost\r\naric(a)codeweavers.com",
- FALSE);
+ L"US\r\nMinnesota\r\nMinneapolis\r\nCodeWeavers\r\nWine Development\r\nlocalhost\r\naric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR,
L"2.5.4.6=US, 2.5.4.8=Minnesota, 2.5.4.7=Minneapolis, 2.5.4.10=CodeWeavers, 2.5.4.11=Wine Development,"
- " 2.5.4.3=localhost, 1.2.840.113549.1.9.1=aric(a)codeweavers.com", FALSE);
+ " 2.5.4.3=localhost, 1.2.840.113549.1.9.1=aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
L"2.5.4.6=US; 2.5.4.8=Minnesota; 2.5.4.7=Minneapolis; 2.5.4.10=CodeWeavers; 2.5.4.11=Wine Development;"
- " 2.5.4.3=localhost; 1.2.840.113549.1.9.1=aric(a)codeweavers.com", FALSE);
+ " 2.5.4.3=localhost; 1.2.840.113549.1.9.1=aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
L"2.5.4.6=US\r\n2.5.4.8=Minnesota\r\n2.5.4.7=Minneapolis\r\n2.5.4.10=CodeWeavers\r\n2.5.4.11=Wine "
- "Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric(a)codeweavers…", FALSE);
+ "Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric(a)codeweavers…");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG,
L"E=aric(a)codeweavers.com; CN=localhost; OU=Wine Development; O=CodeWeavers; L=Minneapolis; S=Minnesota; "
- "C=US", FALSE);
+ "C=US");
CertFreeCertificateContext(context);
}
blob.pbData = encodedSimpleCN;
blob.cbData = sizeof(encodedSimpleCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=1", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=1");
blob.pbData = encodedSingleQuotedCN;
blob.cbData = sizeof(encodedSingleQuotedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN='1'",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"'1'", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN='1'");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"'1'");
blob.pbData = encodedSpacedCN;
blob.cbData = sizeof(encodedSpacedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\" 1 \"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\" 1 \"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\" 1 \"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\" 1 \"");
blob.pbData = encodedQuotedCN;
blob.cbData = sizeof(encodedQuotedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"\"\"1\"\"\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"\"\"1\"\"\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"\"\"1\"\"\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"\"\"1\"\"\"");
blob.pbData = encodedMultipleAttrCN;
blob.cbData = sizeof(encodedMultipleAttrCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"1+2\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"\"1+2\"", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"1+2\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"1+2\"");
blob.pbData = encodedCommaCN;
blob.cbData = sizeof(encodedCommaCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a,b\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a,b\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a,b\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a,b\"");
blob.pbData = encodedEqualCN;
blob.cbData = sizeof(encodedEqualCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a=b\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a=b\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a=b\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a=b\"");
blob.pbData = encodedLessThanCN;
blob.cbData = sizeof(encodedLessThanCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"<\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"<\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"<\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"<\"");
blob.pbData = encodedGreaterThanCN;
blob.cbData = sizeof(encodedGreaterThanCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\">\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"\">\"", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\">\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\">\"");
blob.pbData = encodedHashCN;
blob.cbData = sizeof(encodedHashCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"#\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"#\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"#\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"#\"");
blob.pbData = encodedSemiCN;
blob.cbData = sizeof(encodedSemiCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\";\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\";\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\";\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\";\"");
blob.pbData = encodedNewlineCN;
blob.cbData = sizeof(encodedNewlineCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a\nb\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a\nb\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a\nb\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a\nb\"");
}
struct StrToNameA
@@ -747,153 +739,84 @@ static void test_CertStrToNameW(void)
}
}
-static void test_CertGetNameStringA(void)
+#define test_CertGetNameString_value(a, b, c, d) test_CertGetNameString_value_(__LINE__, a, b, c, d)
+static void test_CertGetNameString_value_(unsigned int line, PCCERT_CONTEXT context, DWORD type, void *type_para,
+ const char *expected)
+{
+ WCHAR expectedW[512];
+ DWORD len, retlen;
+ WCHAR strW[512];
+ unsigned int i;
+ char str[512];
+
+ for (i = 0; expected[i]; ++i)
+ expectedW[i] = expected[i];
+ expectedW[i] = 0;
+
+ len = CertGetNameStringA(context, type, 0, type_para, NULL, 0);
+ ok(len == strlen(expected) + 1, "line %u: unexpected length %ld.\n", line, len);
+ retlen = CertGetNameStringA(context, type, 0, type_para, str, len);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len);
+ ok(!strcmp(str, expected), "line %u: unexpected value %s.\n", line, str);
+ str[0] = str[1] = 0xcc;
+ retlen = CertGetNameStringA(context, type, 0, type_para, str, len - 1);
+ todo_wine ok(retlen == 1, "line %u: Unexpected len %lu, expected 1.\n", line, retlen);
+ todo_wine ok(!str[0], "line %u: unexpected str[0] %#x.\n", line, str[0]);
+ ok(str[1] == expected[1], "line %u: unexpected str[1] %#x.\n", line, str[1]);
+ retlen = CertGetNameStringW(context, type, 0, type_para, strW, len);
+ ok(retlen == len, "line %u: unexpected len %lu, expected 1.\n", line, retlen);
+ ok(!wcscmp(strW, expectedW), "line %u: unexpected value %s.\n", line, debugstr_w(strW));
+ strW[0] = strW[1] = 0xcccc;
+ retlen = CertGetNameStringW(context, type, 0, type_para, strW, len - 1);
+ todo_wine ok(retlen == len - 1, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len - 1);
+ ok(!wcsncmp(strW, expectedW, retlen - 1), "line %u: string data mismatch.\n", line);
+ ok(!strW[retlen - 1], "line %u: string is not zero terminated.\n", line);
+ retlen = CertGetNameStringA(context, type, 0, type_para, NULL, len - 1);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu\n", line, retlen, len);
+ retlen = CertGetNameStringW(context, type, 0, type_para, NULL, len - 1);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu\n", line, retlen, len);
+}
+
+static void test_CertGetNameString(void)
{
+ static const char aric[] = "aric(a)codeweavers.com";
+ static const char localhost[] = "localhost";
PCCERT_CONTEXT context;
+ DWORD len, type;
context = CertCreateCertificateContext(X509_ASN_ENCODING, cert,
sizeof(cert));
- ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
- GetLastError());
- if (context)
- {
- static const char aric[] = "aric(a)codeweavers.com";
- static const char localhost[] = "localhost";
- DWORD len, type;
- LPSTR str;
-
- /* Bad string types/types missing from the cert */
- len = CertGetNameStringA(NULL, 0, 0, NULL, NULL, 0);
- ok(len == 1, "expected 1, got %ld\n", len);
- len = CertGetNameStringA(context, 0, 0, NULL, NULL, 0);
- ok(len == 1, "expected 1, got %ld\n", len);
- len = CertGetNameStringA(context, CERT_NAME_URL_TYPE, 0, NULL, NULL,
- 0);
- ok(len == 1, "expected 1, got %ld\n", len);
-
- len = CertGetNameStringA(context, CERT_NAME_EMAIL_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_EMAIL_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(issuerStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, issuerStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- type = 0;
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type, NULL,
- 0);
- ok(len == strlen(issuerStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type,
- str, len);
- ok(!strcmp(str, issuerStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- type = CERT_OID_NAME_STR;
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type, NULL,
- 0);
- ok(len == strlen(subjectStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type,
- str, len);
- ok(!strcmp(str, subjectStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_RSA_emailAddr, NULL, 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_RSA_emailAddr, str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_COMMON_NAME, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_COMMON_NAME, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 0, NULL, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0,
- NULL, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
- 0, NULL, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_DNS_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- if (len > 1)
- {
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_DNS_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- }
-
- CertFreeCertificateContext(context);
- }
+ ok(!!context, "CertCreateCertificateContext failed, err %lu\n", GetLastError());
+
+ /* Bad string types/types missing from the cert */
+ len = CertGetNameStringA(NULL, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringA(context, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringA(context, CERT_NAME_URL_TYPE, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+
+ len = CertGetNameStringW(NULL, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringW(context, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringW(context, CERT_NAME_URL_TYPE, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+
+ test_CertGetNameString_value(context, CERT_NAME_EMAIL_TYPE, NULL, aric);
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, NULL, issuerStr);
+ type = 0;
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, &type, issuerStr);
+ type = CERT_OID_NAME_STR;
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, &type, subjectStr);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, NULL, aric);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, (void *)szOID_RSA_emailAddr, aric);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, (void *)szOID_COMMON_NAME, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_SIMPLE_DISPLAY_TYPE, NULL, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, NULL, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_DNS_TYPE, NULL, localhost);
+
+ CertFreeCertificateContext(context);
}
START_TEST(str)
@@ -904,5 +827,5 @@ START_TEST(str)
test_CertNameToStrW();
test_CertStrToNameA();
test_CertStrToNameW();
- test_CertGetNameStringA();
+ test_CertGetNameString();
}
--
2.35.1
1
6
[PATCH v5 1/8] msvcr100: Add _StructuredTaskCollection::_Schedule stub.
by Torge Matthies 21 Apr '22
by Torge Matthies 21 Apr '22
21 Apr '22
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47375
Signed-off-by: Torge Matthies <tmatthies(a)codeweavers.com>
---
v4 -> v5:
Changed the spec file entries for i386/arm in addition to win64.
dlls/concrt140/concrt140.spec | 6 +++---
dlls/msvcr100/msvcr100.spec | 4 ++--
dlls/msvcr110/msvcr110.spec | 6 +++---
dlls/msvcr120/msvcr120.spec | 6 +++---
dlls/msvcr120_app/msvcr120_app.spec | 6 +++---
dlls/msvcrt/concurrency.c | 27 +++++++++++++++++++++++++++
6 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/dlls/concrt140/concrt140.spec b/dlls/concrt140/concrt140.spec
index 50db9348327..6bb95661dd1 100644
--- a/dlls/concrt140/concrt140.spec
+++ b/dlls/concrt140/concrt140.spec
@@ -594,9 +594,9 @@
@ stub -arch=arm ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAA?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=i386 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAG?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
-@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@PEAVlocation(a)3@@Z
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 19b4cbe96d7..2a03df03e33 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -363,8 +363,8 @@
@ stub -arch=win64 ?_RunAndWait(a)_StructuredTaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
@ stub -arch=win32 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAG?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win32 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=win32 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
@ stub -arch=win32 ?_Schedule(a)_TaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_Schedule(a)_TaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
@ thiscall -arch=win32 ?_SetSpinCount@?$_SpinWait@$00(a)details@Concurrency@@QAEXI(a)Z(ptr long) SpinWait__SetSpinCount
diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec
index 23840f85eda..2888bd97e00 100644
--- a/dlls/msvcr110/msvcr110.spec
+++ b/dlls/msvcr110/msvcr110.spec
@@ -614,9 +614,9 @@
@ stub -arch=arm ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAA?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=i386 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAG?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
-@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@PEAVlocation(a)3@@Z
diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec
index 64ddeed42f4..8ddc09bcaf8 100644
--- a/dlls/msvcr120/msvcr120.spec
+++ b/dlls/msvcr120/msvcr120.spec
@@ -596,9 +596,9 @@
@ stub -arch=arm ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAA?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=i386 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAG?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
-@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
+@ thiscall -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z(ptr ptr) StructuredTaskCollection__Schedule
@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@PEAVlocation(a)3@@Z
diff --git a/dlls/msvcr120_app/msvcr120_app.spec b/dlls/msvcr120_app/msvcr120_app.spec
index 05f408d6884..4eb7cb6a298 100644
--- a/dlls/msvcr120_app/msvcr120_app.spec
+++ b/dlls/msvcr120_app/msvcr120_app.spec
@@ -592,9 +592,9 @@
@ stub -arch=arm ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAA?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=i386 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QAG?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z
@ stub -arch=win64 ?_RunAndWait(a)_TaskCollection@details(a)Concurrency@@QEAA?AW4_TaskCollectionStatus(a)23@PEAV_UnrealizedChore(a)23@@Z
-@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
-@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z(ptr ptr) msvcr120.?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z(ptr ptr) msvcr120.?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z
+@ thiscall -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z(ptr ptr) msvcr120.?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z
@ stub -arch=arm ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=i386 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z
@ stub -arch=win64 ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@PEAVlocation(a)3@@Z
diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c
index 2ca6421b0e7..db6e34ad457 100644
--- a/dlls/msvcrt/concurrency.c
+++ b/dlls/msvcrt/concurrency.c
@@ -174,6 +174,20 @@ typedef struct cs_queue
#endif
} cs_queue;
+#if _MSVCR_VER >= 100
+
+typedef struct
+{
+ char dummy;
+} UnrealizedChore;
+
+typedef struct
+{
+ char dummy;
+} StructuredTaskCollection;
+
+#endif /* _MSVCR_VER >= 100 */
+
typedef struct
{
ULONG_PTR unk_thread_id;
@@ -1741,6 +1755,19 @@ bool __thiscall SpinWait__SpinOnce(SpinWait *this)
}
}
+#if _MSVCR_VER >= 100
+
+/* ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@@Z */
+/* ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAEXPAV_UnrealizedChore(a)23@@Z */
+/* ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QEAAXPEAV_UnrealizedChore(a)23@@Z */
+DEFINE_THISCALL_WRAPPER(StructuredTaskCollection__Schedule, 8)
+void __thiscall StructuredTaskCollection__Schedule(StructuredTaskCollection *this, UnrealizedChore *chore)
+{
+ FIXME("(%p %p): stub!\n", this, chore);
+}
+
+#endif /* _MSVCR_VER >= 100 */
+
/* ??0critical_section(a)Concurrency@@QAE(a)XZ */
/* ??0critical_section(a)Concurrency@@QEAA(a)XZ */
DEFINE_THISCALL_WRAPPER(critical_section_ctor, 4)
--
2.36.0
3
11
21 Apr '22
Avoid using SetSystemTimer() to specify a callback; it does not support one.
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v3: Actually call the window procedure...
v4: Rebase.
dlls/user.exe16/message.c | 5 +++++
dlls/user.exe16/user_private.h | 2 ++
dlls/user.exe16/window.c | 4 ++--
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/user.exe16/message.c b/dlls/user.exe16/message.c
index 819d9d9b837..46561d722ed 100644
--- a/dlls/user.exe16/message.c
+++ b/dlls/user.exe16/message.c
@@ -1292,6 +1292,11 @@ LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd, UINT
lParam = MAKELPARAM( 0, convert_handle_32_to_16( lParam, GMEM_DDESHARE ));
ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
break; /* FIXME don't know how to free allocated memory (handle) !! */
+ case WM_TIMER:
+ if (wParam & SYSTEM_TIMER_FLAG)
+ msg = WM_SYSTIMER;
+ ret = callback( HWND_16(hwnd), msg, wParam, lParam, result, arg );
+ break;
case SBM_SETRANGE:
ret = callback( HWND_16(hwnd), SBM_SETRANGE16, 0, MAKELPARAM(wParam, lParam), result, arg );
break;
diff --git a/dlls/user.exe16/user_private.h b/dlls/user.exe16/user_private.h
index 8a325cf9fb2..0805997246b 100644
--- a/dlls/user.exe16/user_private.h
+++ b/dlls/user.exe16/user_private.h
@@ -95,6 +95,8 @@ extern void call_WH_CALLWNDPROC_hook( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPAR
#define WM_SYSTIMER 0x0118
+#define SYSTEM_TIMER_FLAG 0x10000
+
/* Dialog info structure (must match the user32 one) */
typedef struct tagDIALOGINFO
{
diff --git a/dlls/user.exe16/window.c b/dlls/user.exe16/window.c
index 590b8ae9f7c..e54dd6a803e 100644
--- a/dlls/user.exe16/window.c
+++ b/dlls/user.exe16/window.c
@@ -111,7 +111,7 @@ UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 pr
UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, TIMERPROC16 proc )
{
TIMERPROC proc32 = (TIMERPROC)WINPROC_AllocProc16( (WNDPROC16)proc );
- return SetSystemTimer( WIN_Handle32(hwnd), id, timeout, proc32 );
+ return SetTimer( WIN_Handle32(hwnd), (UINT_PTR)id | SYSTEM_TIMER_FLAG, timeout, proc32 );
}
@@ -1087,7 +1087,7 @@ void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
*/
BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id )
{
- return KillSystemTimer( WIN_Handle32(hwnd), id );
+ return KillTimer( WIN_Handle32(hwnd), (UINT_PTR)id | SYSTEM_TIMER_FLAG );
}
--
2.35.1
3
12
21 Apr '22
Signed-off-by: Paul Gofman <pgofman(a)codeweavers.com>
---
dlls/crypt32/tests/str.c | 332 +++++++++++++++------------------------
1 file changed, 127 insertions(+), 205 deletions(-)
diff --git a/dlls/crypt32/tests/str.c b/dlls/crypt32/tests/str.c
index a94381591c0..c91a27a0995 100644
--- a/dlls/crypt32/tests/str.c
+++ b/dlls/crypt32/tests/str.c
@@ -429,23 +429,30 @@ static void test_CertNameToStrA(void)
test_NameToStrConversionA(&blob, CERT_SIMPLE_NAME_STR, "\"a\nb\"", FALSE);
}
-static void test_NameToStrConversionW(PCERT_NAME_BLOB pName, DWORD dwStrType,
- LPCWSTR expected, BOOL todo)
+#define test_NameToStrConversionW(a, b, c) test_NameToStrConversionW_(__LINE__, a, b, c)
+static void test_NameToStrConversionW_(unsigned int line, PCERT_NAME_BLOB pName, DWORD dwStrType, LPCWSTR expected)
{
- WCHAR buffer[2000] = { 0 };
- DWORD i;
-
- i = CertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, NULL, 0);
- todo_wine_if (todo)
- ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenW(expected) + 1, i);
- i = CertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, buffer, ARRAY_SIZE(buffer));
- todo_wine_if (todo)
- ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %ld\n",
- lstrlenW(expected) + 1, i);
- todo_wine_if (todo)
- ok(!lstrcmpW(buffer, expected), "Expected %s, got %s\n",
- wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+ WCHAR buffer[2000];
+ DWORD len, retlen;
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ len = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, NULL, 0);
+ ok(len == wcslen(expected) + 1, "line %u: expected %u chars, got %lu\n", line, wcslen(expected) + 1, len);
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, ARRAY_SIZE(buffer));
+ ok(retlen == len, "line %u: expected %lu chars, got %lu.\n", line, len, retlen);
+ ok(!wcscmp(buffer, expected), "Expected %s, got %s\n", wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, len - 1);
+ todo_wine ok(retlen == len - 1, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen);
+ ok(!wcsncmp(buffer, expected, retlen - 1), "line %u: expected %s, got %s\n",
+ line, wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
+ ok(!buffer[retlen - 1], "line %u: string is not zero terminated.\n", line);
+
+ memset(buffer, 0xcc, sizeof(buffer));
+ retlen = CertNameToStrW(X509_ASN_ENCODING, pName, dwStrType, buffer, 0);
+ todo_wine ok(retlen == len, "line %u: expected %lu chars, got %lu\n", line, len - 1, retlen);
+ ok(buffer[0] == 0xcccc, "line %u: got %s\n", line, wine_dbgstr_w(buffer));
}
static void test_CertNameToStrW(void)
@@ -479,95 +486,79 @@ static void test_CertNameToStrW(void)
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR,
- L"US, Minnesota, Minneapolis, CodeWeavers, Wine Development, localhost, aric(a)codeweavers.com", FALSE);
+ L"US, Minnesota, Minneapolis, CodeWeavers, Wine Development, localhost, aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
- L"US; Minnesota; Minneapolis; CodeWeavers; Wine Development; localhost; aric(a)codeweavers.com", FALSE);
+ L"US; Minnesota; Minneapolis; CodeWeavers; Wine Development; localhost; aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Issuer,
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
- L"US\r\nMinnesota\r\nMinneapolis\r\nCodeWeavers\r\nWine Development\r\nlocalhost\r\naric(a)codeweavers.com",
- FALSE);
+ L"US\r\nMinnesota\r\nMinneapolis\r\nCodeWeavers\r\nWine Development\r\nlocalhost\r\naric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR,
L"2.5.4.6=US, 2.5.4.8=Minnesota, 2.5.4.7=Minneapolis, 2.5.4.10=CodeWeavers, 2.5.4.11=Wine Development,"
- " 2.5.4.3=localhost, 1.2.840.113549.1.9.1=aric(a)codeweavers.com", FALSE);
+ " 2.5.4.3=localhost, 1.2.840.113549.1.9.1=aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
L"2.5.4.6=US; 2.5.4.8=Minnesota; 2.5.4.7=Minneapolis; 2.5.4.10=CodeWeavers; 2.5.4.11=Wine Development;"
- " 2.5.4.3=localhost; 1.2.840.113549.1.9.1=aric(a)codeweavers.com", FALSE);
+ " 2.5.4.3=localhost; 1.2.840.113549.1.9.1=aric(a)codeweavers.com");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
L"2.5.4.6=US\r\n2.5.4.8=Minnesota\r\n2.5.4.7=Minneapolis\r\n2.5.4.10=CodeWeavers\r\n2.5.4.11=Wine "
- "Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric(a)codeweavers…", FALSE);
+ "Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric(a)codeweavers…");
test_NameToStrConversionW(&context->pCertInfo->Subject,
CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG,
L"E=aric(a)codeweavers.com; CN=localhost; OU=Wine Development; O=CodeWeavers; L=Minneapolis; S=Minnesota; "
- "C=US", FALSE);
+ "C=US");
CertFreeCertificateContext(context);
}
blob.pbData = encodedSimpleCN;
blob.cbData = sizeof(encodedSimpleCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=1", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=1");
blob.pbData = encodedSingleQuotedCN;
blob.cbData = sizeof(encodedSingleQuotedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN='1'",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"'1'", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN='1'");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"'1'");
blob.pbData = encodedSpacedCN;
blob.cbData = sizeof(encodedSpacedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\" 1 \"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\" 1 \"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\" 1 \"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\" 1 \"");
blob.pbData = encodedQuotedCN;
blob.cbData = sizeof(encodedQuotedCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"\"\"1\"\"\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"\"\"1\"\"\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"\"\"1\"\"\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"\"\"1\"\"\"");
blob.pbData = encodedMultipleAttrCN;
blob.cbData = sizeof(encodedMultipleAttrCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"1+2\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"\"1+2\"", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"1+2\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"1+2\"");
blob.pbData = encodedCommaCN;
blob.cbData = sizeof(encodedCommaCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a,b\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a,b\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a,b\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a,b\"");
blob.pbData = encodedEqualCN;
blob.cbData = sizeof(encodedEqualCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a=b\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a=b\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a=b\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a=b\"");
blob.pbData = encodedLessThanCN;
blob.cbData = sizeof(encodedLessThanCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"<\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"<\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"<\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"<\"");
blob.pbData = encodedGreaterThanCN;
blob.cbData = sizeof(encodedGreaterThanCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\">\"",
- FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR,
- L"\">\"", FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\">\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\">\"");
blob.pbData = encodedHashCN;
blob.cbData = sizeof(encodedHashCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"#\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"#\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"#\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"#\"");
blob.pbData = encodedSemiCN;
blob.cbData = sizeof(encodedSemiCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\";\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\";\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\";\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\";\"");
blob.pbData = encodedNewlineCN;
blob.cbData = sizeof(encodedNewlineCN);
- test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a\nb\"", FALSE);
- test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a\nb\"",
- FALSE);
+ test_NameToStrConversionW(&blob, CERT_X500_NAME_STR, L"CN=\"a\nb\"");
+ test_NameToStrConversionW(&blob, CERT_SIMPLE_NAME_STR, L"\"a\nb\"");
}
struct StrToNameA
@@ -747,153 +738,84 @@ static void test_CertStrToNameW(void)
}
}
-static void test_CertGetNameStringA(void)
+#define test_CertGetNameString_value(a, b, c, d) test_CertGetNameString_value_(__LINE__, a, b, c, d)
+static void test_CertGetNameString_value_(unsigned int line, PCCERT_CONTEXT context, DWORD type, void *type_para,
+ const char *expected)
+{
+ WCHAR expectedW[512];
+ DWORD len, retlen;
+ WCHAR strW[512];
+ unsigned int i;
+ char str[512];
+
+ for (i = 0; expected[i]; ++i)
+ expectedW[i] = expected[i];
+ expectedW[i] = 0;
+
+ len = CertGetNameStringA(context, type, 0, type_para, NULL, 0);
+ ok(len == strlen(expected) + 1, "line %u: unexpected length %ld.\n", line, len);
+ retlen = CertGetNameStringA(context, type, 0, type_para, str, len);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len);
+ ok(!strcmp(str, expected), "line %u: unexpected value %s.\n", line, str);
+ str[0] = str[1] = 0xcc;
+ retlen = CertGetNameStringA(context, type, 0, type_para, str, len - 1);
+ todo_wine ok(retlen == 1, "line %u: Unexpected len %lu, expected 1.\n", line, retlen);
+ todo_wine ok(!str[0], "line %u: unexpected str[0] %#x.\n", line, str[0]);
+ ok(str[1] == expected[1], "line %u: unexpected str[1] %#x.\n", line, str[1]);
+ retlen = CertGetNameStringW(context, type, 0, type_para, strW, len);
+ ok(retlen == len, "line %u: unexpected len %lu, expected 1.\n", line, retlen);
+ ok(!wcscmp(strW, expectedW), "line %u: unexpected value %s.\n", line, debugstr_w(strW));
+ strW[0] = strW[1] = 0xcccc;
+ retlen = CertGetNameStringW(context, type, 0, type_para, strW, len - 1);
+ todo_wine ok(retlen == len - 1, "line %u: unexpected len %lu, expected %lu.\n", line, retlen, len - 1);
+ ok(!wcsncmp(strW, expectedW, retlen - 1), "line %u: string data mismatch.\n", line);
+ ok(!strW[retlen - 1], "line %u: string is not zero terminated.\n", line);
+ retlen = CertGetNameStringA(context, type, 0, type_para, NULL, len - 1);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu\n", line, retlen, len);
+ retlen = CertGetNameStringW(context, type, 0, type_para, NULL, len - 1);
+ ok(retlen == len, "line %u: unexpected len %lu, expected %lu\n", line, retlen, len);
+}
+
+static void test_CertGetNameString(void)
{
+ static const char aric[] = "aric(a)codeweavers.com";
+ static const char localhost[] = "localhost";
PCCERT_CONTEXT context;
+ DWORD len, type;
context = CertCreateCertificateContext(X509_ASN_ENCODING, cert,
sizeof(cert));
- ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
- GetLastError());
- if (context)
- {
- static const char aric[] = "aric(a)codeweavers.com";
- static const char localhost[] = "localhost";
- DWORD len, type;
- LPSTR str;
-
- /* Bad string types/types missing from the cert */
- len = CertGetNameStringA(NULL, 0, 0, NULL, NULL, 0);
- ok(len == 1, "expected 1, got %ld\n", len);
- len = CertGetNameStringA(context, 0, 0, NULL, NULL, 0);
- ok(len == 1, "expected 1, got %ld\n", len);
- len = CertGetNameStringA(context, CERT_NAME_URL_TYPE, 0, NULL, NULL,
- 0);
- ok(len == 1, "expected 1, got %ld\n", len);
-
- len = CertGetNameStringA(context, CERT_NAME_EMAIL_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_EMAIL_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(issuerStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, issuerStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- type = 0;
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type, NULL,
- 0);
- ok(len == strlen(issuerStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type,
- str, len);
- ok(!strcmp(str, issuerStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- type = CERT_OID_NAME_STR;
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type, NULL,
- 0);
- ok(len == strlen(subjectStr) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_RDN_TYPE, 0, &type,
- str, len);
- ok(!strcmp(str, subjectStr), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_RSA_emailAddr, NULL, 0);
- ok(len == strlen(aric) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_RSA_emailAddr, str, len);
- ok(!strcmp(str, aric), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_COMMON_NAME, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_ATTR_TYPE, 0,
- (void *)szOID_COMMON_NAME, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0,
- NULL, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_SIMPLE_DISPLAY_TYPE,
- 0, NULL, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, 0,
- NULL, NULL, 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE,
- 0, NULL, str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
-
- len = CertGetNameStringA(context, CERT_NAME_DNS_TYPE, 0, NULL, NULL,
- 0);
- ok(len == strlen(localhost) + 1, "unexpected length %ld\n", len);
- if (len > 1)
- {
- str = HeapAlloc(GetProcessHeap(), 0, len);
- if (str)
- {
- len = CertGetNameStringA(context, CERT_NAME_DNS_TYPE, 0, NULL,
- str, len);
- ok(!strcmp(str, localhost), "unexpected value %s\n", str);
- HeapFree(GetProcessHeap(), 0, str);
- }
- }
-
- CertFreeCertificateContext(context);
- }
+ ok(!!context, "CertCreateCertificateContext failed, err %lu\n", GetLastError());
+
+ /* Bad string types/types missing from the cert */
+ len = CertGetNameStringA(NULL, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringA(context, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringA(context, CERT_NAME_URL_TYPE, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+
+ len = CertGetNameStringW(NULL, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringW(context, 0, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+ len = CertGetNameStringW(context, CERT_NAME_URL_TYPE, 0, NULL, NULL, 0);
+ ok(len == 1, "expected 1, got %lu\n", len);
+
+ test_CertGetNameString_value(context, CERT_NAME_EMAIL_TYPE, NULL, aric);
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, NULL, issuerStr);
+ type = 0;
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, &type, issuerStr);
+ type = CERT_OID_NAME_STR;
+ test_CertGetNameString_value(context, CERT_NAME_RDN_TYPE, &type, subjectStr);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, NULL, aric);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, (void *)szOID_RSA_emailAddr, aric);
+ test_CertGetNameString_value(context, CERT_NAME_ATTR_TYPE, (void *)szOID_COMMON_NAME, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_SIMPLE_DISPLAY_TYPE, NULL, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_FRIENDLY_DISPLAY_TYPE, NULL, localhost);
+ test_CertGetNameString_value(context, CERT_NAME_DNS_TYPE, NULL, localhost);
+
+ CertFreeCertificateContext(context);
}
START_TEST(str)
@@ -904,5 +826,5 @@ START_TEST(str)
test_CertNameToStrW();
test_CertStrToNameA();
test_CertStrToNameW();
- test_CertGetNameStringA();
+ test_CertGetNameString();
}
--
2.35.1
2
7
[PATCH] kernelbase: Add support for progress callback in CopyFileEx.
by Alistair Leslie-Hughes 21 Apr '22
by Alistair Leslie-Hughes 21 Apr '22
21 Apr '22
Based on patch by Michael Müller.
Signed-off-by: Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com>
---
dlls/kernel32/tests/file.c | 7 +----
dlls/kernelbase/file.c | 54 +++++++++++++++++++++++++++++++++++---
2 files changed, 51 insertions(+), 10 deletions(-)
diff --git a/dlls/kernel32/tests/file.c b/dlls/kernel32/tests/file.c
index 1fb9e98cf41..4f47dd8a51f 100644
--- a/dlls/kernel32/tests/file.c
+++ b/dlls/kernel32/tests/file.c
@@ -1176,21 +1176,16 @@ static void test_CopyFileEx(void)
ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %ld\n", GetLastError());
SetLastError(0xdeadbeef);
retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
- todo_wine
ok(!retok, "CopyFileExA unexpectedly succeeded\n");
- todo_wine
ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %ld\n", GetLastError());
ok(GetFileAttributesA(dest) != INVALID_FILE_ATTRIBUTES, "file was deleted\n");
hfile = CreateFileA(dest, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, 0, 0);
- todo_wine
ok(hfile != INVALID_HANDLE_VALUE, "failed to open destination file, error %ld\n", GetLastError());
SetLastError(0xdeadbeef);
retok = CopyFileExA(source, dest, copy_progress_cb, hfile, NULL, 0);
- todo_wine
ok(!retok, "CopyFileExA unexpectedly succeeded\n");
- todo_wine
ok(GetLastError() == ERROR_REQUEST_ABORTED, "expected ERROR_REQUEST_ABORTED, got %ld\n", GetLastError());
todo_wine
ok(GetFileAttributesA(dest) == INVALID_FILE_ATTRIBUTES, "file was not deleted\n");
@@ -1205,7 +1200,7 @@ static void test_CopyFileEx(void)
ret = DeleteFileA(source);
ok(ret, "DeleteFileA failed with error %ld\n", GetLastError());
ret = DeleteFileA(dest);
- ok(!ret, "DeleteFileA unexpectedly succeeded\n");
+ todo_wine ok(!ret, "DeleteFileA unexpectedly succeeded\n");
}
/*
diff --git a/dlls/kernelbase/file.c b/dlls/kernelbase/file.c
index 8ae982294f6..6803c79a4a4 100644
--- a/dlls/kernelbase/file.c
+++ b/dlls/kernelbase/file.c
@@ -490,6 +490,23 @@ BOOL WINAPI DECLSPEC_HOTPATCH AreFileApisANSI(void)
return !oem_file_apis;
}
+static DWORD call_progress_dialog(LPPROGRESS_ROUTINE progress, LARGE_INTEGER size, LARGE_INTEGER transferred,
+ DWORD cbtype, HANDLE h1, HANDLE h2, void *param)
+{
+ DWORD cbret;
+
+ cbret = progress( size, transferred, size, transferred, 1, cbtype, h1, h2, param );
+ if (cbret == PROGRESS_STOP)
+ SetLastError( ERROR_REQUEST_ABORTED );
+ else if (cbret == PROGRESS_CANCEL)
+ {
+ BOOLEAN disp = TRUE;
+ SetFileInformationByHandle( h2, FileDispositionInfo, &disp, sizeof(disp) );
+ SetLastError( ERROR_REQUEST_ABORTED );
+ }
+
+ return cbret;
+}
/***********************************************************************
* CopyFileExW (kernelbase.@)
@@ -499,11 +516,14 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
{
static const int buffer_size = 65536;
HANDLE h1, h2;
- FILE_BASIC_INFORMATION info;
+ FILE_NETWORK_OPEN_INFORMATION info;
+ FILE_BASIC_INFORMATION basic_info;
IO_STATUS_BLOCK io;
DWORD count;
BOOL ret = FALSE;
char *buffer;
+ LARGE_INTEGER transferred;
+ DWORD cbret;
if (!source || !dest)
{
@@ -533,7 +553,7 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
return FALSE;
}
- if (!set_ntstatus( NtQueryInformationFile( h1, &io, &info, sizeof(info), FileBasicInformation )))
+ if (!set_ntstatus( NtQueryInformationFile( h1, &io, &info, sizeof(info), FileNetworkOpenInformation )))
{
WARN("GetFileInformationByHandle returned error for %s\n", debugstr_w(source));
HeapFree( GetProcessHeap(), 0, buffer );
@@ -569,6 +589,17 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
return FALSE;
}
+ if (progress)
+ {
+ transferred.QuadPart = 0;
+
+ cbret = call_progress_dialog(progress, info.EndOfFile, transferred, CALLBACK_STREAM_SWITCH, h1, h2, param);
+ if (cbret == PROGRESS_QUIET)
+ progress = NULL;
+ else if (cbret != PROGRESS_CONTINUE)
+ goto done;
+ }
+
while (ReadFile( h1, buffer, buffer_size, &count, NULL ) && count)
{
char *p = buffer;
@@ -578,13 +609,28 @@ BOOL WINAPI CopyFileExW( const WCHAR *source, const WCHAR *dest, LPPROGRESS_ROUT
if (!WriteFile( h2, p, count, &res, NULL ) || !res) goto done;
p += res;
count -= res;
+
+ if (progress)
+ {
+ transferred.QuadPart += res;
+
+ cbret = call_progress_dialog(progress, info.EndOfFile, transferred, CALLBACK_CHUNK_FINISHED, h1, h2, param);
+ if (cbret == PROGRESS_QUIET)
+ progress = NULL;
+ else if (cbret != PROGRESS_CONTINUE)
+ goto done;
+ }
}
}
ret = TRUE;
done:
/* Maintain the timestamp of source file to destination file */
- info.FileAttributes = 0;
- NtSetInformationFile( h2, &io, &info, sizeof(info), FileBasicInformation );
+ basic_info.CreationTime = info.CreationTime;
+ basic_info.LastAccessTime = info.LastAccessTime;
+ basic_info.LastWriteTime = info.LastWriteTime;
+ basic_info.ChangeTime = info.ChangeTime;
+ basic_info.FileAttributes = 0;
+ NtSetInformationFile( h2, &io, &basic_info, sizeof(basic_info), FileBasicInformation );
HeapFree( GetProcessHeap(), 0, buffer );
CloseHandle( h1 );
CloseHandle( h2 );
--
2.35.1
2
1
[PATCH v3 3/3] webservices: Always set channel state to WS_CHANNEL_STATE_FAULTED when a send or receive operation failed.
by Hans Leidekker 21 Apr '22
by Hans Leidekker 21 Apr '22
21 Apr '22
Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/webservices/channel.c | 58 ++++++++++++++++++++++++--------------
1 file changed, 37 insertions(+), 21 deletions(-)
diff --git a/dlls/webservices/channel.c b/dlls/webservices/channel.c
index 56ad5692a6b..4c9f9c4ccff 100644
--- a/dlls/webservices/channel.c
+++ b/dlls/webservices/channel.c
@@ -1608,6 +1608,7 @@ HRESULT channel_send_message( WS_CHANNEL *handle, WS_MESSAGE *msg )
}
hr = send_message_bytes( channel, msg );
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
LeaveCriticalSection( &channel->cs );
return hr;
@@ -1723,11 +1724,15 @@ static HRESULT send_message( struct channel *channel, WS_MESSAGE *msg, const WS_
WS_WRITE_OPTION option, const void *body, ULONG size )
{
HRESULT hr;
- if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) return hr;
- if ((hr = message_set_action( msg, desc->action )) != S_OK) return hr;
- if ((hr = init_writer( channel )) != S_OK) return hr;
- if ((hr = write_message( channel, msg, desc->bodyElementDescription, option, body, size )) != S_OK) return hr;
- return send_message_bytes( channel, msg );
+ if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) goto done;
+ if ((hr = message_set_action( msg, desc->action )) != S_OK) goto done;
+ if ((hr = init_writer( channel )) != S_OK) goto done;
+ if ((hr = write_message( channel, msg, desc->bodyElementDescription, option, body, size )) != S_OK) goto done;
+ hr = send_message_bytes( channel, msg );
+
+done:
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
+ return hr;
}
struct send_message
@@ -2260,11 +2265,7 @@ static HRESULT receive_message_bytes_session( struct channel *channel )
{
ULONG size;
if ((hr = build_dict( (const BYTE *)channel->read_buf, channel->read_size, &channel->dict_recv,
- &size )) != S_OK)
- {
- if (hr == WS_E_QUOTA_EXCEEDED) channel->state = WS_CHANNEL_STATE_FAULTED;
- return hr;
- }
+ &size )) != S_OK) return hr;
channel->read_size -= size;
memmove( channel->read_buf, channel->read_buf + size, channel->read_size );
}
@@ -2328,6 +2329,7 @@ HRESULT channel_receive_message( WS_CHANNEL *handle, WS_MESSAGE *msg )
}
if ((hr = receive_message_bytes( channel, msg )) == S_OK) hr = init_reader( channel );
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
LeaveCriticalSection( &channel->cs );
return hr;
@@ -2367,8 +2369,8 @@ static HRESULT receive_message( struct channel *channel, WS_MESSAGE *msg, const
HRESULT hr;
ULONG i;
- if ((hr = receive_message_bytes( channel, msg )) != S_OK) return hr;
- if ((hr = init_reader( channel )) != S_OK) return hr;
+ if ((hr = receive_message_bytes( channel, msg )) != S_OK) goto done;
+ if ((hr = init_reader( channel )) != S_OK) goto done;
for (i = 0; i < count; i++)
{
@@ -2378,10 +2380,14 @@ static HRESULT receive_message( struct channel *channel, WS_MESSAGE *msg, const
if (index) *index = i;
break;
}
- if ((hr = WsResetMessage( msg, NULL )) != S_OK) return hr;
- if ((hr = init_reader( channel )) != S_OK) return hr;
+ if ((hr = WsResetMessage( msg, NULL )) != S_OK) goto done;
+ if ((hr = init_reader( channel )) != S_OK) goto done;
}
- return (i == count) ? WS_E_INVALID_FORMAT : S_OK;
+ hr = (i == count) ? WS_E_INVALID_FORMAT : S_OK;
+
+done:
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
+ return hr;
}
struct receive_message
@@ -2606,6 +2612,7 @@ static HRESULT read_message_start( struct channel *channel, WS_MESSAGE *msg )
HRESULT hr;
if ((hr = receive_message_bytes( channel, msg )) == S_OK && (hr = init_reader( channel )) == S_OK)
hr = WsReadEnvelopeStart( msg, channel->reader, NULL, NULL, NULL );
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
return hr;
}
@@ -2682,14 +2689,17 @@ HRESULT WINAPI WsReadMessageStart( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS
return hr;
}
-static HRESULT read_message_end( WS_MESSAGE *msg )
+static HRESULT read_message_end( struct channel *channel, WS_MESSAGE *msg )
{
- return WsReadEnvelopeEnd( msg, NULL );
+ HRESULT hr = WsReadEnvelopeEnd( msg, NULL );
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
+ return hr;
}
struct read_message_end
{
struct task task;
+ struct channel *channel;
WS_MESSAGE *msg;
WS_ASYNC_CONTEXT ctx;
};
@@ -2699,7 +2709,7 @@ static void read_message_end_proc( struct task *task )
struct read_message_end *r = (struct read_message_end *)task;
HRESULT hr;
- hr = read_message_end( r->msg );
+ hr = read_message_end( r->channel, r->msg );
TRACE( "calling %p(%#lx)\n", r->ctx.callback, hr );
r->ctx.callback( hr, WS_LONG_CALLBACK, r->ctx.callbackState );
@@ -2712,6 +2722,7 @@ static HRESULT queue_read_message_end( struct channel *channel, WS_MESSAGE *msg,
if (!(r = malloc( sizeof(*r) ))) return E_OUTOFMEMORY;
r->task.proc = read_message_end_proc;
+ r->channel = channel;
r->msg = msg;
r->ctx = *ctx;
return queue_task( &channel->recv_q, &r->task );
@@ -2756,9 +2767,13 @@ HRESULT WINAPI WsReadMessageEnd( WS_CHANNEL *handle, WS_MESSAGE *msg, const WS_A
static HRESULT write_message_start( struct channel *channel, WS_MESSAGE *msg )
{
HRESULT hr;
- if ((hr = init_writer( channel )) != S_OK) return hr;
- if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) return hr;
- return WsWriteEnvelopeStart( msg, channel->writer, NULL, NULL, NULL );
+ if ((hr = init_writer( channel )) != S_OK) goto done;
+ if ((hr = WsAddressMessage( msg, &channel->addr, NULL )) != S_OK) goto done;
+ hr = WsWriteEnvelopeStart( msg, channel->writer, NULL, NULL, NULL );
+
+done:
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
+ return hr;
}
struct write_message_start
@@ -2838,6 +2853,7 @@ static HRESULT write_message_end( struct channel *channel, WS_MESSAGE *msg )
{
HRESULT hr;
if ((hr = WsWriteEnvelopeEnd( msg, NULL )) == S_OK) hr = send_message_bytes( channel, msg );
+ if (hr != S_OK) channel->state = WS_CHANNEL_STATE_FAULTED;
return hr;
}
--
2.30.2
1
0