当前位置:   article > 正文

Windows下两种方法弹出U盘

Windows下两种方法弹出U盘

1. 通过设置IOCTL_STORAGE_EJECT_MEDIA

  • 通过CreateFile打开指定盘符的U盘获取设备句柄hDevice
  • 通过DeviceIoControl(hDevice,FSCTL_DISMOUNT_VOLUME…)强制关闭其他进程对设备的占用
  • 通过DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME…)对设备进行加锁,防止其他进程干扰
  • 通过DeviceIoControl(hDevice,IOCTL_STORAGE_MEDIA_REMOVAL…)来禁用阻止删除多媒体设备功能
  • 通过DeviceIoControl(hDevice,IOCTL_STORAGE_EJECT_MEDIA…)来弹出设备。
    注意,此方法只是从文件浏览页面删除盘符,并不是真的弹出了设备
static int EjectLogDisk(const char *discId)
{
	DWORD accessMode = GENERIC_WRITE | GENERIC_READ;
	DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
	HANDLE hDevice;
	long bResult = 0;
	DWORD retu = 0;
	DWORD dwError;
	DWORD dwBytesReturned;
	DWORD dwSleepAmount;
	int nTryCount;
	char szDriv[10];

	if(discId == NULL){
		return 0;
	}
	dwSleepAmount = LOCK_TIMEOUT/LOCK_RETRIES;
	sprintf(szDriv,"\\\\.\\%s:",discId);
	hDevice = CreateFile(szDriv,accessMode,shareMode,NULL,OPEN_EXISTING,0,NULL);
	if(hDevice == INVALID_HANDLE_VALUE){
		printf("uninstallusb createfile failed error:%d\n",GetLastError());
		return -1;
	}
#if 1
	//卸载U盘卷,不论是否在使用
	dwBytesReturned = 0;
	if(!DeviceIoControl(hDevice,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&dwBytesReturned,NULL)){
		printf("deviceIoConrol FSCTL_DISMOUNT_VOLUME failed\n");
	}
	
	//此循环是用于锁定要弹出的U盘设备,如果U盘在使用,则循环等待
	// Do this in a loop until a timeout period has expired
	for(nTryCount = 0;nTryCount < LOCK_RETRIES;nTryCount++){
		if(DeviceIoControl(hDevice,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dwBytesReturned,NULL)){
			break;
		}
	}
#endif

	dwBytesReturned = 0;
	PREVENT_MEDIA_REMOVAL PMRBuffer;
	PMRBuffer.PreventMediaRemoval = FALSE;
	if(!DeviceIoControl(hDevice,IOCTL_STORAGE_MEDIA_REMOVAL,&PMRBuffer,sizeof(PREVENT_MEDIA_REMOVAL),NULL,0,&dwBytesReturned,NULL)){
		printf("DeviceIoControl IOCTL_STORAGE_MEDIA_REMOVAL failed:%d\n",GetLastError());
	}
	bResult = DeviceIoControl(hDevice,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&retu,NULL);
	if(!bResult){
		CloseHandle(hDevice);
		printf("uninstallusb DeviceIoControl failed error:%d\n",GetLastError());
		return -1;
	}
	CloseHandle(hDevice);

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

2. 通过设置CM_Request_Device_Eject

此方法的作用与从右下角托盘中安全删除并弹出媒体的功能一致,设置之后,设备的错误码为47。并且设备只能通过断上电重新接入电脑才可用。

#include <winioctl.h>
#include "setupapi.h" 
#include "cfgmgr32.h" 
#pragma comment(lib,"setupapi.lib")  

DEVINST GetDrivesDevInstByDiskNumber(long DiskNumber)
{
	GUID* guid = (GUID*)(void*)&GUID_DEVINTERFACE_DISK;

	// Get device interface info set handle for all devices attached to system
	HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL,
		DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

	if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		return 0;
	}

	// Retrieve a context structure for a device interface of a device
	// information set.
	DWORD dwIndex = 0;
	SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
	devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
	BOOL bRet = FALSE;


	PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd;
	SP_DEVICE_INTERFACE_DATA spdid;
	SP_DEVINFO_DATA spdd;
	DWORD dwSize;

	spdid.cbSize = sizeof(spdid);

	while ( true )
	{
		bRet = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex,
			&devInterfaceData);
		if (!bRet)
		{
			break;
		}

		SetupDiEnumInterfaceDevice(hDevInfo, NULL, guid, dwIndex, &spdid);

		dwSize = 0;
		SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize,NULL);

		if ( dwSize )
		{
			pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, dwSize);
			if ( pspdidd == NULL ) 
			{
				continue; // autsch
			}
			pspdidd->cbSize = sizeof(*pspdidd);
			ZeroMemory((PVOID)&spdd, sizeof(spdd));
			spdd.cbSize = sizeof(spdd);


			long res = SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid,pspdidd, dwSize, &dwSize, &spdd);
			if ( res )
			{
				HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0,
					FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
				if ( hDrive != INVALID_HANDLE_VALUE )
				{
					STORAGE_DEVICE_NUMBER sdn;
					DWORD dwBytesReturned = 0;
					res = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER,NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
					if ( res ) 
					{
						if ( DiskNumber == (long)sdn.DeviceNumber )
						{
							CloseHandle(hDrive);
							SetupDiDestroyDeviceInfoList(hDevInfo);
							return spdd.DevInst;
						}
					}
					CloseHandle(hDrive);
				}
			}
			HeapFree(GetProcessHeap(), 0, pspdidd);
		}
		dwIndex++;
	}

	SetupDiDestroyDeviceInfoList(hDevInfo);

	return 0;
}

