/**************************************************************************** * * capfile.c * * AVI file writing module. * * Microsoft Video for Windows Sample Capture Class * * Copyright (c) 1992 - 1995 Microsoft Corporation. All Rights Reserved. * * You have a royalty-free right to use, modify, reproduce and * distribute the Sample Files (and/or any modified version) in * any way you find useful, provided that you agree that * Microsoft has no warranty obligations or liability for any * Sample Application Files which are modified. * ***************************************************************************/ #define INC_OLE2 #pragma warning(disable:4103) #include #include #include #include #include #include "ivideo32.h" #include "avicapi.h" /*----------------------------------------------------------------------+ | fileCapFileIsAVI() - Returns TRUE if the capture file is a valid AVI | | | +----------------------------------------------------------------------*/ BOOL FAR PASCAL fileCapFileIsAVI (LPTSTR lpsz) { BOOL fReturn = TRUE; HMMIO hmmioSource = NULL; MMCKINFO ckRIFF; // Does the file exist? hmmioSource = mmioOpen(lpsz, NULL, MMIO_READ); if (!hmmioSource) return FALSE; // Is there an AVI RIFF chunk? // !!! Don't do a FINDRIFF for an AVI chunk or it'll take several minutes to // !!! come back from checking a really big file fReturn = (mmioDescend(hmmioSource, &ckRIFF, NULL, 0) == 0) && (ckRIFF.ckid == FOURCC_RIFF) && (ckRIFF.fccType == formtypeAVI); if (hmmioSource) mmioClose(hmmioSource, 0); return fReturn; } /*----------------------------------------------------------------------+ | fileSaveCopy() - save a copy of the current capture file. | | | +----------------------------------------------------------------------*/ BOOL FAR PASCAL fileSaveCopy(LPCAPSTREAM lpcs) { #define INITFILE_BUFF_SIZE (1024L * 256L) BOOL fReturn = TRUE; char achCaption[80]; // caption on Open File dialog HMMIO hmmioSource = NULL, hmmioDest = NULL; LONG lFileSize, lFileSizeTotal, lTemp; HANDLE hMem = NULL; LPBYTE lpstr = NULL; LONG lBuffSize = INITFILE_BUFF_SIZE; MMCKINFO ckRIFF; HCURSOR hOldCursor; UpdateWindow(lpcs->hwnd); // Make everything pretty hOldCursor = SetCursor( lpcs->hWaitCursor ); if (0 == lstrcmpi(lpcs->achSaveAsFile, lpcs->achFile)) { // IF the source and destination names are the same, then there // is nothing to do return(TRUE); } /* grab a big buffer to xfer the file in, start the */ /* buffer size at 32K and hope we get that much. */ TRYAGAIN: hMem = GlobalAlloc(GMEM_MOVEABLE, lBuffSize); if (!hMem){ /* we don't have this much mem, go for half that */ lBuffSize /= 2; if (lBuffSize) goto TRYAGAIN; else { fReturn = FALSE; goto SAVECOPYOUT; } } /* open up the source file and find the size */ /* Open the source first in case source==destination. Despite the */ /* test above this may still be the case (consider two net use */ /* commands to the same share point with different drive letters). */ /* When we open the destination we truncate the file, which will */ /* lose any existing data. */ hmmioSource = mmioOpen(lpcs->achFile, NULL, MMIO_READ | MMIO_DENYWRITE); if (!hmmioSource){ /* we are totally hosed here, the source file can't even */ /* be opened up, error out. */ errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR)lpcs->achFile); fReturn = FALSE; goto SAVECOPYOUT; } /* let's go and create the destination file */ hmmioDest = mmioOpen(lpcs->achSaveAsFile, NULL, MMIO_CREATE|MMIO_WRITE); if (!hmmioDest){ /* we've got an error of some kind here, let's bail out */ /* on this one. */ errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR)lpcs->achSaveAsFile); fReturn = FALSE; goto SAVECOPYOUT; } /* go down to the RIFF chunk and find out the size of this */ /* thing. If there is no RIFF chunk then we can safely */ /* assume that the file is of 0 length. */ ckRIFF.fccType = formtypeAVI; if (mmioDescend(hmmioSource, &ckRIFF, NULL, MMIO_FINDRIFF) != 0){ /* we are done, this file has no RIFF chunk so it's size */ /* is 0 bytes. Just close up and leave. */ goto SAVECOPYOUT; } else { /* there is a RIFF chunk, get the size of the file and */ /* get back to the start of the file. */ lFileSizeTotal = lFileSize = ckRIFF.cksize + 8; mmioAscend(hmmioSource, &ckRIFF, 0); mmioSeek(hmmioSource, 0L, SEEK_SET); } /* Before trying to write, seek to the end of the destination */ /* file and write one byte. This both preallocates the file, */ /* and confirms enough disk is available for the copy, without */ /* going through the trial and error of writing each byte. */ mmioSeek( hmmioDest, lFileSizeTotal - 1, SEEK_SET ); mmioWrite( hmmioDest, (HPSTR) achCaption, 1L ); if (mmioSeek (hmmioDest, 0, SEEK_END) < lFileSizeTotal) { /* Notify user with message that disk may be full. */ errorUpdateError (lpcs, IDS_CAP_WRITEERROR, (LPTSTR)lpcs->achSaveAsFile); /* close the file and delete it */ mmioClose(hmmioDest, 0); mmioOpen(lpcs->achSaveAsFile, NULL, MMIO_DELETE); hmmioDest = NULL; fReturn = FALSE; goto SAVECOPYOUT; } mmioSeek (hmmioDest, 0L, SEEK_SET); // Back to the beginning UpdateWindow(lpcs->hwnd); // Make everything pretty hOldCursor = SetCursor( lpcs->hWaitCursor ); /* lock our buffer and start xfering data */ lpstr = GlobalLock(hMem); if (!lpstr) { fReturn = FALSE; goto SAVECOPYOUT; } while (lFileSize > 0) { if (lFileSize < lBuffSize) lBuffSize = lFileSize; mmioRead(hmmioSource, (HPSTR)lpstr, lBuffSize); if (mmioWrite(hmmioDest, (HPSTR)lpstr, lBuffSize) <= 0) { /* we got a write error on the file, error on it */ errorUpdateError (lpcs, IDS_CAP_WRITEERROR, (LPTSTR)lpcs->achSaveAsFile); /* close the file and delete it */ mmioClose(hmmioDest, 0); mmioOpen(lpcs->achSaveAsFile, NULL, MMIO_DELETE); hmmioDest = NULL; fReturn = FALSE; goto SAVECOPYOUT0; } // Let the user hit escape to get out if (GetAsyncKeyState(VK_ESCAPE) & 0x0001) { /* close the file and delete it */ mmioClose(hmmioDest, 0); mmioOpen(lpcs->achSaveAsFile, NULL, MMIO_DELETE); hmmioDest = NULL; goto SAVECOPYOUT0; } lFileSize -= lBuffSize; // lTemp is percentage complete lTemp = MulDiv (lFileSizeTotal - lFileSize, 100L, lFileSizeTotal); statusUpdateStatus (lpcs, IDS_CAP_SAVEASPERCENT, lTemp); Yield(); } // endwhile more bytes to copy SAVECOPYOUT: SAVECOPYOUT0: SetCursor( hOldCursor ); /* close files, free up mem, restore cursor and get out */ if (hmmioSource) mmioClose(hmmioSource, 0); if (hmmioDest){ mmioSeek(hmmioDest, 0L, SEEK_END); mmioClose(hmmioDest, 0); } if (hMem) { if (lpstr) { GlobalUnlock(hMem); } GlobalFree(hMem); } statusUpdateStatus (lpcs, 0); return fReturn; } /*--------------------------------------------------------------+ | fileAllocCapFile - allocate the capture file | | | +--------------------------------------------------------------*/ BOOL FAR PASCAL fileAllocCapFile(LPCAPSTREAM lpcs, DWORD dwNewSize) { BOOL fOK = FALSE; HMMIO hmmio; UINT w; HCURSOR hOldCursor; lpcs->fCapFileExists = FALSE; hmmio = mmioOpen(lpcs->achFile, NULL, MMIO_WRITE); if( !hmmio ) { /* try and create */ hmmio = mmioOpen(lpcs-> achFile, NULL, MMIO_CREATE | MMIO_WRITE); if( !hmmio ) { /* find out if the file was read only or we are just */ /* totally hosed up here. */ hmmio = mmioOpen(lpcs-> achFile, NULL, MMIO_READ); if (hmmio){ /* file was read only, error on it */ errorUpdateError (lpcs, IDS_CAP_READONLYFILE, (LPTSTR)lpcs-> achFile); mmioClose(hmmio, 0); return FALSE; } else { /* even weirder error has occured here, give CANTOPEN */ errorUpdateError (lpcs, IDS_CAP_CANTOPEN, (LPTSTR) lpcs-> achFile); return FALSE; } } } /* find the size */ lpcs-> lCapFileSize = mmioSeek(hmmio, 0L, SEEK_END); if( dwNewSize == 0 ) dwNewSize = 1; lpcs-> lCapFileSize = dwNewSize; hOldCursor = SetCursor( lpcs-> hWaitCursor ); // Delete the existing file so we can recreate to the correct size mmioClose(hmmio, 0); // close the file before deleting mmioOpen(lpcs-> achFile, NULL, MMIO_DELETE); /* now create a new file with that name */ hmmio = mmioOpen(lpcs-> achFile, NULL, MMIO_CREATE | MMIO_WRITE); if( !hmmio ) { return FALSE; } /* * rather than just leaving the allocated space as garbage, we * create it as a junk filler chunk */ { MMCKINFO ck; ck.ckid = mmioFOURCC('J', 'U', 'N', 'K'); ck.cksize = dwNewSize - 8L; fOK = (mmioCreateChunk(hmmio, &ck, 0) == 0); fOK &= (mmioSeek(hmmio, dwNewSize - 9, SEEK_CUR) == (LONG)dwNewSize-1); fOK &= (mmioWrite( hmmio, (HPSTR) &w, 1L ) == 1); mmioAscend(hmmio, &ck, 0); } mmioClose( hmmio, 0 ); SetCursor( hOldCursor ); if (!fOK) errorUpdateError (lpcs, IDS_CAP_NODISKSPACE); return fOK; }