Moved VGA-emulating DirectX code from dispdib.c to a separate
[wine/multimedia.git] / multimedia / mmio.c
blob3428f727fc078b93db1de16e789b13d78ec11f7d
1 /*
2 * MMIO functions
4 * Copyright 1998 Andrew Taylor
5 * Copyright 1998 Ove Kåven
7 */
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include "windows.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "file.h"
18 #include "mmsystem.h"
19 #include "debug.h"
20 #include "xmalloc.h"
22 /**************************************************************************
23 * mmioDosIOProc [internal]
25 static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
26 TRACE(mmio, "(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
28 switch (uMessage) {
30 case MMIOM_OPEN: {
31 /* Parameters:
32 * lParam1 = szFileName parameter from mmioOpen
33 * lParam2 = reserved (we use it for 16-bitness)
34 * Returns: zero on success, error code on error
35 * NOTE: lDiskOffset automatically set to zero
38 OFSTRUCT ofs;
39 LPSTR szFileName = (LPSTR) lParam1;
41 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
42 FIXME(mmio, "MMIO_GETTEMP not implemented\n");
43 return MMIOERR_CANNOTOPEN;
46 /* if filename NULL, assume open file handle in adwInfo[0] */
47 if (!szFileName) {
48 if (lParam2) lpmmioinfo->adwInfo[0] =
49 HFILE16_TO_HFILE32(lpmmioinfo->adwInfo[0]);
50 return 0;
53 lpmmioinfo->adwInfo[0] =
54 (DWORD) OpenFile32(szFileName, &ofs, lpmmioinfo->dwFlags);
55 if (lpmmioinfo->adwInfo[0] == -1)
56 return MMIOERR_CANNOTOPEN;
58 return 0;
61 case MMIOM_CLOSE: {
62 /* Parameters:
63 * lParam1 = wFlags parameter from mmioClose
64 * lParam2 = unused
65 * Returns: zero on success, error code on error
68 UINT16 uFlags = (UINT16) lParam1;
70 if (uFlags & MMIO_FHOPEN)
71 return 0;
73 _lclose32((HFILE32)lpmmioinfo->adwInfo[0]);
74 return 0;
78 case MMIOM_READ: {
79 /* Parameters:
80 * lParam1 = huge pointer to read buffer
81 * lParam2 = number of bytes to read
82 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
83 * in wErrorRet)
84 * NOTE: lDiskOffset should be updated
87 HPSTR pch = (HPSTR) lParam1;
88 LONG cch = (LONG) lParam2;
89 LONG count;
91 count = _lread32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
92 if (count != -1)
93 lpmmioinfo->lDiskOffset += count;
95 return count;
98 case MMIOM_WRITE:
99 case MMIOM_WRITEFLUSH: {
100 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
102 /* Parameters:
103 * lParam1 = huge pointer to write buffer
104 * lParam2 = number of bytes to write
105 * Returns: number of bytes written, -1 for error (error code in
106 * wErrorRet)
107 * NOTE: lDiskOffset should be updated
110 HPSTR pch = (HPSTR) lParam1;
111 LONG cch = (LONG) lParam2;
112 LONG count;
114 count = _hwrite32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
115 if (count != -1)
116 lpmmioinfo->lDiskOffset += count;
118 return count;
121 case MMIOM_SEEK: {
122 /* Parameters:
123 * lParam1 = new position
124 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
125 * Returns: new file postion, -1 on error
126 * NOTE: lDiskOffset should be updated
129 LONG Offset = (LONG) lParam1;
130 LONG Whence = (LONG) lParam2;
131 LONG pos;
133 pos = _llseek32((HFILE32)lpmmioinfo->adwInfo[0], Offset, Whence);
134 if (pos != -1)
135 lpmmioinfo->lDiskOffset = pos;
137 return pos;
140 case MMIOM_RENAME: {
141 /* Parameters:
142 * lParam1 = old name
143 * lParam2 = new name
144 * Returns: zero on success, non-zero on failure
147 FIXME(mmio, "MMIOM_RENAME unimplemented\n");
148 return MMIOERR_FILENOTFOUND;
151 default:
152 FIXME(mmio, "unexpected message %u\n", uMessage);
153 return 0;
156 return 0;
159 /**************************************************************************
160 * mmioMemIOProc [internal]
162 static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
163 TRACE(mmio,"(%p,0x%04x,0x%08lx,0x%08lx)\n",lpmmioinfo,uMessage,lParam1,lParam2);
164 switch (uMessage) {
166 case MMIOM_OPEN: {
167 /* Parameters:
168 * lParam1 = filename (must be NULL)
169 * lParam2 = reserved (we use it for 16-bitness)
170 * Returns: zero on success, error code on error
171 * NOTE: lDiskOffset automatically set to zero
174 if (!(lpmmioinfo->dwFlags & MMIO_CREATE))
175 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite;
177 return 0;
180 case MMIOM_CLOSE: {
181 /* Parameters:
182 * lParam1 = wFlags parameter from mmioClose
183 * lParam2 = unused
184 * Returns: zero on success, error code on error
187 return 0;
191 case MMIOM_READ: {
192 /* Parameters:
193 * lParam1 = huge pointer to read buffer
194 * lParam2 = number of bytes to read
195 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
196 * in wErrorRet)
197 * NOTE: lDiskOffset should be updated
200 HPSTR pch = (HPSTR) lParam1;
201 LONG cch = (LONG) lParam2;
203 FIXME(mmio,"MMIOM_READ on memory files should not occur, buffer may be lost!\n");
204 return 0;
207 case MMIOM_WRITE:
208 case MMIOM_WRITEFLUSH: {
209 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
211 /* Parameters:
212 * lParam1 = huge pointer to write buffer
213 * lParam2 = number of bytes to write
214 * Returns: number of bytes written, -1 for error (error code in
215 * wErrorRet)
216 * NOTE: lDiskOffset should be updated
219 HPSTR pch = (HPSTR) lParam1;
220 LONG cch = (LONG) lParam2;
222 FIXME(mmio,"MMIOM_WRITE on memory files should not occur, buffer may be lost!\n");
223 return 0;
226 case MMIOM_SEEK: {
227 /* Parameters:
228 * lParam1 = new position
229 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
230 * Returns: new file postion, -1 on error
231 * NOTE: lDiskOffset should be updated
234 LONG Offset = (LONG) lParam1;
235 LONG Whence = (LONG) lParam2;
237 FIXME(mmio,"MMIOM_SEEK on memory files should not occur, buffer may be lost!\n");
238 return -1;
241 default:
242 FIXME(mmio, "unexpected message %u\n", uMessage);
243 return 0;
246 return 0;
249 /**************************************************************************
250 * MMIO_Open [internal]
252 static HMMIO16 MMIO_Open(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
253 DWORD dwOpenFlags, int use16)
255 LPMMIOINFO16 lpmminfo;
256 HMMIO16 hmmio;
257 UINT16 result;
259 TRACE(mmio, "('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
261 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
262 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
263 if (lpmminfo == NULL)
264 return 0;
265 memset(lpmminfo, 0, sizeof(MMIOINFO16));
267 /* assume DOS file if not otherwise specified */
268 if (!lpmmioinfo ||
269 (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
271 lpmminfo->fccIOProc = FOURCC_DOS;
272 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
274 /* if just the four character code is present, look up IO proc */
275 else if (lpmmioinfo->pIOProc == NULL) {
277 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
278 lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
281 /* if IO proc specified, use it and specified four character code */
282 else {
284 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
285 lpmminfo->pIOProc = lpmmioinfo->pIOProc;
288 if (dwOpenFlags & MMIO_ALLOCBUF) {
289 if ((result = mmioSetBuffer(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
290 if (lpmmioinfo)
291 lpmmioinfo->wErrorRet = result;
292 return 0;
294 } else
295 if (lpmminfo->fccIOProc == FOURCC_MEM) {
296 if ((result = mmioSetBuffer(hmmio, lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer, 0))) {
297 if (lpmmioinfo)
298 lpmmioinfo->wErrorRet = result;
299 return 0;
303 lpmminfo->dwFlags = dwOpenFlags;
304 lpmminfo->hmmio = hmmio;
306 /* call IO proc to actually open file */
307 result = (UINT16) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) use16);
309 GlobalUnlock16(hmmio);
311 if (result != 0) {
312 GlobalFree16(hmmio);
313 return 0;
316 return hmmio;
319 /**************************************************************************
320 * mmioOpenW [WINMM.123]
322 HMMIO32 WINAPI mmioOpen32W(LPWSTR szFileName, MMIOINFO32 * lpmmioinfo,
323 DWORD dwOpenFlags)
325 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
326 HMMIO32 ret = MMIO_Open(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,FALSE);
328 HeapFree(GetProcessHeap(),0,szFn);
329 return ret;
332 /**************************************************************************
333 * mmioOpenA [WINMM.122]
335 HMMIO32 WINAPI mmioOpen32A(LPSTR szFileName, MMIOINFO32 * lpmmioinfo,
336 DWORD dwOpenFlags)
338 return MMIO_Open(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,FALSE);
341 /**************************************************************************
342 * mmioOpen [MMSYSTEM.1210]
344 HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
345 DWORD dwOpenFlags)
347 return MMIO_Open(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags,TRUE);
351 /**************************************************************************
352 * mmioClose [WINMM.114]
354 MMRESULT32 WINAPI mmioClose32(HMMIO32 hmmio, UINT32 uFlags)
356 LPMMIOINFO16 lpmminfo;
357 MMRESULT32 result;
359 TRACE(mmio, "(%04X, %04X);\n", hmmio, uFlags);
361 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
362 if (lpmminfo == NULL)
363 return 0;
365 /* flush the file - if error reported, ignore */
366 if (mmioFlush32(hmmio, MMIO_EMPTYBUF) != 0)
367 lpmminfo->dwFlags &= ~MMIO_DIRTY;
369 result = mmioSendMessage(hmmio,MMIOM_CLOSE,(LPARAM)uFlags,(LPARAM)0);
371 mmioSetBuffer(hmmio, NULL, 0, 0);
373 GlobalUnlock16(hmmio);
374 GlobalFree16(hmmio);
376 return result;
380 /**************************************************************************
381 * mmioClose [MMSYSTEM.1211]
383 MMRESULT16 WINAPI mmioClose16(HMMIO16 hmmio, UINT16 uFlags)
385 return mmioClose32(hmmio,uFlags);
390 /**************************************************************************
391 * mmioRead [WINM.124]
393 LONG WINAPI mmioRead32(HMMIO32 hmmio, HPSTR pch, LONG cch)
395 LONG count;
396 LPMMIOINFO16 lpmminfo;
398 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
400 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
401 if (lpmminfo == NULL)
402 return -1;
404 if (lpmminfo->pchNext != lpmminfo->pchEndRead) {
405 count = lpmminfo->pchEndRead - lpmminfo->pchNext;
406 if (count > cch || count < 0) count = cch;
407 memcpy(pch, lpmminfo->pchNext, count);
408 lpmminfo->pchNext += count;
409 pch += count;
410 cch -= count;
411 } else
412 count = 0;
414 if (cch&&(lpmminfo->fccIOProc!=FOURCC_MEM)) {
415 if (lpmminfo->cchBuffer) {
416 mmioFlush32(hmmio, MMIO_EMPTYBUF);
418 while (cch) {
419 LONG size;
420 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
421 lpmminfo->pchNext = lpmminfo->pchBuffer;
422 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
423 size = mmioSendMessage(hmmio, MMIOM_READ,
424 (LPARAM) lpmminfo->pchBuffer,
425 (LPARAM) lpmminfo->cchBuffer);
426 if (size<=0) break;
427 lpmminfo->pchEndRead = lpmminfo->pchBuffer + size;
428 if (size > cch) size = cch;
429 memcpy(pch, lpmminfo->pchNext, size);
430 lpmminfo->pchNext += size;
431 pch += size;
432 cch -= size;
433 count += size;
435 } else {
436 count += mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
437 if (count>0) lpmminfo->lBufOffset += count;
441 GlobalUnlock16(hmmio);
442 TRACE(mmio, "count=%ld\n", count);
443 return count;
446 /**************************************************************************
447 * mmioRead [MMSYSTEM.1212]
449 LONG WINAPI mmioRead16(HMMIO16 hmmio, HPSTR pch, LONG cch)
451 return mmioRead32(hmmio,pch,cch);
454 /**************************************************************************
455 * mmioWrite [WINMM.133]
457 LONG WINAPI mmioWrite32(HMMIO32 hmmio, HPCSTR pch, LONG cch)
459 LONG count;
460 LPMMIOINFO16 lpmminfo;
462 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
464 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
465 if (lpmminfo == NULL)
466 return -1;
468 if (lpmminfo->cchBuffer) {
469 count = 0;
470 while (cch) {
471 if (lpmminfo->pchNext != lpmminfo->pchEndWrite) {
472 count = lpmminfo->pchEndWrite - lpmminfo->pchNext;
473 if (count > cch || count < 0) count = cch;
474 memcpy(lpmminfo->pchNext, pch, count);
475 lpmminfo->pchNext += count;
476 pch += count;
477 cch -= count;
478 lpmminfo->dwFlags |= MMIO_DIRTY;
479 } else
480 if (lpmminfo->fccIOProc==FOURCC_MEM) {
481 if (lpmminfo->adwInfo[0]) {
482 /* from where would we get the memory handle? */
483 FIXME(mmio, "memory file expansion not implemented!\n");
484 } else break;
487 if (lpmminfo->pchNext == lpmminfo->pchEndWrite
488 && mmioFlush32(hmmio, MMIO_EMPTYBUF)) break;
490 } else {
491 count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
492 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
495 GlobalUnlock16(hmmio);
496 TRACE(mmio, "count=%ld\n", count);
497 return count;
500 /**************************************************************************
501 * mmioWrite [MMSYSTEM.1213]
503 LONG WINAPI mmioWrite16(HMMIO16 hmmio, HPCSTR pch, LONG cch)
505 return mmioWrite32(hmmio,pch,cch);
508 /**************************************************************************
509 * mmioSeek [MMSYSTEM.1214]
511 LONG WINAPI mmioSeek32(HMMIO32 hmmio, LONG lOffset, INT32 iOrigin)
513 int offset;
514 LPMMIOINFO16 lpmminfo;
516 TRACE(mmio, "(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
518 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
519 if (lpmminfo == NULL)
520 return -1;
522 offset = (iOrigin==SEEK_SET)?(lOffset - lpmminfo->lBufOffset):
523 (iOrigin==SEEK_CUR)?(lOffset +
524 (lpmminfo->pchNext - lpmminfo->pchBuffer)):-1;
526 if ((lpmminfo->cchBuffer<0)||
527 ((offset>=0)&&(offset<=(lpmminfo->pchEndRead-lpmminfo->pchBuffer)))) {
528 lpmminfo->pchNext = lpmminfo->pchBuffer + offset;
529 GlobalUnlock16(hmmio);
530 return lpmminfo->lBufOffset + offset;
533 if ((lpmminfo->fccIOProc==FOURCC_MEM)||mmioFlush32(hmmio, MMIO_EMPTYBUF)) {
534 GlobalUnlock16(hmmio);
535 return -1;
538 offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
539 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
541 GlobalUnlock16(hmmio);
542 return offset;
545 /**************************************************************************
546 * mmioSeek [MMSYSTEM.1214]
548 LONG WINAPI mmioSeek16(HMMIO16 hmmio, LONG lOffset, INT16 iOrigin)
550 return mmioSeek32(hmmio,lOffset,iOrigin);
553 /**************************************************************************
554 * mmioGetInfo [MMSYSTEM.1215]
556 UINT16 WINAPI mmioGetInfo16(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
558 LPMMIOINFO16 lpmminfo;
559 TRACE(mmio, "mmioGetInfo\n");
560 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
561 if (lpmminfo == NULL) return 0;
562 memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
563 GlobalUnlock16(hmmio);
564 return 0;
567 /**************************************************************************
568 * mmioGetInfo [WINMM.118]
570 UINT32 WINAPI mmioGetInfo32(HMMIO32 hmmio, MMIOINFO32*lpmmioinfo, UINT32 uFlags)
572 MMIOINFO16 mmioinfo;
573 LPMMIOINFO16 lpmminfo=&mmioinfo;
574 UINT16 ret;
576 TRACE(mmio, "(0x%04x,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
577 ret = mmioGetInfo16(hmmio,&mmioinfo,uFlags);
578 if (!ret)
579 return 0;
580 lpmmioinfo->dwFlags = lpmminfo->dwFlags;
581 lpmmioinfo->fccIOProc = lpmminfo->fccIOProc;
582 lpmmioinfo->pIOProc = (LPMMIOPROC32)lpmminfo->pIOProc;
583 lpmmioinfo->wErrorRet = lpmminfo->wErrorRet;
584 lpmmioinfo->htask = lpmminfo->htask;
585 lpmmioinfo->cchBuffer = lpmminfo->cchBuffer;
586 lpmmioinfo->pchBuffer = lpmminfo->pchBuffer;
587 lpmmioinfo->pchNext = lpmminfo->pchNext;
588 lpmmioinfo->pchEndRead = lpmminfo->pchEndRead;
589 lpmmioinfo->pchEndWrite = lpmminfo->pchEndWrite;
590 lpmmioinfo->lBufOffset = lpmminfo->lBufOffset;
591 lpmmioinfo->lDiskOffset = lpmminfo->lDiskOffset;
592 memcpy(lpmmioinfo->adwInfo,lpmminfo->adwInfo,sizeof(lpmminfo->adwInfo));
593 lpmmioinfo->dwReserved1 = lpmminfo->dwReserved1;
594 lpmmioinfo->dwReserved2 = lpmminfo->dwReserved2;
595 lpmmioinfo->hmmio = lpmminfo->hmmio;
596 return 0;
599 /**************************************************************************
600 * mmioSetInfo [MMSYSTEM.1216]
602 UINT16 WINAPI mmioSetInfo16(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
604 LPMMIOINFO16 lpmminfo;
605 TRACE(mmio, "mmioSetInfo\n");
606 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
607 if (lpmminfo == NULL) return 0;
608 lpmminfo->pchNext = lpmmioinfo->pchNext;
609 lpmminfo->pchEndRead = lpmmioinfo->pchEndRead;
610 GlobalUnlock16(hmmio);
611 return 0;
614 /**************************************************************************
615 * mmioSetInfo [WINMM.130]
617 UINT32 WINAPI mmioSetInfo32(HMMIO32 hmmio, const MMIOINFO32 * lpmmioinfo, UINT32 uFlags)
619 LPMMIOINFO16 lpmminfo;
620 TRACE(mmio, "mmioSetInfo\n");
621 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
622 if (lpmminfo == NULL) return 0;
623 lpmminfo->pchNext = lpmmioinfo->pchNext;
624 lpmminfo->pchEndRead = lpmmioinfo->pchEndRead;
625 GlobalUnlock16(hmmio);
626 return 0;
629 /**************************************************************************
630 * mmioSetBuffer [MMSYSTEM.1217]
632 UINT16 WINAPI mmioSetBuffer(HMMIO16 hmmio, LPSTR pchBuffer,
633 LONG cchBuffer, UINT16 uFlags)
635 LPMMIOINFO16 lpmminfo;
637 if (mmioFlush32(hmmio, MMIO_EMPTYBUF) != 0)
638 return MMIOERR_CANNOTWRITE;
640 TRACE(mmio, "(hmmio=%04x, pchBuf=%p, cchBuf=%ld, uFlags=%#08x)\n",
641 hmmio, pchBuffer, cchBuffer, uFlags);
643 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
644 if (lpmminfo == NULL) return 0;
645 if ((!cchBuffer || pchBuffer) && lpmminfo->dwFlags&MMIO_ALLOCBUF) {
646 GlobalUnlock16(lpmminfo->dwReserved1);
647 GlobalFree16(lpmminfo->dwReserved1);
648 lpmminfo->dwFlags &= ~MMIO_ALLOCBUF;
650 if (pchBuffer) {
651 lpmminfo->pchBuffer = pchBuffer;
652 } else
653 if (lpmminfo->dwFlags&MMIO_ALLOCBUF) {
654 HGLOBAL16 hNewBuf;
655 GlobalUnlock16(lpmminfo->dwReserved1);
656 hNewBuf = GlobalReAlloc16(lpmminfo->dwReserved1, cchBuffer, 0);
657 if (!hNewBuf) {
658 /* FIXME: this assumes the memory block didn't move */
659 GlobalLock16(lpmminfo->dwReserved1);
660 GlobalUnlock16(hmmio);
661 return MMIOERR_OUTOFMEMORY;
663 lpmminfo->dwReserved1 = hNewBuf;
664 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
665 } else
666 if (cchBuffer) {
667 HGLOBAL16 hNewBuf = GlobalAlloc16(GMEM_MOVEABLE, cchBuffer);
668 if (!hNewBuf) {
669 GlobalUnlock16(hmmio);
670 return MMIOERR_OUTOFMEMORY;
672 lpmminfo->dwReserved1 = hNewBuf;
673 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
674 lpmminfo->dwFlags |= MMIO_ALLOCBUF;
675 } else
676 lpmminfo->pchBuffer = NULL;
677 lpmminfo->cchBuffer = cchBuffer;
678 lpmminfo->pchNext = lpmminfo->pchBuffer;
679 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
680 lpmminfo->pchEndWrite = lpmminfo->pchBuffer + cchBuffer;
681 lpmminfo->lBufOffset = 0;
683 GlobalUnlock16(hmmio);
684 return (UINT16) 0;
687 /**************************************************************************
688 * mmioFlush [WINMM.117]
690 UINT32 WINAPI mmioFlush32(HMMIO32 hmmio, UINT32 uFlags)
692 LPMMIOINFO16 lpmminfo;
693 TRACE(mmio, "(%04X, %04X)\n", hmmio, uFlags);
694 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
695 if (lpmminfo == NULL) return 0;
697 if ((!lpmminfo->cchBuffer)||(lpmminfo->fccIOProc==FOURCC_MEM)) {
698 GlobalUnlock16(hmmio);
699 return 0;
701 /* not quite sure what to do here, but I'll guess */
702 if (lpmminfo->dwFlags & MMIO_DIRTY) {
703 mmioSendMessage(hmmio, MMIOM_SEEK,
704 (LPARAM) lpmminfo->lBufOffset,
705 (LPARAM) SEEK_SET);
706 mmioSendMessage(hmmio, MMIOM_WRITE,
707 (LPARAM) lpmminfo->pchBuffer,
708 (LPARAM) (lpmminfo->pchNext - lpmminfo->pchBuffer) );
709 lpmminfo->dwFlags &= ~MMIO_DIRTY;
711 if (uFlags & MMIO_EMPTYBUF) {
712 /* seems Windows doesn't do any seeking here, hopefully this
713 won't matter, otherwise a slight rewrite is necessary */
714 mmioSendMessage(hmmio, MMIOM_SEEK,
715 (LPARAM) (lpmminfo->lBufOffset +
716 (lpmminfo->pchNext - lpmminfo->pchBuffer)),
717 (LPARAM) SEEK_SET);
718 lpmminfo->pchNext = lpmminfo->pchBuffer;
719 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
720 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
723 GlobalUnlock16(hmmio);
724 return 0;
727 /**************************************************************************
728 * mmioFlush [MMSYSTEM.1218]
730 UINT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
732 return mmioFlush32(hmmio,uFlags);
735 /**************************************************************************
736 * mmioAdvance [MMSYSTEM.1219]
738 UINT32 WINAPI mmioAdvance32(HMMIO32 hmmio,MMIOINFO32*lpmmioinfo,UINT32 uFlags)
740 LPMMIOINFO16 lpmminfo;
741 TRACE(mmio, "mmioAdvance\n");
742 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
743 if (lpmminfo == NULL) return 0;
744 if (!lpmminfo->cchBuffer) {
745 GlobalUnlock16(hmmio);
746 return MMIOERR_UNBUFFERED;
748 lpmminfo->pchNext = lpmmioinfo->pchNext;
749 if (mmioFlush32(hmmio, MMIO_EMPTYBUF)) {
750 GlobalUnlock16(hmmio);
751 return MMIOERR_CANNOTWRITE;
753 if (uFlags == MMIO_READ)
754 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
755 mmioSendMessage(hmmio, MMIOM_READ,
756 (LPARAM) lpmmioinfo->pchBuffer,
757 (LPARAM) lpmmioinfo->cchBuffer);
758 #if 0 /* mmioFlush32 already did the writing */
759 if (uFlags == MMIO_WRITE)
760 mmioSendMessage(hmmio, MMIOM_WRITE,
761 (LPARAM) lpmmioinfo->pchBuffer,
762 (LPARAM) lpmmioinfo->cchBuffer);
763 #endif
764 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
765 GlobalUnlock16(hmmio);
766 return 0;
769 /**************************************************************************
770 * mmioAdvance [MMSYSTEM.1219]
772 UINT16 WINAPI mmioAdvance16(HMMIO16 hmmio,MMIOINFO16*lpmmioinfo,UINT16 uFlags)
774 LPMMIOINFO16 lpmminfo;
775 TRACE(mmio, "mmioAdvance\n");
776 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
777 if (lpmminfo == NULL) return 0;
778 if (!lpmminfo->cchBuffer) {
779 GlobalUnlock16(hmmio);
780 return MMIOERR_UNBUFFERED;
782 lpmminfo->pchNext = lpmmioinfo->pchNext;
783 if (mmioFlush32(hmmio, MMIO_EMPTYBUF)) {
784 GlobalUnlock16(hmmio);
785 return MMIOERR_CANNOTWRITE;
787 if (uFlags == MMIO_READ)
788 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
789 mmioSendMessage(hmmio, MMIOM_READ,
790 (LPARAM) lpmmioinfo->pchBuffer,
791 (LPARAM) lpmmioinfo->cchBuffer);
792 #if 0 /* mmioFlush32 already did the writing */
793 if (uFlags == MMIO_WRITE)
794 mmioSendMessage(hmmio, MMIOM_WRITE,
795 (LPARAM) lpmmioinfo->pchBuffer,
796 (LPARAM) lpmmioinfo->cchBuffer);
797 #endif
798 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
799 GlobalUnlock16(hmmio);
800 return 0;
803 /**************************************************************************
804 * mmioStringToFOURCCA [WINMM.131]
806 FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
808 return mmioStringToFOURCC16(sz,uFlags);
811 /**************************************************************************
812 * mmioStringToFOURCCW [WINMM.132]
814 FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
816 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
817 FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
819 HeapFree(GetProcessHeap(),0,szA);
820 return ret;
823 /**************************************************************************
824 * mmioStringToFOURCC [MMSYSTEM.1220]
826 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
828 return mmioFOURCC(sz[0],sz[1],sz[2],sz[3]);
831 /**************************************************************************
832 * mmioInstallIOProc16 [MMSYSTEM.1221]
834 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
835 LPMMIOPROC16 pIOProc, DWORD dwFlags)
837 TRACE(mmio, "(%ld, %p, %08lX)\n",
838 fccIOProc, pIOProc, dwFlags);
840 if (dwFlags & MMIO_GLOBALPROC) {
841 FIXME(mmio, " global procedures not implemented\n");
844 /* just handle the known procedures for now */
845 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
846 case MMIO_INSTALLPROC:
847 return NULL;
848 case MMIO_REMOVEPROC:
849 return NULL;
850 case MMIO_FINDPROC:
851 if (fccIOProc == FOURCC_DOS)
852 return (LPMMIOPROC16) mmioDosIOProc;
853 else if (fccIOProc == FOURCC_MEM)
854 return (LPMMIOPROC16) mmioMemIOProc;
855 else
856 return NULL;
857 default:
858 return NULL;
862 /**************************************************************************
863 * mmioInstallIOProc32A [WINMM.120]
865 LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
866 LPMMIOPROC32 pIOProc, DWORD dwFlags)
868 FIXME(mmio, "(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
869 (char)((fccIOProc&0xff000000)>>24),
870 (char)((fccIOProc&0x00ff0000)>>16),
871 (char)((fccIOProc&0x0000ff00)>> 8),
872 (char)(fccIOProc&0x000000ff),
873 pIOProc, dwFlags );
874 return 0;
877 /**************************************************************************
878 * mmioSendMessage [MMSYSTEM.1222]
880 LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
881 LPARAM lParam1, LPARAM lParam2)
883 LPMMIOINFO16 lpmminfo;
884 LRESULT result;
885 const char *msg = NULL;
887 #ifdef DEBUG_RUNTIME
888 switch (uMessage) {
889 #define msgname(x) case x: msg = #x; break;
890 msgname(MMIOM_OPEN);
891 msgname(MMIOM_CLOSE);
892 msgname(MMIOM_READ);
893 msgname(MMIOM_WRITE);
894 msgname(MMIOM_WRITEFLUSH);
895 msgname(MMIOM_SEEK);
896 msgname(MMIOM_RENAME);
897 #undef msgname
899 #endif
901 if (msg)
902 TRACE(mmio, "(%04X, %s, %ld, %ld)\n",
903 hmmio, msg, lParam1, lParam2);
904 else
905 TRACE(mmio, "(%04X, %u, %ld, %ld)\n",
906 hmmio, uMessage, lParam1, lParam2);
908 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
910 if (lpmminfo && lpmminfo->pIOProc)
911 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
912 else
913 result = MMSYSERR_INVALPARAM;
915 GlobalUnlock16(hmmio);
917 return result;
920 /**************************************************************************
921 * mmioDescend [MMSYSTEM.1223]
923 UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
924 const MMCKINFO * lpckParent, UINT16 uFlags)
926 DWORD dwfcc, dwOldPos;
928 TRACE(mmio, "(%04X, %p, %p, %04X);\n",
929 hmmio, lpck, lpckParent, uFlags);
931 if (lpck == NULL)
932 return 0;
934 dwfcc = lpck->ckid;
935 TRACE(mmio, "dwfcc=%08lX\n", dwfcc);
937 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
938 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
940 if (lpckParent != NULL) {
941 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
942 dwOldPos = mmioSeek32(hmmio,lpckParent->dwDataOffset,SEEK_SET);
946 It seems to be that FINDRIFF should not be treated the same as the
947 other FINDxxx so I treat it as a MMIO_FINDxxx
949 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
950 (uFlags & MMIO_FINDLIST)) {
952 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
953 TRACE(mmio, "MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
954 while (TRUE) {
955 LONG ix;
957 ix = mmioRead32(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
958 TRACE(mmio, "after _lread32 ix = %ld req = %d, errno = %d\n",ix,3 * sizeof(DWORD),errno);
959 if (ix < sizeof(DWORD)) {
960 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
961 WARN(mmio, "return ChunkNotFound\n");
962 return MMIOERR_CHUNKNOTFOUND;
964 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
965 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
966 lpck->dwDataOffset += sizeof(DWORD);
967 if (ix < lpck->dwDataOffset - dwOldPos) {
968 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
969 WARN(mmio, "return ChunkNotFound\n");
970 return MMIOERR_CHUNKNOTFOUND;
972 TRACE(mmio, "dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
973 dwfcc, lpck->ckid, lpck->cksize);
974 if (dwfcc == lpck->ckid)
975 break;
977 dwOldPos = lpck->dwDataOffset + lpck->cksize;
978 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
981 else {
982 if (mmioRead32(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
983 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
984 WARN(mmio, "return ChunkNotFound 2nd\n");
985 return MMIOERR_CHUNKNOTFOUND;
987 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
988 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
989 lpck->dwDataOffset += sizeof(DWORD);
991 mmioSeek32(hmmio, lpck->dwDataOffset, SEEK_SET);
993 TRACE(mmio, "lpck->ckid=%08lX lpck->cksize=%ld !\n",
994 lpck->ckid, lpck->cksize);
995 TRACE(mmio, "lpck->fccType=%08lX !\n", lpck->fccType);
997 return 0;
1000 /**************************************************************************
1001 * mmioAscend [WINMM.113]
1003 UINT32 WINAPI mmioAscend32(HMMIO32 hmmio, MMCKINFO * lpck, UINT32 uFlags)
1005 TRACE(mmio, "(%04X, %p, %04X);\n",
1006 hmmio, lpck, uFlags);
1007 if (lpck->dwFlags&MMIO_DIRTY) {
1008 DWORD dwOldPos, dwNewSize, dwSizePos;
1010 TRACE(mmio, "chunk is marked MMIO_DIRTY, correcting chunk size\n");
1011 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1012 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1013 dwNewSize = dwOldPos - lpck->dwDataOffset;
1014 if (dwNewSize != lpck->cksize) {
1015 TRACE(mmio, "dwNewSize=%ld\n", dwNewSize);
1016 lpck->cksize = dwNewSize;
1018 dwSizePos = lpck->dwDataOffset - sizeof(DWORD);
1019 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1020 dwSizePos -= sizeof(DWORD);
1021 TRACE(mmio, "dwSizePos=%ld\n", dwSizePos);
1023 mmioSeek32(hmmio, dwSizePos, SEEK_SET);
1024 mmioWrite32(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1027 mmioSeek32(hmmio,lpck->dwDataOffset+lpck->cksize,SEEK_SET);
1029 return 0;
1032 /**************************************************************************
1033 * mmioAscend [MMSYSTEM.1224]
1035 UINT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1037 return mmioAscend32(hmmio,lpck,uFlags);
1040 /**************************************************************************
1041 * mmioCreateChunk [MMSYSTEM.1225]
1043 UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1045 DWORD dwOldPos;
1046 LONG ix;
1048 TRACE(mmio, "(%04X, %p, %04X);\n",
1049 hmmio, lpck, uFlags);
1051 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1052 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1054 if (uFlags == MMIO_CREATELIST)
1055 lpck->ckid = FOURCC_LIST;
1056 else if (uFlags == MMIO_CREATERIFF)
1057 lpck->ckid = FOURCC_RIFF;
1059 TRACE(mmio, "ckid=%08lX\n", lpck->ckid);
1061 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1062 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1063 lpck->dwDataOffset += sizeof(DWORD);
1064 lpck->dwFlags = MMIO_DIRTY;
1066 ix = mmioWrite32(hmmio, (LPSTR)lpck, lpck->dwDataOffset - dwOldPos);
1067 TRACE(mmio, "after _lwrite32 ix = %ld req = %ld, errno = %d\n",ix,lpck->dwDataOffset - dwOldPos,errno);
1068 if (ix < lpck->dwDataOffset - dwOldPos) {
1070 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
1071 WARN(mmio, "return CannotWrite\n");
1072 return MMIOERR_CANNOTWRITE;
1075 return 0;
1079 /**************************************************************************
1080 * mmioRename [MMSYSTEM.1226]
1082 UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
1083 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
1085 UINT16 result;
1086 LPMMIOINFO16 lpmminfo;
1087 HMMIO16 hmmio;
1089 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
1090 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
1092 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
1093 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
1095 if (lpmmioinfo)
1096 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
1098 /* assume DOS file if not otherwise specified */
1099 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
1101 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
1102 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
1105 /* if just the four character code is present, look up IO proc */
1106 else if (lpmminfo->pIOProc == NULL) {
1108 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
1111 /* (if IO proc specified, use it and specified four character code) */
1113 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
1115 GlobalUnlock16(hmmio);
1116 GlobalFree16(hmmio);
1118 return result;