ReactOS 0.4.15-dev-7788-g1ad9096
mmio.c
Go to the documentation of this file.
1/*
2 * MMIO functions
3 *
4 * Copyright 1998 Andrew Taylor
5 * Copyright 1998 Ove Kåven
6 * Copyright 2000,2002 Eric Pouech
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23/* Still to be done:
24 * + correct handling of global/local IOProcs (and temporary IOProcs)
25 * + mode of mmio objects is not used (read vs write vs readwrite)
26 * + thread safeness
27 * + 32 A <=> W message mapping
28 */
29
30#include "winemm.h"
31
33
35
36/**************************************************************************
37 * mmioDosIOProc [internal]
38 */
39static LRESULT CALLBACK mmioDosIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage,
40 LPARAM lParam1, LPARAM lParam2)
41{
43
44 TRACE("(%p, %X, 0x%lx, 0x%lx);\n", lpmmioinfo, uMessage, lParam1, lParam2);
45
46 switch (uMessage) {
47 case MMIOM_OPEN:
48 {
49 /* Parameters:
50 * lParam1 = szFileName parameter from mmioOpen
51 * lParam2 = reserved
52 * Returns: zero on success, error code on error
53 * NOTE: lDiskOffset automatically set to zero
54 */
55 LPCSTR szFileName = (LPCSTR)lParam1;
56
57 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) {
58 FIXME("MMIO_GETTEMP not implemented\n");
59 return MMIOERR_CANNOTOPEN;
60 }
61
62 /* if filename NULL, assume open file handle in adwInfo[0] */
63 if (szFileName) {
64 OFSTRUCT ofs;
65 lpmmioinfo->adwInfo[0] = (DWORD)OpenFile(szFileName, &ofs, lpmmioinfo->dwFlags & 0xFFFF);
66 }
67 if (lpmmioinfo->adwInfo[0] == (DWORD)HFILE_ERROR)
69 }
70 break;
71
72 case MMIOM_CLOSE:
73 /* Parameters:
74 * lParam1 = wFlags parameter from mmioClose
75 * lParam2 = unused
76 * Returns: zero on success, error code on error
77 */
78 if (!(lParam1 & MMIO_FHOPEN))
79 _lclose((HFILE)lpmmioinfo->adwInfo[0]);
80 break;
81
82 case MMIOM_READ:
83 /* Parameters:
84 * lParam1 = huge pointer to read buffer
85 * lParam2 = number of bytes to read
86 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
87 * in wErrorRet)
88 */
89 ret = _lread((HFILE)lpmmioinfo->adwInfo[0], (HPSTR)lParam1, (LONG)lParam2);
90 if (ret != -1)
91 lpmmioinfo->lDiskOffset += ret;
92
93 break;
94
95 case MMIOM_WRITE:
97 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
98
99 /* Parameters:
100 * lParam1 = huge pointer to write buffer
101 * lParam2 = number of bytes to write
102 * Returns: number of bytes written, -1 for error (error code in
103 * wErrorRet)
104 */
105 ret = _hwrite((HFILE)lpmmioinfo->adwInfo[0], (HPSTR)lParam1, (LONG)lParam2);
106 if (ret != -1)
107 lpmmioinfo->lDiskOffset += ret;
108 break;
109
110 case MMIOM_SEEK:
111 /* Parameters:
112 * lParam1 = new position
113 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
114 * Returns: new file postion, -1 on error
115 */
116 ret = _llseek((HFILE)lpmmioinfo->adwInfo[0], (LONG)lParam1, (LONG)lParam2);
117 if (ret != -1)
118 lpmmioinfo->lDiskOffset = ret;
119 return ret;
120
121 case MMIOM_RENAME:
122 /* Parameters:
123 * lParam1 = old name
124 * lParam2 = new name
125 * Returns: zero on success, non-zero on failure
126 */
127 if (!MoveFileA((const char*)lParam1, (const char*)lParam2))
129 break;
130
131 default:
132 FIXME("unexpected message %u\n", uMessage);
133 return 0;
134 }
135
136 return ret;
137}
138
139/**************************************************************************
140 * mmioMemIOProc [internal]
141 */
142static LRESULT CALLBACK mmioMemIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage,
143 LPARAM lParam1, LPARAM lParam2)
144{
145 TRACE("(%p,0x%04x,0x%08lx,0x%08lx)\n", lpmmioinfo, uMessage, lParam1, lParam2);
146
147 switch (uMessage) {
148
149 case MMIOM_OPEN:
150 /* Parameters:
151 * lParam1 = filename (must be NULL)
152 * lParam2 = reserved
153 * Returns: zero on success, error code on error
154 * NOTE: lDiskOffset automatically set to zero
155 */
156 /* FIXME: io proc shouldn't change it */
157 if (!(lpmmioinfo->dwFlags & MMIO_CREATE))
158 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite;
159 lpmmioinfo->adwInfo[0] = HFILE_ERROR;
160 return 0;
161
162 case MMIOM_CLOSE:
163 /* Parameters:
164 * lParam1 = wFlags parameter from mmioClose
165 * lParam2 = unused
166 * Returns: zero on success, error code on error
167 */
168 return 0;
169
170 case MMIOM_READ:
171 /* Parameters:
172 * lParam1 = huge pointer to read buffer
173 * lParam2 = number of bytes to read
174 * Returns: number of bytes read, 0 for EOF, -1 for error (error code
175 * in wErrorRet)
176 * NOTE: lDiskOffset should be updated
177 */
178 FIXME("MMIOM_READ on memory files should not occur, buffer may be lost!\n");
179 return 0;
180
181 case MMIOM_WRITE:
182 case MMIOM_WRITEFLUSH:
183 /* no internal buffering, so WRITEFLUSH handled same as WRITE */
184
185 /* Parameters:
186 * lParam1 = huge pointer to write buffer
187 * lParam2 = number of bytes to write
188 * Returns: number of bytes written, -1 for error (error code in
189 * wErrorRet)
190 * NOTE: lDiskOffset should be updated
191 */
192 FIXME("MMIOM_WRITE on memory files should not occur, buffer may be lost!\n");
193 return 0;
194
195 case MMIOM_SEEK:
196 /* Parameters:
197 * lParam1 = new position
198 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END)
199 * Returns: new file postion, -1 on error
200 * NOTE: lDiskOffset should be updated
201 */
202 FIXME("MMIOM_SEEK on memory files should not occur, buffer may be lost!\n");
203 return -1;
204
205 default:
206 FIXME("unexpected message %u\n", uMessage);
207 return 0;
208 }
209}
210
211/* This array will be the entire list for most apps
212 * Note that temporary ioProcs will be stored with a 0 fourCC code
213 */
214
215static struct IOProcList defaultProcs[] = {
218};
219
221
222/****************************************************************
223 * MMIO_FindProcNode [INTERNAL]
224 *
225 * Finds the ProcList node associated with a given FOURCC code.
226 */
227static struct IOProcList* MMIO_FindProcNode(FOURCC fccIOProc)
228{
229 struct IOProcList* pListNode;
230
231 for (pListNode = pIOProcListAnchor; pListNode; pListNode = pListNode->pNext) {
232 if (pListNode->fourCC == fccIOProc) {
233 return pListNode;
234 }
235 }
236 return NULL;
237}
238
239/****************************************************************
240 * MMIO_InstallIOProc [INTERNAL]
241 */
244{
245 LPMMIOPROC lpProc = NULL;
246 struct IOProcList* pListNode;
247 struct IOProcList** ppListNode;
248
249 TRACE("(%08x, %p, %08X, %s)\n", fccIOProc, pIOProc, dwFlags, is_unicode ? "unicode" : "ansi");
250
252 FIXME("Global procedures not implemented\n");
253
254 /* just handle the known procedures for now */
256 case MMIO_INSTALLPROC:
257 /* Create new entry for the IOProc list */
258 pListNode = HeapAlloc(GetProcessHeap(), 0, sizeof(*pListNode));
259 if (pListNode) {
260 /* Fill in this node */
261 pListNode->fourCC = fccIOProc;
262 pListNode->pIOProc = pIOProc;
263 pListNode->is_unicode = is_unicode;
264 pListNode->count = 0;
265
266 /* Stick it on the end of the list */
267 pListNode->pNext = pIOProcListAnchor;
268 pIOProcListAnchor = pListNode;
269
270 /* Return this IOProc - that's how the caller knows we succeeded */
271 lpProc = pIOProc;
272 }
273 break;
274
275 case MMIO_REMOVEPROC:
276 /*
277 * Search for the node that we're trying to remove
278 * We search for a matching fourCC code if it's non null, or the proc
279 * address otherwise
280 * note that this method won't find the first item on the list, but
281 * since the first two items on this list are ones we won't
282 * let the user delete anyway, that's okay
283 */
284 ppListNode = &pIOProcListAnchor;
285 while ((*ppListNode) &&
286 ((fccIOProc != 0) ?
287 (*ppListNode)->fourCC != fccIOProc :
288 (*ppListNode)->pIOProc != pIOProc))
289 ppListNode = &((*ppListNode)->pNext);
290
291 if (*ppListNode) { /* found it */
292 /* FIXME: what should be done if an open mmio object uses this proc ?
293 * shall we return an error, nuke the mmio object ?
294 */
295 if ((*ppListNode)->count) {
296 ERR("Cannot remove a mmIOProc while in use\n");
297 break;
298 }
299 /* remove it, but only if it isn't builtin */
300 if ((*ppListNode) >= defaultProcs &&
301 (*ppListNode) < defaultProcs + sizeof(defaultProcs) / sizeof(defaultProcs[0])) {
302 WARN("Tried to remove built-in mmio proc. Skipping\n");
303 } else {
304 /* Okay, nuke it */
305 struct IOProcList* ptmpNode = *ppListNode;
306 lpProc = (*ppListNode)->pIOProc;
307 *ppListNode = (*ppListNode)->pNext;
308 HeapFree(GetProcessHeap(), 0, ptmpNode);
309 }
310 }
311 break;
312
313 case MMIO_FINDPROC:
314 if ((pListNode = MMIO_FindProcNode(fccIOProc))) {
315 lpProc = pListNode->pIOProc;
316 }
317 break;
318 }
319
320 return lpProc;
321}
322
323/****************************************************************
324 * send_message [INTERNAL]
325 */
326static LRESULT send_message(struct IOProcList* ioProc, LPMMIOINFO mmioinfo,
327 DWORD wMsg, LPARAM lParam1,
328 LPARAM lParam2, BOOL is_unicode)
329{
331 LPARAM lp1 = lParam1, lp2 = lParam2;
332
333 if (!ioProc) {
334 ERR("ioProc NULL\n");
335 return MMSYSERR_INVALPARAM;
336 }
337
338 if (ioProc->is_unicode != is_unicode) {
339 /* map (lParam1, lParam2) into (lp1, lp2) 32 A<=>W */
340 FIXME("NIY 32 A<=>W mapping\n");
341 }
342 result = (ioProc->pIOProc)((LPSTR)mmioinfo, wMsg, lp1, lp2);
343
344#if 0
345 if (ioProc->is_unicode != is_unicode) {
346 /* unmap (lParam1, lParam2) into (lp1, lp2) 32 A<=>W */
347 }
348#endif
349
350 return result;
351}
352
353/**************************************************************************
354 * MMIO_ParseExtA [internal]
355 *
356 * Parses a filename for the extension.
357 *
358 * RETURNS
359 * The FOURCC code for the extension if found, else 0.
360 */
361static FOURCC MMIO_ParseExtA(LPCSTR szFileName)
362{
363 /* Filenames are of the form file.ext{+ABC}
364 For now, we take the last '+' if present */
365
366 FOURCC ret = 0;
367
368 /* Note that ext{Start,End} point to the . and + respectively */
369 LPCSTR extEnd;
370 LPCSTR extStart;
371
372 CHAR ext[5];
373
374 TRACE("(%s)\n", debugstr_a(szFileName));
375
376 if (!szFileName)
377 return ret;
378
379 /* Find the last '+' */
380 extEnd = strrchr(szFileName,'+');
381
382 if (!extEnd) {
383 /* No + so just an extension */
384 return ret;
385 } else {
386 /* Find the first '.' before '+' */
387 extStart = extEnd - 1;
388 while (extStart >= szFileName && *extStart != '.') {
389 extStart--;
390 }
391 if (extStart < szFileName) {
392 ERR("No extension in szFileName: %s\n", debugstr_a(szFileName));
393 return ret;
394 }
395 }
396
397 if (extEnd - extStart - 1 > 4)
398 WARN("Extension length > 4\n");
399 lstrcpynA(ext, extStart + 1, min(extEnd-extStart,5));
400
401 TRACE("Got extension: %s\n", debugstr_a(ext));
402
403 /* FOURCC codes identifying file-extensions must be uppercase */
405
406 return ret;
407}
408
409/**************************************************************************
410 * MMIO_Get [internal]
411 *
412 * Retrieves the mmio object from current process
413 */
414static LPWINE_MMIO MMIO_Get(HMMIO h)
415{
416 LPWINE_MMIO wm = NULL;
417
419 for (wm = MMIOList; wm; wm = wm->lpNext) {
420 if (wm->info.hmmio == h)
421 break;
422 }
424 return wm;
425}
426
427/**************************************************************************
428 * MMIO_Create [internal]
429 *
430 * Creates an internal representation for a mmio instance
431 */
433{
434 static WORD MMIO_counter = 0;
435 LPWINE_MMIO wm;
436
438 if (wm) {
440 /* lookup next unallocated WORD handle, with a non NULL value */
441 while (++MMIO_counter == 0 || MMIO_Get((HMMIO)(ULONG_PTR)MMIO_counter));
442 wm->info.hmmio = (HMMIO)(ULONG_PTR)MMIO_counter;
443 wm->lpNext = MMIOList;
444 MMIOList = wm;
446 }
447 return wm;
448}
449
450/**************************************************************************
451 * MMIO_Destroy [internal]
452 *-
453 * Destroys an internal representation for a mmio instance
454 */
456{
457 LPWINE_MMIO* m;
458
460 /* search for the matching one... */
461 m = &MMIOList;
462 while (*m && *m != wm) m = &(*m)->lpNext;
463 /* ...and destroy */
464 if (*m) {
465 *m = (*m)->lpNext;
466 HeapFree(GetProcessHeap(), 0, wm);
467 wm = NULL;
468 }
470 return wm ? FALSE : TRUE;
471}
472
473/****************************************************************
474 * MMIO_Flush [INTERNAL]
475 */
477{
478 if (wm->info.cchBuffer && (wm->info.fccIOProc != FOURCC_MEM)) {
479 /* not quite sure what to do here, but I'll guess */
480 if (wm->info.dwFlags & MMIO_DIRTY) {
481 /* FIXME: error handling */
484 (LPARAM)wm->info.pchBuffer,
485 wm->info.pchNext - wm->info.pchBuffer, FALSE);
486 }
487 if (uFlags & MMIO_EMPTYBUF)
488 wm->info.pchNext = wm->info.pchEndRead = wm->info.pchBuffer;
489 }
490 wm->info.dwFlags &= ~MMIO_DIRTY;
491
492 return MMSYSERR_NOERROR;
493}
494
495/***************************************************************************
496 * MMIO_GrabNextBuffer [INTERNAL]
497 */
498static LONG MMIO_GrabNextBuffer(LPWINE_MMIO wm, int for_read)
499{
500 LONG size = wm->info.cchBuffer;
501
502 TRACE("bo=%x do=%x of=%lx\n",
505
507 wm->info.pchNext = wm->info.pchBuffer;
508 wm->info.pchEndRead = wm->info.pchBuffer;
510
511 wm->bBufferLoaded = TRUE;
512 if (for_read) {
515 if (size > 0)
516 wm->info.pchEndRead += size;
517 else
518 wm->bBufferLoaded = FALSE;
519 }
520
521 return size;
522}
523
524/***************************************************************************
525 * MMIO_SetBuffer [INTERNAL]
526 */
527static MMRESULT MMIO_SetBuffer(WINE_MMIO* wm, void* pchBuffer, LONG cchBuffer,
528 UINT uFlags)
529{
530 TRACE("(%p %p %d %u)\n", wm, pchBuffer, cchBuffer, uFlags);
531
532 if (cchBuffer > 0xFFFF)
533 WARN("Untested handling of huge mmio buffers (%d >= 64k)\n", cchBuffer);
534
535 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
536 return MMIOERR_CANNOTWRITE;
537
538 /* free previous buffer if allocated */
539 if (wm->info.dwFlags & MMIO_ALLOCBUF) {
541 wm->info.pchBuffer = NULL;
542 wm->info.dwFlags &= ~MMIO_ALLOCBUF;
543 }
544
545 if (pchBuffer) {
546 wm->info.pchBuffer = pchBuffer;
547 } else if (cchBuffer) {
548 if (!(wm->info.pchBuffer = HeapAlloc(GetProcessHeap(), 0, cchBuffer)))
549 return MMIOERR_OUTOFMEMORY;
551 } else {
552 wm->info.pchBuffer = NULL;
553 }
554
556 wm->info.pchNext = wm->info.pchBuffer;
557 wm->info.pchEndRead = wm->info.pchBuffer;
560 wm->bBufferLoaded = FALSE;
561
562 return MMSYSERR_NOERROR;
563}
564
565/**************************************************************************
566 * MMIO_Open [internal]
567 */
568static HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO* refmminfo, DWORD dwOpenFlags, BOOL is_unicode)
569{
570 LPWINE_MMIO wm;
571 MMIOINFO mmioinfo;
572
573 TRACE("('%s', %p, %08X, %s);\n", szFileName, refmminfo, dwOpenFlags, is_unicode ? "unicode" : "ansi");
574
575 if (!refmminfo) {
576 refmminfo = &mmioinfo;
577
578 mmioinfo.fccIOProc = 0;
579 mmioinfo.pIOProc = NULL;
580 mmioinfo.pchBuffer = NULL;
581 mmioinfo.cchBuffer = 0;
583 }
584
585 if (dwOpenFlags & (MMIO_PARSE|MMIO_EXIST)) {
586 char buffer[MAX_PATH];
587
588 if (!szFileName)
589 return (HMMIO)FALSE;
590 if (GetFullPathNameA(szFileName, sizeof(buffer), buffer, NULL) >= sizeof(buffer))
591 return (HMMIO)FALSE;
592 if ((dwOpenFlags & MMIO_EXIST) && (GetFileAttributesA(buffer) == INVALID_FILE_ATTRIBUTES))
593 return (HMMIO)FALSE;
594 strcpy(szFileName, buffer);
595 return (HMMIO)TRUE;
596 }
597
598 if ((wm = MMIO_Create()) == NULL)
599 return 0;
600
601 /* If both params are NULL, then parse the file name if available */
602 if (refmminfo->fccIOProc == 0 && refmminfo->pIOProc == NULL) {
603 wm->info.fccIOProc = MMIO_ParseExtA(szFileName);
604 /* Handle any unhandled/error case. Assume DOS file */
605 if (wm->info.fccIOProc == 0)
607 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) {
608 /* If not found, retry with FOURCC_DOS */
610 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc)))
611 goto error2;
612 }
613 wm->bTmpIOProc = FALSE;
614 }
615 /* if just the four character code is present, look up IO proc */
616 else if (refmminfo->pIOProc == NULL) {
617 wm->info.fccIOProc = refmminfo->fccIOProc;
618 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2;
619 wm->bTmpIOProc = FALSE;
620 }
621 /* if IO proc specified, use it and specified four character code */
622 else {
623 wm->info.fccIOProc = refmminfo->fccIOProc;
626 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2;
627 assert(wm->ioProc->pIOProc == refmminfo->pIOProc);
628 wm->bTmpIOProc = TRUE;
629 }
630
631 wm->ioProc->count++;
632 wm->info.dwFlags = dwOpenFlags;
633
634 if (dwOpenFlags & MMIO_ALLOCBUF) {
635 refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer,
636 refmminfo->cchBuffer ? refmminfo->cchBuffer : MMIO_DEFAULTBUFFER, 0);
637 if (refmminfo->wErrorRet != MMSYSERR_NOERROR)
638 goto error1;
639 } else {
640 refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer, refmminfo->cchBuffer, 0);
641 if (refmminfo->wErrorRet != MMSYSERR_NOERROR)
642 goto error1;
643 }
644
645 if (wm->info.fccIOProc == FOURCC_MEM && !(wm->info.dwFlags & MMIO_ALLOCBUF))
646 wm->bBufferLoaded = TRUE;
647
648 /* see mmioDosIOProc for that one */
649 wm->info.adwInfo[0] = refmminfo->adwInfo[0];
650
651 /* call IO proc to actually open file */
652 refmminfo->wErrorRet = send_message(wm->ioProc, &wm->info, MMIOM_OPEN,
653 (LPARAM)szFileName, 0, FALSE);
654
655 /* grab file size, when possible (FIXME: not 64 bit safe) */
657
658 if (refmminfo->wErrorRet == 0)
659 return wm->info.hmmio;
660 error1:
661 if (wm->ioProc) wm->ioProc->count--;
662 error2:
663 MMIO_Destroy(wm);
664 return 0;
665}
666
667/**************************************************************************
668 * mmioOpenW [WINMM.@]
669 */
670HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO* lpmmioinfo,
671 DWORD dwOpenFlags)
672{
673 HMMIO ret;
674 LPSTR szFn = NULL;
675
676 if (szFileName)
677 {
678 INT len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
679 szFn = HeapAlloc( GetProcessHeap(), 0, len );
680 if (!szFn) return NULL;
681 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
682 }
683
684 ret = MMIO_Open(szFn, lpmmioinfo, dwOpenFlags, TRUE);
685
686 HeapFree(GetProcessHeap(), 0, szFn);
687 return ret;
688}
689
690/**************************************************************************
691 * mmioOpenA [WINMM.@]
692 */
693HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO* lpmmioinfo,
694 DWORD dwOpenFlags)
695{
696 return MMIO_Open(szFileName, lpmmioinfo, dwOpenFlags, FALSE);
697}
698
699/**************************************************************************
700 * mmioClose [WINMM.@]
701 */
703{
704 LPWINE_MMIO wm;
706
707 TRACE("(%p, %04X);\n", hmmio, uFlags);
708
709 if ((wm = MMIO_Get(hmmio)) == NULL)
711
712 if ((result = MMIO_Flush(wm, 0)) != MMSYSERR_NOERROR)
713 return result;
714
716
717 MMIO_SetBuffer(wm, NULL, 0, 0);
718
719 wm->ioProc->count--;
720
721 if (wm->bTmpIOProc)
722 MMIO_InstallIOProc(wm->info.fccIOProc, wm->ioProc->pIOProc,
723 MMIO_REMOVEPROC, wm->ioProc->is_unicode);
724
725 MMIO_Destroy(wm);
726
727 return result;
728}
729
730/**************************************************************************
731 * mmioRead [WINMM.@]
732 */
734{
735 LPWINE_MMIO wm;
736 LONG count;
737
738 TRACE("(%p, %p, %d);\n", hmmio, pch, cch);
739
740 if ((wm = MMIO_Get(hmmio)) == NULL)
741 return -1;
742
743 /* unbuffered case first */
744 if (!wm->info.pchBuffer)
745 return send_message(wm->ioProc, &wm->info, MMIOM_READ, (LPARAM)pch, cch, FALSE);
746
747 /* first try from current buffer */
748 if (wm->info.pchNext != wm->info.pchEndRead) {
749 count = wm->info.pchEndRead - wm->info.pchNext;
750 if (count > cch || count < 0) count = cch;
751 memcpy(pch, wm->info.pchNext, count);
752 wm->info.pchNext += count;
753 pch += count;
754 cch -= count;
755 } else
756 count = 0;
757
758 if (cch && (wm->info.fccIOProc != FOURCC_MEM)) {
759 assert(wm->info.cchBuffer);
760
761 while (cch) {
762 LONG size;
763
765 if (size <= 0) break;
766 if (size > cch) size = cch;
768 wm->info.pchNext += size;
769 pch += size;
770 cch -= size;
771 count += size;
772 }
773 }
774
775 TRACE("count=%d\n", count);
776 return count;
777}
778
779/**************************************************************************
780 * mmioWrite [WINMM.@]
781 */
782LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
783{
784 LPWINE_MMIO wm;
785 LONG count;
786
787 TRACE("(%p, %p, %d);\n", hmmio, pch, cch);
788
789 if ((wm = MMIO_Get(hmmio)) == NULL)
790 return -1;
791
792 if (wm->info.cchBuffer) {
793 LONG bytesW = 0;
794
795 count = 0;
796 while (cch) {
797 if (wm->info.pchNext != wm->info.pchEndWrite) {
798 count = wm->info.pchEndWrite - wm->info.pchNext;
799 if (count > cch || count < 0) count = cch;
800 memcpy(wm->info.pchNext, pch, count);
801 wm->info.pchNext += count;
802 pch += count;
803 cch -= count;
804 bytesW += count;
805 wm->info.dwFlags |= MMIO_DIRTY;
806 } else {
807 if (wm->info.fccIOProc == FOURCC_MEM) {
808 if (wm->info.adwInfo[0]) {
809 /* from where would we get the memory handle? */
810 FIXME("memory file expansion not implemented!\n");
811 break;
812 } else break;
813 }
814 }
815
816 if (wm->info.pchNext == wm->info.pchEndWrite)
817 {
820 }
821 else break;
822 }
823 count = bytesW;
824 } else {
827 }
828
829 TRACE("bytes written=%d\n", count);
830 return count;
831}
832
833/**************************************************************************
834 * mmioSeek [WINMM.@]
835 */
836LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
837{
838 LPWINE_MMIO wm;
839 LONG offset;
840
841 TRACE("(%p, %08X, %d);\n", hmmio, lOffset, iOrigin);
842
843 if ((wm = MMIO_Get(hmmio)) == NULL)
845
846 /* not buffered, direct seek on file */
847 if (!wm->info.pchBuffer)
848 return send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lOffset, iOrigin, FALSE);
849
850 switch (iOrigin) {
851 case SEEK_SET:
852 offset = lOffset;
853 break;
854 case SEEK_CUR:
855 offset = wm->info.lBufOffset + (wm->info.pchNext - wm->info.pchBuffer) + lOffset;
856 break;
857 case SEEK_END:
858 offset = ((wm->info.fccIOProc == FOURCC_MEM)? wm->info.cchBuffer : wm->dwFileSize) - lOffset;
859 break;
860 default:
861 return -1;
862 }
863
864 if (offset && offset >= wm->dwFileSize && wm->info.fccIOProc != FOURCC_MEM) {
865 /* should check that write mode exists */
866 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
867 return -1;
868 wm->info.lBufOffset = offset;
869 wm->info.pchEndRead = wm->info.pchBuffer;
871 if ((wm->info.dwFlags & MMIO_RWMODE) == MMIO_READ) {
872 wm->info.lDiskOffset = wm->dwFileSize;
873 }
874 } else if ((wm->info.cchBuffer > 0) &&
875 ((offset < wm->info.lBufOffset) ||
876 (offset >= wm->info.lBufOffset + wm->info.cchBuffer) ||
877 !wm->bBufferLoaded)) {
878 /* stay in same buffer ? */
879 /* some memory mapped buffers are defined with -1 as a size */
880
881 /* condition to change buffer */
882 if ((wm->info.fccIOProc == FOURCC_MEM) ||
883 MMIO_Flush(wm, 0) != MMSYSERR_NOERROR ||
884 /* this also sets the wm->info.lDiskOffset field */
886 (offset / wm->info.cchBuffer) * wm->info.cchBuffer,
887 SEEK_SET, FALSE) == -1)
888 return -1;
890 }
891
892 wm->info.pchNext = wm->info.pchBuffer + (offset - wm->info.lBufOffset);
893
894 TRACE("=> %d\n", offset);
895 return offset;
896}
897
898/**************************************************************************
899 * mmioGetInfo [WINMM.@]
900 */
901MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
902{
903 LPWINE_MMIO wm;
904
905 TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
906
907 if ((wm = MMIO_Get(hmmio)) == NULL)
909
910 *lpmmioinfo = wm->info;
911
912 return MMSYSERR_NOERROR;
913}
914
915/**************************************************************************
916 * mmioSetInfo [WINMM.@]
917 */
918MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO* lpmmioinfo, UINT uFlags)
919{
920 LPWINE_MMIO wm;
921
922 TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
923
924 if ((wm = MMIO_Get(hmmio)) == NULL)
926
927 /* check pointers coherence */
928 if (lpmmioinfo->pchNext < wm->info.pchBuffer ||
929 lpmmioinfo->pchNext > wm->info.pchBuffer + wm->info.cchBuffer ||
930 lpmmioinfo->pchEndRead < wm->info.pchBuffer ||
931 lpmmioinfo->pchEndRead > wm->info.pchBuffer + wm->info.cchBuffer ||
932 lpmmioinfo->pchEndWrite < wm->info.pchBuffer ||
933 lpmmioinfo->pchEndWrite > wm->info.pchBuffer + wm->info.cchBuffer)
934 return MMSYSERR_INVALPARAM;
935
936 wm->info.pchNext = lpmmioinfo->pchNext;
937 wm->info.pchEndRead = lpmmioinfo->pchEndRead;
938
939 return MMSYSERR_NOERROR;
940}
941
942/**************************************************************************
943* mmioSetBuffer [WINMM.@]
944*/
946{
947 LPWINE_MMIO wm;
948
949 TRACE("(hmmio=%p, pchBuf=%p, cchBuf=%d, uFlags=%#08x)\n",
950 hmmio, pchBuffer, cchBuffer, uFlags);
951
952 if ((wm = MMIO_Get(hmmio)) == NULL)
954
955 return MMIO_SetBuffer(wm, pchBuffer, cchBuffer, uFlags);
956}
957
958/**************************************************************************
959 * mmioFlush [WINMM.@]
960 */
962{
963 LPWINE_MMIO wm;
964
965 TRACE("(%p, %04X)\n", hmmio, uFlags);
966
967 if ((wm = MMIO_Get(hmmio)) == NULL)
969
970 return MMIO_Flush(wm, uFlags);
971}
972
973/**************************************************************************
974 * mmioAdvance [WINMM.@]
975 */
976MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
977{
978 LPWINE_MMIO wm;
979
980 TRACE("hmmio=%p, lpmmioinfo=%p, uFlags=%04X\n", hmmio, lpmmioinfo, uFlags);
981
982 /* NOTE: mmioAdvance16 heavily relies on parameters from lpmmioinfo we're using
983 * here. be sure if you change something here to check mmioAdvance16 as well
984 */
985 if ((wm = MMIO_Get(hmmio)) == NULL)
987
988 if (!wm->info.cchBuffer)
989 return MMIOERR_UNBUFFERED;
990
991 if (uFlags != MMIO_READ && uFlags != MMIO_WRITE)
992 return MMSYSERR_INVALPARAM;
993
994 if (uFlags == MMIO_WRITE && (lpmmioinfo->dwFlags & MMIO_DIRTY))
995 {
996 send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lpmmioinfo->lBufOffset, SEEK_SET, FALSE);
997 send_message(wm->ioProc, &wm->info, MMIOM_WRITE, (LPARAM)lpmmioinfo->pchBuffer,
998 lpmmioinfo->pchNext - lpmmioinfo->pchBuffer, FALSE);
999 lpmmioinfo->dwFlags &= ~MMIO_DIRTY;
1000 }
1001 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
1002 return MMIOERR_CANNOTWRITE;
1003
1004 if (lpmmioinfo) {
1005 wm->dwFileSize = max(wm->dwFileSize, lpmmioinfo->lBufOffset +
1006 (lpmmioinfo->pchNext - lpmmioinfo->pchBuffer));
1007 }
1009
1010 if (lpmmioinfo) {
1011 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
1012 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
1013 (wm->info.pchEndRead - wm->info.pchBuffer);
1014 lpmmioinfo->pchEndWrite = lpmmioinfo->pchBuffer +
1015 (wm->info.pchEndWrite - wm->info.pchBuffer);
1016 lpmmioinfo->lDiskOffset = wm->info.lDiskOffset;
1017 lpmmioinfo->lBufOffset = wm->info.lBufOffset;
1018 }
1019 return MMSYSERR_NOERROR;
1020}
1021
1022/**************************************************************************
1023 * mmioStringToFOURCCA [WINMM.@]
1024 */
1026{
1027 CHAR cc[4];
1028 int i = 0;
1029
1030 for (i = 0; i < 4 && sz[i]; i++) {
1031 if (uFlags & MMIO_TOUPPER) {
1032 cc[i] = toupper(sz[i]);
1033 } else {
1034 cc[i] = sz[i];
1035 }
1036 }
1037
1038 /* Pad with spaces */
1039 while (i < 4) cc[i++] = ' ';
1040
1041 TRACE("Got '%.4s'\n",cc);
1042 return mmioFOURCC(cc[0],cc[1],cc[2],cc[3]);
1043}
1044
1045/**************************************************************************
1046 * mmioStringToFOURCCW [WINMM.@]
1047 */
1049{
1050 char szA[4];
1051
1052 WideCharToMultiByte( CP_ACP, 0, sz, 4, szA, sizeof(szA), NULL, NULL );
1053 return mmioStringToFOURCCA(szA,uFlags);
1054}
1055
1056/**************************************************************************
1057 * mmioInstallIOProcA [WINMM.@]
1058 */
1061{
1062 return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, FALSE);
1063}
1064
1065/**************************************************************************
1066 * mmioInstallIOProcW [WINMM.@]
1067 */
1070{
1071 return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, TRUE);
1072}
1073
1074/******************************************************************
1075 * MMIO_SendMessage
1076 *
1077 *
1078 */
1079static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1,
1080 LPARAM lParam2, BOOL is_unicode)
1081{
1082 LPWINE_MMIO wm;
1083
1084 TRACE("(%p, %u, %ld, %ld, %s)\n", hmmio, uMessage, lParam1, lParam2, is_unicode ? "unicode" : "ansi");
1085
1086 if (uMessage < MMIOM_USER)
1087 return MMSYSERR_INVALPARAM;
1088
1089 if ((wm = MMIO_Get(hmmio)) == NULL)
1090 return MMSYSERR_INVALHANDLE;
1091
1092 return send_message(wm->ioProc, &wm->info, uMessage, lParam1, lParam2, is_unicode);
1093}
1094
1095/**************************************************************************
1096 * mmioSendMessage [WINMM.@]
1097 */
1098LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage,
1099 LPARAM lParam1, LPARAM lParam2)
1100{
1101 return MMIO_SendMessage(hmmio, uMessage, lParam1, lParam2, FALSE);
1102}
1103
1104/**************************************************************************
1105 * mmioDescend [WINMM.@]
1106 */
1108 const MMCKINFO* lpckParent, UINT uFlags)
1109{
1110 DWORD dwOldPos;
1111 FOURCC srchCkId;
1112 FOURCC srchType;
1113
1114 TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags);
1115
1116 if (lpck == NULL)
1117 return MMSYSERR_INVALPARAM;
1118
1119 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1120 TRACE("dwOldPos=%d\n", dwOldPos);
1121
1122 if (lpckParent != NULL) {
1123 TRACE("seek inside parent at %d !\n", lpckParent->dwDataOffset);
1124 /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
1125 if (dwOldPos < lpckParent->dwDataOffset ||
1126 dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) {
1127 WARN("outside parent chunk\n");
1128 return MMIOERR_CHUNKNOTFOUND;
1129 }
1130 }
1131
1132 /* The SDK docu says 'ckid' is used for all cases. Real World
1133 * examples disagree -Marcus,990216.
1134 */
1135
1136 srchCkId = 0;
1137 srchType = 0;
1138
1139 /* find_chunk looks for 'ckid' */
1140 if (uFlags & MMIO_FINDCHUNK)
1141 srchCkId = lpck->ckid;
1142
1143 /* find_riff and find_list look for 'fccType' */
1144 if (uFlags & MMIO_FINDLIST)
1145 {
1146 srchCkId = FOURCC_LIST;
1147 srchType = lpck->fccType;
1148 }
1149
1150 if (uFlags & MMIO_FINDRIFF)
1151 {
1152 srchCkId = FOURCC_RIFF;
1153 srchType = lpck->fccType;
1154 }
1155
1156 TRACE("searching for %4.4s.%4.4s\n",
1157 (LPCSTR)&srchCkId, srchType ? (LPCSTR)&srchType : "any");
1158
1159 while (TRUE)
1160 {
1161 LONG ix;
1162
1163 ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
1164 if (ix < 0 || ix < 2*sizeof(DWORD))
1165 {
1166 mmioSeek(hmmio, dwOldPos, SEEK_SET);
1167 WARN("return ChunkNotFound\n");
1168 return MMIOERR_CHUNKNOTFOUND;
1169 }
1170
1171 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1172 TRACE("ckid=%4.4s fcc=%4.4s cksize=%08X !\n",
1173 (LPCSTR)&lpck->ckid,
1174 srchType ? (LPCSTR)&lpck->fccType:"<na>",
1175 lpck->cksize);
1176 if ( (!srchCkId || (srchCkId == lpck->ckid)) &&
1177 (!srchType || (srchType == lpck->fccType)) )
1178 break;
1179
1180 dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1);
1181 mmioSeek(hmmio, dwOldPos, SEEK_SET);
1182 }
1183
1184 lpck->dwFlags = 0;
1185 /* If we were looking for RIFF/LIST chunks, the final file position
1186 * is after the chunkid. If we were just looking for the chunk
1187 * it is after the cksize. So add 4 in RIFF/LIST case.
1188 */
1189 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1190 mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET);
1191 else
1192 {
1193 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
1194 lpck->fccType = 0;
1195 }
1196 TRACE("lpck: ckid=%.4s, cksize=%d, dwDataOffset=%d fccType=%08X (%.4s)!\n",
1197 (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset,
1198 lpck->fccType, srchType?(LPSTR)&lpck->fccType:"");
1199 return MMSYSERR_NOERROR;
1200}
1201
1202/**************************************************************************
1203 * mmioAscend [WINMM.@]
1204 */
1206{
1207 TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
1208
1209 if (lpck->dwFlags & MMIO_DIRTY) {
1210 DWORD dwOldPos, dwNewSize;
1211
1212 TRACE("Chunk is dirty, checking if chunk's size is correct\n");
1213 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1214 TRACE("dwOldPos=%d lpck->dwDataOffset = %d\n", dwOldPos, lpck->dwDataOffset);
1215 dwNewSize = dwOldPos - lpck->dwDataOffset;
1216 if (dwNewSize != lpck->cksize) {
1217 TRACE("Nope: lpck->cksize=%d dwNewSize=%d\n", lpck->cksize, dwNewSize);
1218 lpck->cksize = dwNewSize;
1219
1220 /* pad odd size with 0 */
1221 if (dwNewSize & 1) {
1222 char ch = 0;
1223 mmioWrite(hmmio, &ch, 1);
1224 }
1225 mmioSeek(hmmio, lpck->dwDataOffset - sizeof(DWORD), SEEK_SET);
1226 mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1227 }
1228 lpck->dwFlags = 0;
1229 }
1230
1231 mmioSeek(hmmio, lpck->dwDataOffset + ((lpck->cksize + 1) & ~1), SEEK_SET);
1232
1233 return MMSYSERR_NOERROR;
1234}
1235
1236/**************************************************************************
1237 * mmioCreateChunk [WINMM.@]
1238 */
1240{
1241 DWORD dwOldPos;
1242 LONG size;
1243 LONG ix;
1244
1245 TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
1246
1247 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1248 TRACE("dwOldPos=%d\n", dwOldPos);
1249
1250 if (uFlags == MMIO_CREATELIST)
1251 lpck->ckid = FOURCC_LIST;
1252 else if (uFlags == MMIO_CREATERIFF)
1253 lpck->ckid = FOURCC_RIFF;
1254
1255 TRACE("ckid=%.4s\n", (LPSTR)&lpck->ckid);
1256
1257 size = 2 * sizeof(DWORD);
1258 lpck->dwDataOffset = dwOldPos + size;
1259
1260 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1261 size += sizeof(DWORD);
1262 lpck->dwFlags = MMIO_DIRTY;
1263
1264 ix = mmioWrite(hmmio, (LPSTR)lpck, size);
1265 TRACE("after mmioWrite ix = %d req = %d, errno = %d\n", ix, size, errno);
1266 if (ix != size) {
1267 mmioSeek(hmmio, dwOldPos, SEEK_SET);
1268 WARN("return CannotWrite\n");
1269 return MMIOERR_CANNOTWRITE;
1270 }
1271
1272 return MMSYSERR_NOERROR;
1273}
1274
1275/**************************************************************************
1276 * mmioRenameA [WINMM.@]
1277 */
1278MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName,
1279 const MMIOINFO* lpmmioinfo, DWORD dwFlags)
1280{
1281 struct IOProcList* ioProc = NULL;
1282 struct IOProcList tmp;
1283 FOURCC fcc;
1284
1285 TRACE("('%s', '%s', %p, %08X);\n",
1286 debugstr_a(szFileName), debugstr_a(szNewFileName), lpmmioinfo, dwFlags);
1287
1288 /* If both params are NULL, then parse the file name */
1289 if (lpmmioinfo && lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)
1290 {
1291 fcc = MMIO_ParseExtA(szFileName);
1292 if (fcc) ioProc = MMIO_FindProcNode(fcc);
1293 }
1294
1295 /* Handle any unhandled/error case from above. Assume DOS file */
1296 if (!lpmmioinfo || (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL && ioProc == NULL))
1297 ioProc = MMIO_FindProcNode(FOURCC_DOS);
1298 /* if just the four character code is present, look up IO proc */
1299 else if (lpmmioinfo->pIOProc == NULL)
1300 ioProc = MMIO_FindProcNode(lpmmioinfo->fccIOProc);
1301 else /* use relevant ioProc */
1302 {
1303 ioProc = &tmp;
1304 tmp.fourCC = lpmmioinfo->fccIOProc;
1305 tmp.pIOProc = lpmmioinfo->pIOProc;
1306 tmp.is_unicode = FALSE;
1307 tmp.count = 1;
1308 }
1309
1310 /* FIXME: should we actually pass lpmmioinfo down the drain ???
1311 * or make a copy of it because it's const ???
1312 */
1313 return send_message(ioProc, (MMIOINFO*)lpmmioinfo, MMIOM_RENAME,
1314 (LPARAM)szFileName, (LPARAM)szNewFileName, FALSE);
1315}
1316
1317/**************************************************************************
1318 * mmioRenameW [WINMM.@]
1319 */
1320MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName,
1321 const MMIOINFO* lpmmioinfo, DWORD dwFlags)
1322{
1323 LPSTR szFn = NULL;
1324 LPSTR sznFn = NULL;
1326 INT len;
1327
1328 if (szFileName)
1329 {
1330 len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
1331 szFn = HeapAlloc( GetProcessHeap(), 0, len );
1332 if (!szFn) goto done;
1333 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
1334 }
1335 if (szNewFileName)
1336 {
1337 len = WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, NULL, 0, NULL, NULL );
1338 sznFn = HeapAlloc( GetProcessHeap(), 0, len );
1339 if (!sznFn) goto done;
1340 WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, sznFn, len, NULL, NULL );
1341 }
1342
1343 ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwFlags);
1344
1345done:
1346 HeapFree(GetProcessHeap(),0,szFn);
1347 HeapFree(GetProcessHeap(),0,sznFn);
1348 return ret;
1349}
int toupper(int c)
Definition: utclib.c:881
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define SEEK_END
Definition: cabinet.c:29
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT uFlags
Definition: api.c:59
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define lstrcpynA
Definition: compat.h:751
#define HeapAlloc
Definition: compat.h:733
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static const WCHAR *const ext[]
Definition: module.c:53
static DWORD cchBuffer
Definition: fusion.c:85
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
Definition: create.c:368
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:331
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:636
BOOL WINAPI MoveFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
Definition: move.c:1137
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:993
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1205
static HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO *refmminfo, DWORD dwOpenFlags, BOOL is_unicode)
Definition: mmio.c:568
static MMRESULT MMIO_Flush(WINE_MMIO *wm, UINT uFlags)
Definition: mmio.c:476
static LPMMIOPROC MMIO_InstallIOProc(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags, BOOL is_unicode)
Definition: mmio.c:242
MMRESULT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT uFlags)
Definition: mmio.c:945
static LONG MMIO_GrabNextBuffer(LPWINE_MMIO wm, int for_read)
Definition: mmio.c:498
MMRESULT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:961
static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, LPARAM lParam2, BOOL is_unicode)
Definition: mmio.c:1079
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:836
MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:901
HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:693
static FOURCC MMIO_ParseExtA(LPCSTR szFileName)
Definition: mmio.c:361
static LRESULT CALLBACK mmioDosIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:39
MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:702
LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
Definition: mmio.c:782
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1107
static struct IOProcList * pIOProcListAnchor
Definition: mmio.c:220
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:733
static struct IOProcList defaultProcs[]
Definition: mmio.c:215
FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR sz, UINT uFlags)
Definition: mmio.c:1048
MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO *lpck, UINT uFlags)
Definition: mmio.c:1239
static BOOL MMIO_Destroy(LPWINE_MMIO wm)
Definition: mmio.c:455
static struct IOProcList * MMIO_FindProcNode(FOURCC fccIOProc)
Definition: mmio.c:227
static MMRESULT MMIO_SetBuffer(WINE_MMIO *wm, void *pchBuffer, LONG cchBuffer, UINT uFlags)
Definition: mmio.c:527
LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
Definition: mmio.c:1059
static WINE_MMIO * MMIOList
Definition: mmio.c:34
FOURCC WINAPI mmioStringToFOURCCA(LPCSTR sz, UINT uFlags)
Definition: mmio.c:1025
MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName, const MMIOINFO *lpmmioinfo, DWORD dwFlags)
Definition: mmio.c:1278
static LRESULT CALLBACK mmioMemIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:142
LPMMIOPROC WINAPI mmioInstallIOProcW(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
Definition: mmio.c:1068
static LPWINE_MMIO MMIO_Create(void)
Definition: mmio.c:432
LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:1098
HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:670
static LRESULT send_message(struct IOProcList *ioProc, LPMMIOINFO mmioinfo, DWORD wMsg, LPARAM lParam1, LPARAM lParam2, BOOL is_unicode)
Definition: mmio.c:326
MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName, const MMIOINFO *lpmmioinfo, DWORD dwFlags)
Definition: mmio.c:1320
MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:976
MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:918
static LPWINE_MMIO MMIO_Get(HMMIO h)
Definition: mmio.c:414
#define assert(x)
Definition: debug.h:53
DWORD FOURCC
Definition: dmdls.h:25
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLintptr offset
Definition: glext.h:5920
const GLfloat * m
Definition: glext.h:10848
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
uint32_t cc
Definition: isohybrid.c:75
#define SEEK_SET
Definition: jmemansi.c:26
#define debugstr_a
Definition: kernel32.h:31
#define _lread(a, b, c)
Definition: kernel32.h:171
int WINAPI _lclose(HFILE hFile)
Definition: lfile.c:138
LONG WINAPI _llseek(HFILE hFile, LONG lOffset, int iOrigin)
Definition: lfile.c:149
long WINAPI _hwrite(HFILE hFile, LPCSTR lpBuffer, long lBytes)
Definition: lfile.c:41
#define pch(ap)
Definition: match.c:418
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define MMIO_PARSE
Definition: mmsystem.h:529
#define MMIO_FINDRIFF
Definition: mmsystem.h:552
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define MMIOM_RENAME
Definition: mmsystem.h:562
#define MMIO_ALLOCBUF
Definition: mmsystem.h:532
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define MMIOERR_CHUNKNOTFOUND
Definition: mmsystem.h:517
UINT MMRESULT
Definition: mmsystem.h:962
#define MMIO_DEFAULTBUFFER
Definition: mmsystem.h:568
#define MMIO_GETTEMP
Definition: mmsystem.h:533
#define MMIOM_WRITEFLUSH
Definition: mmsystem.h:561
#define MMIOERR_FILENOTFOUND
Definition: mmsystem.h:509
#define FOURCC_DOS
Definition: mmsystem.h:566
#define MMIO_FHOPEN
Definition: mmsystem.h:543
#define MMIOERR_OUTOFMEMORY
Definition: mmsystem.h:510
#define MMIOM_READ
Definition: mmsystem.h:556
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
#define MMIOM_USER
Definition: mmsystem.h:563
#define MMIO_CREATE
Definition: mmsystem.h:528
#define MMIO_TOUPPER
Definition: mmsystem.h:545
#define FOURCC_LIST
Definition: mmsystem.h:565
#define MMIOM_CLOSE
Definition: mmsystem.h:560
#define MMIO_CREATELIST
Definition: mmsystem.h:555
#define MMIOM_SEEK
Definition: mmsystem.h:558
#define MMIO_RWMODE
Definition: mmsystem.h:526
#define MMIO_GLOBALPROC
Definition: mmsystem.h:547
#define MMSYSERR_INVALHANDLE
Definition: mmsystem.h:101
#define MMIO_WRITE
Definition: mmsystem.h:536
#define FOURCC_MEM
Definition: mmsystem.h:567
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
#define MMIOM_OPEN
Definition: mmsystem.h:559
#define MMIOERR_CANNOTOPEN
Definition: mmsystem.h:511
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
MMIOPROC * LPMMIOPROC
Definition: mmsystem.h:1483
#define MMIO_REMOVEPROC
Definition: mmsystem.h:548
#define MMIO_DIRTY
Definition: mmsystem.h:534
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define MMIO_INSTALLPROC
Definition: mmsystem.h:546
#define MMIO_EMPTYBUF
Definition: mmsystem.h:544
#define MMIO_READ
Definition: mmsystem.h:535
#define MMIOM_WRITE
Definition: mmsystem.h:557
#define MMIO_CREATERIFF
Definition: mmsystem.h:554
#define MMIO_EXIST
Definition: mmsystem.h:531
#define MMIOERR_UNBUFFERED
Definition: mmsystem.h:518
#define MMIO_FINDPROC
Definition: mmsystem.h:550
#define MMIOERR_CANNOTWRITE
Definition: mmsystem.h:514
char * HPSTR
Definition: mmsystem.h:1477
#define MMIO_FINDLIST
Definition: mmsystem.h:553
#define SEEK_CUR
Definition: util.h:63
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
long LONG
Definition: pedump.c:60
#define errno
Definition: errno.h:18
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define error2(s, a, b)
Definition: debug.h:126
#define error1(s, a)
Definition: debug.h:125
#define TRACE(s)
Definition: solgame.cpp:4
BOOL is_unicode
Definition: winemm.h:138
LPMMIOPROC pIOProc
Definition: winemm.h:137
int count
Definition: winemm.h:139
struct IOProcList * pNext
Definition: winemm.h:135
FOURCC fourCC
Definition: winemm.h:136
FOURCC ckid
Definition: mmsystem.h:1507
DWORD cksize
Definition: mmsystem.h:1508
DWORD dwDataOffset
Definition: mmsystem.h:1510
DWORD dwFlags
Definition: mmsystem.h:1511
FOURCC fccType
Definition: mmsystem.h:1509
LPMMIOPROC pIOProc
Definition: mmsystem.h:1488
HPSTR pchEndRead
Definition: mmsystem.h:1494
LONG cchBuffer
Definition: mmsystem.h:1491
HPSTR pchNext
Definition: mmsystem.h:1493
DWORD dwFlags
Definition: mmsystem.h:1486
HPSTR pchEndWrite
Definition: mmsystem.h:1495
LONG lBufOffset
Definition: mmsystem.h:1496
LONG lDiskOffset
Definition: mmsystem.h:1497
HPSTR pchBuffer
Definition: mmsystem.h:1492
FOURCC fccIOProc
Definition: mmsystem.h:1487
DWORD adwInfo[3]
Definition: mmsystem.h:1498
UINT wErrorRet
Definition: mmsystem.h:1489
HMMIO hmmio
Definition: mmsystem.h:1501
DWORD dwFileSize
Definition: winemm.h:148
unsigned bBufferLoaded
Definition: winemm.h:147
struct IOProcList * ioProc
Definition: winemm.h:145
MMIOINFO info
Definition: winemm.h:143
unsigned bTmpIOProc
Definition: winemm.h:146
struct tagWINE_MMIO * lpNext
Definition: winemm.h:144
#define max(a, b)
Definition: svc.c:63
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define HFILE_ERROR
Definition: winbase.h:111
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
int HFILE
Definition: windef.h:298
#define WINAPI
Definition: msvc.h:6
CRITICAL_SECTION WINMM_cs
Definition: winmm.c:53
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175