|< C & Win32 programming 6 | Main | C & Win32 programming 8 >| Site Index | Download |


 

MODULE F

WIN32 AND C PROGRAMMING 7

 

What are in this Module?

  1. Windows Volume Management Functions

  2. Program Examples

  3. Naming a Volume Stories

  4. Program Examples

 

My Training Period: cc hours. Before you begin, read some instruction here.

 

Programming Abilities:

  • Be familiar and play around with the Win32 programming.

  • Able to find and collect information about volume management functions.

  • Able to understand and use the collected information about the functions in programs.

Windows Volume Management Functions

  • The following Table lists the needed information in order to use the GetDriveType() function.

Information

Description

The function

GetDriveType().

The use

Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.

The prototype

UINT GetDriveType(LPCTSTR  lpRootPathName);

Example

char drive2[i][j] = {"...", "..."};

 

GetDriveType(drive2[i]);

The parameters

lpRootPathName - [in] Pointer to a null-terminated string that specifies the root directory of the disk to return information about. A trailing backslash is required. If this parameter is NULL, the function uses the root of the current directory.

The return value

The return value specifies the type of drive. It can be one of the following values:

  1. DRIVE_UNKNOWN - The drive type cannot be determined.

  2. DRIVE_NO_ROOT_DIR - The root path is invalid. For example, no volume is mounted at the path.

  3. DRIVE_REMOVABLE - The disk can be removed from the drive.

  4. DRIVE_FIXED - The disk cannot be removed from the drive.

  5. DRIVE_REMOTE - The drive is a remote (network) drive.

  6. DRIVE_CDROM - The drive is a CD-ROM drive.

  7. DRIVE_RAMDISK - The drive is a RAM disk.

The header file

<windows.h>

 

Table 1:  GetDriveType() information.

 

 

 

 

#include <windows.h>

#include <stdio.h>

 

// using two dimensional arrays to store the drive strings

char drive2[13][5] = {"A:\\", "B:\\", "C:\\", "D:\\", "E:\\", "F:\\", "G:\\", "H:\\","I:\\", "J:\\", "K:\\", "L:\\"};

 

int main()

{

    for(int i=0; i<12; i++)

    {

        UINT test = GetDriveType(drive2[i]);

        switch(test)

        {

            case 0: printf("Drive %s is type %d - Cannot be determined.\n", &drive2[i], test);

                break;

            case 1: printf("Drive %s is type %d - Invalid root path/Not available.\n", &drive2[i], test);

                break;

        case 2: printf("Drive %s is type %d - Removable.\n", &drive2[i], test);

                break;

        case 3: printf("Drive %s is type %d - Fixed.\n", &drive2[i], test);

                break;

        case 4: printf("Drive %s is type %d - Network.\n", &drive2[i], test);

                break;

        case 5: printf("Drive %s is type %d - CD-ROM.\n", &drive2[i], test);

                break;

        case 6: printf("Drive %s is type %d - RAMDISK.\n", &drive2[i], test);

                break;

        default  : "Unknown value!\n";

        }

    }

   return 0;

}

 

The output:

 

Drive A:\ is type 2 - Removable.

Drive B:\ is type 1 - Invalid root path/Not available.

Drive C:\ is type 3 - Fixed.

Drive D:\ is type 3 - Fixed.

Drive E:\ is type 3 - Fixed.

Drive F:\ is type 3 - Fixed.

Drive G:\ is type 3 - Fixed.

Drive H:\ is type 3 - Fixed.

Drive I:\ is type 3 - Fixed.

Drive J:\ is type 5 - CD-ROM.

Drive K:\ is type 5 - CD-ROM.

Drive L:\ is type 2 - Removable.

Press any key to continue

Information

Description

The function

GetLogicalDrives().

The use

Retrieves a bitmask representing the currently available disk drives.

The prototype

DWORD GetLogicalDrives(void);

Example

TCHAR szDrive[ ] = _T(" A:");

 

DWORD uDriveMask = GetLogicalDrives();

printf("This machine has the following logical drives:\n");

 

while(uDriveMask)

