Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Getting the Volume Serial Number using Borland C++ 4.5 (16-Bit)

Posted on 1997-05-13
Last Modified: 2008-03-03
I am trying to write a dll in C++ that will return the Volume Serial Number of any drive (or at least Drive C:).  I am not sure exactly how to do this.  I'm sure there is a pretty easy way, but I am new at C and have very little time to learn it.  Could someone send me source for a simple 16-bit DLL that will return the Volume Serial Number?
Question by:ehilder

Expert Comment

ID: 1163378
Could you tell us some information concerning your environment? (Win 3.1x, Win95/NT). Do you absolutly need a 16-bit dll?

Author Comment

ID: 1163379
The application that will use the DLL is designed in Visual D-Base.  The application will be run on all platforms of Windows. (3.1x, Win95 and WinNt)  Since it is possible that the application will be run on Windows 3.1 without Win32s, I would prefer a 16-bit DLL.  If this is absolutely impossible, I could recommend that the application be run only in 32-bit mode.

Expert Comment

ID: 1163380
The following function will return you the volume name and serial number of any drive.

static      void      Get_Volume_Info(int Disk, char *Vol, char *SSN)
  unsigned      char buf[1024];
  int           i;

  strcpy(Vol, "");
  strcpy(SSN, "");

  i = biosdisk(2, Disk, Disk >= 0x80 ? 1 : 0, 0, 1, 1, &buf);
  if(i == 0)
#pragma warn -ucp
    strncpy(Vol, buf+0x2B, 11);
    Vol[11] = '\0';
    sprintf(SSN, "%02X%02X-%02X%02X", buf[0x2a], buf[0x29],       buf[0x28], buf[0x27]);
#pragma warn +ucp

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.


Author Comment

ID: 1163381
I know that I am new to C, but I was just wondering...  How exactly do you use a DOS ONLY function in a Windows DLL?
LVL 23

Accepted Solution

