Updated (prepare|unprepare)header functions to allow correct callback
mechanisms.

diff --git a/multimedia/midi.c b/multimedia/midi.c
index 9fa0164..aef23d6 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -28,7 +28,7 @@
 #include "xmalloc.h"
 #include "debug.h"
 #include "heap.h"
-
+#include "ldt.h"
 
 typedef struct {
 #ifndef HAVE_OSS
@@ -38,7 +38,7 @@
     DWORD		bufsize;
     LPMIDIOPENDESC	midiDesc;
     WORD		wFlags;
-    LPMIDIHDR16 		lpQueueHdr;
+    LPMIDIHDR16 	lpQueueHdr;
     DWORD		dwTotalPlayed;
 #ifdef HAVE_OSS
     unsigned char	incoming[3];
@@ -56,7 +56,7 @@
     DWORD		bufsize;
     LPMIDIOPENDESC	midiDesc;
     WORD		wFlags;
-    LPMIDIHDR16 		lpQueueHdr;
+    LPMIDIHDR16 	lpQueueHdr;
     DWORD		dwTotalPlayed;
 #ifdef HAVE_OSS
     void*		lpExtra;	 	/* according to port type (MIDI, FM...), extra data when needed */
@@ -230,14 +230,17 @@
 	TRACE(midi, "input not started, thrown away\n");
 	return;
     }
-    
+
     if (MidiInDev[wDevID].state & 2) { /* system exclusive */
-	LPMIDIHDR16	ptr = MidiInDev[wDevID].lpQueueHdr;
-	WORD 			sbfb = FALSE;
+	LPMIDIHDR16	lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;
+	WORD 		sbfb = FALSE;
+
+	if (lpMidiHdr) {
+	    LPBYTE	lpData = ((DWORD)lpMidiHdr == lpMidiHdr->reserved) ?
+		(LPBYTE)lpMidiHdr->lpData : (LPBYTE)PTR_SEG_TO_LIN(lpMidiHdr->lpData);
 	
-	if (ptr) {
-	    ((LPSTR)(ptr->reserved))[ptr->dwBytesRecorded++] = value;
-	    if (ptr->dwBytesRecorded == ptr->dwBufferLength) {
+	    lpData[lpMidiHdr->dwBytesRecorded++] = value;
+	    if (lpMidiHdr->dwBytesRecorded == lpMidiHdr->dwBufferLength) {
 		sbfb = TRUE;
 	    } 
 	}
@@ -245,12 +248,12 @@
 	    MidiInDev[wDevID].state &= ~2;
 	    sbfb = TRUE;
 	}
-	if (sbfb && ptr != NULL) {
-	    ptr = MidiInDev[wDevID].lpQueueHdr;
-	    ptr->dwFlags &= ~MHDR_INQUEUE;
-	    ptr->dwFlags |= MHDR_DONE;
-	    MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR16)ptr->lpNext;
-	    if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)ptr, dwTime) != MMSYSERR_NOERROR) {
+	if (sbfb && lpMidiHdr != NULL) {
+	    lpMidiHdr = MidiInDev[wDevID].lpQueueHdr;
+	    lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
+	    lpMidiHdr->dwFlags |= MHDR_DONE;
+	    MidiInDev[wDevID].lpQueueHdr = (LPMIDIHDR16)lpMidiHdr->lpNext;
+	    if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, (DWORD)lpMidiHdr->reserved, dwTime) != MMSYSERR_NOERROR) {
 		WARN(midi, "Couldn't notify client\n");
 	    }
 	}
@@ -452,20 +455,7 @@
 #endif /* HAVE_OSS */
     
     MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
-    switch (MidiInDev[wDevID].wFlags) {
-    case DCB_NULL:
-	TRACE(midi,"CALLBACK_NULL !\n");
-	break;
-    case DCB_WINDOW:
-	TRACE(midi, "CALLBACK_WINDOW !\n");
-	break;
-    case DCB_TASK:
-	TRACE(midi, "CALLBACK_TASK !\n");
-	break;
-    case DCB_FUNCTION:
-	TRACE(midi, "CALLBACK_FUNCTION (%08lX)!\n", lpDesc->dwCallback);
-	break;
-    }
+
     MidiInDev[wDevID].lpQueueHdr = NULL;
     MidiInDev[wDevID].dwTotalPlayed = 0;
     MidiInDev[wDevID].bufsize = 0x3FFF;
@@ -541,7 +531,7 @@
     TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
     
     if (lpMidiHdr == NULL)	return MMSYSERR_INVALPARAM;