{

 if(uDriveMask & 1)

    printf(szDrive);

  // binary 1 shows that the drive is available and 0 otherwise

  ++szDrive[1];

  // shift right

  uDriveMask >>= 1;

}

The parameters

This function has no parameters.

The return value

If the function succeeds, the return value is a bitmask representing the currently available disk drives.  Bit position 0 (the least-significant bit) is drive A, bit position 1 is drive B, bit position 2 is drive C, and so on.

The header file

<windows.h>

 

Table 2:  GetLogicalDrives() information.

#include <windows.h>

#include <direct.h>

#include <stdio.h>

#include <tchar.h>

 

// initial value

TCHAR szDrive[ ] = _T(" A:");

 

int main()

{

  DWORD uDriveMask = GetLogicalDrives();

  printf("The bitmask of the logical drives in hex: %0X\n", uDriveMask);

  printf("The bitmask of the logical drives in decimal: %d\n", uDriveMask);

  if(uDriveMask == 0)

      printf("GetLogicalDrives() failed with failure code: %d\n", GetLastError());

  else

  {

      printf("This machine has the following logical drives:\n");

  while(uDriveMask)

    {// use the bitwise AND, 1–available, 0-not available

     if(uDriveMask & 1)

        printf(szDrive);

     // increment... 

     ++szDrive[1];

      // shift the bitmask binary right

      uDriveMask >>= 1;

     }

    printf("\n ");

   }

   return 0;

}

 

The output:

 

The bitmask of the logical drives in hex: FFD

The bitmask of the logical drives in decimal: 4093

This machine has the following logical drives:

 A: C: D: E: F: G: H: I: J: K: L:

 Press any key to continue

Information

Description

The function

GetLogicalDriveStrings().

The use

Fills a buffer with strings that specify valid drives in the system.

The prototype

DWORD GetLogicalDriveStrings(DWORD nBufferLength, LPTSTR lpBuffer);

Example

DWORD mydrives = 100;

char lpBuffer[100];

 

GetLogicalDriveStrings(mydrives, lpBuffer);

The parameters

nBufferLength - [in] Maximum size of the buffer pointed to by lpBuffer, in TCHARs.  This size does not include the terminating null character. If this parameter is zero, lpBuffer is not used.

lpBuffer - [out] Pointer to a buffer that receives a series of null-terminated strings, one for each valid drive in the system, plus with an additional null character.  Each string is a device name.

The return value

If the function succeeds, the return value is the length, in characters, of the strings copied to the buffer, not including the terminating null character.  Note that an ANSI-ASCII null character uses one byte, but a Unicode null character uses two bytes.

If the buffer is not large enough, the return value is greater than nBufferLength.  It is the size of the buffer required to hold the drive strings.

If the function fails, the return value is zero.  To get extended error information, use the GetLastError() function.

The header file

<windows.h>

 

Table 3:  GetLogicalDriveStrings() information.

#include <windows.h>

#include <stdio.h>

 

// buffer length

DWORD mydrives = 100;

// buffer for drive string storage

char lpBuffer[100];

 

int main()

{

      DWORD test = GetLogicalDriveStrings( mydrives, lpBuffer);

      printf("GetLogicalDriveStrings() return value: %d\nError: %d \n", test, GetLastError());

      printf("The logical drives of this machine are:\n");

      for(int i = 0; i<100; i++)

        printf("%c", lpBuffer[i]);

      printf("\n");

      return 0;

}

 

The output:

 

GetLogicalDriveStrings() return value: 44

Error: 0

The logical drives of this machine are:

A:\ C:\ D:\ E:\ F:\ G:\ H:\ I:\ J:\ K:\ L:\

 

Press any key to continue

Information

Description

The function

QueryDosDevice().

The use

Retrieves information about MS-DOS device names.  The function can obtain the current mapping for a particular MS-DOS device name.  The function can also obtain a list of all existing MS-DOS device names.

The prototype

DWORD QueryDosDevice( LPCTSTR lpDeviceName, LPTSTR lpTargetPath, DWORD ucchMax );

Example

char lpDeviceName[11][3] = {"A:", "C:", "D:", "E:", "F:", "G:", "H:","I:", "J:", "K:", "L:"};

