如何枚举机子的移动硬盘和U盘

大海啊全是水 2010-08-26 09:56:18
用GetDriveType不能区分移动硬盘。
网上查了查 可以使用GetRegistryProperty参数用SPDRP_REMOVAL_POLICY 可以判断是否为移动硬盘。
不知道具体使用,
我现在的已经做了
HDEVINFO hDevInfo = SetupDiGetClassDevs(NULL,NULL,0,DIGCF_PRESENT|DIGCF_ALLCLASSES);
SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)};
for( DWORD DeviceId=0; SetupDiEnumDeviceInfo( hDevInfo,DeviceId,&DeviceInfoData); DeviceId++)

SetupDiGetDeviceRegistryProperty ...

SetupDiGetDeviceRegistryPropertyA(
__in HDEVINFO DeviceInfoSet,
__in PSP_DEVINFO_DATA DeviceInfoData,
__in DWORD Property,
__out_opt PDWORD PropertyRegDataType,
__out_bcount_opt(PropertyBufferSize) PBYTE PropertyBuffer,
__in DWORD PropertyBufferSize,
__out_opt PDWORD RequiredSize
);
不知道获取那些属性能够得到所有移动硬盘和U盘,应该有SPDRP_REMOVAL_POLICY这个什么的,但是得到的PropertyBuffer该怎么判断呢?好像与CM_DRP_REMOVAL_POLICY有关。
最后判断出来是移动硬盘或者U盘以后 如何得到盘符呢? 通过他的GUID? 要用到什么函数呢?
...全文
578 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
大海啊全是水 2011-09-26
  • 打赏
  • 举报
回复

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <winioctl.h>


#define _WIN32_WINNT 0x0500
#define WINVER 0x0500


#define IOCTL_STORAGE_QUERY_PROPERTY CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)

