Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1973 lines
44 KiB

/*++
Copyright (c) 1993 Microsoft Corporation
Module Name:
Drives.c
Abstract:
This module contains support for displaying the Drives dialog.
Author:
David J. Gilman (davegi) 19-Mar-1993
Gregg R. Acheson (GreggA) 7-Sep-1993
Environment:
User Mode
--*/
// For LargeInteger routines
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include "dialogs.h"
#include "dlgprint.h"
#include "drives.h"
#include "msg.h"
#include "strtab.h"
#include "strresid.h"
#include "winmsd.h"
#include <malloc.h>
#include <string.h>
#include <tchar.h>
//
// Macro to support freeing of NULL pointers.
//
#define Free( p ) \
{ if(p) free(p); }
//
// Object used to pass information around about a logical drive.
//
typedef
struct
_DRIVE_INFO {
DECLARE_SIGNATURE
TCHAR DriveLetter[ 3 ];
UINT DriveType;
TCHAR RemoteNameBuffer[ MAX_PATH ];
DWORD SectorsPerCluster;
DWORD BytesPerSector;
DWORD FreeClusters;
DWORD Clusters;
TCHAR VolumeNameBuffer[ MAX_PATH ];
DWORD VolumeSerialNumber;
DWORD MaximumComponentLength;
DWORD FileSystemFlags;
TCHAR FileSystemNameBuffer[ MAX_PATH ];
BOOL ValidDetails;
} DRIVE_INFO, *LPDRIVE_INFO;
//
// Internal function prototypes.
//
LPDRIVE_INFO
CreateDriveInfoStructure(
void
);
BOOL
FreeDriveInfoStructures(
HWND hWnd
);
BOOL
GetDriveInfo(
IN LPDRIVE_INFO di
);
HICON
GetIcon (int nImage,
int nImageSize
);
BOOL
DestroyDriveInfo(
IN LPDRIVE_INFO DriveInfo
);
BOOL
GeneralDriveDetailsDlgProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
);
BOOL
FilesystemDetailsDlgProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
);
BOOL
InitializeDrivesTab(
IN HWND hWnd
);
HTREEITEM
AddTreeViewItem(
HWND hwndTV,
LPTV_INSERTSTRUCT lpis
);
HTREEITEM
FindOrAddTreeViewItem ( HWND hWndTV,
LPTV_INSERTSTRUCT lpis
);
BOOL
DisplaySCSIDevices( HWND hWnd,
HWND hTreeView
);
BOOL
FillTreeViewWithDrives( IN HWND hWnd,
IN HWND hTreeView,
IN int nStyle );
BOOL
DisplayDrivePropertySheet(
HWND hWnd,
LPDRIVE_INFO di
);
int
GetDriveImage (
int nDriveType
);
BOOL
GetDriveInfo(
LPDRIVE_INFO di
)
/*++
Routine Description:
Fills in a given DRIVE_INFO object based on the DriveLetter member.
Arguments:
Required:
di.DriveLetter - the root directory of the drive (e.g. c:\)
Return Value:
LPDRIVE_INFO - Returns a pointer to a DRIVE_INFO object with information
about the supplied drive completed.
--*/
{
UINT OldErrorMode;
DWORD SizeOfRemoteNameBuffer;
HCURSOR hSaveCursor;
hSaveCursor = SetCursor ( LoadCursor ( NULL, IDC_WAIT ) );
DbgHandleAssert( hSaveCursor );
//
// Get the type of this drive.
//
di->DriveType = GetDriveType( di->DriveLetter );
//
// If this is a network drive, get the share its connected to.
//
if( di->DriveType == DRIVE_REMOTE ) {
DWORD WNetError;
//
// WinNet APIs want the drive name w/o a trailing slash so use the
// remove it temporarily
//
di->DriveLetter[ 2 ] = TEXT( '\0' );
SizeOfRemoteNameBuffer = sizeof( di->RemoteNameBuffer );
WNetError = WNetGetConnection(
di->DriveLetter,
di->RemoteNameBuffer,
&SizeOfRemoteNameBuffer
);
di->DriveLetter[ 2 ] = TEXT( '\\' );
DbgAssert( ( WNetError == NO_ERROR )
|| ( WNetError == ERROR_VC_DISCONNECTED ));
}
//
// Disable pop-ups (especially if there is no media in the
// removable drives.)
//
OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );
//
// Get the space statistics for this drive.
//
di->ValidDetails = GetDiskFreeSpace(
di->DriveLetter,
&di->SectorsPerCluster,
&di->BytesPerSector,
&di->FreeClusters,
&di->Clusters
);
if( di->ValidDetails == FALSE ) {
//
// Reenable pop-ups.
//
SetErrorMode( OldErrorMode );
SetCursor ( hSaveCursor );
return FALSE;
}
//
// Get information about the volume for this drive.
//
di->ValidDetails = GetVolumeInformation(
di->DriveLetter,
di->VolumeNameBuffer,
sizeof( di->VolumeNameBuffer ),
&di->VolumeSerialNumber,
&di->MaximumComponentLength,
&di->FileSystemFlags,
di->FileSystemNameBuffer,
sizeof( di->FileSystemNameBuffer )
);
SetErrorMode (OldErrorMode);
SetCursor ( hSaveCursor );
return di->ValidDetails;
}
LPDRIVE_INFO
CreateDriveInfoStructure(
void
)
/*++
Routine Description:
Create a DRIVE_INFO object for the supplied drive.
Arguments:
None
Return Value:
LPDRIVE_INFO - Allocates and returns a pointer to a DRIVE_INFO object
--*/
{
LPDRIVE_INFO DriveInfo;
//
// Allocate a DRIVE_INFO object.
//
DriveInfo = AllocateObject( DRIVE_INFO, 1 );
DbgPointerAssert( DriveInfo );
if( DriveInfo == NULL ) {
return NULL;
}
//
// Initialize buffers with empty strings.
//
ZeroMemory( DriveInfo, sizeof(DRIVE_INFO) );
//
// Set the signature
//
SetSignature( DriveInfo );
//
// Mark Structure as invalid since it is not filled out yet.
//
DriveInfo->ValidDetails = FALSE;
return DriveInfo;
}
BOOL
FreeDriveInfoStructures(
HWND hWnd
)
/*++
Routine Description:
Walks the tree in the tree view window, freeing DRIVE_INFO objects.
Arguments:
hWnd - tab window handle
Return Value:
BOOL true if successful
--*/
{
HWND hWndTree = GetDlgItem(hWnd, IDC_TV_DRIVE_LIST);
TV_ITEM tvi;
TV_ITEM tviChild;
LPDRIVE_INFO lpdi;
tvi.mask = tviChild.mask = TVIF_HANDLE | TVIF_PARAM;
tvi.hItem = TreeView_GetRoot( hWndTree );
tvi.hItem = TreeView_GetChild( hWndTree, tvi.hItem);
//
// Walk the TreeView, freeing memory associated with the tvis.item.lParam
//
while( tvi.hItem ){
if ( TreeView_GetItem(hWndTree, &tvi) ){
//
// If we have found a pointer to a DRIVE_INFO, free it
//
lpdi = (LPDRIVE_INFO) tvi.lParam;
if( ( lpdi != NULL ) && ( CheckSignature( lpdi ) ) ){
FreeObject( lpdi );
}
}
//
// Check the children as well
//
tviChild.hItem = TreeView_GetChild( hWndTree, tvi.hItem);
while( tviChild.hItem ) {
if ( TreeView_GetItem(hWndTree, &tviChild) ){
//
// If we have found a pointer to a DRIVE_INFO, free it
//
lpdi = (LPDRIVE_INFO) tviChild.lParam;
if( ( lpdi != NULL ) && ( CheckSignature( lpdi ) ) ){
FreeObject( lpdi );
}
}
tviChild.hItem = TreeView_GetNextSibling(hWndTree, tviChild.hItem);
}
//
// Get next tree item
//
tvi.hItem = TreeView_GetNextSibling(hWndTree, tvi.hItem);
}
return(TRUE);
}
BOOL
DestroyDriveInfo(
IN LPDRIVE_INFO DriveInfo
)
/*++
Routine Description:
Destroys a DRIVE_INFO object by freeing it, only after making sure it is valid
Arguments:
LPDRIVE_INFO - Supplies a pointer to a DRIVE_INFO object.
Return Value:
BOOL - Returns TRUE if the DRIVE_OBJECT is succesfully destroyed
--*/
{
BOOL Success;
DbgPointerAssert( DriveInfo );
DbgAssert( CheckSignature( DriveInfo ));
if(( DriveInfo == NULL ) || ( !CheckSignature( DriveInfo ))) {
return FALSE;
}
//
// Delete the DRIVE_INFO object itself.
//
Success = FreeObject( DriveInfo );
DbgAssert( Success );
return TRUE;
}
BOOL
DrivesTabProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
DrivesTabProc processes messages when the Drives Tab is currently selected.
Arguments:
Standard WINPROC entry.
Return Value:
BOOL - Depending on input message and processing options.
--*/
{
BOOL Success;
HWND hTreeView;
switch( message ) {
case WM_INITDIALOG:
InitializeDrivesTab(hWnd);
break;
case WM_DESTROY:
FreeDriveInfoStructures( hWnd );
break;
case WM_NOTIFY:
{
switch( ((LPNMHDR)lParam)->code ){
case TVN_GETDISPINFO:
{
// TVN_GETDISPINFO is sent my I_IMAGECALLBACK to determine
// folder state
if ((((TV_DISPINFO *)lParam)->item.state) & TVIS_EXPANDED)
{
((TV_DISPINFO *)lParam)->item.iImage =
((TV_DISPINFO *)lParam)->item.iSelectedImage = IMAGE_FOLDER_OPEN;
}
else
{
((TV_DISPINFO *)lParam)->item.iImage =
((TV_DISPINFO *)lParam)->item.iSelectedImage = IMAGE_FOLDER_CLOSED;
}
break;
}
case TVN_SELCHANGED:
{
//
// Enable or disable the Properties button, depending on whether
// this item has any children--only allow properties for items
// with no children
//
TV_ITEM tvi;
tvi = ((LPNM_TREEVIEW)lParam)->itemNew;
tvi.mask = TVIF_CHILDREN;
TreeView_GetItem (GetDlgItem(hWnd, IDC_TV_DRIVE_LIST), &tvi);
Success = EnableControl(
GetParent(hWnd),
IDC_PUSH_PROPERTIES,
(tvi.cChildren == 0) ? TRUE : FALSE
);
break;
}
case NM_DBLCLK:
{
// pretend we have clicked the Property button
PostMessage(
GetParent(hWnd),
WM_COMMAND,
MAKEWPARAM( IDC_PUSH_PROPERTIES, BN_CLICKED ),
0
);
break;
}
}
}
case WM_COMMAND:
{
LPDRIVE_INFO DriveInfo;
switch( LOWORD( wParam )) {
case IDC_PUSH_DRIVE_TYPE:
case IDC_PUSH_DRIVE_LETTER:
case IDC_PUSH_REFRESH:
FreeDriveInfoStructures( hWnd );
FillTreeViewWithDrives( hWnd,
GetDlgItem(hWnd, IDC_TV_DRIVE_LIST),
LOWORD( wParam ) );
EnableControl( GetParent(hWnd),
IDC_PUSH_PROPERTIES,
FALSE);
break;
case IDC_PUSH_SCSI_CHAIN:
DisplaySCSIDevices( hWnd, GetDlgItem(hWnd, IDC_TV_DRIVE_LIST) );
break;
case IDC_PUSH_PHYSICAL_DISKS:
//WORKITEM
break;
case IDC_PUSH_PROPERTIES:
if (HIWORD( wParam) == BN_CLICKED) {
TV_ITEM tvi;
TCHAR szBuffer[512];
tvi.mask = TVIF_TEXT | TVIF_CHILDREN | TVIF_PARAM;
tvi.hItem = TreeView_GetSelection( GetDlgItem(hWnd, IDC_TV_DRIVE_LIST) );
tvi.pszText = szBuffer;
tvi.cchTextMax = sizeof(szBuffer);
TreeView_GetItem (GetDlgItem(hWnd, IDC_TV_DRIVE_LIST), &tvi);
if ( !tvi.cChildren )
{
if ( GetDriveInfo( (LPDRIVE_INFO) tvi.lParam ) )
{
DisplayDrivePropertySheet( hWnd, (LPDRIVE_INFO) tvi.lParam);
}
else
{
TCHAR Buffer[256];
wsprintf( Buffer, (LPCTSTR) GetString( IDS_APPLICATION_FULLNAME ));
MessageBox ( hWnd,
(LPCTSTR) GetString( IDS_DRIVE_PROPERTY_NOT_AVAILABLE ),
Buffer,
MB_ICONSTOP | MB_OK );
}
}
break;
}
}
break;
}
}
return(FALSE);
}
BOOL
GeneralDriveDetailsDlgProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
GeneralDriveDetailsDlgProc supports the display of the General information
tab of the Drive Details Property Dialog.
Arguments:
Standard DLGPROC entry.
Return Value:
BOOL - Depending on input message and processing options.
--*/
{
BOOL Success;
LARGE_INTEGER LargeInt;
HANDLE hIcon;
switch( message ) {
case WM_INITDIALOG:
{
int i;
TCHAR szBuffer[ MAX_PATH ];
LPDRIVE_INFO DriveInfo;
//
// Retrieve and validate the DRIVE_INFO object.
//
DriveInfo = (LPDRIVE_INFO) ( ( LPPROPSHEETPAGE ) lParam)->lParam ;
DbgPointerAssert( DriveInfo );
DbgAssert( CheckSignature( DriveInfo ));
DbgAssert( DriveInfo->ValidDetails );
if( ( DriveInfo == NULL )
|| ( ! CheckSignature( DriveInfo ))
|| ( ! DriveInfo->ValidDetails )) {
EndDialog( hWnd, 0 );
return FALSE;
}
//
// If the drive is remote, display its connection name in the title.
//
if( DriveInfo->DriveType == DRIVE_REMOTE ) {
SetDlgItemText(
hWnd,
IDC_DRIVE_NAME,
DriveInfo->RemoteNameBuffer
);
}
//
// Set the appropriate Icon
//
hIcon = GetIcon (GetDriveImage(DriveInfo->DriveType), 32);
if ( hIcon )
{
hIcon = (HICON)SendDlgItemMessage(hWnd, IDC_DRIVE_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
if (hIcon)
DestroyIcon(hIcon);
}
//
// Fill in drive label
//
SetDlgItemText(
hWnd,
IDC_DRIVE_LABEL,
DriveInfo->VolumeNameBuffer
);
//
// Fill in serial number
//
wsprintf( szBuffer, L"%X - %X",
HIWORD( DriveInfo->VolumeSerialNumber ),
LOWORD( DriveInfo->VolumeSerialNumber ));
SetDlgItemText(
hWnd,
IDC_DRIVE_SERIAL_NUMBER,
szBuffer
);
//
// Display the space statistics.
//
SetDlgItemText(
hWnd,
IDC_SECTORS_PER_CLUSTER,
FormatBigInteger(
DriveInfo->SectorsPerCluster,
FALSE
)
);
SetDlgItemText(
hWnd,
IDC_BYTES_PER_SECTOR,
FormatBigInteger(
DriveInfo->BytesPerSector,
FALSE
)
);
SetDlgItemText(
hWnd,
IDC_FREE_CLUSTERS,
FormatBigInteger(
DriveInfo->FreeClusters,
FALSE
)
);
SetDlgItemText(
hWnd,
IDC_USED_CLUSTERS,
FormatBigInteger(
DriveInfo->Clusters
- DriveInfo->FreeClusters,
FALSE
)
);
SetDlgItemText(
hWnd,
IDC_TOTAL_CLUSTERS,
FormatBigInteger(
DriveInfo->Clusters,
FALSE
)
);
//
// Use LargeInteger routines for large drives ( > 4G )
//
LargeInt.QuadPart = UInt32x32To64(
DriveInfo->FreeClusters,
(DriveInfo->SectorsPerCluster * DriveInfo->BytesPerSector)
);
SetDlgItemText(
hWnd,
IDC_FREE_BYTES,
FormatLargeInteger(
&LargeInt,
FALSE ) );
LargeInt.QuadPart = UInt32x32To64(
(DriveInfo->Clusters - DriveInfo->FreeClusters),
(DriveInfo->SectorsPerCluster * DriveInfo->BytesPerSector)
);
SetDlgItemText(
hWnd,
IDC_USED_BYTES,
FormatLargeInteger(
&LargeInt,
FALSE ) );
LargeInt.QuadPart = UInt32x32To64(
DriveInfo->Clusters,
(DriveInfo->SectorsPerCluster * DriveInfo->BytesPerSector)
);
SetDlgItemText(
hWnd,
IDC_TOTAL_BYTES,
FormatLargeInteger(
&LargeInt,
FALSE ) );
return TRUE;
}
case WM_COMMAND:
{
switch( LOWORD( wParam )) {
case IDOK:
case IDCANCEL:
EndDialog( hWnd, 1 );
return TRUE;
}
break;
}
}
return( FALSE );
}
BOOL
FilesystemDetailsDlgProc(
IN HWND hWnd,
IN UINT message,
IN WPARAM wParam,
IN LPARAM lParam
)
/*++
Routine Description:
DriveDetailsDlgProc supports the display of the drives detail dialog which
displays information about a logical drive, including, label, serial number,
file system information and a host of space statistics.
Arguments:
Standard DLGPROC entry.
Return Value:
BOOL - Depending on input message and processing options.
--*/
{
BOOL Success;
HICON hIcon;
switch( message ) {
case WM_INITDIALOG:
{
int i;
TCHAR szBuffer[ MAX_PATH ];
LPDRIVE_INFO DriveInfo;
VALUE_ID_MAP FSFlags[ ] = {
FS_CASE_IS_PRESERVED, IDC_TEXT_CASE_IS_PRESERVED,
FS_CASE_SENSITIVE, IDC_TEXT_CASE_SENSITIVE,
FS_UNICODE_STORED_ON_DISK, IDC_TEXT_UNICODE_STORED_ON_DISK,
FS_FILE_COMPRESSION, IDC_TEXT_FILE_COMPRESSION,
FS_PERSISTENT_ACLS, IDC_TEXT_PERSISTENT_ACLS
};
//
// Retrieve and validate the DRIVE_INFO object.
//
DriveInfo = (LPDRIVE_INFO) ( ( LPPROPSHEETPAGE ) lParam)->lParam ;
DbgPointerAssert( DriveInfo );
DbgAssert( CheckSignature( DriveInfo ));
DbgAssert( DriveInfo->ValidDetails );
if( ( DriveInfo == NULL )
|| ( ! CheckSignature( DriveInfo ))
|| ( ! DriveInfo->ValidDetails )) {
EndDialog( hWnd, 0 );
return FALSE;
}
//
// If the drive is remote, display its connection name in the title.
//
if( DriveInfo->DriveType == DRIVE_REMOTE ) {
SetDlgItemText(
hWnd,
IDC_DRIVE_NAME,
DriveInfo->RemoteNameBuffer
);
}
//
// Set the appropriate Icon
//
hIcon = GetIcon (GetDriveImage(DriveInfo->DriveType), 32);
if (hIcon)
{
hIcon = (HICON)SendDlgItemMessage(hWnd, IDC_DRIVE_ICON, STM_SETICON, (WPARAM)hIcon, 0L);
if (hIcon)
DestroyIcon(hIcon);
}
//
// Fill in drive label
//
SetDlgItemText(
hWnd,
IDC_DRIVE_LABEL,
DriveInfo->VolumeNameBuffer
);
//
// Fill in serial number
//
wsprintf( szBuffer, L"%X - %X",
HIWORD( DriveInfo->VolumeSerialNumber ),
LOWORD( DriveInfo->VolumeSerialNumber ));
SetDlgItemText(
hWnd,
IDC_DRIVE_SERIAL_NUMBER,
szBuffer
);
//
// Display the file system information.
//
SetDlgItemText(
hWnd,
IDC_FILESYSTEM_NAME,
DriveInfo->FileSystemNameBuffer
);
SetDlgItemText(
hWnd,
IDC_EDIT_FS_MAX_COMPONENT,
FormatBigInteger(
DriveInfo->MaximumComponentLength,
FALSE
)
);
for( i = 0; i < NumberOfEntries( FSFlags ); i++ ) {
Success = EnableControl(
hWnd,
FSFlags[ i ].Id,
DriveInfo->FileSystemFlags
& FSFlags[ i ].Value
);
DbgAssert( Success );
}
return TRUE;
}
}
return FALSE;
}
BOOL
BuildDrivesReport(
IN HWND hWnd,
IN UINT iDetailLevel
)
/*++
Routine Description:
Formats and adds DrivesData to the report buffer.
Arguments:
hWnd - Main window handle
iDetailLevel - summary or complete details?
Return Value:
BOOL - TRUE if report is build successfully, FALSE otherwise.
--*/
{
TCHAR LogicalDrives[ MAX_PATH ],
OutputBuffer[MAX_PATH],
szBuffer[MAX_PATH],
szBuffer2[MAX_PATH];
LPTSTR Drive;
DWORD Chars;
BOOL Success;
UINT OldErrorMode;
DRIVE_INFO di;
LARGE_INTEGER LargeInt;
TCHAR szTotalBytes [ 64 ],
szFreeBytes [ 64 ];
if(_fIsRemote){
return(TRUE);
}
AddLineToReport( 1, RFO_SKIPLINE, NULL, NULL );
AddLineToReport( 0, RFO_SINGLELINE, (LPTSTR) GetString( IDS_DRIVES_REPORT ), NULL );
AddLineToReport( 0, RFO_SEPARATOR, NULL, NULL );
//
// Retrieve the logical drive strings from the system.
//
Chars = GetLogicalDriveStrings(
sizeof( LogicalDrives ),
LogicalDrives
);
DbgAssert(( Chars != 0 ) && ( Chars <= sizeof( LogicalDrives )));
Drive = LogicalDrives;
//
// Disable pop-ups (especially if there is no media in the
// removable drives.)
//
OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );
while( *Drive ) {
TCHAR VolumeNameBuffer[512];
TCHAR FileSystemNameBuffer[512];
TCHAR DriveLetter[3];
TCHAR szKB[64];
DriveLetter[ 0 ] = Drive [ 0 ];
DriveLetter[ 1 ] = Drive [ 1 ];
DriveLetter[ 2 ] = TEXT( '\\');
ZeroMemory( &di, sizeof(DRIVE_INFO));
//
// Skip floppies
//
if ((Drive[0] == 'A') || (Drive[0] == 'B'))
{
Drive += _tcslen( Drive ) + 1;
continue;
}
//
// GetDrive info
//
_tcsncpy( di.DriveLetter, Drive, 4 );
GetDriveInfo( &di );
//
// Skip empty drives
//
if (di.Clusters == 0)
{
Drive += _tcslen( Drive ) + 1;
continue;
}
//
// skip unknown types
//
if (( di.DriveType < DRIVE_REMOVABLE) ||
( di.DriveType > DRIVE_CDROM )){
Drive += _tcslen( Drive ) + 1;
continue;
}
//
// Display summary information
//
lstrcpy(szBuffer, GetString( IDS_DRV_BASE + di.DriveType ) );
lstrcpy(szBuffer2, GetString( IDS_TOTAL_MB ) );
//
// Calculate the total and free bytes (Use LargeInteger routines for large drives ( > 4G )
//
LargeInt.QuadPart = UInt32x32To64(
di.FreeClusters,
(di.SectorsPerCluster * di.BytesPerSector)
);
LargeInt.QuadPart = Int64ShraMod32(LargeInt.QuadPart, 10);
lstrcpy( szFreeBytes, FormatLargeInteger( &LargeInt, FALSE ));
LargeInt.QuadPart = UInt32x32To64(
di.Clusters,
(di.SectorsPerCluster * di.BytesPerSector)
);
LargeInt.QuadPart = Int64ShraMod32(LargeInt.QuadPart, 10);
lstrcpy( szTotalBytes, FormatLargeInteger( &LargeInt, FALSE ));
lstrcpy( szKB, GetString( IDS_KB ) );
if (di.DriveType == DRIVE_REMOTE) {
wsprintf(OutputBuffer, L"%.2s (%s - %s) %s %s %s %s %s, %s %s %s",
di.DriveLetter,
szBuffer,
di.FileSystemNameBuffer,
di.RemoteNameBuffer,
di.VolumeNameBuffer,
szBuffer2,
szTotalBytes,
szKB,
GetString( IDS_FREE_MB ),
szFreeBytes,
szKB);
AddLineToReport(0,RFO_SINGLELINE,OutputBuffer,NULL);
} else {
wsprintf(OutputBuffer, L"%s (%s - %s) %s %s %s %s, %s %s %s",
di.DriveLetter,
szBuffer,
di.FileSystemNameBuffer,
di.VolumeNameBuffer,
szBuffer2,
szTotalBytes,
szKB,
GetString( IDS_FREE_MB ),
szFreeBytes,
szKB);
AddLineToReport(0,RFO_SINGLELINE,OutputBuffer,NULL);
}
//
// If we are making a detailed report, display additional info
//
if (iDetailLevel == IDC_COMPLETE_REPORT) {
wsprintf( szBuffer, L"%X - %X",
HIWORD( di.VolumeSerialNumber ),
LOWORD( di.VolumeSerialNumber ));
AddLineToReport( SINGLE_INDENT,
RFO_RPTLINE,
(LPTSTR) GetString( IDS_DRIVE_SERIAL_NUM ),
szBuffer );
wsprintf(szBuffer, L"%d", di.BytesPerSector);
AddLineToReport( SINGLE_INDENT,
RFO_RPTLINE,
(LPTSTR) GetString( IDS_BYTES_PER_CLUSTER ),
szBuffer );
wsprintf(szBuffer, L"%d", di.SectorsPerCluster);
AddLineToReport( SINGLE_INDENT,
RFO_RPTLINE,
(LPTSTR) GetString( IDS_SECTORS_PER_CLUSTER ),
szBuffer );
wsprintf(szBuffer, L"%d", di.MaximumComponentLength);
AddLineToReport( SINGLE_INDENT,
RFO_RPTLINE,
(LPTSTR) GetString( IDS_CHARS_IN_FILENAME ),
szBuffer );
}
//
// Examine the next logical drive.
//
Drive += _tcslen( Drive ) + 1;
}
//
// Restore error mode
//
SetErrorMode (OldErrorMode);
return TRUE;
}
BOOL
FillTreeViewWithDrives( HWND hWnd,
HWND hTreeView,
int nStyle )
/*++
Routine Description:
FillTreeViewWithDrives - fills tree view with list of drives
Arguments:
hWnd - Handle of Dialog
hTreeView - Handle of TreeView
nStyle - either IDC_RADIO_TYPES or IDC_RADIO_LETTERS
Return Value:
BOOL - TRUE if tree is built successfully, FALSE otherwise.
--*/
{
TCHAR LogicalDrives[ MAX_PATH ];
LPTSTR Drive;
DWORD Chars;
HTREEITEM hParent;
HTREEITEM hMyComputer;
TV_INSERTSTRUCT tvis;
HCURSOR hSaveCursor;
UINT OldErrorMode;
static
UINT nDisplayStyle;
//
// Set the style iff we get a valid style
//
if ((nStyle == IDC_PUSH_DRIVE_TYPE) ||
(nStyle == IDC_PUSH_DRIVE_LETTER) ){
nDisplayStyle = nStyle;
}
//
// Set the pointer to an hourglass - this could take a while
//
hSaveCursor = SetCursor ( LoadCursor ( NULL, IDC_WAIT ) ) ;
DbgHandleAssert( hSaveCursor ) ;
//initialize the basic TV structures
tvis.hParent = TVI_ROOT;
tvis.hInsertAfter = TVI_LAST;
tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
// create the ROOT entry
tvis.item.pszText = (LPTSTR) GetString ( IDS_MY_COMPUTER );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_MY_COMPUTER;
tvis.item.lParam = 0;
//clear the treeview
TreeView_DeleteAllItems( hTreeView );
//add a root entry
hMyComputer = AddTreeViewItem(hTreeView, &tvis);
//
// Retrieve the logical drive strings from the system.
//
Chars = GetLogicalDriveStrings(
sizeof( LogicalDrives ),
LogicalDrives
);
DbgAssert(( Chars != 0 ) && ( Chars <= sizeof( LogicalDrives )));
Drive = LogicalDrives;
//
// Disable pop-ups (especially if there is no media in the
// removable drives.)
//
OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS );
//
// For each logical drive, create a DRIVE_INFO object and display
// its name and type.
//
while( *Drive ) {
LPDRIVE_INFO DriveInfo;
TCHAR VolumeNameBuffer[512];
TCHAR FileSystemNameBuffer[512];
TCHAR DriveLetter[3];
DriveLetter[ 0 ] = Drive [ 0 ];
DriveLetter[ 1 ] = Drive [ 1 ];
DriveLetter[ 2 ] = TEXT( '\0');
switch( GetDriveType( Drive ) ) {
case 1:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_NO_ROOT_DIR );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_FOLDER_OPEN;
break;
case DRIVE_REMOVABLE:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_REMOVABLE );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_REMOVABLE;
break;
case DRIVE_FIXED:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_FIXED );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_HARD;
break;
case DRIVE_REMOTE:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_REMOTE );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_NET_CARD;
break;
case DRIVE_CDROM:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_CDROM );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_CDROM;
break;
case DRIVE_RAMDISK:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_RAMDISK );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_RAM;
break;
case 0:
tvis.item.pszText =(LPTSTR) GetString ( IDS_DRIVE_UNKNOWN );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_FOLDER_OPEN;
break;
}
tvis.hParent = hMyComputer;
tvis.hInsertAfter = TVI_LAST;
if ( nDisplayStyle == IDC_PUSH_DRIVE_TYPE )
{
tvis.item.lParam = 0;
hParent = FindOrAddTreeViewItem ( hTreeView, &tvis);
}
else
{
hParent = hMyComputer;
}
tvis.hParent = hParent;
tvis.item.pszText = DriveLetter;
tvis.item.lParam = (DWORD) CreateDriveInfoStructure();
((LPDRIVE_INFO) tvis.item.lParam)->DriveLetter[0]= Drive[0];
((LPDRIVE_INFO) tvis.item.lParam)->DriveLetter[1]= Drive[1];
((LPDRIVE_INFO) tvis.item.lParam)->DriveLetter[2]= Drive[2];
switch( GetDriveType( Drive ) ) {
case 1:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_HARD;
break;
case DRIVE_REMOVABLE:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_REMOVABLE;
break;
case DRIVE_FIXED:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_HARD;
break;
case DRIVE_REMOTE:
{
// Get the remote name
DWORD WNetError;
TCHAR RemoteNameBuffer[512];
DWORD SizeOfRemoteNameBuffer;
NETRESOURCE NetResource;
TCHAR ResourceInformationBuffer[ 1024 ];
DWORD cchResourceInformationBuffer;
TCHAR SystemBuffer[ MAX_PATH ];
TCHAR DisplayName[ MAX_PATH ];
SizeOfRemoteNameBuffer = sizeof( RemoteNameBuffer );
WNetError = WNetGetConnection(
DriveLetter,
RemoteNameBuffer,
&SizeOfRemoteNameBuffer
);
wsprintf(DisplayName, L"%s %s", tvis.item.pszText, RemoteNameBuffer);
tvis.item.pszText = DisplayName;
//
// Call code to determine which tiny icon to display
//
/*
NetResource.dwType = RESOURCETYPE_DISK;
NetResource.lpProvider = NULL;
WNetGetResourceInformation( &NetResource,
(void *) &ResourceInformationBuffer,
&cchResourceInformationBuffer,
&SystemBuffer);
*/
// BUGBUG: subst hits this error
//if (WNetError == NO_ERROR) {
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_NET;
//}
//else
//{
// tvis.item.iImage =
// tvis.item.iSelectedImage = IMAGE_DRIVE_NET_X;
// }
break;
}
case DRIVE_CDROM:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_CDROM;
break;
case DRIVE_RAMDISK:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_RAM;
break;
case 0:
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_DRIVE_HARD;
break;
}
AddTreeViewItem (hTreeView, &tvis);
//
// Examine the next logical drive.
//
Drive += _tcslen( Drive ) + 1;
}
TreeView_Expand(GetDlgItem(hWnd, IDC_TV_DRIVE_LIST),
hMyComputer,
TVE_EXPAND);
//
// Lengthy operation completed. Restore Cursor, and error mode
//
SetCursor ( hSaveCursor ) ;
SetErrorMode ( OldErrorMode ) ;
return(TRUE);
}
BOOL
DisplaySCSIDevices( HWND hWnd,
HWND hTreeView
)
/*++
Routine Description:
DisplaySCSIDevices - fills tree view with list of SCSI Devices
Arguments:
hWnd - Handle of Dialog
hTreeView - Handle of TreeView
Return Value:
BOOL - TRUE if tree is built successfully, FALSE otherwise.
--*/
{
TCHAR LogicalDrives[ MAX_PATH ];
LPTSTR Drive;
DWORD Chars;
HTREEITEM hParent;
HTREEITEM hMyComputer;
TV_INSERTSTRUCT tvis;
HCURSOR hSaveCursor;
//
// Set the pointer to an hourglass - this could take a while
//
hSaveCursor = SetCursor ( LoadCursor ( NULL, IDC_WAIT ) ) ;
DbgHandleAssert( hSaveCursor ) ;
//initialize the basic TV structures
tvis.hParent = TVI_ROOT;
tvis.hInsertAfter = TVI_LAST;
tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
// create the ROOT entry
tvis.item.pszText = (LPTSTR) GetString ( IDS_MY_COMPUTER );
tvis.item.iImage =
tvis.item.iSelectedImage = IMAGE_MY_COMPUTER;
//clear the treeview
TreeView_DeleteAllItems( hTreeView );
//add a root entry
hMyComputer = AddTreeViewItem(hTreeView, &tvis);
TreeView_Expand(GetDlgItem(hWnd, IDC_TV_DRIVE_LIST),
hMyComputer,
TVE_EXPAND);
//
// Lengthy operation completed. Restore Cursor.
//
SetCursor ( hSaveCursor ) ;
return(TRUE);
}
BOOL
DisplayDrivePropertySheet(
HWND hWnd,
LPDRIVE_INFO di
)
/*++
Routine Description:
Displays the property pages for the current drive
Arguments:
hWnd - Handle of the owner window
LPDRIVE_INFO - pointer to DRIVE_INFO structure
Return Value:
BOOL - TRUE if succesful
--*/
{
PROPSHEETPAGE psp[2];
PROPSHEETHEADER psh;
TCHAR Tab1[256];
TCHAR Tab2[256];
// Get Tab names
wsprintf (Tab1, (LPTSTR) GetString( IDS_GENERAL_TAB ));
wsprintf (Tab2, (LPTSTR) GetString( IDS_FILESYSTEM_TAB ));
//Fill out the PROPSHEETPAGE data structure for the General info sheet
psp[0].dwSize = sizeof(PROPSHEETPAGE);
psp[0].dwFlags = PSP_USETITLE;
psp[0].hInstance = _hModule;
psp[0].pszTemplate = MAKEINTRESOURCE(IDD_GENERAL_DRIVE_PAGE);
psp[0].pfnDlgProc = GeneralDriveDetailsDlgProc;
psp[0].pszTitle = Tab1;
psp[0].lParam = (LONG) di;
//Fill out the PROPSHEETPAGE data structure for the filesystem info sheet
psp[1].dwSize = sizeof(PROPSHEETPAGE);
psp[1].dwFlags = PSP_USETITLE;
psp[1].hInstance = _hModule;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_FILESYSTEM_PAGE);
psp[1].pfnDlgProc = FilesystemDetailsDlgProc;
psp[1].pszTitle = Tab2;
psp[1].lParam = (LONG) di;
//Fill out the PROPSHEETHEADER
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_USEICONID | PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW | PSH_PROPTITLE;
psh.hwndParent = hWnd;
psh.hInstance = _hModule;
psh.pszIcon = MAKEINTRESOURCE(IDI_WINMSD);
psh.pszCaption = di->DriveLetter;
psh.nPages = sizeof(psp) / sizeof(PROPSHEETPAGE);
psh.ppsp = (LPCPROPSHEETPAGE) &psp;
//And finally display the dialog with the two property sheets.
return PropertySheet(&psh);
}
int
GetDriveImage (
int nDriveType
)
/*++
Routine Description:
Returns and ImageList index based on drive type
Arguments:
nDriveType - Drive type
Return Value:
int - Index to drive image
--*/
{
int nImage = 0;
switch (nDriveType) {
case 1:
nImage = IMAGE_MY_COMPUTER;
break;
case DRIVE_REMOVABLE:
nImage = IMAGE_DRIVE_REMOVABLE;
break;
case DRIVE_FIXED:
nImage = IMAGE_DRIVE_HARD;
break;
case DRIVE_REMOTE:
nImage = IMAGE_DRIVE_NET;
break;
case DRIVE_CDROM:
nImage = IMAGE_DRIVE_CDROM;
break;
case DRIVE_RAMDISK:
nImage = IMAGE_DRIVE_RAM;
break;
case 0:
nImage = IMAGE_MY_COMPUTER;
break;
}
return(nImage);
}
HTREEITEM
AddTreeViewItem(
HWND hwndTV,
LPTV_INSERTSTRUCT lpis
)
/*++
Routine Description:
AddTreeViewItem - adds items to a tree-view control.
Arguments:
hwndTV - handle of the tree-view control
TV_INSERTSTRUCT - structures to add
Return Value:
HWND - Returns the handle of the newly added item.
--*/
{
//
// Use nImage for iImage unless this is a
// folder, in which case use a callback for image,
// so we can open and close folders.
//
if (lpis->item.iImage == IMAGE_FOLDER_CLOSED)
{
lpis->item.iImage =
lpis->item.iSelectedImage = I_IMAGECALLBACK;
}
// Add the item to the tree-view control.
return TreeView_InsertItem( hwndTV, lpis );
}
HTREEITEM
FindOrAddTreeViewItem ( HWND hWndTV,
LPTV_INSERTSTRUCT lpis
)
/*++
Routine Description:
FindOrAddTreeViewItem: This function will add an item to
a TreeView in the right spot. You
must specify the parent node of where
this item is to be added, and then
this function will check to see if a
node already exists with this name.
If a node with this name already
exists, then its handle is returned.
If the node does not exist, then the
AddTreeViewItem function from
above is called to add the item.
See how this function is used
in the FillTreeView function down
below.
Arguments:
none
Return Value:
none
--*/
{
TV_ITEM tvItem; // Temporary item
HTREEITEM hItem; // Handle to item
TCHAR szBuffer[512]; // Temporary buffer
// Get the first child of the passed in parent
hItem = TreeView_GetChild ( hWndTV, lpis->hParent );
// Loop through all children, looking for an already existing
// child.
while ( hItem )
{
tvItem.mask = TVIF_TEXT; // We want the text
tvItem.hItem = hItem; // Indicate the item to fetch
tvItem.pszText = szBuffer; // Indicate the buffer
tvItem.cchTextMax = sizeof(szBuffer); // Indicate buffer's size
TreeView_GetItem ( hWndTV, &tvItem ); // Get Text
if (!lstrcmpi (tvItem.pszText, lpis->item.pszText)) // Found it! Just return item
return hItem;
// Get the next sibling item in the TreeView, if any.
hItem = TreeView_GetNextSibling ( hWndTV, hItem );
}
// If we made it here, then the item needs to be added
// onto the end of the list
return AddTreeViewItem ( hWndTV, // Handle of TreeView
lpis // pass through the original TV_INSERTSTRUCT
);
}
HICON
GetIcon (int nImage,
int nImageSize
)
/*++
Routine Description:
GetIcon extracts an Icon from the applications image list
Arguments:
nImage -- index of Image
nImageSize -- 16 or 32
Return Value:
HICON -- Handle to Icon
--*/
{
HANDLE hImageList;
if (nImageSize == 16) {
hImageList = _h16x16Imagelist;
}
else
{
hImageList = _h32x32Imagelist;
}
return( ImageList_ExtractIcon(_hModule, hImageList, nImage) );
}
BOOL
InitializeDrivesTab(
HWND hWnd
)
/*++
Routine Description:
Adds the appropriate controls to the drives tab control and
initializes any needed structures.
Arguments:
hWnd - to the main window
Return Value:
BOOL - TRUE if successful
--*/
{
HWND hWndTV; // handle of tree-view control
HCURSOR hSaveCursor;
DLGHDR *pHdr = (DLGHDR *) GetWindowLong(
GetParent(hWnd), GWL_USERDATA);
static
BOOL fInitialized = FALSE;
//
// Set the pointer to an hourglass
//
hSaveCursor = SetCursor ( LoadCursor ( NULL, IDC_WAIT ) ) ;
DbgHandleAssert( hSaveCursor ) ;
//
// set state of global buttons
//
EnableControl( GetParent(hWnd),
IDC_PUSH_PROPERTIES,
FALSE);
EnableControl( GetParent(hWnd),
IDC_PUSH_REFRESH,
TRUE);
//
// Size and position the child dialog
//
SetWindowPos(hWnd, HWND_TOP,
pHdr->rcDisplay.left,
pHdr->rcDisplay.top,
pHdr->rcDisplay.right - pHdr->rcDisplay.left,
pHdr->rcDisplay.bottom - pHdr->rcDisplay.top,
SWP_SHOWWINDOW);
//
// Initialize the Drive Type selection buttons
//
SendDlgItemMessage( hWnd,
IDC_PUSH_DRIVE_TYPE,
BM_SETCHECK,
BST_CHECKED,
0
);
UpdateWindow ( hWnd );
// get handle to Tree view control
hWndTV = GetDlgItem(hWnd, IDC_TV_DRIVE_LIST);
//
// Set the image list used with this TV
//
TreeView_SetImageList (hWndTV,
_h16x16Imagelist,
TVSIL_NORMAL);
//
// Fill the treeview with drives
//
FillTreeViewWithDrives( hWnd,
hWndTV,
IDC_PUSH_DRIVE_TYPE);
SetCursor ( hSaveCursor );
fInitialized = TRUE;
return( TRUE );
}