Ensure that CreateFileMoniker functions don't return a bogus moniker
[wine.git] / multimedia / mmio.c
blob6fd9b7025486aea228360f2482513653b6010550
1 /*
2 * MMIO functions
4 * Copyright 1998 Andrew Taylor
5 * Copyright 1998 Ove Kåven
7 */
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include "windows.h"
14 #include "win.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "file.h"
18 #include "mmsystem.h"
19 #include "debug.h"
20 #include "xmalloc.h"
22 /**************************************************************************
23 * mmioDosIOProc [internal]
25 static LRESULT mmioDosIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
26 TRACE(mmio, "(%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2);
28 switch (uMessage) {
30 case MMIOM_OPEN: {
31 /* Parameters:
32 * lParam1 = szFileName parameter from mmioOpen
33 * lParam2 = reserved (we use it for 16-bitness)
34 * Returns: zero on success, error code on error
35 * NOTE: lDiskOffset automatically set to zero
38 OFSTRUCT ofs;
39 LPSTR szFileName = (LPSTR) lParam1;
41 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
42 FIXME(mmio, "MMIO_GETTEMP not implemented\n");
43 return MMIOERR_CANNOTOPEN;
46 /* if filename NULL, assume open file handle in adwInfo[0] */
47 if (!szFileName) {
48 if (lParam2) lpmmioinfo->adwInfo[0] =
49 HFILE16_TO_HFILE32(lpmmioinfo->adwInfo[0]);
50 return 0;
53 lpmmioinfo->adwInfo[0] =
54 (DWORD) OpenFile32(szFileName, &ofs, lpmmioinfo->dwFlags);
55 if (lpmmioinfo->adwInfo[0] == -1)
56 return MMIOERR_CANNOTOPEN;
58 return 0;
61 case MMIOM_CLOSE: {
62 /* Parameters:
63 * lParam1 = wFlags parameter from mmioClose
64 * lParam2 = unused
65 * Returns: zero on success, error code on error
68 UINT16 uFlags = (UINT16) lParam1;
70 if (uFlags & MMIO_FHOPEN)
71 return 0;
73 _lclose32((HFILE32)lpmmioinfo->adwInfo[0]);
74 return 0;
78 case MMIOM_READ: {
79 /* Parameters:
80 * lParam1 = huge pointer to read buffer
81 * lParam2 = number of bytes to read
82 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
83 * in wErrorRet)
84 * NOTE: lDiskOffset should be updated
87 HPSTR pch = (HPSTR) lParam1;
88 LONG cch = (LONG) lParam2;
89 LONG count;
91 count = _lread32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
92 if (count != -1)
93 lpmmioinfo->lDiskOffset += count;
95 return count;
98 case MMIOM_WRITE:
99 case MMIOM_WRITEFLUSH: {
100 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
102 /* Parameters:
103 * lParam1 = huge pointer to write buffer
104 * lParam2 = number of bytes to write
105 * Returns: number of bytes written, -1 for error (error code in
106 * wErrorRet)
107 * NOTE: lDiskOffset should be updated
110 HPSTR pch = (HPSTR) lParam1;
111 LONG cch = (LONG) lParam2;
112 LONG count;
114 count = _hwrite32((HFILE32)lpmmioinfo->adwInfo[0], pch, cch);
115 if (count != -1)
116 lpmmioinfo->lDiskOffset += count;
118 return count;
121 case MMIOM_SEEK: {
122 /* Parameters:
123 * lParam1 = new position
124 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
125 * Returns: new file postion, -1 on error
126 * NOTE: lDiskOffset should be updated
129 LONG Offset = (LONG) lParam1;
130 LONG Whence = (LONG) lParam2;
131 LONG pos;
133 pos = _llseek32((HFILE32)lpmmioinfo->adwInfo[0], Offset, Whence);
134 if (pos != -1)
135 lpmmioinfo->lDiskOffset = pos;
137 return pos;
140 case MMIOM_RENAME: {
141 /* Parameters:
142 * lParam1 = old name
143 * lParam2 = new name
144 * Returns: zero on success, non-zero on failure
147 FIXME(mmio, "MMIOM_RENAME unimplemented\n");
148 return MMIOERR_FILENOTFOUND;
151 default:
152 FIXME(mmio, "unexpected message %u\n", uMessage);
153 return 0;
156 return 0;
159 /**************************************************************************
160 * mmioMemIOProc [internal]
162 static LRESULT mmioMemIOProc(LPMMIOINFO16 lpmmioinfo, UINT16 uMessage, LPARAM lParam1, LPARAM lParam2) {
163 TRACE(mmio,"(%p,0x%04x,0x%08lx,0x%08lx)\n",lpmmioinfo,uMessage,lParam1,lParam2);
164 switch (uMessage) {
166 case MMIOM_OPEN: {
167 /* Parameters:
168 * lParam1 = filename (must be NULL)
169 * lParam2 = reserved (we use it for 16-bitness)
170 * Returns: zero on success, error code on error
171 * NOTE: lDiskOffset automatically set to zero
174 if (!(lpmmioinfo->dwFlags & MMIO_CREATE))
175 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite;
177 return 0;
180 case MMIOM_CLOSE: {
181 /* Parameters:
182 * lParam1 = wFlags parameter from mmioClose
183 * lParam2 = unused
184 * Returns: zero on success, error code on error
187 return 0;
191 case MMIOM_READ: {
192 /* Parameters:
193 * lParam1 = huge pointer to read buffer
194 * lParam2 = number of bytes to read
195 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
196 * in wErrorRet)
197 * NOTE: lDiskOffset should be updated
200 HPSTR pch = (HPSTR) lParam1;
201 LONG cch = (LONG) lParam2;
203 FIXME(mmio,"MMIOM_READ on memory files should not occur, buffer may be lost!\n");
204 return 0;
207 case MMIOM_WRITE:
208 case MMIOM_WRITEFLUSH: {
209 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
211 /* Parameters:
212 * lParam1 = huge pointer to write buffer
213 * lParam2 = number of bytes to write
214 * Returns: number of bytes written, -1 for error (error code in
215 * wErrorRet)
216 * NOTE: lDiskOffset should be updated
219 HPSTR pch = (HPSTR) lParam1;
220 LONG cch = (LONG) lParam2;
222 FIXME(mmio,"MMIOM_WRITE on memory files should not occur, buffer may be lost!\n");
223 return 0;
226 case MMIOM_SEEK: {
227 /* Parameters:
228 * lParam1 = new position
229 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
230 * Returns: new file postion, -1 on error
231 * NOTE: lDiskOffset should be updated
234 LONG Offset = (LONG) lParam1;
235 LONG Whence = (LONG) lParam2;
237 FIXME(mmio,"MMIOM_SEEK on memory files should not occur, buffer may be lost!\n");
238 return -1;
241 default:
242 FIXME(mmio, "unexpected message %u\n", uMessage);
243 return 0;
246 return 0;
249 /**************************************************************************
250 * MMIO_Open [internal]
252 static HMMIO16 MMIO_Open(LPSTR szFileName, MMIOINFO16 * lpmmioinfo,
253 DWORD dwOpenFlags, int use16)
255 LPMMIOINFO16 lpmminfo;
256 HMMIO16 hmmio;
257 UINT16 result;
259 TRACE(mmio, "('%s', %p, %08lX);\n", szFileName, lpmmioinfo, dwOpenFlags);
261 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
262 lpmminfo = (LPMMIOINFO16)GlobalLock16(hmmio);
263 if (lpmminfo == NULL)
264 return 0;
265 memset(lpmminfo, 0, sizeof(MMIOINFO16));
267 /* assume DOS file if not otherwise specified */
268 if (!lpmmioinfo ||
269 (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)) {
271 lpmminfo->fccIOProc = FOURCC_DOS;
272 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
274 /* if just the four character code is present, look up IO proc */
275 else if (lpmmioinfo->pIOProc == NULL) {
277 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
278 lpmminfo->pIOProc = mmioInstallIOProc16(lpmmioinfo->fccIOProc, NULL, MMIO_FINDPROC);
281 /* if IO proc specified, use it and specified four character code */
282 else {
284 lpmminfo->fccIOProc = lpmmioinfo->fccIOProc;
285 lpmminfo->pIOProc = lpmmioinfo->pIOProc;
288 if (dwOpenFlags & MMIO_ALLOCBUF) {
289 if ((result = 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;
935 TRACE(mmio, "(%04X, %p, %p, %04X);\n",
936 hmmio, lpck, lpckParent, uFlags);
938 if (lpck == NULL)
939 return 0;
941 dwfcc = lpck->ckid;
942 TRACE(mmio, "dwfcc=%08lX\n", dwfcc);
944 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
945 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
947 if (lpckParent != NULL) {
948 TRACE(mmio, "seek inside parent at %ld !\n", lpckParent->dwDataOffset);
949 dwOldPos = mmioSeek32(hmmio,lpckParent->dwDataOffset,SEEK_SET);
953 It seems to be that FINDRIFF should not be treated the same as the
954 other FINDxxx so I treat it as a MMIO_FINDxxx
956 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDRIFF) ||
957 (uFlags & MMIO_FINDLIST)) {
959 if ((uFlags & MMIO_FINDCHUNK) || (uFlags & MMIO_FINDLIST)) {
960 TRACE(mmio, "MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
961 while (TRUE) {
962 LONG ix;
964 ix = mmioRead32(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
965 TRACE(mmio, "after _lread32 ix = %ld req = %d, errno = %d\n",ix,3 * sizeof(DWORD),errno);
966 if (ix < sizeof(DWORD)) {
967 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
968 WARN(mmio, "return ChunkNotFound\n");
969 return MMIOERR_CHUNKNOTFOUND;
971 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
972 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
973 lpck->dwDataOffset += sizeof(DWORD);
974 if (ix < lpck->dwDataOffset - dwOldPos) {
975 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
976 WARN(mmio, "return ChunkNotFound\n");
977 return MMIOERR_CHUNKNOTFOUND;
979 TRACE(mmio, "dwfcc=%08lX ckid=%08lX cksize=%08lX !\n",
980 dwfcc, lpck->ckid, lpck->cksize);
981 if (dwfcc == lpck->ckid)
982 break;
984 dwOldPos = lpck->dwDataOffset + lpck->cksize;
985 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
988 else {
989 if (mmioRead32(hmmio, (LPSTR)lpck, sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
990 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
991 WARN(mmio, "return ChunkNotFound 2nd\n");
992 return MMIOERR_CHUNKNOTFOUND;
994 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
995 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
996 lpck->dwDataOffset += sizeof(DWORD);
998 mmioSeek32(hmmio, lpck->dwDataOffset, SEEK_SET);
1000 TRACE(mmio, "lpck->ckid=%08lX lpck->cksize=%ld !\n",
1001 lpck->ckid, lpck->cksize);
1002 TRACE(mmio, "lpck->fccType=%08lX !\n", lpck->fccType);
1004 return 0;
1007 /**************************************************************************
1008 * mmioAscend [WINMM.113]
1010 UINT32 WINAPI mmioAscend32(HMMIO32 hmmio, MMCKINFO * lpck, UINT32 uFlags)
1012 TRACE(mmio, "(%04X, %p, %04X);\n",
1013 hmmio, lpck, uFlags);
1014 if (lpck->dwFlags&MMIO_DIRTY) {
1015 DWORD dwOldPos, dwNewSize, dwSizePos;
1017 TRACE(mmio, "chunk is marked MMIO_DIRTY, correcting chunk size\n");
1018 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1019 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1020 dwNewSize = dwOldPos - lpck->dwDataOffset;
1021 if (dwNewSize != lpck->cksize) {
1022 TRACE(mmio, "dwNewSize=%ld\n", dwNewSize);
1023 lpck->cksize = dwNewSize;
1025 dwSizePos = lpck->dwDataOffset - sizeof(DWORD);
1026 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1027 dwSizePos -= sizeof(DWORD);
1028 TRACE(mmio, "dwSizePos=%ld\n", dwSizePos);
1030 mmioSeek32(hmmio, dwSizePos, SEEK_SET);
1031 mmioWrite32(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1034 mmioSeek32(hmmio,lpck->dwDataOffset+lpck->cksize,SEEK_SET);
1036 return 0;
1039 /**************************************************************************
1040 * mmioAscend [MMSYSTEM.1224]
1042 UINT16 WINAPI mmioAscend16(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1044 return mmioAscend32(hmmio,lpck,uFlags);
1047 /**************************************************************************
1048 * mmioCreateChunk [MMSYSTEM.1225]
1050 UINT16 WINAPI mmioCreateChunk(HMMIO16 hmmio, MMCKINFO * lpck, UINT16 uFlags)
1052 DWORD dwOldPos;
1053 LONG ix;
1055 TRACE(mmio, "(%04X, %p, %04X);\n",
1056 hmmio, lpck, uFlags);
1058 dwOldPos = mmioSeek32(hmmio, 0, SEEK_CUR);
1059 TRACE(mmio, "dwOldPos=%ld\n", dwOldPos);
1061 if (uFlags == MMIO_CREATELIST)
1062 lpck->ckid = FOURCC_LIST;
1063 else if (uFlags == MMIO_CREATERIFF)
1064 lpck->ckid = FOURCC_RIFF;
1066 TRACE(mmio, "ckid=%08lX\n", lpck->ckid);
1068 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1069 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1070 lpck->dwDataOffset += sizeof(DWORD);
1071 lpck->dwFlags = MMIO_DIRTY;
1073 ix = mmioWrite32(hmmio, (LPSTR)lpck, lpck->dwDataOffset - dwOldPos);
1074 TRACE(mmio, "after _lwrite32 ix = %ld req = %ld, errno = %d\n",ix,lpck->dwDataOffset - dwOldPos,errno);
1075 if (ix < lpck->dwDataOffset - dwOldPos) {
1077 mmioSeek32(hmmio, dwOldPos, SEEK_SET);
1078 WARN(mmio, "return CannotWrite\n");
1079 return MMIOERR_CANNOTWRITE;
1082 return 0;
1086 /**************************************************************************
1087 * mmioRename [MMSYSTEM.1226]
1089 UINT16 WINAPI mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
1090 MMIOINFO16 * lpmmioinfo, DWORD dwRenameFlags)
1092 UINT16 result;
1093 LPMMIOINFO16 lpmminfo;
1094 HMMIO16 hmmio;
1096 TRACE(mmio, "('%s', '%s', %p, %08lX);\n",
1097 szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
1099 hmmio = GlobalAlloc16(GHND, sizeof(MMIOINFO16));
1100 lpmminfo = (LPMMIOINFO16) GlobalLock16(hmmio);
1102 if (lpmmioinfo)
1103 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO16));
1105 /* assume DOS file if not otherwise specified */
1106 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
1108 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
1109 lpmminfo->pIOProc = (LPMMIOPROC16) mmioDosIOProc;
1112 /* if just the four character code is present, look up IO proc */
1113 else if (lpmminfo->pIOProc == NULL) {
1115 lpmminfo->pIOProc = mmioInstallIOProc16(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
1118 /* (if IO proc specified, use it and specified four character code) */
1120 result = (UINT16) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
1122 GlobalUnlock16(hmmio);
1123 GlobalFree16(hmmio);
1125 return result;