|
|
Comments and Discussions
|
|
 |

|
I ejected usb using CM_Query_And_Remove_SubTree but the MessageBox is not displaying("Safe to remove"). I am using this method for later i want to re-enable the device. How can i use CM_Query_And_Remove_SubTree method with MessageBox
-- Modified Friday, August 19, 2011 1:25 AM
|
|
|
|

|
hi Uwe: I used the codes you posted and made some necessary changes,but i found out that under WIN7 X64 is not working ,the error message i got is:the "drect memory access controller" device is not removable and can not be ejected or unplugged.why?can you give me a basic direction about why is message appeared?thanks ~ FYI: the device i want to eject is a calculaor.
|
|
|
|

|
It would be very convenient to tell user which processes block safely removal. Sometimes let say Firefox opens some file and disable safely removal.
Btw. I had problems translating your code in Delphi cause lots of functions in setupapi.pas (interface) file are not good mapped. I thought that my code is not working, but actually both code worked excellent and thanks to your sample I found out problems!!
If someone knows if it's possible to map processes that locked files or entire drive I would be very thankful.
Ivan
|
|
|
|

|
Nice explanation with details and analysis
|
|
|
|

|
Very good explanation with references. Several updates to cover gotchas. Working code sample with build instructions.
|
|
|
|

|
Hi Uwe,
thank you for this great article. Digging into the problem of determining if a removable drive is a floppy, I found this thread:
http://www.techtalkz.com/microsoft-device-drivers/244257-how-determine-removable-drive-floppy-drive.html[^]
I'm going to test the IOCTL_DISK_GET_DRIVE_GEOMETRY DeviceIoControl call --
cheers from Italy - Lorenzo -
-- EDIT --
well, seems it works... if you were looking for a better way to detect a floppy, here it is.
works even if floppy drive is empty or media is badly formatted or corrupted --
bool VolumeIsFloppy(HANDLE hVolume)
{
DISK_GEOMETRY geom;
DWORD dwBytesReturned = 0;
long res = DeviceIoControl(hVolume, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof(geom), &dwBytesReturned, NULL);
if ( res )
return ( geom.MediaType != RemovableMedia ) && ( geom.MediaType != FixedMedia );
else
return GetLastError() == ERROR_NOT_READY;
}
modified on Friday, April 1, 2011 6:03 AM
|
|
|
|

|
I have used the above code to remove the PCI drive and found the following errors.
1. If CM_Query_And_Remove_SubTreeW function is used , it returns PNP_VetoOutstandingOpen when tried to remove the device.
2. If CM_Request_Device_EjectW function is used , it returns PNP_VetoIllegalDeviceRequest when tried to remove the device.
Please tell me how to solve these issues
|
|
|
|

|
Very complete; information difficult to derive from MSDN documentation [sic]
|
|
|
|

|
You use CM_Request_Device_Eject to eject the drive, which should logically and physically eject the drive. It physically ejects the drive in XP, but not in Windows 7. The drive cable must be manually removed for the USB device to register a disconnect. How can I send a physical disconnect in Windows 7 to the USB drive?
|
|
|
|

|
Thanks alot for this nice code!!!
But I have a question. Very often something gets corrupted in the system or in one of the programs that uses this USB device and no matter what you do it won't be ejected, CM_Request_Device_Eject returns CR_REMOVE_VETOED.
I'm curious, is there any way to forcefully remove a USB Flash Drive (well, aside from physically yanking it out of the slot), via some kernel API call? Maybe some undocumented one? And if no, is there any way to know what process is holding a reference to this device that it preventing it from being ejected?
|
|
|
|

|
The link given above gives the contents of the cfg.h file on the screen with line numbers in it. Why not just include it along with the .lib file in this download???
|
|
|
|

|
Hey,
Thanks, this is a good article =)
Anthony
|
|
|
|

|
Hello Uwe
You have released some excellent code and it is helping me a lot. I found a difference in your two programs, where RemoveDrive can remove a SATA device, but RemoveDriveByLetter cannot.
Could you please tell me what the difference is between the two programs?
Thank you! I have included the logs below to show what is going on.
D:\RemoveDriveByLetter\Debug>RemoveDriveByLetter.exe f:
failed
Result=0x17
VetoName=PCIIDE\IDEChannel\4&3adfead3&0&0)
C:\RemoveDrive\x64>removedrive f:
RemoveDrive V1.9 (x64) - prepares drives for safe removal
Freeware by Uwe Sieber - www.uwe-sieber.de
Removing Drive 'F:\' (WDC WD7500AACS-65D6B0 ATA Device)
success
|
|
|
|