chensu earned 150 total points
ID: 1163382
I answered a similar question in Microsoft Windows Programming Topic Area. (4/14/97  10 Accessing HDD serial # <PAQ>)

For 32-bit:
The Win32 function GetVolumeInformation() returns this info.

                   BOOL GetVolumeInformation(
                       LPCTSTR lpRootPathName, // address of root directory of the file system
                       LPTSTR lpVolumeNameBuffer, // address of name of the volume
                       DWORD nVolumeNameSize, // length of lpVolumeNameBuffer
                       LPDWORD lpVolumeSerialNumber, // address of volume serial number
                       LPDWORD lpMaximumComponentLength, // address of system's maximum filename
                       LPDWORD lpFileSystemFlags, // address of file system flags
                       LPTSTR lpFileSystemNameBuffer, // address of name of file system
                       DWORD nFileSystemNameSize // length of lpFileSystemNameBuffer

For 16-bit:
I copied an article from Visaul C++ KBase here.

                  Retrieving a Disk Volume Serial Number from C

                  PSS ID Number: Q69223
                  Article last modified on 01-24-1995
                  5.10 6.00 6.00a 6.00ax 7.00 | 1.00 1.50
                  MS-DOS | WINDOWS

                  The information in this article applies to:
                   - The C Run-time (CRT) included with:
                      - Microsoft C for MS-DOS, versions 5.1, 6.0, 6.0a, and 6.0ax
                      - Microsoft C/C++ for MS-DOS, version 7.0
                      - Microsoft Visual C++ for Windows, versions 1.0 and 1.5
                  Beginning with MS-DOS version 4.0, a semi-random 32-bit binary
                  identification number (ID) is assigned to each disk that MS-DOS
                  formats. The volume serial number (or ID) is stored at offset 27H to
                  2AH in the boot sector of each disk.
                  NOTE: code compiled with Visual C++ version 1.5 may yield the following
                  message from Windows NT:
                     An applicaion has attempted to directly access the hard disk, which
                     cannot be supported. This may cause the application to function
                  It provides Terminate and Ignore buttons. If the user is logged on with
                  Administrative privileges, this will succeed for a FAT partition, else it
                  fails for a FAT partition. It always fails for an NTFS partition. After
                  clicking Terminate or Ignore the program returns with the error message
                  that has been coded (error on int 25).
                  MORE INFORMATION
                  The following program illustrates how to retrieve this information:
                  /* */
                  /* This program reads the volume serial number (or ID) from */
                  /* the boot sector of a specified disk. The DOS interrupt 25 */
                  /* Absolute Disk Read is used to read in the boot sector. */
                  /* */
                  /* Note: The volume ID is only implemented from MS-DOS 4.0 */
                  /* and later. */
                  /* */
                  /* The output consists of the OEM name and version of the */
                  /* disk-formatting program (stored at offset 03H to 0AH in the */
                  /* boot sector), the disk volume label, and the disk-volume */
                  /* serial number. */
                  /* */
                  #include <stdio.h>
                  #include <stdlib.h>
                  #include <string.h>
                  #include <dos.h>
                  #include <conio.h>
                  char bootsector[1024];
                  char volume[12];
                  char ver[9];
                  char block[10];
                  void main(void)
                     int ax, _far *p, drive;
                     struct find_t fileinfo;
                     char filename[13], _far *myvar, _far *q;
                     union REGS inregs, outregs;
                     struct SREGS segregs;
                     printf("Enter drive number (0=A,1=B,2=C, ...): ");
                     drive = getche() - '0';
                     /* Parameter block for int 25H */
                     /* Bytes Description */
                     /* ------- ----------- */
                     /* 00H-03H 32-bit sector number */
                     /* 04H-05H Number of sectors to read */
                     /* 06H-07H Offset of buffer */
                     /* 08H-09H Segment of buffer */
                     block[0] = block[1] = block[2] = block[3] = 0;
                     block[4] = 1;
                     block[5] = 0;
                     myvar = bootsector;
                     p = (int *)&block[6];
                     *p = FP_OFF(myvar);
                     p = (int *)&block[8];
                     *p = FP_SEG(myvar);
                     q = block;
                     inregs.h.al = (char)drive;
                     inregs.x.cx = -1;
                     inregs.x.bx = FP_OFF(q);
                     segregs.ds = FP_SEG(q);
                     ax = int86x(0x25, &inregs, &outregs, &segregs);
                     /*** Error routine ***/
                     if (outregs.x.cflag)
                      printf("\n\nerror on int 25\n");
                      printf("this is AX:%04X", ax);
                     /*** Output ***/
                     printf("\n\nDrive %c\n-------\n\n", drive +'A');
                     strncpy(ver, &bootsector[3], 8);
                     printf("OEM name and version: %s\n", ver);
                     /* Use _dos_findfirst for the volume label */
                     filename[0] = (char)(drive + 'A');
                     filename[1] = '\0';
                     strcat(filename, ":\\*.*");
                     if(!_dos_findfirst(filename, _A_VOLID, &fileinfo))
                     printf("Volume name : %s\n", fileinfo.name);
                     /* Before printing serial number, check if version >= 4.x */
                     if ((ver[6] == '.') && (ver[5] >= '4') && (ver[5] <= '9'))
                      printf("Serial number : %02X%02X-%02X%02X\n\n",
                      (unsigned char) bootsector[0x2a],
                      (unsigned char) bootsector[0x29],
                      (unsigned char) bootsector[0x28],
                      (unsigned char) bootsector[0x27]);
                  Additional reference words: kbinf 5.10 6.00 6.00a 6.00ax 7.00 1.00 1.50
                  KBCategory: kbprg
                  KBSubcategory: CRTIss
                  Copyright Microsoft Corporation 1995.


Author Comment

ID: 1163383
The 16-Bit example works great, but I do need a little more information.  I am increasing the points to 150.

I am new to C++ and I was wondering if you could post an example using the GetVolumeInformation() function in Win32.  Also, is there a way to tell if Windows is running 16-bit or 32-bit.  
The reasoning is that this DLL needs to run in 16-bit and 32-bit and on Windows NT.

If I can tell that Windows is running in 32-bit, I can branch from the 16-bit routine to the 32-bit routine.  Even if they are in two DLL's.  Can you test for 32-bit mode in a 16-bit DLL???  If so, this is how I would like to work it.

Does this make sense?
LVL 23

Expert Comment

ID: 1163384
The following is the example using GetVolumeInformation.

CHAR szVolumeName[MAX_PATH], szFSName[MAX_PATH];
      DWORD dwVolSerialNum,
      ::GetVolumeInformation("c:\\",  // "d:\\" for d:, NULL for current directory

CHAR szBuf[256];
                   "szVolumeName = %s\n"
                   "dwVolSerialNum = %lX\n"
                   "dwMaxCompLen = %lu\n"
                     "dwFSFlags = %lu\n"
                     "szFSName = %s\n",
      ::MessageBox(NULL, szBuf, "GetVolumeInformation", MB_OK);

If your program is 32-bit, it must be running on a 32-bit platform (including Win32s on Windows 3.1, you can check it with GetVersionEx function). A 16-bit platform cannot run a 32-bit program.

If your program is 16-bit, it may be running on a 16-bit platform or a 32-bit platform. You can check the version with GetVersion function in a 16-bit program. For Windows 3.1, it returns version 3.1. For Windows 95, it returns version 3.95. I have not tried it on Windows NT. However, you cannot call a 32-bit DLL from a 16-bit program or DLL although you can run a 32-bit EXE from a 16-bit program or DLL.

So, in your case, you might need to provide two version: one is 16-bit, another is 32-bit.

LVL 23

Expert Comment

ID: 1163385
Sorry, I think I made a mistake. I said "you cannot call a 32-bit DLL from a 16-bit program or DLL". In fact, there is a way to do so. Generic Thunks allow a 16-bit Windows-based application to load and call a Win32-based DLL on Windows NT and Windows 95. See the following Win32 SDK documentation:
Win32 SDK/Programming Guides and Tools/Programming Techniques/Generic Thunks.

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Embarcadero C++ Builder XE2 TDateTime 8 75
convert char array to number in c 5 86
computer science syllabus 3 89
How to Correctly derive class from CWinThread in MFC 4 66
In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

829 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question