Windows-Server-2003/net/snmp/subagent/hostmib/hrdiskst.c

2066 lines
71 KiB
C
Raw Normal View History

2024-08-04 01:28:15 +02:00
/*
* 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