|
Hi Uwe
This smal sample is a powerful help for my private work. Thanks for sharing it. Checking the other discussions and your home page I found a additional very helpfull tool called DriveCleanup. I my special case it make sense to use both, so do you also share the code of this DriveCleanup tool. Than I'm able to combine it in one software I'm just building for my private use. Will be great.
Greetings from Germany
Raimund
|
|
|
|

|
Hi Uwe,
While discussing an issue related to drive *insertion* sometimes requiring a reboot with a Microsoft support engineer, I was supplied with the following information:
QUOTE
I think the DriveCleanup tool (http://www.uwe-sieber.de/drivetools_e.html ) may have the defect that it doesn't call co-installer to uninstall driver, hence sometimes when re-installing USB storage device, device vetoes removal failed, in the end the installation finished with marking DI_NEEDREBOOT flag.
UNQUOTE
QUOTE
DriverCleanup calls CM_xxx API's to remove device, such as CM_Query_And_Remove_SubTree. This is bad, because CM_XXX API's bypass class/co-installers.
Co-installer sets Flags member of the SP_DEVINSTALL_PARAMS structure for the device with the DI_NEEDREBOOT flag, and the installer also notifies the user that a system restart is required.
The correct method is to invoke DIF_REMOVE, which is shown in Devcon. You may check the codes in WDK(\WinDDK\6001.18002\src\setup\devcon -> cmds.cpp->
RemoveCallback())
UNQUOTE
What do you think?
Grüße;
P.S. I'll share the final word on "why does XP sometimes prompt for a reboot" and how to avoid it.
|
|
|
|

|
Hi there! I've tried to compile Release version of program in Visual Studio 2008, but got link errors:
error LNK2019: unresolved external symbol _GUID_DEVINTERFACE_DISK
error LNK2019: unresolved external symbol _GUID_DEVINTERFACE_FLOPPY
error LNK2019: unresolved external symbol _GUID_DEVINTERFACE_CDROM
Then I've found link on page to download Platform SDK for Windows Server 2003 Build 3780.0 but there is newer version 3790.0. I've downloaded it and installed. But when I've tried to include "Setupapi.h" and connect "Setupapi.lib" from there, I've got the same error. What do I need to do to compile and link without errors?
|
|
|
|

|
Compiling...
RemoveDriveByLetter.cpp
c:\program files\microsoft sdk\include\cfgmgr32.h(122) : error C2146: syntax error : missing ';' before identifier 'LOG_CONF'
c:\program files\microsoft sdk\include\cfgmgr32.h(122) : fatal error C1004: unexpected end of file found
Error executing cl.exe.
Please help me.
Thanks..
SeonBin
|
|
|
|

|
When I click My App in the usb disk,and I create process a new copyed My App in System32 directory.and Use the second process to unplug the usb disk ,but when eject ,it always return false and CM_Request_Device_EjectW returns 0x17.
Now I wonder how to unplug the usb disk in this way .I am eager for your answers.Thanks in advance!
|
|
|
|

|
When using a card reader, is there any programmatic way to eject a card without ejecting the reader itself? If a card is mistakenly enjected, is it possible to remount it without having to physically remove and reinsert it?
I do a lot of development on a piece of hardware that accepts code via MMC card. It is a little irksome to have to visit the "My Computer" window every time I want to move the MMC card from the computer to the device. It would be more handy to include the 'eject' function into the batch file that copies the code.
|
|
|
|

|
Great article! This is the first method I've seen that works properly.
I do have a question though. After reading all the other comments, what is your current recommendation for using Device_Eject vs Remove_SubTree? In some places it seems like you recommend Eject when the device has the DN_REMOVABLE flag, but elsewhere it seems like you might try SubTree first always, and fall back to Eject if you get a CR_ACCESS_DENIED return. What's the best way to go about this choice (how do you handle it in RemoveDrive 1.9)?
|
|
|
|

|
Hi there,
Is there a way to AVOID the standard Windows Pop-Up, when inserting a new USB storage device into a PC?
If I want to handle the interaction programmatically, I prefer the user not to see this popup...
Hope someone can help me,
Thanks
Alex
|
|
|
|

|
Hello,
great function.
But do you have also some code to flush to disk, without remove drive ?
I've found only sync.exe, but no source code.
Jimmy
|
|
|
|

|
when I set the project configuration to Win32 Release then build this project..
I get the link error "LNK2001" as below,
error LNK2001: unresolved external symbol @__security_check_cookie@4
how can I solve this problem? please help me.
thanks,
this project can be built success with Win32 Debug setting.
I use VC6.0 to build it.
|
|
|
|

|
Hello,
Thanks a lot for the excellent code.
I imported the main body of the sample to my remove.dll code. The remove.dll is called from my GINA so that the Windows user can remove USB flash drive within GINA.
This solution works well on XP.
However, in case of W2K, CM_Request_Device_EjectW in remove.dll returns 0x33 (CR_ACCESS_DENIED).
Of course, the remove.dll itself correctly works if it is called from other standard application even though on W2K. It fails only within W2K GINA.
What should be suspected and how to avoid it?
|
|
|
|

|
Hallo Uwe!
Great code, but I don't want to throw out my usb-device. I just want to know if the selected drive is connected by usb or not. So I rewrite your code in one function:
bool IsUsbDevice(TCHAR Letter)
{
TCHAR szDevicePath[3];
_stprintf(szDevicePath,_T("%C:"),Letter);
TCHAR szVolumeAccessPath[8];
_stprintf(szVolumeAccessPath,_T("\\\\.\\%C:"),Letter); // "\\.\X:" -> to open the volume
HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if(hVolume == INVALID_HANDLE_VALUE) return false;
STORAGE_DEVICE_NUMBER sdn;
DWORD dwBytesReturned = 0;
long DeviceNumber = -1;
long res = DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
if(res) DeviceNumber = sdn.DeviceNumber;
CloseHandle(hVolume);
if(DeviceNumber == -1 ) return false;
TCHAR szDosDeviceName[MAX_PATH];
res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
if( !res ) return false;
bool IsFloppy = (_tcsstr(szDosDeviceName, _T("\\Floppy")) != NULL);
GUID* guid;
switch (GetDriveType(szDevicePath)) {
case DRIVE_REMOVABLE:
if ( IsFloppy )
guid = (GUID*)&GUID_DEVINTERFACE_FLOPPY;
else
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_FIXED:
guid = (GUID*)&GUID_DEVINTERFACE_DISK;
break;
case DRIVE_CDROM:
guid = (GUID*)&GUID_DEVINTERFACE_CDROM;
break;
default:
return false;
}
HDEVINFO hDevInfo = SetupDiGetClassDevs(guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) return false;
DWORD dwIndex = 0;
DEVINST DevInst = 0;
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);
memset(szDosDeviceName,0,MAX_PATH * sizeof(TCHAR));
while ( true ) {
res = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, guid, dwIndex, &spdid);
if ( !res ) break;
dwSize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &spdid, NULL, 0, &dwSize, NULL); // check the buffer size
if ( dwSize!=0 && dwSize<=sizeof(Buf) ) {
pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
ZeroMemory(&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, 0, 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 ( DeviceNumber == (long)sdn.DeviceNumber ) { // match the given device number with the one of the current device
CloseHandle(hDrive);
DevInst = spdd.DevInst;
_stprintf(szDosDeviceName,pspdidd->DevicePath);
break;
}
}
CloseHandle(hDrive);
}
}
}
dwIndex++;
}
SetupDiDestroyDeviceInfoList(hDevInfo);
if(DevInst == 0) return false;
if(_tcslen(szDosDeviceName) == 0) return false;
if(_tcsstr(szDosDeviceName,_T("usb")) == NULL) return false;
return true;
}
|
|
|
|
|

