CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 23

Hybrid View

  1. #1
    Join Date
    May 2009
    Posts
    15

    Force stop/kill/eject usb mass storage device

    Hi,
    I am writing a security app that would disable or stop or eject a usb mass storage device if its detected. But so far I can only disable or eject it successfully if its not being used, if a file is opened on that storage device, calling the api to eject or disable the device do not work. I know that windows does this to prevent data corruption but what if its more important for security to kill the device than to prevent data corruption. How do i force stop/kill/eject a usb mass storage device ?

    Also in vista, you dont event have to have a file opened on the USB mass storage device, you just need to have it opened in your file explorer and it wont allow you to eject/disable the device.

    thanks,
    Elman

  2. #2
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Force stop/kill/eject usb mass storage device

    I'm pretty certain windows has built in security features in the policies to prevent the use of removable media.


    Simplest case... Give them a zero write quota except for their home drive.

  3. #3
    Join Date
    May 2009
    Posts
    15

    Re: Force stop/kill/eject usb mass storage device

    How do I implement this zero write quota ? Would this effectively prevent access both read/write on the USB mass storage device ?
    as I understand it, this will only limit write access to the mass storage device but still allows read access. Which could be bad especially if you dont want malicious software/virus copied from the removable device and installed on your system.

  4. #4
    Join Date
    May 2009
    Posts
    15

    Re: Force stop/kill/eject usb mass storage device

    Also would this affect already opened devices ?
    I know that setting the group policy to prevent the use of mass storage devices works only as long as the device was not in used when the policy was enforced. But if a device was being used when the policy was applied, a reboot will be necessary or the device will need to be unplugged and replugged for the group policy to be applied.

    So I was wondering if there is a way to force stop/kill/eject a usb mass storage device when its in use. I know when I reboot/shutdown the computer, windows seems to know how to shut down the device and eject it, there must be a way to kill the device short of rebooting windows ?

  5. #5
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Force stop/kill/eject usb mass storage device

    Discussing how to set up and organise security policies in windows isn't really the topic for a programmers forum

    You may want to go check out forums dealing with this very subject... I'd be highly surprised if features to block external devices aren't built into the OS. But I'm not that up to spec with the latest in security

  6. #6
    Join Date
    May 2009
    Posts
    15

    Question Re: Force stop/kill/eject usb mass storage device

    Sorry, I guess I was misunderstood, I do not want to set up and organize windows policy on blocking usb mass storage devices.

    My question is how to programmatically force kill/stop/eject a usb mass storage thats in use in VC++.

    what I have tried:
    - I programmatically disabled the device by changing its state to disabled, unfortunately, if the device is in use, it will change the device state to disabled and return that the change state to disable was successful in the api, however the device will still be functional, a reboot is required for it to be disabled.
    - I programmatically eject the device, the api returns fail if the device is in use
    - I programmatically change the registry to how the group policy OReubens was talking about in order to disallow usb mass storage device. again If the device is in used when I made the change, it will not kill/eject/stop the device. A reboot is required for it to get blocked.
    - I have tried all 3 above together and differing combinations, but no luck


    if anyone has any insight, I just want to force kill a USB mass storage device so that it wont be accessible. The app I have right now only works at blocking USB devices if it hasn't been plugged in yet but if a device is being used, there is no way I can force kill it Any help would be kindly appreciated.

  7. #7
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Force stop/kill/eject usb mass storage device

    Well... things aren't as easy. There's the whole "sharing" thing going on afterall...

    If your VC program is the one and only programm accessing the USB... then ejecting it should be easy enough and you can do that with this.

    If however the USB is accessed by other programs... you cannot safely remove it and windows will not allow you to eject it programmatically. you can manuall yank the usb device out of the port, but that could very well leave the data corrupt, and may crash the other applications.

  8. #8
    Join Date
    May 2009
    Posts
    15

    Re: Force stop/kill/eject usb mass storage device

    Thanks for your thoughts OReubens.
    However I am already using that eject api and another eject api not for scsi devices. Both returns that it could not eject the device since its in used.

    Anyone else have a solution to my problem ?


    how to programmatically force kill/stop/eject a usb mass storage thats in use by other apps ?
    any usb mass storage device guru out there ?
    if not in xp maybe in vista ?

  9. #9
    Join Date
    May 2009
    Posts
    4

    Re: Force stop/kill/eject usb mass storage device

    If you can't find a direct way of doing this you can try the same approach used by unlocker i.e finding which processes have locked the drive and unlocking/killing them.
    Or if you're into reverse engineering try reversing Starforce Nightmare. That program can even disconnect your main hard drive while windows is running Almost screwed my HDD once.

  10. #10
    Join Date
    Jun 2009
    Posts
    7

    Re: Force stop/kill/eject usb mass storage device

    try this code
    you'll have to use WinDDK
    and link to setupapi.lib

    worked for me

    if you want i can send you a link to the project

    USBFixedDiskSafeRemoval.h

    Code:
    // The following ifdef block is the standard way of creating macros which make exporting 
    // from a DLL simpler. All files within this DLL are compiled with the USBFIXEDDISKSAFEREMOVAL_EXPORTS
    // symbol defined on the command line. this symbol should not be defined on any project
    // that uses this DLL. This way any other project whose source files include this file see 
    // USBFIXEDDISKSAFEREMOVAL_API functions as being imported from a DLL, whereas this DLL sees symbols
    // defined with this macro as being exported.
    #ifdef USBFIXEDDISKSAFEREMOVAL_EXPORTS
    #define USBFIXEDDISKSAFEREMOVAL_API __declspec(dllexport)
    #else
    #define USBFIXEDDISKSAFEREMOVAL_API __declspec(dllimport)
    #endif
    
    // This class is exported from the USBFixedDiskSafeRemoval.dll
    class USBFIXEDDISKSAFEREMOVAL_API CUSBFixedDiskSafeRemoval {
    public:
    	CUSBFixedDiskSafeRemoval(void);
    	// TODO: add your methods here.
    };
    
    extern USBFIXEDDISKSAFEREMOVAL_API int nUSBFixedDiskSafeRemoval;
    
    USBFIXEDDISKSAFEREMOVAL_API int fnUSBFixedDiskSafeRemoval(char cDriveLetter);
    USBFixedDiskSafeRemoval.cpp

    Code:
    // USBFixedDiskSafeRemoval.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    #include "USBFixedDiskSafeRemoval.h"
    #include <winioctl.h>
    #include <Setupapi.h>
    #include <stdio.h>
    #include <cfgmgr32.h>
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
    	switch (ul_reason_for_call)
    	{
    	case DLL_PROCESS_ATTACH:
    	case DLL_THREAD_ATTACH:
    	case DLL_THREAD_DETACH:
    	case DLL_PROCESS_DETACH:
    		break;
    	}
        return TRUE;
    }
    
    // This is an example of an exported variable
    USBFIXEDDISKSAFEREMOVAL_API int nUSBFixedDiskSafeRemoval=0;
    
    DEVINST GetDrivesDevInstByDeviceNumber(long DeviceNumber, UINT DriveType, char* szDosDeviceName)
    {
    	bool IsFloppy = (strstr(szDosDeviceName, "\\Floppy") != NULL); // who knows a better way?
    
    	GUID* guid;
    
    	switch (DriveType) {
    	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 0;
    	}
    
    	// 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;
    	long res;
    
    	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 )	{
    		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 ) {
    
    				// in case you are interested in the USB serial number:
    				// the device id string contains the serial number if the device has one,
    				// otherwise a generated id that contains the '&' char...
    				/*
    				DEVINST DevInstParent = 0;
    				CM_Get_Parent(&DevInstParent, spdd.DevInst, 0); 
    				char szDeviceIdString[MAX_PATH];
    				CM_Get_Device_ID(DevInstParent, szDeviceIdString, MAX_PATH, 0);
    				printf("DeviceId=&#37;s\n", szDeviceIdString);
    				*/
    
    				// open the disk or cdrom or floppy
    				HANDLE hDrive = CreateFile(pspdidd->DevicePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    				if ( hDrive != INVALID_HANDLE_VALUE ) {
    					// get its device number
    					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);
    							SetupDiDestroyDeviceInfoList(hDevInfo);
    							return spdd.DevInst;
    						}
    					}
    					CloseHandle(hDrive);
    				}
    			}
    		}
    		dwIndex++;
    	}
    
    	SetupDiDestroyDeviceInfoList(hDevInfo);
    
    	return 0;
    }
    
    // This is an example of an exported function.
    USBFIXEDDISKSAFEREMOVAL_API int fnUSBFixedDiskSafeRemoval(char cDriveLetter)
    {
    	cDriveLetter &= ~0x20; // uppercase
    
    	if ( cDriveLetter < 'A' || cDriveLetter > 'Z' ) {
    		return 1;
    	}
    
    	char szRootPath[] = "X:\\";   // "X:\"  -> for GetDriveType
    	szRootPath[0] = cDriveLetter;
    
    	char szDevicePath[] = "X:";   // "X:"   -> for QueryDosDevice
    	szDevicePath[0] = cDriveLetter;
    
    	char szVolumeAccessPath[] = "\\\\.\\X:";   // "\\.\X:"  -> to open the volume
    	szVolumeAccessPath[4] = cDriveLetter;
    
    	long DeviceNumber = -1;
    
    	// open the storage volume
    	HANDLE hVolume = CreateFile(szVolumeAccessPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
    	if (hVolume == INVALID_HANDLE_VALUE) {
    		return 1;
    	}
    
    	// get the volume's device number
    	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 ) {
    		DeviceNumber = sdn.DeviceNumber;
    	}
    	CloseHandle(hVolume);
    
    	if ( DeviceNumber == -1 ) {
    		return 1;
    	}
    
    	// get the drive type which is required to match the device numbers correctely
    	UINT DriveType = GetDriveType(szRootPath);
    
    	// get the dos device name (like \device\floppy0) to decide if it's a floppy or not - who knows a better way?
    	char szDosDeviceName[MAX_PATH];
    	res = QueryDosDevice(szDevicePath, szDosDeviceName, MAX_PATH);
    	if ( !res ) {
    		return 1;
    	}
    
    	// get the device instance handle of the storage volume by means of a SetupDi enum and matching the device number
    	DEVINST DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, DriveType, szDosDeviceName);
    
    	if ( DevInst == 0 ) {
    		return 1;
    	}
    
    	PNP_VETO_TYPE VetoType = PNP_VetoTypeUnknown; 
    	WCHAR VetoNameW[MAX_PATH];
    	VetoNameW[0] = 0;
    	bool bSuccess = false;
    
    	// get drives's parent, e.g. the USB bridge, the SATA port, an IDE channel with two drives!
    	DEVINST DevInstParent = 0;
    	res = CM_Get_Parent(&DevInstParent, DevInst, 0); 
    
    	for ( long tries=1; tries<=3; tries++ ) { // sometimes we need some tries...
    
    		VetoNameW[0] = 0;
    
    		// CM_Query_And_Remove_SubTree doesn't work for restricted users
    		//res = CM_Query_And_Remove_SubTreeW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, CM_REMOVE_NO_RESTART); // CM_Query_And_Remove_SubTreeA is not implemented under W2K!
    		//res = CM_Query_And_Remove_SubTreeW(DevInstParent, NULL, NULL, 0, CM_REMOVE_NO_RESTART);  // with messagebox (W2K, Vista) or balloon (XP)
    
    		res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
    		//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
    
    		bSuccess = (res==CR_SUCCESS && VetoType==PNP_VetoTypeUnknown);
    		if ( bSuccess )  { 
    			break;
    		}
    
    		Sleep(500); // required to give the next tries a chance!
    	}
    
    	if ( bSuccess ) {
    		printf("Success\n\n");
    		return 1;
    	}
    
    	printf("failed\n");
    
    	printf("Result=0x%2X\n", res);
    
    	if ( VetoNameW[0] ) {
    		printf("VetoName=%ws)\n\n", VetoNameW);
    	}	
    	return 0;
    }
    
    // This is the constructor of a class that has been exported.
    // see USBFixedDiskSafeRemoval.h for the class definition
    CUSBFixedDiskSafeRemoval::CUSBFixedDiskSafeRemoval()
    { 
    	return; 
    }
    "Use The source Luke"

  11. #11
    Join Date
    Apr 2009
    Posts
    4

    Re: Force stop/kill/eject usb mass storage device

    Thanks Karpatuz,

    I executed the code but it does not seem to work. The USB is rejected if no process are running.

    If you open a txt file in notepad from the USB then this will code fail. But I want it to eject even if any file open.

    Regards,
    Vipin

  12. #12
    Join Date
    May 2009
    Posts
    15

    Re: Force stop/kill/eject usb mass storage device

    Karpatuz,
    Sorry been busy with another project.
    From a quick code review I noticed I am using the same api as you, but just in case your code has an option that I missed, I tried it out anyway. Your code only stops a usb device that is not being used ie no file is opened in the usb or no file transfer happening between usb and internal storage.
    As vipink85 pointed out, the code you posted does not work to block/stop/kill/eject a usb mass storage device that is currently being used.

  13. #13
    Join Date
    Jun 2009
    Posts
    4

    Re: Force stop/kill/eject usb mass storage device

    I'm working at a similar project.
    I need to block usb devices .. therefore i have to eject them first.
    I combined a few ideas so far:
    - close open file handles to the devices i want 2 remove.
    - close open processes with a processimagepath pointing to any of the devices. (when running applications directly from the usb device)
    - eject the device with cm_request_device_eject

    it works quite okay so far. but i still have a few problems:
    - excel for example loads a ddl with filemapping structure, so i can't eject with just closing the file handle
    - while copying or deleting files closing the file handle results in a crash

    how did u block usb devices after ejecting them? with the registry value?

  14. #14
    Join Date
    May 2009
    Posts
    15

    Re: Force stop/kill/eject usb mass storage device

    christian_k1984,
    There is a windows group policy that allows you to block USB devices. However it will only block usb devices that are not already inserted or being used. For it to work on usb devices already connected, you will need to reboot
    How did you know which file handles and processes belong to the USB device ?

  15. #15
    Join Date
    Jun 2009
    Posts
    4

    Re: Force stop/kill/eject usb mass storage device

    You can get the handles by inspecting the handle names, but you have to do a few things therefor.
    First of all you have to find out witch of your disks are attached via usb. There are a few examples how to get this done. I use SetupDiEnumDeviceInterfaces. You should get drive names like:
    \Device\Harddisk1\DP(1)0-0+3b

    If you have the drives, you can enumerate all openhandles. (http://forum.sysinternals.com/forum_posts.asp?TID=18892)
    Just compare the handlenames with the list of drives you have. If you find any matching paths, you can get the the process id with handle.ProcessId. At the moment I'm trying to just close the handles. This works for most applications and I'm able to eject the device. But I have problems with explorer (copying / deleting) and excel.
    I think this is by far the best solution for open files.

    I also implemented a function that inspects all running processes and compares the ImagePath of the process with the usb devices to find processes running directly from the usb drives (firefox portable for example)

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured