Release 980118

Sun Jan 18 17:05:58 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [include/stackframe.h] [tools/build.c]
	Some cleanups in stack frame building.

	* [misc/port.c]
	Implemented clone() wrapper for libc5 users.

	* [scheduler/mutex.c] [scheduler/synchro.c]
	Implemented abandoned mutexes.

	* [scheduler/process.c] [scheduler/thread.c]
	We now create a process and a thread structure as soon as possible
	during initialization.

	* [scheduler/thread.c] [scheduler/sysdeps.c]
	Moved system-specific thread handling to sysdeps.c.

Fri Jan 16 10:45:15 1998  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [graphics/ddraw.c][include/ddraw.h]
	Surface handling enhanced. Some stuff already works ;)

	* [multimedia/dsound.c][include/dsound.h]
	Implemented using the Open Sound System.
	Slowly starts to work (sounds terrible for some programs).

	* [configure.in][multimedia/audio.c][include/config.h.in]
	Added check for OpenSoundSystem, fixed -lXxf86dga check.
	Replaced OS #ifdefs by #ifdef HAVE_OSS in mm/audio.c.

	* [if1632/relay.c][relay32/relay386.c]
	Do not print control characters for 'str' or 'wstr' args.

	* [misc/registry.c]
	"" seems to equals NULL in keynames. Replace where needed. Seems
	to help the win95 regedit.exe...

	* [win32/newfns.c]
	Implemented QueryPerformance* using gettimeofday(2)
	(should be done using the pentium timers probably).

	* [tools/ipcl]
	Removed useless open_pipe construct.

Sun Jan 11 17:10:02 1998  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/region.c] [include/region.h] [graphics/x11drv/clipping.c]
	Regions are now internal to Wine. The basis of this code is taken
	from the X11 distribution. GetRegionData() is implemented as is 
	ExtCreateRegion() (without Xforms). CreatePolyPolygonRgn() should
	behave correctly now. 

	* [objects/metafile.c] [graphics/metafiledrv/graphics.c]
	  [graphics/metafiledrv/init.c] [include/metafile.h]
	  [include/metafiledrv.h]
	Playback of META_CREATEREGION should now work. Implemented recording
	of META_CREATEREGION and META_PAINTREGION.

	* [graphics/x11drv/graphics.c]
	FillRgn() (and therefore its friends) respect logical co-ords.

Wed Jan  7 01:21:45 1998  Steinar Hamre  <steinarh@stud.fim.ntnu.no>

	* [configure.in] [include/acconfig.h] [tools/build.c]
	Now checking whether to use .string or .ascii.

	* [configure.in] [include/acconfig.h] [scheduler/critsection.c]
	Defining union semun if this is not available from header files.

	* [misc/lstr.c]
	Moved wine's own header files below <wctype.h> to avoid
	parse error on Solaris.

Sun Jan  4 15:38:07 1998  Andrew Taylor <ataylor@cadvision.com>

	* [multimedia/mmsystem.c] [multimedia/mmio.c]
	Implemented mmioSendMessage and rearranged the mmio
	subsystem in terms of this function.

Wed Dec 24 00:51:29 1997  Charles Duffy <cduffy@bigfoot.com>

	* [windows/clipboard.c] [relay32/user32.spec]
	GetPriorityClipboardFormat32 now has something other than just
	a stub. I have no idea if it works (can't test until
	SetClipboardData is finished) but HEdit likes things a lot more
	this way.
diff --git a/multimedia/mmio.c b/multimedia/mmio.c
new file mode 100644
index 0000000..d140fe1
--- /dev/null
+++ b/multimedia/mmio.c
@@ -0,0 +1,674 @@
+/*
+ * MMIO functions
+ *
+ * Copyright 1998 Andrew Taylor
+ *
+ * NOTES:  I/O is still unbuffered;  mmioSetBuffer must be implemented
+ * and mmio{Read,Write,Seek,others?} need buffer support.
+ * Buffering should almost give us memory files for free.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "windows.h"
+#include "win.h"
+#include "heap.h"
+#include "user.h"
+#include "file.h"
+#include "mmsystem.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+/**************************************************************************
+*               mmioDosIOProc           [internal]
+*/
+static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
+	dprintf_mmio(stddeb, "mmioDosIOProc(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
+
+	switch (uMessage) {
+
+		case MMIOM_OPEN: {
+			/* Parameters:
+			 * lParam1 = szFileName parameter from mmioOpen
+			 * lParam2 = unused
+			 * Returns: zero on success, error code on error
+			 * NOTE: lDiskOffset automatically set to zero
+			 */
+
+			OFSTRUCT ofs;
+			LPSTR szFileName = (LPSTR) lParam1;
+
+			if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
+				dprintf_mmio(stdnimp, "mmioDosIOProc // MMIO_GETTEMP not implemented\n");
+				return MMIOERR_CANNOTOPEN;
+			}
+
+			/* if filename NULL, assume open file handle in adwInfo[0] */
+			if (!szFileName)
+				return 0;
+
+			lpmmioinfo->adwInfo[0] =
+				(DWORD) OpenFile32(szFileName, &ofs, lpmmioinfo->dwFlags);
+			if (lpmmioinfo->adwInfo[0] == -1)
+				return MMIOERR_CANNOTOPEN;
+
+			return 0;
+		}
+
+		case MMIOM_CLOSE: {
+			/* Parameters:
+			 * lParam1 = wFlags parameter from mmioClose
+			 * lParam2 = unused
+			 * Returns: zero on success, error code on error
+			 */
+
+			UINT16 uFlags = (UINT16) lParam1;
+
+			if (uFlags & MMIO_FHOPEN)
+				return 0;
+
+			_lclose32((HFILE32)lpmmioinfo->adwInfo[0]);
+			return 0;
+
+		}
+
+		case MMIOM_READ: {
+			/* Parameters:
+			 * lParam1 = huge pointer to read buffer
+			 * lParam2 = number of bytes to read
+			 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
+			 *	   in wErrorRet)
+			 * NOTE: lDiskOffset should be updated
+			 */
+
+			HPSTR pch = (HPSTR) lParam1;
+			LONG cch = (LONG) lParam2;
+			LONG count;
+
+			count = _lread32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
+			if (count != -1)
+				lpmmioinfo->lDiskOffset += count;
+
+			return count;
+		}
+
+		case MMIOM_WRITE:
+		case MMIOM_WRITEFLUSH: { 
+			/* no internal buffering, so WRITEFLUSH handled same as WRITE */
+
+			/* Parameters:
+			 * lParam1 = huge pointer to write buffer
+			 * lParam2 = number of bytes to write
+			 * Returns: number of bytes written, -1 for error (error code in
+			 *		wErrorRet)
+			 * NOTE: lDiskOffset should be updated
+			 */
+
+			HPSTR pch = (HPSTR) lParam1;
+			LONG cch = (LONG) lParam2;
+			LONG count;
+
+			count = _hwrite16((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
+			if (count != -1)
+				lpmmioinfo->lDiskOffset += count;
+
+			return count;
+		}
+
+		case MMIOM_SEEK: {
+            /* Parameters:
+             * lParam1 = new position
+             * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
+             * Returns: new file postion, -1 on error
+             * NOTE: lDiskOffset should be updated
+             */
+
+            LONG Offset = (LONG) lParam1; 
+            LONG Whence = (LONG) lParam2; 
+            LONG pos;
+
+            pos = _llseek32((HFILE32)lpmmioinfo->adwInfo[0], Offset, Whence);
+            if (pos != -1)
+                lpmmioinfo->lDiskOffset = pos;
+
+            return pos;
+		}
+		  
+		case MMIOM_RENAME: {
+            /* Parameters:
+             * lParam1 = old name
+             * lParam2 = new name
+             * Returns: zero on success, non-zero on failure
+             */
+
+            dprintf_mmio(stddeb, "mmioDosIOProc: MMIOM_RENAME unimplemented\n");
+            return MMIOERR_FILENOTFOUND;
+		}
+
+		default:
+			dprintf_mmio(stddeb, "mmioDosIOProc: unexpected message %u\n", uMessage);
+			return 0;
+	}
+	
+	return 0;
+}
+
+/**************************************************************************
+*               mmioDosIOProc           [internal]
+*/
+static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
+	return 0;
+}
+
+/**************************************************************************
+ * 				mmioOpenW       		[WINMM.123]
+ */
+HMMIO32 WINAPI mmioOpen32W(LPWSTR szFileName, MMIOINFO32 * lpmmioinfo,
+                          DWORD dwOpenFlags)
+{
+	LPSTR	szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
+	HMMIO32 ret = mmioOpen16(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
+
+	HeapFree(GetProcessHeap(),0,szFn);
+	return ret;
+}
+
+/**************************************************************************
+ * 				mmioOpenA       		[WINMM.122]
+ */
+HMMIO32 WINAPI mmioOpen32A(LPSTR szFileName, MMIOINFO32 * lpmmioinfo,
+                          DWORD dwOpenFlags)
+{
+	return mmioOpen16(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
+}
+
+/**************************************************************************
+ * 				mmioOpen       		[MMSYSTEM.1210]
+ */
+HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
+                          DWORD dwOpenFlags)
+{
+	LPMMIOINFO16 lpmminfo;
+	HMMIO16 hmmio;
+	UINT16 result;
+
+	dprintf_mmio(stddeb, "mmioOpen('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
+
+	hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL)
+		return 0;
+	memset(lpmminfo, 0, sizeof(MMIOINFO16));
+
+	/* assume DOS file if not otherwise specified */
+	if (!lpmmioinfo ||
+		(lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
+
+		lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
+		lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
+	}
+	/* if just the four character code is present, look up IO proc */
+	else if (lpmmioinfo->pIOProc == NULL) {
+
+		lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
+		lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
+
+	} 
+	/* if IO proc specified, use it and specified four character code */
+	else {
+
+		lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
+		lpmminfo->pIOProc = lpmmioinfo->pIOProc;
+	}
+
+	if (dwOpenFlags & MMIO_ALLOCBUF) {
+		if ((result = mmioSetBuffer(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
+			if (lpmmioinfo)
+				lpmmioinfo->wErrorRet = result;
+			return 0;
+		}
+	}
+
+	lpmminfo->hmmio = hmmio;
+
+	/* call IO proc to actually open file */
+	result = (UINT16) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) 0);
+
+	GlobalUnlock16(hmmio);
+
+	if (result != 0) {
+		GlobalFree16(hmmio);
+		return 0;
+	}
+
+	return hmmio;
+}
+
+    
+/**************************************************************************
+* 				mmioClose      		[MMSYSTEM.1211]
+*/
+UINT16 WINAPI mmioClose(HMMIO16 hmmio, UINT16 uFlags)
+{
+	LPMMIOINFO16 lpmminfo;
+	UINT16 result;
+
+	dprintf_mmio(stddeb, "mmioClose(%04X, %04X);\n", hmmio, uFlags);
+
+	lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
+	if (lpmminfo == NULL)
+		return 0;
+
+	/* flush the file - if error reported, ignore */
+	if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
+		lpmminfo->dwFlags &= ~MMIO_DIRTY;
+
+	result = (UINT16) mmioSendMessage(hmmio, MMIOM_CLOSE, (LPARAM) uFlags, (LPARAM) 0);
+
+	mmioSetBuffer(hmmio, NULL, 0, 0);
+
+	GlobalUnlock16(hmmio);
+	GlobalFree16(hmmio);
+
+	return result;
+}
+
+
+
+/**************************************************************************
+* 				mmioRead	       	[MMSYSTEM.1212]
+*/
+LONG WINAPI mmioRead(HMMIO16 hmmio, HPSTR pch, LONG cch)
+{
+	LONG count;
+	LPMMIOINFO16 lpmminfo;
+
+	dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch);
+
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL)
+		return -1;
+
+	count = mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
+
+	GlobalUnlock16(hmmio);
+	dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count);
+	return count;
+}
+
+
+
+/**************************************************************************
+* 				mmioWrite      		[MMSYSTEM.1213]
+*/
+LONG WINAPI mmioWrite(HMMIO16 hmmio, HPCSTR pch, LONG cch)
+{
+	LONG count;
+	LPMMIOINFO16 lpmminfo;
+
+	dprintf_mmio(stddeb, "mmioWrite(%04X, %p, %ld);\n", hmmio, pch, cch);
+
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL)
+		return -1;
+
+	count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
+
+	GlobalUnlock16(hmmio);
+	dprintf_mmio(stddeb, "mmioWrite // count=%ld\n", count);
+	return count;
+}
+
+/**************************************************************************
+* 				mmioSeek       		[MMSYSTEM.1214]
+*/
+LONG WINAPI mmioSeek(HMMIO16 hmmio, LONG lOffset, int iOrigin)
+{
+	int offset;
+	LPMMIOINFO16 lpmminfo;
+
+	dprintf_mmio(stddeb, "mmioSeek(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
+
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL)
+		return 0;
+
+    offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
+
+	GlobalUnlock16(hmmio);
+	return offset;
+}
+
+/**************************************************************************
+* 				mmioGetInfo	       	[MMSYSTEM.1215]
+*/
+UINT16 WINAPI mmioGetInfo(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+	LPMMIOINFO16	lpmminfo;
+	dprintf_mmio(stddeb, "mmioGetInfo\n");
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL) return 0;
+	memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
+	GlobalUnlock16(hmmio);
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioSetInfo    		[MMSYSTEM.1216]
+*/
+UINT16 WINAPI mmioSetInfo(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+	LPMMIOINFO16	lpmminfo;
+	dprintf_mmio(stddeb, "mmioSetInfo\n");
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL) return 0;
+	GlobalUnlock16(hmmio);
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioSetBuffer		[MMSYSTEM.1217]
+*/
+UINT16 WINAPI mmioSetBuffer(HMMIO16 hmmio, LPSTR pchBuffer, 
+                            LONG cchBuffer, UINT16 uFlags)
+{
+	dprintf_mmio(stddeb, "mmioSetBuffer // empty stub \n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioFlush      		[MMSYSTEM.1218]
+*/
+UINT16 WINAPI mmioFlush(HMMIO16 hmmio, UINT16 uFlags)
+{
+	LPMMIOINFO16	lpmminfo;
+	dprintf_mmio(stddeb, "mmioFlush(%04X, %04X)\n", hmmio, uFlags);
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL) return 0;
+	GlobalUnlock16(hmmio);
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioAdvance    		[MMSYSTEM.1219]
+*/
+UINT16 WINAPI mmioAdvance(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
+{
+	int		count = 0;
+	LPMMIOINFO16	lpmminfo;
+	dprintf_mmio(stddeb, "mmioAdvance\n");
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+	if (lpmminfo == NULL) return 0;
+	if (uFlags == MMIO_READ) {
+		count = _lread32(LOWORD(lpmminfo->adwInfo[0]), 
+			lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
+		}
+	if (uFlags == MMIO_WRITE) {
+		count = _lwrite32(LOWORD(lpmminfo->adwInfo[0]),
+			lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
+		}
+	lpmmioinfo->pchNext	+= count;
+	GlobalUnlock16(hmmio);
+	lpmminfo->lDiskOffset = _llseek32((HFILE32)lpmminfo->adwInfo[0], 0, SEEK_CUR);
+	return 0;
+}
+
+/**************************************************************************
+ * 				mmioStringToFOURCCA	[WINMM.131]
+ */
+FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
+{
+	return mmioStringToFOURCC16(sz,uFlags);
+}
+
+/**************************************************************************
+ * 				mmioStringToFOURCCW	[WINMM.132]
+ */
+FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
+{
+	LPSTR	szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
+	FOURCC	ret = mmioStringToFOURCC32A(szA,uFlags);
+
+	HeapFree(GetProcessHeap(),0,szA);
+	return ret;
+}
+
+/**************************************************************************
+ * 				mmioStringToFOURCC	[MMSYSTEM.1220]
+ */
+FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
+{
+	dprintf_mmio(stddeb, "mmioStringToFOURCC // empty stub \n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioInstallIOProc16	[MMSYSTEM.1221]
+*/
+LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc, 
+                                        LPMMIOPROC16 pIOProc, DWORD dwFlags)
+{
+	dprintf_mmio(stddeb, "mmioInstallIOProc(%ld, %p, %08lX)\n",
+				 fccIOProc, pIOProc, dwFlags);
+
+	if (dwFlags & MMIO_GLOBALPROC) {
+		fprintf(stdnimp, "mmioInstallIOProc: global procedures not "
+				"implemented\n");
+	}
+
+	/* just handle the known procedures for now */
+	switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
+		case MMIO_INSTALLPROC:
+			return NULL;
+		case MMIO_REMOVEPROC:
+			return NULL;
+		case MMIO_FINDPROC:
+			if (fccIOProc == FOURCC_DOS)
+				return (LPMMIOPROC16) mmioDosIOProc;
+			else if (fccIOProc == FOURCC_MEM)
+				return (LPMMIOPROC16) mmioMemIOProc;
+			else
+				return NULL;
+		default:
+			return NULL;
+	}
+}
+
+/**************************************************************************
+ * 				mmioInstallIOProc32A   [WINMM.120]
+ */
+LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc, 
+                                         LPMMIOPROC32 pIOProc, DWORD dwFlags)
+{
+	dprintf_mmio(stddeb, "mmioInstallIOProcA (%c%c%c%c,%p,0x%08lx)// empty stub \n",
+                     (char)((fccIOProc&0xff000000)>>24),
+                     (char)((fccIOProc&0x00ff0000)>>16),
+                     (char)((fccIOProc&0x0000ff00)>> 8),
+                     (char)(fccIOProc&0x000000ff),
+                     pIOProc, dwFlags );
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioSendMessage		[MMSYSTEM.1222]
+*/
+LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
+                               LPARAM lParam1, LPARAM lParam2)
+{
+	LPMMIOINFO16 lpmminfo;
+	LRESULT result;
+	const char *msg = NULL;
+
+#ifdef DEBUG_RUNTIME
+	switch (uMessage) {
+#define msgname(x) case x: msg = #x; break;
+		msgname(MMIOM_OPEN);
+		msgname(MMIOM_CLOSE);
+		msgname(MMIOM_READ);
+		msgname(MMIOM_WRITE);
+		msgname(MMIOM_WRITEFLUSH);
+		msgname(MMIOM_SEEK);
+		msgname(MMIOM_RENAME);
+#undef msgname
+	}
+#endif
+
+	if (msg)
+		dprintf_mmio(stddeb, "mmioSendMessage(%04X, %s, %ld, %ld)\n",
+					 hmmio, msg, lParam1, lParam2);
+	else
+		dprintf_mmio(stddeb, "mmioSendMessage(%04X, %u, %ld, %ld)\n",
+					 hmmio, uMessage, lParam1, lParam2);
+	
+	lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
+
+	if (lpmminfo && lpmminfo->pIOProc)
+		result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
+	else
+		result = MMSYSERR_INVALPARAM;
+
+	GlobalUnlock16(hmmio);
+
+	return result;
+}
+
+/**************************************************************************
+* 				mmioDescend	       	[MMSYSTEM.1223]
+*/
+UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
+                          const MMCKINFO * lpckParent, UINT16 uFlags)
+{
+	DWORD	dwfcc, dwOldPos;
+
+	dprintf_mmio(stddeb, "mmioDescend(%04X, %p, %p, %04X);\n", 
+				hmmio, lpck, lpckParent, uFlags);
+
+	if (lpck == NULL)
+	    return 0;
+
+	dwfcc = lpck->ckid;
+	dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX\n", dwfcc);
+
+	dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
+	dprintf_mmio(stddeb, "mmioDescend // dwOldPos=%ld\n", dwOldPos);
+
+	if (lpckParent != NULL) {
+		dprintf_mmio(stddeb, "mmioDescend // seek inside parent at %ld !\n", lpckParent->dwDataOffset);
+		dwOldPos = mmioSeek(hmmio, lpckParent->dwDataOffset, SEEK_SET);
+	}
+/*
+
+   It seems to be that FINDRIFF should not be treated the same as the 
+   other FINDxxx so I treat it as a MMIO_FINDxxx
+
+	if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) || 
+		(uFlags & MMIO_FINDLIST)) {
+*/
+	if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
+		dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
+		while (TRUE) {
+		        LONG ix;
+
+			ix = mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO));
+			dprintf_mmio(stddeb, "mmioDescend // after _lread32 ix = %ld req = %d, errno = %d\n",ix,sizeof(MMCKINFO),errno);
+			if (ix < sizeof(MMCKINFO)) {
+
+				mmioSeek(hmmio, dwOldPos, SEEK_SET);
+				dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound\n");
+				return MMIOERR_CHUNKNOTFOUND;
+			}
+			dprintf_mmio(stddeb, "mmioDescend // dwfcc=%08lX ckid=%08lX cksize=%08lX !\n", 
+									dwfcc, lpck->ckid, lpck->cksize);
+			if (dwfcc == lpck->ckid)
+				break;
+
+			dwOldPos += lpck->cksize + 2 * sizeof(DWORD);
+			if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST) 
+				dwOldPos += sizeof(DWORD);
+			mmioSeek(hmmio, dwOldPos, SEEK_SET);
+		}
+	}
+	else {
+		if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
+			mmioSeek(hmmio, dwOldPos, SEEK_SET);
+			dprintf_mmio(stddeb, "mmioDescend // return ChunkNotFound 2nd\n");
+			return MMIOERR_CHUNKNOTFOUND;
+		}
+	}
+	lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
+	if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST) 
+		lpck->dwDataOffset += sizeof(DWORD);
+	mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
+
+	dprintf_mmio(stddeb, "mmioDescend // lpck->ckid=%08lX lpck->cksize=%ld !\n", 
+								lpck->ckid, lpck->cksize);
+	dprintf_mmio(stddeb, "mmioDescend // lpck->fccType=%08lX !\n", lpck->fccType);
+
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioAscend     		[MMSYSTEM.1224]
+*/
+UINT16 WINAPI mmioAscend(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
+{
+	dprintf_mmio(stddeb, "mmioAscend // empty stub !\n");
+	return 0;
+}
+
+/**************************************************************************
+* 				mmioCreateChunk		[MMSYSTEM.1225]
+*/
+UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
+{
+	dprintf_mmio(stddeb, "mmioCreateChunk // empty stub \n");
+	return 0;
+}
+
+
+/**************************************************************************
+* 				mmioRename     		[MMSYSTEM.1226]
+*/
+UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
+                         MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
+{
+	UINT16 result;
+	LPMMIOINFO16 lpmminfo;
+	HMMIO16 hmmio;
+
+	dprintf_mmio(stddeb, "mmioRename('%s', '%s', %p, %08lX);\n",
+				 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
+
+	hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
+	lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
+
+	if (lpmmioinfo)
+		memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
+	
+	/* assume DOS file if not otherwise specified */
+	if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
+
+		lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
+		lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
+
+	}
+	/* if just the four character code is present, look up IO proc */
+	else if (lpmminfo->pIOProc == NULL) {
+
+		lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
+
+	} 
+	/* (if IO proc specified, use it and specified four character code) */
+
+	result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
+	
+	GlobalUnlock16(hmmio);
+	GlobalFree16(hmmio);
+
+	return result;
+}
+