Now that DLLDEMO has access to the Viewer functions it needs, it is ready to copy a file from the .MVB file system. The ExportBag function performs this operation. ExportBag uses the following variables:
PUBLIC RC PASCAL EXPORT ExportBag(
LPSTR lszMVBname,
LPSTR lszBagFName,
LPSTR lszExportName,
DWORD fFlags)
{
RC rc; // return code
HANDLE hfMvb; // handle for .MVB file
HANDLE hfBag; // file handle to bag file
DWORD dBagStartPos; // bag file start of file
// position
HANDLE hFile; // handle to output file
BOOL fClean = TRUE; // if set, delete file in error
// state machine
DWORD dwBytesRead; // input bytes read
HANDLE hMem; // handle to copy buffer
LPBYTE lpMem; // pointer to copy buffer
VPTR VPtr;
First, ExportBag uses the HfsOpenSz function to get a handle to the .MVB file system, as follows:
if ((hfMvb = (*lpfn_HfsOpenSz)(lszMVBname, fFSOpenReadOnly)) == NULL) {
rc = rcFailure;
UNDOstateEXIT:
return rc;
}
The lszMVBname parameter identifies the .MVB file for which it wants the handle. This parameter takes its value from Viewer's qchPath internal variable.
As you'll recall, ExportBag is executed from a hot spot in the DLLDEMO.MVB title. The DLLDEMO.MVP project file for that title includes a RegisterRoutine command that registers ExportBag as a Viewer authoring command. When ExportBag is run from the hot spot, qchPath is given as the first parameter to ExportBag.
Next, ExportBag makes sure the baggage file within the .MVP file system is valid, as follows:
if (((*lpfn_FAccessHfs)(hfMvb, lszBagFName, NULL)) == FALSE) {
rc = rcNoExists;
goto UNDOstateEXIT;
}
The lszBagFName parameter to ExportBag gives this filename. Like the lszMVBname parameter, the baggage filename in lszBagFName is passed from the hot spot encoded in the DLLDEMO.MVB title. However, the baggage filename is hard-coded in the hot spot rather than obtained from a Viewer internal variable.
In this and other examples, the return code rc would normally be serviced in a common error routine at label UNDOstateEXIT. This error routine would inform the user of the problem. For simplicity, this error routine has been omitted from DLLDEMO.C.
ExportBag now opens the baggage file for reading, as folows:
if ((hfBag = (*lpfn_HfOpenHfs)(hfMvb, lszBagFName, fFSOpenReadOnly)) ==
NULL) {
rc=rcNoExists;
UNDOstate1:
(*lpfn_RcCloseHfs)(hfMvb);
goto UNDOstateEXIT;
}
It creates a buffer to improve efficiency in the copy:
if ((hMem = GlobalAlloc(GMEM_MOVEABLE, (DWORD)wCOPY_SIZE)) == NULL) {
rc = rcOutOfMemory;
UNDOstate2:
(*lpfn_RcCloseHf)(hfBag);
goto UNDOstate1;
}
lpMem = GlobalLock(hMem);
To make sure the MS-DOS file it's copying to is not already present, ExportBag calls an assembler routine called lunlink. This routine executes a MS-DOS function to purge the filename ExportBag is using:
lunlink(lszExportName);
ExportBag creates the MS-DOS file it's copying to and obtains a handle to the new file, as follows:
if ((hFile = _lcreat(lszExportName,0)) == -1) {
rc = rcOutOfMemory;
UNDOstate3:
GlobalUnlock(hMem);
GlobalFree(hMem);
goto UNDOstate2;
}
Now ExportBag starts the write loop that copies the baggage file to the new MS-DOS file, as follows:
do {
if ((dwBytesRead = (*lpfn_LcbReadHf)(hfBag, lpMem, wCOPY_SIZE)) == -1L)
{
rc = rcReadError;
UNDOstate4:
_lclose(hFile);
if (fClean)
lunlink(lszExportName);
goto UNDOstate3;
}
if (_lwrite(hFile, lpMem,(WORD) dwBytesRead) != (WORD) dwBytesRead) {
rc = rcDiskFull;
goto UNDOstate4;
}
} while (dwBytesRead == wCOPY_SIZE);
ExportBag reads chunks the size of the buffer it created until it reaches the end of the baggage file. The end-of-file condition is indicated when the LcbReadhf function returns -1L. ExportBag writes to the new MS-DOS file using the standard Windows function _lwrite.
When ExportBag has finished writing the MS-DOS file, it closes the baggage and MS-DOS files and cleans up its memory, as follows:
(*lpfn_RcCloseHfs)(hfMvb);
_lclose(hFile);
GlobalUnlock(hMem);
GlobalFree(hMem);
return rcSuccess; }