// the buffer for storage

char lpTargetPath[1000];

 

QueryDosDevice(lpDeviceName[i], lpTargetPath, 1000);

The parameters

lpDeviceName - [in] Pointer to an MS-DOS device name string specifying the target of the query.  The device name cannot have a trailing backslash. This parameter can be NULL.  In that case, the QueryDosDevice() function will store a list of all existing MS-DOS device names into the buffer pointed to by lpTargetPath.

lpTargetPath - [out] Pointer to a buffer that will receive the result of the query. The function fills this buffer with one or more null-terminated strings.  The final null-terminated string is followed by an additional NULL. If lpDeviceName is non-NULL, the function retrieves information about the particular MS-DOS device specified by lpDeviceName.  The first null-terminated string stored into the buffer is the current mapping for the device.  The other null-terminated strings represent undeleted prior mappings for the device.

If lpDeviceName is NULL, the function retrieves a list of all existing MS-DOS device names.  Each null-terminated string stored into the buffer is the name of an existing MS-DOS device.

ucchMax - [in] Maximum number of TCHARs that can be stored into the buffer pointed to by lpTargetPath.

The return value

If the function succeeds, the return value is the number of TCHARs stored into the buffer pointed to by lpTargetPath. If the function fails, the return value is zero. To get extended error information, call GetLastError(). If the buffer is too small, the function fails and the last error code is ERROR_INSUFFICIENT_BUFFER.

The header file

<windows.h>

 

Table 4:  QueryDosDevice() information.

#include <windows.h>

#include <stdio.h>

 

// query these on my machine. The L: is thumb drive, J: and K: are CD-ROMs

char lpDeviceName[11][3] = {"A:", "C:", "D:", "E:", "F:", "G:", "H:","I:", "J:", "K:", "L:"};

// the buffer for storage

char lpTargetPath[1000];

 

int main()

{

  for(int i=0; i<13; i++)

  {

    // using NULL for the parameter 1 is not working lol...

    DWORD test = QueryDosDevice(lpDeviceName[i], lpTargetPath, 1000);

    // test the return value and error if any

    printf("\nQueryDosDevice() return value: %d, Error: %d\n", test, GetLastError());

    printf("The DOS device for %s is:\n", lpDeviceName[i]);

    // display the result

    for(int i = 0; i<35; i++)

      printf("%c", lpTargetPath[i]);

  }

     printf("\n");

     return 0;

}

 

The output:

 

QueryDosDevice() return value: 17, Error: 0

The DOS device for A: is:

\Device\Floppy0

QueryDosDevice() return value: 25, Error: 0

The DOS device for C: is:

\Device\HarddiskVolume1

QueryDosDevice() return value: 25, Error: 0

The DOS device for D: is:

\Device\HarddiskVolume5

QueryDosDevice() return value: 25, Error: 0

The DOS device for E: is:

\Device\HarddiskVolume2

QueryDosDevice() return value: 25, Error: 0

The DOS device for F: is:

\Device\HarddiskVolume3

QueryDosDevice() return value: 25, Error: 0

The DOS device for G: is:

\Device\HarddiskVolume4

QueryDosDevice() return value: 25, Error: 0

The DOS device for H: is:

\Device\HarddiskVolume6

QueryDosDevice() return value: 25, Error: 0

The DOS device for I: is:

\Device\HarddiskVolume7

QueryDosDevice() return value: 16, Error: 0

The DOS device for J: is:

\Device\CdRom0   olume7

QueryDosDevice() return value: 16, Error: 0

The DOS device for K: is:

\Device\CdRom1   olume7

QueryDosDevice() return value: 30, Error: 0

The DOS device for L: is:

\Device\Harddisk2\DP(1)0-0+a

QueryDosDevice() return value: 0, Error: 6

The DOS device for  is:

\Device\Harddisk2\DP(1)0-0+a

QueryDosDevice() return value: 0, Error: 6

The DOS device for  is:

\Device\Harddisk2\DP(1)0-0+a

Press any key to continue

Information

Description

The function

GetDiskFreeSpaceEx().

The use

