4 * Copyright 1998 Andrew Taylor
6 * NOTES: I/O is still unbuffered; mmioSetBuffer must be implemented
7 * and mmio{Read,Write,Seek,others?} need buffer support.
8 * Buffering should almost give us memory files for free.
25 /**************************************************************************
26 * mmioDosIOProc [internal]
28 static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
29 TRACE(mmio, "(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
35 * lParam1 = szFileName parameter from mmioOpen
37 * Returns: zero on success, error code on error
38 * NOTE: lDiskOffset automatically set to zero
42 LPSTR szFileName = (LPSTR) lParam1;
44 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
45 FIXME(mmio, "MMIO_GETTEMP not implemented\n");
46 return MMIOERR_CANNOTOPEN;
49 /* if filename NULL, assume open file handle in adwInfo[0] */
53 lpmmioinfo->adwInfo[0] =
54 (DWORD) OpenFile32(szFileName, &ofs, lpmmioinfo->dwFlags);
55 if (lpmmioinfo->adwInfo[0] == -1)
56 return MMIOERR_CANNOTOPEN;
63 * lParam1 = wFlags parameter from mmioClose
65 * Returns: zero on success, error code on error
68 UINT16 uFlags = (UINT16) lParam1;
70 if (uFlags & MMIO_FHOPEN)
73 _lclose32((HFILE32)lpmmioinfo->adwInfo[0]);
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
84 * NOTE: lDiskOffset should be updated
87 HPSTR pch = (HPSTR) lParam1;
88 LONG cch = (LONG) lParam2;
91 count = _lread32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
93 lpmmioinfo->lDiskOffset += count;
99 case MMIOM_WRITEFLUSH: {
100 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
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
107 * NOTE: lDiskOffset should be updated
110 HPSTR pch = (HPSTR) lParam1;
111 LONG cch = (LONG) lParam2;
114 count = _hwrite16((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
116 lpmmioinfo->lDiskOffset += count;
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;
133 pos = _llseek32((HFILE32)lpmmioinfo->adwInfo[0], Offset, Whence);
135 lpmmioinfo->lDiskOffset = pos;
144 * Returns: zero on success, non-zero on failure
147 FIXME(mmio, "MMIOM_RENAME unimplemented\n");
148 return MMIOERR_FILENOTFOUND;
152 WARN(mmio, "unexpected message %u\n", uMessage);
159 /**************************************************************************
160 * mmioDosIOProc [internal]
162 static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
166 /**************************************************************************
167 * mmioOpenW [WINMM.123]
169 HMMIO32 WINAPI mmioOpen32W(LPWSTR szFileName, MMIOINFO32 * lpmmioinfo,
172 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
173 HMMIO32 ret = mmioOpen16(szFn,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
175 HeapFree(GetProcessHeap(),0,szFn);
179 /**************************************************************************
180 * mmioOpenA [WINMM.122]
182 HMMIO32 WINAPI mmioOpen32A(LPSTR szFileName, MMIOINFO32 * lpmmioinfo,
185 return mmioOpen16(szFileName,(LPMMIOINFO16)lpmmioinfo,dwOpenFlags);
188 /**************************************************************************
189 * mmioOpen [MMSYSTEM.1210]
191 HMMIO16 WINAPI mmioOpen16(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
194 LPMMIOINFO16 lpmminfo;
198 TRACE(mmio, "('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
200 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
201 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
202 if (lpmminfo == NULL)
204 memset(lpmminfo, 0, sizeof(MMIOINFO16));
206 /* assume DOS file if not otherwise specified */
208 (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
210 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
211 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
213 /* if just the four character code is present, look up IO proc */
214 else if (lpmmioinfo->pIOProc == NULL) {
216 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
217 lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
220 /* if IO proc specified, use it and specified four character code */
223 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
224 lpmminfo->pIOProc = lpmmioinfo->pIOProc;
227 if (dwOpenFlags & MMIO_ALLOCBUF) {
228 if ((result = mmioSetBuffer(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
230 lpmmioinfo->wErrorRet = result;
235 lpmminfo->hmmio = hmmio;
237 /* call IO proc to actually open file */
238 result = (UINT16) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) 0);
240 GlobalUnlock16(hmmio);
251 /**************************************************************************
252 * mmioClose [MMSYSTEM.1211]
254 UINT16 WINAPI mmioClose(HMMIO16 hmmio, UINT16 uFlags)
256 LPMMIOINFO16 lpmminfo;
259 TRACE(mmio, "(%04X, %04X);\n", hmmio, uFlags);
261 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
262 if (lpmminfo == NULL)
265 /* flush the file - if error reported, ignore */
266 if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
267 lpmminfo->dwFlags &= ~MMIO_DIRTY;
269 result = (UINT16) mmioSendMessage(hmmio, MMIOM_CLOSE, (LPARAM) uFlags, (LPARAM) 0);
271 mmioSetBuffer(hmmio, NULL, 0, 0);
273 GlobalUnlock16(hmmio);
281 /**************************************************************************
282 * mmioRead [MMSYSTEM.1212]
284 LONG WINAPI mmioRead(HMMIO16 hmmio, HPSTR pch, LONG cch)
287 LPMMIOINFO16 lpmminfo;
289 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
291 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
292 if (lpmminfo == NULL)
295 count = mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
297 GlobalUnlock16(hmmio);
298 TRACE(mmio, "count=%ld\n", count);
304 /**************************************************************************
305 * mmioWrite [MMSYSTEM.1213]
307 LONG WINAPI mmioWrite(HMMIO16 hmmio, HPCSTR pch, LONG cch)
310 LPMMIOINFO16 lpmminfo;
312 TRACE(mmio, "(%04X, %p, %ld);\n", hmmio, pch, cch);
314 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
315 if (lpmminfo == NULL)
318 count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
320 GlobalUnlock16(hmmio);
321 TRACE(mmio, "count=%ld\n", count);
325 /**************************************************************************
326 * mmioSeek [MMSYSTEM.1214]
328 LONG WINAPI mmioSeek(HMMIO16 hmmio, LONG lOffset, int iOrigin)
331 LPMMIOINFO16 lpmminfo;
333 TRACE(mmio, "(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
335 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
336 if (lpmminfo == NULL)
339 offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
341 GlobalUnlock16(hmmio);
345 /**************************************************************************
346 * mmioGetInfo [MMSYSTEM.1215]
348 UINT16 WINAPI mmioGetInfo(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
350 LPMMIOINFO16 lpmminfo;
351 TRACE(mmio, "mmioGetInfo\n");
352 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
353 if (lpmminfo == NULL) return 0;
354 memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO16));
355 GlobalUnlock16(hmmio);
359 /**************************************************************************
360 * mmioSetInfo [MMSYSTEM.1216]
362 UINT16 WINAPI mmioSetInfo(HMMIO16 hmmio, const MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
364 LPMMIOINFO16 lpmminfo;
365 TRACE(mmio, "mmioSetInfo\n");
366 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
367 if (lpmminfo == NULL) return 0;
368 GlobalUnlock16(hmmio);
372 /**************************************************************************
373 * mmioSetBuffer [MMSYSTEM.1217]
375 UINT16 WINAPI mmioSetBuffer(HMMIO16 hmmio, LPSTR pchBuffer,
376 LONG cchBuffer, UINT16 uFlags)
378 FIXME(mmio, "empty stub \n");
382 /**************************************************************************
383 * mmioFlush [MMSYSTEM.1218]
385 UINT16 WINAPI mmioFlush(HMMIO16 hmmio, UINT16 uFlags)
387 LPMMIOINFO16 lpmminfo;
388 TRACE(mmio, "(%04X, %04X)\n", hmmio, uFlags);
389 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
390 if (lpmminfo == NULL) return 0;
391 GlobalUnlock16(hmmio);
395 /**************************************************************************
396 * mmioAdvance [MMSYSTEM.1219]
398 UINT16 WINAPI mmioAdvance(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
401 LPMMIOINFO16 lpmminfo;
402 TRACE(mmio, "mmioAdvance\n");
403 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
404 if (lpmminfo == NULL) return 0;
405 if (uFlags == MMIO_READ) {
406 count = _lread32(LOWORD(lpmminfo->adwInfo[0]),
407 lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
409 if (uFlags == MMIO_WRITE) {
410 count = _lwrite32(LOWORD(lpmminfo->adwInfo[0]),
411 lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
413 lpmmioinfo->pchNext += count;
414 GlobalUnlock16(hmmio);
415 lpmminfo->lDiskOffset = _llseek32((HFILE32)lpmminfo->adwInfo[0], 0, SEEK_CUR);
419 /**************************************************************************
420 * mmioStringToFOURCCA [WINMM.131]
422 FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
424 return mmioStringToFOURCC16(sz,uFlags);
427 /**************************************************************************
428 * mmioStringToFOURCCW [WINMM.132]
430 FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
432 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
433 FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
435 HeapFree(GetProcessHeap(),0,szA);
439 /**************************************************************************
440 * mmioStringToFOURCC [MMSYSTEM.1220]
442 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
444 FIXME(mmio, "empty stub \n");
448 /**************************************************************************
449 * mmioInstallIOProc16 [MMSYSTEM.1221]
451 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
452 LPMMIOPROC16 pIOProc, DWORD dwFlags)
454 TRACE(mmio, "(%ld, %p, %08lX)\n",
455 fccIOProc, pIOProc, dwFlags);
457 if (dwFlags & MMIO_GLOBALPROC) {
458 FIXME(mmio, " global procedures not implemented\n");
461 /* just handle the known procedures for now */
462 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
463 case MMIO_INSTALLPROC:
465 case MMIO_REMOVEPROC:
468 if (fccIOProc == FOURCC_DOS)
469 return (LPMMIOPROC16) mmioDosIOProc;
470 else if (fccIOProc == FOURCC_MEM)
471 return (LPMMIOPROC16) mmioMemIOProc;
479 /**************************************************************************
480 * mmioInstallIOProc32A [WINMM.120]
482 LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
483 LPMMIOPROC32 pIOProc, DWORD dwFlags)
485 FIXME(mmio, "(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
486 (char)((fccIOProc&0xff000000)>>24),
487 (char)((fccIOProc&0x00ff0000)>>16),
488 (char)((fccIOProc&0x0000ff00)>> 8),
489 (char)(fccIOProc&0x000000ff),
494 /**************************************************************************
495 * mmioSendMessage [MMSYSTEM.1222]
497 LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
498 LPARAM lParam1, LPARAM lParam2)
500 LPMMIOINFO16 lpmminfo;
502 const char *msg = NULL;
506 #define msgname(x) case x: msg = #x; break;
508 msgname(MMIOM_CLOSE);
510 msgname(MMIOM_WRITE);
511 msgname(MMIOM_WRITEFLUSH);
513 msgname(MMIOM_RENAME);
519 TRACE(mmio, "(%04X, %s, %ld, %ld)\n",
520 hmmio, msg, lParam1, lParam2);
522 TRACE(mmio, "(%04X, %u, %ld, %ld)\n",
523 hmmio, uMessage, lParam1, lParam2);
525 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
527 if (lpmminfo && lpmminfo->pIOProc)
528 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
530 result = MMSYSERR_INVALPARAM;
532 GlobalUnlock16(hmmio);
537 /**************************************************************************
538 * mmioDescend [MMSYSTEM.1223]
540 UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
541 const MMCKINFO * lpckParent, UINT16 uFlags)
543 DWORD dwfcc, dwOldPos;
545 TRACE(mmio, "(%04X, %p, %p, %04X);\n",
546 hmmio, lpck, lpckParent, uFlags);
552 TRACE(mmio, "dwfcc=%08lX\n", dwfcc);
554 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
555 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
557 if (lpckParent != NULL) {
558 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
559 dwOldPos = mmioSeek(hmmio, lpckParent->dwDataOffset, SEEK_SET);
563 It seems to be that FINDRIFF should not be treated the same as the
564 other FINDxxx so I treat it as a MMIO_FINDxxx
566 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
567 (uFlags & MMIO_FINDLIST)) {
569 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
570 TRACE(mmio, "MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
574 ix = mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO));
575 TRACE(mmio, "after _lread32 ix = %ld req = %d, errno = %d\n",ix,sizeof(MMCKINFO),errno);
576 if (ix < sizeof(MMCKINFO)) {
578 mmioSeek(hmmio, dwOldPos, SEEK_SET);
579 WARN(mmio, "return ChunkNotFound\n");
580 return MMIOERR_CHUNKNOTFOUND;
582 TRACE(mmio, "dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
583 dwfcc, lpck->ckid, lpck->cksize);
584 if (dwfcc == lpck->ckid)
587 dwOldPos += lpck->cksize + 2 * sizeof(DWORD);
588 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
589 dwOldPos += sizeof(DWORD);
590 mmioSeek(hmmio, dwOldPos, SEEK_SET);
594 if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
595 mmioSeek(hmmio, dwOldPos, SEEK_SET);
596 WARN(mmio, "return ChunkNotFound 2nd\n");
597 return MMIOERR_CHUNKNOTFOUND;
600 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
601 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
602 lpck->dwDataOffset += sizeof(DWORD);
603 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
605 TRACE(mmio, "lpck->ckid=%08lX lpck->cksize=%ld !\n",
606 lpck->ckid, lpck->cksize);
607 TRACE(mmio, "lpck->fccType=%08lX !\n", lpck->fccType);
612 /**************************************************************************
613 * mmioAscend [MMSYSTEM.1224]
615 UINT16 WINAPI mmioAscend(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
617 FIXME(mmio, "empty stub !\n");
621 /**************************************************************************
622 * mmioCreateChunk [MMSYSTEM.1225]
624 UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
626 FIXME(mmio, "empty stub \n");
631 /**************************************************************************
632 * mmioRename [MMSYSTEM.1226]
634 UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
635 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
638 LPMMIOINFO16 lpmminfo;
641 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
642 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
644 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
645 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
648 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
650 /* assume DOS file if not otherwise specified */
651 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
653 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
654 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
657 /* if just the four character code is present, look up IO proc */
658 else if (lpmminfo->pIOProc == NULL) {
660 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
663 /* (if IO proc specified, use it and specified four character code) */
665 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
667 GlobalUnlock16(hmmio);