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

Last change on this file since 10367 was 8470, checked in by sandervl, 23 years ago

added debug wrappers (.def)

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