VC++ 安全卸载移动设备

#include <windows.h>
#include <windef.h>

#ifndef _WIN64
typedef  long LONG_PTR;
typedef  unsigned long ULONG_PTR;
typedef  DWORD	DWORD_PTR;
#endif

#include "Setupapi.h"
#include "winioctl.h"
#include "cfgmgr32.h"
#include <initguid.h>

#pragma comment(lib,"Cfgmgr32.lib")
#pragma comment(lib,"hid.lib")  
#pragma comment(lib,"setupapi.lib")

DEFINE_GUID(GUID_DEVINTERFACE_DISK,   0x53f56307L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
DEFINE_GUID(GUID_DEVINTERFACE_CDROM,  0x53f56308L, 0xb6bf, 0x11d0, 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);

DEVINST GetDrivesDevInstByDiskNumber(long DiskNumber, UINT DriveType) 
{
	GUID* guid;

	switch (DriveType) 
	{
	case DRIVE_REMOVABLE:
		//break;
	case DRIVE_FIXED:
		guid = (GUID*)(void*)&GUID_DEVINTERFACE_DISK;
		break;
	case DRIVE_CDROM:
		guid = (GUID*)(void*)&GUID_DEVINTERFACE_CDROM;
		break;
	default:
		return 0;
	}

	HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
	if (hDevInfo == INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	
	DWORD dwIndex = 0;
	SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
	devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
	BOOL bRet = FALSE;

	BYTE Buf[1024];
	PSP_DEVICE_INTERFACE_DETAIL_DATA pspdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;
	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!=0 && dwSize<=sizeof(Buf) ) 
		{
			pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
			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);
				}
			}
		}
		dwIndex++;
	}
	SetupDiDestroyDeviceInfoList(hDevInfo);
	
	return 0;
}

BOOL RemovalUDisk(TCHAR* szDisk)
{
	TCHAR DriveLetter = szDisk[0];
	DriveLetter &= ~0x20;
	toupper(DriveLetter);
	if ( DriveLetter < 'A' || DriveLetter > 'Z' ) 
		return FALSE;
	
	TCHAR szRootPath[] = _T("X:\\");   // "X:\"
	szRootPath[0] = DriveLetter;
	TCHAR szVolumeAccessPath[] = _T("\\\\.\\X:");   // "\\.\X:"
	szVolumeAccessPath[4] = DriveLetter;
	long DiskNumber = -1;
	HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
	if (hVolume == INVALID_HANDLE_VALUE)
	{
		DWORD dwError = GetLastError();
		if (dwError == ERROR_FILE_NOT_FOUND)
			return TRUE;
		else
			return FALSE;
	}

	STORAGE_DEVICE_NUMBER sdn;
	DWORD dwBytesReturned = 0;
	long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
	if ( res ) 
		DiskNumber = sdn.DeviceNumber;
	CloseHandle(hVolume);
	if ( DiskNumber == -1 ) 
		return FALSE;
	
	UINT DriveType = GetDriveType(szRootPath);
	DEVINST DevInst = GetDrivesDevInstByDiskNumber(DiskNumber, DriveType);
	if ( DevInst == 0 ) 
		return FALSE;
	
	ULONG Status = 0;
	ULONG ProblemNumber = 0;
	PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown; 
	WCHAR VetoNameW[MAX_PATH];
	BOOL bSuccess = FALSE;
	res = CM_Get_Parent(&DevInst, DevInst, 0);  // disk's parent, e.g. the USB bridge, the SATA port....
	res = CM_Get_DevNode_Status(&Status, &ProblemNumber, DevInst, 0);
	BOOL IsRemovable = ((Status & DN_REMOVABLE) != 0);
	for ( long tries=1; tries<=3; tries++ )  // 重试3次机会
	{
		VetoNameW[0] = 0;
		if ( IsRemovable ) 
		{
			wchar_t VetoNameW[MAX_PATH];
			res = CM_Request_Device_EjectW(DevInst, &VetoType, VetoNameW, sizeof(VetoNameW), 0); 
			//res = CM_Request_Device_EjectW(DevInst, &VetoType, NULL, 0, 0);  // with MessageBox or 'bubble'
		}
		else 
		{
			res = CM_Query_And_Remove_SubTreeW(DevInst, &VetoType, VetoNameW, sizeof(VetoNameW), 0); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
		}

		bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
		if ( bSuccess )  
			break;
		else
			Sleep(200); // required to give the next tries a chance!
	}

	if ( bSuccess ) 
		return TRUE;

	return FALSE;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值