-    if (sizeof(MIDIHDR16) != dwSize) return MMSYSERR_INVALPARAM;
+    if (sizeof(MIDIHDR16) > dwSize) return MMSYSERR_INVALPARAM;
     if (lpMidiHdr->dwBufferLength == 0) return MMSYSERR_INVALPARAM;
     if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
     if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;
@@ -566,7 +556,7 @@
 {
     TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
     
-    if (dwSize != sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
+    if (dwSize < sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
 	lpMidiHdr->lpData == 0 || lpMidiHdr->dwFlags != 0 || 
 	lpMidiHdr->dwBufferLength >= 0x10000ul)
 	return MMSYSERR_INVALPARAM;
@@ -585,7 +575,7 @@
 {
     TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
     
-    if (dwSize != sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
+    if (dwSize < sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
 	lpMidiHdr->lpData == 0 || lpMidiHdr->dwBufferLength >= 0x10000ul)
 	return MMSYSERR_INVALPARAM;
     
@@ -609,6 +599,7 @@
     while (MidiInDev[wDevID].lpQueueHdr) {
 	MidiInDev[wDevID].lpQueueHdr->dwFlags &= ~MHDR_INQUEUE;
 	MidiInDev[wDevID].lpQueueHdr->dwFlags |= MHDR_DONE;
+	/* FIXME: when called from 16 bit, lpQueueHdr needs to be a segmented ptr */
 	if (MIDI_NotifyClient(wDevID, MIM_LONGDATA, 
 			      (DWORD)MidiInDev[wDevID].lpQueueHdr, dwTime) != MMSYSERR_NOERROR) {
 	    WARN(midi, "Couldn't notify client\n");
@@ -894,20 +885,7 @@
 #endif /* HAVE_OSS */	
     
     MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
-    switch (MidiOutDev[wDevID].wFlags) {
-    case DCB_NULL:
-	TRACE(midi,"CALLBACK_NULL !\n");
-	break;
-    case DCB_WINDOW:
-	TRACE(midi, "CALLBACK_WINDOW !\n");
-	break;
-    case DCB_TASK:
-	TRACE(midi, "CALLBACK_TASK !\n");
-	break;
-    case DCB_FUNCTION:
-	TRACE(midi, "CALLBACK_FUNCTION !\n");
-	break;
-    }
+
     MidiOutDev[wDevID].lpQueueHdr = NULL;
     MidiOutDev[wDevID].dwTotalPlayed = 0;
     MidiOutDev[wDevID].bufsize = 0x3FFF;
@@ -1285,7 +1263,8 @@
 static DWORD modLongData(WORD wDevID, LPMIDIHDR16 lpMidiHdr, DWORD dwSize)
 {
     int		count;
-    
+    LPBYTE	lpData;
+
     TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
     
 #ifdef HAVE_OSS
@@ -1300,7 +1279,10 @@
     }
 #endif /* HAVE_OSS */
     
-    if (lpMidiHdr->lpData == NULL) 
+    lpData = ((DWORD)lpMidiHdr == lpMidiHdr->reserved) ?
+	(LPBYTE)lpMidiHdr->lpData : (LPBYTE)PTR_SEG_TO_LIN(lpMidiHdr->lpData);
+
+    if (lpData == NULL) 
 	return MIDIERR_UNPREPARED;
     if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) 
 	return MIDIERR_UNPREPARED;
@@ -1309,33 +1291,39 @@
     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 latest is true, then the following WARNing will fire up
+     */
+    if (lpData[0] != 0xF0 || lpData[lpMidiHdr->dwBytesRecorded - 1] != 0xF7) {
+	WARN(midi, "Alledged system exclusive buffer is not correct\nPlease report with MIDI file\n");
+    }
+
     TRACE(midi, "dwBytesRecorded %lu !\n", lpMidiHdr->dwBytesRecorded);
     TRACE(midi, "                 %02X %02X %02X %02X\n",
-	  ((LPBYTE)(lpMidiHdr->reserved))[0],
-	  ((LPBYTE)(lpMidiHdr->reserved))[1],
-	  ((LPBYTE)(lpMidiHdr->reserved))[2],
-	  ((LPBYTE)(lpMidiHdr->reserved))[3]);
+	  lpData[0], lpData[1], lpData[2], lpData[3]);
+
 #ifdef HAVE_OSS
     switch (midiOutDevices[wDevID]->wTechnology) {
     case MOD_FMSYNTH:
 	/* FIXME: I don't think there is much to do here */
 	break;
     case MOD_MIDIPORT:
-	if (((LPBYTE)lpMidiHdr->reserved)[0] != 0xF0) {
+	if (lpData[0] != 0xF0) {
 	    /* Send end of System Exclusive */
 	    SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF0);
-	    TRACE(midi, "Adding missing 0xF0 marker at the begining of "
-		  "system exclusive byte stream\n");
+	    WARN(midi, "Adding missing 0xF0 marker at the begining of "
+		 "system exclusive byte stream\n");
 	}
 	for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) {
-	    SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 
-			((LPBYTE)lpMidiHdr->reserved)[count]);	
+	    SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, lpData[count]);	
 	}
-	if (((LPBYTE)lpMidiHdr->reserved)[count - 1] != 0xF7) {
+	if (lpData[count - 1] != 0xF7) {
 	    /* Send end of System Exclusive */
 	    SEQ_MIDIOUT(wDevID - MODM_NUMFMSYNTHDEVS, 0xF7);
-	    TRACE(midi, "Adding missing 0xF7 marker at the end of "
-		  "system exclusive byte stream\n");
+	    WARN(midi, "Adding missing 0xF7 marker at the end of "
+		 "system exclusive byte stream\n");
 	}
 	SEQ_DUMPBUF();
 	break;
@@ -1346,14 +1334,13 @@
     }
 #else /* HAVE_OSS */
     {
-	LPWORD	ptr = (LPWORD)lpMidiHdr->reserved;
-	int		en;
+	int	en;
 	
 	for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) {
 	    if (write(MidiOutDev[wDevID].unixdev, 
-		      ptr, sizeof(WORD)) != sizeof(WORD)) 
+		      lpData, sizeof(WORD)) != sizeof(WORD)) 
 		break;
-	    ptr++;
+	    ptr += 2;
 	}
 	
 	en = errno;