Retrieves information about the amount of space available on a disk volume: the total amount of space, the total amount of free space, and the total amount of free space available to the user associated with the calling thread.

The prototype

BOOL GetDiskFreeSpaceEx( LPCTSTR  lpDirectoryName, PULARGE_INTEGER  lpFreeBytesAvailable,
PULARGE_INTEGER  lpTotalNumberOfBytes,   PULARGE_INTEGER  lpTotalNumberOfFreeBytes);

Example

char pszDrive[10] = "C:\\";

DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;

 

GetDiskFreeSpace(pszDrive, &dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);

The parameters

lpDirectoryName - [in] Pointer to a null-terminated string that specifies a directory on the disk of interest.  If this parameter is NULL, the function uses the root of the current disk.  If this parameter is a UNC name, it must include a trailing backslash (for example, \\MyServer\MyShare\). Note that this parameter does not have to specify the root directory on a disk.  The function accepts any directory on the disk.

lpFreeBytesAvailable - [out] Pointer to a variable that receives the total number of free bytes on the disk that are available to the user associated with the calling thread.  This parameter can be NULL. If per-user quotas are in use, this value may be less than the total number of free bytes on the disk.

lpTotalNumberOfBytes - [out] Pointer to a variable that receives the total number of bytes on the disk that are available to the user associated with the calling thread.  This parameter can be NULL. If per-user quotas are in use, this value may be less than the total number of bytes on the disk. To determine the total number of bytes on a disk or volume, use IOCTL_DISK_GET_LENGTH_INFO.

lpTotalNumberOfFreeBytes - [out] Pointer to a variable that receives the total number of free bytes on the disk.  This parameter can be NULL.

The return value

If the function succeeds, the return value is nonzero.  If the function fails, the return value is zero.  To get extended error information, call GetLastError().

The header file

<windows.h>

 

Table 5:  GetDiskFreeSpaceEx() information.

#include <windows.h>

#include <stdio.h>

 

int main()

{

   char pszDrive[10] = "C:\\";

   // 64 bits integer

   __int64 lpFreeBytesAvailable, lpTotalNumberOfBytes, lpTotalNumberOfFreeBytes;

   DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters, dwTotalClusters;

 

  BOOL test = GetDiskFreeSpaceEx(

  pszDrive,

  (PULARGE_INTEGER)&lpFreeBytesAvailable,

  (PULARGE_INTEGER)&lpTotalNumberOfBytes,

  (PULARGE_INTEGER)&lpTotalNumberOfFreeBytes

);

 

  printf("Drive to be checked: %s\n", pszDrive);

  printf("\nUsing GetDiskFreeSpaceEx()...\n");

  // check the return value

  printf("The return value: %d, error code: %d\n", test, GetLastError());

  printf("Total number of free bytes available for user-caller: %ul\n", lpFreeBytesAvailable);

  printf("Total number of bytes available for user: %ul\n", lpTotalNumberOfBytes);

  // just straight to the free bytes result

  printf("Total number of free bytes on disk: %ul\n", lpTotalNumberOfFreeBytes);

 

  BOOL fResult = GetDiskFreeSpace(pszDrive,

                 &dwSectPerClust,

                 &dwBytesPerSect,

                 &dwFreeClusters,

                 &dwTotalClusters);

   

    printf("\nUsing GetDiskFreeSpace()...\n");

    printf("The return value: %d, error code: %d\n", fResult, GetLastError());

    printf("Sector per cluster = %ul\n", dwSectPerClust);

    printf("Bytes per sector = %ul\n", dwBytesPerSect);

    printf("Free cluster = %ul\n", dwFreeClusters);

    printf("Total cluster = %ul\n", dwTotalClusters);

    // using GetDiskFreeSpace() need some calculation for the free bytes on disk

    printf("Total free bytes = %ul\n", (dwFreeClusters*dwSectPerClust*dwBytesPerSect));

   

  return 0;

}

 

 

The output:

 

Drive to be checked: C:\

 

Using GetDiskFreeSpaceEx()...

The return value: 1, error code: 0

Total number of free bytes available for user-caller: 263147520l

