Networking CD-ROMs Using Cached CD Images
When it comes to storage space, the more the merrier
John H. McCoy
John is a member of the computer science staff at Sam Houston State University in Huntsville, Texas. He can be contacted at [email protected].
In our article entitled "Network Access to CD-ROMs," (DDJ, August 1993), Wuhsiung Lu and I described a client/server system for networking CD-ROMs in a DOS/Windows environment. That system worked fine, except when 25 or 30 users simultaneously accessed the same drive. Caching the CD-ROM to the server's hard disk eliminated that problem. Making the cache permanent even eliminated the need for a dedicated drive for the CD-ROM.
The space needed for this permanent cache depends on the CD-ROM volume size and how much it can be compressed. The system I used for adding caching to the server program, for instance, used a 508-MB hard disk. By running PC-DOS 7 with Stacker, I was able to cache both a 635-MB tax-reference CD and the 27-MB PC-DOS 7 installation CD with room to spare. In short, storing cache images can be cheaper than installing more CD drives.
On the client side, MSCDEX allocates buffer space and maps a drive letter to every drive supported by the driver, even if you aren't going to use them all. As the number of CDs increased, this became unmanageable, leading me to write a MSCDEX substitute called SHSUCDX that allows selective drive mapping. The latest versions of the client/server programs are available electronically at ftp://ftp.shsu.edu/pub/cdrom/shsucd12.zip. In this article, I'll describe a cache driver that reads the cached CD images and makes them appear as CD drives. The images can be located either on the client machine or a network file server if the client accesses the network via a real-mode redirector rather than a shell. (I've used the system with the Windows NT DOS client and NetWare VLMs, but it won't work with the NetWare shell NETX.) For these networks, using the cache driver allows you to network CDs without having to use client/server software.
There are DOS programs (the NCJRS database, for example) that bypass Microsoft's CD-ROM extensions and access the driver directly. These programs work fine with the cache driver. Most programs, however, use the extensions and require the use of SHSUCDX, the MSCDEX substitute I'm including with this article. Note that if you attempt to use MSCDEX, your system will crash. MSCDEX trashes itself on a superfluous Qualify File Name request that DOS broadcasts on the INT 2Fh chain when the cache driver attempts to read the cache file.
How the Driver Works
When it installs, MSCDEX maps the CDs to drive letters, sets the attribute bits to indicate that the drive is a network drive (and another one that says it really isn't), and hooks the INT 2Fh multiplexer interrupt as if it were a network redirector. Figure 1, which assumes that MSCDEX has been loaded after the network redirector, illustrates this process.
DOS applications normally access a CD by making a DOS call (INT 21h). DOS, in turn, recognizes from the attributes that the CD is a network drive and makes an appropriate function 11h call to INT 2Fh. MSCDEX checks to see if the call involves one of its drives; if it does, it handles the request by making a call to the CD driver. If the call does not involve one of MSCDEX's drives, MCSDEX passes it down the INT 2Fh chain.
DOS applications can also call MSCDEX directly with function 15h calls to INT 2Fh. These calls bypass the DOS file system to provide access services that are unique to CDs. Some programs use DOS and MSCDEX to locate the CD driver, then make subsequent calls directly to the driver, bypassing both DOS and MSCDEX.
Adding the Cache Driver
When a cache image is used instead of a physical CD, the driver reads sectors from the cache image file; see Figure 2. If the application has made an INT 2Fh call or called the driver directly, then DOS has been bypassed and the driver is free to make an INT 21h call to read the image file. However, if the image file is a network file, DOS will have to make an INT 2Fh call to the network redirector. SHSUCDX sees the call and passes it on to the redirector.
MSCDEX cannot be used even if the image file is on a local disk. When called by the cache driver, DOS sends what appear to be superfluous broadcasts down the INT 2Fh chain, even if a network file is not involved. MSCDEX will crash when it sees a second call on the INT 2Fh chain while processing a prior call-regardless of whether the call is intended for MSCDEX.
Most DOS applications call DOS to access the CD instead of making an INT 2Fh call or calling the driver directly. In this case, when the cache driver needs to read the cache file, it can't make an INT 21h call because it is already in DOS. An undocumented INT 2Fh call is used instead.
Undocumented DOS Calls
Only three INT 2Fh, function 12h calls-open, read, and close-are used. None of these are officially documented. Ralf Brown's interrupt listings indicate that function 12h calls can only be made while in DOS and that they are known to be used by DOS to access COUNTRY.SYS. Andrew Schulman's Undocumented DOS, second edition (Addison-Wesley, 1994) and Geoff Chappel's DOS Internals (Addison-Wesley, 1994) provide some help, along with a lot of caveats. Without this help I wouldn't have known where to start.
Before making a function 12h call, the DOS swappable data area (SDA) must be saved, a switch to the DOS internal stack must be made, and the appropriate registers must be loaded. An INT 21h, function 5D06h call, also undocumented, is needed to locate the DOS stack, get the limits of the SDA, and locate the IN DOS flag. The current PSP and DTA don't seem to be significant in INT 2Fh, function 12h calls. It is not necessary to change them. In particular, you can't open a file during driver install and then use the handle from the driver's PSP to access that file in a subsequent INT 2Fh call. The simple approach I employ here is to test the IN DOS flag, then make an open call followed by a read and a close call using either INT 21h or INT 2Fh, as appropriate, for every image-file access.
Program Details
There are three programs involved. CDCACHER, which is available electronically in both source and executable form, builds the cache file. It is a straightforward process to read the CD blocks and write them to a file. Only single-session, ISO 9660 or High Sierra format CDs are supported. The first 16 blocks on the CD comprise the system area, followed by the primary volume descriptor (PVD) in block 16. I elected to ignore the system area by dropping block zero entirely and zeroing out the remaining blocks. The "cooked" data (2048 bytes) from block 1 through the end of the volume space is then copied to its corresponding record in a direct-access file; for example, block 16 becomes record 16 in the image file.
CDCACHER assumes that the driver name for the CD to be cached is "MSCD001." This can be overridden by including the driver name on the command line or by entering a new name in the dialog box after starting the program.
Caching a full CD takes time-at eight to ten MBytes/min, it takes over an hour. It doesn't run any faster in an OS/2 DOS window (unless you have a faster system), but you can get on with other things while it's copying. CDCACHER won't run in an NT DOS session. I've been told that there is no CD device-driver interface.
SHSUCDHD (also available electronically) is the cache driver. When executed, it installs as SHSU-CDH, using up to five cache images specified on the command line. The filenames are stored in canonical form before discarding the initialization code and TSRing. SHSUCDHD/U unloads the driver.
The resident code follows the standard driver form: A header that specifies the device type and name, a strategy, and an interrupt section. The interrupt section is basically an if statement that handles the I/O commands that Microsoft requires, flagging the others as unknown.
The CD Read Long command actually reads the cache image file. The IN DOS flag is checked first. If IN DOS is set, the DOS SDA is saved before switching to the DOS stack and opening the file with an INT 2Fh, 1226h call. The filename supplied to DOS is already in canonical form but, as mentioned previously, DOS will broadcast a Qualify File Name request on the INT 2Fh chain anyway, before opening the file. An INT 2Fh, 1229h call reads the required block(s) into the data buffer specified in the request header passed to the driver when it was called. Another INT 2Fh call closes the cache file before the driver switches back to its own stack and restores the SDA.
If the IN DOS flag is not set, the SDA does not have to be saved/restored, the driver does not need to switch to the DOS stack, and INT 21h (rather than INT 2Fh) calls are used to open, read, and close the cache file.
The read procedure is also used by the IOCTL ReturnVolumeSize command to read part of the primary volume descriptor into a temporary buffer where the volume size can be extracted.
SHSUCDX (the executable is available electronically) is a replacement for MSCDEX that must be used with SHSUCDHD. It maps one or all of the drive images to drive letters (the last drive must be set in config.sys to provide enough drive letters). If the maximum of five image files were specified when SHSUCDHD was loaded, these will appear as drive units 0 through 4. All five units can be mapped to drive letters beginning with the first available letter by entering SHSUCDX /D:SHSU-CDH. Entering SHSUCDX /D:SHSU-CDH,F,1,2 will map two units: unit 1 to drive F, and unit 2 to drive G. Other combinations and multiple drivers can be specified to map up to ten drives. SHSUCDX /U unloads it.
Recompiling from the Source Code
SHSUCDHD is written entirely in assembler and compiled and linked with MASM 6.0b. CDCACHER, on the other hand, is written in C and compiled with Quick C 2.0. It uses Mix Software's C/Windows ToolChest for the user interface. You will need the C/ToolChest (or you can write your own interface) to recompile and link it.
The source code for SHSUCDX is not included here, but it is available from the URL given earlier. It is written partly in C and partly in assembler. From the SHSUCD11.ZIP file you'll need SHSUCDXASM, CDROM.INC, UNDOC.INC, CMDS.C, CDROM.H, and REDIR.H. Again, the Quick C 2.0 and MASM 6.0b compilers were used for compiling and linking.
Figure 1: How MSCDEX normally works.
Figure 2: Reading sectors from the cache image file.