|
Hi,
I used the code and it isn't working when i run to remove more the one devices (in win2000), it isn't notifing when the device is removed in wm_devicechange (DBT_DEVICEREMOVECOMPLETE) on winproc. I allocated a array with, example, [d:,e:,f:] (they're pendrive's volume).
for(int i=0;i < 3,i++)
eject(arrayVol[i]);
eject(...) is the function where the code of this article are
sorry about my english.
Please help me
|
|
|
|

|
Hi Uwe,
I came across your article by accident. I am looking for a way to detect "removable" USB drives, since GetDriveType thinks most of them are DRIVE_FIXED.
I found this codeproject article[^] that claims to do just that, but it looks like it doesn't work for normal users (not administrators)
I understand that you are doing something else but I wonder if your code detects USB disks in the process of ejecting them, and if that procedure requires admin privileges or not.
Please be gentle with me because I have no clue about USB or DeviceIOControl
thanks
nikos
|
|
|
|

|
Hi,
I use this project to remove the drive (CD-ROM + Removable, Mass Storage + HID), it always fail:
Dos Device: \Device\CdRom5
Device Inst.: 89c
Removable: No
Type: 8
Name: USB\Vid_abcd&Pid_ec50&Mi_01\6&128aa316&0&1
Type: 8
Name: USB\Vid_abcd&Pid_ec50&Mi_01\6&128aa316&0&1
Type: 8
Name: USB\Vid_abcd&Pid_ec50&Mi_01\6&128aa316&0&1
failed
Result=0x17
VetoName=USB\Vid_abcd&Pid_ec50&Mi_01\6&128aa316&0&1)
But it removes successly with your RemoveDrive 1.2, any difference? What should I do?
Thanks.
Lee
|
|
|
|

