ReactOS  0.4.13-dev-249-gcba1a2f
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  */
39 static 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:
96  case MMIOM_WRITEFLUSH:
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  */
142 static 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 
215 static struct IOProcList defaultProcs[] = {
218 };
219 
221 
222 /****************************************************************
223  * MMIO_FindProcNode [INTERNAL]
224  *
225  * Finds the ProcList node associated with a given FOURCC code.
226  */
227 static 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 
251  if (dwFlags & MMIO_GLOBALPROC)
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  */
326 static 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  */
361 static 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  LPSTR extEnd;
370  LPSTR extStart;
371 
372  TRACE("(%s)\n", debugstr_a(szFileName));
373 
374  if (!szFileName)
375  return ret;
376 
377  /* Find the last '.' */
378  extStart = strrchr(szFileName,'.');
379 
380  if (!extStart) {
381  ERR("No . in szFileName: %s\n", debugstr_a(szFileName));
382  } else {
383  CHAR ext[5];
384 
385  /* Find the '+' afterwards */
386  extEnd = strchr(extStart,'+');
387  if (extEnd) {
388 
389  if (extEnd - extStart - 1 > 4)
390  WARN("Extension length > 4\n");
391  lstrcpynA(ext, extStart + 1, min(extEnd-extStart,5));
392 
393  } else {
394  /* No + so just an extension */
395  if (strlen(extStart) > 4) {
396  WARN("Extension length > 4\n");
397  }
398  lstrcpynA(ext, extStart + 1, 5);
399  }
400  TRACE("Got extension: %s\n", debugstr_a(ext));
401 
402  /* FOURCC codes identifying file-extensions must be uppercase */
404  }
405  return ret;
406 }
407 
408 /**************************************************************************
409  * MMIO_Get [internal]
410  *
411  * Retrieves the mmio object from current process
412  */
413 static LPWINE_MMIO MMIO_Get(HMMIO h)
414 {
415  LPWINE_MMIO wm = NULL;
416 
418  for (wm = MMIOList; wm; wm = wm->lpNext) {
419  if (wm->info.hmmio == h)
420  break;
421  }
423  return wm;
424 }
425 
426 /**************************************************************************
427  * MMIO_Create [internal]
428  *
429  * Creates an internal representation for a mmio instance
430  */
432 {
433  static WORD MMIO_counter = 0;
434  LPWINE_MMIO wm;
435 
437  if (wm) {
439  /* lookup next unallocated WORD handle, with a non NULL value */
440  while (++MMIO_counter == 0 || MMIO_Get((HMMIO)(ULONG_PTR)MMIO_counter));
441  wm->info.hmmio = (HMMIO)(ULONG_PTR)MMIO_counter;
442  wm->lpNext = MMIOList;
443  MMIOList = wm;
445  }
446  return wm;
447 }
448 
449 /**************************************************************************
450  * MMIO_Destroy [internal]
451  *-
452  * Destroys an internal representation for a mmio instance
453  */
455 {
456  LPWINE_MMIO* m;
457 
459  /* search for the matching one... */
460  m = &MMIOList;
461  while (*m && *m != wm) m = &(*m)->lpNext;
462  /* ...and destroy */
463  if (*m) {
464  *m = (*m)->lpNext;
465  HeapFree(GetProcessHeap(), 0, wm);
466  wm = NULL;
467  }
469  return wm ? FALSE : TRUE;
470 }
471 
472 /****************************************************************
473  * MMIO_Flush [INTERNAL]
474  */
476 {
477  if (wm->info.cchBuffer && (wm->info.fccIOProc != FOURCC_MEM)) {
478  /* not quite sure what to do here, but I'll guess */
479  if (wm->info.dwFlags & MMIO_DIRTY) {
480  /* FIXME: error handling */
482  send_message(wm->ioProc, &wm->info, MMIOM_WRITE,
483  (LPARAM)wm->info.pchBuffer,
484  wm->info.pchNext - wm->info.pchBuffer, FALSE);
485  }
486  if (uFlags & MMIO_EMPTYBUF)
487  wm->info.pchNext = wm->info.pchEndRead = wm->info.pchBuffer;
488  }
489  wm->info.dwFlags &= ~MMIO_DIRTY;
490 
491  return MMSYSERR_NOERROR;
492 }
493 
494 /***************************************************************************
495  * MMIO_GrabNextBuffer [INTERNAL]
496  */
497 static LONG MMIO_GrabNextBuffer(LPWINE_MMIO wm, int for_read)
498 {
499  LONG size = wm->info.cchBuffer;
500 
501  TRACE("bo=%x do=%x of=%lx\n",
502  wm->info.lBufOffset, wm->info.lDiskOffset,
503  send_message(wm->ioProc, &wm->info, MMIOM_SEEK, 0, SEEK_CUR, FALSE));
504 
505  wm->info.lBufOffset = wm->info.lDiskOffset;
506  wm->info.pchNext = wm->info.pchBuffer;
507  wm->info.pchEndRead = wm->info.pchBuffer;
508  wm->info.pchEndWrite = wm->info.pchBuffer + wm->info.cchBuffer;
509 
510  wm->bBufferLoaded = TRUE;
511  if (for_read) {
512  size = send_message(wm->ioProc, &wm->info, MMIOM_READ,
513  (LPARAM)wm->info.pchBuffer, size, FALSE);
514  if (size > 0)
515  wm->info.pchEndRead += size;
516  else
517  wm->bBufferLoaded = FALSE;
518  }
519 
520  return size;
521 }
522 
523 /***************************************************************************
524  * MMIO_SetBuffer [INTERNAL]
525  */
526 static MMRESULT MMIO_SetBuffer(WINE_MMIO* wm, void* pchBuffer, LONG cchBuffer,
527  UINT uFlags)
528 {
529  TRACE("(%p %p %d %u)\n", wm, pchBuffer, cchBuffer, uFlags);
530 
531  if (cchBuffer > 0xFFFF)
532  WARN("Untested handling of huge mmio buffers (%d >= 64k)\n", cchBuffer);
533 
534  if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
535  return MMIOERR_CANNOTWRITE;
536 
537  /* free previous buffer if allocated */
538  if (wm->info.dwFlags & MMIO_ALLOCBUF) {
540  wm->info.pchBuffer = NULL;
541  wm->info.dwFlags &= ~MMIO_ALLOCBUF;
542  }
543 
544  if (pchBuffer) {
545  wm->info.pchBuffer = pchBuffer;
546  } else if (cchBuffer) {
547  if (!(wm->info.pchBuffer = HeapAlloc(GetProcessHeap(), 0, cchBuffer)))
548  return MMIOERR_OUTOFMEMORY;
549  wm->info.dwFlags |= MMIO_ALLOCBUF;
550  } else {
551  wm->info.pchBuffer = NULL;
552  }
553 
554  wm->info.cchBuffer = cchBuffer;
555  wm->info.pchNext = wm->info.pchBuffer;
556  wm->info.pchEndRead = wm->info.pchBuffer;
558  wm->info.lBufOffset = wm->info.lDiskOffset;
559  wm->bBufferLoaded = FALSE;
560 
561  return MMSYSERR_NOERROR;
562 }
563 
564 /**************************************************************************
565  * MMIO_Open [internal]
566  */
567 static HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO* refmminfo, DWORD dwOpenFlags, BOOL is_unicode)
568 {
569  LPWINE_MMIO wm;
570  MMIOINFO mmioinfo;
571 
572  TRACE("('%s', %p, %08X, %s);\n", szFileName, refmminfo, dwOpenFlags, is_unicode ? "unicode" : "ansi");
573 
574  if (!refmminfo) {
575  refmminfo = &mmioinfo;
576 
577  mmioinfo.fccIOProc = 0;
578  mmioinfo.pIOProc = NULL;
579  mmioinfo.pchBuffer = NULL;
580  mmioinfo.cchBuffer = 0;
581  is_unicode = FALSE;
582  }
583 
584  if (dwOpenFlags & (MMIO_PARSE|MMIO_EXIST)) {
585  char buffer[MAX_PATH];
586 
587  if (!szFileName)
588  return (HMMIO)FALSE;
589  if (GetFullPathNameA(szFileName, sizeof(buffer), buffer, NULL) >= sizeof(buffer))
590  return (HMMIO)FALSE;
591  if ((dwOpenFlags & MMIO_EXIST) && (GetFileAttributesA(buffer) == INVALID_FILE_ATTRIBUTES))
592  return (HMMIO)FALSE;
593  strcpy(szFileName, buffer);
594  return (HMMIO)TRUE;
595  }
596 
597  if ((wm = MMIO_Create()) == NULL)
598  return 0;
599 
600  /* If both params are NULL, then parse the file name if available */
601  if (refmminfo->fccIOProc == 0 && refmminfo->pIOProc == NULL) {
602  wm->info.fccIOProc = MMIO_ParseExtA(szFileName);
603  /* Handle any unhandled/error case. Assume DOS file */
604  if (wm->info.fccIOProc == 0)
605  wm->info.fccIOProc = FOURCC_DOS;
606  if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) {
607  /* If not found, retry with FOURCC_DOS */
608  wm->info.fccIOProc = FOURCC_DOS;
609  if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc)))
610  goto error2;
611  }
612  wm->bTmpIOProc = FALSE;
613  }
614  /* if just the four character code is present, look up IO proc */
615  else if (refmminfo->pIOProc == NULL) {
616  wm->info.fccIOProc = refmminfo->fccIOProc;
617  if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2;
618  wm->bTmpIOProc = FALSE;
619  }
620  /* if IO proc specified, use it and specified four character code */
621  else {
622  wm->info.fccIOProc = refmminfo->fccIOProc;
623  MMIO_InstallIOProc(wm->info.fccIOProc, refmminfo->pIOProc,
625  if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2;
626  assert(wm->ioProc->pIOProc == refmminfo->pIOProc);
627  wm->bTmpIOProc = TRUE;
628  }
629 
630  wm->ioProc->count++;
631  wm->info.dwFlags = dwOpenFlags;
632 
633  if (dwOpenFlags & MMIO_ALLOCBUF) {
634  refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer,
635  refmminfo->cchBuffer ? refmminfo->cchBuffer : MMIO_DEFAULTBUFFER, 0);
636  if (refmminfo->wErrorRet != MMSYSERR_NOERROR)
637  goto error1;
638  } else {
639  refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer, refmminfo->cchBuffer, 0);
640  if (refmminfo->wErrorRet != MMSYSERR_NOERROR)
641  goto error1;
642  }
643 
644  if (wm->info.fccIOProc == FOURCC_MEM && !(wm->info.dwFlags & MMIO_ALLOCBUF))
645  wm->bBufferLoaded = TRUE;
646 
647  /* see mmioDosIOProc for that one */
648  wm->info.adwInfo[0] = refmminfo->adwInfo[0];
649 
650  /* call IO proc to actually open file */
651  refmminfo->wErrorRet = send_message(wm->ioProc, &wm->info, MMIOM_OPEN,
652  (LPARAM)szFileName, 0, FALSE);
653 
654  /* grab file size, when possible (FIXME: not 64 bit safe) */
656 
657  if (refmminfo->wErrorRet == 0)
658  return wm->info.hmmio;
659  error1:
660  if (wm->ioProc) wm->ioProc->count--;
661  error2:
662  MMIO_Destroy(wm);
663  return 0;
664 }
665 
666 /**************************************************************************
667  * mmioOpenW [WINMM.@]
668  */
669 HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO* lpmmioinfo,
670  DWORD dwOpenFlags)
671 {
672  HMMIO ret;
673  LPSTR szFn = NULL;
674 
675  if (szFileName)
676  {
677  INT len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
678  szFn = HeapAlloc( GetProcessHeap(), 0, len );
679  if (!szFn) return NULL;
680  WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
681  }
682 
683  ret = MMIO_Open(szFn, lpmmioinfo, dwOpenFlags, TRUE);
684 
685  HeapFree(GetProcessHeap(), 0, szFn);
686  return ret;
687 }
688 
689 /**************************************************************************
690  * mmioOpenA [WINMM.@]
691  */
692 HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO* lpmmioinfo,
693  DWORD dwOpenFlags)
694 {
695  return MMIO_Open(szFileName, lpmmioinfo, dwOpenFlags, FALSE);
696 }
697 
698 /**************************************************************************
699  * mmioClose [WINMM.@]
700  */
702 {
703  LPWINE_MMIO wm;
705 
706  TRACE("(%p, %04X);\n", hmmio, uFlags);
707 
708  if ((wm = MMIO_Get(hmmio)) == NULL)
709  return MMSYSERR_INVALHANDLE;
710 
711  if ((result = MMIO_Flush(wm, 0)) != MMSYSERR_NOERROR)
712  return result;
713 
715 
716  MMIO_SetBuffer(wm, NULL, 0, 0);
717 
718  wm->ioProc->count--;
719 
720  if (wm->bTmpIOProc)
721  MMIO_InstallIOProc(wm->info.fccIOProc, wm->ioProc->pIOProc,
722  MMIO_REMOVEPROC, wm->ioProc->is_unicode);
723 
724  MMIO_Destroy(wm);
725 
726  return result;
727 }
728 
729 /**************************************************************************
730  * mmioRead [WINMM.@]
731  */
733 {
734  LPWINE_MMIO wm;
735  LONG count;
736 
737  TRACE("(%p, %p, %d);\n", hmmio, pch, cch);
738 
739  if ((wm = MMIO_Get(hmmio)) == NULL)
740  return -1;
741 
742  /* unbuffered case first */
743  if (!wm->info.pchBuffer)
744  return send_message(wm->ioProc, &wm->info, MMIOM_READ, (LPARAM)pch, cch, FALSE);
745 
746  /* first try from current buffer */
747  if (wm->info.pchNext != wm->info.pchEndRead) {
748  count = wm->info.pchEndRead - wm->info.pchNext;
749  if (count > cch || count < 0) count = cch;
750  memcpy(pch, wm->info.pchNext, count);
751  wm->info.pchNext += count;
752  pch += count;
753  cch -= count;
754  } else
755  count = 0;
756 
757  if (cch && (wm->info.fccIOProc != FOURCC_MEM)) {
758  assert(wm->info.cchBuffer);
759 
760  while (cch) {
761  LONG size;
762 
764  if (size <= 0) break;
765  if (size > cch) size = cch;
766  memcpy(pch, wm->info.pchBuffer, size);
767  wm->info.pchNext += size;
768  pch += size;
769  cch -= size;
770  count += size;
771  }
772  }
773 
774  TRACE("count=%d\n", count);
775  return count;
776 }
777 
778 /**************************************************************************
779  * mmioWrite [WINMM.@]
780  */
781 LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
782 {
783  LPWINE_MMIO wm;
784  LONG count;
785 
786  TRACE("(%p, %p, %d);\n", hmmio, pch, cch);
787 
788  if ((wm = MMIO_Get(hmmio)) == NULL)
789  return -1;
790 
791  if (wm->info.cchBuffer) {
792  LONG bytesW = 0;
793 
794  count = 0;
795  while (cch) {
796  if (wm->info.pchNext != wm->info.pchEndWrite) {
797  count = wm->info.pchEndWrite - wm->info.pchNext;
798  if (count > cch || count < 0) count = cch;
799  memcpy(wm->info.pchNext, pch, count);
800  wm->info.pchNext += count;
801  pch += count;
802  cch -= count;
803  bytesW += count;
804  wm->info.dwFlags |= MMIO_DIRTY;
805  } else {
806  if (wm->info.fccIOProc == FOURCC_MEM) {
807  if (wm->info.adwInfo[0]) {
808  /* from where would we get the memory handle? */
809  FIXME("memory file expansion not implemented!\n");
810  break;
811  } else break;
812  }
813  }
814 
815  if (wm->info.pchNext == wm->info.pchEndWrite)
816  {
819  }
820  else break;
821  }
822  count = bytesW;
823  } else {
825  wm->info.lBufOffset = wm->info.lDiskOffset;
826  }
827 
828  TRACE("bytes written=%d\n", count);
829  return count;
830 }
831 
832 /**************************************************************************
833  * mmioSeek [WINMM.@]
834  */
835 LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
836 {
837  LPWINE_MMIO wm;
838  LONG offset;
839 
840  TRACE("(%p, %08X, %d);\n", hmmio, lOffset, iOrigin);
841 
842  if ((wm = MMIO_Get(hmmio)) == NULL)
843  return MMSYSERR_INVALHANDLE;
844 
845  /* not buffered, direct seek on file */
846  if (!wm->info.pchBuffer)
847  return send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lOffset, iOrigin, FALSE);
848 
849  switch (iOrigin) {
850  case SEEK_SET:
851  offset = lOffset;
852  break;
853  case SEEK_CUR:
854  offset = wm->info.lBufOffset + (wm->info.pchNext - wm->info.pchBuffer) + lOffset;
855  break;
856  case SEEK_END:
857  offset = ((wm->info.fccIOProc == FOURCC_MEM)? wm->info.cchBuffer : wm->dwFileSize) - lOffset;
858  break;
859  default:
860  return -1;
861  }
862 
863  if (offset && offset >= wm->dwFileSize && wm->info.fccIOProc != FOURCC_MEM) {
864  /* should check that write mode exists */
865  if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
866  return -1;
867  wm->info.lBufOffset = offset;
868  wm->info.pchEndRead = wm->info.pchBuffer;
869  wm->info.pchEndWrite = wm->info.pchBuffer + wm->info.cchBuffer;
870  if ((wm->info.dwFlags & MMIO_RWMODE) == MMIO_READ) {
871  wm->info.lDiskOffset = wm->dwFileSize;
872  }
873  } else if ((wm->info.cchBuffer > 0) &&
874  ((offset < wm->info.lBufOffset) ||
875  (offset >= wm->info.lBufOffset + wm->info.cchBuffer) ||
876  !wm->bBufferLoaded)) {
877  /* stay in same buffer ? */
878  /* some memory mapped buffers are defined with -1 as a size */
879 
880  /* condition to change buffer */
881  if ((wm->info.fccIOProc == FOURCC_MEM) ||
882  MMIO_Flush(wm, 0) != MMSYSERR_NOERROR ||
883  /* this also sets the wm->info.lDiskOffset field */
884  send_message(wm->ioProc, &wm->info, MMIOM_SEEK,
885  (offset / wm->info.cchBuffer) * wm->info.cchBuffer,
886  SEEK_SET, FALSE) == -1)
887  return -1;
889  }
890 
891  wm->info.pchNext = wm->info.pchBuffer + (offset - wm->info.lBufOffset);
892 
893  TRACE("=> %d\n", offset);
894  return offset;
895 }
896 
897 /**************************************************************************
898  * mmioGetInfo [WINMM.@]
899  */
900 MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
901 {
902  LPWINE_MMIO wm;
903 
904  TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
905 
906  if ((wm = MMIO_Get(hmmio)) == NULL)
907  return MMSYSERR_INVALHANDLE;
908 
909  *lpmmioinfo = wm->info;
910 
911  return MMSYSERR_NOERROR;
912 }
913 
914 /**************************************************************************
915  * mmioSetInfo [WINMM.@]
916  */
917 MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO* lpmmioinfo, UINT uFlags)
918 {
919  LPWINE_MMIO wm;
920 
921  TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
922 
923  if ((wm = MMIO_Get(hmmio)) == NULL)
924  return MMSYSERR_INVALHANDLE;
925 
926  /* check pointers coherence */
927  if (lpmmioinfo->pchNext < wm->info.pchBuffer ||
928  lpmmioinfo->pchNext > wm->info.pchBuffer + wm->info.cchBuffer ||
929  lpmmioinfo->pchEndRead < wm->info.pchBuffer ||
930  lpmmioinfo->pchEndRead > wm->info.pchBuffer + wm->info.cchBuffer ||
931  lpmmioinfo->pchEndWrite < wm->info.pchBuffer ||
932  lpmmioinfo->pchEndWrite > wm->info.pchBuffer + wm->info.cchBuffer)
933  return MMSYSERR_INVALPARAM;
934 
935  wm->info.pchNext = lpmmioinfo->pchNext;
936  wm->info.pchEndRead = lpmmioinfo->pchEndRead;
937 
938  return MMSYSERR_NOERROR;
939 }
940 
941 /**************************************************************************
942 * mmioSetBuffer [WINMM.@]
943 */
945 {
946  LPWINE_MMIO wm;
947 
948  TRACE("(hmmio=%p, pchBuf=%p, cchBuf=%d, uFlags=%#08x)\n",
949  hmmio, pchBuffer, cchBuffer, uFlags);
950 
951  if ((wm = MMIO_Get(hmmio)) == NULL)
952  return MMSYSERR_INVALHANDLE;
953 
954  return MMIO_SetBuffer(wm, pchBuffer, cchBuffer, uFlags);
955 }
956 
957 /**************************************************************************
958  * mmioFlush [WINMM.@]
959  */
961 {
962  LPWINE_MMIO wm;
963 
964  TRACE("(%p, %04X)\n", hmmio, uFlags);
965 
966  if ((wm = MMIO_Get(hmmio)) == NULL)
967  return MMSYSERR_INVALHANDLE;
968 
969  return MMIO_Flush(wm, uFlags);
970 }
971 
972 /**************************************************************************
973  * mmioAdvance [WINMM.@]
974  */
975 MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
976 {
977  LPWINE_MMIO wm;
978 
979  TRACE("hmmio=%p, lpmmioinfo=%p, uFlags=%04X\n", hmmio, lpmmioinfo, uFlags);
980 
981  /* NOTE: mmioAdvance16 heavily relies on parameters from lpmmioinfo we're using
982  * here. be sure if you change something here to check mmioAdvance16 as well
983  */
984  if ((wm = MMIO_Get(hmmio)) == NULL)
985  return MMSYSERR_INVALHANDLE;
986 
987  if (!wm->info.cchBuffer)
988  return MMIOERR_UNBUFFERED;
989 
990  if (uFlags != MMIO_READ && uFlags != MMIO_WRITE)
991  return MMSYSERR_INVALPARAM;
992 
993  if (uFlags == MMIO_WRITE && (lpmmioinfo->dwFlags & MMIO_DIRTY))
994  {
995  send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lpmmioinfo->lBufOffset, SEEK_SET, FALSE);
996  send_message(wm->ioProc, &wm->info, MMIOM_WRITE, (LPARAM)lpmmioinfo->pchBuffer,
997  lpmmioinfo->pchNext - lpmmioinfo->pchBuffer, FALSE);
998  lpmmioinfo->dwFlags &= ~MMIO_DIRTY;
999  }
1000  if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
1001  return MMIOERR_CANNOTWRITE;
1002 
1003  if (lpmmioinfo) {
1004  wm->dwFileSize = max(wm->dwFileSize, lpmmioinfo->lBufOffset +
1005  (lpmmioinfo->pchNext - lpmmioinfo->pchBuffer));
1006  }
1008 
1009  if (lpmmioinfo) {
1010  lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
1011  lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
1012  (wm->info.pchEndRead - wm->info.pchBuffer);
1013  lpmmioinfo->pchEndWrite = lpmmioinfo->pchBuffer +
1014  (wm->info.pchEndWrite - wm->info.pchBuffer);
1015  lpmmioinfo->lDiskOffset = wm->info.lDiskOffset;
1016  lpmmioinfo->lBufOffset = wm->info.lBufOffset;
1017  }
1018  return MMSYSERR_NOERROR;
1019 }
1020 
1021 /**************************************************************************
1022  * mmioStringToFOURCCA [WINMM.@]
1023  */
1025 {
1026  CHAR cc[4];
1027  int i = 0;
1028 
1029  for (i = 0; i < 4 && sz[i]; i++) {
1030  if (uFlags & MMIO_TOUPPER) {
1031  cc[i] = toupper(sz[i]);
1032  } else {
1033  cc[i] = sz[i];
1034  }
1035  }
1036 
1037  /* Pad with spaces */
1038  while (i < 4) cc[i++] = ' ';
1039 
1040  TRACE("Got '%.4s'\n",cc);
1041  return mmioFOURCC(cc[0],cc[1],cc[2],cc[3]);
1042 }
1043 
1044 /**************************************************************************
1045  * mmioStringToFOURCCW [WINMM.@]
1046  */
1048 {
1049  char szA[4];
1050 
1051  WideCharToMultiByte( CP_ACP, 0, sz, 4, szA, sizeof(szA), NULL, NULL );
1052  return mmioStringToFOURCCA(szA,uFlags);
1053 }
1054 
1055 /**************************************************************************
1056  * mmioInstallIOProcA [WINMM.@]
1057  */
1060 {
1061  return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, FALSE);
1062 }
1063 
1064 /**************************************************************************
1065  * mmioInstallIOProcW [WINMM.@]
1066  */
1069 {
1070  return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, TRUE);
1071 }
1072 
1073 /******************************************************************
1074  * MMIO_SendMessage
1075  *
1076  *
1077  */
1078 static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1,
1079  LPARAM lParam2, BOOL is_unicode)
1080 {
1081  LPWINE_MMIO wm;
1082 
1083  TRACE("(%p, %u, %ld, %ld, %s)\n", hmmio, uMessage, lParam1, lParam2, is_unicode ? "unicode" : "ansi");
1084 
1085  if (uMessage < MMIOM_USER)
1086  return MMSYSERR_INVALPARAM;
1087 
1088  if ((wm = MMIO_Get(hmmio)) == NULL)
1089  return MMSYSERR_INVALHANDLE;
1090 
1091  return send_message(wm->ioProc, &wm->info, uMessage, lParam1, lParam2, is_unicode);
1092 }
1093 
1094 /**************************************************************************
1095  * mmioSendMessage [WINMM.@]
1096  */
1097 LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage,
1098  LPARAM lParam1, LPARAM lParam2)
1099 {
1100  return MMIO_SendMessage(hmmio, uMessage, lParam1, lParam2, FALSE);
1101 }
1102 
1103 /**************************************************************************
1104  * mmioDescend [WINMM.@]
1105  */
1107  const MMCKINFO* lpckParent, UINT uFlags)
1108 {
1109  DWORD dwOldPos;
1110  FOURCC srchCkId;
1111  FOURCC srchType;
1112 
1113  TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags);
1114 
1115  if (lpck == NULL)
1116  return MMSYSERR_INVALPARAM;
1117 
1118  dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1119  TRACE("dwOldPos=%d\n", dwOldPos);
1120 
1121  if (lpckParent != NULL) {
1122  TRACE("seek inside parent at %d !\n", lpckParent->dwDataOffset);
1123  /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
1124  if (dwOldPos < lpckParent->dwDataOffset ||
1125  dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) {
1126  WARN("outside parent chunk\n");
1127  return MMIOERR_CHUNKNOTFOUND;
1128  }
1129  }
1130 
1131  /* The SDK docu says 'ckid' is used for all cases. Real World
1132  * examples disagree -Marcus,990216.
1133  */
1134 
1135  srchCkId = 0;
1136  srchType = 0;
1137 
1138  /* find_chunk looks for 'ckid' */
1139  if (uFlags & MMIO_FINDCHUNK)
1140  srchCkId = lpck->ckid;
1141 
1142  /* find_riff and find_list look for 'fccType' */
1143  if (uFlags & MMIO_FINDLIST)
1144  {
1145  srchCkId = FOURCC_LIST;
1146  srchType = lpck->fccType;
1147  }
1148 
1149  if (uFlags & MMIO_FINDRIFF)
1150  {
1151  srchCkId = FOURCC_RIFF;
1152  srchType = lpck->fccType;
1153  }
1154 
1155  TRACE("searching for %4.4s.%4.4s\n",
1156  (LPCSTR)&srchCkId, srchType ? (LPCSTR)&srchType : "any");
1157 
1158  while (TRUE)
1159  {
1160  LONG ix;
1161 
1162  ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
1163  if (ix < 2*sizeof(DWORD))
1164  {
1165  mmioSeek(hmmio, dwOldPos, SEEK_SET);
1166  WARN("return ChunkNotFound\n");
1167  return MMIOERR_CHUNKNOTFOUND;
1168  }
1169 
1170  lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
1171  TRACE("ckid=%4.4s fcc=%4.4s cksize=%08X !\n",
1172  (LPCSTR)&lpck->ckid,
1173  srchType ? (LPCSTR)&lpck->fccType:"<na>",
1174  lpck->cksize);
1175  if ( (!srchCkId || (srchCkId == lpck->ckid)) &&
1176  (!srchType || (srchType == lpck->fccType)) )
1177  break;
1178 
1179  dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1);
1180  mmioSeek(hmmio, dwOldPos, SEEK_SET);
1181  }
1182 
1183  lpck->dwFlags = 0;
1184  /* If we were looking for RIFF/LIST chunks, the final file position
1185  * is after the chunkid. If we were just looking for the chunk
1186  * it is after the cksize. So add 4 in RIFF/LIST case.
1187  */
1188  if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1189  mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET);
1190  else
1191  {
1192  mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
1193  lpck->fccType = 0;
1194  }
1195  TRACE("lpck: ckid=%.4s, cksize=%d, dwDataOffset=%d fccType=%08X (%.4s)!\n",
1196  (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset,
1197  lpck->fccType, srchType?(LPSTR)&lpck->fccType:"");
1198  return MMSYSERR_NOERROR;
1199 }
1200 
1201 /**************************************************************************
1202  * mmioAscend [WINMM.@]
1203  */
1205 {
1206  TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
1207 
1208  if (lpck->dwFlags & MMIO_DIRTY) {
1209  DWORD dwOldPos, dwNewSize;
1210 
1211  TRACE("Chunk is dirty, checking if chunk's size is correct\n");
1212  dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1213  TRACE("dwOldPos=%d lpck->dwDataOffset = %d\n", dwOldPos, lpck->dwDataOffset);
1214  dwNewSize = dwOldPos - lpck->dwDataOffset;
1215  if (dwNewSize != lpck->cksize) {
1216  TRACE("Nope: lpck->cksize=%d dwNewSize=%d\n", lpck->cksize, dwNewSize);
1217  lpck->cksize = dwNewSize;
1218 
1219  /* pad odd size with 0 */
1220  if (dwNewSize & 1) {
1221  char ch = 0;
1222  mmioWrite(hmmio, &ch, 1);
1223  }
1224  mmioSeek(hmmio, lpck->dwDataOffset - sizeof(DWORD), SEEK_SET);
1225  mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
1226  }
1227  lpck->dwFlags = 0;
1228  }
1229 
1230  mmioSeek(hmmio, lpck->dwDataOffset + ((lpck->cksize + 1) & ~1), SEEK_SET);
1231 
1232  return MMSYSERR_NOERROR;
1233 }
1234 
1235 /**************************************************************************
1236  * mmioCreateChunk [WINMM.@]
1237  */
1239 {
1240  DWORD dwOldPos;
1241  LONG size;
1242  LONG ix;
1243 
1244  TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
1245 
1246  dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
1247  TRACE("dwOldPos=%d\n", dwOldPos);
1248 
1249  if (uFlags == MMIO_CREATELIST)
1250  lpck->ckid = FOURCC_LIST;
1251  else if (uFlags == MMIO_CREATERIFF)
1252  lpck->ckid = FOURCC_RIFF;
1253 
1254  TRACE("ckid=%.4s\n", (LPSTR)&lpck->ckid);
1255 
1256  size = 2 * sizeof(DWORD);
1257  lpck->dwDataOffset = dwOldPos + size;
1258 
1259  if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
1260  size += sizeof(DWORD);
1261  lpck->dwFlags = MMIO_DIRTY;
1262 
1263  ix = mmioWrite(hmmio, (LPSTR)lpck, size);
1264  TRACE("after mmioWrite ix = %d req = %d, errno = %d\n", ix, size, errno);
1265  if (ix < size) {
1266  mmioSeek(hmmio, dwOldPos, SEEK_SET);
1267  WARN("return CannotWrite\n");
1268  return MMIOERR_CANNOTWRITE;
1269  }
1270 
1271  return MMSYSERR_NOERROR;
1272 }
1273 
1274 /**************************************************************************
1275  * mmioRenameA [WINMM.@]
1276  */
1277 MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName,
1278  const MMIOINFO* lpmmioinfo, DWORD dwFlags)
1279 {
1280  struct IOProcList* ioProc = NULL;
1281  struct IOProcList tmp;
1282  FOURCC fcc;
1283 
1284  TRACE("('%s', '%s', %p, %08X);\n",
1285  debugstr_a(szFileName), debugstr_a(szNewFileName), lpmmioinfo, dwFlags);
1286 
1287  /* If both params are NULL, then parse the file name */
1288  if (lpmmioinfo && lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)
1289  {
1290  fcc = MMIO_ParseExtA(szFileName);
1291  if (fcc) ioProc = MMIO_FindProcNode(fcc);
1292  }
1293 
1294  /* Handle any unhandled/error case from above. Assume DOS file */
1295  if (!lpmmioinfo || (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL && ioProc == NULL))
1296  ioProc = MMIO_FindProcNode(FOURCC_DOS);
1297  /* if just the four character code is present, look up IO proc */
1298  else if (lpmmioinfo->pIOProc == NULL)
1299  ioProc = MMIO_FindProcNode(lpmmioinfo->fccIOProc);
1300  else /* use relevant ioProc */
1301  {
1302  ioProc = &tmp;
1303  tmp.fourCC = lpmmioinfo->fccIOProc;
1304  tmp.pIOProc = lpmmioinfo->pIOProc;
1305  tmp.is_unicode = FALSE;
1306  tmp.count = 1;
1307  }
1308 
1309  /* FIXME: should we actually pass lpmmioinfo down the drain ???
1310  * or make a copy of it because it's const ???
1311  */
1312  return send_message(ioProc, (MMIOINFO*)lpmmioinfo, MMIOM_RENAME,
1313  (LPARAM)szFileName, (LPARAM)szNewFileName, FALSE);
1314 }
1315 
1316 /**************************************************************************
1317  * mmioRenameW [WINMM.@]
1318  */
1319 MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName,
1320  const MMIOINFO* lpmmioinfo, DWORD dwFlags)
1321 {
1322  LPSTR szFn = NULL;
1323  LPSTR sznFn = NULL;
1325  INT len;
1326 
1327  if (szFileName)
1328  {
1329  len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
1330  szFn = HeapAlloc( GetProcessHeap(), 0, len );
1331  if (!szFn) goto done;
1332  WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
1333  }
1334  if (szNewFileName)
1335  {
1336  len = WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, NULL, 0, NULL, NULL );
1337  sznFn = HeapAlloc( GetProcessHeap(), 0, len );
1338  if (!sznFn) goto done;
1339  WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, sznFn, len, NULL, NULL );
1340  }
1341 
1342  ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwFlags);
1343 
1344 done:
1345  HeapFree(GetProcessHeap(),0,szFn);
1346  HeapFree(GetProcessHeap(),0,sznFn);
1347  return ret;
1348 }
#define FOURCC_DOS
Definition: mmsystem.h:566
LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
Definition: mmio.c:1058
#define MMIO_ALLOCBUF
Definition: mmsystem.h:532
struct IOProcList * ioProc
Definition: winemm.h:145
MMRESULT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:960
#define SEEK_CUR
Definition: util.h:63
HMMIO hmmio
Definition: mmsystem.h:1501
#define max(a, b)
Definition: svc.c:63
LPMMIOPROC pIOProc
Definition: mmsystem.h:1488
#define TRUE
Definition: types.h:120
FOURCC fccIOProc
Definition: mmsystem.h:1487
#define MMIO_RWMODE
Definition: mmsystem.h:526
LPMMIOPROC WINAPI mmioInstallIOProcW(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags)
Definition: mmio.c:1067
HPSTR pchNext
Definition: mmsystem.h:1493
MMIOPROC * LPMMIOPROC
Definition: mmsystem.h:1483
LONG cchBuffer
Definition: mmsystem.h:1491
#define WideCharToMultiByte
Definition: compat.h:101
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
LONG WINAPI _llseek(HFILE hFile, LONG lOffset, int iOrigin)
Definition: lfile.c:149
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
unsigned bBufferLoaded
Definition: winemm.h:146
BOOL is_unicode
Definition: winemm.h:138
#define error1(s, a)
Definition: debug.h:109
#define MMIO_CREATELIST
Definition: mmsystem.h:555
#define MMIOERR_CANNOTWRITE
Definition: mmsystem.h:514
#define CP_ACP
Definition: compat.h:99
GLuint GLuint GLsizei count
Definition: gl.h:1545
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
Definition: mmio.c:1204
char CHAR
Definition: xmlstorage.h:175
DWORD dwFileSize
Definition: winemm.h:148
static LPWINE_MMIO MMIO_Create(void)
Definition: mmio.c:431
#define WARN(fmt,...)
Definition: debug.h:111
#define MMIOM_READ
Definition: mmsystem.h:556
DWORD dwDataOffset
Definition: mmsystem.h:1510
FOURCC fourCC
Definition: winemm.h:136
GLintptr offset
Definition: glext.h:5920
#define CALLBACK
Definition: compat.h:27
static MMRESULT MMIO_Flush(WINE_MMIO *wm, UINT uFlags)
Definition: mmio.c:475
static LONG MMIO_GrabNextBuffer(LPWINE_MMIO wm, int for_read)
Definition: mmio.c:497
int count
Definition: winemm.h:139
BOOL WINAPI MoveFileA(IN LPCSTR lpExistingFileName, IN LPCSTR lpNewFileName)
Definition: move.c:1077
#define MMIOM_WRITE
Definition: mmsystem.h:557
#define assert(x)
Definition: debug.h:53
UINT MMRESULT
Definition: mmsystem.h:962
MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags)
Definition: mmio.c:701
GLuint buffer
Definition: glext.h:5915
HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:669
#define MMSYSERR_INVALHANDLE
Definition: mmsystem.h:101
int errno
static LRESULT CALLBACK mmioMemIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:142
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
#define MMIOERR_FILENOTFOUND
Definition: mmsystem.h:509
UINT uFlags
Definition: api.c:60
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
static WINE_MMIO * MMIOList
Definition: mmio.c:34
char * LPSTR
Definition: xmlstorage.h:182
unsigned bTmpIOProc
Definition: winemm.h:146
DWORD adwInfo[3]
Definition: mmsystem.h:1498
HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO *lpmmioinfo, DWORD dwOpenFlags)
Definition: mmio.c:692
#define DWORD
Definition: nt_native.h:44
int32_t INT
Definition: typedefs.h:56
LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin)
Definition: mmio.c:835
struct IOProcList * pNext
Definition: winemm.h:135
DWORD dwFlags
Definition: mmsystem.h:1511
int WINAPI _lclose(HFILE hFile)
Definition: lfile.c:138
#define pch(ap)
Definition: match.c:418
const GLfloat * m
Definition: glext.h:10848
FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR sz, UINT uFlags)
Definition: mmio.c:1047
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
#define MMIO_FHOPEN
Definition: mmsystem.h:543
uint32_t ULONG_PTR
Definition: typedefs.h:63
DWORD WINAPI GetFullPathNameA(IN LPCSTR lpFileName, IN DWORD nBufferLength, OUT LPSTR lpBuffer, OUT LPSTR *lpFilePart)
Definition: path.c:992
#define MMIO_DEFAULTBUFFER
Definition: mmsystem.h:568
LPMMIOPROC pIOProc
Definition: winemm.h:137
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
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
#define HFILE_ERROR
Definition: winbase.h:111
LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:1097
static BOOL MMIO_Destroy(LPWINE_MMIO wm)
Definition: mmio.c:454
unsigned int BOOL
Definition: ntddk_ex.h:94
static FOURCC MMIO_ParseExtA(LPCSTR szFileName)
Definition: mmio.c:361
long LONG
Definition: pedump.c:60
long WINAPI _hwrite(HFILE hFile, LPCSTR lpBuffer, long lBytes)
Definition: lfile.c:41
DWORD WINAPI GetFileAttributesA(LPCSTR lpFileName)
Definition: fileinfo.c:786
UINT WINAPI _lread(_In_ HFILE hFile, _Out_writes_bytes_to_(uBytes, return) LPVOID lpBuffer, _In_ UINT uBytes)
static DWORD cchBuffer
Definition: fusion.c:83
#define FIXME(fmt,...)
Definition: debug.h:110
LONG lDiskOffset
Definition: mmsystem.h:1497
LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
Definition: mmio.c:781
#define MMIO_GLOBALPROC
Definition: mmsystem.h:547
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:201
smooth NULL
Definition: ftsmooth.c:416
#define MMIOERR_UNBUFFERED
Definition: mmsystem.h:518
char ext[3]
Definition: mkdosfs.c:358
LONG_PTR LPARAM
Definition: windef.h:208
#define MMIO_FINDCHUNK
Definition: mmsystem.h:551
FOURCC fccType
Definition: mmsystem.h:1509
MMIOINFO info
Definition: winemm.h:143
const char * LPCSTR
Definition: xmlstorage.h:183
#define MMIO_INSTALLPROC
Definition: mmsystem.h:546
#define error2(s, a, b)
Definition: debug.h:110
#define MMIO_REMOVEPROC
Definition: mmsystem.h:548
#define MMIO_READ
Definition: mmsystem.h:535
FOURCC WINAPI mmioStringToFOURCCA(LPCSTR sz, UINT uFlags)
Definition: mmio.c:1024
#define MMIOM_USER
Definition: mmsystem.h:563
HFILE WINAPI OpenFile(LPCSTR lpFileName, LPOFSTRUCT lpReOpenBuff, UINT uStyle)
Definition: create.c:368
#define SEEK_SET
Definition: jmemansi.c:26
#define MMIO_DIRTY
Definition: mmsystem.h:534
int toupper(int c)
Definition: utclib.c:881
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HPSTR pchBuffer
Definition: mmsystem.h:1492
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:395
#define FOURCC_LIST
Definition: mmsystem.h:565
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define MMSYSERR_ERROR
Definition: mmsystem.h:97
CRITICAL_SECTION WINMM_cs
Definition: winmm.c:54
#define debugstr_a
Definition: kernel32.h:31
LONG lBufOffset
Definition: mmsystem.h:1496
#define MMIOERR_OUTOFMEMORY
Definition: mmsystem.h:510
#define MAX_PATH
Definition: compat.h:26
WINE_DEFAULT_DEBUG_CHANNEL(mmio)
#define WINAPI
Definition: msvc.h:8
static LPMMIOPROC MMIO_InstallIOProc(FOURCC fccIOProc, LPMMIOPROC pIOProc, DWORD dwFlags, BOOL is_unicode)
Definition: mmio.c:242
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD WINAPI GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh)
Definition: fileinfo.c:481
DWORD cksize
Definition: mmsystem.h:1508
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
static LPWINE_MMIO MMIO_Get(HMMIO h)
Definition: mmio.c:413
HPSTR pchEndWrite
Definition: mmsystem.h:1495
#define MMIO_EMPTYBUF
Definition: mmsystem.h:544
int ret
char * HPSTR
Definition: mmsystem.h:1477
#define FOURCC_RIFF
Definition: mmsystem.h:564
#define MMIOM_CLOSE
Definition: mmsystem.h:560
MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO *lpck, UINT uFlags)
Definition: mmio.c:1238
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define mmioFOURCC(c0, c1, c2, c3)
Definition: mmsystem.h:38
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName, const MMIOINFO *lpmmioinfo, DWORD dwFlags)
Definition: mmio.c:1277
GLenum GLsizei len
Definition: glext.h:6722
DWORD dwFlags
Definition: mmsystem.h:1486
DWORD FOURCC
Definition: dmdls.h:25
#define MMIO_CREATERIFF
Definition: mmsystem.h:554
#define MMIOM_WRITEFLUSH
Definition: mmsystem.h:561
static struct IOProcList * pIOProcListAnchor
Definition: mmio.c:220
#define ERR(fmt,...)
Definition: debug.h:109
uint32_t cc
Definition: isohybrid.c:75
MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:975
#define MMIOM_OPEN
Definition: mmsystem.h:559
UINT wErrorRet
Definition: mmsystem.h:1489
MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:900
FOURCC ckid
Definition: mmsystem.h:1507
#define MMSYSERR_INVALPARAM
Definition: mmsystem.h:107
#define MMIO_GETTEMP
Definition: mmsystem.h:533
#define MMIO_TOUPPER
Definition: mmsystem.h:545
#define MMIOERR_CHUNKNOTFOUND
Definition: mmsystem.h:517
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, const MMCKINFO *lpckParent, UINT uFlags)
Definition: mmio.c:1106
struct tagWINE_MMIO * lpNext
Definition: winemm.h:144
static struct IOProcList * MMIO_FindProcNode(FOURCC fccIOProc)
Definition: mmio.c:227
#define MMIO_FINDPROC
Definition: mmsystem.h:550
MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO *lpmmioinfo, UINT uFlags)
Definition: mmio.c:917
static HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO *refmminfo, DWORD dwOpenFlags, BOOL is_unicode)
Definition: mmio.c:567
HPSTR pchEndRead
Definition: mmsystem.h:1494
#define MMIO_EXIST
Definition: mmsystem.h:531
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
#define FOURCC_MEM
Definition: mmsystem.h:567
#define MMIO_PARSE
Definition: mmsystem.h:529
#define lstrcpynA
Definition: compat.h:408
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
MMRESULT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT uFlags)
Definition: mmio.c:944
char * strchr(const char *String, int ch)
Definition: utclib.c:501
MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName, const MMIOINFO *lpmmioinfo, DWORD dwFlags)
Definition: mmio.c:1319
#define MMIO_FINDRIFF
Definition: mmsystem.h:552
#define MMIOERR_CANNOTOPEN
Definition: mmsystem.h:511
#define MMIOM_SEEK
Definition: mmsystem.h:558
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define SEEK_END
Definition: cabinet.c:27
static LRESULT send_message(struct IOProcList *ioProc, LPMMIOINFO mmioinfo, DWORD wMsg, LPARAM lParam1, LPARAM lParam2, BOOL is_unicode)
Definition: mmio.c:326
static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, LPARAM lParam2, BOOL is_unicode)
Definition: mmio.c:1078
#define MMIOM_RENAME
Definition: mmsystem.h:562
#define MMIO_CREATE
Definition: mmsystem.h:528
static MMRESULT MMIO_SetBuffer(WINE_MMIO *wm, void *pchBuffer, LONG cchBuffer, UINT uFlags)
Definition: mmio.c:526
#define MMIO_FINDLIST
Definition: mmsystem.h:553
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static LRESULT CALLBACK mmioDosIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, LPARAM lParam1, LPARAM lParam2)
Definition: mmio.c:39
WCHAR * LPWSTR
Definition: xmlstorage.h:184
LONG_PTR LRESULT
Definition: windef.h:209
#define MMIO_WRITE
Definition: mmsystem.h:536
GLuint64EXT * result
Definition: glext.h:11304
int HFILE
Definition: windef.h:283
#define HeapFree(x, y, z)
Definition: compat.h:394
static struct IOProcList defaultProcs[]
Definition: mmio.c:215
LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
Definition: mmio.c:732