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


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?
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

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;
            = (char)drive;
            = -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",;
                     /* 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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

758 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now