|
|
/*
* HrDiskStorageEntry.c v0.10 * Generated in conjunction with Management Factory scripts: * script version: SNMPv1, 0.16, Apr 25, 1996 * project: D:\TEMP\EXAMPLE\HOSTMIB **************************************************************************** * * * (C) Copyright 1995 DIGITAL EQUIPMENT CORPORATION * * * * This software is an unpublished work protected under the * * the copyright laws of the United States of America, all * * rights reserved. * * * * In the event this software is licensed for use by the United * * States Government, all use, duplication or disclosure by the * * United States Government is subject to restrictions as set * * forth in either subparagraph (c)(1)(ii) of the Rights in * * Technical Data And Computer Software Clause at DFARS * * 252.227-7013, or the Commercial Computer Software Restricted * * Rights Clause at FAR 52.221-19, whichever is applicable. * * * **************************************************************************** * * Facility: * * Windows NT SNMP Extension Agent * * Abstract: * * This module contains the code for dealing with the get, set, and * instance name routines for the HrDiskStorageEntry. Actual * instrumentation code is supplied by the developer. * * Functions: * * A get and set routine for each attribute in the class. * * The routines for instances within the class. * * Author: * * D. D. Burns @ Webenable Inc * * Revision History: * * V1.00 - 04/28/97 D. D. Burns Genned: Thu Nov 07 16:43:17 1996 * */
#include <windows.h>
#include <malloc.h>
#include <stdio.h> /* For sprintf */
#include <string.h>
#include <snmp.h>
#include "mib.h"
#include "smint.h"
#include "hostmsmi.h"
#include "user.h" /* Developer supplied include file */
#include "HMCACHE.H" /* Cache-related definitions */
#include "HRDEVENT.H" /* HrDevice Table-related definitions */
#include <winioctl.h> /* For PARTITION_INFORMATION et. al. */
/*
|============================================================================== | Function prototypes for this module. | */ /* Gen_nonFixed_disks - Scan for Floppies and CD-ROMS */ static BOOL Gen_nonFixed_disks ( ULONG type_arc );
/* Gen_Fixed_disks - Scan for Fixed Disks */ static BOOL Gen_Fixed_disks ( ULONG type_arc );
/* ProcessPartitions - Process Partition Information into HrDevice Row */ static BOOL ProcessPartitions( HANDLE hdrv, /* Fixed-Disk containing partitions */ CACHEROW *dv_row, /* Row in hrDevice table for disk */ CHAR *pntdev /* NT Device name for physical disk */ );
/* Process_DS_Row - Process Information into HrDevice and hrDiskStorage Row */ static CACHEROW *Process_DS_Row ( ULONG type_arc, /* hrDeviceType last arc value */ ULONG access, /* hrDiskStorageAccess = readWrite(1) */ ULONG media, /* hrDiskStorageMedia = floppyDisk(4) */ ULONG removable, /* hrDiskStorageRemovable = TRUE */ ULONG capacityKB,/* hrDiskStorageCapacity, (kilobytes) */ ULONG status, /* hrDeviceStatus = unknown(1) */ CHAR *descr /* hrDeviceDescr string */ );
/* FindPartitionLabel - Find MS-DOS Device Label for a Fixed-Disk Partition */ static PCHAR FindPartitionLabel( CHAR *pntdev, /* NT Device name for physical disk */ UINT part_id /* Partition Number (1-origined) */ );
/* debug_print_hrdiskstorage - Prints a Row from HrDiskStorage sub-table */ static void debug_print_hrdiskstorage( CACHEROW *row /* Row in hrDiskStorage table */ );
/* debug_print_hrpartition - Prints a Row from HrPartition sub-table */ static void debug_print_hrpartition( CACHEROW *row /* Row in hrPartition table */ );
/*
|============================================================================== | Create the list-head for the HrDiskStorage cache. | | (This macro is defined in "HMCACHE.H"). */ CACHEHEAD_INSTANCE(hrDiskStorage_cache, debug_print_hrdiskstorage);
/*
* GetHrDiskStorageAccess * An indication if this long-term storage device is readable and writable * or only readable. This should reflect the media type, a * * Gets the value for HrDiskStorageAccess. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrDiskStorageAccess | | ACCESS SYNTAX | read-only INTEGER {readWrite(1), readOnly(2)} | | "An indication if this long-term storage device is readable and writable or | only readable. This should reflect the media type, any write-protect | mechanism, and any device configuration that affects the entire device." | | DISCUSSION: | | This information for the entire drive is obtained using Win32 API CreateFile | to open the device and DeviceIoControl to retrieve the needed information. | |============================================================================ | 1.3.6.1.2.1.25.3.6.1.1.<instance> | | | | | | | | | *-hrDiskStorageAccess | | | *-hrDiskStorageEntry | | *-hrDiskStorageTable (the table) | *-hrDevice */
UINT GetHrDiskStorageAccess( OUT INTAccess *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrDiskStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Return the "hrDiskStorageAccess" value from this entry */ *outvalue = row->attrib_list[HRDS_ACCESS].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrDiskStorageAccess() */
/*
* GetHrDiskStorageMedia * An indication of the type of media used in this long-term storage device. * * Gets the value for HrDiskStorageMedia. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrDiskStorageMedia | | ACCESS SYNTAX | read-only INTEGER {other(1),unknown(2),hardDisk(3),floppyDisk(4), | opticalDiskROM(5),opticalDiskWORM(6),opticalDiskRW(7), | ramDisk(8)} | | "An indication of the type of media used in this long-term storage device." | | Discussion | | This information for the entire drive is obtained using Win32 API CreateFile | to open the device and DeviceIoControl to retrieve the needed information. | |============================================================================ | 1.3.6.1.2.1.25.3.6.1.2.<instance> | | | | | | | | | *-hrDiskStorageMedia | | | *-hrDiskStorageEntry | | *-hrDiskStorageTable (the table) | *-hrDevice */
UINT GetHrDiskStorageMedia( OUT INThrDiskStorageMedia *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrDiskStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Return the "hrDiskStorageAccess" value from this entry */ *outvalue = row->attrib_list[HRDS_MEDIA].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrDiskStorageMedia() */
/*
* GetHrDiskStorageRemoveble * Denotes whether or not the disk media may be removed from the drive. * * Gets the value for HrDiskStorageRemoveble. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrDiskStorageRemoveble | | ACCESS SYNTAX | read-only Boolean | | "Denotes whether or not the disk media may be removed from the drive." | | DISCUSSION: | | This information for the entire drive is obtained using Win32 API CreateFile | to open the device and DeviceIoControl to retrieve the needed information. | |============================================================================ | 1.3.6.1.2.1.25.3.6.1.3.<instance> | | | | | | | | | *-hrDiskStorageRemovable | | | *-hrDiskStorageEntry | | *-hrDiskStorageTable (the table) | *-hrDevice */
UINT GetHrDiskStorageRemoveble( OUT Boolean *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrDiskStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Return the "hrDiskStorageRemovable" value from this entry */ *outvalue = row->attrib_list[HRDS_REMOVABLE].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrDiskStorageRemoveble() */
/*
* GetHrDiskStorageCapacity * The total size for this long-term storage device. * * Gets the value for HrDiskStorageCapacity. * * Arguments: * * outvalue address to return variable value * accesss Reserved for future security use * instance address of instance name as ordered native * data type(s) * * Return Codes: * * Standard PDU error codes. * * SNMP_ERRORSTATUS_NOERROR Successful get * SNMP_ERRORSTATUS_GENERR Catch-all failure code * mibtget.c v0.10 * | =============== From WebEnable Design Spec Rev 3 04/11/97================== | hrDiskStorageCapacity | | ACCESS SYNTAX | read-only KBytes | | "The total size for this long-term storage device." | | DISCUSSION: | | This information for the entire drive is obtained using Win32 API CreateFile | to open the device and DeviceIoControl to retrieve the needed information. | |============================================================================ | 1.3.6.1.2.1.25.3.6.1.4.<instance> | | | | | | | | | *-hrDiskStorageCapacity | | | *-hrDiskStorageEntry | | *-hrDiskStorageTable (the table) | *-hrDevice */
UINT GetHrDiskStorageCapacity( OUT KBytes *outvalue , IN Access_Credential *access , IN InstanceName *instance )
{ ULONG index; /* As fetched from instance structure */ CACHEROW *row; /* Row entry fetched from cache */
/*
| Grab the instance information */ index = GET_INSTANCE(0);
/*
| Use it to find the right entry in the cache */ if ((row = FindTableRow(index, &hrDiskStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_GENERR; }
/*
| Return the "hrDiskStorageCapacity" value from this entry */ *outvalue = row->attrib_list[HRDS_CAPACITY].u.unumber_value;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of GetHrDiskStorageCapacity() */
/*
* HrDiskStorageEntryFindInstance * * This routine is used to verify that the specified instance is * valid. * * Arguments: * * FullOid Address for the full oid - group, variable, * and instance information * instance Address for instance specification as an oid * * Return Codes: * * SNMP_ERRORSTATUS_NOERROR Instance found and valid * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance * */
UINT HrDiskStorageEntryFindInstance( IN ObjectIdentifier *FullOid , IN OUT ObjectIdentifier *instance ) { UINT tmp_instance ;
//
// Developer instrumentation code to find appropriate instance goes here.
// For non-tables, it is not necessary to modify this routine. However, if
// there is any context that needs to be set, it can be done here.
//
if ( FullOid->idLength <= HRDISKSTORAGEENTRY_VAR_INDEX ) // No instance was specified
return SNMP_ERRORSTATUS_NOSUCHNAME ; else if ( FullOid->idLength != HRDISKSTORAGEENTRY_VAR_INDEX + 1 ) // Instance length is more than 1
return SNMP_ERRORSTATUS_NOSUCHNAME ; else // The only valid instance for a non-table are instance 0. If this
// is a non-table, the following code validates the instances. If this
// is a table, developer modification is necessary below.
tmp_instance = FullOid->ids[ HRDISKSTORAGEENTRY_VAR_INDEX ] ;
/*
| For hrDiskStorage, the instance arc(s) is a single arc, and it must | correctly select an entry in the hrDiskStorage cache. | Check that here. | | Note that if there is a row there, there is also one in the | hrDevice table with the same index. */ if ( FindTableRow(tmp_instance, &hrDiskStorage_cache) == NULL ) { return SNMP_ERRORSTATUS_NOSUCHNAME ; } else { // the instance is valid. Create the instance portion of the OID
// to be returned from this call.
instance->ids[ 0 ] = tmp_instance ; instance->idLength = 1 ; }
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of HrDiskStorageEntryFindInstance() */
/*
* HrDiskStorageEntryFindNextInstance * * This routine is called to get the next instance. If no instance * was passed than return the first instance (1). * * Arguments: * * FullOid Address for the full oid - group, variable, * and instance information * instance Address for instance specification as an oid * * Return Codes: * * SNMP_ERRORSTATUS_NOERROR Instance found and valid * SNMP_ERRORSTATUS_NOSUCHNAME Invalid instance * */
UINT HrDiskStorageEntryFindNextInstance( IN ObjectIdentifier *FullOid , IN OUT ObjectIdentifier *instance ) { //
// Developer supplied code to find the next instance of class goes here.
// If this is a class with cardinality 1, no modification of this routine
// is necessary unless additional context needs to be set.
// If the FullOid does not specify an instance, then the only instance
// of the class is returned. If this is a table, the first row of the
// table is returned.
//
// If an instance is specified and this is a non-table class, then
// NOSUCHNAME is returned so that correct MIB rollover processing occurs.
// If this is a table, then the next instance is the one following the
// current instance.
//
// If there are no more instances in the table, return NOSUCHNAME.
//
CACHEROW *row; ULONG tmp_instance;
if ( FullOid->idLength <= HRDISKSTORAGEENTRY_VAR_INDEX ) { /*
| Too short: must return the instance arc that selects the first | entry in the table if there is one. */ tmp_instance = 0; } else { /*
| There is at least one instance arc. Even if it is the only arc | we use it as the "index" in a request for the "NEXT" one. */ tmp_instance = FullOid->ids[ HRDISKSTORAGEENTRY_VAR_INDEX ] ; }
/* Now go off and try to find the next instance in the table */ if ((row = FindNextTableRow(tmp_instance, &hrDiskStorage_cache)) == NULL) { return SNMP_ERRORSTATUS_NOSUCHNAME ; }
instance->ids[ 0 ] = row->index ; instance->idLength = 1 ;
return SNMP_ERRORSTATUS_NOERROR ;
} /* end of HrDiskStorageEntryFindNextInstance() */
/*
* HrDiskStorageEntryConvertInstance * * This routine is used to convert the object id specification of an * instance into an ordered native representation. The object id format * is that object identifier that is returned from the Find Instance * or Find Next Instance routines. It is NOT the full object identifier * that contains the group and variable object ids as well. The native * representation is an argc/argv-like structure that contains the * ordered variables that define the instance. This is specified by * the MIB's INDEX clause. See RFC 1212 for information about the INDEX * clause. * * * Arguments: * * oid_spec Address of the object id instance specification * native_spec Address to return the ordered native instance * specification * * Return Codes: * * SUCCESS Conversion complete successfully * FAILURE Unable to convert object id into native format * */
UINT HrDiskStorageEntryConvertInstance( IN ObjectIdentifier *oid_spec , IN OUT InstanceName *native_spec ) { static char *array; /* The address of this (char *) is passed back */ /* as though it were an array of length 1 of these */ /* types. */
static ULONG inst; /* The address of this ULONG is passed back */ /* (Obviously, no "free()" action is needed) */
/* We only expect the one arc in "oid_spec" */ inst = oid_spec->ids[0]; array = (char *) &inst;
native_spec->count = 1; native_spec->array = &array; return SUCCESS ;
} /* end of HrDiskStorageEntryConvertInstance() */
/*
* HrDiskStorageEntryFreeInstance * * This routine is used to free an ordered native representation of an * instance name. * * Arguments: * * instance Address to return the ordered native instance * specification * * Return Codes: * * */
void HrDiskStorageEntryFreeInstance( IN OUT InstanceName *instance ) {
/* No action needed for hrDiskStorageTable */ } /* end of HrDiskStorageEntryFreeInstance() */
/*
| End of Generated Code */
/* Gen_HrDiskStorage_Cache - Generate a initial cache for HrDiskStorage Table */ /* Gen_HrDiskStorage_Cache - Generate a initial cache for HrDiskStorage Table */ /* Gen_HrDiskStorage_Cache - Generate a initial cache for HrDiskStorage Table */
BOOL Gen_HrDiskStorage_Cache( ULONG type_arc )
/*
| EXPLICIT INPUTS: | | "type_arc" is the number "n" to be used as the last arc in the | device-type OID: | | 1.3.6.1.2.1.25.3.1.n | | | | | | | * Identifying arc for type | | *-hrDeviceTypes (OIDs specifying device types) | *-hrDevice | | for devices created by this cache-population routine. | | IMPLICIT INPUTS: | | The module-local head of the cache for the HrDiskStorage table, | "HrDiskStorage_cache". | | OUTPUTS: | | On Success: | Function returns TRUE indicating that both caches have been fully | populated with all "static" cache-able values. This function populates | not only the hrDevice table cache but the hrDiskStorage cache as well. | | On any Failure: | Function returns FALSE (indicating "not enough storage"). | | THE BIG PICTURE: | | At subagent startup time, the cache for each table in the MIB is | populated with rows for each row in the table. This function is | invoked by the start-up code in "Gen_HrDevice_Cache()" ("HRDEVENT.C") | to populate the cache for the HrDiskStorage table AND the hrDevice | Table. | | OTHER THINGS TO KNOW: | | There is one of these function for every table that has a cache. | Each is found in the respective source file. | | This function differs from all of the other corresponding sub-table | function instances in that this sub-table has its own cache, rather | than depending solely on that of the hrDevice table. | | As a consequence, we don't need fancy logic in the FindInstance() | and FindNextInstance() functions to determine whether a particular | instance is valid: if it is, there is a row entry in the local | hrDiskStorage cache. | | As another consequence, this function must load both caches with | data (and it must use the same "index" numbers in both caches | for each row entered). | | ---- | | The strategy on getting all disks goes like this: | | * Since the "\\.\PHYSICALDRIVEn" trick with "CreateFile" doesn't allow | access to floppies or CD-ROMs, we process these separately as a | first step. | | + We presume "A:" and "B:" may be floppies and we look for them | explicitly. Any found are presumed "readWrite" and Removable. | If a medium is present, we may get a full description plus an | accurate storage size, otherwise we just don't know for sure, | (DeviceIoControl for drive info fails if no disk is in the | floppy drive). | | + We then scan all logical drive strings looking for instances of | CD-ROM drives. Any found are presumed "readOnly" and Removable. | We can't obtain storage sizes even if a disk is present for these, | so storage is left at zero. | | * Then the "\\.\PHYSICALDRIVEn" trick is used to enumerate the real | hard disks, and real storage sizes are obtainable. | |============================================================================ | 1.3.6.1.2.1.25.3.6.... | | | | | *-hrDiskStorageTable (the table) | *-hrDevice */ {
// Blow away any old copy of the cache
DestroyTable(&hrDiskStorage_cache);
/*
| Do Floppies and CD-ROM drives (non-fixed disks) */ if (Gen_nonFixed_disks( type_arc ) == FALSE) { DestroyTable(&hrDiskStorage_cache); // destroy any partial rows if necessary
return ( FALSE ); }
/*
| Do Fixed drives */ if (Gen_Fixed_disks( type_arc ) == FALSE) { DestroyTable(&hrDiskStorage_cache); return ( FALSE ); }
/* Success */ return ( TRUE ); }
/* Gen_nonFixed_disks - Scan for Floppies and CD-ROMS */ /* Gen_nonFixed_disks - Scan for Floppies and CD-ROMS */ /* Gen_nonFixed_disks - Scan for Floppies and CD-ROMS */
static BOOL Gen_nonFixed_disks ( ULONG type_arc ) /*
| EXPLICIT INPUTS: | | "type_arc" is the number "n" to be used as the last arc in the | device-type OID: | | 1.3.6.1.2.1.25.3.1.n | | | | | | | * Identifying arc for type | | *-hrDeviceTypes (OIDs specifying device types) | *-hrDevice | | for devices created by this cache-population routine. | | IMPLICIT INPUTS: | | The module-local head of the cache for the HrDiskStorage table, | "HrDiskStorage_cache". | | OUTPUTS: | | On Success: | Function returns TRUE indicating that the both cachees have been fully | populated with all non-Fixed disks. | | On any Failure: | Function returns FALSE (indicating "not enough storage"). | | THE BIG PICTURE: | | Part I of hrDiskStorage cache population. | | OTHER THINGS TO KNOW: | | We scan using the list of Logical Disk drive strings from | GetLogicalDriveStrings() formed up into UNC form, (e.g. "\\.\A:" | for "A:\" returned from GetLogicalDriveStrings()). */ { CHAR temp[8]; /* Temporary buffer for first call */ LPSTR pDrvStrings; /* --> allocated storage for drive strings */ LPSTR pOriginal_DrvStrings; /* (Needed for final deallocation */ DWORD DS_request_len; /* Storage actually needed */ DWORD DS_current_len; /* Storage used on 2nd call */
#define PHYS_SIZE 32
CHAR phys_name[PHYS_SIZE+1]; /* Buffer where a string like "\\.C:" (for */ /* example) is built for drive access. */
phys_name[PHYS_SIZE] = 0; // ensures null terminated phys_name
/*
| We're going to call GetLogicalDriveStrings() twice, once to get the proper | buffer size, and the second time to actually get the drive strings. | | The Bogus call. */ if ((DS_request_len = GetLogicalDriveStrings(2, temp)) == 0) {
/* Request failed altogether, can't initialize */ return ( FALSE ); }
/*
| Grab enough storage for the drive strings plus one null byte at the end */
if ( (pOriginal_DrvStrings = pDrvStrings = malloc( (DS_request_len + 2) ) ) == NULL) {
/* Storage Request failed altogether, can't initialize */ return ( FALSE ); }
/* Go for all of the strings
| | The Real Call. */ if ((DS_current_len = GetLogicalDriveStrings(DS_request_len, pDrvStrings)) == 0) {
/* Request failed altogether, can't initialize */ free( pOriginal_DrvStrings ); return ( FALSE ); }
/*
|============================================================================== | For each logical drive . . . */ while ( strlen(pDrvStrings) > 0 ) {
UINT drivetype; /* Type of the drive from "GetDriveType()" */
/*
| Get the drive-type so we can decide whether it should participate in | this population effort. We do only CD-ROMS and REMOVABLES. */ drivetype = GetDriveType(pDrvStrings);
/* Skip the stuff we don't want to look at */ if ( drivetype != DRIVE_REMOVABLE && drivetype != DRIVE_CDROM ) {
/* Step to next string, if any */ pDrvStrings += strlen(pDrvStrings) + 1;
continue; }
/* If we have room in the buffer to build the handle-name string */ if ((strlen(pDrvStrings) + strlen("\\\\.\\")) < PHYS_SIZE) {
#define DESCR_BSZ 512
CHAR d_buf[DESCR_BSZ+1];/* Dsecription bld buff */ HANDLE hdrv; /* Handle to device */ DWORD bytes_out; /* Bytes retnd into geo_info */ DISK_GEOMETRY geo_info; /* Geometry Info from drive */ char *mt; /* Media Type */
ULONG access; /* hrDiskStorageAccess = readWrite(1) */ ULONG media; /* hrDiskStorageMedia = floppyDisk(4) */ ULONG removable; /* hrDiskStorageRemovable = TRUE */ ULONG capacityKB; /* hrDiskStorageCapacity, (kilobytes) */ ULONG status; /* hrDeviceStatus = unknown(1) */ CHAR *descr; /* hrDeviceDescr string */ UINT nPrevErrorMode; /* previous state of error-mode bit flags */
d_buf[DESCR_BSZ] = 0; // ensures null terminated d_buf
/* 012345
| Build it for device A: "\\.\A:" */ _snprintf(phys_name, PHYS_SIZE, "\\\\.\\%2.2s", pDrvStrings);
/*
| Set SNMP variables accordingly */ if (drivetype != DRIVE_CDROM) { /* Floppy */
access = 1; /* hrDiskStorageAccess = readWrite(1) */ media = 4; /* hrDiskStorageMedia = floppyDisk(4) */ removable = TRUE; /* hrDiskStorageRemovable = TRUE */ capacityKB = 0; /* hrDiskStorageCapacity (unknown) */ status = 1; /* hrDeviceStatus = unknown(1) */ descr = pDrvStrings; /* hrDeviceDescr, initial (e.g."A:\") */ }
else { /* CD-ROM */ /*
| We can't get much of anything about CD-ROMs except the fact | that there is one. Capacity cannot be presumed as DVD is | now available and some drives read both CD-ROMs and DVD. */ access = 2; /* hrDiskStorageAccess = readOnly(2) */ media = 5; /* hrDiskStorageMedia = opticalDiskROM(5)*/ removable = TRUE; /* hrDiskStorageRemovable = TRUE */ capacityKB = 0; /* hrDiskStorageCapacity (unknown) */ status = 1; /* hrDeviceStatus = unknown(1) */ descr = pDrvStrings; /* hrDeviceDescr, initial (e.g."D:\") */ }
/*
| Suppress any attempt by the system to make the user put a volume in a | removable drive ("CreateFile" will just fail). */ nPrevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
/* Attempt to get a handle using this physical name string */ hdrv = CreateFile(phys_name, // Device
GENERIC_READ, // device query
// Share Mode
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // Security
OPEN_EXISTING, // CreationDistribution
FILE_ATTRIBUTE_NORMAL, // FlagsandAttributes
NULL // Template file
);
/* If we successfully opened the device . . . */ if (hdrv != INVALID_HANDLE_VALUE) {
/*
| Device is Open. | | If it is NOT a CD-ROM, (ie, a floppy) its worth trying to get | DRIVE GEOMETRY (which will come back if there is a floppy in | the drive). */
if (drivetype != DRIVE_CDROM) { /* Floppy */
/* ==========================================================
| IOCTL_DISK_GET_DRIVE_GEOMETRY | | If we can get this, we get a better description and an | accurate capacity value. */ if (DeviceIoControl(hdrv, // device handle
// IoControlCode (op-code)
IOCTL_DISK_GET_DRIVE_GEOMETRY,
NULL, // "input buffer"
0, // "input buffer size"
&geo_info, // "output buffer"
// "output buffer size"
sizeof(DISK_GEOMETRY),
&bytes_out, // bytes written to geo_info
NULL // no Overlapped I/o
)) {
/*
| Compute capacity */ capacityKB = (ULONG) ((geo_info.Cylinders.QuadPart * // 64 bits
(geo_info.TracksPerCylinder * // 32 bits
geo_info.SectorsPerTrack * geo_info.BytesPerSector)
) / 1024);
/* hrDeviceStatus = running(2) */ status = 2;
switch ( geo_info.MediaType ) {
case F5_1Pt2_512: mt = "5.25, 1.2MB, 512 bytes/sector"; break; case F3_1Pt44_512: mt = "3.5, 1.44MB, 512 bytes/sector"; break; case F3_2Pt88_512: mt = "3.5, 2.88MB, 512 bytes/sector"; break; case F3_20Pt8_512: mt = "3.5, 20.8MB, 512 bytes/sector"; break; case F3_720_512: mt = "3.5, 720KB, 512 bytes/sector"; break; case F5_360_512: mt = "5.25, 360KB, 512 bytes/sector"; break; case F5_320_512: mt = "5.25, 320KB, 512 bytes/sector"; break; case F5_320_1024: mt = "5.25, 320KB, 1024 bytes/sector"; break; case F5_180_512: mt = "5.25, 180KB, 512 bytes/sector"; break; case F5_160_512: mt = "5.25, 160KB, 512 bytes/sector"; break; case F3_120M_512: mt = "3.5, 120M Floppy"; break; case F3_640_512: mt = "3.5 , 640KB, 512 bytes/sector"; break; case F5_640_512: mt = "5.25, 640KB, 512 bytes/sector"; break; case F5_720_512: mt = "5.25, 720KB, 512 bytes/sector"; break; case F3_1Pt2_512: mt = "3.5 , 1.2Mb, 512 bytes/sector"; break; case F3_1Pt23_1024: mt = "3.5 , 1.23Mb, 1024 bytes/sector"; break; case F5_1Pt23_1024: mt = "5.25, 1.23MB, 1024 bytes/sector"; break; case F3_128Mb_512: mt = "3.5 MO 128Mb 512 bytes/sector"; break; case F3_230Mb_512: mt = "3.5 MO 230Mb 512 bytes/sector"; break; case F8_256_128: mt = "8in, 256KB, 128 bytes/sector"; break;
default: case RemovableMedia: case FixedMedia: case Unknown: mt = "Format is unknown"; break; }
/* Format a better description if it'll all fit */ if ((strlen(pDrvStrings) + strlen(mt) + 1) < DESCR_BSZ ) { _snprintf(d_buf, DESCR_BSZ, "%s%s", pDrvStrings, mt); descr = d_buf; } } /* If (we managed to get geometry information) */ }
CloseHandle(hdrv);
} /* if (we managed to "CreateFile" the device successfully) */
SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */
/*
| Create a row in HrDevice Table and a corresponding row in | hrDiskStorage sub-table. */ if ( Process_DS_Row ( type_arc, /* hrDeviceType last arc */ access, /* hrDiskStorageAccess */ media, /* hrDiskStorageMedia */ removable, /* hrDiskStorageRemovable */ capacityKB,/* hrDiskStorageCapacity */ status, /* hrDeviceStatus */ descr /* hrDeviceDescr */ ) == NULL) {
/* Something blew */ free( pOriginal_DrvStrings ); return ( FALSE ); } } /* if (we managed to build a device name) */
/* Step to next string, if any */ pDrvStrings += strlen(pDrvStrings) + 1; }
free( pOriginal_DrvStrings );
/* Successful scan */ return ( TRUE ); }
/* Gen_Fixed_disks - Scan for Fixed Disks */ /* Gen_Fixed_disks - Scan for Fixed Disks */ /* Gen_Fixed_disks - Scan for Fixed Disks */
static BOOL Gen_Fixed_disks ( ULONG type_arc ) /*
| EXPLICIT INPUTS: | | "type_arc" is the number "n" to be used as the last arc in the | device-type OID: | | 1.3.6.1.2.1.25.3.1.n | | | | | | | * Identifying arc for type | | *-hrDeviceTypes (OIDs specifying device types) | *-hrDevice | | for devices created by this cache-population routine. | | IMPLICIT INPUTS: | | The module-local head of the cache for the HrDiskStorage table, | "HrDiskStorage_cache". | | OUTPUTS: | | On Success: | Function returns TRUE indicating that the both cachees have been fully | populated with all non-Fixed disks. If the device from which the | system was booted is encountered, it's hrDevice index is set into | "InitLoadDev_index" (defined in "HRDEVENT.C"). | | On any Failure: | Function returns FALSE (indicating "not enough storage"). | | THE BIG PICTURE: | | Part II of hrDiskStorage cache population. | | OTHER THINGS TO KNOW: | | We scan using the "\\.\PHYSICALDRIVEx" syntax permitted to | "CreateFile()". CreateFile seems to allow opens only on disks | that are hard-fixed disks (no floppies, no CD-ROMS). | | This function is also (while it is "at it") looking for the drive | from which the system was booted (in order to set a global value | (hrdevice table index) for the value of "InitLoadDev_index" (defined | in "HRDEVENT.C") which becomes the value of "HrSystemInitialLoadDevice". */ { HANDLE hdrv; /* Handle to device */ UINT dev_number; /* Current "x" in "\\.\PHYSICALDRIVEx" */
#undef PHYS_SIZE
#define PHYS_SIZE 64
CHAR phys_name[PHYS_SIZE+1]; /* Buffer where a string like */ /* "\\.PHYSICALDRIVE0" (for example) */ /* is built for drive access. */
DRIVE_LAYOUT_INFORMATION *dl; /* Drive-layout pointer */ #define BBSz 768
CHAR big[BBSz]; /* Big buffer for layout info */ DWORD bytes_out; /* Bytes retnd into "big" */
CHAR windir[MAX_PATH+1]; /* Current Windows Directory */ CHAR ntdev[MAX_PATH+2]; /* NT Device Name for MSDOS drive */ CHAR pntdev[MAX_PATH+2]; /* NT Device Name for PHYSICALDRIVE*/ UINT nPrevErrorMode; /* previous state of error-mode bit flags */
phys_name[PHYS_SIZE] = 0; // ensures null terminated phys_name
/*
|============================================================================== | Compute the NT "device name" we expect is the device from which the | system was booted. | | Strategy: | | - Obtain "current windows directory" and truncate to obtain just the MS-DOS | device name. | | - Do QueryDosDevice to get the underlying "NT Device Name", which will | include a "\PartitionX" on the end of it, where "X" is presumed to be | the 1-origined partition number. | | - Mangle the NT Device Name so that it sez "....\Partition0" (ie "partition | zero") which is the NT Device Name we expect to be associated with the | "\\.\PHYSICALDRIVEy" string we generate for each valid fixed disk below. */ /* If we can get the current Windows Directory */ if (GetWindowsDirectory(windir, MAX_PATH+1) != 0 ) {
/* Truncate to just "C:" (or whatever) */ windir[2] = 0;
/* Obtain the NT Device Name associated with MS-DOS logical drive */ if (QueryDosDevice(windir, ntdev, MAX_PATH) != 0) {
PCHAR partition;
/* If the string "\Partition" appears in this string */ if ((partition = strstr(ntdev,"\\Partition")) != NULL) {
/* Convert it to say "\Partition0" regardless */ strcpy(partition, "\\Partition0"); } else { /* Failure: Null-terminate so we fail gracefully */ ntdev[0] = '\0'; } } else { /* Failure: Null-terminate so we fail gracefully */ ntdev[0] = '\0'; } } else { /* Failure: Null-terminate so we fail gracefully */ ntdev[0] = '\0'; }
/*
|============================================================================== | For every physical device we can open successfully. . . */ for (dev_number = 0; ; dev_number += 1) {
/* Build it for device n: "\\.\PHYSICALDRIVEn" */ _snprintf(phys_name, PHYS_SIZE, "\\\\.\\PHYSICALDRIVE%d", dev_number);
/*
| Suppress any attempt by the system to make the user put a volume in a | removable drive ("CreateFile" will just fail). */ nPrevErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
/* Attempt to get a handle using this physical name string */ if ((hdrv = CreateFile(phys_name, // Device
GENERIC_READ, // Access
// Share Mode
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, // Security
OPEN_EXISTING, // CreationDistribution
FILE_ATTRIBUTE_NORMAL, // FlagsandAttributes
NULL // Template file
)) != INVALID_HANDLE_VALUE) {
ULONG access; /* hrDiskStorageAccess = readWrite(1) */ ULONG media; /* hrDiskStorageMedia = floppyDisk(4) */ ULONG removable; /* hrDiskStorageRemovable = TRUE */ ULONG capacityKB; /* hrDiskStorageCapacity, (kilobytes) */ ULONG status; /* hrDeviceStatus = unknown(1) */ CHAR *descr; /* hrDeviceDescr string */ DWORD bytes_out; /* Bytes retnd into geo_info */ DISK_GEOMETRY geo_info; /* Geometry Info from drive */ char *mt; /* Media Type */ CACHEROW *dv_row; /* HrDevice table row created for disk*/
/*
| Device is Open, so we can presume it really exists, so it goes | into the hrDevice table. | | It is presumed to be a FIXED disk. */
access = 1; /* hrDiskStorageAccess = readWrite(1) */ media = 3; /* hrDiskStorageMedia = hardDisk(3) */ removable = FALSE; /* hrDiskStorageRemovable = FALSE */ capacityKB = 0; /* hrDiskStorageCapacity (unknown) */ status = 1; /* hrDeviceStatus = unknown(1) */ descr = "Fixed Disk";/* hrDeviceDescr */
/* ==========================================================
| IOCTL_DISK_GET_DRIVE_GEOMETRY | | If we can get this, we get a better description and an | accurate capacity value. */ if (DeviceIoControl(hdrv, // device handle
// IoControlCode (op-code)
IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, // "input buffer"
0, // "input buffer size"
&geo_info, // "output buffer"
// "output buffer size"
sizeof(DISK_GEOMETRY), &bytes_out, // bytes written to geo_info
NULL // no Overlapped I/o
)) {
/*
| Compute capacity */ capacityKB = (ULONG) (geo_info.Cylinders.QuadPart * // 64 bit
(geo_info.TracksPerCylinder * // 32 bits
geo_info.SectorsPerTrack * geo_info.BytesPerSector)
) / 1024;
/* hrDeviceStatus = running(2) */ status = 2;
switch ( geo_info.MediaType ) {
case FixedMedia: break;
default: descr = "Unknown Media"; } }
/*
| Create a row in HrDevice Table and a corresponding row in | hrDiskStorage sub-table. */ if ((dv_row = Process_DS_Row (type_arc, /* hrDeviceType last arc */ access, /* hrDiskStorageAccess */ media, /* hrDiskStorageMedia */ removable, /* hrDiskStorageRemovable */ capacityKB,/* hrDiskStorageCapacity */ status, /* hrDeviceStatus */ descr /* hrDeviceDescr */ ) ) == NULL) {
/* Something blew */ CloseHandle(hdrv); SetErrorMode(nPrevErrorMode);/* Turn error suppression mode off */ return ( FALSE ); }
/*
| If it turns out this is the device from which the system was | booted, we need to return the index associated with the "dv_row" | row into "InitLoadDev_index" (defined in "HRDEVENT.C") to become | the value of "HrSystemInitialLoadDevice". | | See if the NT Device name associated with this "\\.\PHYSICALDRIVEx" | matches the value predicted for the system boot device. | | If we can get the NT Device name for "PHYSICALDRIVEn" . . . */ if (QueryDosDevice(&phys_name[4], pntdev, MAX_PATH) != 0 ) {
/* If it matches the predicted value for boot device . . . */ if ( strcmp(pntdev, ntdev) == 0) {
/* Record the index for the current "physicaldrive" */ InitLoadDev_index = dv_row->index; } } else { /*
| Fail gracefully so things will still work in | "ProcessPartition()" below. */ pntdev[0] = '\0'; }
/*
| Create a hrPartition table (in the HrDevice Table row just created | for the disk) to represent the partitions on this fixed disk. */ if ( ProcessPartitions( hdrv, dv_row, pntdev ) != TRUE ) { /* Something blew */ CloseHandle(hdrv); SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */ return ( FALSE ); }
/* Fold up shop on this disk */ CloseHandle(hdrv); } /* If we managed to "CreateFile()" the device */
else { /* Open failed... give up the scan */ SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */ break; }
SetErrorMode(nPrevErrorMode); /* Turn error suppression mode off */ } /* For each device */
/* Successful scan */ return ( TRUE ); }
/* Process_DS_Row - Process Information into HrDevice and hrDiskStorage Row */ /* Process_DS_Row - Process Information into HrDevice and hrDiskStorage Row */ /* Process_DS_Row - Process Information into HrDevice and hrDiskStorage Row */
static CACHEROW * Process_DS_Row ( ULONG type_arc, /* hrDeviceType last arc value */ ULONG access, /* hrDiskStorageAccess = readWrite(1) */ ULONG media, /* hrDiskStorageMedia = floppyDisk(4) */ ULONG removable, /* hrDiskStorageRemovable = TRUE */ ULONG capacityKB,/* hrDiskStorageCapacity, (kilobytes) */ ULONG status, /* hrDeviceStatus = unknown(1) */ CHAR *descr /* hrDeviceDescr string */ ) /*
| EXPLICIT INPUTS: | | "type_arc" is the number "n" to be used as the last arc in the | device-type OID: | | 1.3.6.1.2.1.25.3.1.n | | | | | | | * Identifying arc for type | | *-hrDeviceTypes (OIDs specifying device types) | *-hrDevice | | for devices created by this cache-population routine. | | The rest of the arguments outline above are used to fill in | attribute values in both the hrDevice table row and the corresponding | hrDiskStorage row. | | IMPLICIT INPUTS: | | The module-local head of the cache for the HrDiskStorage table, | "HrDiskStorage_cache". | | OUTPUTS: | | On Success: | Function returns pointer to row entry made to the hrDevice | table indicating that the both caches have been fully | populated with a new row. | | On any Failure: | Function returns NULL (indicating "not enough storage" or other | failure.). | | THE BIG PICTURE: | | | OTHER THINGS TO KNOW: | | This function contains common "row-insertion" code for the | Gen_Fixed_disks() and Gen_nonFixed_disks() functions. */ { CACHEROW *dv_row; /* Row created in hrDevice table */ CACHEROW *ds_row; /* Row created in hrDiskStorage table */
/*
|========================== | Create hrDevice Row entry. | | Note we're initializing this as though the Hidden Context is always | going to be a Cache pointer. It will be for fixed-disks (that have | Partition Tables), but for other disks the "NULL" signals "No Partition | Table". | | For fixed-disks, the NULL is overwritten later (in "ProcessPartitions()") | by a pointer to malloced storage containing an instance of CACHEHEAD | structure that carries the hrPartition Table for that fixed-disk). */ if ((dv_row = AddHrDeviceRow(type_arc, // DeviceType OID Last-Arc
descr, // Used as description
NULL, // Hidden Ctx (none)
CA_CACHE // Hidden Ctx type
)) == NULL ) { /* Something blew */ return ( NULL ); }
/* Re-Set hrDeviceStatus */ dv_row->attrib_list[HRDV_STATUS].attrib_type = CA_NUMBER; dv_row->attrib_list[HRDV_STATUS].u.unumber_value = status;
/*
|=============================== | Create hrDiskStorage Row entry | | Note: The index is not recorded IN the row, but the entry | is "indexed": by the hrDevice row index. This happens | in the AddTableRow() call below. */ if ((ds_row = CreateTableRow( HRDS_ATTRIB_COUNT ) ) == NULL) { return ( NULL ); // Out of memory
}
/*
| Set the attribute values for this row */
/* =========== hrDiskStorageAccess ==========*/ ds_row->attrib_list[HRDS_ACCESS].attrib_type = CA_NUMBER; ds_row->attrib_list[HRDS_ACCESS].u.unumber_value = access;
/* =========== hrDiskStorageAccess ==========*/ ds_row->attrib_list[HRDS_MEDIA].attrib_type = CA_NUMBER; ds_row->attrib_list[HRDS_MEDIA].u.unumber_value = media;
/* =========== hrDiskStorageRemovable ==========*/ ds_row->attrib_list[HRDS_REMOVABLE].attrib_type = CA_NUMBER; ds_row->attrib_list[HRDS_REMOVABLE].u.unumber_value = removable;
/* =========== hrDiskStorageCapacity ==========*/ ds_row->attrib_list[HRDS_CAPACITY].attrib_type = CA_NUMBER; ds_row->attrib_list[HRDS_CAPACITY].u.unumber_value = capacityKB;
/*
| Now insert the filled-in CACHEROW structure into the | cache-list for the hrDiskStorage Table.. | | Use the same index that was used to specify the row inserted | into the hrDevice table. */
if (AddTableRow(dv_row->attrib_list[HRDV_INDEX].u.unumber_value, /* Index */ ds_row, /* Row */ &hrDiskStorage_cache /* Cache */ ) == FALSE) {
DestroyTableRow(ds_row); return ( NULL ); /* Internal Logic Error! */ }
/* Processing complete */ return ( dv_row ); }
/* ProcessPartitions - Process Partition Information into HrDevice Row */ /* ProcessPartitions - Process Partition Information into HrDevice Row */ /* ProcessPartitions - Process Partition Information into HrDevice Row */
static BOOL ProcessPartitions( HANDLE hdrv, /* Fixed-Disk containing partitions */ CACHEROW *dv_row, /* Row in hrDevice table for disk */ CHAR *pntdev /* NT Device name for physical disk */ ) /*
| EXPLICIT INPUTS: | | "hdrv" - handle open to the fixed disk whose partitions are to be | enumerated. | | "dv_row" - the HrDevice row into which the new hrPartition Table | is to go. | | "pntdev" - NT Device Name for the physical disk we're dealing with. | We need this to infer the logical device name for any | active partition. | | IMPLICIT INPUTS: | | "HrFSTable_cache" - this gets scanned to allow "hrPartitionFSIndex" | to be filled in. | | OUTPUTS: | | On Success: | Function returns TRUE indicating that the Partition Information | for the given disk has been used to populate an hrPartition Table | instance. | | On any Failure: | Function returns NULL (indicating "not enough storage" or other | failure.). | | THE BIG PICTURE: | | This is the function that instantiates hrPartition tables. | | OTHER THINGS TO KNOW: | | Documentation at the top of the hrPartition Table file "HRPARTIT.C" | might be of interest. | | BUG: As of build 1515, (and indeed in earlier versions of NT) the | "PartitionNumber" returned in response to DeviceIoControl opcode | "IOCTL_DISK_GET_DRIVE_LAYOUT" comes back as garbage. Whatever | comes back is reported as the value of "hrPartitionID" (garbage or | not). However when trying to fetch the Volume Label, as part of a | workaround attempt, we use the index generated in the code below | in an attempt to approximate the proper Partition Number. */ { #define DL_SIZE 1024
CHAR dl_buf[DL_SIZE]; /* Drive-Layout info comes back here */ UINT i; /* Handy-Dandy loop index */ ULONG table_index=0; /* hrPartition Table row index counter */ DWORD bytes_out; /* Exactly how big "dl_buf" got filled */ DRIVE_LAYOUT_INFORMATION *dl; /* Drive-layout pointer */
/*
| See if we can grab the Drive's partition layout info. */ if (DeviceIoControl(hdrv, // device handle
IOCTL_DISK_GET_DRIVE_LAYOUT, // IoControlCode (op-code)
NULL, // "input buffer"
0, // "input buffer size"
dl_buf, // "output buffer"
DL_SIZE, // "output buffer size"
&bytes_out, // bytes written to part_info
NULL // no Overlapped I/o
)) {
CACHEHEAD *ch;
/*
| OK, there's presumed to be at least one partition: instantiate the | new partition table. | | Do this by creating its cache list-head structure. */ dv_row->attrib_list[HIDDEN_CTX].attrib_type = CA_CACHE; if ((dv_row->attrib_list[HIDDEN_CTX].u.cache = ch = (CACHEHEAD *) malloc( sizeof(CACHEHEAD) )) == NULL) { return ( FALSE ); }
/*
| Now initialize the contents properly. | (This should match what macro CACHEHEAD_INSTANCE does to a static | instance). */ ch->list_count = 0; ch->list = NULL;
#if defined(CACHE_DUMP)
ch->print_row = debug_print_hrpartition; #else
ch->print_row = NULL; #endif
/* Grab a dereferencable pointer to the Drive Layout info */ dl = (DRIVE_LAYOUT_INFORMATION *) dl_buf;
/* For every Partition "slot" returned . . . */ for (i = 0; i < dl->PartitionCount; i += 1) {
PARTITION_INFORMATION *p; /* Partition info thats going to go . . */ CACHEROW *row; /* . . .into this row in HrPartition */ CACHEROW *fs_row; /* Row ptr in HrFSEntry table */ ULONG last_arc; /* Last OID arc to use as FS-Type */
/* Grab a simple pointer to the next PARTITION_INFO to consider */ p = &(dl->PartitionEntry[i]);
/*
| Note: It may be that not all of the PartitionEntry elements are | "live". */ if (p->PartitionType == PARTITION_ENTRY_UNUSED) { continue; }
/*
|=============================== | Create hrPartition Row entry | | Note: This table is also "indexed" by the hrDevice row index */ if ((row = CreateTableRow( HRPT_ATTRIB_COUNT ) ) == NULL) { return ( FALSE ); // Out of memory
}
/* =========== hrPartitionIndex ==========*/ row->attrib_list[HRPT_INDEX].attrib_type = CA_NUMBER; row->attrib_list[HRPT_INDEX].u.unumber_value = (table_index += 1);
/* =========== hrPartitionLabel ==========*/ row->attrib_list[HRPT_LABEL].attrib_type = CA_STRING;
/*
| If there is an MS-DOS logical device letter assigned to this | partition. . . */ if ( p->RecognizedPartition ) {
/*
| Go get the label, copy it to malloc'ed storage and return it. | | NOTE: Due to what seems like a bug, we're passing in "i+1" here | rather than "p->PartitionNumber" (which seems to come | back as garbage). Clearly "i" is not a proper substitute | in the long run. See "OTHER THINGS TO KNOW" in the docs | above for this function. */ row->attrib_list[HRPT_LABEL].u.string_value = FindPartitionLabel(pntdev, (i+1)); } else { /* No label if no MS-DOS device */ row->attrib_list[HRPT_LABEL].u.string_value = NULL; }
/* =========== hrPartitionID ==========
| | In build 1515, this number is returned as garbage. See | "OTHER THINGS TO KNOW" above. */ row->attrib_list[HRPT_ID].attrib_type = CA_NUMBER; row->attrib_list[HRPT_ID].u.unumber_value = p->PartitionNumber;
/* =========== hrPartitionSize ==========*/ row->attrib_list[HRPT_SIZE].attrib_type = CA_NUMBER; row->attrib_list[HRPT_SIZE].u.unumber_value = p->PartitionLength.LowPart / 1024;
/* =========== hrPartitionFSIndex ==========*/ row->attrib_list[HRPT_FSINDEX].attrib_type = CA_NUMBER;
/* Assume no file system mounted (that we can find) */ row->attrib_list[HRPT_FSINDEX].u.unumber_value = 0;
/* Find the first Row (if any) in the hrFSTable */ if ((fs_row = FindNextTableRow(0, &hrFSTable_cache)) == NULL) {
/* No file systems listed at all.. we're done */ DestroyTableRow(row); continue; }
/*
| Convert the Partition-Type into the "last-arc" value we use | to indicate what kind of file-system it is. */ last_arc = PartitionTypeToLastArc( p->PartitionType );
do { /* Walk the hrFSEntry table */
/*
| If we found that the hrFSTable entry "fs_row" specifies a | file-system TYPE (by arc number) that matches what the current | partition's type number translates to ... we're done. */ if (fs_row->attrib_list[HRFS_TYPE].u.unumber_value == last_arc) { row->attrib_list[HRPT_FSINDEX].u.unumber_value = fs_row->index; break; }
/* Step to the next row */ fs_row = GetNextTableRow(fs_row); } while (fs_row != NULL);
/*
|=============================== |Now add the row to the table */ if (AddTableRow(row->attrib_list[HRPT_INDEX].u.unumber_value,/* Index */ row, /* Row */ ch /* Cache */ ) == FALSE) {
DestroyTableRow(row); return ( FALSE ); /* Internal Logic Error! */ }
} /* For each partition */
} /* If DeviceIoControl succeeded */
/* Partition Table complete */ return ( TRUE ) ; }
/* FindPartitionLabel - Find MS-DOS Device Label for a Fixed-Disk Partition */ /* FindPartitionLabel - Find MS-DOS Device Label for a Fixed-Disk Partition */ /* FindPartitionLabel - Find MS-DOS Device Label for a Fixed-Disk Partition */
static PCHAR FindPartitionLabel( CHAR *pntdev, /* NT Device name for physical disk */ UINT part_id /* Partition Number (1-origined) */ ) /*
| EXPLICIT INPUTS: | | "pntdev" - the NT Device Name (e.g. "\Device\Harddisk0\Partition0" | for the PHYSICAL device we're working on). | | "part_id" - One-origined Partition number for which we hope to find | an MS-DOS Volume Label. | | IMPLICIT INPUTS: | | None. | | OUTPUTS: | | On Success: | Function returns a pointer to malloc'ed storage containing the | MS-DOS Device Volume label (as returned by "GetVolumeInformation()"). | | On any Failure: | Function returns NULL (indicating "some kind of failure"). | | THE BIG PICTURE: | | This "helper" function attempts to map an NT Device Name and a | one-origined Partition Number into a Volume Label for return as | the value of "hrPartitionLabel". | | OTHER THINGS TO KNOW: | | The algorithm is based on studying the output from "QueryDosDevices()" | and blithely assuming that we can "back-map" the string | "\Device\HarddiskX\PartitionY" for any Partition "Y" to the associated | MS-DOS Device. There is precious little documentation that sez we can, | but we try. | | Here's the approach: | | * Using the NT Device Name for the "PHYSICALDRIVEn", we scrape the | "\Partition0" off the end of the name and replace it with "\PartitionY" | where "Y" is the Partition number passed as input to this function. | This is the "Generated Partition Name". | | ("PHYSICALDRIVE" NT Device Names all seem to have "\Partition0" as | the terminating part of their name, and since the Win32 docs say that | Partition Numbers are "1-origined", this seems like a safe approach.) | | * We generate a list of all the MS-DOS device names (using QueryDosDevices). | | * We take each MS-DOS Device name and ask for it's current underlying | NT Device name mapping. | | + If the first name mapping for any MS-DOS Device matches our | "Generated Partition Name", then the MS-DOS Device name is submitted | to "GetVolumeInformation()" and the Volume Label returned is used as | the "Partition Label". */ { #define BIG_BUFF 1024
CHAR gen_part_name[MAX_PATH+32]; /* "pntdev" is at most MAX_PATH+2 */ CHAR *partition; /* Where "\Partition0" starts */ CHAR MSDOS_devices[BIG_BUFF]; /* List of MS-DOS device names */ CHAR NT_device[BIG_BUFF]; /* Mapping of NT device names */ CHAR *devname; /* Index for MSDOS_devices */
/* Copy the NT Device Name for the Physical Drive */ strcpy(gen_part_name, pntdev);
/* Obtain a pointer to the beginning of "\Partition0" in this string */ if ((partition = strstr(gen_part_name, "\\Partition")) != NULL) {
/*
| Replace "\Partition0" with "\PartitionY" where "Y" is the supplied | partition number: We've got the "Generated Partition Name". */ sprintf(partition, "\\Partition%d", part_id);
/*
| Now ask for a list of MS-DOS Device Names */ if ( QueryDosDevice(NULL, MSDOS_devices, BIG_BUFF) != 0) {
/*
| Swing down the list of MS-DOS device names and get the NT Device | name mappings. */ for (devname = MSDOS_devices; *devname != '\0'; devname += (strlen(devname)+1)) {
/* Obtain the mappings for device "devname" */ if (QueryDosDevice(devname, NT_device, BIG_BUFF) == 0) continue;
/* If the first mapping matches the Generated Partition Name */ if (strcmp(gen_part_name, NT_device) == 0) {
#define VOL_LABEL_SIZE 128
CHAR MSDOS_root[64+1]; /* Root Path Name */ CHAR v_label[VOL_LABEL_SIZE]; /* Volume Label */ CHAR *ret_label; /* --> Malloced storage */ DWORD comp_len; /* Filename length */ DWORD flags;
/*
| We're obliged to add a root-directory "\" to the MS-DOS | device name. */ MSDOS_root[64] = 0; // ensures null terminated string
_snprintf(MSDOS_root, 64, "%s\\", devname);
/* Fetch the Volume Information for the MS-DOS Device */ if (GetVolumeInformation( MSDOS_root, // MS-DOS root name
v_label, // Vol. Label buf
VOL_LABEL_SIZE, // vol. label size
NULL, // Serial Number
&comp_len, // FileName length
&flags, // Flags
NULL, // File System name
0 // Name buff. len
) != 0) { /*
| Allocate storage to hold a returnable copy */ if ( (ret_label = (CHAR *) malloc(strlen(v_label) + 1)) != NULL) {
/* Copy the label to malloced storage */ strcpy(ret_label, v_label);
return (ret_label); } else { /* Out of storage */ return (NULL); } } else { /* "GetVolumeInformation" failed on MSDOS name */ return (NULL); } } } } }
return (NULL); /* Other Failure */ }
#if defined(CACHE_DUMP)
/* debug_print_hrdiskstorage - Prints a Row from HrDiskStorage sub-table */ /* debug_print_hrdiskstorage - Prints a Row from HrDiskStorage sub-table */ /* debug_print_hrdiskstorage - Prints a Row from HrDiskStorage sub-table */
static void debug_print_hrdiskstorage( CACHEROW *row /* Row in hrDiskStorage table */ ) /*
| EXPLICIT INPUTS: | | "row" - points to the row to be dumped, if NULL, the function | merely prints a suitable title. | | IMPLICIT INPUTS: | | - Symbols used to reference the attributes in the row entry. | - File handle defined by OFILE, presumed to be open. | | OUTPUTS: | | On Success: | Function prints a dump of the row in ASCII for debugging purposes | on file handle OFILE. | | THE BIG PICTURE: | | Debugging only. | | OTHER THINGS TO KNOW: */ {
if (row == NULL) { fprintf(OFILE, "=========================\n"); fprintf(OFILE, "hrDiskStorage Table Cache\n"); fprintf(OFILE, "=========================\n"); return; }
fprintf(OFILE, "hrDiskStorageAccess. . . . %d ", row->attrib_list[HRDS_ACCESS].u.unumber_value); switch (row->attrib_list[HRDS_ACCESS].u.unumber_value) { case 1: fprintf(OFILE, "(readWrite)\n"); break; case 2: fprintf(OFILE, "(readOnly)\n"); break; default:fprintf(OFILE, "(???)\n"); break; }
fprintf(OFILE, "hrDiskStorageMedia . . . . %d ", row->attrib_list[HRDS_MEDIA].u.unumber_value); switch (row->attrib_list[HRDS_MEDIA].u.unumber_value) { case 1: fprintf(OFILE, "(Other)\n"); break; case 2: fprintf(OFILE, "(Unknown)\n"); break; case 3: fprintf(OFILE, "(hardDisk)\n"); break; case 4: fprintf(OFILE, "(floppyDisk)\n"); break; case 5: fprintf(OFILE, "(opticalDiskROM)\n"); break; case 6: fprintf(OFILE, "(opticalDiskWORM)\n"); break; case 7: fprintf(OFILE, "(opticalDiskRW)\n"); break; case 8: fprintf(OFILE, "(ramDisk)\n"); break; default:fprintf(OFILE, "(???)\n"); break; }
fprintf(OFILE, "hrDiskStorageRemovable . . %d ", row->attrib_list[HRDS_REMOVABLE].u.unumber_value); switch (row->attrib_list[HRDS_REMOVABLE].u.unumber_value) { case 0: fprintf(OFILE, "(FALSE)\n"); break; case 1: fprintf(OFILE, "(TRUE)\n"); break; default: fprintf(OFILE, "(???)\n"); break; }
fprintf(OFILE, "hrDiskStorageCapacity. . . %d (KBytes)\n", row->attrib_list[HRDS_CAPACITY].u.unumber_value);
}
/* debug_print_hrpartition - Prints a Row from HrPartition sub-table */ /* debug_print_hrpartition - Prints a Row from HrPartition sub-table */ /* debug_print_hrpartition - Prints a Row from HrPartition sub-table */
static void debug_print_hrpartition( CACHEROW *row /* Row in hrPartition table */ ) /*
| EXPLICIT INPUTS: | | "row" - points to the row to be dumped, if NULL, the function | merely prints a suitable title. | | IMPLICIT INPUTS: | | - Symbols used to reference the attributes in the row entry. | - File handle defined by OFILE, presumed to be open. | | OUTPUTS: | | On Success: | Function prints a dump of the row in ASCII for debugging purposes | on file handle OFILE. | | THE BIG PICTURE: | | Debugging only. | | OTHER THINGS TO KNOW: */ {
if (row == NULL) { fprintf(OFILE, " =======================\n"); fprintf(OFILE, " hrPartition Table Cache\n"); fprintf(OFILE, " =======================\n"); return; }
fprintf(OFILE, " hrPartitionIndex . . . . . %d\n", row->attrib_list[HRPT_INDEX].u.unumber_value);
fprintf(OFILE, " hrPartitionLabel . . . . . \"%s\"\n", row->attrib_list[HRPT_LABEL].u.string_value);
fprintf(OFILE, " hrPartitionID. . . . . . . 0x%x\n", row->attrib_list[HRPT_ID].u.unumber_value);
fprintf(OFILE, " hrPartitionSize. . . . . . %d\n", row->attrib_list[HRPT_SIZE].u.unumber_value);
fprintf(OFILE, " hrPartitionFSIndex . . . . %d\n", row->attrib_list[HRPT_FSINDEX].u.unumber_value); } #endif
|