|
For my application i need to detect which type of USB device is connected to my USB port...
I know that each device will have Vendor ID & Product IDs..
How to get those information to my application..
Can anyone help me how to proceed..
Thanks in advance
Regards
vijay
|
|
|
|

|
The title of the article says 'Save remoal'. I didn't read it yet, but from the first 2 lines, I guess it should be 'How to prepare an USB drive for safe removal'
//This is not a signature
while (I'm_alive) {
cout<<"I Love Programming";
}
|
|
|
|

|
It is working when my exe is running from other drive.
But when my exe running fromm USB drive it is not working.
So i want work it when Applicastion is running from USB Drive.
|
|
|
|

|
Hi,
i use this code to safely remove a usb hard drive. Work many times really good but sometimes i get the error "6 - The handle is invalid" at the function:
DeviceIoControl(hVolume, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesReturned, NULL);
The drive letter exists and no other process have any open handles. I have checked this with the tool "handle" from sysinternals and i can safely remove the usb-hd via the systray-icon...
Any hints why the volume handle from the CreateFile function is not valid?
thx Micc
|
|
|
|

|
Hello Uwe,
Thank you for your excellent sample source code. I have been searching for the link between drive letter and Device ID for over a year, and you have very clearly explained how to do it. My many thanks.
Firstly, in your download I think there may be a bug where CM_Request_Device_EjectW is called before CM_Query_And_Remove_SubTreeW. However, when I modified the source to use what you have in the HTML, it works perfectly.
Your method of ejecting is a little different to DevCon. When I eject using your code, Windows does not play the sound that normally plays when you unplug a device, but it does with DevCon.
I downloaded the source to DevCon (in the DDK) and found this in the comments:
Callback for use by Remove
Invokes DIF_REMOVE
uses SetupDiCallClassInstaller so cannot be done for remote devices
Don't use CM_xxx API's, they bypass class/co-installers and this is bad.
I wonder if you have any comments? DevCon uses the SetupDiSetClassInstallParams and SetupDiCallClassInstaller API calls.
Thanks again for such helpful code!
Linus
|
|
|
|

|
Hi, your example uses "CM_Query_And_Remove_SubTree" to remove a drive.
I have a requirement of enumerating vendor ID and unique Identity for USB drives.
CM_Query_And_Remove_SubTree uses Query and Remove. How do I Query the USB drive?
Raja Nagulan
|
|
|
|

