/************************************************************************** * mmioClose [WINMM.@] */ MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags) { LPWINE_MMIO wm; MMRESULT result; TRACE("(%p, %04X);\n", hmmio, uFlags); if ((wm = MMIO_Get(hmmio)) == NULL) return MMSYSERR_INVALHANDLE; if ((result = MMIO_Flush(wm, 0)) != MMSYSERR_NOERROR) return result; result = send_message(wm->ioProc, &wm->info, MMIOM_CLOSE, uFlags, 0, FALSE); MMIO_SetBuffer(wm, NULL, 0, 0); wm->ioProc->count--; if (wm->bTmpIOProc) MMIO_InstallIOProc(wm->info.fccIOProc, wm->ioProc->pIOProc, MMIO_REMOVEPROC, wm->ioProc->is_unicode); MMIO_Destroy(wm); return result; }
/************************************************************************** * 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); }
/************************************************************************** * mmioSeek [WINMM.@] */ LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin) { LPWINE_MMIO wm; LONG offset; TRACE("(%p, %08X, %d);\n", hmmio, lOffset, iOrigin); if ((wm = MMIO_Get(hmmio)) == NULL) return MMSYSERR_INVALHANDLE; /* not buffered, direct seek on file */ if (!wm->info.pchBuffer) return send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lOffset, iOrigin, FALSE); switch (iOrigin) { case SEEK_SET: offset = lOffset; break; case SEEK_CUR: offset = wm->info.lBufOffset + (wm->info.pchNext - wm->info.pchBuffer) + lOffset; break; case SEEK_END: offset = ((wm->info.fccIOProc == FOURCC_MEM)? wm->info.cchBuffer : wm->dwFileSize) - lOffset; break; default: return -1; } /* stay in same buffer ? */ /* some memory mapped buffers are defined with -1 as a size */ if ((wm->info.cchBuffer > 0) && ((offset < wm->info.lBufOffset) || (offset >= wm->info.lBufOffset + wm->info.cchBuffer) || (offset > wm->dwFileSize && wm->info.fccIOProc != FOURCC_MEM) || !wm->bBufferLoaded)) { /* condition to change buffer */ if ((wm->info.fccIOProc == FOURCC_MEM) || MMIO_Flush(wm, 0) != MMSYSERR_NOERROR || /* this also sets the wm->info.lDiskOffset field */ send_message(wm->ioProc, &wm->info, MMIOM_SEEK, offset, SEEK_SET, FALSE) == -1) return -1; wm->info.lBufOffset = offset; wm->bBufferLoaded = FALSE; wm->info.pchNext = wm->info.pchEndRead = wm->info.pchBuffer; } else wm->info.pchNext = wm->info.pchBuffer + (offset - wm->info.lBufOffset); TRACE("=> %d\n", offset); return offset; }
/************************************************************************** * mmioWrite [WINMM.@] */ LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch) { LPWINE_MMIO wm; LONG count; TRACE("(%p, %p, %d);\n", hmmio, pch, cch); if ((wm = MMIO_Get(hmmio)) == NULL) return -1; if (wm->info.cchBuffer) { LONG bytesW = 0; count = 0; while (cch) { if (wm->info.pchNext != wm->info.pchEndWrite) { count = wm->info.pchEndWrite - wm->info.pchNext; if (count > cch || count < 0) count = cch; memcpy(wm->info.pchNext, pch, count); wm->info.pchNext += count; pch += count; cch -= count; bytesW += count; wm->info.dwFlags |= MMIO_DIRTY; } else { if (wm->info.fccIOProc == FOURCC_MEM) { if (wm->info.adwInfo[0]) { /* from where would we get the memory handle? */ FIXME("memory file expansion not implemented!\n"); break; } else break; } } if (wm->info.pchNext == wm->info.pchEndWrite) { MMIO_Flush(wm, MMIO_EMPTYBUF); MMIO_GrabNextBuffer(wm, FALSE); } else break; } count = bytesW; } else { count = send_message(wm->ioProc, &wm->info, MMIOM_WRITE, (LPARAM)pch, cch, MMIO_PROC_32A); wm->info.lBufOffset = wm->info.lDiskOffset; } TRACE("bytes written=%d\n", count); return count; }
/************************************************************************** * 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; }
/*************************************************************************** * MMIO_SetBuffer [INTERNAL] */ static MMRESULT MMIO_SetBuffer(WINE_MMIO* wm, void* pchBuffer, LONG cchBuffer, UINT uFlags) { TRACE("(%p %p %d %u)\n", wm, pchBuffer, cchBuffer, uFlags); if (cchBuffer > 0xFFFF) WARN("Untested handling of huge mmio buffers (%d >= 64k)\n", cchBuffer); if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR) return MMIOERR_CANNOTWRITE; /* free previous buffer if allocated */ if (wm->info.dwFlags & MMIO_ALLOCBUF) { HeapFree(GetProcessHeap(), 0, wm->info.pchBuffer); wm->info.pchBuffer = NULL; wm->info.dwFlags &= ~MMIO_ALLOCBUF; } if (pchBuffer) { wm->info.pchBuffer = pchBuffer; } else if (cchBuffer) { if (!(wm->info.pchBuffer = HeapAlloc(GetProcessHeap(), 0, cchBuffer))) return MMIOERR_OUTOFMEMORY; wm->info.dwFlags |= MMIO_ALLOCBUF; } else { wm->info.pchBuffer = NULL; } wm->info.cchBuffer = cchBuffer; wm->info.pchNext = wm->info.pchBuffer; wm->info.pchEndRead = wm->info.pchBuffer; wm->info.pchEndWrite = wm->info.pchBuffer + cchBuffer; wm->info.lBufOffset = wm->info.lDiskOffset; wm->bBufferLoaded = FALSE; return MMSYSERR_NOERROR; }