Total number of bytes available for user: 1897263104l

Total number of free bytes on disk: 263147520l

 

Using GetDiskFreeSpace()...

The return value: 1, error code: 0

Sector per cluster = 8l

Bytes per sector = 512l

Free cluster = 64245l

Total cluster = 2560351l

Total free bytes = 263147520l

Press any key to continue

 

Naming a Volume Stories

  1. Two different volumes can have the same label, which makes them indistinguishable except by drive letter.

  2. Drive letters do not necessarily remain the same.  If a computer's administrator does not use the Disk Administrator to enforce drive letters, then drive letters can change as drives are removed from or added to the system.

"\\?\Volume{GUID}\"

\\?\Volume{a3446ed5-ebd9-11d8-a25c-806d6172696f}\

  1. Refer to volumes by their unique volume names.

  2. Use the Unicode (W) versions of file functions, which support the \\?\ prefix.

Information

Description

The function

GetVolumeInformation().

The use

Retrieves information about a file system and volume whose root directory is specified.

The prototype

BOOL GetVolumeInformation( LPCTSTR lpRootPathName, LPTSTR  lpVolumeNameBuffer, DWORD   nVolumeNameSize,
LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags,
LPTSTR  lpFileSystemNameBuffer, DWORD   nFileSystemNameSize);

Example

#define BUFSIZE MAX_PATH

#define FILESYSNAMEBUFSIZE MAX_PATH

 

// buffer for unique volume identifiers

char buf[BUFSIZE];

DWORD lpMaximumComponentLength;

// flags that describe the file system

DWORD dwSysFlags;

char FileSysNameBuf[FILESYSNAMEBUFSIZE];

 

GetVolumeInformation( buf, NULL, BUFSIZE, NULL, &lpMaximumComponentLength, &dwSysFlags, FileSysNameBuf, FILESYSNAMEBUFSIZE);

The parameters

lpRootPathName - [in] Pointer to a string that contains the root directory of the volume to be described.  If this parameter is NULL, the root of the current directory is used.  A trailing backslash is required.  For example, you would specify \\MyServer\MyShare as \\MyServer\MyShare\, or the C drive as "C:\".

lpVolumeNameBuffer - [out] Pointer to a buffer that receives the name of the specified volume.

nVolumeNameSize - [in] Length of the volume name buffer, in TCHARs.  This parameter is ignored if the volume name buffer is not supplied.

lpVolumeSerialNumber - [out] Pointer to a variable that receives the volume serial number. This parameter can be NULL if the serial number is not required.

lpMaximumComponentLength - [out] Pointer to a variable that receives the maximum length, in TCHARs, of a file name component supported by the specified file system. A file name component is that portion of a file name between backslashes. The value stored in variable pointed to by *lpMaximumComponentLength is used to indicate that long names are supported by the specified file system.  For example, for a FAT file system supporting long names, the function stores the value 255, rather than the previous 8.3 indicator.  Long names can also be supported on systems that use the NTFS file system.

lpFileSystemFlags - [out] Pointer to a variable that receives flags associated with the specified file system.  This parameter can be one or more of the following flags; however, FS_FILE_COMPRESSION and FS_VOL_IS_COMPRESSED are mutually exclusive.

  1. FILE_NAMED_STREAMS - The file system supports named streams.

  2. FILE_READ_ONLY_VOLUME - The specified volume is read-only.

  3. FILE_SUPPORTS_OBJECT_IDS - The file system supports object identifiers.

  4. FILE_SUPPORTS_REPARSE_POINTS - The file system supports reparse points.

  5. FILE_SUPPORTS_SPARSE_FILES - The file system supports sparse files.

  6. FILE_VOLUME_QUOTAS - The file system supports disk quotas.

  7. FS_CASE_IS_PRESERVED - The file system preserves the case of file names when it places a name on disk.

  8. FS_CASE_SENSITIVE - The file system supports case-sensitive file names.

  9. FS_FILE_COMPRESSION - The file system supports file-based compression.

  10. FS_FILE_ENCRYPTION - The file system supports the Encrypted File System (EFS).

  11. FS_PERSISTENT_ACLS