参考:http://bbs.csdn.net/topics/390011646
http://blog.163.com/maple_zh@126/blog/static/107129598200921072150858/
在VC6 XP.sp3中的运行正常的代码:
//
//
两种方式:
//
1 DeviceIoControl读取磁盘扇区
//
2 _getdiskfree显示磁盘扇区信息
//
//
方式切换开关
#define WITH_IOCTL_DISK_GET_DRIVE_GEOMETRY
#ifdef WITH_IOCTL_DISK_GET_DRIVE_GEOMETRY
/*
-------------------------------------------------------------------------- *
*
*
* 1 DeviceIoControl读取磁盘扇区
*
*
* --------------------------------------------------------------------------
*/
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <tchar.h>
#include <winioctl.h>
enum E_DISK_TYPE
{
eDT_Physicaldrive,
eDT_CDROM
};
VOID __cdecl _tmain (INT Argc, PTCHAR Argv[])
{
//
E_DISK_TYPE eDiskType = eDT_Physicaldrive;
//
读取磁盘信息
E_DISK_TYPE eDiskType = eDT_CDROM;
//
读取光盘信息时
TCHAR szName[MAX_PATH] = {
0 };
HANDLE hDisk = NULL;
//
//
命令行参数可在Project Settings->Debug->Program arguments下指定 如:0 1
//
if (Argc !=
3)
{
_tprintf(_T(
"
Reads a sector on the disk\n\n
"));
_tprintf(_T(
"
%s [disk number] [sector]\n
"), Argv[
0]);
return;
}
switch (eDT_CDROM)
{
case eDT_Physicaldrive:
_sntprintf(szName,
sizeof(szName) /
sizeof(szName[
0]) -
1, _T(
"
\\\\.\\Physicaldrive%d
"), _ttoi(Argv[
1]));
//
读取磁盘信息时
break;
case eDT_CDROM:
_sntprintf(szName,
sizeof(szName) /
sizeof(szName[
0]) -
1, _T(
"
\\\\.\\CDROM%d
"), _ttoi(Argv[
1]));
//
读取光盘信息时
break;
}
//
//
打开磁盘
//
hDisk = CreateFile(szName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
NULL,
0);
if (hDisk != INVALID_HANDLE_VALUE)
{
//
//
磁盘的结构信息存在此结束中。
/*
typedef struct _DISK_GEOMETRY
{
LARGE_INTEGER Cylinders; // 柱面数
MEDIA_TYPE MediaType; // 磁盘类型,见MSDN
DWORD TracksPerCylinder; // 每道柱面数
DWORD SectorsPerTrack; // 每道扇区数
DWORD BytesPerSector; // 每扇区字节数
} DISK_GEOMETRY;
*/
DISK_GEOMETRY diskGeometry;
DWORD dwBytes =
0;
//
//
获得磁盘结构信息
if (!DeviceIoControl(hDisk,
IOCTL_DISK_GET_DRIVE_GEOMETRY,
//
调用了CTL_CODE macro宏
NULL,
0,
&diskGeometry,
sizeof(DISK_GEOMETRY),
&dwBytes,
NULL))
{
_tprintf(_T(
"
IOCTL_DISK_GET_DRIVE_GEOMETRY failed with error code %d\n
"), GetLastError());
return;
}
//
//
DWORD dwSize = diskGeometry.BytesPerSector;
//
每sector字节数
PVOID lpBuffer =
new BYTE [dwSize];
if (lpBuffer == NULL)
{
_tprintf(_T(
"
Unable to allocate resources, exiting\n
"));
return;
}
//
//
关于磁盘分区的信息
//
/*
typedef struct _PARTITION_INFORMATION
{
LARGE_INTEGER StartingOffset; // 启动分区偏移
LARGE_INTEGER PartitionLength; // 分区长度(字节)
DWORD HiddenSectors; // 分区中隐藏扇区数
DWORD PartitionNumber; // 分区数
BYTE PartitionType; // 分区类型
BOOLEAN BootIndicator; // 是否为引导分区,TRUE是
BOOLEAN RecognizedPartition; // 验证过的分区。TRUE是
BOOLEAN RewritePartition; // 分区是否可改变。TRUE
} PARTITION_INFORMATION, *PPARTITION_INFORMATION;
*/
PARTITION_INFORMATION partitionInfo;
//
//
获得磁盘磁盘分区的信息
if (DeviceIoControl(hDisk,
IOCTL_DISK_GET_PARTITION_INFO,
NULL,
0,
&partitionInfo,
sizeof(PARTITION_INFORMATION),
&dwBytes,
NULL))
{
switch (eDT_CDROM)
{
case eDT_Physicaldrive:
_tprintf ( _T(
"
磁盘空间为 %.2fGB 每扇区 %ld字节 共%ld个扇区\r\n
"),
partitionInfo.PartitionLength.QuadPart/
1024./
1024./
1024.
//
磁盘空间
, diskGeometry.BytesPerSector
//
每扇区字节数
, partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector);
//
总扇区数
break;
case eDT_CDROM:
_tprintf ( _T(
"
光盘空间为 %.2fMB 每扇区 %ld字节 共%ld个扇区\r\n
"),
partitionInfo.PartitionLength.QuadPart/
1024./
1024.
//
光盘空间
, diskGeometry.BytesPerSector
//
每扇区字节数
, partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector);
//
总扇区数
break;
}
//
获取总扇区数
LONGLONG sectorCount = partitionInfo.PartitionLength.QuadPart / diskGeometry.BytesPerSector;
//
以16进制输出
switch (eDT_CDROM)
{
case eDT_Physicaldrive:
_tprintf(_T(
"
PhysicalDisk %d has 0x%I64x sectors with 0x%x bytes in every sector\n
"), _ttoi(Argv[
1]), sectorCount, diskGeometry.BytesPerSector);
break;
case eDT_CDROM:
_tprintf(_T(
"
CDROM %d has 0x%I64x sectors with 0x%x bytes in every sector\n
"), _ttoi(Argv[
1]), sectorCount, diskGeometry.BytesPerSector);
break;
}
//
LONGLONG nIndex = _ttoi64(Argv[
2]);
//
//
读取被请求的sector
//
if (nIndex < sectorCount)
{
//
有符号的64位整型表示
LARGE_INTEGER offset;
//
sector数所占字节
offset.QuadPart = (nIndex) * diskGeometry.BytesPerSector;
//
从打开的文件(磁盘)中移动文件指针。offset.LowPart低32位为移动字节数
SetFilePointer(hDisk, offset.LowPart, &offset.HighPart, FILE_BEGIN);
//
读取扇区的数据
if (ReadFile(hDisk, lpBuffer, dwSize, &dwBytes, NULL))
{
//
扇区的数据
_tprintf(_T(
"
扇区%d数据:\n
"), nIndex);
//
//
The dwBytes field holds the number of bytes that were actually read [ <= dwSize ]
//
for (ULONG nOffset =
0; nOffset < dwBytes; nOffset +=
0x10)
{
ULONG nBytes, nIdx;
//
//
显示地址
//
_tprintf(_T(
"
%011I64x
"), (offset.QuadPart) + nOffset);
//
//
显示16进制数据
//
nBytes = min(
0x10, dwBytes - nOffset);
for (nIdx =
0; nIdx < nBytes; nIdx++)
{
_tprintf(_T(
"
%02x %s
"), ((PUCHAR)lpBuffer)[nOffset + nIdx], ((nIdx +
1) %
0x8) ? _T(
"") : _T(
"
"));
}
for ( ; nIdx <
0x10; nIdx++)
{
_tprintf(_T(
"
%s
"), ((nIdx +
1) %
0x8) ? _T(
"") : _T(
"
"));
}
//
//
显示ascii格式数据
//
for (nIdx =
0; nIdx < nBytes; nIdx++)
{
_tprintf(_T(
"
%c
"), isprint(((PUCHAR)lpBuffer)[nOffset + nIdx]) ? ((PUCHAR)lpBuffer)[nOffset + nIdx] : _T(
'
.
'));
}
_tprintf(_T(
"
\n
"));
}
}
//
end ReadFile
else
{
_tprintf(_T(
"
ReadFile() on sector 0x%I64x failed with error code: %d\n
"), nIndex, GetLastError());
}
}
//
end if (nIndex < sectorCount)
else
{
_tprintf(_T(
"
The requested sector is out-of-bounds\n
"));
}
}
//
end 1 if (DeviceIoControl
else
{
_tprintf(_T(
"
IOCTL_DISK_GET_PARTITION_INFO failed with error code %d\n
"), GetLastError());
}
delete [] lpBuffer;
CloseHandle(hDisk);
}
//
if (hDisk != INVALID_HANDLE_VALUE)
else
{
_tprintf(_T(
"
CreateFile() on %s failed with error code %d\n
"), szName, GetLastError());
}
_tprintf(_T(
"
\n
"));
return;
}
#else
/*
-------------------------------------------------------------------------- *
*
*
* 2 _getdiskfree显示磁盘扇区信息
*
*
* --------------------------------------------------------------------------
*/
//
crt_getdiskfree.c
#include <windows.h>
#include <direct.h>
#include <stdio.h>
#include <tchar.h>
TCHAR g_szBorder[] = _T(
"
======================================================================\n
");
TCHAR g_szTitle1[] = _T(
"
|DRIVE|TOTAL CLUSTERS|AVAIL CLUSTERS|SECTORS / CLUSTER|BYTES / SECTOR|\n
");
TCHAR g_szTitle2[] = _T(
"
|=====|==============|==============|=================|==============|\n
");
TCHAR g_szLine[] = _T(
"
| A: | | | | |\n
");
void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uVal);
int main(
int argc,
char* argv[])
{
TCHAR szMsg[
4200];
struct _diskfree_t df = {
0};
ULONG uDriveMask = _getdrives();
//
表示当前可用的磁盘
unsigned uErr, uLen, uDrive;
printf(g_szBorder);
printf(g_szTitle1);
printf(g_szTitle2);
int ifor =
0;
for (uDrive=
1; uDrive<=
26; ++uDrive)
{
if (uDriveMask &
1)
{
uErr = _getdiskfree(uDrive, &df);
memcpy(szMsg, g_szLine,
sizeof(g_szLine));
szMsg[
3] = uDrive +
'
A
' -
1;
char lp[
5] =
"
C:\\
";
lp[
0] = uDrive +
'
A
' -
1;
if (uErr ==
0)
{
utoiRightJustified(szMsg+
8, szMsg+
19, df.total_clusters);
utoiRightJustified(szMsg+
23, szMsg+
34, df.avail_clusters);
utoiRightJustified(szMsg+
38, szMsg+
52, df.sectors_per_cluster);
utoiRightJustified(szMsg+
56, szMsg+
67, df.bytes_per_sector);
ifor ++;
}
else
{
uLen = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, uErr,
0, szMsg+
8,
4100, NULL);
szMsg[uLen+
6] =
'
';
szMsg[uLen+
7] =
'
';
szMsg[uLen+
8] =
'
';
ifor ++;
}
printf(szMsg);
}
uDriveMask >>=
1;
if (!uDriveMask)
break;
}
printf(g_szBorder);
printf (
"
共%d个\n
", ifor);
return
0;
}
void utoiRightJustified(TCHAR* szLeft, TCHAR* szRight, unsigned uVal)
{
TCHAR* szCur = szRight;
int nComma =
0;
if (uVal)
{
while (uVal && (szCur >= szLeft))
{
if (nComma ==
3)
{
*szCur =
'
,
';
nComma =
0;
}
else
{
*szCur = (uVal %
10) |
0x30;
uVal /=
10;
++nComma;
}
--szCur;
}
}
else
{
*szCur =
'
0
';
--szCur;
}
if (uVal)
{
szCur = szLeft;
while (szCur <= szRight)
{
*szCur =
'
*
';
++szCur;
}
}
}
#endif