Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmmio.c
Go to the documentation of this file.
00001 /* 00002 * MMIO functions 00003 * 00004 * Copyright 1998 Andrew Taylor 00005 * Copyright 1998 Ove Kåven 00006 * Copyright 2000,2002 Eric Pouech 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 /* Still to be done: 00024 * + correct handling of global/local IOProcs (and temporary IOProcs) 00025 * + mode of mmio objects is not used (read vs write vs readwrite) 00026 * + thread safeness 00027 * + 32 A <=> W message mapping 00028 */ 00029 00030 00031 #include <ctype.h> 00032 #include <stdarg.h> 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include <errno.h> 00036 #include <assert.h> 00037 00038 #include "windef.h" 00039 #include "winbase.h" 00040 #include "winnls.h" 00041 #include "mmsystem.h" 00042 #include "winemm.h" 00043 00044 #include "wine/debug.h" 00045 00046 WINE_DEFAULT_DEBUG_CHANNEL(mmio); 00047 00048 static WINE_MMIO *MMIOList; 00049 00050 /************************************************************************** 00051 * mmioDosIOProc [internal] 00052 */ 00053 static LRESULT CALLBACK mmioDosIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, 00054 LPARAM lParam1, LPARAM lParam2) 00055 { 00056 LRESULT ret = MMSYSERR_NOERROR; 00057 00058 TRACE("(%p, %X, 0x%lx, 0x%lx);\n", lpmmioinfo, uMessage, lParam1, lParam2); 00059 00060 switch (uMessage) { 00061 case MMIOM_OPEN: 00062 { 00063 /* Parameters: 00064 * lParam1 = szFileName parameter from mmioOpen 00065 * lParam2 = reserved 00066 * Returns: zero on success, error code on error 00067 * NOTE: lDiskOffset automatically set to zero 00068 */ 00069 LPCSTR szFileName = (LPCSTR)lParam1; 00070 00071 if (lpmmioinfo->dwFlags & MMIO_GETTEMP) { 00072 FIXME("MMIO_GETTEMP not implemented\n"); 00073 return MMIOERR_CANNOTOPEN; 00074 } 00075 00076 /* if filename NULL, assume open file handle in adwInfo[0] */ 00077 if (szFileName) { 00078 OFSTRUCT ofs; 00079 lpmmioinfo->adwInfo[0] = (DWORD)OpenFile(szFileName, &ofs, lpmmioinfo->dwFlags & 0xFFFF); 00080 } 00081 if (lpmmioinfo->adwInfo[0] == (DWORD)HFILE_ERROR) 00082 ret = MMIOERR_CANNOTOPEN; 00083 } 00084 break; 00085 00086 case MMIOM_CLOSE: 00087 /* Parameters: 00088 * lParam1 = wFlags parameter from mmioClose 00089 * lParam2 = unused 00090 * Returns: zero on success, error code on error 00091 */ 00092 if (!(lParam1 & MMIO_FHOPEN)) 00093 _lclose((HFILE)lpmmioinfo->adwInfo[0]); 00094 break; 00095 00096 case MMIOM_READ: 00097 /* Parameters: 00098 * lParam1 = huge pointer to read buffer 00099 * lParam2 = number of bytes to read 00100 * Returns: number of bytes read, 0 for EOF, -1 for error (error code 00101 * in wErrorRet) 00102 */ 00103 ret = _lread((HFILE)lpmmioinfo->adwInfo[0], (HPSTR)lParam1, (LONG)lParam2); 00104 if (ret != -1) 00105 lpmmioinfo->lDiskOffset += ret; 00106 00107 break; 00108 00109 case MMIOM_WRITE: 00110 case MMIOM_WRITEFLUSH: 00111 /* no internal buffering, so WRITEFLUSH handled same as WRITE */ 00112 00113 /* Parameters: 00114 * lParam1 = huge pointer to write buffer 00115 * lParam2 = number of bytes to write 00116 * Returns: number of bytes written, -1 for error (error code in 00117 * wErrorRet) 00118 */ 00119 ret = _hwrite((HFILE)lpmmioinfo->adwInfo[0], (HPSTR)lParam1, (LONG)lParam2); 00120 if (ret != -1) 00121 lpmmioinfo->lDiskOffset += ret; 00122 break; 00123 00124 case MMIOM_SEEK: 00125 /* Parameters: 00126 * lParam1 = new position 00127 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END) 00128 * Returns: new file postion, -1 on error 00129 */ 00130 ret = _llseek((HFILE)lpmmioinfo->adwInfo[0], (LONG)lParam1, (LONG)lParam2); 00131 if (ret != -1) 00132 lpmmioinfo->lDiskOffset = ret; 00133 return ret; 00134 00135 case MMIOM_RENAME: 00136 /* Parameters: 00137 * lParam1 = old name 00138 * lParam2 = new name 00139 * Returns: zero on success, non-zero on failure 00140 */ 00141 if (!MoveFileA((const char*)lParam1, (const char*)lParam2)) 00142 ret = MMIOERR_FILENOTFOUND; 00143 break; 00144 00145 default: 00146 FIXME("unexpected message %u\n", uMessage); 00147 return 0; 00148 } 00149 00150 return ret; 00151 } 00152 00153 /************************************************************************** 00154 * mmioMemIOProc [internal] 00155 */ 00156 static LRESULT CALLBACK mmioMemIOProc(LPMMIOINFO lpmmioinfo, UINT uMessage, 00157 LPARAM lParam1, LPARAM lParam2) 00158 { 00159 TRACE("(%p,0x%04x,0x%08lx,0x%08lx)\n", lpmmioinfo, uMessage, lParam1, lParam2); 00160 00161 switch (uMessage) { 00162 00163 case MMIOM_OPEN: 00164 /* Parameters: 00165 * lParam1 = filename (must be NULL) 00166 * lParam2 = reserved 00167 * Returns: zero on success, error code on error 00168 * NOTE: lDiskOffset automatically set to zero 00169 */ 00170 /* FIXME: io proc shouldn't change it */ 00171 if (!(lpmmioinfo->dwFlags & MMIO_CREATE)) 00172 lpmmioinfo->pchEndRead = lpmmioinfo->pchEndWrite; 00173 lpmmioinfo->adwInfo[0] = HFILE_ERROR; 00174 return 0; 00175 00176 case MMIOM_CLOSE: 00177 /* Parameters: 00178 * lParam1 = wFlags parameter from mmioClose 00179 * lParam2 = unused 00180 * Returns: zero on success, error code on error 00181 */ 00182 return 0; 00183 00184 case MMIOM_READ: 00185 /* Parameters: 00186 * lParam1 = huge pointer to read buffer 00187 * lParam2 = number of bytes to read 00188 * Returns: number of bytes read, 0 for EOF, -1 for error (error code 00189 * in wErrorRet) 00190 * NOTE: lDiskOffset should be updated 00191 */ 00192 FIXME("MMIOM_READ on memory files should not occur, buffer may be lost!\n"); 00193 return 0; 00194 00195 case MMIOM_WRITE: 00196 case MMIOM_WRITEFLUSH: 00197 /* no internal buffering, so WRITEFLUSH handled same as WRITE */ 00198 00199 /* Parameters: 00200 * lParam1 = huge pointer to write buffer 00201 * lParam2 = number of bytes to write 00202 * Returns: number of bytes written, -1 for error (error code in 00203 * wErrorRet) 00204 * NOTE: lDiskOffset should be updated 00205 */ 00206 FIXME("MMIOM_WRITE on memory files should not occur, buffer may be lost!\n"); 00207 return 0; 00208 00209 case MMIOM_SEEK: 00210 /* Parameters: 00211 * lParam1 = new position 00212 * lParam2 = from whence to seek (SEEK_SET, SEEK_CUR, SEEK_END) 00213 * Returns: new file postion, -1 on error 00214 * NOTE: lDiskOffset should be updated 00215 */ 00216 FIXME("MMIOM_SEEK on memory files should not occur, buffer may be lost!\n"); 00217 return -1; 00218 00219 default: 00220 FIXME("unexpected message %u\n", uMessage); 00221 return 0; 00222 } 00223 } 00224 00225 /* This array will be the entire list for most apps 00226 * Note that temporary ioProcs will be stored with a 0 fourCC code 00227 */ 00228 00229 static struct IOProcList defaultProcs[] = { 00230 {&defaultProcs[1], FOURCC_DOS, (LPMMIOPROC)mmioDosIOProc, FALSE, 0}, 00231 {NULL, FOURCC_MEM, (LPMMIOPROC)mmioMemIOProc, FALSE, 0}, 00232 }; 00233 00234 static struct IOProcList* pIOProcListAnchor = &defaultProcs[0]; 00235 00236 /**************************************************************** 00237 * MMIO_FindProcNode [INTERNAL] 00238 * 00239 * Finds the ProcList node associated with a given FOURCC code. 00240 */ 00241 static struct IOProcList* MMIO_FindProcNode(FOURCC fccIOProc) 00242 { 00243 struct IOProcList* pListNode; 00244 00245 for (pListNode = pIOProcListAnchor; pListNode; pListNode = pListNode->pNext) { 00246 if (pListNode->fourCC == fccIOProc) { 00247 return pListNode; 00248 } 00249 } 00250 return NULL; 00251 } 00252 00253 /**************************************************************** 00254 * MMIO_InstallIOProc [INTERNAL] 00255 */ 00256 static LPMMIOPROC MMIO_InstallIOProc(FOURCC fccIOProc, LPMMIOPROC pIOProc, 00257 DWORD dwFlags, BOOL is_unicode) 00258 { 00259 LPMMIOPROC lpProc = NULL; 00260 struct IOProcList* pListNode; 00261 struct IOProcList** ppListNode; 00262 00263 TRACE("(%08x, %p, %08X, %s)\n", fccIOProc, pIOProc, dwFlags, is_unicode ? "unicode" : "ansi"); 00264 00265 if (dwFlags & MMIO_GLOBALPROC) 00266 FIXME("Global procedures not implemented\n"); 00267 00268 /* just handle the known procedures for now */ 00269 switch (dwFlags & (MMIO_INSTALLPROC|MMIO_REMOVEPROC|MMIO_FINDPROC)) { 00270 case MMIO_INSTALLPROC: 00271 /* Create new entry for the IOProc list */ 00272 pListNode = HeapAlloc(GetProcessHeap(), 0, sizeof(*pListNode)); 00273 if (pListNode) { 00274 /* Fill in this node */ 00275 pListNode->fourCC = fccIOProc; 00276 pListNode->pIOProc = pIOProc; 00277 pListNode->is_unicode = is_unicode; 00278 pListNode->count = 0; 00279 00280 /* Stick it on the end of the list */ 00281 pListNode->pNext = pIOProcListAnchor; 00282 pIOProcListAnchor = pListNode; 00283 00284 /* Return this IOProc - that's how the caller knows we succeeded */ 00285 lpProc = pIOProc; 00286 } 00287 break; 00288 00289 case MMIO_REMOVEPROC: 00290 /* 00291 * Search for the node that we're trying to remove 00292 * We search for a matching fourCC code if it's non null, or the proc 00293 * address otherwise 00294 * note that this method won't find the first item on the list, but 00295 * since the first two items on this list are ones we won't 00296 * let the user delete anyway, that's okay 00297 */ 00298 ppListNode = &pIOProcListAnchor; 00299 while ((*ppListNode) && 00300 ((fccIOProc != 0) ? 00301 (*ppListNode)->fourCC != fccIOProc : 00302 (*ppListNode)->pIOProc != pIOProc)) 00303 ppListNode = &((*ppListNode)->pNext); 00304 00305 if (*ppListNode) { /* found it */ 00306 /* FIXME: what should be done if an open mmio object uses this proc ? 00307 * shall we return an error, nuke the mmio object ? 00308 */ 00309 if ((*ppListNode)->count) { 00310 ERR("Cannot remove a mmIOProc while in use\n"); 00311 break; 00312 } 00313 /* remove it, but only if it isn't builtin */ 00314 if ((*ppListNode) >= defaultProcs && 00315 (*ppListNode) < defaultProcs + sizeof(defaultProcs) / sizeof(defaultProcs[0])) { 00316 WARN("Tried to remove built-in mmio proc. Skipping\n"); 00317 } else { 00318 /* Okay, nuke it */ 00319 struct IOProcList* ptmpNode = *ppListNode; 00320 lpProc = (*ppListNode)->pIOProc; 00321 *ppListNode = (*ppListNode)->pNext; 00322 HeapFree(GetProcessHeap(), 0, ptmpNode); 00323 } 00324 } 00325 break; 00326 00327 case MMIO_FINDPROC: 00328 if ((pListNode = MMIO_FindProcNode(fccIOProc))) { 00329 lpProc = pListNode->pIOProc; 00330 } 00331 break; 00332 } 00333 00334 return lpProc; 00335 } 00336 00337 /**************************************************************** 00338 * send_message [INTERNAL] 00339 */ 00340 static LRESULT send_message(struct IOProcList* ioProc, LPMMIOINFO mmioinfo, 00341 DWORD wMsg, LPARAM lParam1, 00342 LPARAM lParam2, BOOL is_unicode) 00343 { 00344 LRESULT result = MMSYSERR_ERROR; 00345 LPARAM lp1 = lParam1, lp2 = lParam2; 00346 00347 if (!ioProc) { 00348 ERR("ioProc NULL\n"); 00349 return MMSYSERR_INVALPARAM; 00350 } 00351 00352 if (ioProc->is_unicode != is_unicode) { 00353 /* map (lParam1, lParam2) into (lp1, lp2) 32 A<=>W */ 00354 FIXME("NIY 32 A<=>W mapping\n"); 00355 } 00356 result = (ioProc->pIOProc)((LPSTR)mmioinfo, wMsg, lp1, lp2); 00357 00358 #if 0 00359 if (ioProc->is_unicode != is_unicode) { 00360 /* unmap (lParam1, lParam2) into (lp1, lp2) 32 A<=>W */ 00361 } 00362 #endif 00363 00364 return result; 00365 } 00366 00367 /************************************************************************** 00368 * MMIO_ParseExtA [internal] 00369 * 00370 * Parses a filename for the extension. 00371 * 00372 * RETURNS 00373 * The FOURCC code for the extension if found, else 0. 00374 */ 00375 static FOURCC MMIO_ParseExtA(LPCSTR szFileName) 00376 { 00377 /* Filenames are of the form file.ext{+ABC} 00378 For now, we take the last '+' if present */ 00379 00380 FOURCC ret = 0; 00381 00382 /* Note that ext{Start,End} point to the . and + respectively */ 00383 LPSTR extEnd; 00384 LPSTR extStart; 00385 00386 TRACE("(%s)\n", debugstr_a(szFileName)); 00387 00388 if (!szFileName) 00389 return ret; 00390 00391 /* Find the last '.' */ 00392 extStart = strrchr(szFileName,'.'); 00393 00394 if (!extStart) { 00395 ERR("No . in szFileName: %s\n", debugstr_a(szFileName)); 00396 } else { 00397 CHAR ext[5]; 00398 00399 /* Find the '+' afterwards */ 00400 extEnd = strchr(extStart,'+'); 00401 if (extEnd) { 00402 00403 if (extEnd - extStart - 1 > 4) 00404 WARN("Extension length > 4\n"); 00405 lstrcpynA(ext, extStart + 1, min(extEnd-extStart,5)); 00406 00407 } else { 00408 /* No + so just an extension */ 00409 if (strlen(extStart) > 4) { 00410 WARN("Extension length > 4\n"); 00411 } 00412 lstrcpynA(ext, extStart + 1, 5); 00413 } 00414 TRACE("Got extension: %s\n", debugstr_a(ext)); 00415 00416 /* FOURCC codes identifying file-extensions must be uppercase */ 00417 ret = mmioStringToFOURCCA(ext, MMIO_TOUPPER); 00418 } 00419 return ret; 00420 } 00421 00422 /************************************************************************** 00423 * MMIO_Get [internal] 00424 * 00425 * Retrieves the mmio object from current process 00426 */ 00427 static LPWINE_MMIO MMIO_Get(HMMIO h) 00428 { 00429 LPWINE_MMIO wm = NULL; 00430 00431 EnterCriticalSection(&WINMM_cs); 00432 for (wm = MMIOList; wm; wm = wm->lpNext) { 00433 if (wm->info.hmmio == h) 00434 break; 00435 } 00436 LeaveCriticalSection(&WINMM_cs); 00437 return wm; 00438 } 00439 00440 /************************************************************************** 00441 * MMIO_Create [internal] 00442 * 00443 * Creates an internal representation for a mmio instance 00444 */ 00445 static LPWINE_MMIO MMIO_Create(void) 00446 { 00447 static WORD MMIO_counter = 0; 00448 LPWINE_MMIO wm; 00449 00450 wm = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MMIO)); 00451 if (wm) { 00452 EnterCriticalSection(&WINMM_cs); 00453 /* lookup next unallocated WORD handle, with a non NULL value */ 00454 while (++MMIO_counter == 0 || MMIO_Get((HMMIO)(ULONG_PTR)MMIO_counter)); 00455 wm->info.hmmio = (HMMIO)(ULONG_PTR)MMIO_counter; 00456 wm->lpNext = MMIOList; 00457 MMIOList = wm; 00458 LeaveCriticalSection(&WINMM_cs); 00459 } 00460 return wm; 00461 } 00462 00463 /************************************************************************** 00464 * MMIO_Destroy [internal] 00465 *- 00466 * Destroys an internal representation for a mmio instance 00467 */ 00468 static BOOL MMIO_Destroy(LPWINE_MMIO wm) 00469 { 00470 LPWINE_MMIO* m; 00471 00472 EnterCriticalSection(&WINMM_cs); 00473 /* search for the matching one... */ 00474 m = &MMIOList; 00475 while (*m && *m != wm) m = &(*m)->lpNext; 00476 /* ...and destroy */ 00477 if (*m) { 00478 *m = (*m)->lpNext; 00479 HeapFree(GetProcessHeap(), 0, wm); 00480 wm = NULL; 00481 } 00482 LeaveCriticalSection(&WINMM_cs); 00483 return wm ? FALSE : TRUE; 00484 } 00485 00486 /**************************************************************** 00487 * MMIO_Flush [INTERNAL] 00488 */ 00489 static MMRESULT MMIO_Flush(WINE_MMIO* wm, UINT uFlags) 00490 { 00491 if (wm->info.cchBuffer && (wm->info.fccIOProc != FOURCC_MEM)) { 00492 /* not quite sure what to do here, but I'll guess */ 00493 if (wm->info.dwFlags & MMIO_DIRTY) { 00494 /* FIXME: error handling */ 00495 send_message(wm->ioProc, &wm->info, MMIOM_SEEK, wm->info.lBufOffset, SEEK_SET, FALSE); 00496 send_message(wm->ioProc, &wm->info, MMIOM_WRITE, 00497 (LPARAM)wm->info.pchBuffer, 00498 wm->info.pchNext - wm->info.pchBuffer, FALSE); 00499 } 00500 if (uFlags & MMIO_EMPTYBUF) 00501 wm->info.pchNext = wm->info.pchEndRead = wm->info.pchBuffer; 00502 } 00503 wm->info.dwFlags &= ~MMIO_DIRTY; 00504 00505 return MMSYSERR_NOERROR; 00506 } 00507 00508 /*************************************************************************** 00509 * MMIO_GrabNextBuffer [INTERNAL] 00510 */ 00511 static LONG MMIO_GrabNextBuffer(LPWINE_MMIO wm, int for_read) 00512 { 00513 LONG size = wm->info.cchBuffer; 00514 00515 TRACE("bo=%x do=%x of=%lx\n", 00516 wm->info.lBufOffset, wm->info.lDiskOffset, 00517 send_message(wm->ioProc, &wm->info, MMIOM_SEEK, 0, SEEK_CUR, FALSE)); 00518 00519 wm->info.lBufOffset = wm->info.lDiskOffset; 00520 wm->info.pchNext = wm->info.pchBuffer; 00521 wm->info.pchEndRead = wm->info.pchBuffer; 00522 wm->info.pchEndWrite = wm->info.pchBuffer + wm->info.cchBuffer; 00523 00524 wm->bBufferLoaded = TRUE; 00525 if (for_read) { 00526 size = send_message(wm->ioProc, &wm->info, MMIOM_READ, 00527 (LPARAM)wm->info.pchBuffer, size, FALSE); 00528 if (size > 0) 00529 wm->info.pchEndRead += size; 00530 else 00531 wm->bBufferLoaded = FALSE; 00532 } 00533 00534 return size; 00535 } 00536 00537 /*************************************************************************** 00538 * MMIO_SetBuffer [INTERNAL] 00539 */ 00540 static MMRESULT MMIO_SetBuffer(WINE_MMIO* wm, void* pchBuffer, LONG cchBuffer, 00541 UINT uFlags) 00542 { 00543 TRACE("(%p %p %d %u)\n", wm, pchBuffer, cchBuffer, uFlags); 00544 00545 if (cchBuffer > 0xFFFF) 00546 WARN("Untested handling of huge mmio buffers (%d >= 64k)\n", cchBuffer); 00547 00548 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR) 00549 return MMIOERR_CANNOTWRITE; 00550 00551 /* free previous buffer if allocated */ 00552 if (wm->info.dwFlags & MMIO_ALLOCBUF) { 00553 HeapFree(GetProcessHeap(), 0, wm->info.pchBuffer); 00554 wm->info.pchBuffer = NULL; 00555 wm->info.dwFlags &= ~MMIO_ALLOCBUF; 00556 } 00557 00558 if (pchBuffer) { 00559 wm->info.pchBuffer = pchBuffer; 00560 } else if (cchBuffer) { 00561 if (!(wm->info.pchBuffer = HeapAlloc(GetProcessHeap(), 0, cchBuffer))) 00562 return MMIOERR_OUTOFMEMORY; 00563 wm->info.dwFlags |= MMIO_ALLOCBUF; 00564 } else { 00565 wm->info.pchBuffer = NULL; 00566 } 00567 00568 wm->info.cchBuffer = cchBuffer; 00569 wm->info.pchNext = wm->info.pchBuffer; 00570 wm->info.pchEndRead = wm->info.pchBuffer; 00571 wm->info.pchEndWrite = wm->info.pchBuffer + cchBuffer; 00572 wm->info.lBufOffset = wm->info.lDiskOffset; 00573 wm->bBufferLoaded = FALSE; 00574 00575 return MMSYSERR_NOERROR; 00576 } 00577 00578 /************************************************************************** 00579 * MMIO_Open [internal] 00580 */ 00581 static HMMIO MMIO_Open(LPSTR szFileName, MMIOINFO* refmminfo, DWORD dwOpenFlags, BOOL is_unicode) 00582 { 00583 LPWINE_MMIO wm; 00584 MMIOINFO mmioinfo; 00585 00586 TRACE("('%s', %p, %08X, %s);\n", szFileName, refmminfo, dwOpenFlags, is_unicode ? "unicode" : "ansi"); 00587 00588 if (!refmminfo) { 00589 refmminfo = &mmioinfo; 00590 00591 mmioinfo.fccIOProc = 0; 00592 mmioinfo.pIOProc = NULL; 00593 mmioinfo.pchBuffer = NULL; 00594 mmioinfo.cchBuffer = 0; 00595 is_unicode = FALSE; 00596 } 00597 00598 if (dwOpenFlags & (MMIO_PARSE|MMIO_EXIST)) { 00599 char buffer[MAX_PATH]; 00600 00601 if (!szFileName) 00602 return (HMMIO)FALSE; 00603 if (GetFullPathNameA(szFileName, sizeof(buffer), buffer, NULL) >= sizeof(buffer)) 00604 return (HMMIO)FALSE; 00605 if ((dwOpenFlags & MMIO_EXIST) && (GetFileAttributesA(buffer) == INVALID_FILE_ATTRIBUTES)) 00606 return (HMMIO)FALSE; 00607 strcpy(szFileName, buffer); 00608 return (HMMIO)TRUE; 00609 } 00610 00611 if ((wm = MMIO_Create()) == NULL) 00612 return 0; 00613 00614 /* If both params are NULL, then parse the file name if available */ 00615 if (refmminfo->fccIOProc == 0 && refmminfo->pIOProc == NULL) { 00616 wm->info.fccIOProc = MMIO_ParseExtA(szFileName); 00617 /* Handle any unhandled/error case. Assume DOS file */ 00618 if (wm->info.fccIOProc == 0) 00619 wm->info.fccIOProc = FOURCC_DOS; 00620 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) { 00621 /* If not found, retry with FOURCC_DOS */ 00622 wm->info.fccIOProc = FOURCC_DOS; 00623 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) 00624 goto error2; 00625 } 00626 wm->bTmpIOProc = FALSE; 00627 } 00628 /* if just the four character code is present, look up IO proc */ 00629 else if (refmminfo->pIOProc == NULL) { 00630 wm->info.fccIOProc = refmminfo->fccIOProc; 00631 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2; 00632 wm->bTmpIOProc = FALSE; 00633 } 00634 /* if IO proc specified, use it and specified four character code */ 00635 else { 00636 wm->info.fccIOProc = refmminfo->fccIOProc; 00637 MMIO_InstallIOProc(wm->info.fccIOProc, refmminfo->pIOProc, 00638 MMIO_INSTALLPROC, is_unicode); 00639 if (!(wm->ioProc = MMIO_FindProcNode(wm->info.fccIOProc))) goto error2; 00640 assert(wm->ioProc->pIOProc == refmminfo->pIOProc); 00641 wm->bTmpIOProc = TRUE; 00642 } 00643 00644 wm->ioProc->count++; 00645 wm->info.dwFlags = dwOpenFlags; 00646 00647 if (dwOpenFlags & MMIO_ALLOCBUF) { 00648 refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer, 00649 refmminfo->cchBuffer ? refmminfo->cchBuffer : MMIO_DEFAULTBUFFER, 0); 00650 if (refmminfo->wErrorRet != MMSYSERR_NOERROR) 00651 goto error1; 00652 } else { 00653 refmminfo->wErrorRet = MMIO_SetBuffer(wm, refmminfo->pchBuffer, refmminfo->cchBuffer, 0); 00654 if (refmminfo->wErrorRet != MMSYSERR_NOERROR) 00655 goto error1; 00656 } 00657 00658 if (wm->info.fccIOProc == FOURCC_MEM && !(wm->info.dwFlags & MMIO_ALLOCBUF)) 00659 wm->bBufferLoaded = TRUE; 00660 00661 /* see mmioDosIOProc for that one */ 00662 wm->info.adwInfo[0] = refmminfo->adwInfo[0]; 00663 00664 /* call IO proc to actually open file */ 00665 refmminfo->wErrorRet = send_message(wm->ioProc, &wm->info, MMIOM_OPEN, 00666 (LPARAM)szFileName, 0, FALSE); 00667 00668 /* grab file size, when possible (FIXME: not 64 bit safe) */ 00669 wm->dwFileSize = GetFileSize((HANDLE)(ULONG_PTR)wm->info.adwInfo[0], NULL); 00670 00671 if (refmminfo->wErrorRet == 0) 00672 return wm->info.hmmio; 00673 error1: 00674 if (wm->ioProc) wm->ioProc->count--; 00675 error2: 00676 MMIO_Destroy(wm); 00677 return 0; 00678 } 00679 00680 /************************************************************************** 00681 * mmioOpenW [WINMM.@] 00682 */ 00683 HMMIO WINAPI mmioOpenW(LPWSTR szFileName, MMIOINFO* lpmmioinfo, 00684 DWORD dwOpenFlags) 00685 { 00686 HMMIO ret; 00687 LPSTR szFn = NULL; 00688 00689 if (szFileName) 00690 { 00691 INT len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL ); 00692 szFn = HeapAlloc( GetProcessHeap(), 0, len ); 00693 if (!szFn) return NULL; 00694 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL ); 00695 } 00696 00697 ret = MMIO_Open(szFn, lpmmioinfo, dwOpenFlags, TRUE); 00698 00699 HeapFree(GetProcessHeap(), 0, szFn); 00700 return ret; 00701 } 00702 00703 /************************************************************************** 00704 * mmioOpenA [WINMM.@] 00705 */ 00706 HMMIO WINAPI mmioOpenA(LPSTR szFileName, MMIOINFO* lpmmioinfo, 00707 DWORD dwOpenFlags) 00708 { 00709 return MMIO_Open(szFileName, lpmmioinfo, dwOpenFlags, FALSE); 00710 } 00711 00712 /************************************************************************** 00713 * mmioClose [WINMM.@] 00714 */ 00715 MMRESULT WINAPI mmioClose(HMMIO hmmio, UINT uFlags) 00716 { 00717 LPWINE_MMIO wm; 00718 MMRESULT result; 00719 00720 TRACE("(%p, %04X);\n", hmmio, uFlags); 00721 00722 if ((wm = MMIO_Get(hmmio)) == NULL) 00723 return MMSYSERR_INVALHANDLE; 00724 00725 if ((result = MMIO_Flush(wm, 0)) != MMSYSERR_NOERROR) 00726 return result; 00727 00728 result = send_message(wm->ioProc, &wm->info, MMIOM_CLOSE, uFlags, 0, FALSE); 00729 00730 MMIO_SetBuffer(wm, NULL, 0, 0); 00731 00732 wm->ioProc->count--; 00733 00734 if (wm->bTmpIOProc) 00735 MMIO_InstallIOProc(wm->info.fccIOProc, wm->ioProc->pIOProc, 00736 MMIO_REMOVEPROC, wm->ioProc->is_unicode); 00737 00738 MMIO_Destroy(wm); 00739 00740 return result; 00741 } 00742 00743 /************************************************************************** 00744 * mmioRead [WINMM.@] 00745 */ 00746 LONG WINAPI mmioRead(HMMIO hmmio, HPSTR pch, LONG cch) 00747 { 00748 LPWINE_MMIO wm; 00749 LONG count; 00750 00751 TRACE("(%p, %p, %d);\n", hmmio, pch, cch); 00752 00753 if ((wm = MMIO_Get(hmmio)) == NULL) 00754 return -1; 00755 00756 /* unbuffered case first */ 00757 if (!wm->info.pchBuffer) 00758 return send_message(wm->ioProc, &wm->info, MMIOM_READ, (LPARAM)pch, cch, FALSE); 00759 00760 /* first try from current buffer */ 00761 if (wm->info.pchNext != wm->info.pchEndRead) { 00762 count = wm->info.pchEndRead - wm->info.pchNext; 00763 if (count > cch || count < 0) count = cch; 00764 memcpy(pch, wm->info.pchNext, count); 00765 wm->info.pchNext += count; 00766 pch += count; 00767 cch -= count; 00768 } else 00769 count = 0; 00770 00771 if (cch && (wm->info.fccIOProc != FOURCC_MEM)) { 00772 assert(wm->info.cchBuffer); 00773 00774 while (cch) { 00775 LONG size; 00776 00777 size = MMIO_GrabNextBuffer(wm, TRUE); 00778 if (size <= 0) break; 00779 if (size > cch) size = cch; 00780 memcpy(pch, wm->info.pchBuffer, size); 00781 wm->info.pchNext += size; 00782 pch += size; 00783 cch -= size; 00784 count += size; 00785 } 00786 } 00787 00788 TRACE("count=%d\n", count); 00789 return count; 00790 } 00791 00792 /************************************************************************** 00793 * mmioWrite [WINMM.@] 00794 */ 00795 LONG WINAPI mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch) 00796 { 00797 LPWINE_MMIO wm; 00798 LONG count; 00799 00800 TRACE("(%p, %p, %d);\n", hmmio, pch, cch); 00801 00802 if ((wm = MMIO_Get(hmmio)) == NULL) 00803 return -1; 00804 00805 if (wm->info.cchBuffer) { 00806 LONG bytesW = 0; 00807 00808 count = 0; 00809 while (cch) { 00810 if (wm->info.pchNext != wm->info.pchEndWrite) { 00811 count = wm->info.pchEndWrite - wm->info.pchNext; 00812 if (count > cch || count < 0) count = cch; 00813 memcpy(wm->info.pchNext, pch, count); 00814 wm->info.pchNext += count; 00815 pch += count; 00816 cch -= count; 00817 bytesW += count; 00818 wm->info.dwFlags |= MMIO_DIRTY; 00819 } else { 00820 if (wm->info.fccIOProc == FOURCC_MEM) { 00821 if (wm->info.adwInfo[0]) { 00822 /* from where would we get the memory handle? */ 00823 FIXME("memory file expansion not implemented!\n"); 00824 break; 00825 } else break; 00826 } 00827 } 00828 00829 if (wm->info.pchNext == wm->info.pchEndWrite) 00830 { 00831 MMIO_Flush(wm, MMIO_EMPTYBUF); 00832 MMIO_GrabNextBuffer(wm, FALSE); 00833 } 00834 else break; 00835 } 00836 count = bytesW; 00837 } else { 00838 count = send_message(wm->ioProc, &wm->info, MMIOM_WRITE, (LPARAM)pch, cch, FALSE); 00839 wm->info.lBufOffset = wm->info.lDiskOffset; 00840 } 00841 00842 TRACE("bytes written=%d\n", count); 00843 return count; 00844 } 00845 00846 /************************************************************************** 00847 * mmioSeek [WINMM.@] 00848 */ 00849 LONG WINAPI mmioSeek(HMMIO hmmio, LONG lOffset, INT iOrigin) 00850 { 00851 LPWINE_MMIO wm; 00852 LONG offset; 00853 00854 TRACE("(%p, %08X, %d);\n", hmmio, lOffset, iOrigin); 00855 00856 if ((wm = MMIO_Get(hmmio)) == NULL) 00857 return MMSYSERR_INVALHANDLE; 00858 00859 /* not buffered, direct seek on file */ 00860 if (!wm->info.pchBuffer) 00861 return send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lOffset, iOrigin, FALSE); 00862 00863 switch (iOrigin) { 00864 case SEEK_SET: 00865 offset = lOffset; 00866 break; 00867 case SEEK_CUR: 00868 offset = wm->info.lBufOffset + (wm->info.pchNext - wm->info.pchBuffer) + lOffset; 00869 break; 00870 case SEEK_END: 00871 offset = ((wm->info.fccIOProc == FOURCC_MEM)? wm->info.cchBuffer : wm->dwFileSize) - lOffset; 00872 break; 00873 default: 00874 return -1; 00875 } 00876 00877 if (offset && offset >= wm->dwFileSize && wm->info.fccIOProc != FOURCC_MEM) { 00878 /* should check that write mode exists */ 00879 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR) 00880 return -1; 00881 wm->info.lBufOffset = offset; 00882 wm->info.pchEndRead = wm->info.pchBuffer; 00883 wm->info.pchEndWrite = wm->info.pchBuffer + wm->info.cchBuffer; 00884 if ((wm->info.dwFlags & MMIO_RWMODE) == MMIO_READ) { 00885 wm->info.lDiskOffset = wm->dwFileSize; 00886 } 00887 } else if ((wm->info.cchBuffer > 0) && 00888 ((offset < wm->info.lBufOffset) || 00889 (offset >= wm->info.lBufOffset + wm->info.cchBuffer) || 00890 !wm->bBufferLoaded)) { 00891 /* stay in same buffer ? */ 00892 /* some memory mapped buffers are defined with -1 as a size */ 00893 00894 /* condition to change buffer */ 00895 if ((wm->info.fccIOProc == FOURCC_MEM) || 00896 MMIO_Flush(wm, 0) != MMSYSERR_NOERROR || 00897 /* this also sets the wm->info.lDiskOffset field */ 00898 send_message(wm->ioProc, &wm->info, MMIOM_SEEK, 00899 (offset / wm->info.cchBuffer) * wm->info.cchBuffer, 00900 SEEK_SET, FALSE) == -1) 00901 return -1; 00902 MMIO_GrabNextBuffer(wm, TRUE); 00903 } 00904 00905 wm->info.pchNext = wm->info.pchBuffer + (offset - wm->info.lBufOffset); 00906 00907 TRACE("=> %d\n", offset); 00908 return offset; 00909 } 00910 00911 /************************************************************************** 00912 * mmioGetInfo [WINMM.@] 00913 */ 00914 MMRESULT WINAPI mmioGetInfo(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags) 00915 { 00916 LPWINE_MMIO wm; 00917 00918 TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags); 00919 00920 if ((wm = MMIO_Get(hmmio)) == NULL) 00921 return MMSYSERR_INVALHANDLE; 00922 00923 *lpmmioinfo = wm->info; 00924 00925 return MMSYSERR_NOERROR; 00926 } 00927 00928 /************************************************************************** 00929 * mmioSetInfo [WINMM.@] 00930 */ 00931 MMRESULT WINAPI mmioSetInfo(HMMIO hmmio, const MMIOINFO* lpmmioinfo, UINT uFlags) 00932 { 00933 LPWINE_MMIO wm; 00934 00935 TRACE("(%p,%p,0x%08x)\n",hmmio,lpmmioinfo,uFlags); 00936 00937 if ((wm = MMIO_Get(hmmio)) == NULL) 00938 return MMSYSERR_INVALHANDLE; 00939 00940 /* check pointers coherence */ 00941 if (lpmmioinfo->pchNext < wm->info.pchBuffer || 00942 lpmmioinfo->pchNext > wm->info.pchBuffer + wm->info.cchBuffer || 00943 lpmmioinfo->pchEndRead < wm->info.pchBuffer || 00944 lpmmioinfo->pchEndRead > wm->info.pchBuffer + wm->info.cchBuffer || 00945 lpmmioinfo->pchEndWrite < wm->info.pchBuffer || 00946 lpmmioinfo->pchEndWrite > wm->info.pchBuffer + wm->info.cchBuffer) 00947 return MMSYSERR_INVALPARAM; 00948 00949 wm->info.pchNext = lpmmioinfo->pchNext; 00950 wm->info.pchEndRead = lpmmioinfo->pchEndRead; 00951 00952 return MMSYSERR_NOERROR; 00953 } 00954 00955 /************************************************************************** 00956 * mmioSetBuffer [WINMM.@] 00957 */ 00958 MMRESULT WINAPI mmioSetBuffer(HMMIO hmmio, LPSTR pchBuffer, LONG cchBuffer, UINT uFlags) 00959 { 00960 LPWINE_MMIO wm; 00961 00962 TRACE("(hmmio=%p, pchBuf=%p, cchBuf=%d, uFlags=%#08x)\n", 00963 hmmio, pchBuffer, cchBuffer, uFlags); 00964 00965 if ((wm = MMIO_Get(hmmio)) == NULL) 00966 return MMSYSERR_INVALHANDLE; 00967 00968 return MMIO_SetBuffer(wm, pchBuffer, cchBuffer, uFlags); 00969 } 00970 00971 /************************************************************************** 00972 * mmioFlush [WINMM.@] 00973 */ 00974 MMRESULT WINAPI mmioFlush(HMMIO hmmio, UINT uFlags) 00975 { 00976 LPWINE_MMIO wm; 00977 00978 TRACE("(%p, %04X)\n", hmmio, uFlags); 00979 00980 if ((wm = MMIO_Get(hmmio)) == NULL) 00981 return MMSYSERR_INVALHANDLE; 00982 00983 return MMIO_Flush(wm, uFlags); 00984 } 00985 00986 /************************************************************************** 00987 * mmioAdvance [WINMM.@] 00988 */ 00989 MMRESULT WINAPI mmioAdvance(HMMIO hmmio, MMIOINFO* lpmmioinfo, UINT uFlags) 00990 { 00991 LPWINE_MMIO wm; 00992 00993 TRACE("hmmio=%p, lpmmioinfo=%p, uFlags=%04X\n", hmmio, lpmmioinfo, uFlags); 00994 00995 /* NOTE: mmioAdvance16 heavily relies on parameters from lpmmioinfo we're using 00996 * here. be sure if you change something here to check mmioAdvance16 as well 00997 */ 00998 if ((wm = MMIO_Get(hmmio)) == NULL) 00999 return MMSYSERR_INVALHANDLE; 01000 01001 if (!wm->info.cchBuffer) 01002 return MMIOERR_UNBUFFERED; 01003 01004 if (uFlags != MMIO_READ && uFlags != MMIO_WRITE) 01005 return MMSYSERR_INVALPARAM; 01006 01007 if (uFlags == MMIO_WRITE && (lpmmioinfo->dwFlags & MMIO_DIRTY)) 01008 { 01009 send_message(wm->ioProc, &wm->info, MMIOM_SEEK, lpmmioinfo->lBufOffset, SEEK_SET, FALSE); 01010 send_message(wm->ioProc, &wm->info, MMIOM_WRITE, (LPARAM)lpmmioinfo->pchBuffer, 01011 lpmmioinfo->pchNext - lpmmioinfo->pchBuffer, FALSE); 01012 lpmmioinfo->dwFlags &= ~MMIO_DIRTY; 01013 } 01014 if (MMIO_Flush(wm, 0) != MMSYSERR_NOERROR) 01015 return MMIOERR_CANNOTWRITE; 01016 01017 if (lpmmioinfo) { 01018 wm->dwFileSize = max(wm->dwFileSize, lpmmioinfo->lBufOffset + 01019 (lpmmioinfo->pchNext - lpmmioinfo->pchBuffer)); 01020 } 01021 MMIO_GrabNextBuffer(wm, uFlags == MMIO_READ); 01022 01023 if (lpmmioinfo) { 01024 lpmmioinfo->pchNext = lpmmioinfo->pchBuffer; 01025 lpmmioinfo->pchEndRead = lpmmioinfo->pchBuffer + 01026 (wm->info.pchEndRead - wm->info.pchBuffer); 01027 lpmmioinfo->pchEndWrite = lpmmioinfo->pchBuffer + 01028 (wm->info.pchEndWrite - wm->info.pchBuffer); 01029 lpmmioinfo->lDiskOffset = wm->info.lDiskOffset; 01030 lpmmioinfo->lBufOffset = wm->info.lBufOffset; 01031 } 01032 return MMSYSERR_NOERROR; 01033 } 01034 01035 /************************************************************************** 01036 * mmioStringToFOURCCA [WINMM.@] 01037 */ 01038 FOURCC WINAPI mmioStringToFOURCCA(LPCSTR sz, UINT uFlags) 01039 { 01040 CHAR cc[4]; 01041 int i = 0; 01042 01043 for (i = 0; i < 4 && sz[i]; i++) { 01044 if (uFlags & MMIO_TOUPPER) { 01045 cc[i] = toupper(sz[i]); 01046 } else { 01047 cc[i] = sz[i]; 01048 } 01049 } 01050 01051 /* Pad with spaces */ 01052 while (i < 4) cc[i++] = ' '; 01053 01054 TRACE("Got '%.4s'\n",cc); 01055 return mmioFOURCC(cc[0],cc[1],cc[2],cc[3]); 01056 } 01057 01058 /************************************************************************** 01059 * mmioStringToFOURCCW [WINMM.@] 01060 */ 01061 FOURCC WINAPI mmioStringToFOURCCW(LPCWSTR sz, UINT uFlags) 01062 { 01063 char szA[4]; 01064 01065 WideCharToMultiByte( CP_ACP, 0, sz, 4, szA, sizeof(szA), NULL, NULL ); 01066 return mmioStringToFOURCCA(szA,uFlags); 01067 } 01068 01069 /************************************************************************** 01070 * mmioInstallIOProcA [WINMM.@] 01071 */ 01072 LPMMIOPROC WINAPI mmioInstallIOProcA(FOURCC fccIOProc, 01073 LPMMIOPROC pIOProc, DWORD dwFlags) 01074 { 01075 return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, FALSE); 01076 } 01077 01078 /************************************************************************** 01079 * mmioInstallIOProcW [WINMM.@] 01080 */ 01081 LPMMIOPROC WINAPI mmioInstallIOProcW(FOURCC fccIOProc, 01082 LPMMIOPROC pIOProc, DWORD dwFlags) 01083 { 01084 return MMIO_InstallIOProc(fccIOProc, pIOProc, dwFlags, TRUE); 01085 } 01086 01087 /****************************************************************** 01088 * MMIO_SendMessage 01089 * 01090 * 01091 */ 01092 static LRESULT MMIO_SendMessage(HMMIO hmmio, UINT uMessage, LPARAM lParam1, 01093 LPARAM lParam2, BOOL is_unicode) 01094 { 01095 LPWINE_MMIO wm; 01096 01097 TRACE("(%p, %u, %ld, %ld, %s)\n", hmmio, uMessage, lParam1, lParam2, is_unicode ? "unicode" : "ansi"); 01098 01099 if (uMessage < MMIOM_USER) 01100 return MMSYSERR_INVALPARAM; 01101 01102 if ((wm = MMIO_Get(hmmio)) == NULL) 01103 return MMSYSERR_INVALHANDLE; 01104 01105 return send_message(wm->ioProc, &wm->info, uMessage, lParam1, lParam2, is_unicode); 01106 } 01107 01108 /************************************************************************** 01109 * mmioSendMessage [WINMM.@] 01110 */ 01111 LRESULT WINAPI mmioSendMessage(HMMIO hmmio, UINT uMessage, 01112 LPARAM lParam1, LPARAM lParam2) 01113 { 01114 return MMIO_SendMessage(hmmio, uMessage, lParam1, lParam2, FALSE); 01115 } 01116 01117 /************************************************************************** 01118 * mmioDescend [WINMM.@] 01119 */ 01120 MMRESULT WINAPI mmioDescend(HMMIO hmmio, LPMMCKINFO lpck, 01121 const MMCKINFO* lpckParent, UINT uFlags) 01122 { 01123 DWORD dwOldPos; 01124 FOURCC srchCkId; 01125 FOURCC srchType; 01126 01127 TRACE("(%p, %p, %p, %04X);\n", hmmio, lpck, lpckParent, uFlags); 01128 01129 if (lpck == NULL) 01130 return MMSYSERR_INVALPARAM; 01131 01132 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR); 01133 TRACE("dwOldPos=%d\n", dwOldPos); 01134 01135 if (lpckParent != NULL) { 01136 TRACE("seek inside parent at %d !\n", lpckParent->dwDataOffset); 01137 /* EPP: was dwOldPos = mmioSeek(hmmio,lpckParent->dwDataOffset,SEEK_SET); */ 01138 if (dwOldPos < lpckParent->dwDataOffset || 01139 dwOldPos >= lpckParent->dwDataOffset + lpckParent->cksize) { 01140 WARN("outside parent chunk\n"); 01141 return MMIOERR_CHUNKNOTFOUND; 01142 } 01143 } 01144 01145 /* The SDK docu says 'ckid' is used for all cases. Real World 01146 * examples disagree -Marcus,990216. 01147 */ 01148 01149 srchCkId = 0; 01150 srchType = 0; 01151 01152 /* find_chunk looks for 'ckid' */ 01153 if (uFlags & MMIO_FINDCHUNK) 01154 srchCkId = lpck->ckid; 01155 01156 /* find_riff and find_list look for 'fccType' */ 01157 if (uFlags & MMIO_FINDLIST) 01158 { 01159 srchCkId = FOURCC_LIST; 01160 srchType = lpck->fccType; 01161 } 01162 01163 if (uFlags & MMIO_FINDRIFF) 01164 { 01165 srchCkId = FOURCC_RIFF; 01166 srchType = lpck->fccType; 01167 } 01168 01169 TRACE("searching for %4.4s.%4.4s\n", 01170 (LPCSTR)&srchCkId, srchType ? (LPCSTR)&srchType : "any"); 01171 01172 while (TRUE) 01173 { 01174 LONG ix; 01175 01176 ix = mmioRead(hmmio, (LPSTR)lpck, 3 * sizeof(DWORD)); 01177 if (ix < 2*sizeof(DWORD)) 01178 { 01179 mmioSeek(hmmio, dwOldPos, SEEK_SET); 01180 WARN("return ChunkNotFound\n"); 01181 return MMIOERR_CHUNKNOTFOUND; 01182 } 01183 01184 lpck->dwDataOffset = dwOldPos + 2 * sizeof(DWORD); 01185 TRACE("ckid=%4.4s fcc=%4.4s cksize=%08X !\n", 01186 (LPCSTR)&lpck->ckid, 01187 srchType ? (LPCSTR)&lpck->fccType:"<na>", 01188 lpck->cksize); 01189 if ( (!srchCkId || (srchCkId == lpck->ckid)) && 01190 (!srchType || (srchType == lpck->fccType)) ) 01191 break; 01192 01193 dwOldPos = lpck->dwDataOffset + ((lpck->cksize + 1) & ~1); 01194 mmioSeek(hmmio, dwOldPos, SEEK_SET); 01195 } 01196 01197 lpck->dwFlags = 0; 01198 /* If we were looking for RIFF/LIST chunks, the final file position 01199 * is after the chunkid. If we were just looking for the chunk 01200 * it is after the cksize. So add 4 in RIFF/LIST case. 01201 */ 01202 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST) 01203 mmioSeek(hmmio, lpck->dwDataOffset + sizeof(DWORD), SEEK_SET); 01204 else 01205 { 01206 mmioSeek(hmmio, lpck->dwDataOffset, SEEK_SET); 01207 lpck->fccType = 0; 01208 } 01209 TRACE("lpck: ckid=%.4s, cksize=%d, dwDataOffset=%d fccType=%08X (%.4s)!\n", 01210 (LPSTR)&lpck->ckid, lpck->cksize, lpck->dwDataOffset, 01211 lpck->fccType, srchType?(LPSTR)&lpck->fccType:""); 01212 return MMSYSERR_NOERROR; 01213 } 01214 01215 /************************************************************************** 01216 * mmioAscend [WINMM.@] 01217 */ 01218 MMRESULT WINAPI mmioAscend(HMMIO hmmio, LPMMCKINFO lpck, UINT uFlags) 01219 { 01220 TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags); 01221 01222 if (lpck->dwFlags & MMIO_DIRTY) { 01223 DWORD dwOldPos, dwNewSize; 01224 01225 TRACE("Chunk is dirty, checking if chunk's size is correct\n"); 01226 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR); 01227 TRACE("dwOldPos=%d lpck->dwDataOffset = %d\n", dwOldPos, lpck->dwDataOffset); 01228 dwNewSize = dwOldPos - lpck->dwDataOffset; 01229 if (dwNewSize != lpck->cksize) { 01230 TRACE("Nope: lpck->cksize=%d dwNewSize=%d\n", lpck->cksize, dwNewSize); 01231 lpck->cksize = dwNewSize; 01232 01233 /* pad odd size with 0 */ 01234 if (dwNewSize & 1) { 01235 char ch = 0; 01236 mmioWrite(hmmio, &ch, 1); 01237 } 01238 mmioSeek(hmmio, lpck->dwDataOffset - sizeof(DWORD), SEEK_SET); 01239 mmioWrite(hmmio, (LPSTR)&dwNewSize, sizeof(DWORD)); 01240 } 01241 lpck->dwFlags = 0; 01242 } 01243 01244 mmioSeek(hmmio, lpck->dwDataOffset + ((lpck->cksize + 1) & ~1), SEEK_SET); 01245 01246 return MMSYSERR_NOERROR; 01247 } 01248 01249 /************************************************************************** 01250 * mmioCreateChunk [WINMM.@] 01251 */ 01252 MMRESULT WINAPI mmioCreateChunk(HMMIO hmmio, MMCKINFO* lpck, UINT uFlags) 01253 { 01254 DWORD dwOldPos; 01255 LONG size; 01256 LONG ix; 01257 01258 TRACE("(%p, %p, %04X);\n", hmmio, lpck, uFlags); 01259 01260 dwOldPos = mmioSeek(hmmio, 0, SEEK_CUR); 01261 TRACE("dwOldPos=%d\n", dwOldPos); 01262 01263 if (uFlags == MMIO_CREATELIST) 01264 lpck->ckid = FOURCC_LIST; 01265 else if (uFlags == MMIO_CREATERIFF) 01266 lpck->ckid = FOURCC_RIFF; 01267 01268 TRACE("ckid=%.4s\n", (LPSTR)&lpck->ckid); 01269 01270 size = 2 * sizeof(DWORD); 01271 lpck->dwDataOffset = dwOldPos + size; 01272 01273 if (lpck->ckid == FOURCC_RIFF || lpck->ckid == FOURCC_LIST) 01274 size += sizeof(DWORD); 01275 lpck->dwFlags = MMIO_DIRTY; 01276 01277 ix = mmioWrite(hmmio, (LPSTR)lpck, size); 01278 TRACE("after mmioWrite ix = %d req = %d, errno = %d\n", ix, size, errno); 01279 if (ix < size) { 01280 mmioSeek(hmmio, dwOldPos, SEEK_SET); 01281 WARN("return CannotWrite\n"); 01282 return MMIOERR_CANNOTWRITE; 01283 } 01284 01285 return MMSYSERR_NOERROR; 01286 } 01287 01288 /************************************************************************** 01289 * mmioRenameA [WINMM.@] 01290 */ 01291 MMRESULT WINAPI mmioRenameA(LPCSTR szFileName, LPCSTR szNewFileName, 01292 const MMIOINFO* lpmmioinfo, DWORD dwFlags) 01293 { 01294 struct IOProcList* ioProc = NULL; 01295 struct IOProcList tmp; 01296 FOURCC fcc; 01297 01298 TRACE("('%s', '%s', %p, %08X);\n", 01299 debugstr_a(szFileName), debugstr_a(szNewFileName), lpmmioinfo, dwFlags); 01300 01301 /* If both params are NULL, then parse the file name */ 01302 if (lpmmioinfo && lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL) 01303 { 01304 fcc = MMIO_ParseExtA(szFileName); 01305 if (fcc) ioProc = MMIO_FindProcNode(fcc); 01306 } 01307 01308 /* Handle any unhandled/error case from above. Assume DOS file */ 01309 if (!lpmmioinfo || (lpmmioinfo->fccIOProc == 0 && lpmmioinfo->pIOProc == NULL && ioProc == NULL)) 01310 ioProc = MMIO_FindProcNode(FOURCC_DOS); 01311 /* if just the four character code is present, look up IO proc */ 01312 else if (lpmmioinfo->pIOProc == NULL) 01313 ioProc = MMIO_FindProcNode(lpmmioinfo->fccIOProc); 01314 else /* use relevant ioProc */ 01315 { 01316 ioProc = &tmp; 01317 tmp.fourCC = lpmmioinfo->fccIOProc; 01318 tmp.pIOProc = lpmmioinfo->pIOProc; 01319 tmp.is_unicode = FALSE; 01320 tmp.count = 1; 01321 } 01322 01323 /* FIXME: should we actually pass lpmmioinfo down the drain ??? 01324 * or make a copy of it because it's const ??? 01325 */ 01326 return send_message(ioProc, (MMIOINFO*)lpmmioinfo, MMIOM_RENAME, 01327 (LPARAM)szFileName, (LPARAM)szNewFileName, FALSE); 01328 } 01329 01330 /************************************************************************** 01331 * mmioRenameW [WINMM.@] 01332 */ 01333 MMRESULT WINAPI mmioRenameW(LPCWSTR szFileName, LPCWSTR szNewFileName, 01334 const MMIOINFO* lpmmioinfo, DWORD dwFlags) 01335 { 01336 LPSTR szFn = NULL; 01337 LPSTR sznFn = NULL; 01338 UINT ret = MMSYSERR_NOMEM; 01339 INT len; 01340 01341 if (szFileName) 01342 { 01343 len = WideCharToMultiByte( CP_ACP, 0, szFileName, -1, NULL, 0, NULL, NULL ); 01344 szFn = HeapAlloc( GetProcessHeap(), 0, len ); 01345 if (!szFn) goto done; 01346 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szFn, len, NULL, NULL ); 01347 } 01348 if (szNewFileName) 01349 { 01350 len = WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, NULL, 0, NULL, NULL ); 01351 sznFn = HeapAlloc( GetProcessHeap(), 0, len ); 01352 if (!sznFn) goto done; 01353 WideCharToMultiByte( CP_ACP, 0, szNewFileName, -1, sznFn, len, NULL, NULL ); 01354 } 01355 01356 ret = mmioRenameA(szFn, sznFn, lpmmioinfo, dwFlags); 01357 01358 done: 01359 HeapFree(GetProcessHeap(),0,szFn); 01360 HeapFree(GetProcessHeap(),0,sznFn); 01361 return ret; 01362 } Generated on Sat May 26 2012 04:25:29 for ReactOS by
1.7.6.1
|