PRODUCT : Borland C++ NUMBER : 1731 VERSION : All OS : WIN DATE : October 25, 1993 PAGE : 1/4 TITLE : Getting a drive's serial number under Windows #define STRICT // // winseria.c - Getting the drive Serial Number under Window. // /* This file shows an example of calling a real mode interrupt ( 0x21, 0x69 ) from within a Windows application to determine the Serial Number, Volume Label, and File System Type ( which is either "FAT12" or "FAT16". The Info Level will be 0. One of the main issues involved is to create two pointers to the same memory location - a selector address which is usable by Windows, and a segment address which is usable by DOS. This is done using the GlobalDOSAlloc() function, which returns both the selector and the segment address of the allocated memory. Note that this function should not be used for most allocation because it allocates a non-moveable memory block from the base 1Meg of memory. The segment address is then passed to DOS int 21h, 69h to get information regarding the drive. The selector address is then used by the Windows parts of the code to access that data. */ #include // MK_FP #include // ltoa() #include // strncpy(), strcpy(), strup() #include // wsprintf() // Structure to contain the register values for the // DPMI services typedef struct { DWORD di,si,bp,res1,bx,dx,cx,ax; WORD flags, es,ds,fs,gs,res2,res3,sp,ss; } DPMIRegs; // Stucture to contain the disk information typedef struct { unsigned int InfoLevel; unsigned long Serial; PRODUCT : Borland C++ NUMBER : 1731 VERSION : All OS : WIN DATE : October 25, 1993 PAGE : 2/4 TITLE : Getting a drive's serial number under Windows unsigned char VolumeLabel[11]; unsigned char FileSystemType[8]; } Info; // Create globally to initialize to Zero DPMIRegs r; // Use DPMI services to access Real mode void SimRealInt (BYTE i, DPMIRegs far *p) { asm { mov bl, [i] // DOS interupt mov bh, 0 les di, [p] // Register Values mov cx, 0 mov ax, 0300h int 31h } } #pragma argsused int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int Drive=3 ; // 3 = C drive DWORD dwValue ; unsigned size ; char temp[5] ; char diskInfo[120] ; char Label[12] ; char Type[9] ; char Serial[10] ; WORD wSegment, wSelector ; Info far *WindowsPtr ; size = sizeof( Info ) ; dwValue = GlobalDosAlloc( size ) ; if (!dwValue) { MessageBox( NULL, "Could not Allocate Memory", "Error", PRODUCT : Borland C++ NUMBER : 1731 VERSION : All OS : WIN DATE : October 25, 1993 PAGE : 3/4 TITLE : Getting a drive's serial number under Windows MB_ICONINFORMATION | MB_OK ) ; return 1 ; } wSegment = HIWORD(dwValue) ; wSelector = LOWORD(dwValue) ; WindowsPtr = (Info far *)MK_FP(wSelector,0) ; r.ax = 0x6900; r.bx = Drive ; r.dx = 0; r.ds = wSegment; SimRealInt (0x21, &r) ; // Call DOS int 21h, 69h // Check for read error if ( r.flags & 0x01) { WindowsPtr->Serial = 0; } // Add a NULL terminator to the strings which were returned // in the Info structure. _fstrncpy( Label, (char far *)WindowsPtr->VolumeLabel, 11 ) ; Label[11] = 0 ; _fstrncpy( Type, (char far *)WindowsPtr->FileSystemType, 8 ); Type[8] = 0 ; ltoa( WindowsPtr->Serial, Serial, 16 ) ; _fstrcpy( temp, &Serial[4] ) ; _fstrcpy( &Serial[5], temp ) ; _fstrupr( Serial ) ; // Convert all characters to UPPER CASE Serial[4] = ':' ; Serial[9] = 0 ; // Format the string to be displayed. wsprintf( diskInfo, "Drive:\t\t%c\r\n" "Serial Number:\t%s\r\n" "Volume Label:\t%s\r\n" "File System type:\t%s", (Drive + 64), (char far*)Serial, (char far *)Label, (char far *)Type ) ; MessageBox( NULL, (char far *)diskInfo, "Disk Info", MB_ICONINFORMATION | MB_OK ) ; PRODUCT : Borland C++ NUMBER : 1731 VERSION : All OS : WIN DATE : October 25, 1993 PAGE : 4/4 TITLE : Getting a drive's serial number under Windows GlobalDosFree(wSelector) ; return 0 ; } DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.