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

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

PD: Ported MMIO from Wine (v991031)

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