/************************************************************************** * 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); }
/************************************************************************** * mmioSetBuffer [WINMM.@] */ MMRESULT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT uFlags) { LPWINE_MMIO wm; TRACE("(hmmio=%p, pchBuf=%p, cchBuf=%d, uFlags=%#08x)\n", hmmio, pchBuffer, cchBuffer, uFlags); if ((wm = MMIO_Get(hmmio)) == NULL) return MMSYSERR_INVALHANDLE; return MMIO_SetBuffer(wm, pchBuffer, cchBuffer, 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; }
/************************************************************************** * mmioGetInfo [WINMM.@] */ 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; *lpmmioinfo = wm->info; return MMSYSERR_NOERROR; }
/************************************************************************** * 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; }
/************************************************************************** * mmioRead [WINMM.@] */ LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch) { LPWINE_MMIO wm; LONG count; TRACE("(%p, %p, %d);\n", hmmio, pch, cch); if ((wm = MMIO_Get(hmmio)) == NULL) return -1; /* unbuffered case first */ if (!wm->info.pchBuffer) return send_message(wm->ioProc, &wm->info, MMIOM_READ, (LPARAM)pch, cch, FALSE); /* first try from current buffer */ if (cch && wm->info.fccIOProc != FOURCC_MEM && wm->info.pchNext == wm->info.pchEndRead) MMIO_GrabNextBuffer(wm, TRUE); if (wm->info.pchNext != wm->info.pchEndRead) { count = wm->info.pchEndRead - wm->info.pchNext; if (count > cch || count < 0) count = cch; memcpy(pch, wm->info.pchNext, count); wm->info.pchNext += count; pch += count; cch -= count; } else count = 0; if (cch && (wm->info.fccIOProc != FOURCC_MEM)) { assert(wm->info.cchBuffer); while (cch) { LONG size; size = MMIO_GrabNextBuffer(wm, TRUE); if (size <= 0) break; if (size > cch) size = cch; memcpy(pch, wm->info.pchBuffer, size); wm->info.pchNext += size; pch += size; cch -= size; count += size; } wm->bBufferLoaded = FALSE; mmioSeek(hmmio, 0, SEEK_CUR); } TRACE("count=%d\n", count); return count; }
/****************************************************************** * MMIO_SendMessage * * */ static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, LPARAM lParam2, BOOL is_unicode) { LPWINE_MMIO wm; TRACE("(%p, %u, %ld, %ld, %s)\n", hmmio, uMessage, lParam1, lParam2, is_unicode ? "unicode" : "ansi"); 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, is_unicode); }
/****************************************************************** * 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); }
/************************************************************************** * mmioGetInfo [WINMM.@] */ 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; *lpmmioinfo = wm->info; /* don't expose 16 bit ioproc:s */ if (wm->ioProc->type != MMIO_PROC_16) lpmmioinfo->pIOProc = wm->ioProc->pIOProc; return MMSYSERR_NOERROR; }
/************************************************************************** * 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_Create [internal] * * Creates an internal representation for a mmio instance */ static LPWINE_MMIO MMIO_Create(void) { static WORD MMIO_counter = 0; LPWINE_MMIO wm; wm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MMIO)); if (wm) { EnterCriticalSection(&WINMM_cs); /* lookup next unallocated WORD handle, with a non NULL value */ while (++MMIO_counter == 0 || MMIO_Get((HMMIO)(ULONG_PTR)MMIO_counter)); wm->info.hmmio = (HMMIO)(ULONG_PTR)MMIO_counter; wm->lpNext = MMIOList; MMIOList = wm; LeaveCriticalSection(&WINMM_cs); } return wm; }
/************************************************************************** * 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; }