static int EjectUSBDisk(char *discId)
{
	DWORD accessMode = GENERIC_WRITE | GENERIC_READ;
	DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
	HANDLE hDevice;
	long bResult = 0;
	DWORD retu = 0;
	DWORD dwError;
	DWORD dwBytesReturned;
	int nTryCount;
	char szDriv[10];

	if(discId == NULL)
	{
		return 0;
	}

	sprintf(szDriv,"\\\\.\\%s:",discId);
	hDevice = CreateFile(szDriv,accessMode,shareMode,NULL,OPEN_EXISTING,0,NULL);
	if(hDevice == INVALID_HANDLE_VALUE)
	{
		printf("uninstallusb createfile failed error:%d\n",GetLastError());
		return -1;
	}

	//使用CM_Request_Device_Eject弹出USB设备
	STORAGE_DEVICE_NUMBER sdn;
	long DiskNumber = -1;
	long res = DeviceIoControl(hDevice,IOCTL_STORAGE_GET_DEVICE_NUMBER,NULL,0,&sdn,sizeof(sdn),&dwBytesReturned,NULL);
	if(!res)
	{
		printf("DeviceIoControl IOCTL_STORAGE_GET_DEVICE_NUMBER failed:%d\n",GetLastError());
		CloseHandle(hDevice);
		return -1;
	}

	CloseHandle(hDevice);
	DiskNumber = sdn.DeviceNumber;
	if(DiskNumber == -1)
	{
		printf("DiskNumber == -1\n");
		return -1;
	}

	DEVINST DevInst = GetDrivesDevInstByDiskNumber(DiskNumber);
	if(DevInst == 0)
	{
		printf("GetDrivesDevInstDiskNumber failed\n");
		return -1;
	}

	ULONG Status = 0;
	ULONG ProblemNumber = 0;
	PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown;
	char VetoName[MAX_PATH];
	bool bSuccess = false;

	res = CM_Get_Parent(&DevInst,DevInst,0); //disk's parent, e.g. the USB bridge, the SATA controller....
	res = CM_Get_DevNode_Status(&Status,&ProblemNumber,DevInst,0);
	bool IsRemovable = ((Status & DN_REMOVABLE) != 0);

	printf("isremovable:%d\n",IsRemovable);
	long i;
	// try 3 times
	for(i = 0;i < 3;i++)
	{
		VetoName[0] = '\0';
		if(IsRemovable)
		{
			res = CM_Request_Device_Eject(DevInst,&VetoType,VetoName,MAX_PATH,0);
		}
		else
		{
			res = CM_Query_And_Remove_SubTree(DevInst,&VetoType,VetoName,MAX_PATH,0);
		}
		bSuccess = (res == CR_SUCCESS && VetoName[0] == '\0');
		if(bSuccess)
		{
			break;
		}
		else
		{
			Sleep(200);
		}
	}
	if(bSuccess){
		printf("Success\n\n");
	}else{
		printf("failed\n");

	}
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号