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, "(hmmio=%d, pchBuf=%p, cchBuf=%d, uFlags=%#08x): stub\n",
379 hmmio, pchBuffer, cchBuffer, uFlags);
380 return MMIOERR_OUTOFMEMORY;
383 /**************************************************************************
384 * mmioFlush [MMSYSTEM.1218]
386 UINT16 WINAPI mmioFlush(HMMIO16 hmmio, UINT16 uFlags)
388 LPMMIOINFO16 lpmminfo;
389 TRACE(mmio, "(%04X, %04X)\n", hmmio, uFlags);
390 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
391 if (lpmminfo == NULL) return 0;
392 GlobalUnlock16(hmmio);
396 /**************************************************************************
397 * mmioAdvance [MMSYSTEM.1219]
399 UINT16 WINAPI mmioAdvance(HMMIO16 hmmio, MMIOINFO16 * lpmmioinfo, UINT16 uFlags)
402 LPMMIOINFO16 lpmminfo;
403 TRACE(mmio, "mmioAdvance\n");
404 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
405 if (lpmminfo == NULL) return 0;
406 if (uFlags == MMIO_READ) {
407 count = _lread32(LOWORD(lpmminfo->adwInfo[0]),
408 lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
410 if (uFlags == MMIO_WRITE) {
411 count = _lwrite32(LOWORD(lpmminfo->adwInfo[0]),
412 lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
414 lpmmioinfo->pchNext += count;
415 GlobalUnlock16(hmmio);
416 lpmminfo->lDiskOffset = _llseek32((HFILE32)lpmminfo->adwInfo[0], 0, SEEK_CUR);
420 /**************************************************************************
421 * mmioStringToFOURCCA [WINMM.131]
423 FOURCC WINAPI mmioStringToFOURCC32A(LPCSTR sz, UINT32 uFlags)
425 return mmioStringToFOURCC16(sz,uFlags);
428 /**************************************************************************
429 * mmioStringToFOURCCW [WINMM.132]
431 FOURCC WINAPI mmioStringToFOURCC32W(LPCWSTR sz, UINT32 uFlags)
433 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
434 FOURCC ret = mmioStringToFOURCC32A(szA,uFlags);
436 HeapFree(GetProcessHeap(),0,szA);
440 /**************************************************************************
441 * mmioStringToFOURCC [MMSYSTEM.1220]
443 FOURCC WINAPI mmioStringToFOURCC16(LPCSTR sz, UINT16 uFlags)
445 FIXME(mmio, "empty stub \n");
449 /**************************************************************************
450 * mmioInstallIOProc16 [MMSYSTEM.1221]
452 LPMMIOPROC16 WINAPI mmioInstallIOProc16(FOURCC fccIOProc,
453 LPMMIOPROC16 pIOProc, DWORD dwFlags)
455 TRACE(mmio, "(%ld, %p, %08lX)\n",
456 fccIOProc, pIOProc, dwFlags);
458 if (dwFlags & MMIO_GLOBALPROC) {
459 FIXME(mmio, " global procedures not implemented\n");
462 /* just handle the known procedures for now */
463 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
464 case MMIO_INSTALLPROC:
466 case MMIO_REMOVEPROC:
469 if (fccIOProc == FOURCC_DOS)
470 return (LPMMIOPROC16) mmioDosIOProc;
471 else if (fccIOProc == FOURCC_MEM)
472 return (LPMMIOPROC16) mmioMemIOProc;
480 /**************************************************************************
481 * mmioInstallIOProc32A [WINMM.120]
483 LPMMIOPROC32 WINAPI mmioInstallIOProc32A(FOURCC fccIOProc,
484 LPMMIOPROC32 pIOProc, DWORD dwFlags)
486 FIXME(mmio, "(%c%c%c%c,%p,0x%08lx) -- empty stub \n",
487 (char)((fccIOProc&0xff000000)>>24),
488 (char)((fccIOProc&0x00ff0000)>>16),
489 (char)((fccIOProc&0x0000ff00)>> 8),
490 (char)(fccIOProc&0x000000ff),
495 /**************************************************************************
496 * mmioSendMessage [MMSYSTEM.1222]
498 LRESULT WINAPI mmioSendMessage(HMMIO16 hmmio, UINT16 uMessage,
499 LPARAM lParam1, LPARAM lParam2)
501 LPMMIOINFO16 lpmminfo;
503 const char *msg = NULL;
507 #define msgname(x) case x: msg = #x; break;
509 msgname(MMIOM_CLOSE);
511 msgname(MMIOM_WRITE);
512 msgname(MMIOM_WRITEFLUSH);
514 msgname(MMIOM_RENAME);
520 TRACE(mmio, "(%04X, %s, %ld, %ld)\n",
521 hmmio, msg, lParam1, lParam2);
523 TRACE(mmio, "(%04X, %u, %ld, %ld)\n",
524 hmmio, uMessage, lParam1, lParam2);
526 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
528 if (lpmminfo && lpmminfo->pIOProc)
529 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, uMessage, lParam1, lParam2);
531 result = MMSYSERR_INVALPARAM;
533 GlobalUnlock16(hmmio);
538 /**************************************************************************
539 * mmioDescend [MMSYSTEM.1223]
541 UINT16 WINAPI mmioDescend(HMMIO16 hmmio, MMCKINFO * lpck,
542 const MMCKINFO * lpckParent, UINT16 uFlags)
544 DWORD dwfcc, dwOldPos;
546 TRACE(mmio, "(%04X, %p, %p, %04X);\n",
547 hmmio, lpck, lpckParent, uFlags);
553 TRACE(mmio, "dwfcc=%08lX\n", dwfcc);
555 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
556 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
558 if (lpckParent != NULL) {
559 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
560 dwOldPos = mmioSeek(hmmio, lpckParent->dwDataOffset, SEEK_SET);
564 It seems to be that FINDRIFF should not be treated the same as the
565 other FINDxxx so I treat it as a MMIO_FINDxxx
567 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
568 (uFlags & MMIO_FINDLIST)) {
570 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
571 TRACE(mmio, "MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
575 ix = mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO));
576 TRACE(mmio, "after _lread32 ix = %ld req = %d, errno = %d\n",ix,sizeof(MMCKINFO),errno);
577 if (ix < sizeof(MMCKINFO)) {
579 mmioSeek(hmmio, dwOldPos, SEEK_SET);
580 WARN(mmio, "return ChunkNotFound\n");
581 return MMIOERR_CHUNKNOTFOUND;
583 TRACE(mmio, "dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
584 dwfcc, lpck->ckid, lpck->cksize);
585 if (dwfcc == lpck->ckid)
588 dwOldPos += lpck->cksize + 2 * sizeof(DWORD);
589 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
590 dwOldPos += sizeof(DWORD);
591 mmioSeek(hmmio, dwOldPos, SEEK_SET);
595 if (mmioRead(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
596 mmioSeek(hmmio, dwOldPos, SEEK_SET);
597 WARN(mmio, "return ChunkNotFound 2nd\n");
598 return MMIOERR_CHUNKNOTFOUND;
601 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
602 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
603 lpck->dwDataOffset += sizeof(DWORD);
604 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
606 TRACE(mmio, "lpck->ckid=%08lX lpck->cksize=%ld !\n",
607 lpck->ckid, lpck->cksize);
608 TRACE(mmio, "lpck->fccType=%08lX !\n", lpck->fccType);
613 /**************************************************************************
614 * mmioAscend [MMSYSTEM.1224]
616 UINT16 WINAPI mmioAscend(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
618 FIXME(mmio, "empty stub !\n");
622 /**************************************************************************
623 * mmioCreateChunk [MMSYSTEM.1225]
625 UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
627 FIXME(mmio, "empty stub \n");
632 /**************************************************************************
633 * mmioRename [MMSYSTEM.1226]
635 UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
636 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
639 LPMMIOINFO16 lpmminfo;
642 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
643 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
645 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
646 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
649 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
651 /* assume DOS file if not otherwise specified */
652 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
654 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
655 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
658 /* if just the four character code is present, look up IO proc */
659 else if (lpmminfo->pIOProc == NULL) {
661 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
664 /* (if IO proc specified, use it and specified four character code) */
666 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
668 GlobalUnlock16(hmmio);