typedef enum _STORAGE_PROPERTY_ID {
StorageDeviceProperty = 0,
StorageAdapterProperty,
StorageDeviceIdProperty
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;

typedef enum _STORAGE_QUERY_TYPE {
PropertyStandardQuery = 0,
PropertyExistsQuery,
PropertyMaskQuery,
PropertyQueryMaxDefined
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;


typedef struct _STORAGE_PROPERTY_QUERY {
STORAGE_PROPERTY_ID PropertyId;
STORAGE_QUERY_TYPE QueryType;
UCHAR AdditionalParameters[1];
} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

typedef struct _STORAGE_DEVICE_DESCRIPTOR {
ULONG Version;
ULONG Size;
UCHAR DeviceType;
UCHAR DeviceTypeModifier;
BOOLEAN RemovableMedia;
BOOLEAN CommandQueueing;
ULONG VendorIdOffset;
ULONG ProductIdOffset;
ULONG ProductRevisionOffset;
ULONG SerialNumberOffset;
STORAGE_BUS_TYPE BusType;
ULONG RawPropertiesLength;
UCHAR RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;

static CHAR BufType[0x7f][128] = {"未知类型","SCSI","Atapi","Ata","1394","Ssa","Fibre","Usb","RAID","iSCSI","SATA","SAS","",};

//typedef BOOL (WINAPI* osGetVolumePathNamesForVolumeName)(LPCTSTR, LPTSTR, DWORD, PDWORD);
//
//osGetVolumePathNamesForVolumeName GetFunction_GetVolumePathNamesForVolumeName(void)
//{
// TCHAR tcPath[MAX_PATH] = {0};
// osGetVolumePathNamesForVolumeName pFunc = NULL;
// HMODULE hKer32 = GetModuleHandle(_T("Kernel32.dll"));
// if( hKer32 == NULL )
// {
// if( ::GetSystemDirectory(tcPath, sizeof(tcPath) / sizeof(tcPath[0])) )
// {
// _tcscat(tcPath, _T("\\Kernel32.dll"));
// hKer32 = LoadLibrary(tcPath);
// }
// }
//
// if( hKer32 )
// {
//#ifdef _UNICODE
// pFunc = (osGetVolumePathNamesForVolumeName)GetProcAddress(hKer32, "GetVolumePathNamesForVolumeNameW");
//#else
// pFunc = (osGetVolumePathNamesForVolumeName)GetProcAddress(hKer32, "GetVolumePathNamesForVolumeNameA");
//#endif
// }
//
// return pFunc;
//}

void DisplayVolumeBusType(TCHAR* szPath)
{
STORAGE_PROPERTY_QUERY StoragePropertyQuery;
STORAGE_DEVICE_DESCRIPTOR StDescript = { 0 };
StoragePropertyQuery.PropertyId = StorageDeviceProperty;
StoragePropertyQuery.QueryType = PropertyStandardQuery;
DWORD NumberOfBytesReturned;
HANDLE Handle;

TCHAR Name[MAX_PATH]=_T("");
Name[0]=_T('\\');
Name[1]=_T('\\');
Name[2]=_T('.');
Name[3]=_T('\\');
Name[4]=_T('\0');

_tcscpy(&Name[4],szPath);
Name[6]=_T('\0');
Handle = ::CreateFile(Name,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

if (Handle == INVALID_HANDLE_VALUE)
{
printf("CreateFileW File,Error Code=%d\n", GetLastError());
return;
}


BOOL Status = DeviceIoControl( Handle,
IOCTL_STORAGE_QUERY_PROPERTY,
&StoragePropertyQuery,
sizeof(STORAGE_PROPERTY_QUERY),
&StDescript,
sizeof(STORAGE_DEVICE_DESCRIPTOR),
&NumberOfBytesReturned,
NULL );
if (Status)
{
printf("\n磁盘类型:%s类型<%s>\n", BufType[StDescript.BusType],StDescript.RemovableMedia ? "移动磁盘" : "固定磁盘");
//printf("BusType %X\n",(BYTE)StDescript.BusType);
}
CloseHandle(Handle);

}

void DisplayVolumePaths(
TCHAR* VolumeName
)
{
DWORD CharCount = MAX_PATH + 1;
TCHAR* Names = NULL;
TCHAR* NameIdx = NULL;
BOOL Success = FALSE;

//osGetVolumePathNamesForVolumeName funcGetVolume = GetFunction_GetVolumePathNamesForVolumeName();
//if( funcGetVolume == NULL ){
// printf("GetFunction_GetVolumePathNamesForVolumeName Fail, Error Code=%d\n", GetLastError());
// return;
//}

for (;;)
{
Names = (TCHAR*) new BYTE [CharCount * sizeof(TCHAR)];

if ( !Names )
{
return;
}

Success = GetVolumePathNamesForVolumeName(
VolumeName, Names, CharCount, &CharCount
);

if ( Success )
{
break;
}

if ( GetLastError() != ERROR_MORE_DATA )
{
break;
}

delete [] Names;
Names = NULL;
}

if ( Success )
{
for ( NameIdx = Names;
NameIdx[0] != L'\0';
NameIdx += wcslen(NameIdx) + 1 )
{
_tprintf(_T(" %s"), NameIdx);
DisplayVolumeBusType(NameIdx);
}
_tprintf(_T("\n"));
}

if ( Names != NULL )
{
delete [] Names;
Names = NULL;
}

return;
}


int _tmain(int argc, _TCHAR* argv[])
{
DWORD CharCount = 0;
TCHAR DeviceName[MAX_PATH] = _T("");
DWORD Error = ERROR_SUCCESS;
HANDLE FindHandle = INVALID_HANDLE_VALUE;
BOOL Found = FALSE;
size_t Index = 0;
BOOL Success = FALSE;
TCHAR VolumeName[MAX_PATH] = _T("");

FindHandle = FindFirstVolume(VolumeName,MAX_PATH);

if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
_tprintf(_T("FindFirstVolumeW failed with error code %d\n"), Error);
_getch();
return -1;
}

for (;;)
{
Index = wcslen(VolumeName) - 1;

if (VolumeName[0] != _T('\\') ||
VolumeName[1] != _T('\\') ||
VolumeName[2] != _T('?') ||
VolumeName[3] != _T('\\') ||
VolumeName[Index] != _T('\\'))
{
Error = ERROR_BAD_PATHNAME;
_tprintf(_T("FindFirstVolume/FindNextVolume returned a bad path: %s\n"), VolumeName);
break;
}
VolumeName[Index] = _T('\0');

CharCount = QueryDosDevice(&VolumeName[4], DeviceName,MAX_PATH-4);

VolumeName[Index] = _T('\\');

if ( CharCount == 0 )
{
Error = GetLastError();
_tprintf(_T("QueryDosDevice failed with error code %d\n"), Error);
break;
}

_tprintf(_T("\nFound a device:\n %s"), DeviceName);
_tprintf(_T("\nVolume name: %s"), VolumeName);
_tprintf(_T("\nPaths:"));
DisplayVolumePaths(VolumeName);

Success = FindNextVolume(FindHandle, VolumeName, MAX_PATH);

if ( !Success )
{
Error = GetLastError();

if (Error != ERROR_NO_MORE_FILES)
{
_tprintf(_T("FindNextVolume failed with error code %d\n"), Error);
break;
}

Error = ERROR_SUCCESS;
break;
}
}

FindVolumeClose(FindHandle);
FindHandle = INVALID_HANDLE_VALUE;
_getch();
return 0;
}

紫電靑霜 2011-09-20
  • 打赏
  • 举报
回复
tianhaoma8888最后是咋搞定的呢?
大海啊全是水 2010-09-26
  • 打赏
  • 举报
回复
最后使用DeviceIoContrl函数搞定了的 都忘了揭帖了
大海啊全是水 2010-09-01
  • 打赏
  • 举报
回复
这两天 继续看了看 Setup api有点眉目了 但是还存在一些问题
setup api 能够判断一个存储设备是本地还是可插拔的。但是好像不能得到这个存储设备的磁盘分区盘符
希望各位大侠指点指点。 继续研究着
兄弟些 要是知道的话 就帮帮我
不知道的话 就帮忙顶顶
大海啊全是水 2010-08-26
  • 打赏
  • 举报
回复
GetDriveType 本地磁盘 和 移动磁盘 得到的都是 DRIVE_FIXED
所以这个无法区分本地磁盘和移动磁盘啊
「已注销」 2010-08-26
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 tianhaoma8888 的回复:]

移动硬盘 用GetDriveType得到的是DRIVE_FIXED
[/Quote]
这不正好区分开了吗?
移动硬盘是DRIVE_FIXED,U盘是DRIVE_REMOVABLE。
记得把之前的分区总数先记下来。

这里有一个实时检测的例子:
#include <windows.h>
#include <stdio.h>
BOOL bDriver[27];
BOOL bFirst = TRUE;
void dect()
{
char szDriver[3];
for (int i = 'C'; i <= 'Z'; i++)
{
szDriver[0] = i;
szDriver[1] = ':';
szDriver[2] = 0;
UINT uType = GetDriveType(szDriver);
if (uType == DRIVE_REMOVABLE || uType == DRIVE_FIXED)
{
if ((!bFirst) && (!bDriver[i-'C'])) printf("found %c:\n", i);
bDriver[i-'C'] = TRUE;
}
else //移走?
{
if (bDriver[i-'C'])
{
bDriver[i-'C'] = FALSE;
printf("remove %c:\n", i);
}
}
}
if (bFirst) bFirst = FALSE;
}

int main()
{
ZeroMemory(bDriver, sizeof(bDriver));
while (1)
{
dect();
Sleep(2000);
}
return 0;
}
大海啊全是水 2010-08-26
  • 打赏
  • 举报
回复
移动硬盘 用GetDriveType得到的是DRIVE_FIXED
「已注销」 2010-08-26
  • 打赏
  • 举报
回复
GetDriveType((LPCTSTR)strdir)==DRIVE_REMOVABLE
大海啊全是水 2010-08-26
  • 打赏
  • 举报
回复
兄弟些帮忙顶顶 我都给分
cheeralen兄的方法 我会去查查的 我现在在家没有移动硬盘 没法用命令看
暗黑帝国 2010-08-26
  • 打赏
  • 举报
回复
通过WMI接口 diskdrive可以区分是USB还是本地硬盘

在cmd命令下试了一下,可以的,所以应该可以用wmi接口api来获取信息。
wmic
diskdrive
大海啊全是水 2010-08-26
  • 打赏
  • 举报
回复
我说的是 不能区分移动硬盘和本地硬盘

上面说的“网上查了查 可以使用GetRegistryProperty参数用SPDRP_REMOVAL_POLICY 可以判断是否为移动硬盘。”
修改下,可以使用SetupDiGetDeviceRegistryProperty函数
zhangkewen1234 2010-08-26
  • 打赏
  • 举报
回复
试过了,可以区分的

65,199

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