Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 4 participants
- 84544 discussions
April 21, 2022
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
See also the corresponding user details patch.
---
testbot/web/Activity.pl | 2 +-
testbot/web/Stats.pl | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/testbot/web/Activity.pl b/testbot/web/Activity.pl
index 5a5a37505..a92435805 100644
--- a/testbot/web/Activity.pl
+++ b/testbot/web/Activity.pl
@@ -238,7 +238,7 @@ EOF
$Label .= "/64" if ($Bitness);
}
}
- my $URL = GetTaskURL($VMStatus->{job}->Id, $VMStatus->{step}->No, $VMStatus->{task}->No);
+ my $URL = $self->escapeHTML(GetTaskURL($VMStatus->{job}->Id, $VMStatus->{step}->No, $VMStatus->{task}->No));
my $Title = $self->escapeHTML($VMStatus->{job}->Remarks);
$Label = "<a href='$URL' title='$Title'>$Label</a>";
}
diff --git a/testbot/web/Stats.pl b/testbot/web/Stats.pl
index 3c0fe9990..773fe3bb9 100644
--- a/testbot/web/Stats.pl
+++ b/testbot/web/Stats.pl
@@ -147,7 +147,7 @@ sub _GetStatHtml($$;$$)
my ($JobId, $StepNo, $TaskNo) = ObjectModel::Collection::SplitKey(undef, $SrcObj->GetFullKey());
if (defined $TaskNo)
{
- return "<a href='". GetTaskURL($JobId, $StepNo, $TaskNo) ."'>$Value</a>";
+ return "<a href='". $Stats->{Page}->escapeHTML(GetTaskURL($JobId, $StepNo, $TaskNo)) ."'>$Value</a>";
}
return "<a href='/index.pl#job$JobId'>$Value</a>";
}
@@ -174,6 +174,7 @@ sub _GenStatsLine($$$$;$)
foreach my $Col (@$ColumnKeys)
{
my $Stats = $RowStats->{items}->{$Col};
+ $Stats->{Page} = $RowStats->{Page};
my $Value = _GetStatHtml($Stats, $StatKey, $RowStats, $Flags);
print "<td>$Value</td>\n";
}
@@ -205,6 +206,7 @@ sub GenerateBody($)
### Show global statistics
my $GlobalStats = $Stats->{global};
+ $GlobalStats->{Page} = $self;
print "<h2>General statistics</h2>\n";
print "<div class='CollectionBlock'><table>\n";
@@ -251,6 +253,7 @@ sub GenerateBody($)
print "<tr><td class='StatSeparator'>Activity</td><td colspan='2'><hr></td></tr>\n";
my $VMsStats = $Stats->{vms};
+ $VMsStats->{Page} = $self;
_GenGlobalLine($VMsStats, "elapsed", "Activity history", "How far back the activity records go. This is used for the VM and VM host tables.");
_GenGlobalLine($GlobalStats, "records.count", "Record count", "The number of activity records.");
@@ -264,7 +267,8 @@ sub GenerateBody($)
print "<thead><tr><th>Stat</th>\n";
my $HostsStats = $Stats->{hosts};
- my $SortedHosts = [ sort keys %{$Stats->{hosts}->{items}} ];
+ $HostsStats->{Page} = $self;
+ my $SortedHosts = [ sort keys %{$HostsStats->{items}} ];
foreach my $Host (@$SortedHosts)
{
my $DisplayHost = $Host;
--
2.30.2
1
0
April 21, 2022
There is no need to call uri_escape() on integers.
But GetDetailsLink() should go through escapeHTML() in case it contains
ampersands.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
See also the corresponding user details patch.
---
testbot/web/index.pl | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/testbot/web/index.pl b/testbot/web/index.pl
index 0b8a9cb78..1c506c9b1 100644
--- a/testbot/web/index.pl
+++ b/testbot/web/index.pl
@@ -26,7 +26,6 @@ use ObjectModel::CGI::CollectionBlock;
our @ISA = qw(ObjectModel::CGI::CollectionBlock);
use POSIX qw(strftime);
-use URI::Escape;
use WineTestBot::Branches;
use WineTestBot::Users;
@@ -89,9 +88,9 @@ sub GenerateDataView($$$)
}
elsif ($PropertyName eq "Status")
{
- my $EscapedKey = uri_escape($Row->{Item}->GetKey());
my $DetailsLink = $self->GetDetailsLink($Row);
- print "<a id='job$EscapedKey' href='$DetailsLink'>";
+ print "<a id='job", $Job->Id, "' href='", $self->escapeHTML($DetailsLink),
+ "'>";
my %HTMLChunks = ("queued" => "<span class='queued'>queued</span>",
"running" => "<span class='running'>running</span>",
--
2.30.2
1
0
April 21, 2022
It may contain ampersands which should be escaped in HTML documents.
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
Web browsers don't actually care and HTML 5 reportedly allows not
escaping them in URLs as long as they are not ambiguous
(!~ /&[a-zA-Z]+;/) which ours shouldn't be (=~ /&[a-zA-Z]+=/).
But the TestBot is still on HTML 4 which means strictly speaking it
should escape these ampersands.
---
testbot/web/admin/UsersList.pl | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/testbot/web/admin/UsersList.pl b/testbot/web/admin/UsersList.pl
index dcdb8111c..ec6d2822e 100644
--- a/testbot/web/admin/UsersList.pl
+++ b/testbot/web/admin/UsersList.pl
@@ -82,7 +82,7 @@ sub GenerateDataView($$$)
{
($Class, $Label) = ('usernone', 'none');
}
- my $DetailsLink = $self->GetDetailsLink($Row);
+ my $DetailsLink = $self->escapeHTML($self->GetDetailsLink($Row));
print "<a href='$DetailsLink'><span class='$Class'>$Label</span></a>";
}
else
--
2.30.2
1
0
April 21, 2022
Signed-off-by: Francois Gouget <fgouget(a)codeweavers.com>
---
testbot/lib/WineTestBot/Patches.pm | 2 +-
testbot/tests/TestWTBS | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/testbot/lib/WineTestBot/Patches.pm b/testbot/lib/WineTestBot/Patches.pm
index d2ac52e4e..c0768bea7 100644
--- a/testbot/lib/WineTestBot/Patches.pm
+++ b/testbot/lib/WineTestBot/Patches.pm
@@ -550,7 +550,7 @@ sub NewPatch($$;$)
my $SubjectInfo = $Patch->ParseSubject();
if (@PatchBodies == 0)
{
- $Patch->Disposition("No patch found");
+ $Patch->Disposition("No patch");
}
elsif (@PatchBodies > 1)
{
diff --git a/testbot/tests/TestWTBS b/testbot/tests/TestWTBS
index 8067a62e5..e5cd44832 100755
--- a/testbot/tests/TestWTBS
+++ b/testbot/tests/TestWTBS
@@ -1460,7 +1460,7 @@ sub CheckPatches()
{
ok(($Patch->Subject =~ /NoPatch/ or
$Patch->Disposition eq "Reply to a patch series" or
- $Patch->Disposition eq "No patch found"),
+ $Patch->Disposition eq "No patch"),
"Found no file for patch ". $Patch->Id .": ". $Patch->Subject)
or diag("Disposition=". $Patch->Disposition);
}
--
2.30.2
1
0
[PATCH V3 1/5] dlls/kernel32/tests: move CreateProcess() handle inheritance test into a dedicated function
by Eric Pouech April 21, 2022
by Eric Pouech April 21, 2022
April 21, 2022
Signed-off-by: Eric Pouech <eric.pouech(a)gmail.com>
---
dlls/kernel32/tests/process.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 8f18a0d37a7..e7b4f30b565 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -1521,10 +1521,6 @@ static void test_Console(void)
CONSOLE_SCREEN_BUFFER_INFO sbi, sbiC;
DWORD modeIn, modeOut, modeInC, modeOutC;
DWORD cpIn, cpOut, cpInC, cpOutC;
- DWORD w;
- HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
- const char* msg = "This is a std-handle inheritance test.";
- unsigned msg_len;
BOOL run_tests = TRUE;
char *result;
@@ -1647,6 +1643,17 @@ static void test_Console(void)
release_memory();
DeleteFileA(resfile);
+}
+
+static void test_StdInheritance(void)
+{
+ char buffer[2 * MAX_PATH + 35];
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ DWORD w;
+ HANDLE hChildIn, hChildInInh, hChildOut, hChildOutInh, hParentIn, hParentOut;
+ const char* msg = "This is a std-handle inheritance test.";
+ unsigned msg_len;
ok(CreatePipe(&hParentIn, &hChildOut, NULL, 0), "Creating parent-input pipe\n");
ok(DuplicateHandle(GetCurrentProcess(), hChildOut, GetCurrentProcess(),
@@ -5095,6 +5102,7 @@ START_TEST(process)
test_SuspendFlag();
test_DebuggingFlag();
test_Console();
+ test_StdInheritance();
test_ExitCode();
test_OpenProcess();
test_GetProcessVersion();
4
9
[PATCH 4/4] wineoss: Move MODM_PREPARE and MODM_UNPREPARE to the unixlib.
by Huw Davies April 21, 2022
by Huw Davies April 21, 2022
April 21, 2022
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 April 21, 2022
by Huw Davies April 21, 2022
April 21, 2022
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
[PATCH v3 1/7] crypt32/tests: Add tests for short return string buffer.
by Paul Gofman April 21, 2022
by Paul Gofman April 21, 2022
April 21, 2022
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