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