|
In your article you've explained that CM_Request_Device_EjectW is used for removable usb disks (like dok, ipod, mp3 player etc) and CM_Query_And_Remove_SubTreeW for usb hard disks and local disks.
First i want to ask, does it mean basically that for windows nt/2k/xp i should use CM_Request_Device_EjectW to eject an iPod for example?
The only reason for me to call CM_Query_And_Remove_SubTreeW is when my device is a local drive, right?
But i did some hooking for programs and i can say they do on XP CM_Query_And_Remove_SubTreeW, what does it do then if not ejecting?
I've noticed if this function isn't called, in the safe removal in windows tray, i can still see the volume listing, and if it's called, after i eject it's gone.
Cause for example you know that, if i right click on a device disk in my computer and do eject, it uses DeviceIoControl with IOCTL_STORAGE_EJECT_MEDIA to eject it and not CM_Request_Device_EjectW (although on rare cases i've seen both when CM is the latter to be called).
So tell me if my assumption is correct:
CM_Query_And_Remove_SubTreeW is used when you need to eject a usb hard disk fixed OR after you safely ejected the removable usb device and just want to delete it's device instance from the list (as the name really applies: query and remove sub tree).
Thanks in advance
|
|
|
|

|
'cause Createfile can fail without Admin account support,so How can we do that under a guest account?
Thanks!
|
|
|
|

|
We may face such problems that we have teminated all the applications that have something to do with the USB disk,but when we want to delete it by using "Safely remove the hardware",we still fail.
Maybe there're some apps running in the memory.How could we terminated them?your code seems not work under such situation^-^
|
|
|
|

|
hi
when i was trying to use this exe in Windows 2000 to eject a USB drive i got vetoed by a Win32 application with PNP_VetoWindowsApp. The application is Svchost.exe. Has anyone faced this problem before? if so is there any known solution for this issue?
Any help will be appreciated
Thanks in advance
Sunil M
|
|
|
|

|
Hello,
What is new in this version ?
Do you have a history ?
Jimmy
|
|
|
|

|
Dear friends..! I am using Visual C++..Plz help me to display .jpg image as a face of command button..
K.Selvanathan
|
|
|
|

|
error LNK2001: unresolved external symbol __imp__CM_Request_Device_EjectW@20
|
|
|
|

|
Is there any way to tell the USB drive to flush data without unmounting device?
|
|
|
|

|
char *DriveUSB=(char*)malloc(200);
int drive;
int total;
drive=getdisk();
total=setdisk(drive);
strcpy(DriveUSB,"X:\\");
DriveUSB[0]=(char)(total+'A');
if(GetDriveType(DriveUSB)==DRIVE_REMOVABLE)
{
USB (ON)
}
}
free(DriveUSB);
hi my name is reza `
|
|
|
|

|
Recently, I've compiled this source for use in one of my project, with greate success , so first of all, I would like to thank the author.
In that build, I used Microsoft Platform SDK 2003 SP1 (the compiler was Visual Studio Express 5), and I would like to point out some issues:
1. The include file cfgmgr32.h is a part of that PSDK distribution, so there is no need to find it elsewhere.
2. Some GUID_* constants are missing. To fix that the following lines should be added (in order):
#include <initguid.h>
#include <winioctl.h>
3. The documentation warns that the CM_* functions are obsolete and may not be supported in future version. It suggest converting them into SetupDi* functions. Currently I have made no such changes.
Thanks, Avishay
|
|
|
|

|
After safely removing the device is there any way to mount the device without replugging it
|
|
|
|

|
I would like to know how Device Manager (My Computer->Manage->Device Manager) reports the "Online" or "No Media" status for a removable device? Is there a specific flag beyond DN_REMOVABLE? I was not able to find it. Or does Computer Management simply compute something like:
((PARTITION_INFORMATION_EX *)struc)->PartitionLength.QuadPart==0 ? "No Media" : "Online"
Many thanks by advance for any answer,
Gregoire
-- modified at 15:17 Saturday 22nd July, 2006
|
|
|
|

|
...and the discussion of it. Readers shouldn't be required to download the project(s) to try and make sense as to what is going on.
"The largest fire starts but with the smallest spark." - David Crow
"Judge not by the eye but by the heart." - Native American Proverb
|
|
|
|

|
First, thanks for you. This is very useful for me.
But, I run it under win2000, it would return error code 0x34 (CR_CALL_NOT_IMPLEMENTED).
In the illustration, you say that "Under win2000, we would use unicode version not ansi version".
What means ??
thanks.
Sorena
-- modified at 23:39 Sunday 2nd July, 2006
|
|
|
|

|
Was looking for programmaticaly unmount a usb stick and found your project.
Plug and compile in my application (thanks for the link to cfg.h) and it works .
Thanks,
AbrKen
|
|
|
|

|
Hi, I have run this project with Microsoft Visual Studio 6.0 but there is an error: "can not open file cfgmgr32.h". And I have add this file in project but there is still an error : "can not open file cfg.h". Hope u'll help me, thanks
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
|
Shows the link between a drive letter, its disk number, and the disk's device instance
| Type | Article |
| Licence | CPOL |
| First Posted | 18 Apr 2006 |
| Views | 423,774 |
| Downloads | 5,843 |
| Bookmarked | 266 times |
|
|