4 * Copyright 1998 Andrew Taylor
5 * Copyright 1998 Ove Kåven
14 #include "wine/winbase16.h"
16 #include "selectors.h"
19 #include "debugtools.h"
21 DEFAULT_DEBUG_CHANNEL(mmio
)
23 /**************************************************************************
24 * mmioDosIOProc [internal]
26 static LRESULT
mmioDosIOProc(LPMMIOINFO16 lpmmioinfo
, UINT16 uMessage
, LPARAM lParam1
, LPARAM lParam2
) {
27 TRACE("(%p, %X, %ld, %ld);\n", lpmmioinfo
, uMessage
, lParam1
, lParam2
);
33 * lParam1 = szFileName parameter from mmioOpen
34 * lParam2 = reserved (we use it for 16-bitness)
35 * Returns: zero on success, error code on error
36 * NOTE: lDiskOffset automatically set to zero
40 LPSTR szFileName
= (LPSTR
) lParam1
;
42 if (lpmmioinfo
->dwFlags
& MMIO_GETTEMP
) {
43 FIXME("MMIO_GETTEMP not implemented\n");
44 return MMIOERR_CANNOTOPEN
;
47 /* if filename NULL, assume open file handle in adwInfo[0] */
49 if (lParam2
) lpmmioinfo
->adwInfo
[0] =
50 FILE_GetHandle(lpmmioinfo
->adwInfo
[0]);
54 lpmmioinfo
->adwInfo
[0] =
55 (DWORD
) OpenFile(szFileName
, &ofs
, lpmmioinfo
->dwFlags
);
56 if (lpmmioinfo
->adwInfo
[0] == -1)
57 return MMIOERR_CANNOTOPEN
;
64 * lParam1 = wFlags parameter from mmioClose
66 * Returns: zero on success, error code on error
69 UINT16 uFlags
= (UINT16
) lParam1
;
71 if (uFlags
& MMIO_FHOPEN
)
74 _lclose((HFILE
)lpmmioinfo
->adwInfo
[0]);
81 * lParam1 = huge pointer to read buffer
82 * lParam2 = number of bytes to read
83 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
85 * NOTE: lDiskOffset should be updated
88 HPSTR pch
= (HPSTR
) lParam1
;
89 LONG cch
= (LONG
) lParam2
;
92 count
= _lread((HFILE
)lpmmioinfo
->adwInfo
[0], pch
, cch
);
94 lpmmioinfo
->lDiskOffset
+= count
;
100 case MMIOM_WRITEFLUSH
: {
101 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
104 * lParam1 = huge pointer to write buffer
105 * lParam2 = number of bytes to write
106 * Returns: number of bytes written, -1 for error (error code in
108 * NOTE: lDiskOffset should be updated
111 HPSTR pch
= (HPSTR
) lParam1
;
112 LONG cch
= (LONG
) lParam2
;
115 count
= _hwrite((HFILE
)lpmmioinfo
->adwInfo
[0], pch
, cch
);
117 lpmmioinfo
->lDiskOffset
+= count
;
124 * lParam1 = new position
125 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
126 * Returns: new file postion, -1 on error
127 * NOTE: lDiskOffset should be updated
130 LONG Offset
= (LONG
) lParam1
;
131 LONG Whence
= (LONG
) lParam2
;
134 pos
= _llseek((HFILE
)lpmmioinfo
->adwInfo
[0], Offset
, Whence
);
136 lpmmioinfo
->lDiskOffset
= pos
;
145 * Returns: zero on success, non-zero on failure
148 FIXME("MMIOM_RENAME unimplemented\n");
149 return MMIOERR_FILENOTFOUND
;
153 FIXME("unexpected message %u\n", uMessage
);
160 /**************************************************************************
161 * mmioMemIOProc [internal]
163 static LRESULT
mmioMemIOProc(LPMMIOINFO16 lpmmioinfo
, UINT16 uMessage
, LPARAM lParam1
, LPARAM lParam2
) {
164 TRACE("(%p,0x%04x,0x%08lx,0x%08lx)\n",lpmmioinfo
,uMessage
,lParam1
,lParam2
);
169 * lParam1 = filename (must be NULL)
170 * lParam2 = reserved (we use it for 16-bitness)
171 * Returns: zero on success, error code on error
172 * NOTE: lDiskOffset automatically set to zero
175 if (!(lpmmioinfo
->dwFlags
& MMIO_CREATE
))
176 lpmmioinfo
->pchEndRead
= lpmmioinfo
->pchEndWrite
;
183 * lParam1 = wFlags parameter from mmioClose
185 * Returns: zero on success, error code on error
194 * lParam1 = huge pointer to read buffer
195 * lParam2 = number of bytes to read
196 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
198 * NOTE: lDiskOffset should be updated
201 /* HPSTR pch = (HPSTR) lParam1; */
202 /* LONG cch = (LONG) lParam2; */
204 FIXME("MMIOM_READ on memory files should not occur, buffer may be lost!\n");
209 case MMIOM_WRITEFLUSH
: {
210 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
213 * lParam1 = huge pointer to write buffer
214 * lParam2 = number of bytes to write
215 * Returns: number of bytes written, -1 for error (error code in
217 * NOTE: lDiskOffset should be updated
220 /* HPSTR pch = (HPSTR) lParam1; */
221 /* LONG cch = (LONG) lParam2; */
223 FIXME("MMIOM_WRITE on memory files should not occur, buffer may be lost!\n");
229 * lParam1 = new position
230 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
231 * Returns: new file postion, -1 on error
232 * NOTE: lDiskOffset should be updated
235 /* LONG Offset = (LONG) lParam1; */
236 /* LONG Whence = (LONG) lParam2; */
238 FIXME("MMIOM_SEEK on memory files should not occur, buffer may be lost!\n");
243 FIXME("unexpected message %u\n", uMessage
);
250 /**************************************************************************
251 * MMIO_Open [internal]
253 static HMMIO16
MMIO_Open(LPSTR szFileName
, FOURCC fccIOProc
, LPMMIOPROC16 pIOProc
,
254 HPSTR pchBuffer
, LONG cchBuffer
,
255 DWORD dwOpenFlags
, LPUINT lpRet
, int use16
)
257 LPMMIOINFO16 lpmminfo
;
260 TRACE("('%s', %08lX);\n", szFileName
, dwOpenFlags
);
262 if (dwOpenFlags
& MMIO_PARSE
) {
263 char buffer
[MAX_PATH
];
265 if (GetFullPathNameA(szFileName
, sizeof(buffer
), buffer
, NULL
) >= sizeof(buffer
))
266 return (HMMIO16
)FALSE
;
267 strcpy(szFileName
, buffer
);
268 return (HMMIO16
)TRUE
;
271 hmmio
= GlobalAlloc16(GHND
, sizeof(MMIOINFO16
));
272 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
273 if (lpmminfo
== NULL
)
275 memset(lpmminfo
, 0, sizeof(MMIOINFO16
));
277 /* assume DOS file if not otherwise specified */
278 if (fccIOProc
== 0 && pIOProc
== NULL
) {
279 lpmminfo
->fccIOProc
= FOURCC_DOS
;
280 lpmminfo
->pIOProc
= (LPMMIOPROC16
) mmioDosIOProc
;
282 /* if just the four character code is present, look up IO proc */
283 else if (pIOProc
== NULL
) {
285 lpmminfo
->fccIOProc
= fccIOProc
;
286 lpmminfo
->pIOProc
= mmioInstallIOProc16(fccIOProc
, NULL
, MMIO_FINDPROC
);
289 /* if IO proc specified, use it and specified four character code */
292 lpmminfo
->fccIOProc
= fccIOProc
;
293 lpmminfo
->pIOProc
= pIOProc
;
296 if (dwOpenFlags
& MMIO_ALLOCBUF
) {
297 if ((*lpRet
= mmioSetBuffer16(hmmio
, NULL
, MMIO_DEFAULTBUFFER
, 0))) {
300 } else if (lpmminfo
->fccIOProc
== FOURCC_MEM
) {
301 if ((*lpRet
= mmioSetBuffer16(hmmio
, pchBuffer
, cchBuffer
, 0))) {
306 lpmminfo
->dwFlags
= dwOpenFlags
;
307 lpmminfo
->hmmio
= hmmio
;
309 /* call IO proc to actually open file */
310 *lpRet
= (UINT16
) mmioSendMessage(hmmio
, MMIOM_OPEN
, (LPARAM
) szFileName
, (LPARAM
) use16
);
312 GlobalUnlock16(hmmio
);
322 /**************************************************************************
323 * mmioOpenW [WINMM.123]
325 HMMIO WINAPI
mmioOpenW(LPWSTR szFileName
, MMIOINFO
* lpmmioinfo
,
328 LPSTR szFn
= HEAP_strdupWtoA(GetProcessHeap(),0,szFileName
);
332 ret
= MMIO_Open(szFn
, lpmmioinfo
->fccIOProc
,
333 (LPMMIOPROC16
)lpmmioinfo
->pIOProc
,
334 lpmmioinfo
->pchBuffer
, lpmmioinfo
->cchBuffer
,
335 dwOpenFlags
, &lpmmioinfo
->wErrorRet
, FALSE
);
338 ret
= MMIO_Open(szFn
, 0, NULL
, NULL
, 0,
339 dwOpenFlags
, &res
, FALSE
);
341 HeapFree(GetProcessHeap(),0,szFn
);
345 /**************************************************************************
346 * mmioOpenA [WINMM.122]
348 HMMIO WINAPI
mmioOpenA(LPSTR szFileName
, MMIOINFO
* lpmmioinfo
,
355 ret
= MMIO_Open(szFileName
, lpmmioinfo
->fccIOProc
,
356 (LPMMIOPROC16
)lpmmioinfo
->pIOProc
,
357 lpmmioinfo
->pchBuffer
, lpmmioinfo
->cchBuffer
,
358 dwOpenFlags
, &lpmmioinfo
->wErrorRet
, FALSE
);
360 ret
= MMIO_Open(szFileName
, 0, NULL
, NULL
, 0, dwOpenFlags
, &res
, FALSE
);
365 /**************************************************************************
366 * mmioOpen [MMSYSTEM.1210]
368 HMMIO16 WINAPI
mmioOpen16(LPSTR szFileName
, MMIOINFO16
* lpmmioinfo
,
375 ret
= MMIO_Open(szFileName
, lpmmioinfo
->fccIOProc
, lpmmioinfo
->pIOProc
,
376 PTR_SEG_TO_LIN(lpmmioinfo
->pchBuffer
), lpmmioinfo
->cchBuffer
,
377 dwOpenFlags
, &res
, FALSE
);
378 lpmmioinfo
->wErrorRet
= res
;
380 ret
= MMIO_Open(szFileName
, 0, NULL
, NULL
, 0, dwOpenFlags
, &res
, TRUE
);
386 /**************************************************************************
387 * mmioClose [WINMM.114]
389 MMRESULT WINAPI
mmioClose(HMMIO hmmio
, UINT uFlags
)
391 LPMMIOINFO16 lpmminfo
;
394 TRACE("(%04X, %04X);\n", hmmio
, uFlags
);
396 lpmminfo
= (LPMMIOINFO16
) GlobalLock16(hmmio
);
397 if (lpmminfo
== NULL
)
400 /* flush the file - if error reported, ignore */
401 if (mmioFlush(hmmio
, MMIO_EMPTYBUF
) != 0)
402 lpmminfo
->dwFlags
&= ~MMIO_DIRTY
;
404 result
= mmioSendMessage(hmmio
,MMIOM_CLOSE
,(LPARAM
)uFlags
,(LPARAM
)0);
406 mmioSetBuffer16(hmmio
, NULL
, 0, 0);
408 GlobalUnlock16(hmmio
);
415 /**************************************************************************
416 * mmioClose [MMSYSTEM.1211]
418 MMRESULT16 WINAPI
mmioClose16(HMMIO16 hmmio
, UINT16 uFlags
)
420 return mmioClose(hmmio
,uFlags
);
425 /**************************************************************************
426 * mmioRead [WINMM.124]
428 LONG WINAPI
mmioRead(HMMIO hmmio
, HPSTR pch
, LONG cch
)
431 LPMMIOINFO16 lpmminfo
;
433 TRACE("(%04X, %p, %ld);\n", hmmio
, pch
, cch
);
435 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
436 if (lpmminfo
== NULL
)
439 if (lpmminfo
->pchNext
!= lpmminfo
->pchEndRead
) {
440 count
= lpmminfo
->pchEndRead
- lpmminfo
->pchNext
;
441 if (count
> cch
|| count
< 0) count
= cch
;
442 memcpy(pch
, lpmminfo
->pchNext
, count
);
443 lpmminfo
->pchNext
+= count
;
449 if (cch
&&(lpmminfo
->fccIOProc
!=FOURCC_MEM
)) {
450 if (lpmminfo
->cchBuffer
) {
451 mmioFlush(hmmio
, MMIO_EMPTYBUF
);
455 lpmminfo
->lBufOffset
= lpmminfo
->lDiskOffset
;
456 lpmminfo
->pchNext
= lpmminfo
->pchBuffer
;
457 lpmminfo
->pchEndRead
= lpmminfo
->pchBuffer
;
458 size
= mmioSendMessage(hmmio
, MMIOM_READ
,
459 (LPARAM
) lpmminfo
->pchBuffer
,
460 (LPARAM
) lpmminfo
->cchBuffer
);
462 lpmminfo
->pchEndRead
= lpmminfo
->pchBuffer
+ size
;
463 if (size
> cch
) size
= cch
;
464 memcpy(pch
, lpmminfo
->pchNext
, size
);
465 lpmminfo
->pchNext
+= size
;
471 count
+= mmioSendMessage(hmmio
, MMIOM_READ
, (LPARAM
) pch
, (LPARAM
) cch
);
472 if (count
>0) lpmminfo
->lBufOffset
+= count
;
476 GlobalUnlock16(hmmio
);
477 TRACE("count=%ld\n", count
);
481 /**************************************************************************
482 * mmioRead [MMSYSTEM.1212]
484 LONG WINAPI
mmioRead16(HMMIO16 hmmio
, HPSTR pch
, LONG cch
)
486 return mmioRead(hmmio
,pch
,cch
);
489 /**************************************************************************
490 * mmioWrite [WINMM.133]
492 LONG WINAPI
mmioWrite(HMMIO hmmio
, HPCSTR pch
, LONG cch
)
495 LPMMIOINFO16 lpmminfo
;
497 TRACE("(%04X, %p, %ld);\n", hmmio
, pch
, cch
);
499 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
500 if (lpmminfo
== NULL
)
503 if (lpmminfo
->cchBuffer
) {
506 if (lpmminfo
->pchNext
!= lpmminfo
->pchEndWrite
) {
507 count
= lpmminfo
->pchEndWrite
- lpmminfo
->pchNext
;
508 if (count
> cch
|| count
< 0) count
= cch
;
509 memcpy(lpmminfo
->pchNext
, pch
, count
);
510 lpmminfo
->pchNext
+= count
;
513 lpmminfo
->dwFlags
|= MMIO_DIRTY
;
515 if (lpmminfo
->fccIOProc
==FOURCC_MEM
) {
516 if (lpmminfo
->adwInfo
[0]) {
517 /* from where would we get the memory handle? */
518 FIXME("memory file expansion not implemented!\n");
522 if (lpmminfo
->pchNext
== lpmminfo
->pchEndWrite
523 && mmioFlush(hmmio
, MMIO_EMPTYBUF
)) break;
526 count
= mmioSendMessage(hmmio
, MMIOM_WRITE
, (LPARAM
) pch
, (LPARAM
) cch
);
527 lpmminfo
->lBufOffset
= lpmminfo
->lDiskOffset
;
530 GlobalUnlock16(hmmio
);
531 TRACE("count=%ld\n", count
);
535 /**************************************************************************
536 * mmioWrite [MMSYSTEM.1213]
538 LONG WINAPI
mmioWrite16(HMMIO16 hmmio
, HPCSTR pch
, LONG cch
)
540 return mmioWrite(hmmio
,pch
,cch
);
543 /**************************************************************************
544 * mmioSeek [MMSYSTEM.1214]
546 LONG WINAPI
mmioSeek(HMMIO hmmio
, LONG lOffset
, INT iOrigin
)
549 LPMMIOINFO16 lpmminfo
;
551 TRACE("(%04X, %08lX, %d);\n", hmmio
, lOffset
, iOrigin
);
553 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
554 if (lpmminfo
== NULL
)
557 offset
= (iOrigin
==SEEK_SET
)?(lOffset
- lpmminfo
->lBufOffset
):
558 (iOrigin
==SEEK_CUR
)?(lOffset
+
559 (lpmminfo
->pchNext
- lpmminfo
->pchBuffer
)):-1;
561 if ((lpmminfo
->cchBuffer
<0)||
562 ((offset
>=0)&&(offset
<=(lpmminfo
->pchEndRead
-lpmminfo
->pchBuffer
)))) {
563 lpmminfo
->pchNext
= lpmminfo
->pchBuffer
+ offset
;
564 GlobalUnlock16(hmmio
);
565 return lpmminfo
->lBufOffset
+ offset
;
568 if ((lpmminfo
->fccIOProc
==FOURCC_MEM
)||mmioFlush(hmmio
, MMIO_EMPTYBUF
)) {
569 GlobalUnlock16(hmmio
);
573 offset
= mmioSendMessage(hmmio
, MMIOM_SEEK
, (LPARAM
) lOffset
, (LPARAM
) iOrigin
);
574 lpmminfo
->lBufOffset
= lpmminfo
->lDiskOffset
;
576 GlobalUnlock16(hmmio
);
580 /**************************************************************************
581 * mmioSeek [MMSYSTEM.1214]
583 LONG WINAPI
mmioSeek16(HMMIO16 hmmio
, LONG lOffset
, INT16 iOrigin
)
585 return mmioSeek(hmmio
,lOffset
,iOrigin
);
588 /**************************************************************************
589 * mmioGetInfo [MMSYSTEM.1215]
591 UINT16 WINAPI
mmioGetInfo16(HMMIO16 hmmio
, MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
593 LPMMIOINFO16 lpmminfo
;
594 TRACE("mmioGetInfo\n");
595 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
596 if (lpmminfo
== NULL
) return 0;
597 memcpy(lpmmioinfo
, lpmminfo
, sizeof(MMIOINFO16
));
598 GlobalUnlock16(hmmio
);
602 /**************************************************************************
603 * mmioGetInfo [WINMM.118]
605 UINT WINAPI
mmioGetInfo(HMMIO hmmio
, MMIOINFO
*lpmmioinfo
, UINT uFlags
)
608 LPMMIOINFO16 lpmminfo
=&mmioinfo
;
611 TRACE("(0x%04x,%p,0x%08x)\n",hmmio
,lpmmioinfo
,uFlags
);
612 ret
= mmioGetInfo16(hmmio
,&mmioinfo
,uFlags
);
615 lpmmioinfo
->dwFlags
= lpmminfo
->dwFlags
;
616 lpmmioinfo
->fccIOProc
= lpmminfo
->fccIOProc
;
617 lpmmioinfo
->pIOProc
= (LPMMIOPROC
)lpmminfo
->pIOProc
;
618 lpmmioinfo
->wErrorRet
= lpmminfo
->wErrorRet
;
619 lpmmioinfo
->htask
= lpmminfo
->htask
;
620 lpmmioinfo
->cchBuffer
= lpmminfo
->cchBuffer
;
621 lpmmioinfo
->pchBuffer
= lpmminfo
->pchBuffer
;
622 lpmmioinfo
->pchNext
= lpmminfo
->pchNext
;
623 lpmmioinfo
->pchEndRead
= lpmminfo
->pchEndRead
;
624 lpmmioinfo
->pchEndWrite
= lpmminfo
->pchEndWrite
;
625 lpmmioinfo
->lBufOffset
= lpmminfo
->lBufOffset
;
626 lpmmioinfo
->lDiskOffset
= lpmminfo
->lDiskOffset
;
627 memcpy(lpmmioinfo
->adwInfo
,lpmminfo
->adwInfo
,sizeof(lpmminfo
->adwInfo
));
628 lpmmioinfo
->dwReserved1
= lpmminfo
->dwReserved1
;
629 lpmmioinfo
->dwReserved2
= lpmminfo
->dwReserved2
;
630 lpmmioinfo
->hmmio
= lpmminfo
->hmmio
;
634 /**************************************************************************
635 * mmioSetInfo [MMSYSTEM.1216]
637 UINT16 WINAPI
mmioSetInfo16(HMMIO16 hmmio
, const MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
639 LPMMIOINFO16 lpmminfo
;
640 TRACE("mmioSetInfo\n");
641 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
642 if (lpmminfo
== NULL
) return 0;
643 lpmminfo
->pchNext
= lpmmioinfo
->pchNext
;
644 lpmminfo
->pchEndRead
= lpmmioinfo
->pchEndRead
;
645 GlobalUnlock16(hmmio
);
649 /**************************************************************************
650 * mmioSetInfo [WINMM.130]
652 UINT WINAPI
mmioSetInfo(HMMIO hmmio
, const MMIOINFO
* lpmmioinfo
, UINT uFlags
)
654 LPMMIOINFO16 lpmminfo
;
655 TRACE("mmioSetInfo\n");
656 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
657 if (lpmminfo
== NULL
) return 0;
658 lpmminfo
->pchNext
= lpmmioinfo
->pchNext
;
659 lpmminfo
->pchEndRead
= lpmmioinfo
->pchEndRead
;
660 GlobalUnlock16(hmmio
);
664 /**************************************************************************
665 * mmioSetBuffer [WINMM.129]
667 UINT WINAPI
mmioSetBuffer(HMMIO hmmio
, LPSTR pchBuffer
,
668 LONG cchBuffer
, UINT uFlags
)
670 LPMMIOINFO16 lpmminfo
;
672 if (mmioFlush(hmmio
, MMIO_EMPTYBUF
) != 0)
673 return MMIOERR_CANNOTWRITE
;
675 TRACE("(hmmio=%04x, pchBuf=%p, cchBuf=%ld, uFlags=%#08x)\n",
676 hmmio
, pchBuffer
, cchBuffer
, uFlags
);
678 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
679 if (lpmminfo
== NULL
) return 0;
680 if ((!cchBuffer
|| pchBuffer
) && lpmminfo
->dwFlags
&MMIO_ALLOCBUF
) {
681 GlobalUnlock16(lpmminfo
->dwReserved1
);
682 GlobalFree16(lpmminfo
->dwReserved1
);
683 lpmminfo
->dwFlags
&= ~MMIO_ALLOCBUF
;
686 lpmminfo
->pchBuffer
= pchBuffer
;
687 } else if (lpmminfo
->dwFlags
&MMIO_ALLOCBUF
) {
689 GlobalUnlock16(lpmminfo
->dwReserved1
);
690 hNewBuf
= GlobalReAlloc16(lpmminfo
->dwReserved1
, cchBuffer
, 0);
692 /* FIXME: this assumes the memory block didn't move */
693 GlobalLock16(lpmminfo
->dwReserved1
);
694 GlobalUnlock16(hmmio
);
695 return MMIOERR_OUTOFMEMORY
;
697 lpmminfo
->dwReserved1
= hNewBuf
;
698 lpmminfo
->pchBuffer
= GlobalLock16(hNewBuf
);
699 } else if (cchBuffer
) {
700 HGLOBAL16 hNewBuf
= GlobalAlloc16(GMEM_MOVEABLE
, cchBuffer
);
702 GlobalUnlock16(hmmio
);
703 return MMIOERR_OUTOFMEMORY
;
705 lpmminfo
->dwReserved1
= hNewBuf
;
706 lpmminfo
->pchBuffer
= GlobalLock16(hNewBuf
);
707 lpmminfo
->dwFlags
|= MMIO_ALLOCBUF
;
709 lpmminfo
->pchBuffer
= NULL
;
710 lpmminfo
->cchBuffer
= cchBuffer
;
711 lpmminfo
->pchNext
= lpmminfo
->pchBuffer
;
712 lpmminfo
->pchEndRead
= lpmminfo
->pchBuffer
;
713 lpmminfo
->pchEndWrite
= lpmminfo
->pchBuffer
+ cchBuffer
;
714 lpmminfo
->lBufOffset
= 0;
716 GlobalUnlock16(hmmio
);
720 /**************************************************************************
721 * mmioSetBuffer [MMSYSTEM.1217]
723 UINT16 WINAPI
mmioSetBuffer16(HMMIO16 hmmio
, LPSTR pchBuffer
,
724 LONG cchBuffer
, UINT16 uFlags
)
726 return mmioSetBuffer(hmmio
, pchBuffer
, cchBuffer
, uFlags
);
729 /**************************************************************************
730 * mmioFlush [WINMM.117]
732 UINT WINAPI
mmioFlush(HMMIO hmmio
, UINT uFlags
)
734 LPMMIOINFO16 lpmminfo
;
735 TRACE("(%04X, %04X)\n", hmmio
, uFlags
);
736 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
737 if (lpmminfo
== NULL
) return 0;
739 if ((!lpmminfo
->cchBuffer
)||(lpmminfo
->fccIOProc
==FOURCC_MEM
)) {
740 GlobalUnlock16(hmmio
);
743 /* not quite sure what to do here, but I'll guess */
744 if (lpmminfo
->dwFlags
& MMIO_DIRTY
) {
745 mmioSendMessage(hmmio
, MMIOM_SEEK
,
746 (LPARAM
) lpmminfo
->lBufOffset
,
748 mmioSendMessage(hmmio
, MMIOM_WRITE
,
749 (LPARAM
) lpmminfo
->pchBuffer
,
750 (LPARAM
) (lpmminfo
->pchNext
- lpmminfo
->pchBuffer
) );
751 lpmminfo
->dwFlags
&= ~MMIO_DIRTY
;
753 if (uFlags
& MMIO_EMPTYBUF
) {
754 /* seems Windows doesn't do any seeking here, hopefully this
755 won't matter, otherwise a slight rewrite is necessary */
756 mmioSendMessage(hmmio
, MMIOM_SEEK
,
757 (LPARAM
) (lpmminfo
->lBufOffset
+
758 (lpmminfo
->pchNext
- lpmminfo
->pchBuffer
)),
760 lpmminfo
->pchNext
= lpmminfo
->pchBuffer
;
761 lpmminfo
->pchEndRead
= lpmminfo
->pchBuffer
;
762 lpmminfo
->lBufOffset
= lpmminfo
->lDiskOffset
;
765 GlobalUnlock16(hmmio
);
769 /**************************************************************************
770 * mmioFlush [MMSYSTEM.1218]
772 UINT16 WINAPI
mmioFlush16(HMMIO16 hmmio
, UINT16 uFlags
)
774 return mmioFlush(hmmio
,uFlags
);
777 /**************************************************************************
778 * mmioAdvance [MMSYSTEM.1219]
780 UINT WINAPI
mmioAdvance(HMMIO hmmio
,MMIOINFO
*lpmmioinfo
,UINT uFlags
)
782 LPMMIOINFO16 lpmminfo
;
783 TRACE("mmioAdvance\n");
784 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
785 if (lpmminfo
== NULL
) return 0;
786 if (!lpmminfo
->cchBuffer
) {
787 GlobalUnlock16(hmmio
);
788 return MMIOERR_UNBUFFERED
;
790 lpmminfo
->pchNext
= lpmmioinfo
->pchNext
;
791 if (mmioFlush(hmmio
, MMIO_EMPTYBUF
)) {
792 GlobalUnlock16(hmmio
);
793 return MMIOERR_CANNOTWRITE
;
795 if (uFlags
== MMIO_READ
)
796 lpmmioinfo
->pchEndRead
= lpmmioinfo
->pchBuffer
+
797 mmioSendMessage(hmmio
, MMIOM_READ
,
798 (LPARAM
) lpmmioinfo
->pchBuffer
,
799 (LPARAM
) lpmmioinfo
->cchBuffer
);
800 #if 0 /* mmioFlush already did the writing */
801 if (uFlags
== MMIO_WRITE
)
802 mmioSendMessage(hmmio
, MMIOM_WRITE
,
803 (LPARAM
) lpmmioinfo
->pchBuffer
,
804 (LPARAM
) lpmmioinfo
->cchBuffer
);
806 lpmmioinfo
->pchNext
= lpmmioinfo
->pchBuffer
;
807 GlobalUnlock16(hmmio
);
811 /**************************************************************************
812 * mmioAdvance [MMSYSTEM.1219]
814 UINT16 WINAPI
mmioAdvance16(HMMIO16 hmmio
,MMIOINFO16
*lpmmioinfo
,UINT16 uFlags
)
816 LPMMIOINFO16 lpmminfo
;
817 TRACE("mmioAdvance\n");
818 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
819 if (lpmminfo
== NULL
) return 0;
820 if (!lpmminfo
->cchBuffer
) {
821 GlobalUnlock16(hmmio
);
822 return MMIOERR_UNBUFFERED
;
824 lpmminfo
->pchNext
= lpmmioinfo
->pchNext
;
825 if (mmioFlush(hmmio
, MMIO_EMPTYBUF
)) {
826 GlobalUnlock16(hmmio
);
827 return MMIOERR_CANNOTWRITE
;
829 if (uFlags
== MMIO_READ
)
830 lpmmioinfo
->pchEndRead
= lpmmioinfo
->pchBuffer
+
831 mmioSendMessage(hmmio
, MMIOM_READ
,
832 (LPARAM
) lpmmioinfo
->pchBuffer
,
833 (LPARAM
) lpmmioinfo
->cchBuffer
);
834 #if 0 /* mmioFlush already did the writing */
835 if (uFlags
== MMIO_WRITE
)
836 mmioSendMessage(hmmio
, MMIOM_WRITE
,
837 (LPARAM
) lpmmioinfo
->pchBuffer
,
838 (LPARAM
) lpmmioinfo
->cchBuffer
);
840 lpmmioinfo
->pchNext
= lpmmioinfo
->pchBuffer
;
841 GlobalUnlock16(hmmio
);
845 /**************************************************************************
846 * mmioStringToFOURCCA [WINMM.131]
848 FOURCC WINAPI
mmioStringToFOURCCA(LPCSTR sz
, UINT uFlags
)
850 return mmioStringToFOURCC16(sz
,uFlags
);
853 /**************************************************************************
854 * mmioStringToFOURCCW [WINMM.132]
856 FOURCC WINAPI
mmioStringToFOURCCW(LPCWSTR sz
, UINT uFlags
)
858 LPSTR szA
= HEAP_strdupWtoA(GetProcessHeap(),0,sz
);
859 FOURCC ret
= mmioStringToFOURCCA(szA
,uFlags
);
861 HeapFree(GetProcessHeap(),0,szA
);
865 /**************************************************************************
866 * mmioStringToFOURCC [MMSYSTEM.1220]
868 FOURCC WINAPI
mmioStringToFOURCC16(LPCSTR sz
, UINT16 uFlags
)
870 return mmioFOURCC(sz
[0],sz
[1],sz
[2],sz
[3]);
873 /**************************************************************************
874 * mmioInstallIOProc16 [MMSYSTEM.1221]
876 LPMMIOPROC16 WINAPI
mmioInstallIOProc16(FOURCC fccIOProc
,
877 LPMMIOPROC16 pIOProc
, DWORD dwFlags
)
879 TRACE("(%ld, %p, %08lX)\n",
880 fccIOProc
, pIOProc
, dwFlags
);
882 if (dwFlags
& MMIO_GLOBALPROC
) {
883 FIXME(" global procedures not implemented\n");
886 /* just handle the known procedures for now */
887 switch(dwFlags
& (MMIO_INSTALLPROC
|MMIO_REMOVEPROC
|MMIO_FINDPROC
)) {
888 case MMIO_INSTALLPROC
:
890 case MMIO_REMOVEPROC
:
893 if (fccIOProc
== FOURCC_DOS
)
894 return (LPMMIOPROC16
) mmioDosIOProc
;
895 else if (fccIOProc
== FOURCC_MEM
)
896 return (LPMMIOPROC16
) mmioMemIOProc
;
904 /**************************************************************************
905 * mmioInstallIOProcA [WINMM.120]
907 LPMMIOPROC WINAPI
mmioInstallIOProcA(FOURCC fccIOProc
,
908 LPMMIOPROC pIOProc
, DWORD dwFlags
)
910 FIXME("(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
911 (char)((fccIOProc
&0xff000000)>>24),
912 (char)((fccIOProc
&0x00ff0000)>>16),
913 (char)((fccIOProc
&0x0000ff00)>> 8),
914 (char)(fccIOProc
&0x000000ff),
919 /**************************************************************************
920 * mmioSendMessage [MMSYSTEM.1222]
922 LRESULT WINAPI
mmioSendMessage(HMMIO16 hmmio
, UINT16 uMessage
,
923 LPARAM lParam1
, LPARAM lParam2
)
925 LPMMIOINFO16 lpmminfo
;
927 const char *msg
= NULL
;
931 #define msgname(x) case x: msg = #x; break;
933 msgname(MMIOM_CLOSE
);
935 msgname(MMIOM_WRITE
);
936 msgname(MMIOM_WRITEFLUSH
);
938 msgname(MMIOM_RENAME
);
944 TRACE("(%04X, %s, %ld, %ld)\n",
945 hmmio
, msg
, lParam1
, lParam2
);
947 TRACE("(%04X, %u, %ld, %ld)\n",
948 hmmio
, uMessage
, lParam1
, lParam2
);
950 lpmminfo
= (LPMMIOINFO16
)GlobalLock16(hmmio
);
952 if (lpmminfo
&& lpmminfo
->pIOProc
)
953 result
= (*lpmminfo
->pIOProc
)((LPSTR
)lpmminfo
, uMessage
, lParam1
, lParam2
);
955 result
= MMSYSERR_INVALPARAM
;
957 GlobalUnlock16(hmmio
);
962 /**************************************************************************
963 * mmioDescend [MMSYSTEM.1223]
965 UINT16 WINAPI
mmioDescend(HMMIO16 hmmio
, LPMMCKINFO lpck
,
966 const MMCKINFO
* lpckParent
, UINT16 uFlags
)
973 TRACE("(%04X, %p, %p, %04X);\n", hmmio
, lpck
, lpckParent
, uFlags
);
976 return MMSYSERR_INVALPARAM
;
978 dwOldPos
= mmioSeek(hmmio
, 0, SEEK_CUR
);
979 TRACE("dwOldPos=%ld\n", dwOldPos
);
981 if (lpckParent
!= NULL
) {
982 TRACE("seek inside parent at %ld !\n", lpckParent
->dwDataOffset
);
983 /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
984 if (dwOldPos
< lpckParent
->dwDataOffset
|| dwOldPos
>= lpckParent
->dwDataOffset
+ lpckParent
->cksize
) {
985 WARN("outside parent chunk\n");
986 return MMIOERR_CHUNKNOTFOUND
;
990 /* The SDK docu says 'ckid' is used for all cases. Real World
991 * examples disagree -Marcus,990216.
995 /* find_chunk looks for 'ckid' */
996 if (uFlags
& MMIO_FINDCHUNK
)
997 srchCkId
= lpck
->ckid
;
998 /* find_riff and find_list look for 'fccType' */
999 if (uFlags
& MMIO_FINDLIST
) {
1000 srchCkId
= FOURCC_LIST
;
1001 srchType
= lpck
->fccType
;
1003 if (uFlags
& MMIO_FINDRIFF
) {
1004 srchCkId
= FOURCC_RIFF
;
1005 srchType
= lpck
->fccType
;
1008 TRACE("searching for %.4s.%.4s\n",
1010 srchType
?(LPSTR
)&srchType
:"<any>");
1012 if (uFlags
& (MMIO_FINDCHUNK
|MMIO_FINDLIST
|MMIO_FINDRIFF
)) {
1016 ix
= mmioRead(hmmio
, (LPSTR
)lpck
, 3 * sizeof(DWORD
));
1017 if (ix
< 2*sizeof(DWORD
)) {
1018 mmioSeek(hmmio
, dwOldPos
, SEEK_SET
);
1019 WARN("return ChunkNotFound\n");
1020 return MMIOERR_CHUNKNOTFOUND
;
1022 lpck
->dwDataOffset
= dwOldPos
+ 2 * sizeof(DWORD
);
1023 if (ix
< lpck
->dwDataOffset
- dwOldPos
) {
1024 mmioSeek(hmmio
, dwOldPos
, SEEK_SET
);
1025 WARN("return ChunkNotFound\n");
1026 return MMIOERR_CHUNKNOTFOUND
;
1028 TRACE("ckid=%.4ss fcc=%.4ss cksize=%08lX !\n",
1030 srchType
?(LPSTR
)&lpck
->fccType
:"<unused>",
1032 if ((srchCkId
== lpck
->ckid
) &&
1033 (!srchType
|| (srchType
== lpck
->fccType
))
1037 dwOldPos
= lpck
->dwDataOffset
+ ((lpck
->cksize
+ 1) & ~1);
1038 mmioSeek(hmmio
, dwOldPos
, SEEK_SET
);
1041 /* FIXME: unverified, does it do this? */
1042 if (mmioRead(hmmio
, (LPSTR
)lpck
, 3 * sizeof(DWORD
)) < 3 * sizeof(DWORD
)) {
1043 mmioSeek(hmmio
, dwOldPos
, SEEK_SET
);
1044 WARN("return ChunkNotFound 2nd\n");
1045 return MMIOERR_CHUNKNOTFOUND
;
1047 lpck
->dwDataOffset
= dwOldPos
+ 2 * sizeof(DWORD
);
1050 /* If we were looking for RIFF/LIST chunks, the final file position
1051 * is after the chunkid. If we were just looking for the chunk
1052 * it is after the cksize. So add 4 in RIFF/LIST case.
1054 if (lpck
->ckid
== FOURCC_RIFF
|| lpck
->ckid
== FOURCC_LIST
)
1055 mmioSeek(hmmio
, lpck
->dwDataOffset
+ sizeof(DWORD
), SEEK_SET
);
1057 mmioSeek(hmmio
, lpck
->dwDataOffset
, SEEK_SET
);
1058 TRACE("lpck: ckid=%.4s, cksize=%ld, dwDataOffset=%ld fccType=%08lX (%.4s)!\n",
1059 (LPSTR
)&lpck
->ckid
, lpck
->cksize
, lpck
->dwDataOffset
,
1060 lpck
->fccType
, srchType
?(LPSTR
)&lpck
->fccType
:"");
1064 /**************************************************************************
1065 * mmioAscend [WINMM.113]
1067 UINT WINAPI
mmioAscend(HMMIO hmmio
, MMCKINFO
* lpck
, UINT uFlags
)
1069 TRACE("(%04X, %p, %04X);\n", hmmio
, lpck
, uFlags
);
1071 if (lpck
->dwFlags
& MMIO_DIRTY
) {
1072 DWORD dwOldPos
, dwNewSize
, dwSizePos
;
1074 TRACE("chunk is marked MMIO_DIRTY, correcting chunk size\n");
1075 dwOldPos
= mmioSeek(hmmio
, 0, SEEK_CUR
);
1076 TRACE("dwOldPos=%ld\n", dwOldPos
);
1077 dwNewSize
= dwOldPos
- lpck
->dwDataOffset
;
1078 if (dwNewSize
!= lpck
->cksize
) {
1079 TRACE("dwNewSize=%ld\n", dwNewSize
);
1080 lpck
->cksize
= dwNewSize
;
1082 dwSizePos
= lpck
->dwDataOffset
- sizeof(DWORD
);
1083 TRACE("dwSizePos=%ld\n", dwSizePos
);
1085 mmioSeek(hmmio
, dwSizePos
, SEEK_SET
);
1086 mmioWrite(hmmio
, (LPSTR
)&dwNewSize
, sizeof(DWORD
));
1090 mmioSeek(hmmio
, lpck
->dwDataOffset
+ ((lpck
->cksize
+ 1) & ~1), SEEK_SET
);
1095 /**************************************************************************
1096 * mmioAscend [MMSYSTEM.1224]
1098 UINT16 WINAPI
mmioAscend16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
1100 return mmioAscend(hmmio
,lpck
,uFlags
);
1103 /**************************************************************************
1104 * mmioCreateChunk [MMSYSTEM.1225]
1106 UINT16 WINAPI
mmioCreateChunk16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
1112 TRACE("(%04X, %p, %04X);\n", hmmio
, lpck
, uFlags
);
1114 dwOldPos
= mmioSeek(hmmio
, 0, SEEK_CUR
);
1115 TRACE("dwOldPos=%ld\n", dwOldPos
);
1117 if (uFlags
== MMIO_CREATELIST
)
1118 lpck
->ckid
= FOURCC_LIST
;
1119 else if (uFlags
== MMIO_CREATERIFF
)
1120 lpck
->ckid
= FOURCC_RIFF
;
1122 TRACE("ckid=%08lX\n", lpck
->ckid
);
1124 size
= 2 * sizeof(DWORD
);
1125 lpck
->dwDataOffset
= dwOldPos
+ size
;
1127 if (lpck
->ckid
== FOURCC_RIFF
|| lpck
->ckid
== FOURCC_LIST
)
1128 size
+= sizeof(DWORD
);
1129 lpck
->dwFlags
= MMIO_DIRTY
;
1131 ix
= mmioWrite(hmmio
, (LPSTR
)lpck
, size
);
1132 TRACE("after mmioWrite ix = %ld req = %ld, errno = %d\n",ix
, size
, errno
);
1134 mmioSeek(hmmio
, dwOldPos
, SEEK_SET
);
1135 WARN("return CannotWrite\n");
1136 return MMIOERR_CANNOTWRITE
;
1142 /**************************************************************************
1143 * mmioCreateChunk [WINMM.115]
1145 UINT WINAPI
mmioCreateChunk(HMMIO hmmio
, MMCKINFO
* lpck
, UINT uFlags
)
1147 return mmioCreateChunk16(hmmio
, lpck
, uFlags
);
1150 /**************************************************************************
1151 * mmioRename [MMSYSTEM.1226]
1153 UINT16 WINAPI
mmioRename16(LPCSTR szFileName
, LPCSTR szNewFileName
,
1154 MMIOINFO16
* lpmmioinfo
, DWORD dwRenameFlags
)
1157 LPMMIOINFO16 lpmminfo
;
1160 TRACE("('%s', '%s', %p, %08lX);\n",
1161 szFileName
, szNewFileName
, lpmmioinfo
, dwRenameFlags
);
1163 hmmio
= GlobalAlloc16(GHND
, sizeof(MMIOINFO16
));
1164 lpmminfo
= (LPMMIOINFO16
) GlobalLock16(hmmio
);
1167 memcpy(lpmminfo
, lpmmioinfo
, sizeof(MMIOINFO16
));
1169 /* assume DOS file if not otherwise specified */
1170 if (lpmminfo
->fccIOProc
== 0 && lpmminfo
->pIOProc
== NULL
) {
1172 lpmminfo
->fccIOProc
= mmioFOURCC('D', 'O', 'S', ' ');
1173 lpmminfo
->pIOProc
= (LPMMIOPROC16
) mmioDosIOProc
;
1176 /* if just the four character code is present, look up IO proc */
1177 else if (lpmminfo
->pIOProc
== NULL
) {
1179 lpmminfo
->pIOProc
= mmioInstallIOProc16(lpmminfo
->fccIOProc
, NULL
, MMIO_FINDPROC
);
1182 /* (if IO proc specified, use it and specified four character code) */
1184 result
= (UINT16
) mmioSendMessage(hmmio
, MMIOM_RENAME
, (LPARAM
) szFileName
, (LPARAM
) szNewFileName
);
1186 GlobalUnlock16(hmmio
);
1187 GlobalFree16(hmmio
);
1192 /**************************************************************************
1193 * mmioRenameA [WINMM.125]
1195 UINT WINAPI
mmioRenameA(LPCSTR szFileName
, LPCSTR szNewFileName
,
1196 MMIOINFO
* lpmmioinfo
, DWORD dwRenameFlags
)
1198 FIXME("This may fail\n");
1199 return mmioRename16(szFileName
, szNewFileName
, (MMIOINFO16
*)lpmmioinfo
, dwRenameFlags
);
1202 /**************************************************************************
1203 * mmioRenameW [WINMM.126]
1205 UINT WINAPI
mmioRenameW(LPCWSTR szFileName
, LPCWSTR szNewFileName
,
1206 MMIOINFO
* lpmmioinfo
, DWORD dwRenameFlags
)
1208 LPSTR szFn
= HEAP_strdupWtoA(GetProcessHeap(), 0, szFileName
);
1209 LPSTR sznFn
= HEAP_strdupWtoA(GetProcessHeap(), 0, szNewFileName
);
1210 UINT ret
= mmioRenameA(szFn
, sznFn
, lpmmioinfo
, dwRenameFlags
);
1212 HeapFree(GetProcessHeap(),0,szFn
);
1213 HeapFree(GetProcessHeap(),0,sznFn
);