by the way

更新时间:2022-11-24 22:50:58 阅读: 评论:0


2022年11月24日发(作者:伞的英文单词)

RemoveDriveByLetter

Introduction

RemovingaUSBdriveusingtheWindowstrayiconiasy,especiallyifyousingle

left-clickit,butsometimesit'sufultodoitfromyourprogram.

Background

Therearesomesamplesaround,buttheonesIsawwerearchingforthevolume

andthencallingCM_Get_

ives

(drivetype:DRIVE_REMOVABLE)arehandleddifferentlyfrombasicdisks

(DRIVE_FIXED)bledriveshaveaone-to-onerelation

betweenthevolumeandthedisk,wherethediskistheparentdeviceofthevolume.

USBdriveswithoutremovablemediaarehandledlikebasicdisks,sotheycanhave

multiplepartitionsandthevolume'sparentdeviceisnotthedisk!UnderVista,this

isthecaforremovabledrivestoo,

theway,

someinformation.

cangetitviaDeviceIoControlcalledwith

IOCTL_STORAGE_GET_DEVICE_llworkswithhandlestostorage

volumesontheoneside,anddisks,

gwithdriveletters,we

havetodistinguishbetweenthedeviceinterfacesGUID_DEVINTERFACE_DISK,

GUID_DEVINTERFACE_FLOPPYandGUID_DEVINTERFACE_ppies

werenotconsideredhereuntilendofOctober2006,soaUSBfloppyscrewedup

everything,life,aUSBfloppyhasdevicenumber0whileanyother

USBdrivehasahighernumber,sotherewerenorealproblems.

Bytheway:LegacyfloppiesarenotpartoftheGUID_DEVINTERFACE_FLOPPY

enumeration.

TheSample

sthe

volumeandgetsitsdevicenumber:

Collap

//"X:"->forGetDriveType

charszRootPath[]="X:";

szRootPath[0]=DriveLetter;

//"X:"->forQueryDosDevice

charszDevicePath[]="X:";

szDevicePath[0]=DriveLetter;

//".X:"->toopenthevolume

charszVolumeAccessPath[]=".X:";

szVolumeAccessPath[4]=DriveLetter;

longDeviceNumber=-1;

HANDLEhVolume=CreateFile(szVolumeAccessPath,0,

FILE_SHARE_READ|FILE_SHARE_WRITE,

NULL,OPEN_EXISTING,0,NULL);

if(hVolume==INVALID_HANDLE_VALUE){

return1;

}

STORAGE_DEVICE_NUMBERsdn;

DWORDdwBytesReturned=0;

longres=DeviceIoControl(hVolume,

IOCTL_STORAGE_GET_DEVICE_NUMBER,

NULL,0,&sdn,sizeof(sdn),

&dwBytesReturned,NULL);

if(res){

DeviceNumber=Number;

}

CloHandle(hVolume);

if(DeviceNumber==-1){

return1;

}

UINTDriveType=GetDriveType(szRootPath);

//getthedosdevicename(likedevicefloppy0)

//todecideifit'safloppyornot

charszDosDeviceName[MAX_PATH];

res=QueryDosDevice(szDevicePath,szDosDeviceName,MAX_PATH);

if(!res){

return1;

}

DEVINSTDevInst=GetDrivesDevInstByDeviceNumber(DeviceNumber,

DriveType,szDosDeviceName);

if(DeviceNumber==-1){

return1;

}

Thenitenumeratesalldisks,floppiesorCD-ROMs—dependingonthedrivetype

andtheDOSdevicename—k'sdevicenumbersare

matchedwiththedevicenumbermentionedaboveinordertogetthedevice

instance:

Collap

//---------------------------------------------------------

DEVINSTGetDrivesDevInstByDeviceNumber(longDeviceNumber,

UINTDriveType,char*szDosDeviceName)

{

boolIsFloppy=(strstr(szDosDeviceName,

"Floppy")!=NULL);//isthereabetterway?

GUID*guid;

switch(DriveType){

caDRIVE_REMOVABLE:

if(IsFloppy){

guid=(GUID*)&GUID_DEVINTERFACE_FLOPPY;

}el{

guid=(GUID*)&GUID_DEVINTERFACE_DISK;

}

break;

caDRIVE_FIXED:

guid=(GUID*)&GUID_DEVINTERFACE_DISK;

break;

caDRIVE_CDROM:

guid=(GUID*)&GUID_DEVINTERFACE_CDROM;

break;

default:

return0;

}

//Getdeviceinterfaceinfothandle

//foralldevicesattachedtosystem

HDEVINFOhDevInfo=SetupDiGetClassDevs(guid,NULL,NULL,

DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);

if(hDevInfo==INVALID_HANDLE_VALUE){

return0;

}

//Retrieveacontextstructureforadeviceinterface

//ofadeviceinformationt.

DWORDdwIndex=0;

BOOLbRet=FALSE;

BYTEBuf[1024];

PSP_DEVICE_INTERFACE_DETAIL_DATApspdidd=

(PSP_DEVICE_INTERFACE_DETAIL_DATA)Buf;

SP_DEVICE_INTERFACE_DATAspdid;

SP_DEVINFO_DATAspdd;

DWORDdwSize;

=sizeof(spdid);

while(true){

bRet=SetupDiEnumDeviceInterfaces(hDevInfo,NULL,

guid,dwIndex,&spdid);

if(!bRet){

break;

}

dwSize=0;

SetupDiGetDeviceInterfaceDetail(hDevInfo,

&spdid,NULL,0,&dwSize,NULL);

if(dwSize!=0&&dwSize<=sizeof(Buf)){

pspdidd->cbSize=sizeof(*pspdidd);//5Bytes!

ZeroMemory((PVOID)&spdd,sizeof(spdd));

=sizeof(spdd);

longres=

SetupDiGetDeviceInterfaceDetail(hDevInfo,&

spdid,pspdidd,

dwSize,&dwSize,

&spdd);

if(res){

HANDLEhDrive=CreateFile(pspdidd->DevicePath,0,

FILE_SHARE_READ|FILE_SHARE_WRITE,

NULL,OPEN_EXISTING,NULL,NULL);

if(hDrive!=INVALID_HANDLE_VALUE){

STORAGE_DEVICE_NUMBERsdn;

DWORDdwBytesReturned=0;

res=DeviceIoControl(hDrive,

IOCTL_STORAGE_GET_DEVICE_NUMBER,

NULL,0,&sdn,sizeof(sdn),

&dwBytesReturned,NULL);

if(res){

if(DeviceNumber==(long)Number){

CloHandle(hDrive);

SetupDiDestroyDeviceInfoList(hDevInfo);

t;

}

}

CloHandle(hDrive);

}

}

}

dwIndex++;

}

SetupDiDestroyDeviceInfoList(hDevInfo);

return0;

}

