2 * MMSYSTEM mmio* functions
4 * Copyright 1993 Martin Ayotte
5 * 1998-2003,2009 Eric Pouech
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
34 #include "wine/winuser16.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mmsys
);
41 /* ###################################################
43 * ###################################################
46 #define MMIO_MAX_THUNKS 32
48 static struct mmio_thunk
50 BYTE popl_eax
; /* popl %eax (return address) */
51 BYTE pushl_func
; /* pushl $pfn16 (16bit callback function) */
53 BYTE pushl_eax
; /* pushl %eax */
54 BYTE jmp
; /* ljmp MMIO_Callback1632 */
56 HMMIO hMmio
; /* Handle to 32bit mmio object */
57 SEGPTR segbuffer
; /* actual segmented ptr to buffer */
62 static CRITICAL_SECTION mmio_cs
;
63 static CRITICAL_SECTION_DEBUG mmio_critsect_debug
=
66 { &mmio_critsect_debug
.ProcessLocksList
, &mmio_critsect_debug
.ProcessLocksList
},
67 0, 0, { (DWORD_PTR
)(__FILE__
": mmsystem_mmio_cs") }
69 static CRITICAL_SECTION mmio_cs
= { &mmio_critsect_debug
, -1, 0, 0, 0, 0 };
71 /****************************************************************
72 * MMIO_Map32To16 [INTERNAL]
74 static LRESULT
MMIO_Map32To16(DWORD wMsg
, LPARAM
* lp1
, LPARAM
* lp2
)
84 case MMIOM_WRITEFLUSH
:
85 *lp1
= MapLS( (void *)*lp1
);
88 *lp1
= MapLS( (void *)*lp1
);
89 *lp2
= MapLS( (void *)*lp2
);
92 if (wMsg
< MMIOM_USER
)
93 TRACE("Not a mappable message (%d)\n", wMsg
);
95 return MMSYSERR_NOERROR
;
98 /****************************************************************
99 * MMIO_UnMap32To16 [INTERNAL]
101 static LRESULT
MMIO_UnMap32To16(DWORD wMsg
, LPARAM lParam1
, LPARAM lParam2
,
102 LPARAM lp1
, LPARAM lp2
)
112 case MMIOM_WRITEFLUSH
:
120 if (wMsg
< MMIOM_USER
)
121 TRACE("Not a mappable message (%d)\n", wMsg
);
123 return MMSYSERR_NOERROR
;
126 /******************************************************************
131 static LRESULT
MMIO_Callback3216(SEGPTR cb16
, LPMMIOINFO lpmmioinfo
, UINT uMessage
,
132 LPARAM lParam1
, LPARAM lParam2
)
135 MMIOINFO16 mmioInfo16
;
136 SEGPTR segmmioInfo16
;
137 LPARAM lp1
= lParam1
, lp2
= lParam2
;
140 if (!cb16
) return MMSYSERR_INVALPARAM
;
142 memset(&mmioInfo16
, 0, sizeof(MMIOINFO16
));
143 mmioInfo16
.lDiskOffset
= lpmmioinfo
->lDiskOffset
;
144 mmioInfo16
.adwInfo
[0] = lpmmioinfo
->adwInfo
[0];
145 mmioInfo16
.adwInfo
[1] = lpmmioinfo
->adwInfo
[1];
146 mmioInfo16
.adwInfo
[2] = lpmmioinfo
->adwInfo
[2];
147 /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */
148 if ((result
= MMIO_Map32To16(uMessage
, &lp1
, &lp2
)) != MMSYSERR_NOERROR
)
151 segmmioInfo16
= MapLS(&mmioInfo16
);
152 args
[6] = HIWORD(segmmioInfo16
);
153 args
[5] = LOWORD(segmmioInfo16
);
155 args
[3] = HIWORD(lp1
);
156 args
[2] = LOWORD(lp1
);
157 args
[1] = HIWORD(lp2
);
158 args
[0] = LOWORD(lp2
);
159 WOWCallback16Ex( cb16
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
160 UnMapLS(segmmioInfo16
);
161 MMIO_UnMap32To16(uMessage
, lParam1
, lParam2
, lp1
, lp2
);
163 lpmmioinfo
->lDiskOffset
= mmioInfo16
.lDiskOffset
;
164 lpmmioinfo
->adwInfo
[0] = mmioInfo16
.adwInfo
[0];
165 lpmmioinfo
->adwInfo
[1] = mmioInfo16
.adwInfo
[1];
166 lpmmioinfo
->adwInfo
[2] = mmioInfo16
.adwInfo
[2];
171 /******************************************************************
175 static struct mmio_thunk
* MMIO_AddThunk(LPMMIOPROC16 pfn16
, HPSTR segbuf
)
177 struct mmio_thunk
* thunk
;
181 MMIO_Thunks
= VirtualAlloc(NULL
, MMIO_MAX_THUNKS
* sizeof(*MMIO_Thunks
), MEM_COMMIT
,
182 PAGE_EXECUTE_READWRITE
);
183 if (!MMIO_Thunks
) return NULL
;
184 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
186 thunk
->popl_eax
= 0x58; /* popl %eax */
187 thunk
->pushl_func
= 0x68; /* pushl $pfn16 */
189 thunk
->pushl_eax
= 0x50; /* pushl %eax */
190 thunk
->jmp
= 0xe9; /* jmp MMIO_Callback3216 */
191 thunk
->callback
= (char *)MMIO_Callback3216
- (char *)(&thunk
->callback
+ 1);
193 thunk
->segbuffer
= 0;
196 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
198 if (thunk
->pfn16
== 0 && thunk
->hMmio
== NULL
)
200 thunk
->pfn16
= pfn16
;
202 thunk
->segbuffer
= (SEGPTR
)segbuf
;
206 FIXME("Out of mmio-thunks. Bump MMIO_MAX_THUNKS\n");
210 /******************************************************************
214 static struct mmio_thunk
* MMIO_HasThunk(HMMIO hmmio
)
216 struct mmio_thunk
* thunk
;
218 if (!MMIO_Thunks
) return NULL
;
219 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
221 if (thunk
->hMmio
== hmmio
) return thunk
;
226 /******************************************************************
227 * MMIO_SetSegmentedBuffer
230 static void MMIO_SetSegmentedBuffer(struct mmio_thunk
* thunk
, SEGPTR ptr
, BOOL release
)
232 if (release
) UnMapLS(thunk
->segbuffer
);
233 thunk
->segbuffer
= ptr
;
236 /**************************************************************************
237 * mmioOpen [MMSYSTEM.1210]
239 HMMIO16 WINAPI
mmioOpen16(LPSTR szFileName
, MMIOINFO16
* lpmmioinfo16
,
246 struct mmio_thunk
* thunk
= NULL
;
248 memset(&mmioinfo
, 0, sizeof(mmioinfo
));
250 EnterCriticalSection(&mmio_cs
);
251 if (lpmmioinfo16
->pIOProc
&& !(thunk
= MMIO_AddThunk(lpmmioinfo16
->pIOProc
, lpmmioinfo16
->pchBuffer
)))
253 LeaveCriticalSection(&mmio_cs
);
257 mmioinfo
.dwFlags
= lpmmioinfo16
->dwFlags
;
258 mmioinfo
.fccIOProc
= lpmmioinfo16
->fccIOProc
;
259 mmioinfo
.pIOProc
= (LPMMIOPROC
)thunk
;
260 mmioinfo
.cchBuffer
= lpmmioinfo16
->cchBuffer
;
261 mmioinfo
.pchBuffer
= MapSL((DWORD
)lpmmioinfo16
->pchBuffer
);
262 mmioinfo
.adwInfo
[0] = lpmmioinfo16
->adwInfo
[0];
263 /* if we don't have a file name, it's likely a passed open file descriptor */
265 mmioinfo
.adwInfo
[0] = (DWORD
)DosFileHandleToWin32Handle(mmioinfo
.adwInfo
[0]);
266 mmioinfo
.adwInfo
[1] = lpmmioinfo16
->adwInfo
[1];
267 mmioinfo
.adwInfo
[2] = lpmmioinfo16
->adwInfo
[2];
269 ret
= mmioOpenA(szFileName
, &mmioinfo
, dwOpenFlags
);
272 if (!ret
|| (dwOpenFlags
& (MMIO_PARSE
|MMIO_EXIST
)))
277 else thunk
->hMmio
= ret
;
279 LeaveCriticalSection(&mmio_cs
);
281 lpmmioinfo16
->wErrorRet
= mmioinfo
.wErrorRet
;
282 lpmmioinfo16
->hmmio
= HMMIO_16(mmioinfo
.hmmio
);
284 ret
= mmioOpenA(szFileName
, NULL
, dwOpenFlags
);
286 return HMMIO_16(ret
);
289 /**************************************************************************
290 * mmioClose [MMSYSTEM.1211]
292 MMRESULT16 WINAPI
mmioClose16(HMMIO16 hmmio
, UINT16 uFlags
)
296 EnterCriticalSection(&mmio_cs
);
297 ret
= mmioClose(HMMIO_32(hmmio
), uFlags
);
298 if (ret
== MMSYSERR_NOERROR
)
300 struct mmio_thunk
* thunk
;
302 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))))
304 MMIO_SetSegmentedBuffer(thunk
, 0, TRUE
);
309 LeaveCriticalSection(&mmio_cs
);
313 /**************************************************************************
314 * mmioRead [MMSYSTEM.1212]
316 LONG WINAPI
mmioRead16(HMMIO16 hmmio
, HPSTR pch
, LONG cch
)
318 return mmioRead(HMMIO_32(hmmio
), pch
, cch
);
321 /**************************************************************************
322 * mmioWrite [MMSYSTEM.1213]
324 LONG WINAPI
mmioWrite16(HMMIO16 hmmio
, HPCSTR pch
, LONG cch
)
326 return mmioWrite(HMMIO_32(hmmio
),pch
,cch
);
329 /**************************************************************************
330 * mmioSeek [MMSYSTEM.1214]
332 LONG WINAPI
mmioSeek16(HMMIO16 hmmio
, LONG lOffset
, INT16 iOrigin
)
334 return mmioSeek(HMMIO_32(hmmio
), lOffset
, iOrigin
);
337 /**************************************************************************
338 * mmioGetInfo [MMSYSTEM.1215]
340 MMRESULT16 WINAPI
mmioGetInfo16(HMMIO16 hmmio
, MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
344 struct mmio_thunk
* thunk
;
346 TRACE("(0x%04x,%p,0x%08x)\n", hmmio
, lpmmioinfo
, uFlags
);
348 EnterCriticalSection(&mmio_cs
);
349 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))) == NULL
)
351 LeaveCriticalSection(&mmio_cs
);
352 return MMSYSERR_INVALHANDLE
;
355 ret
= mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
356 if (ret
!= MMSYSERR_NOERROR
)
358 LeaveCriticalSection(&mmio_cs
);
362 lpmmioinfo
->dwFlags
= mmioinfo
.dwFlags
;
363 lpmmioinfo
->fccIOProc
= mmioinfo
.fccIOProc
;
364 lpmmioinfo
->pIOProc
= thunk
->pfn16
;
365 lpmmioinfo
->wErrorRet
= mmioinfo
.wErrorRet
;
366 lpmmioinfo
->hTask
= HTASK_16(mmioinfo
.hTask
);
367 lpmmioinfo
->cchBuffer
= mmioinfo
.cchBuffer
;
368 lpmmioinfo
->pchBuffer
= (void*)thunk
->segbuffer
;
369 lpmmioinfo
->pchNext
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchNext
- mmioinfo
.pchBuffer
));
370 lpmmioinfo
->pchEndRead
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchEndRead
- mmioinfo
.pchBuffer
));
371 lpmmioinfo
->pchEndWrite
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchEndWrite
- mmioinfo
.pchBuffer
));
372 lpmmioinfo
->lBufOffset
= mmioinfo
.lBufOffset
;
373 lpmmioinfo
->lDiskOffset
= mmioinfo
.lDiskOffset
;
374 lpmmioinfo
->adwInfo
[0] = mmioinfo
.adwInfo
[0];
375 lpmmioinfo
->adwInfo
[1] = mmioinfo
.adwInfo
[1];
376 lpmmioinfo
->adwInfo
[2] = mmioinfo
.adwInfo
[2];
377 lpmmioinfo
->dwReserved1
= 0;
378 lpmmioinfo
->dwReserved2
= 0;
379 lpmmioinfo
->hmmio
= HMMIO_16(mmioinfo
.hmmio
);
380 LeaveCriticalSection(&mmio_cs
);
382 return MMSYSERR_NOERROR
;
385 /**************************************************************************
386 * mmioSetInfo [MMSYSTEM.1216]
388 MMRESULT16 WINAPI
mmioSetInfo16(HMMIO16 hmmio
, const MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
393 TRACE("(0x%04x,%p,0x%08x)\n",hmmio
,lpmmioinfo
,uFlags
);
395 ret
= mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, 0);
396 if (ret
!= MMSYSERR_NOERROR
) return ret
;
398 /* check if seg and lin buffers are the same */
399 if (mmioinfo
.cchBuffer
!= lpmmioinfo
->cchBuffer
||
400 mmioinfo
.pchBuffer
!= MapSL((DWORD
)lpmmioinfo
->pchBuffer
))
401 return MMSYSERR_INVALPARAM
;
403 /* check pointers coherence */
404 if (lpmmioinfo
->pchNext
< lpmmioinfo
->pchBuffer
||
405 lpmmioinfo
->pchNext
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
||
406 lpmmioinfo
->pchEndRead
< lpmmioinfo
->pchBuffer
||
407 lpmmioinfo
->pchEndRead
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
||
408 lpmmioinfo
->pchEndWrite
< lpmmioinfo
->pchBuffer
||
409 lpmmioinfo
->pchEndWrite
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
)
410 return MMSYSERR_INVALPARAM
;
412 mmioinfo
.pchNext
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchNext
- lpmmioinfo
->pchBuffer
);
413 mmioinfo
.pchEndRead
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchEndRead
- lpmmioinfo
->pchBuffer
);
414 mmioinfo
.pchEndWrite
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchEndWrite
- lpmmioinfo
->pchBuffer
);
416 return mmioSetInfo(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
419 /**************************************************************************
420 * mmioSetBuffer [MMSYSTEM.1217]
422 MMRESULT16 WINAPI
mmioSetBuffer16(HMMIO16 hmmio
, LPSTR pchBuffer
,
423 LONG cchBuffer
, UINT16 uFlags
)
425 MMRESULT ret
= mmioSetBuffer(HMMIO_32(hmmio
), MapSL((DWORD
)pchBuffer
),
428 if (ret
== MMSYSERR_NOERROR
)
430 struct mmio_thunk
* thunk
;
432 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))) == NULL
)
435 return MMSYSERR_INVALHANDLE
;
437 MMIO_SetSegmentedBuffer(thunk
, (DWORD
)pchBuffer
, TRUE
);
440 UnMapLS((DWORD
)pchBuffer
);
444 /**************************************************************************
445 * mmioFlush [MMSYSTEM.1218]
447 MMRESULT16 WINAPI
mmioFlush16(HMMIO16 hmmio
, UINT16 uFlags
)
449 return mmioFlush(HMMIO_32(hmmio
), uFlags
);
452 /***********************************************************************
453 * mmioAdvance [MMSYSTEM.1219]
455 MMRESULT16 WINAPI
mmioAdvance16(HMMIO16 hmmio
, MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
460 /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
465 mmioinfo
.pchBuffer
= MapSL((DWORD
)lpmmioinfo
->pchBuffer
);
466 mmioinfo
.pchNext
= MapSL((DWORD
)lpmmioinfo
->pchNext
);
467 mmioinfo
.dwFlags
= lpmmioinfo
->dwFlags
;
468 mmioinfo
.lBufOffset
= lpmmioinfo
->lBufOffset
;
469 ret
= mmioAdvance(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
472 ret
= mmioAdvance(HMMIO_32(hmmio
), NULL
, uFlags
);
474 if (ret
!= MMSYSERR_NOERROR
) return ret
;
478 lpmmioinfo
->dwFlags
= mmioinfo
.dwFlags
;
479 lpmmioinfo
->pchNext
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchNext
- mmioinfo
.pchBuffer
));
480 lpmmioinfo
->pchEndRead
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchEndRead
- mmioinfo
.pchBuffer
));
481 lpmmioinfo
->pchEndWrite
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchEndWrite
- mmioinfo
.pchBuffer
));
482 lpmmioinfo
->lBufOffset
= mmioinfo
.lBufOffset
;
483 lpmmioinfo
->lDiskOffset
= mmioinfo
.lDiskOffset
;
486 return MMSYSERR_NOERROR
;
489 /**************************************************************************
490 * mmioStringToFOURCC [MMSYSTEM.1220]
492 FOURCC WINAPI
mmioStringToFOURCC16(LPCSTR sz
, UINT16 uFlags
)
494 return mmioStringToFOURCCA(sz
, uFlags
);
497 /**************************************************************************
498 * mmioInstallIOProc [MMSYSTEM.1221]
500 LPMMIOPROC16 WINAPI
mmioInstallIOProc16(FOURCC fccIOProc
, LPMMIOPROC16 pIOProc
,
503 struct mmio_thunk
* thunk
= NULL
;
504 LPMMIOPROC pIOProc32
;
506 EnterCriticalSection(&mmio_cs
);
508 switch (dwFlags
& (MMIO_INSTALLPROC
|MMIO_REMOVEPROC
|MMIO_FINDPROC
)) {
509 case MMIO_INSTALLPROC
:
510 if (!(thunk
= MMIO_AddThunk(pIOProc
, NULL
)))
512 LeaveCriticalSection(&mmio_cs
);
515 if (!mmioInstallIOProcA(fccIOProc
, (LPMMIOPROC
)thunk
, dwFlags
))
521 case MMIO_REMOVEPROC
:
524 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
526 if (thunk
->pfn16
== pIOProc
&& thunk
->segbuffer
== 0)
528 if (mmioInstallIOProcA(fccIOProc
, (LPMMIOPROC
)thunk
, dwFlags
))
536 if (!thunk
) pIOProc
= NULL
;
539 if ((pIOProc32
= mmioInstallIOProcA(fccIOProc
, NULL
, dwFlags
)) && MMIO_Thunks
)
541 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
543 if ((LPMMIOPROC
)thunk
== pIOProc32
)
545 pIOProc
= thunk
->pfn16
;
552 WINE_FIXME("Unsupported flags %08x\n", dwFlags
);
555 LeaveCriticalSection(&mmio_cs
);
560 /**************************************************************************
561 * mmioSendMessage [MMSYSTEM.1222]
563 LRESULT WINAPI
mmioSendMessage16(HMMIO16 hmmio
, UINT16 uMessage
,
564 LPARAM lParam1
, LPARAM lParam2
)
566 struct mmio_thunk
* thunk
;
568 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))))
571 if (mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, 0) == MMSYSERR_NOERROR
)
573 return MMIO_Callback3216((SEGPTR
)thunk
->pfn16
, &mmioinfo
, uMessage
, lParam1
, lParam2
);
575 return MMSYSERR_INVALHANDLE
;
579 /* FIXME: we need to map lParam1 and lParam2 to 32bit entities */
580 return mmioSendMessage(HMMIO_32(hmmio
), uMessage
, lParam1
, lParam2
);
584 /**************************************************************************
585 * mmioDescend [MMSYSTEM.1223]
587 MMRESULT16 WINAPI
mmioDescend16(HMMIO16 hmmio
, LPMMCKINFO lpck
,
588 const MMCKINFO
* lpckParent
, UINT16 uFlags
)
590 return mmioDescend(HMMIO_32(hmmio
), lpck
, lpckParent
, uFlags
);
593 /**************************************************************************
594 * mmioAscend [MMSYSTEM.1224]
596 MMRESULT16 WINAPI
mmioAscend16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
598 return mmioAscend(HMMIO_32(hmmio
),lpck
,uFlags
);
601 /**************************************************************************
602 * mmioCreateChunk [MMSYSTEM.1225]
604 MMRESULT16 WINAPI
mmioCreateChunk16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
606 return mmioCreateChunk(HMMIO_32(hmmio
), lpck
, uFlags
);
609 /**************************************************************************
610 * mmioRename [MMSYSTEM.1226]
612 MMRESULT16 WINAPI
mmioRename16(LPCSTR szFileName
, LPCSTR szNewFileName
,
613 MMIOINFO16
* lpmmioinfo
, DWORD dwRenameFlags
)
619 if (lpmmioinfo
!= NULL
&& lpmmioinfo
->pIOProc
!= NULL
&&
620 lpmmioinfo
->fccIOProc
== 0) {
621 FIXME("Can't handle this case yet\n");
622 return MMSYSERR_ERROR
;
625 /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
626 * but a non installed ioproc without a fourcc won't do
628 if (lpmmioinfo
&& lpmmioinfo
->fccIOProc
&& lpmmioinfo
->pIOProc
) {
629 mmioInstallIOProc16(lpmmioinfo
->fccIOProc
, lpmmioinfo
->pIOProc
,
633 memset(&mmioinfo
, 0, sizeof(mmioinfo
));
635 mmioinfo
.fccIOProc
= lpmmioinfo
->fccIOProc
;
636 ret
= mmioRenameA(szFileName
, szNewFileName
, &mmioinfo
, dwRenameFlags
);
638 mmioInstallIOProc16(lpmmioinfo
->fccIOProc
, NULL
, MMIO_REMOVEPROC
);