📄 mmio.c
字号:
*/
MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
{
LPWINE_MMIO wm;
TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
memcpy(lpmmioinfo, &wm->info, sizeof(MMIOINFO));
/* don't expose 16 bit ioproc:s */
if (wm->ioProc->type != MMIO_PROC_16)
lpmmioinfo->pIOProc = wm->ioProc->pIOProc;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioSetInfo [WINMM.@]
*/
MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO* lpmmioinfo, UINT uFlags)
{
LPWINE_MMIO wm;
TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags);
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
/* check pointers coherence */
if (lpmmioinfo->pchNext < wm->info.pchBuffer ||
lpmmioinfo->pchNext > wm->info.pchBuffer + wm->info.cchBuffer ||
lpmmioinfo->pchEndRead < wm->info.pchBuffer ||
lpmmioinfo->pchEndRead > wm->info.pchBuffer + wm->info.cchBuffer ||
lpmmioinfo->pchEndWrite < wm->info.pchBuffer ||
lpmmioinfo->pchEndWrite > wm->info.pchBuffer + wm->info.cchBuffer)
return MMSYSERR_INVALPARAM;
wm->info.pchNext = lpmmioinfo->pchNext;
wm->info.pchEndRead = lpmmioinfo->pchEndRead;
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioSetBuffer [WINMM.@]
*/
MMRESULT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT uFlags)
{
LPWINE_MMIO wm;
TRACE("(hmmio=%p, pchBuf=%p, cchBuf=%ld, uFlags=%#08x)\n",
hmmio, pchBuffer, cchBuffer, uFlags);
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
return MMIO_SetBuffer(wm, pchBuffer, cchBuffer, uFlags);
}
/**************************************************************************
* mmioFlush [WINMM.@]
*/
MMRESULT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags)
{
LPWINE_MMIO wm;
TRACE("(%p, %04X)\n", hmmio, uFlags);
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
return MMIO_Flush(wm, uFlags);
}
/**************************************************************************
* mmioAdvance [WINMM.@]
*/
MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags)
{
LPWINE_MMIO wm;
TRACE("hmmio=%p, lpmmioinfo=%p, uFlags=%04X\n", hmmio, lpmmioinfo, uFlags);
/* NOTE: mmioAdvance16 heavily relies on parameters from lpmmioinfo we're using
* here. be sure if you change something here to check mmioAdvance16 as well
*/
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
if (!wm->info.cchBuffer)
return MMIOERR_UNBUFFERED;
if (uFlags != MMIO_READ && uFlags != MMIO_WRITE)
return MMSYSERR_INVALPARAM;
if (uFlags == MMIO_WRITE && (lpmmioinfo->dwFlags & MMIO_DIRTY))
{
send_message(wm->ioProc, &wm->info, MMIOM_SEEK,
lpmmioinfo->lBufOffset, SEEK_SET, MMIO_PROC_32A);
send_message(wm->ioProc, &wm->info, MMIOM_WRITE,
(LPARAM)lpmmioinfo->pchBuffer,
lpmmioinfo->pchNext - lpmmioinfo->pchBuffer, MMIO_PROC_32A);
lpmmioinfo->dwFlags &= ~MMIO_DIRTY;
}
if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR)
return MMIOERR_CANNOTWRITE;
if (lpmmioinfo) {
wm->dwFileSize = max(wm->dwFileSize, lpmmioinfo->lBufOffset +
(lpmmioinfo->pchNext - lpmmioinfo->pchBuffer));
}
MMIO_GrabNextBuffer(wm, uFlags == MMIO_READ);
if (lpmmioinfo) {
lpmmioinfo->pchNext = lpmmioinfo->pchBuffer;
lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer +
(wm->info.pchEndRead - wm->info.pchBuffer);
lpmmioinfo->pchEndWrite = lpmmioinfo->pchBuffer +
(wm->info.pchEndWrite - wm->info.pchBuffer);
lpmmioinfo->lDiskOffset = wm->info.lDiskOffset;
lpmmioinfo->lBufOffset = wm->info.lBufOffset;
}
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioStringToFOURCCA [WINMM.@]
*/
FOURCC WINAPI mmioStringToFOURCCA(LPCSTR sz, UINT uFlags)
{
CHAR cc[4];
int i = 0;
for (i = 0; i < 4 && sz[i]; i++) {
if (uFlags & MMIO_TOUPPER) {
cc[i] = toupper(sz[i]);
} else {
cc[i] = sz[i];
}
}
/* Pad with spaces */
while (i < 4) cc[i++] = ' ';
TRACE("Got '%.4s'\n",cc);
return mmioFOURCC(cc[0],cc[1],cc[2],cc[3]);
}
/**************************************************************************
* mmioStringToFOURCCW [WINMM.@]
*/
FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR sz, UINT uFlags)
{
char szA[4];
WideCharToMultiByte( CP_ACP, 0, sz, 4, szA, sizeof(szA), NULL, NULL );
return mmioStringToFOURCCA(szA,uFlags);
}
/**************************************************************************
* mmioInstallIOProcA [WINMM.@]
*/
LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC fccIOProc,
LPMMIOPROC pIOProc, DWORD dwFlags)
{
return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, MMIO_PROC_32A);
}
/**************************************************************************
* mmioInstallIOProcW [WINMM.@]
*/
LPMMIOPROC WINAPI mmioInstallIOProcW(FOURCC fccIOProc,
LPMMIOPROC pIOProc, DWORD dwFlags)
{
return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, MMIO_PROC_32W);
}
/******************************************************************
* MMIO_SendMessage
*
*
*/
LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1,
LPARAM lParam2, enum mmioProcType type)
{
LPWINE_MMIO wm;
TRACE("(%p, %u, %ld, %ld, %d)\n", hmmio, uMessage, lParam1, lParam2, type);
if (uMessage < MMIOM_USER)
return MMSYSERR_INVALPARAM;
if ((wm = MMIO_Get(hmmio)) == NULL)
return MMSYSERR_INVALHANDLE;
return send_message(wm->ioProc, &wm->info, uMessage, lParam1, lParam2, type);
}
/**************************************************************************
* mmioSendMessage [WINMM.@]
*/
LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage,
LPARAM lParam1, LPARAM lParam2)
{
return MMIO_SendMessage(hmmio, uMessage, lParam1, lParam2, MMIO_PROC_32A);
}
/**************************************************************************
* mmioDescend [WINMM.@]
*/
MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck,
const MMCKINFO* lpckParent, UINT uFlags)
{
DWORD dwOldPos;
FOURCC srchCkId;
FOURCC srchType;
TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags);
if (lpck == NULL)
return MMSYSERR_INVALPARAM;
dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
TRACE("dwOldPos=%ld\n", dwOldPos);
if (lpckParent != NULL) {
TRACE("seek inside parent at %ld !\n", lpckParent->dwDataOffset);
/* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */
if (dwOldPos < lpckParent->dwDataOffset ||
dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) {
WARN("outside parent chunk\n");
return MMIOERR_CHUNKNOTFOUND;
}
}
/* The SDK docu says 'ckid' is used for all cases. Real World
* examples disagree -Marcus,990216.
*/
srchType = 0;
/* find_chunk looks for 'ckid' */
if (uFlags & MMIO_FINDCHUNK)
srchCkId = lpck->ckid;
/* find_riff and find_list look for 'fccType' */
if (uFlags & MMIO_FINDLIST) {
srchCkId = FOURCC_LIST;
srchType = lpck->fccType;
}
if (uFlags & MMIO_FINDRIFF) {
srchCkId = FOURCC_RIFF;
srchType = lpck->fccType;
}
if (uFlags & (MMIO_FINDCHUNK|MMIO_FINDLIST|MMIO_FINDRIFF)) {
TRACE("searching for %.4s.%.4s\n",
(LPSTR)&srchCkId,
srchType?(LPSTR)&srchType:"any ");
while (TRUE) {
LONG ix;
ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD));
if (ix < 2*sizeof(DWORD)) {
mmioSeek(hmmio, dwOldPos, SEEK_SET);
WARN("return ChunkNotFound\n");
return MMIOERR_CHUNKNOTFOUND;
}
lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
if (ix < lpck->dwDataOffset - dwOldPos) {
mmioSeek(hmmio, dwOldPos, SEEK_SET);
WARN("return ChunkNotFound\n");
return MMIOERR_CHUNKNOTFOUND;
}
TRACE("ckid=%.4s fcc=%.4s cksize=%08lX !\n",
(LPSTR)&lpck->ckid,
srchType?(LPSTR)&lpck->fccType:"<na>",
lpck->cksize);
if ((srchCkId == lpck->ckid) &&
(!srchType || (srchType == lpck->fccType))
)
break;
dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1);
mmioSeek(hmmio, dwOldPos, SEEK_SET);
}
} else {
/* FIXME: unverified, does it do this? */
/* NB: This part is used by WAVE_mciOpen, among others */
if (mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD)) < 3 * sizeof(DWORD)) {
mmioSeek(hmmio, dwOldPos, SEEK_SET);
WARN("return ChunkNotFound 2nd\n");
return MMIOERR_CHUNKNOTFOUND;
}
lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD);
}
lpck->dwFlags = 0;
/* If we were looking for RIFF/LIST chunks, the final file position
* is after the chunkid. If we were just looking for the chunk
* it is after the cksize. So add 4 in RIFF/LIST case.
*/
if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET);
else
mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET);
TRACE("lpck: ckid=%.4s, cksize=%ld, dwDataOffset=%ld fccType=%08lX (%.4s)!\n",
(LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset,
lpck->fccType, srchType?(LPSTR)&lpck->fccType:"");
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioAscend [WINMM.@]
*/
MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags)
{
TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
if (lpck->dwFlags & MMIO_DIRTY) {
DWORD dwOldPos, dwNewSize;
TRACE("Chunk is dirty, checking if chunk's size is correct\n");
dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
TRACE("dwOldPos=%ld lpck->dwDataOffset = %ld\n", dwOldPos, lpck->dwDataOffset);
dwNewSize = dwOldPos - lpck->dwDataOffset;
if (dwNewSize != lpck->cksize) {
TRACE("Nope: lpck->cksize=%ld dwNewSize=%ld\n", lpck->cksize, dwNewSize);
lpck->cksize = dwNewSize;
/* pad odd size with 0 */
if (dwNewSize & 1) {
char ch = 0;
mmioWrite(hmmio, &ch, 1);
}
mmioSeek(hmmio, lpck->dwDataOffset - sizeof(DWORD), SEEK_SET);
mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD));
}
lpck->dwFlags = 0;
}
mmioSeek(hmmio, lpck->dwDataOffset + ((lpck->cksize + 1) & ~1), SEEK_SET);
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioCreateChunk [WINMM.@]
*/
MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO* lpck, UINT uFlags)
{
DWORD dwOldPos;
LONG size;
LONG ix;
TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags);
dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR);
TRACE("dwOldPos=%ld\n", dwOldPos);
if (uFlags == MMIO_CREATELIST)
lpck->ckid = FOURCC_LIST;
else if (uFlags == MMIO_CREATERIFF)
lpck->ckid = FOURCC_RIFF;
TRACE("ckid=%.4s\n", (LPSTR)&lpck->ckid);
size = 2 * sizeof(DWORD);
lpck->dwDataOffset = dwOldPos + size;
if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST)
size += sizeof(DWORD);
lpck->dwFlags = MMIO_DIRTY;
ix = mmioWrite(hmmio, (LPSTR)lpck, size);
TRACE("after mmioWrite ix = %ld req = %ld, errno = %d\n",ix, size, errno);
if (ix < size) {
mmioSeek(hmmio, dwOldPos, SEEK_SET);
WARN("return CannotWrite\n");
return MMIOERR_CANNOTWRITE;
}
return MMSYSERR_NOERROR;
}
/**************************************************************************
* mmioRenameA [WINMM.@]
*/
MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName,
const MMIOINFO* lpmmioinfo, DWORD dwFlags)
{
struct IOProcList* ioProc = NULL;
struct IOProcList tmp;
FOURCC fcc;
TRACE("('%s', '%s', %p, %08lX);\n",
debugstr_a(szFileName), debugstr_a(szNewFileName), lpmmioinfo, dwFlags);
/* If both params are NULL, then parse the file name */
if (lpmmioinfo && lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL)
{
fcc = MMIO_ParseExtA(szFileName);
if (fcc) ioProc = MMIO_FindProcNode(fcc);
}
/* Handle any unhandled/error case from above. Assume DOS file */
if (!lpmmioinfo || (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL && ioProc == NULL))
ioProc = MMIO_FindProcNode(FOURCC_DOS);
/* if just the four character code is present, look up IO proc */
else if (lpmmioinfo->pIOProc == NULL)
ioProc = MMIO_FindProcNode(lpmmioinfo->fccIOProc);
else /* use relevant ioProc */
{
ioProc = &tmp;
tmp.fourCC = lpmmioinfo->fccIOProc;
tmp.pIOProc = lpmmioinfo->pIOProc;
tmp.type = MMIO_PROC_32A;
tmp.count = 1;
}
/* FIXME: should we actually pass lpmmioinfo down the drain ???
* or make a copy of it because it's const ???
*/
return send_message(ioProc, (MMIOINFO*)lpmmioinfo, MMIOM_RENAME,
(LPARAM)szFileName, (LPARAM)szNewFileName, MMIO_PROC_32A);
}
/**************************************************************************
* mmioRenameW [WINMM.@]
*/
MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName,
const MMIOINFO* lpmmioinfo, DWORD dwFlags)
{
LPSTR szFn = NULL;
LPSTR sznFn = NULL;
UINT ret = MMSYSERR_NOMEM;
INT len;
if (szFileName)
{
len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL );
szFn = HeapAlloc( GetProcessHeap(), 0, len );
if (!szFn) goto done;
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL );
}
if (szNewFileName)
{
len = WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, NULL, 0, NULL, NULL );
sznFn = HeapAlloc( GetProcessHeap(), 0, len );
if (!sznFn) goto done;
WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, sznFn, len, NULL, NULL );
}
ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwFlags);
done:
HeapFree(GetProcessHeap(),0,szFn);
HeapFree(GetProcessHeap(),0,sznFn);
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -