Sunday, November 6, 2011

Communication with Storage Devices in C programming language

Since DOS is commercially dead the rest of the chapter would focus on communication with the devices under Windows platform. We would illustrate this with the help of several programs.

Let us begin with the one that interacts with the simplest storage device, namely the floppy disk. Rather than the physical structure of the floppy disk it is the way the stored information is laid out and managed that concerns programmers most. Let us understand how the information is laid out on a floppy disk. Each floppy disk consists of four logical parts—Boot Sector, File Allocation Table (FAT), Directory and Data space. Of these, the Boot Sector contains information about how the disk is organized. That is, how many sides does it contain, how many tracks are there on each side, how many sectors are there per track, how many bytes are there per sector, etc. The files and the directories are stored in the Data Space. The Directory contains information about the files like its attributes, name, size, etc. The FAT contains information about where the files and directories are stored in the data space. Figure 19.5 shows the four logical parts of a 1.44 MB disk.





With the logical structure of the floppy disk behind us let us now write a program that reads the boot sector of a floppy disk and displays its contents on the screen. But why on earth would we ever like to do this? Well, that’s what all Windows-based Anti-viral softwares do when they scan for boot sector viruses. A good enough reason for us to add the capability to read a boot sector to our knowledge! Here is the program…

# include <stdafx.h>
# include <windows.h>
# include <stdio.h>
# include <conio.h>
# pragma pack ( 1 )
struct boot
{
BYTE jump [ 3 ] ;
char bsOemName [ 8 ] ;
WORD bytesperSector ;
BYTE sectorspercluster ;
WORD sectorsreservedarea ;
BYTE copiesFAT ;
WORD maxrootdirentries ;
WORD totalSectors ;
BYTE mediaDescriptor ;
WORD sectorsperFAT ;
WORD sectorsperTrack ;
WORD sides ;
WORD hiddenSectors ;
char reserve [ 480 ] ;
} ;
void ReadSector ( char*src, int ss, int num, void* buff ) ;
void main( )
{
struct boot b ;
ReadSector ( "\\\\.\\A:", 0, 1, &b ) ;
printf ( "Boot Sector name: %s\n", b.id ) ;
printf ( "Bytes per Sector: %d\n", b.bps ) ;
printf ( "Sectors per Cluster: %d\n", b.spc ) ;
/* rest of the statements can be written by referring Figure 19.6
and Appendix G*/
}

void ReadSector ( char *src, int ss, int num, void* buff )
{
HANDLE h ;
unsigned int br ;
h = CreateFile ( src, GENERIC_READ,
FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0 ) ;
SetFilePointer ( h, ( ss * 512 ), NULL, FILE_BEGIN ) ;
ReadFile ( h, buff, 512 * num, &br, NULL ) )
CloseHandle ( h ) ;
}

The boot sector contains two parts—‘Boot Parameters’ and ‘Disk Bootstrap Program’. The Boot Parameters are useful while performing read/write operations on the disk. Figure 19.6 shows the break up of the boot parameters for a floppy disk


Using the breakup of bytes shown in Figure 19.6 our program has first created a structure called boot. Notice the usage of #pragma pack to ensure that all elements of the structure are aligned on a 1-byte boundary, rather than the default 4-byte boundary. Then comes the surprise—there is no WinMain( ) in the program. This is because we want to display the boot sector contents on the screen rather than in a window. This has been done only for the sake of simplicity. Remember that our aim is to interact with the floppy, and not in drawing and painting in a window. If you wish you can of course adapt this program to display the same contents in a window. So the program is still a Windows application. Only difference is that it is built as a ‘Win32 Console Application’ using VC++. A console application always begins with main( ) rather than WinMain( ).

To actually read the contents of boot sector of the floppy disk the program makes a call to a user-defined function called ReadSector( ). The ReadSector( ) function is quite similar to the absread( ) library function available in Turbo C/C++ under DOS.

The first parameter passed to ReadSector( ) is a string that indicates the storage device from where the reading has to take place. The syntax for this string is \\machine-name\storage-device name. In \\.\\A:, we have used ‘.’ for the machine name. A ‘.’ means the same machine on which the program is executing. Needless to say, A: refers to the floppy drive. The second parameter is the logical sector number. We have specified this as 0 which means the boot sector in case of a floppy disk. The third parameter is the number of sectors that we wish to read. This parameter is specified as 1 since the boot sector occupies only a single sector. The last parameter is the address of a buffer/variable that would collect the data that is read from the floppy. Here we have passed the address of the boot structure variable b. As a result, the structure variable would be setup with the contents of the boot sector data at the end of the function call.

Once the contents of the boot sector have been read into the structure variable b we have displayed the first few of them on the screen using printf( ). If you wish you can print the rest of the contents as well.

No comments:

Post a Comment