source: trunk/src/winmm/mmio.cpp@ 3830

Last change on this file since 3830 was 2812, checked in by sandervl, 26 years ago

Added new logging feature + fixed waveout query format bug

File size: 30.7 KB
Line 
1/*
2 * MMIO functions
3 *
4 * Copyright 1999 Przemyslaw Dobrowolski
5 *
6 * Based on Wine code:
7 * Copyright 1998 Andrew Taylor
8 * Copyright 1998 Ove Kåven
9 *
10 */
11
12#include <os2win.h>
13#include <mmsystem.h>
14#include <odinwrap.h>
15#include <misc.h>
16#include <string.h>
17#include <heapstring.h>
18
19#include <stdlib.h>
20#include <errno.h>
21#include "windef.h"
22#include "file.h"
23#include "mmsystem.h"
24#include "debugtools.h"
25
26#define DBG_LOCALLOG DBG_mmio
27#include "dbglocal.h"
28
29ODINDEBUGCHANNEL(WINMM-MMIO)
30
31/**************************************************************************
32 * mmioDosIOProc [internal]
33 */
34static LRESULT WIN32API mmioDosIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
35{
36 dprintf(("mmioDosIOProc (%p, %X, %ld, %ld);\n", lpmmioinfo, uMessage, lParam1, lParam2));
37
38 switch (uMessage) {
39
40 case MMIOM_OPEN: {
41 /* Parameters:
42 * lParam1 = szFileName parameter from mmioOpen
43 * lParam2 = resrved
44 * NOTE: lDiskOffset automatically set to zero
45 */
46
47 OFSTRUCT ofs;
48 LPSTR szFileName = (LPSTR) lParam1;
49
50 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
51 dprintf(("WINMM: mmioDosIOProc MMIO_GETTEMP not implemented\n"));
52 return MMIOERR_CANNOTOPEN;
53 }
54
55 lpmmioinfo->adwInfo[0] =
56 (DWORD) OpenFile(szFileName, &ofs, lpmmioinfo->dwFlags);
57 if (lpmmioinfo->adwInfo[0] == -1)
58 return MMIOERR_CANNOTOPEN;
59
60 return 0;
61 }
62
63 case MMIOM_CLOSE: {
64 /* Parameters:
65 * lParam1 = wFlags parameter from mmioClose
66 * lParam2 = unused
67 * Returns: zero on success, error code on error
68 */
69
70 UINT uFlags = (UINT)lParam1;
71
72 if (uFlags & MMIO_FHOPEN)
73 return 0;
74
75 _lclose((HFILE)lpmmioinfo->adwInfo[0]);
76 return 0;
77
78 }
79
80 case MMIOM_READ: {
81 /* Parameters:
82 * lParam1 = huge pointer to read buffer
83 * lParam2 = number of bytes to read
84 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
85 * in wErrorRet)
86 * NOTE: lDiskOffset should be updated
87 */
88
89 HPSTR pch = (HPSTR) lParam1;
90 LONG cch = (LONG) lParam2;
91 LONG count;
92
93 count = _lread((HFILE)lpmmioinfo->adwInfo[0], pch, cch);
94 if (count != -1)
95 lpmmioinfo->lDiskOffset += count;
96
97 return count;
98 }
99
100 case MMIOM_WRITE:
101 case MMIOM_WRITEFLUSH: {
102 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
103
104 /* Parameters:
105 * lParam1 = huge pointer to write buffer
106 * lParam2 = number of bytes to write
107 * Returns: number of bytes written, -1 for error (error code in
108 * wErrorRet)
109 * NOTE: lDiskOffset should be updated
110 */
111
112 HPSTR pch = (HPSTR) lParam1;
113 LONG cch = (LONG) lParam2;
114 LONG count;
115
116 count = _hwrite((HFILE)lpmmioinfo->adwInfo[0], pch, cch);
117 if (count != -1)
118 lpmmioinfo->lDiskOffset += count;
119
120 return count;
121 }
122
123 case MMIOM_SEEK: {
124 /* Parameters:
125 * lParam1 = new position
126 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
127 * Returns: new file postion, -1 on error
128 * NOTE: lDiskOffset should be updated
129 */
130
131 LONG Offset = (LONG) lParam1;
132 LONG Whence = (LONG) lParam2;
133 LONG pos;
134
135 pos = _llseek((HFILE)lpmmioinfo->adwInfo[0], Offset, Whence);
136 if (pos != -1)
137 lpmmioinfo->lDiskOffset = pos;
138
139 return pos;
140 }
141
142 case MMIOM_RENAME: {
143 /* Parameters:
144 * lParam1 = old name
145 * lParam2 = new name
146 * Returns: zero on success, non-zero on failure
147 */
148
149 dprintf(("WINMM: mmioDosIOProc MMIOM_RENAME unimplemented\n"));
150 return MMIOERR_FILENOTFOUND;
151 }
152
153 default:
154 dprintf(("WINMM: mmioDosIOProc unexpected message %u\n", uMessage));
155 return 0;
156 }
157
158 return 0;
159}
160
161/**************************************************************************
162* mmioMemIOProc [internal]
163*/
164static LRESULT WIN32API mmioMemIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2) {
165// TRACE("(%p,0x%04x,0x%08lx,0x%08lx)\n",lpmmioinfo,uMessage,lParam1,lParam2);
166 switch (uMessage) {
167
168 case MMIOM_OPEN: {
169 /* Parameters:
170 * lParam1 = filename (must be NULL)
171 * lParam2 = reserved
172 * Returns: zero on success, error code on error
173 * NOTE: lDiskOffset automatically set to zero
174 */
175
176 if (!(lpmmioinfo->dwFlags & MMIO_CREATE))
177 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite;
178
179 return 0;
180 }
181
182 case MMIOM_CLOSE: {
183 /* Parameters:
184 * lParam1 = wFlags parameter from mmioClose
185 * lParam2 = unused
186 * Returns: zero on success, error code on error
187 */
188
189 return 0;
190
191 }
192
193 case MMIOM_READ: {
194 /* Parameters:
195 * lParam1 = huge pointer to read buffer
196 * lParam2 = number of bytes to read
197 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
198 * in wErrorRet)
199 * NOTE: lDiskOffset should be updated
200 */
201
202 /* HPSTR pch = (HPSTR) lParam1; */
203 /* LONG cch = (LONG) lParam2; */
204
205 dprintf(("WINMM (mmioMemIOProc) MMIOM_READ on memory files should not occur, buffer may be lost!\n"));
206 return 0;
207 }
208
209 case MMIOM_WRITE:
210 case MMIOM_WRITEFLUSH: {
211 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
212
213 /* Parameters:
214 * lParam1 = huge pointer to write buffer
215 * lParam2 = number of bytes to write
216 * Returns: number of bytes written, -1 for error (error code in
217 * wErrorRet)
218 * NOTE: lDiskOffset should be updated
219 */
220
221 /* HPSTR pch = (HPSTR) lParam1; */
222 /* LONG cch = (LONG) lParam2; */
223
224 dprintf(("WINMM (mmioMemIOProc) MMIOM_WRITE on memory files should not occur, buffer may be lost!\n"));
225 return 0;
226 }
227
228 case MMIOM_SEEK: {
229 /* Parameters:
230 * lParam1 = new position
231 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
232 * Returns: new file postion, -1 on error
233 * NOTE: lDiskOffset should be updated
234 */
235
236 /* LONG Offset = (LONG) lParam1; */
237 /* LONG Whence = (LONG) lParam2; */
238
239 dprintf(("WINMM (mmioMemIOProc) MMIOM_SEEK on memory files should not occur, buffer may be lost!\n"));
240 return -1;
241 }
242
243 default:
244 dprintf(("WINMM (mmioMemIOProc) unexpected message %u\n", uMessage));
245 return 0;
246 }
247
248 return 0;
249}
250
251/**************************************************************************
252 * MMIO_Open [internal]
253 */
254static HMMIO MMIO_Open(LPSTR szFileName, LPMMIOINFO refmminfo, DWORD dwOpenFlags)
255{
256 LPMMIOINFO lpmminfo;
257 HMMIO hmmio;
258
259// TRACE("('%s', %08lX);\n", szFileName, dwOpenFlags);
260
261 if (dwOpenFlags & MMIO_PARSE) {
262 char buffer[MAX_PATH];
263
264 if (GetFullPathNameA(szFileName, sizeof(buffer), buffer, NULL) >= sizeof(buffer))
265 return (HMMIO)FALSE;
266 strcpy(szFileName, buffer);
267 return (HMMIO)TRUE;
268 }
269
270 hmmio = GlobalAlloc(GHND, sizeof(MMIOINFO));
271 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
272 if (lpmminfo == NULL)
273 return 0;
274 memset(lpmminfo, 0, sizeof(MMIOINFO));
275
276 /* assume DOS file if not otherwise specified */
277 if (refmminfo->fccIOProc == 0 && refmminfo->pIOProc == NULL) {
278 lpmminfo->fccIOProc = FOURCC_DOS;
279 lpmminfo->pIOProc = (LPMMIOPROC) mmioDosIOProc;
280 }
281 /* if just the four character code is present, look up IO proc */
282 else if (refmminfo->pIOProc == NULL) {
283
284 lpmminfo->fccIOProc = refmminfo->fccIOProc;
285 lpmminfo->pIOProc = mmioInstallIOProcA(refmminfo->fccIOProc, NULL, MMIO_FINDPROC);
286
287 }
288 /* if IO proc specified, use it and specified four character code */
289 else {
290
291 lpmminfo->fccIOProc = refmminfo->fccIOProc;
292 lpmminfo->pIOProc = (LPMMIOPROC)refmminfo->pIOProc;
293 }
294
295 if (dwOpenFlags & MMIO_ALLOCBUF) {
296 if ((refmminfo->wErrorRet = mmioSetBuffer(hmmio, NULL, MMIO_DEFAULTBUFFER, 0))) {
297 return 0;
298 }
299 } else if (lpmminfo->fccIOProc == FOURCC_MEM) {
300 if ((refmminfo->wErrorRet = mmioSetBuffer(hmmio, refmminfo->pchBuffer, refmminfo->cchBuffer, 0))) {
301 return 0;
302 }
303 }
304
305 /* see mmioDosIOProc for that one */
306 lpmminfo->adwInfo[0] = refmminfo->adwInfo[0];
307 lpmminfo->dwFlags = dwOpenFlags;
308 lpmminfo->hmmio = hmmio;
309
310 /* call IO proc to actually open file */
311 refmminfo->wErrorRet = (UINT) mmioSendMessage(hmmio, MMIOM_OPEN, (LPARAM) szFileName, (LPARAM) 0);
312
313 GlobalUnlock(hmmio);
314
315 if (refmminfo->wErrorRet != 0) {
316 GlobalFree(hmmio);
317 return 0;
318 }
319
320 return hmmio;
321}
322
323/**************************************************************************
324 * mmioOpenW [WINMM.123]
325 */
326ODINFUNCTION3(HMMIO, mmioOpenW,
327 LPWSTR,szFileName,
328 LPMMIOINFO,lpmmioinfo,
329 DWORD,dwOpenFlags)
330{
331 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(),0,szFileName);
332 HMMIO ret = mmioOpenA(szFn, lpmmioinfo, dwOpenFlags);
333
334 HeapFree(GetProcessHeap(),0,szFn);
335 return ret;
336}
337
338/**************************************************************************
339 * mmioOpenA [WINMM.122]
340 */
341ODINFUNCTION3(HMMIO, mmioOpenA,
342 LPSTR,szFileName,
343 LPMMIOINFO,lpmmioinfo,
344 DWORD,dwOpenFlags)
345{
346 HMMIO ret;
347
348 if (lpmmioinfo) {
349 ret = MMIO_Open(szFileName, lpmmioinfo, dwOpenFlags);
350 } else {
351 MMIOINFO mmioinfo;
352
353 mmioinfo.fccIOProc = 0;
354 mmioinfo.pIOProc = NULL;
355 mmioinfo.pchBuffer = NULL;
356 mmioinfo.cchBuffer = 0;
357
358 ret = MMIO_Open(szFileName, &mmioinfo, dwOpenFlags);
359 }
360 return ret;
361}
362
363
364/**************************************************************************
365 * mmioClose [WINMM.114]
366 */
367ODINFUNCTION2(MMRESULT, mmioClose,
368 HMMIO,hmmio,
369 UINT,uFlags)
370{
371 LPMMIOINFO lpmminfo;
372 MMRESULT result;
373
374// TRACE("(%04X, %04X);\n", hmmio, uFlags);
375
376 lpmminfo = (LPMMIOINFO) GlobalLock(hmmio);
377 if (lpmminfo == NULL)
378 return 0;
379
380 /* flush the file - if error reported, ignore */
381 if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
382 lpmminfo->dwFlags &= ~MMIO_DIRTY;
383
384 result = mmioSendMessage(hmmio,MMIOM_CLOSE,(LPARAM)uFlags,(LPARAM)0);
385
386 mmioSetBuffer(hmmio, NULL, 0, 0);
387
388 GlobalUnlock(hmmio);
389 GlobalFree(hmmio);
390
391 return result;
392}
393
394
395
396/**************************************************************************
397 * mmioRead [WINMM.124]
398 */
399ODINFUNCTION3(LONG, mmioRead,
400 HMMIO,hmmio,
401 HPSTR,pch,
402 LONG,cch)
403{
404 LONG count;
405 LPMMIOINFO lpmminfo;
406
407// TRACE("(%04X, %p, %ld);\n", hmmio, pch, cch);
408
409 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
410 if (lpmminfo == NULL)
411 return -1;
412
413 if (lpmminfo->pchNext != lpmminfo->pchEndRead) {
414 count = lpmminfo->pchEndRead - lpmminfo->pchNext;
415 if (count > cch || count < 0) count = cch;
416 memcpy(pch, lpmminfo->pchNext, count);
417 lpmminfo->pchNext += count;
418 pch += count;
419 cch -= count;
420 } else
421 count = 0;
422
423 if (cch&&(lpmminfo->fccIOProc!=FOURCC_MEM)) {
424 if (lpmminfo->cchBuffer) {
425 mmioFlush(hmmio, MMIO_EMPTYBUF);
426
427 while (cch) {
428 LONG size;
429 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
430 lpmminfo->pchNext = lpmminfo->pchBuffer;
431 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
432 size = mmioSendMessage(hmmio, MMIOM_READ,
433 (LPARAM) lpmminfo->pchBuffer,
434 (LPARAM) lpmminfo->cchBuffer);
435 if (size<=0) break;
436 lpmminfo->pchEndRead = lpmminfo->pchBuffer + size;
437 if (size > cch) size = cch;
438 memcpy(pch, lpmminfo->pchNext, size);
439 lpmminfo->pchNext += size;
440 pch += size;
441 cch -= size;
442 count += size;
443 }
444 } else {
445 count += mmioSendMessage(hmmio, MMIOM_READ, (LPARAM) pch, (LPARAM) cch);
446 if (count>0) lpmminfo->lBufOffset += count;
447 }
448 }
449
450 GlobalUnlock(hmmio);
451 TRACE("count=%ld\n", count);
452 return count;
453}
454
455/**************************************************************************
456 * mmioWrite [WINMM.133]
457 */
458ODINFUNCTION3(LONG, mmioWrite,
459 HMMIO,hmmio,
460 HPCSTR,pch,
461 LONG,cch)
462{
463 LONG count;
464 LPMMIOINFO lpmminfo;
465
466// TRACE("(%04X, %p, %ld);\n", hmmio, pch, cch);
467
468 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
469 if (lpmminfo == NULL)
470 return -1;
471
472 if (lpmminfo->cchBuffer) {
473 count = 0;
474 while (cch) {
475 if (lpmminfo->pchNext != lpmminfo->pchEndWrite) {
476 count = lpmminfo->pchEndWrite - lpmminfo->pchNext;
477 if (count > cch || count < 0) count = cch;
478 memcpy(lpmminfo->pchNext, pch, count);
479 lpmminfo->pchNext += count;
480 pch += count;
481 cch -= count;
482 lpmminfo->dwFlags |= MMIO_DIRTY;
483 } else
484 if (lpmminfo->fccIOProc==FOURCC_MEM) {
485 if (lpmminfo->adwInfo[0]) {
486 /* from where would we get the memory handle? */
487 dprintf(("WINMM (mmioWrite) memory file expansion not implemented!\n"));
488 } else break;
489 }
490
491 if (lpmminfo->pchNext == lpmminfo->pchEndWrite
492 && mmioFlush(hmmio, MMIO_EMPTYBUF)) break;
493 }
494 } else {
495 count = mmioSendMessage(hmmio, MMIOM_WRITE, (LPARAM) pch, (LPARAM) cch);
496 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
497 }
498
499 GlobalUnlock(hmmio);
500// TRACE("count=%ld\n", count);
501 return count;
502}
503
504/**************************************************************************
505 * mmioSeek [MMSYSTEM.1214]
506 */
507ODINFUNCTION3(LONG, mmioSeek,
508 HMMIO, hmmio,
509 LONG,lOffset,
510 INT,iOrigin)
511{
512 int offset;
513 LPMMIOINFO lpmminfo;
514
515// TRACE("(%04X, %08lX, %d);\n", hmmio, lOffset, iOrigin);
516
517 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
518 if (lpmminfo == NULL)
519 return -1;
520
521 offset = (iOrigin==SEEK_SET)?(lOffset - lpmminfo->lBufOffset):
522 (iOrigin==SEEK_CUR)?(lOffset +
523 (lpmminfo->pchNext - lpmminfo->pchBuffer)):-1;
524
525 if ((lpmminfo->cchBuffer<0)||
526 ((offset>=0)&&(offset<=(lpmminfo->pchEndRead-lpmminfo->pchBuffer)))) {
527 lpmminfo->pchNext = lpmminfo->pchBuffer + offset;
528 GlobalUnlock(hmmio);
529 return lpmminfo->lBufOffset + offset;
530 }
531
532 if ((lpmminfo->fccIOProc==FOURCC_MEM)||mmioFlush(hmmio, MMIO_EMPTYBUF)) {
533 GlobalUnlock(hmmio);
534 return -1;
535 }
536
537 offset = mmioSendMessage(hmmio, MMIOM_SEEK, (LPARAM) lOffset, (LPARAM) iOrigin);
538 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
539
540 GlobalUnlock(hmmio);
541 return offset;
542}
543
544/**************************************************************************
545 * mmioGetInfo [MMSYSTEM.1215]
546 */
547ODINFUNCTION3(UINT, mmioGetInfo,
548 HMMIO,hmmio,
549 LPMMIOINFO,lpmmioinfo,
550 UINT,uFlags)
551{
552 LPMMIOINFO lpmminfo;
553// TRACE("mmioGetInfo\n");
554 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
555 if (lpmminfo == NULL) return 0;
556 memcpy(lpmmioinfo, lpmminfo, sizeof(MMIOINFO));
557 GlobalUnlock(hmmio);
558 return 0;
559}
560
561
562/**************************************************************************
563 * mmioSetInfo [WINMM.130]
564 */
565ODINFUNCTION3(MMRESULT,mmioSetInfo,
566 HMMIO, hmmio,
567 const MMIOINFO*,lpmmioinfo,
568 UINT,uFlags)
569{
570 LPMMIOINFO lpmminfo;
571// TRACE("mmioSetInfo\n");
572 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
573 if (lpmminfo == NULL) return 0;
574 lpmminfo->pchNext = lpmmioinfo->pchNext;
575 lpmminfo->pchEndRead = lpmmioinfo->pchEndRead;
576 GlobalUnlock(hmmio);
577 return 0;
578}
579
580/**************************************************************************
581* mmioSetBuffer [WINMM.129]
582*/
583ODINFUNCTION4(UINT,mmioSetBuffer,
584 HMMIO,hmmio,
585 LPSTR,pchBuffer,
586 LONG,cchBuffer,
587 UINT,uFlags)
588{
589 LPMMIOINFO lpmminfo;
590
591 if (mmioFlush(hmmio, MMIO_EMPTYBUF) != 0)
592 return MMIOERR_CANNOTWRITE;
593
594// TRACE("(hmmio=%04x, pchBuf=%p, cchBuf=%ld, uFlags=%#08x)\n",
595// hmmio, pchBuffer, cchBuffer, uFlags);
596
597 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
598 if (lpmminfo == NULL) return 0;
599 if ((!cchBuffer || pchBuffer) && lpmminfo->dwFlags&MMIO_ALLOCBUF) {
600 GlobalUnlock(lpmminfo->dwReserved1);
601 GlobalFree(lpmminfo->dwReserved1);
602 lpmminfo->dwFlags &= ~MMIO_ALLOCBUF;
603 }
604 if (pchBuffer) {
605 lpmminfo->pchBuffer = pchBuffer;
606 } else if (lpmminfo->dwFlags&MMIO_ALLOCBUF) {
607 HGLOBAL hNewBuf;
608 GlobalUnlock(lpmminfo->dwReserved1);
609 hNewBuf = GlobalReAlloc(lpmminfo->dwReserved1, cchBuffer, 0);
610 if (!hNewBuf) {
611 /* FIXME: this assumes the memory block didn't move */
612 GlobalLock(lpmminfo->dwReserved1);
613 GlobalUnlock(hmmio);
614 return MMIOERR_OUTOFMEMORY;
615 }
616 lpmminfo->dwReserved1 = hNewBuf;
617 lpmminfo->pchBuffer = (LPSTR)GlobalLock(hNewBuf);
618 } else if (cchBuffer) {
619 HGLOBAL hNewBuf = GlobalAlloc(GMEM_MOVEABLE, cchBuffer);
620 if (!hNewBuf) {
621 GlobalUnlock(hmmio);
622 return MMIOERR_OUTOFMEMORY;
623 }
624 lpmminfo->dwReserved1 = hNewBuf;
625 lpmminfo->pchBuffer = (LPSTR)GlobalLock(hNewBuf);
626 lpmminfo->dwFlags |= MMIO_ALLOCBUF;
627 } else
628 lpmminfo->pchBuffer = NULL;
629 lpmminfo->cchBuffer = cchBuffer;
630 lpmminfo->pchNext = lpmminfo->pchBuffer;
631 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
632 lpmminfo->pchEndWrite = lpmminfo->pchBuffer + cchBuffer;
633 lpmminfo->lBufOffset = 0;
634
635 GlobalUnlock(hmmio);
636 return 0;
637}
638
639/**************************************************************************
640 * mmioFlush [WINMM.117]
641 */
642ODINFUNCTION2(UINT,mmioFlush,
643 HMMIO,hmmio,
644 UINT,uFlags)
645{
646 LPMMIOINFO lpmminfo;
647// TRACE("(%04X, %04X)\n", hmmio, uFlags);
648 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
649 if (lpmminfo == NULL) return 0;
650
651 if ((!lpmminfo->cchBuffer)||(lpmminfo->fccIOProc==FOURCC_MEM)) {
652 GlobalUnlock(hmmio);
653 return 0;
654 }
655 /* not quite sure what to do here, but I'll guess */
656 if (lpmminfo->dwFlags & MMIO_DIRTY) {
657 mmioSendMessage(hmmio, MMIOM_SEEK,
658 (LPARAM) lpmminfo->lBufOffset,
659 (LPARAM) SEEK_SET);
660 mmioSendMessage(hmmio, MMIOM_WRITE,
661 (LPARAM) lpmminfo->pchBuffer,
662 (LPARAM) (lpmminfo->pchNext - lpmminfo->pchBuffer) );
663 lpmminfo->dwFlags &= ~MMIO_DIRTY;
664 }
665 if (uFlags & MMIO_EMPTYBUF) {
666 /* seems Windows doesn't do any seeking here, hopefully this
667 won't matter, otherwise a slight rewrite is necessary */
668 mmioSendMessage(hmmio, MMIOM_SEEK,
669 (LPARAM) (lpmminfo->lBufOffset +
670 (lpmminfo->pchNext - lpmminfo->pchBuffer)),
671 (LPARAM) SEEK_SET);
672 lpmminfo->pchNext = lpmminfo->pchBuffer;
673 lpmminfo->pchEndRead = lpmminfo->pchBuffer;
674 lpmminfo->lBufOffset = lpmminfo->lDiskOffset;
675 }
676
677 GlobalUnlock(hmmio);
678 return 0;
679}
680
681
682/**************************************************************************
683 * mmioAdvance [WINMM.113]
684 */
685ODINFUNCTION3(UINT,mmioAdvance,
686 HMMIO, hmmio,
687 LPMMIOINFO,lpmmioinfo,
688 UINT,uFlags)
689{
690 LPMMIOINFO lpmminfo;
691// TRACE("mmioAdvance\n");
692 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
693 if (lpmminfo == NULL) return 0;
694 if (!lpmminfo->cchBuffer) {
695 GlobalUnlock(hmmio);
696 return MMIOERR_UNBUFFERED;
697 }
698 lpmminfo->pchNext = lpmmioinfo->pchNext;
699 if (mmioFlush(hmmio, MMIO_EMPTYBUF)) {
700 GlobalUnlock(hmmio);
701 return MMIOERR_CANNOTWRITE;
702 }
703 if (uFlags == MMIO_READ)
704 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
705 mmioSendMessage(hmmio, MMIOM_READ,
706 (LPARAM) lpmmioinfo->pchBuffer,
707 (LPARAM) lpmmioinfo->cchBuffer);
708 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
709 GlobalUnlock(hmmio);
710 return 0;
711}
712
713
714/**************************************************************************
715 * mmioStringToFOURCCA [WINMM.131]
716 */
717ODINFUNCTION2(FOURCC,mmioStringToFOURCCA,
718 LPCSTR, sz, UINT, uFlags)
719{
720 return mmioFOURCC(sz[0],sz[1],sz[2],sz[3]);
721}
722
723/**************************************************************************
724 * mmioStringToFOURCCW [WINMM.132]
725 */
726ODINFUNCTION2(FOURCC,mmioStringToFOURCCW,
727 LPCWSTR, sz, UINT, uFlags)
728{
729 LPSTR szA = HEAP_strdupWtoA(GetProcessHeap(),0,sz);
730 FOURCC ret = mmioStringToFOURCCA(szA,uFlags);
731
732 HeapFree(GetProcessHeap(),0,szA);
733 return ret;
734}
735
736
737/* maximum number of I/O procedures which can be installed */
738
739struct IOProcList
740{
741 struct IOProcList *pNext; /* Next item in linked list */
742 FOURCC fourCC; /* four-character code identifying IOProc */
743 LPMMIOPROC pIOProc; /* pointer to IProc */
744};
745
746/* This array will be the entire list for most apps */
747
748static struct IOProcList defaultProcs[] = {
749 { &defaultProcs[1], (FOURCC) FOURCC_DOS,(LPMMIOPROC) mmioDosIOProc },
750 { NULL, (FOURCC) FOURCC_MEM,(LPMMIOPROC) mmioMemIOProc },
751};
752
753static struct IOProcList *pIOProcListAnchor = &defaultProcs[0];
754
755ODINFUNCTION3(LPMMIOPROC, mmioInstallIOProcA,
756 FOURCC,fccIOProc,
757 LPMMIOPROC,pIOProc,
758 DWORD,dwFlags)
759{
760 LPMMIOPROC lpProc = NULL;
761 struct IOProcList *pListNode;
762
763// TRACE("(%ld, %p, %08lX)\n",
764// fccIOProc, pIOProc, dwFlags);
765
766 if (dwFlags & MMIO_GLOBALPROC) {
767 dprintf(("WINMM: mmioInstallIOProcA global procedures not implemented\n"));
768 }
769
770 /* just handle the known procedures for now */
771 switch(dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) {
772 case MMIO_INSTALLPROC:
773 /* Create new entry for the IOProc list */
774 pListNode = (struct IOProcList *)HeapAlloc(GetProcessHeap(),0,sizeof(*pListNode));
775 if (pListNode)
776 {
777 /* Find the end of the list, so we can add our new entry to it */
778 struct IOProcList *pListEnd = pIOProcListAnchor;
779 while (pListEnd->pNext)
780 pListEnd = pListEnd->pNext;
781
782 /* Fill in this node */
783 pListNode->fourCC = fccIOProc;
784 pListNode->pIOProc = pIOProc;
785
786 /* Stick it on the end of the list */
787 pListEnd->pNext = pListNode;
788 pListNode->pNext = NULL;
789
790 /* Return this IOProc - that's how the caller knows we succeeded */
791 lpProc = pIOProc;
792 };
793 break;
794
795 case MMIO_REMOVEPROC:
796 /*
797 * Search for the node that we're trying to remove - note
798 * that this method won't find the first item on the list, but
799 * since the first two items on this list are ones we won't
800 * let the user delete anyway, that's okay
801 */
802
803 pListNode = pIOProcListAnchor;
804 while (pListNode && pListNode->pNext->fourCC != fccIOProc)
805 pListNode = pListNode->pNext;
806
807 /* If we found it, remove it, but only if it isn't builtin */
808 if (pListNode &&
809 ((pListNode >= defaultProcs) && (pListNode < defaultProcs + sizeof(defaultProcs))))
810 {
811 /* Okay, nuke it */
812 pListNode->pNext = pListNode->pNext->pNext;
813 HeapFree(GetProcessHeap(),0,pListNode);
814 };
815 break;
816
817 case MMIO_FINDPROC:
818 /* Iterate through the list looking for this proc identified by fourCC */
819 for (pListNode = pIOProcListAnchor; pListNode; pListNode=pListNode->pNext)
820 {
821 if (pListNode->fourCC == fccIOProc)
822 {
823 lpProc = pListNode->pIOProc;
824 break;
825 };
826 };
827 break;
828 }
829
830 return lpProc;
831}
832
833
834/**************************************************************************
835* mmioSendMessage [MMSYSTEM.1222]
836*/
837ODINFUNCTION4(LRESULT,mmioSendMessage,
838 HMMIO,hmmio,
839 UINT,uMessage,
840 LPARAM,lParam1,
841 LPARAM,lParam2)
842{
843 LPMMIOINFO lpmminfo;
844 LRESULT result;
845 const char *msg = NULL;
846
847#ifdef DEBUG
848 switch (uMessage) {
849#define msgname(x) case x: msg = #x; break;
850 msgname(MMIOM_OPEN);
851 msgname(MMIOM_CLOSE);
852 msgname(MMIOM_READ);
853 msgname(MMIOM_WRITE);
854 msgname(MMIOM_WRITEFLUSH);
855 msgname(MMIOM_SEEK);
856 msgname(MMIOM_RENAME);
857#undef msgname
858 }
859#endif
860
861 if (msg)
862 dprintf(("WINMM: mmioSendMessage (%04X, %s, %ld, %ld)\n",
863 hmmio, msg, lParam1, lParam2));
864 else
865 dprintf(("WINMM: mmioSendMessage (%04X, %u, %ld, %ld)\n",
866 hmmio, uMessage, lParam1, lParam2));
867
868 lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
869
870 if (lpmminfo && lpmminfo->pIOProc)
871 result = (*lpmminfo->pIOProc)((LPSTR)lpmminfo, (UINT)uMessage, lParam1, lParam2);
872 else
873 result = MMSYSERR_INVALPARAM;
874
875 GlobalUnlock(hmmio);
876
877 return result;
878}
879
880/**************************************************************************
881* mmioDescend [MMSYSTEM.1223]
882*/
883ODINFUNCTION4(UINT,mmioDescend,
884 HMMIO,hmmio,
885 LPMMCKINFO,lpck,
886 const MMCKINFO *,lpckParent,
887 UINT,uFlags)
888{
889 DWORD dwOldPos;
890 FOURCC srchCkId;
891 FOURCC srchType;
892
893
894// TRACE("(%04X, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags);
895
896 if (lpck == NULL)
897 return MMSYSERR_INVALPARAM;
898
899 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
900 dprintf(("WINMM: mmioDescend - dwOldPos=%ld\n", dwOldPos));
901
902 if (lpckParent != NULL) {
903 TRACE("seek inside parent at %ld !\n", lpckParent->dwDataOffset);
904 /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
905 if (dwOldPos < lpckParent->dwDataOffset || dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) {
906 dprintf(("WINMM: mmioDescend - outside parent chunk\n"));
907 return MMIOERR_CHUNKNOTFOUND;
908 }
909 }
910
911 /* The SDK docu says 'ckid' is used for all cases. Real World
912 * examples disagree -Marcus,990216.
913 */
914
915 srchType = 0;
916 /* find_chunk looks for 'ckid' */
917 if (uFlags & MMIO_FINDCHUNK)
918 srchCkId = lpck->ckid;
919 /* find_riff and find_list look for 'fccType' */
920 if (uFlags & MMIO_FINDLIST) {
921 srchCkId = FOURCC_LIST;
922 srchType = lpck->fccType;
923 }
924 if (uFlags & MMIO_FINDRIFF) {
925 srchCkId = FOURCC_RIFF;
926 srchType = lpck->fccType;
927 }
928 dprintf(("WINMM: mmioDescend - searching for %.4s.%.4s\n",
929 (LPSTR)&srchCkId,
930 srchType?(LPSTR)&srchType:"<any>"));
931
932 if (uFlags & (MMIO_FINDCHUNK|MMIO_FINDLIST|MMIO_FINDRIFF)) {
933 while (TRUE) {
934 LONG ix;
935
936 ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
937 if (ix < 2*sizeof(DWORD)) {
938 mmioSeek(hmmio, dwOldPos, SEEK_SET);
939 WARN("return ChunkNotFound\n");
940 return MMIOERR_CHUNKNOTFOUND;
941 }
942 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
943 if (ix < lpck->dwDataOffset - dwOldPos) {
944 mmioSeek(hmmio, dwOldPos, SEEK_SET);
945 WARN("return ChunkNotFound\n");
946 return MMIOERR_CHUNKNOTFOUND;
947 }
948 dprintf(("WINMM: mmioDescend - ckid=%.4ss fcc=%.4ss cksize=%08lX !\n",
949 (LPSTR)&lpck->ckid,
950 srchType?(LPSTR)&lpck->fccType:"<unused>",
951 lpck->cksize));
952 if ((srchCkId == lpck->ckid) &&
953 (!srchType || (srchType == lpck->fccType))
954 )
955 break;
956
957 dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1);
958 mmioSeek(hmmio, dwOldPos, SEEK_SET);
959 }
960 } else {
961 /* FIXME: unverified, does it do this? */
962 if (mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD)) < 3 * sizeof(DWORD)) {
963 mmioSeek(hmmio, dwOldPos, SEEK_SET);
964 dprintf(("WINMM: mmioDescend - return ChunkNotFound 2nd\n"));
965 return MMIOERR_CHUNKNOTFOUND;
966 }
967 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
968 }
969 lpck->dwFlags = 0;
970 /* If we were looking for RIFF/LIST chunks, the final file position
971 * is after the chunkid. If we were just looking for the chunk
972 * it is after the cksize. So add 4 in RIFF/LIST case.
973 */
974 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
975 mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET);
976 else
977 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
978 dprintf(("WINMM: mmioDescend - lpck: ckid=%.4s, cksize=%ld, dwDataOffset=%ld fccType=%08lX (%.4s)!\n",
979 (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset,
980 lpck->fccType, srchType?(LPSTR)&lpck->fccType:""));
981 return 0;
982}
983
984/**************************************************************************
985 * mmioAscend [WINMM.113]
986 */
987ODINFUNCTION3(UINT,mmioAscend,
988 HMMIO,hmmio,
989 LPMMCKINFO,lpck,
990 UINT,uFlags)
991{
992// TRACE("(%04X, %p, %04X);\n", hmmio, lpck, uFlags);
993
994 if (lpck->dwFlags & MMIO_DIRTY) {
995 DWORD dwOldPos, dwNewSize, dwSizePos;
996
997 dprintf(("WINMM: mmioAscend - chunk is marked MMIO_DIRTY, correcting chunk size\n"));
998 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
999 dprintf(("WINMM: mmioAscend - dwOldPos=%ld\n", dwOldPos));
1000 dwNewSize = dwOldPos - lpck->dwDataOffset;
1001 if (dwNewSize != lpck->cksize) {
1002 TRACE("dwNewSize=%ld\n", dwNewSize);
1003 lpck->cksize = dwNewSize;
1004
1005 dwSizePos = lpck->dwDataOffset - sizeof(DWORD);
1006 dprintf(("WINMM: mmioAscend - dwSizePos=%ld\n", dwSizePos));
1007
1008 mmioSeek(hmmio, dwSizePos, SEEK_SET);
1009 mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1010 }
1011 }
1012
1013 mmioSeek(hmmio, lpck->dwDataOffset + ((lpck->cksize + 1) & ~1), SEEK_SET);
1014
1015 return 0;
1016}
1017
1018/**************************************************************************
1019 * mmioCreateChunk [WINMM.115]
1020 */
1021ODINFUNCTION3(UINT,mmioCreateChunk,
1022 HMMIO,hmmio,
1023 LPMMCKINFO,lpck,
1024 UINT,uFlags)
1025{
1026 DWORD dwOldPos;
1027 LONG size;
1028 LONG ix;
1029
1030// TRACE("(%04X, %p, %04X);\n", hmmio, lpck, uFlags);
1031
1032 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1033 dprintf(("WINMM: mmioCreateChunk - dwOldPos=%ld\n", dwOldPos));
1034
1035 if (uFlags == MMIO_CREATELIST)
1036 lpck->ckid = FOURCC_LIST;
1037 else if (uFlags == MMIO_CREATERIFF)
1038 lpck->ckid = FOURCC_RIFF;
1039
1040 dprintf(("WINMM: mmioCreateChunk - ckid=%08lX\n", lpck->ckid));
1041
1042 size = 2 * sizeof(DWORD);
1043 lpck->dwDataOffset = dwOldPos + size;
1044
1045 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1046 size += sizeof(DWORD);
1047 lpck->dwFlags = MMIO_DIRTY;
1048
1049 ix = mmioWrite(hmmio, (LPSTR)lpck, size);
1050 TRACE("after mmioWrite ix = %ld req = %ld, errno = %d\n",ix, size, errno);
1051 if (ix < size) {
1052 mmioSeek(hmmio, dwOldPos, SEEK_SET);
1053 dprintf(("WINMM: mmioCreateChunk - return CannotWrite\n"));
1054 return MMIOERR_CANNOTWRITE;
1055 }
1056
1057 return 0;
1058}
1059
1060/**************************************************************************
1061 * mmioRenameA [WINMM.125]
1062 */
1063ODINFUNCTION4(UINT,mmioRenameA,
1064 LPCSTR,szFileName,
1065 LPCSTR,szNewFileName,
1066 LPMMIOINFO,lpmmioinfo,
1067 DWORD,dwRenameFlags)
1068{
1069 UINT result;
1070 LPMMIOINFO lpmminfo;
1071 HMMIO hmmio;
1072
1073// TRACE("('%s', '%s', %p, %08lX);\n",
1074// szFileName, szNewFileName, lpmmioinfo, dwRenameFlags);
1075 dprintf(("WINMM: This may fail - function untested\n"));
1076 hmmio = GlobalAlloc(GHND, sizeof(MMIOINFO));
1077 lpmminfo = (LPMMIOINFO) GlobalLock(hmmio);
1078
1079 if (lpmmioinfo)
1080 memcpy(lpmminfo, lpmmioinfo, sizeof(MMIOINFO));
1081
1082 /* assume DOS file if not otherwise specified */
1083 if (lpmminfo->fccIOProc == 0 && lpmminfo->pIOProc == NULL) {
1084
1085 lpmminfo->fccIOProc = mmioFOURCC('D', 'O', 'S', ' ');
1086 lpmminfo->pIOProc = (LPMMIOPROC) mmioDosIOProc;
1087
1088 }
1089 /* if just the four character code is present, look up IO proc */
1090 else if (lpmminfo->pIOProc == NULL) {
1091
1092 lpmminfo->pIOProc = mmioInstallIOProcA(lpmminfo->fccIOProc, NULL, MMIO_FINDPROC);
1093
1094 }
1095 /* (if IO proc specified, use it and specified four character code) */
1096
1097 result = (UINT) mmioSendMessage(hmmio, MMIOM_RENAME, (LPARAM) szFileName, (LPARAM) szNewFileName);
1098
1099 GlobalUnlock(hmmio);
1100 GlobalFree(hmmio);
1101
1102 return result;
1103}
1104
1105
1106/**************************************************************************
1107 * mmioRenameW [WINMM.126]
1108 */
1109ODINFUNCTION4(UINT,mmioRenameW,
1110 LPCWSTR,szFileName,
1111 LPCWSTR,szNewFileName,
1112 LPMMIOINFO,lpmmioinfo,
1113 DWORD,dwRenameFlags)
1114{
1115 LPSTR szFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szFileName);
1116 LPSTR sznFn = HEAP_strdupWtoA(GetProcessHeap(), 0, szNewFileName);
1117 UINT ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwRenameFlags);
1118
1119 HeapFree(GetProcessHeap(),0,szFn);
1120 HeapFree(GetProcessHeap(),0,sznFn);
1121 return ret;
1122}
1123
1124ODINFUNCTION3(LPMMIOPROC, mmioInstallIOProcW,
1125 FOURCC, fccIOProc,
1126 LPMMIOPROC, pIOProc,
1127 DWORD, dwFlags)
1128{
1129 // TODO: What is difference in mmioInstallIOProcW and mmioInstallIOProcA?
1130 dprintf(("WINMM:mmioInstallIOProcW - stub\n"));
1131 return 0;
1132}
Note: See TracBrowser for help on using the repository browser.