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
32 #include "wine/winuser16.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mmsys
);
39 /* ###################################################
41 * ###################################################
44 #define MMIO_MAX_THUNKS 32
46 static struct mmio_thunk
48 BYTE popl_eax
; /* popl %eax (return address) */
49 BYTE pushl_func
; /* pushl $pfn16 (16bit callback function) */
51 BYTE pushl_eax
; /* pushl %eax */
52 BYTE jmp
; /* ljmp MMIO_Callback1632 */
54 HMMIO hMmio
; /* Handle to 32bit mmio object */
55 SEGPTR segbuffer
; /* actual segmented ptr to buffer */
60 static CRITICAL_SECTION mmio_cs
;
61 static CRITICAL_SECTION_DEBUG mmio_critsect_debug
=
64 { &mmio_critsect_debug
.ProcessLocksList
, &mmio_critsect_debug
.ProcessLocksList
},
65 0, 0, { (DWORD_PTR
)(__FILE__
": mmsystem_mmio_cs") }
67 static CRITICAL_SECTION mmio_cs
= { &mmio_critsect_debug
, -1, 0, 0, 0, 0 };
69 /****************************************************************
70 * MMIO_Map32To16 [INTERNAL]
72 static LRESULT
MMIO_Map32To16(DWORD wMsg
, LPARAM
* lp1
, LPARAM
* lp2
)
82 case MMIOM_WRITEFLUSH
:
83 *lp1
= MapLS( (void *)*lp1
);
86 *lp1
= MapLS( (void *)*lp1
);
87 *lp2
= MapLS( (void *)*lp2
);
90 if (wMsg
< MMIOM_USER
)
91 TRACE("Not a mappable message (%d)\n", wMsg
);
93 return MMSYSERR_NOERROR
;
96 /****************************************************************
97 * MMIO_UnMap32To16 [INTERNAL]
99 static LRESULT
MMIO_UnMap32To16(DWORD wMsg
, LPARAM lParam1
, LPARAM lParam2
,
100 LPARAM lp1
, LPARAM lp2
)
110 case MMIOM_WRITEFLUSH
:
118 if (wMsg
< MMIOM_USER
)
119 TRACE("Not a mappable message (%d)\n", wMsg
);
121 return MMSYSERR_NOERROR
;
124 /******************************************************************
129 static LRESULT
MMIO_Callback3216(SEGPTR cb16
, LPMMIOINFO lpmmioinfo
, UINT uMessage
,
130 LPARAM lParam1
, LPARAM lParam2
)
133 MMIOINFO16 mmioInfo16
;
134 SEGPTR segmmioInfo16
;
135 LPARAM lp1
= lParam1
, lp2
= lParam2
;
138 if (!cb16
) return MMSYSERR_INVALPARAM
;
140 memset(&mmioInfo16
, 0, sizeof(MMIOINFO16
));
141 mmioInfo16
.lDiskOffset
= lpmmioinfo
->lDiskOffset
;
142 mmioInfo16
.adwInfo
[0] = lpmmioinfo
->adwInfo
[0];
143 mmioInfo16
.adwInfo
[1] = lpmmioinfo
->adwInfo
[1];
144 mmioInfo16
.adwInfo
[2] = lpmmioinfo
->adwInfo
[2];
145 /* map (lParam1, lParam2) into (lp1, lp2) 32=>16 */
146 if ((result
= MMIO_Map32To16(uMessage
, &lp1
, &lp2
)) != MMSYSERR_NOERROR
)
149 segmmioInfo16
= MapLS(&mmioInfo16
);
150 args
[6] = HIWORD(segmmioInfo16
);
151 args
[5] = LOWORD(segmmioInfo16
);
153 args
[3] = HIWORD(lp1
);
154 args
[2] = LOWORD(lp1
);
155 args
[1] = HIWORD(lp2
);
156 args
[0] = LOWORD(lp2
);
157 WOWCallback16Ex( cb16
, WCB16_PASCAL
, sizeof(args
), args
, &result
);
158 UnMapLS(segmmioInfo16
);
159 MMIO_UnMap32To16(uMessage
, lParam1
, lParam2
, lp1
, lp2
);
161 lpmmioinfo
->lDiskOffset
= mmioInfo16
.lDiskOffset
;
162 lpmmioinfo
->adwInfo
[0] = mmioInfo16
.adwInfo
[0];
163 lpmmioinfo
->adwInfo
[1] = mmioInfo16
.adwInfo
[1];
164 lpmmioinfo
->adwInfo
[2] = mmioInfo16
.adwInfo
[2];
169 /******************************************************************
173 static struct mmio_thunk
* MMIO_AddThunk(LPMMIOPROC16 pfn16
, HPSTR segbuf
)
175 struct mmio_thunk
* thunk
;
179 MMIO_Thunks
= VirtualAlloc(NULL
, MMIO_MAX_THUNKS
* sizeof(*MMIO_Thunks
), MEM_COMMIT
,
180 PAGE_EXECUTE_READWRITE
);
181 if (!MMIO_Thunks
) return NULL
;
182 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
184 thunk
->popl_eax
= 0x58; /* popl %eax */
185 thunk
->pushl_func
= 0x68; /* pushl $pfn16 */
187 thunk
->pushl_eax
= 0x50; /* pushl %eax */
188 thunk
->jmp
= 0xe9; /* jmp MMIO_Callback3216 */
189 thunk
->callback
= (char *)MMIO_Callback3216
- (char *)(&thunk
->callback
+ 1);
191 thunk
->segbuffer
= 0;
194 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
196 if (thunk
->pfn16
== 0 && thunk
->hMmio
== NULL
)
198 thunk
->pfn16
= pfn16
;
200 thunk
->segbuffer
= (SEGPTR
)segbuf
;
204 FIXME("Out of mmio-thunks. Bump MMIO_MAX_THUNKS\n");
208 /******************************************************************
212 static struct mmio_thunk
* MMIO_HasThunk(HMMIO hmmio
)
214 struct mmio_thunk
* thunk
;
216 if (!MMIO_Thunks
) return NULL
;
217 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
219 if (thunk
->hMmio
== hmmio
) return thunk
;
224 /******************************************************************
225 * MMIO_SetSegmentedBuffer
228 static void MMIO_SetSegmentedBuffer(struct mmio_thunk
* thunk
, SEGPTR ptr
, BOOL release
)
230 if (release
) UnMapLS(thunk
->segbuffer
);
231 thunk
->segbuffer
= ptr
;
234 /**************************************************************************
235 * mmioOpen [MMSYSTEM.1210]
237 HMMIO16 WINAPI
mmioOpen16(LPSTR szFileName
, MMIOINFO16
* lpmmioinfo16
,
244 struct mmio_thunk
* thunk
= NULL
;
246 memset(&mmioinfo
, 0, sizeof(mmioinfo
));
248 EnterCriticalSection(&mmio_cs
);
249 if (!(thunk
= MMIO_AddThunk(lpmmioinfo16
->pIOProc
, lpmmioinfo16
->pchBuffer
)))
251 LeaveCriticalSection(&mmio_cs
);
255 mmioinfo
.dwFlags
= lpmmioinfo16
->dwFlags
;
256 mmioinfo
.fccIOProc
= lpmmioinfo16
->fccIOProc
;
257 mmioinfo
.pIOProc
= lpmmioinfo16
->pIOProc
? (LPMMIOPROC
)thunk
: 0;
258 mmioinfo
.cchBuffer
= lpmmioinfo16
->cchBuffer
;
259 mmioinfo
.pchBuffer
= MapSL((DWORD
)lpmmioinfo16
->pchBuffer
);
260 mmioinfo
.adwInfo
[0] = lpmmioinfo16
->adwInfo
[0];
261 /* if we don't have a file name, it's likely a passed open file descriptor */
263 mmioinfo
.adwInfo
[0] = (DWORD
)DosFileHandleToWin32Handle(mmioinfo
.adwInfo
[0]);
264 mmioinfo
.adwInfo
[1] = lpmmioinfo16
->adwInfo
[1];
265 mmioinfo
.adwInfo
[2] = lpmmioinfo16
->adwInfo
[2];
267 ret
= mmioOpenA(szFileName
, &mmioinfo
, dwOpenFlags
);
268 if (!ret
|| (dwOpenFlags
& (MMIO_PARSE
|MMIO_EXIST
)))
273 else thunk
->hMmio
= ret
;
274 if (ret
&& (dwOpenFlags
& MMIO_ALLOCBUF
))
277 if (lpmmioinfo16
->pchBuffer
) FIXME("ooch\n");
278 /* FIXME: check whether mmioOpen should set pchBuffer */
279 mmioGetInfo(ret
, &m
, 0);
280 thunk
->segbuffer
= MapLS(m
.pchBuffer
);
282 LeaveCriticalSection(&mmio_cs
);
284 lpmmioinfo16
->wErrorRet
= mmioinfo
.wErrorRet
;
285 lpmmioinfo16
->hmmio
= HMMIO_16(mmioinfo
.hmmio
);
287 ret
= mmioOpenA(szFileName
, NULL
, dwOpenFlags
);
289 return HMMIO_16(ret
);
292 /**************************************************************************
293 * mmioClose [MMSYSTEM.1211]
295 MMRESULT16 WINAPI
mmioClose16(HMMIO16 hmmio
, UINT16 uFlags
)
299 EnterCriticalSection(&mmio_cs
);
300 ret
= mmioClose(HMMIO_32(hmmio
), uFlags
);
301 if (ret
== MMSYSERR_NOERROR
)
303 struct mmio_thunk
* thunk
;
305 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))))
307 MMIO_SetSegmentedBuffer(thunk
, 0, TRUE
);
312 LeaveCriticalSection(&mmio_cs
);
316 /**************************************************************************
317 * mmioRead [MMSYSTEM.1212]
319 LONG WINAPI
mmioRead16(HMMIO16 hmmio
, HPSTR pch
, LONG cch
)
321 return mmioRead(HMMIO_32(hmmio
), pch
, cch
);
324 /**************************************************************************
325 * mmioWrite [MMSYSTEM.1213]
327 LONG WINAPI
mmioWrite16(HMMIO16 hmmio
, HPCSTR pch
, LONG cch
)
329 return mmioWrite(HMMIO_32(hmmio
),pch
,cch
);
332 /**************************************************************************
333 * mmioSeek [MMSYSTEM.1214]
335 LONG WINAPI
mmioSeek16(HMMIO16 hmmio
, LONG lOffset
, INT16 iOrigin
)
337 return mmioSeek(HMMIO_32(hmmio
), lOffset
, iOrigin
);
340 /**************************************************************************
341 * mmioGetInfo [MMSYSTEM.1215]
343 MMRESULT16 WINAPI
mmioGetInfo16(HMMIO16 hmmio
, MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
347 struct mmio_thunk
* thunk
;
349 TRACE("(0x%04x,%p,0x%08x)\n", hmmio
, lpmmioinfo
, uFlags
);
351 EnterCriticalSection(&mmio_cs
);
352 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))) == NULL
)
354 LeaveCriticalSection(&mmio_cs
);
355 return MMSYSERR_INVALHANDLE
;
358 ret
= mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
359 if (ret
!= MMSYSERR_NOERROR
)
361 LeaveCriticalSection(&mmio_cs
);
365 lpmmioinfo
->dwFlags
= mmioinfo
.dwFlags
;
366 lpmmioinfo
->fccIOProc
= mmioinfo
.fccIOProc
;
367 lpmmioinfo
->pIOProc
= thunk
->pfn16
;
368 lpmmioinfo
->wErrorRet
= mmioinfo
.wErrorRet
;
369 lpmmioinfo
->hTask
= HTASK_16(mmioinfo
.hTask
);
370 lpmmioinfo
->cchBuffer
= mmioinfo
.cchBuffer
;
371 lpmmioinfo
->pchBuffer
= (void*)thunk
->segbuffer
;
372 lpmmioinfo
->pchNext
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchNext
- mmioinfo
.pchBuffer
));
373 lpmmioinfo
->pchEndRead
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchEndRead
- mmioinfo
.pchBuffer
));
374 lpmmioinfo
->pchEndWrite
= (void*)(thunk
->segbuffer
+ (mmioinfo
.pchEndWrite
- mmioinfo
.pchBuffer
));
375 lpmmioinfo
->lBufOffset
= mmioinfo
.lBufOffset
;
376 lpmmioinfo
->lDiskOffset
= mmioinfo
.lDiskOffset
;
377 lpmmioinfo
->adwInfo
[0] = mmioinfo
.adwInfo
[0];
378 lpmmioinfo
->adwInfo
[1] = mmioinfo
.adwInfo
[1];
379 lpmmioinfo
->adwInfo
[2] = mmioinfo
.adwInfo
[2];
380 lpmmioinfo
->dwReserved1
= 0;
381 lpmmioinfo
->dwReserved2
= 0;
382 lpmmioinfo
->hmmio
= HMMIO_16(mmioinfo
.hmmio
);
383 LeaveCriticalSection(&mmio_cs
);
385 return MMSYSERR_NOERROR
;
388 /**************************************************************************
389 * mmioSetInfo [MMSYSTEM.1216]
391 MMRESULT16 WINAPI
mmioSetInfo16(HMMIO16 hmmio
, const MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
396 TRACE("(0x%04x,%p,0x%08x)\n",hmmio
,lpmmioinfo
,uFlags
);
398 ret
= mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, 0);
399 if (ret
!= MMSYSERR_NOERROR
) return ret
;
401 /* check if seg and lin buffers are the same */
402 if (mmioinfo
.cchBuffer
!= lpmmioinfo
->cchBuffer
||
403 mmioinfo
.pchBuffer
!= MapSL((DWORD
)lpmmioinfo
->pchBuffer
))
404 return MMSYSERR_INVALPARAM
;
406 /* check pointers coherence */
407 if (lpmmioinfo
->pchNext
< lpmmioinfo
->pchBuffer
||
408 lpmmioinfo
->pchNext
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
||
409 lpmmioinfo
->pchEndRead
< lpmmioinfo
->pchBuffer
||
410 lpmmioinfo
->pchEndRead
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
||
411 lpmmioinfo
->pchEndWrite
< lpmmioinfo
->pchBuffer
||
412 lpmmioinfo
->pchEndWrite
> lpmmioinfo
->pchBuffer
+ lpmmioinfo
->cchBuffer
)
413 return MMSYSERR_INVALPARAM
;
415 mmioinfo
.pchNext
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchNext
- lpmmioinfo
->pchBuffer
);
416 mmioinfo
.pchEndRead
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchEndRead
- lpmmioinfo
->pchBuffer
);
417 mmioinfo
.pchEndWrite
= mmioinfo
.pchBuffer
+ (lpmmioinfo
->pchEndWrite
- lpmmioinfo
->pchBuffer
);
419 return mmioSetInfo(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
422 /**************************************************************************
423 * mmioSetBuffer [MMSYSTEM.1217]
425 MMRESULT16 WINAPI
mmioSetBuffer16(HMMIO16 hmmio
, SEGPTR pchBuffer
,
426 LONG cchBuffer
, UINT16 uFlags
)
428 MMRESULT ret
= mmioSetBuffer(HMMIO_32(hmmio
), MapSL(pchBuffer
),
431 if (ret
== MMSYSERR_NOERROR
)
433 struct mmio_thunk
* thunk
;
435 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))) == NULL
)
438 return MMSYSERR_INVALHANDLE
;
440 MMIO_SetSegmentedBuffer(thunk
, pchBuffer
, TRUE
);
447 /**************************************************************************
448 * mmioFlush [MMSYSTEM.1218]
450 MMRESULT16 WINAPI
mmioFlush16(HMMIO16 hmmio
, UINT16 uFlags
)
452 return mmioFlush(HMMIO_32(hmmio
), uFlags
);
455 /***********************************************************************
456 * mmioAdvance [MMSYSTEM.1219]
458 MMRESULT16 WINAPI
mmioAdvance16(HMMIO16 hmmio
, MMIOINFO16
* lpmmioinfo
, UINT16 uFlags
)
463 /* WARNING: this heavily relies on mmioAdvance implementation (for choosing which
468 mmioinfo
.pchBuffer
= MapSL((DWORD
)lpmmioinfo
->pchBuffer
);
469 mmioinfo
.pchNext
= MapSL((DWORD
)lpmmioinfo
->pchNext
);
470 mmioinfo
.dwFlags
= lpmmioinfo
->dwFlags
;
471 mmioinfo
.lBufOffset
= lpmmioinfo
->lBufOffset
;
472 ret
= mmioAdvance(HMMIO_32(hmmio
), &mmioinfo
, uFlags
);
475 ret
= mmioAdvance(HMMIO_32(hmmio
), NULL
, uFlags
);
477 if (ret
!= MMSYSERR_NOERROR
) return ret
;
481 lpmmioinfo
->dwFlags
= mmioinfo
.dwFlags
;
482 lpmmioinfo
->pchNext
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchNext
- mmioinfo
.pchBuffer
));
483 lpmmioinfo
->pchEndRead
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchEndRead
- mmioinfo
.pchBuffer
));
484 lpmmioinfo
->pchEndWrite
= (void*)(lpmmioinfo
->pchBuffer
+ (mmioinfo
.pchEndWrite
- mmioinfo
.pchBuffer
));
485 lpmmioinfo
->lBufOffset
= mmioinfo
.lBufOffset
;
486 lpmmioinfo
->lDiskOffset
= mmioinfo
.lDiskOffset
;
489 return MMSYSERR_NOERROR
;
492 /**************************************************************************
493 * mmioStringToFOURCC [MMSYSTEM.1220]
495 FOURCC WINAPI
mmioStringToFOURCC16(LPCSTR sz
, UINT16 uFlags
)
497 return mmioStringToFOURCCA(sz
, uFlags
);
500 /**************************************************************************
501 * mmioInstallIOProc [MMSYSTEM.1221]
503 LPMMIOPROC16 WINAPI
mmioInstallIOProc16(FOURCC fccIOProc
, LPMMIOPROC16 pIOProc
,
506 struct mmio_thunk
* thunk
= NULL
;
507 LPMMIOPROC pIOProc32
;
509 EnterCriticalSection(&mmio_cs
);
511 switch (dwFlags
& (MMIO_INSTALLPROC
|MMIO_REMOVEPROC
|MMIO_FINDPROC
)) {
512 case MMIO_INSTALLPROC
:
513 if (!(thunk
= MMIO_AddThunk(pIOProc
, NULL
)))
515 LeaveCriticalSection(&mmio_cs
);
518 if (!mmioInstallIOProcA(fccIOProc
, (LPMMIOPROC
)thunk
, dwFlags
))
524 case MMIO_REMOVEPROC
:
527 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
529 if (thunk
->pfn16
== pIOProc
&& thunk
->segbuffer
== 0)
531 if (mmioInstallIOProcA(fccIOProc
, (LPMMIOPROC
)thunk
, dwFlags
))
539 if (!thunk
) pIOProc
= NULL
;
542 if ((pIOProc32
= mmioInstallIOProcA(fccIOProc
, NULL
, dwFlags
)) && MMIO_Thunks
)
544 for (thunk
= MMIO_Thunks
; thunk
< &MMIO_Thunks
[MMIO_MAX_THUNKS
]; thunk
++)
546 if ((LPMMIOPROC
)thunk
== pIOProc32
)
548 pIOProc
= thunk
->pfn16
;
555 FIXME("Unsupported flags %08x\n", dwFlags
);
558 LeaveCriticalSection(&mmio_cs
);
563 /**************************************************************************
564 * mmioSendMessage [MMSYSTEM.1222]
566 LRESULT WINAPI
mmioSendMessage16(HMMIO16 hmmio
, UINT16 uMessage
,
567 LPARAM lParam1
, LPARAM lParam2
)
569 struct mmio_thunk
* thunk
;
571 if ((thunk
= MMIO_HasThunk(HMMIO_32(hmmio
))))
574 if (mmioGetInfo(HMMIO_32(hmmio
), &mmioinfo
, 0) == MMSYSERR_NOERROR
)
576 return MMIO_Callback3216((SEGPTR
)thunk
->pfn16
, &mmioinfo
, uMessage
, lParam1
, lParam2
);
578 return MMSYSERR_INVALHANDLE
;
582 /* FIXME: we need to map lParam1 and lParam2 to 32bit entities */
583 return mmioSendMessage(HMMIO_32(hmmio
), uMessage
, lParam1
, lParam2
);
587 /**************************************************************************
588 * mmioDescend [MMSYSTEM.1223]
590 MMRESULT16 WINAPI
mmioDescend16(HMMIO16 hmmio
, LPMMCKINFO lpck
,
591 const MMCKINFO
* lpckParent
, UINT16 uFlags
)
593 return mmioDescend(HMMIO_32(hmmio
), lpck
, lpckParent
, uFlags
);
596 /**************************************************************************
597 * mmioAscend [MMSYSTEM.1224]
599 MMRESULT16 WINAPI
mmioAscend16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
601 return mmioAscend(HMMIO_32(hmmio
),lpck
,uFlags
);
604 /**************************************************************************
605 * mmioCreateChunk [MMSYSTEM.1225]
607 MMRESULT16 WINAPI
mmioCreateChunk16(HMMIO16 hmmio
, MMCKINFO
* lpck
, UINT16 uFlags
)
609 return mmioCreateChunk(HMMIO_32(hmmio
), lpck
, uFlags
);
612 /**************************************************************************
613 * mmioRename [MMSYSTEM.1226]
615 MMRESULT16 WINAPI
mmioRename16(LPCSTR szFileName
, LPCSTR szNewFileName
,
616 MMIOINFO16
* lpmmioinfo
, DWORD dwRenameFlags
)
622 if (lpmmioinfo
!= NULL
&& lpmmioinfo
->pIOProc
!= NULL
&&
623 lpmmioinfo
->fccIOProc
== 0) {
624 FIXME("Can't handle this case yet\n");
625 return MMSYSERR_ERROR
;
628 /* this is a bit hacky, but it'll work if we get a fourCC code or nothing.
629 * but a non installed ioproc without a fourcc won't do
631 if (lpmmioinfo
&& lpmmioinfo
->fccIOProc
&& lpmmioinfo
->pIOProc
) {
632 mmioInstallIOProc16(lpmmioinfo
->fccIOProc
, lpmmioinfo
->pIOProc
,
636 memset(&mmioinfo
, 0, sizeof(mmioinfo
));
638 mmioinfo
.fccIOProc
= lpmmioinfo
->fccIOProc
;
639 ret
= mmioRenameA(szFileName
, szNewFileName
, &mmioinfo
, dwRenameFlags
);
641 mmioInstallIOProc16(lpmmioinfo
->fccIOProc
, NULL
, MMIO_REMOVEPROC
);