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

Last change on this file since 5120 was 3932, checked in by bird, 25 years ago

Added the CVS Keyword Id.

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