//---------------------------------------------------------

Theparentdeviceofthedisk,floppyorCD-ROMistheUSBdevicetoeject.

CM_Request_Device_Ejectshallbeudfordeviceswhichhavethe

i,CM_Query_And_Remove_SubTree

Nhereandhere.

However,CM_Query_And_Remove_SubTreedoesn'tworkforrestrictedurs—it

returnsCR_ACCESS_DENIEDinthecas—whilethenon-suggested

CM_Request_Device_ista,wehave

toaddtheflagCM_REMOVE_NO_RESTARTbecauotherwithejust-removed

heeasywayandnowu

CM_Request_Device_Ejectexclusively.

Discussion

Herearesomeinterestinglinks:

/lists_archive/ntdev/

/MSDN/?PostID=705890&SiteI

D=1

IfyouuitforPATAdrives,thenbothmasterandslavedrivesareremoved!

However,bothcanbebroughtbackwithaDEVCONRESCAN.

IfthefunctionsarecalledwithNULL/0forthevetoparameters,thenXPshowsthe

"it'ssafenow"balloontip,

McCoyoncesaid:"vetochangethings."

IrememberthatI'veenCM_Query_And_Remove_SubTreeand

CM_Request_Device_EjectreturningCR_SUCCESSevenwhenthecallfailed

treproduceitbutI'msureI'veenthis,maybeitwas

oreitemstobebettertocheckthevetovaluesthatthe

functionsreturn.

UnderWindows2000,theANSIversionsofbothfunctionsarenotimplemented.

TheyreturnCR_CALL_NOT_IMPLEMENTED,soweutheUnicodeversionsinstead.

Bothfunctionsmaytakeveralcondsuntiltheyreturn,soit'sagoodideatoput

r,Ididn'tdothatinthissimpleexampleof

removal:

ULONGStatus=0;

ULONGProblemNumber=0;

PNP_VETO_TYPEVetoType=PNP_VetoTypeUnknown;

WCHARVetoNameW[MAX_PATH];

boolbSuccess=fal;

//getdrives'sparent,bridge,

//theSATAport,anIDEchannelwithtwodrives!

DEVINSTDevInstParent=0;

res=CM_Get_Parent(&DevInstParent,DevInst,0);

for(longtries=1;tries>=3;tries++){

//sometimesweneedsometries...

VetoNameW[0]=0;

res=CM_Request_Device_EjectW(DevInstParent,

&VetoType,VetoNameW,MAX_PATH,0);

bSuccess=(res==CR_SUCCESS&&

VetoType==PNP_VetoTypeUnknown);

if(bSuccess){

break;

}

Sleep(500);//requiredtogivethenexttriesachance!

}

It'softenenthattheremovalfailsonthefirstattemptbutworksonthecond

ore,Ijusttryitthreetimes.

WhatMakestheRemovalFail

Theprepartionforsaferemovalfailsaslongasthereisoneopenhandletothedisk

ouryoucannotrunthisEXEfromthedriveto

atyouwouldneedatemporarycopyonanotherdrive.

ProcessExplorerisgreatfordiscoveringwhichprocessholdsanopenhandletoa

trl+Fandenterthedriveletter,likeU:.I'veoftenenthatitcannot

resolvedriveletters,

shouldbesomethinglikeDeviceHarddisk4DP(1)0-0+ficantpart,such

as'disk4,'sion,however,eventhedriver-driven

ProcessExplorerisn'tabletofindthenastyhandle.

TheDemoProject

iresLIBsandheadersfromtheMicrosoft

estversionthatintegratesandworksperfectlywith

'scalledPlatformSDKforWindowsServer2003Build

3780.0andisstillavailablefordownload:

here

Unfortunately,takeitfrom

theVistaPlatformSDKorfromanyDDK/WDKsincebuild2600.

Ifyoudon'twanttodownloadawholeDDKforasinglefilethenyoucanuthe

heReactOSproject,

sfileinthatca.

History

15Jan2007-Updateddownload

27Jan2007-Updatedarticleanddownload,

CM_Query_And_Remove_SubTreeisn'tudanymore

16May2007-Updatedarticleanddownload;removed

SetupDiEnumInterfaceDevicebecauit'sjustadefinefor

SetupDiEnumDeviceInterfaceswhichhasbeencalledsomelinesbefore

7Nov2007-fixedthehintsabouttherequiredSDKforusingVS6

Licen

Thisarticle,alongwithanyassociatedsourcecodeandfiles,islicendunderThe

CodeProjectOpenLicen(CPOL)

本文发布于:2022-11-24 22:50:58,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/14750.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:admitted
下一篇:choose过去分词
标签:by the way
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图