Fixed message filtering check.
[wine/testsucceed.git] / multimedia / mmio.c
blob4586fcb99c189b2f378ecf847566c9bb43795414
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 FILE_GetHandle32(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 = mmioSetBuffer16(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 = mmioSetBuffer16(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 mmioSetBuffer16(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 [WINMM.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 [WINMM.129]
632 UINT32 WINAPI mmioSetBuffer32(HMMIO32 hmmio, LPSTR pchBuffer,
633 LONG cchBuffer, UINT32 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 if (lpmminfo->dwFlags&MMIO_ALLOCBUF) {
653 HGLOBAL16 hNewBuf;
654 GlobalUnlock16(lpmminfo->dwReserved1);
655 hNewBuf = GlobalReAlloc16(lpmminfo->dwReserved1, cchBuffer, 0);
656 if (!hNewBuf) {
657 /* FIXME: this assumes the memory block didn't move */
658 GlobalLock16(lpmminfo->dwReserved1);
659 GlobalUnlock16(hmmio);
660 return MMIOERR_OUTOFMEMORY;
662 lpmminfo->dwReserved1 = hNewBuf;
663 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
664 } else if (cchBuffer) {
665 HGLOBAL16 hNewBuf = GlobalAlloc16(GMEM_MOVEABLE, cchBuffer);
666 if (!hNewBuf) {
667 GlobalUnlock16(hmmio);
668 return MMIOERR_OUTOFMEMORY;
670 lpmminfo->dwReserved1 = hNewBuf;
671 lpmminfo->pchBuffer = GlobalLock16(hNewBuf);
672 lpmminfo->dwFlags |= MMIO_ALLOCBUF;
673 } else
674 lpmminfo->pchBuffer = NULL;
675 lpmminfo->cchBuffer = cchBuffer;
676 lpmminfo->pchNext = lpmminfo->pchBuffer;
677 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
678 lpmminfo->pchEndWrite = lpmminfo->pchBuffer + cchBuffer;
679 lpmminfo->lBufOffset = 0;
681 GlobalUnlock16(hmmio);
682 return (UINT16) 0;
685 /**************************************************************************
686 * mmioSetBuffer [MMSYSTEM.1217]
688 UINT16 WINAPI mmioSetBuffer16(HMMIO16 hmmio, LPSTR pchBuffer,
689 LONG cchBuffer, UINT16 uFlags)
691 return mmioSetBuffer32(hmmio, pchBuffer, cchBuffer, uFlags);
694 /**************************************************************************
695 * mmioFlush [WINMM.117]
697 UINT32 WINAPI mmioFlush32(HMMIO32 hmmio, UINT32 uFlags)
699 LPMMIOINFO16 lpmminfo;
700 TRACE(mmio, "(%04X, %04X)\n", hmmio, uFlags);
701 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
702 if (lpmminfo == NULL) return 0;
704 if ((!lpmminfo->cchBuffer)||(lpmminfo->fccIOProc==FOURCC_MEM)) {
705 GlobalUnlock16(hmmio);
706 return 0;
708 /* not quite sure what to do here, but I'll guess */
709 if (lpmminfo->dwFlags & MMIO_DIRTY) {
710 mmioSendMessage(hmmio, MMIOM_SEEK,
711 (LPARAM) lpmminfo->lBufOffset,
712 (LPARAM) SEEK_SET);
713 mmioSendMessage(hmmio, MMIOM_WRITE,
714 (LPARAM) lpmminfo->pchBuffer,
715 (LPARAM) (lpmminfo->pchNext - lpmminfo->pchBuffer) );
716 lpmminfo->dwFlags &= ~MMIO_DIRTY;
718 if (uFlags & MMIO_EMPTYBUF) {
719 /* seems Windows doesn't do any seeking here, hopefully this
720 won't matter, otherwise a slight rewrite is necessary */
721 mmioSendMessage(hmmio, MMIOM_SEEK,
722 (LPARAM) (lpmminfo->lBufOffset +
723 (lpmminfo->pchNext - lpmminfo->pchBuffer)),
724 (LPARAM) SEEK_SET);
725 lpmminfo->pchNext = lpmminfo->pchBuffer;
726 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
727 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
730 GlobalUnlock16(hmmio);
731 return 0;
734 /**************************************************************************
735 * mmioFlush [MMSYSTEM.1218]
737 UINT16 WINAPI mmioFlush16(HMMIO16 hmmio, UINT16 uFlags)
739 return mmioFlush32(hmmio,uFlags);
742 /**************************************************************************
743 * mmioAdvance [MMSYSTEM.1219]
745 UINT32 WINAPI mmioAdvance32(HMMIO32 hmmio,MMIOINFO32*lpmmioinfo,UINT32 uFlags)
747 LPMMIOINFO16 lpmminfo;
748 TRACE(mmio, "mmioAdvance\n");
749 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
750 if (lpmminfo == NULL) return 0;
751 if (!lpmminfo->cchBuffer) {
752 GlobalUnlock16(hmmio);
753 return MMIOERR_UNBUFFERED;
755 lpmminfo->pchNext = lpmmioinfo->pchNext;
756 if (mmioFlush32(hmmio, MMIO_EMPTYBUF)) {
757 GlobalUnlock16(hmmio);
758 return MMIOERR_CANNOTWRITE;
760 if (uFlags == MMIO_READ)
761 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
762 mmioSendMessage(hmmio, MMIOM_READ,
763 (LPARAM) lpmmioinfo->pchBuffer,
764 (LPARAM) lpmmioinfo->cchBuffer);
765 #if 0 /* mmioFlush32 already did the writing */
766 if (uFlags == MMIO_WRITE)
767 mmioSendMessage(hmmio, MMIOM_WRITE,
768 (LPARAM) lpmmioinfo->pchBuffer,
769 (LPARAM) lpmmioinfo->cchBuffer);
770 #endif
771 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
772 GlobalUnlock16(hmmio);
773 return 0;
776 /**************************************************************************
777 * mmioAdvance [MMSYSTEM.1219]
779 UINT16 WINAPI mmioAdvance16(HMMIO16 hmmio,MMIOINFO16*lpmmioinfo,UINT16 uFlags)
781 LPMMIOINFO16 lpmminfo;
782 TRACE(mmio, "mmioAdvance\n");
783 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
784 if (lpmminfo == NULL) return 0;
785 if (!lpmminfo->cchBuffer) {
786 GlobalUnlock16(hmmio);
787 return MMIOERR_UNBUFFERED;
789 lpmminfo->pchNext = lpmmioinfo->pchNext;
790 if (mmioFlush32(hmmio, MMIO_EMPTYBUF)) {
791 GlobalUnlock16(hmmio);
792 return MMIOERR_CANNOTWRITE;
794 if (uFlags == MMIO_READ)
795 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
796 mmioSendMessage(hmmio, MMIOM_READ,
797 (LPARAM) lpmmioinfo->pchBuffer,
798 (LPARAM) lpmmioinfo->cchBuffer);
799 #if 0 /* mmioFlush32 already did the writing */
800 if (uFlags == MMIO_WRITE)
801 mmioSendMessage(hmmio, MMIOM_WRITE,
802 (LPARAM) lpmmioinfo->pchBuffer,
803 (LPARAM) lpmmioinfo->cchBuffer);
804 #endif
805 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
806 GlobalUnlock16(hmmio);
807 return 0;
810 /**************************************************************************
811 * mmioStringToFOURCCA [WINMM.131]
813 FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
815 return mmioStringToFOURCC16(sz,uFlags);
818 /**************************************************************************
819 * mmioStringToFOURCCW [WINMM.132]
821 FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
823 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
824 FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
826 HeapFree(GetProcessHeap(),0,szA);
827 return ret;
830 /**************************************************************************
831 * mmioStringToFOURCC [MMSYSTEM.1220]
833 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
835 return mmioFOURCC(sz[0],sz[1],sz[2],sz[3]);
838 /**************************************************************************
839 * mmioInstallIOProc16 [MMSYSTEM.1221]
841 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
842 LPMMIOPROC16 pIOProc, DWORD dwFlags)
844 TRACE(mmio, "(%ld, %p, %08lX)\n",
845 fccIOProc, pIOProc, dwFlags);
847 if (dwFlags & MMIO_GLOBALPROC) {
848 FIXME(mmio, " global procedures not implemented\n");
851 /* just handle the known procedures for now */
852 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
853 case MMIO_INSTALLPROC:
854 return NULL;
855 case MMIO_REMOVEPROC:
856 return NULL;
857 case MMIO_FINDPROC:
858 if (fccIOProc == FOURCC_DOS)
859 return (LPMMIOPROC16) mmioDosIOProc;
860 else if (fccIOProc == FOURCC_MEM)
861 return (LPMMIOPROC16) mmioMemIOProc;
862 else
863 return NULL;
864 default:
865 return NULL;
869 /**************************************************************************
870 * mmioInstallIOProc32A [WINMM.120]
872 LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
873 LPMMIOPROC32 pIOProc, DWORD dwFlags)
875 FIXME(mmio, "(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
876 (char)((fccIOProc&0xff000000)>>24),
877 (char)((fccIOProc&0x00ff0000)>>16),
878 (char)((fccIOProc&0x0000ff00)>> 8),
879 (char)(fccIOProc&0x000000ff),
880 pIOProc, dwFlags );
881 return 0;
884 /**************************************************************************
885 * mmioSendMessage [MMSYSTEM.1222]
887 LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
888 LPARAM lParam1, LPARAM lParam2)
890 LPMMIOINFO16 lpmminfo;
891 LRESULT result;
892 const char *msg = NULL;
894 #ifdef DEBUG_RUNTIME
895 switch (uMessage) {
896 #define msgname(x) case x: msg = #x; break;
897 msgname(MMIOM_OPEN);
898 msgname(MMIOM_CLOSE);
899 msgname(MMIOM_READ);
900 msgname(MMIOM_WRITE);
901 msgname(MMIOM_WRITEFLUSH);
902 msgname(MMIOM_SEEK);
903 msgname(MMIOM_RENAME);
904 #undef msgname
906 #endif
908 if (msg)
909 TRACE(mmio, "(%04X, %s, %ld, %ld)\n",
910 hmmio, msg, lParam1, lParam2);
911 else
912 TRACE(mmio, "(%04X, %u, %ld, %ld)\n",
913 hmmio, uMessage, lParam1, lParam2);
915 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
917 if (lpmminfo && lpmminfo->pIOProc)
918 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
919 else
920 result = MMSYSERR_INVALPARAM;
922 GlobalUnlock16(hmmio);
924 return result;
927 /**************************************************************************
928 * mmioDescend [MMSYSTEM.1223]
930 UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
931 const MMCKINFO * lpckParent, UINT16 uFlags)
933 DWORD dwfcc, dwOldPos;
934 LPDWORD tocheck;
936 TRACE(mmio, "(%04X, %p, %p, %04X);\n",
937 hmmio, lpck, lpckParent, uFlags);
939 if (lpck == NULL)
940 return 0;
942 dwfcc = lpck->ckid;
943 TRACE(mmio, "dwfcc=%08lX\n", dwfcc);
945 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
946 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
948 if (lpckParent != NULL) {
949 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
950 dwOldPos = mmioSeek32(hmmio,lpckParent->dwDataOffset,SEEK_SET);
953 /* The SDK docu says 'ckid' is used for all cases. Real World
954 * examples disagree -Marcus,990216.
957 /* find_chunk looks for 'ckid' */
958 if (uFlags & MMIO_FINDCHUNK) {
959 tocheck = &(lpck->ckid);
960 dwfcc = lpck->ckid;
962 /* find_riff and find_list look for 'fccType' */
963 if (uFlags & (MMIO_FINDLIST|MMIO_FINDRIFF)) {
964 dwfcc = lpck->fccType;
965 tocheck = &(lpck->fccType);
968 if (uFlags & (MMIO_FINDCHUNK|MMIO_FINDLIST|MMIO_FINDRIFF)) {
969 TRACE(mmio, "MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
970 while (TRUE) {
971 LONG ix;
972 char fcc[5],ckid[5];
974 ix = mmioRead32(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
975 TRACE(mmio, "after _lread32 ix = %ld req = %d, errno = %d\n",ix,3 * sizeof(DWORD),errno);
976 if (ix < sizeof(DWORD)) {
977 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
978 WARN(mmio, "return ChunkNotFound\n");
979 return MMIOERR_CHUNKNOTFOUND;
981 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
982 if (ix < lpck->dwDataOffset - dwOldPos) {
983 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
984 WARN(mmio, "return ChunkNotFound\n");
985 return MMIOERR_CHUNKNOTFOUND;
987 memcpy(fcc,&dwfcc,4);fcc[4]='\0';
988 memcpy(ckid,&lpck->ckid,4);ckid[4]='\0';
989 TRACE(mmio, "dwfcc=%s ckid=%s cksize=%08lX !\n", fcc, ckid, lpck->cksize);
990 if (dwfcc == *tocheck)
991 break;
993 dwOldPos = lpck->dwDataOffset + lpck->cksize;
994 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
996 /* If we were looking for RIFF/LIST chunks, the final dataptr
997 * is after the chunkid. If we were just looking for the chunk
998 * it is after the cksize. So add 4 in RIFF/LIST case.
1000 if (uFlags & (MMIO_FINDLIST|MMIO_FINDRIFF))
1001 lpck->dwDataOffset+=sizeof(DWORD);
1002 } else {
1003 /* FIXME: unverified, does it do this? */
1004 if (mmioRead32(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
1005 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
1006 WARN(mmio, "return ChunkNotFound 2nd\n");
1007 return MMIOERR_CHUNKNOTFOUND;
1009 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1010 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1011 lpck->dwDataOffset += sizeof(DWORD);
1013 mmioSeek32(hmmio, lpck->dwDataOffset, SEEK_SET);
1014 TRACE(mmio, "lpck->ckid=%08lX lpck->cksize=%ld !\n", lpck->ckid, lpck->cksize);
1015 TRACE(mmio, "lpck->fccType=%08lX !\n", lpck->fccType);
1016 return 0;
1019 /**************************************************************************
1020 * mmioAscend [WINMM.113]
1022 UINT32 WINAPI mmioAscend32(HMMIO32 hmmio, MMCKINFO * lpck, UINT32 uFlags)
1024 TRACE(mmio, "(%04X, %p, %04X);\n",
1025 hmmio, lpck, uFlags);
1026 if (lpck->dwFlags&MMIO_DIRTY) {
1027 DWORD dwOldPos, dwNewSize, dwSizePos;
1029 TRACE(mmio, "chunk is marked MMIO_DIRTY, correcting chunk size\n");
1030 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1031 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1032 dwNewSize = dwOldPos - lpck->dwDataOffset;
1033 if (dwNewSize != lpck->cksize) {
1034 TRACE(mmio, "dwNewSize=%ld\n", dwNewSize);
1035 lpck->cksize = dwNewSize;
1037 dwSizePos = lpck->dwDataOffset - sizeof(DWORD);
1038 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1039 dwSizePos -= sizeof(DWORD);
1040 TRACE(mmio, "dwSizePos=%ld\n", dwSizePos);
1042 mmioSeek32(hmmio, dwSizePos, SEEK_SET);
1043 mmioWrite32(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1046 mmioSeek32(hmmio,lpck->dwDataOffset+lpck->cksize,SEEK_SET);
1048 return 0;
1051 /**************************************************************************
1052 * mmioAscend [MMSYSTEM.1224]
1054 UINT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1056 return mmioAscend32(hmmio,lpck,uFlags);
1059 /**************************************************************************
1060 * mmioCreateChunk [MMSYSTEM.1225]
1062 UINT16 WINAPI mmioCreateChunk16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1064 DWORD dwOldPos;
1065 LONG ix;
1067 TRACE(mmio, "(%04X, %p, %04X);\n",
1068 hmmio, lpck, uFlags);
1070 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1071 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1073 if (uFlags == MMIO_CREATELIST)
1074 lpck->ckid = FOURCC_LIST;
1075 else if (uFlags == MMIO_CREATERIFF)
1076 lpck->ckid = FOURCC_RIFF;
1078 TRACE(mmio, "ckid=%08lX\n", lpck->ckid);
1080 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1081 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1082 lpck->dwDataOffset += sizeof(DWORD);
1083 lpck->dwFlags = MMIO_DIRTY;
1085 ix = mmioWrite32(hmmio, (LPSTR)lpck, lpck->dwDataOffset - dwOldPos);
1086 TRACE(mmio, "after _lwrite32 ix = %ld req = %ld, errno = %d\n",ix,lpck->dwDataOffset - dwOldPos,errno);
1087 if (ix < lpck->dwDataOffset - dwOldPos) {
1089 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
1090 WARN(mmio, "return CannotWrite\n");
1091 return MMIOERR_CANNOTWRITE;
1094 return 0;
1097 /**************************************************************************
1098 * mmioCreateChunk [WINMM.115]
1100 UINT32 WINAPI mmioCreateChunk32(HMMIO32 hmmio, MMCKINFO * lpck, UINT32 uFlags)
1102 return mmioCreateChunk16(hmmio, lpck, uFlags);
1105 /**************************************************************************
1106 * mmioRename [MMSYSTEM.1226]
1108 UINT16 WINAPI mmioRename16(LPCSTR szFileName, LPCSTR szNewFileName,
1109 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
1111 UINT16 result;
1112 LPMMIOINFO16 lpmminfo;
1113 HMMIO16 hmmio;
1115 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
1116 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
1118 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
1119 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
1121 if (lpmmioinfo)
1122 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
1124 /* assume DOS file if not otherwise specified */
1125 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
1127 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
1128 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
1131 /* if just the four character code is present, look up IO proc */
1132 else if (lpmminfo->pIOProc == NULL) {
1134 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
1137 /* (if IO proc specified, use it and specified four character code) */
1139 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
1141 GlobalUnlock16(hmmio);
1142 GlobalFree16(hmmio);
1144 return result;
1147 /**************************************************************************
1148 * mmioRenameA [WINMM.125]
1150 UINT32 WINAPI mmioRename32A(LPCSTR szFileName, LPCSTR szNewFileName,
1151 MMIOINFO32* lpmmioinfo, DWORD dwRenameFlags)
1153 FIXME(mmio, "This may fail\n");
1154 return mmioRename16(szFileName, szNewFileName, (MMIOINFO16*)lpmmioinfo, dwRenameFlags);
1157 /**************************************************************************
1158 * mmioRenameW [WINMM.126]
1160 UINT32 WINAPI mmioRename32W(LPCWSTR szFileName, LPCWSTR szNewFileName,
1161 MMIOINFO32* lpmmioinfo, DWORD dwRenameFlags)
1163 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szFileName);
1164 LPSTR sznFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szNewFileName);
1165 UINT32 ret = mmioRename32A(szFn, sznFn, lpmmioinfo, dwRenameFlags);
1167 HeapFree(GetProcessHeap(),0,szFn);
1168 HeapFree(GetProcessHeap(),0,sznFn);
1169 return ret;