@@ -1370,7 +1357,7 @@
     
     lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
     lpMidiHdr->dwFlags |= MHDR_DONE;
-    if (MIDI_NotifyClient(wDevID, MOM_DONE, (DWORD)lpMidiHdr, 0L) != MMSYSERR_NOERROR) {
+    if (MIDI_NotifyClient(wDevID, MOM_DONE, lpMidiHdr->reserved, 0L) != MMSYSERR_NOERROR) {
 	WARN(midi,"can't notify client !\n");
 	return MMSYSERR_INVALPARAM;
     }
@@ -1395,10 +1382,13 @@
 	return MMSYSERR_NOTENABLED;
     }
 #endif /* HAVE_OSS */
-    if (dwSize != sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
+    if (dwSize < sizeof(MIDIHDR16) || lpMidiHdr == 0 || 
 	lpMidiHdr->lpData == 0 || lpMidiHdr->dwFlags != 0 || 
-	lpMidiHdr->dwBufferLength >= 0x10000ul)
+	lpMidiHdr->dwBufferLength >= 0x10000ul) {
+	WARN(midi, "%p %p %08lx %d/%ld\n", lpMidiHdr, lpMidiHdr->lpData, 
+	           lpMidiHdr->dwFlags, sizeof(MIDIHDR16), dwSize);
 	return MMSYSERR_INVALPARAM;
+    }
     
     lpMidiHdr->lpNext = 0;
     lpMidiHdr->dwFlags |= MHDR_PREPARED;
@@ -1424,7 +1414,7 @@
 	return MMSYSERR_NOTENABLED;
     }
 #endif /* HAVE_OSS */
-    if (dwSize != sizeof(MIDIHDR16) || lpMidiHdr == 0)
+    if (dwSize < sizeof(MIDIHDR16) || lpMidiHdr == 0)
 	return MMSYSERR_INVALPARAM;
     if (lpMidiHdr->dwFlags & MHDR_INQUEUE)
 	return MIDIERR_STILLPLAYING;
@@ -1511,7 +1501,7 @@
     case MODM_UNPREPARE:
 	return modUnprepare(wDevID, (LPMIDIHDR16)dwParam1, dwParam2);
     case MODM_GETDEVCAPS:
-	return modGetDevCaps(wDevID,(LPMIDIOUTCAPS16)dwParam1,dwParam2);
+	return modGetDevCaps(wDevID, (LPMIDIOUTCAPS16)dwParam1, dwParam2);
     case MODM_GETNUMDEVS:
 	return MODM_NUMDEVS;
     case MODM_GETVOLUME:
@@ -1531,7 +1521,7 @@
  * 				MIDI_DriverProc32	[sample driver]
  */
 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, DWORD wMsg, 
-		       DWORD dwParam1, DWORD dwParam2)
+		     DWORD dwParam1, DWORD dwParam2)
 {
     switch (wMsg) {
     case DRV_LOAD:		return 1;