I have come across something strange. I'm writing via WriteFile to a file opened on a UNC path to a NAS device. If it runs out of space with a short write, I free up space by deleting other files, then continue writing but it is failing with windows error 6 ERROR_INVALID_HANDLE. If I do the same thing using local drives (hard drives or USB Flash Drives) it works fine.
Does anyone know why the handle becomes invalid?
Is there a type of reset of the handle that is needed in some cases after an error?
TIA!!
Related
I have a PCI driver for a FPGA card that installs and works fine.However, we have a need to clean up our system without rebooting which includes unloading this driver.
When starting again (without rebooting) the driver is re-installed. I have found that when I do this process (install/uninstall) multiple times, on the 5th unload of the driver the directory associated with the device just disappears.
lspci command can no longer find my device because of a bad link. I have to reboot to get the device directory (/sys/bus/pci/devices/00000:04:00.0) to show up again.
With some experimentation and reducing the driver down to the bare minimum I discovered that if I do not do a call to pci_enable_device(..) function in my pci_probe_method, then I am able to install/uninstall the driver multiple times without error.
Of course, I need to call this method before I can do anything with the device but I wanted to be sure it was not some other of the more complex initialization I am doing was causing the problem.
I have verified that my call to pci_disable_device() is being called in the pci_remove_method(). I should be able to enable and disable a PCI device indefinitely, right? Any help in figuring out what is happening would be appreciated.
The actual solution to this problem was to eliminate an extraneous call I had to pci_dev_put(..). I did not notice this before when submitting the question. This was leftover from when this driver was not using the pci_probe() method to discover this device. So, executing this call in the exit routine caused the structure for this device to go away after 5 calls. So for now this problem is solved.
Are there any libraries or Windows API functions that enable writing to the sectors of a CD-R directly? I am able to read sectors from the drive using the ReadFile function provided by the Windows API but using the WriteFile function on the drive seems only to mark the disk as in-use (after executing a program in which WriteFile is used on a CD-R, I am unable to burn files onto the disk or eject it until I restart the system). When I restart the system, there is no data on the disk. Opening the disk drive for write access and calling the WriteFile function with the disk drive handle produces no system errors.
I don't know easy way, but there is a set of SCSI commands, that burning software use.
Under windows you has to get ASPI library to obtain SendASPI32Command Free one and find somewhere a description of Multi-Media Commands. Start from www.t10.org, they sell it, but working draft can be found for free.
and then start there and then look for example of MMC commands using in cdrecord sources.
It can be done but hard though.
Access to the write process is probably restricted to allow compatibility with the drag-and-drop writing that can be done in the Explorer.
You could use an alternative approach and write to an ISO image and then dump that to the CD when it is complete.
Do you know what is the API, or sequence of API calls that windows uses to accomplish the "Eject" function which is available on the shell context menu for removable volumes?
So far I've tried two things:
using CM_Request_Device_Eject, I enumerate the removable disks (using the SetupDiXXX APIs), find the one that I'm interested in, walk the device manager hierarchy (using CM_XXX APIs) and finally call CM_Request_Device_Eject on the devInst of the device I'm interesed in. This works in the sense that it does remove the volumes from My Computer and makes the device "safe to remove" (ready to be removed) but it is not the same as the shell context menu "Eject" function. The way I know this is because the device that I'm trying to eject is supposed to do something when it is ejected and that something is not happening when I do the eject using CM_Request_Device_Eject.
using DeviceIoControl with the IOCTL_STORAGE_EJECT_MEDIA control code. The sequence of events is:
obtain a handle to the volume I'm interested in using CreateFile as suggested in the documentation
try to lock the volume with FSCTL_LOCK_VOLUME
try to dismount it using FSCTL_DISMOUNT_VOLUME
disable the prevent storage media removal using IOCTL_STORAGE_MEDIA_REMOVAL
and finally execute the IOCTL_STORAGE_EJECT_MEDIA function.
This doesn't work at all. Each one of the DeviceIoControl calls fails with ERROR_IVALID_FUNCTION (0x00000001). I don't know why the calls fail. I've verified that other calls to DeviceIoControl work fine for the same file handle (such as IOCTL_STORAGE_GET_DEVICE_NUMBER)
Finally, my development machine is running Windows 7 x64, and in order to get the second method to work I've tried running my application with Administrator privileges and that did not change anything.
EDIT
Eventually, I found out where I was making a mistake with approach #2. It turns out that for some reason I was not setting the desired access correctly when opening the handle to the volume using CreateFile. The correct access mode is GENERIC_READ | GENERIC_WRITE and I was passing 0. After correcting my error I was able to successfully eject the device using DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, as well as with method #1, using CM_Request_Device_Eject.
And it turns out that method #2 is indeed the method used by the shell context menu's "Eject" function. Using this method the device reacts correctly.
Eventually, I found out where I was making a mistake with approach #2.
It turns out that for some reason I was not setting the desired access correctly when opening the handle to the volume using CreateFile.
The correct access mode is GENERIC_READ | GENERIC_WRITE and I was passing 0. After correcting my error I was able to successfully eject the device using DeviceIoControl - IOCTL_STORAGE_EJECT_MEDIA, as well as with method #1, using CM_Request_Device_Eject.
Finally, it turns out that method #2 is indeed the method used by the shell context menu's "Eject" function. Using this method the device reacts correctly.
I came here accidentally while doing a search on "CM_Request_Device_Eject", and saw that it was similar to a solution I'd recently done by pulling together similar pieces of a solution. Forgive the late answer.
I've summarized the steps I've done for this on my project in this SO answer.
I wrote a disk utility that allowed you to erase whole physical drives. it uses the windows file api, calling :
destFile = CreateFile("\\\\.\\PhysicalDrive1",
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,createflags, NULL);
and then just calling WriteFile, and making sure you write in multiples of sectors, i.e. 512 bytes.
this worked fine in the past, on XP, and even on the Win7 RC, all you have to do is make sure you are running it as an administrator.
but now I have retail Win7 professional, it doesn't work anymore! the drives still open fine for writing, but calling WriteFile on the successfully opened Drive now fails!
does anyone know why this might be? could it have something to do with opening it with shared flags? this is always what I have done before, and its worked. could it be that something is now sharing the drive? blocking the writes? is there some way to properly "unmount" a drive, or at least the partitions on it so that I would have exclusive access to it?
some other tools that used to work don't any more either, but some do, like the WD Diagnostic's erase functionality. and after it has erased the drive, my tool then works on it too! leading me to believe there is some "unmount" process I need to be doing to the drive first, to free up permission to write to it.
Any ideas?
Update:
the error code returned from WriteFile is '5', ERROR_ACCESS_DENIED
but again, if I 'erase' the drive first using WD Diag, I can then access and write to the drive fine. when I initialize the drive again, and give it a partition, I go back to getting the ERROR_ACCESS_DENIED error.
This is almost certainly related to preventing the attack found against driver signing by changing sectors in the page file. It will prevent writing to the areas of the disk containing partitions.
See http://msdn.microsoft.com/en-us/library/aa365747%28VS.85%29.aspx and look at the information starting with the text "If you write directly to a volume that has a mounted file system", basically you have to lock the disk's volumes in order to write to their sectors.
My application writes some bytes of data to an alternate data stream. This works fine on all but one machine (Windows Server 2003 SP2).
Instead, CreateFile returns ERROR_DISK_FULL when I try to create an alternate data stream (on the root directory). I don't find the reason for this result, because...
There's plenty of space on that drive.
The drive is NTFS formatted (due to GetVolumeInformation).
The drive supports altenate data
streams (due to GetVolumeInformation).
Edit: I can provide some more information about what the reason not is:
I added many streams on a test system which didn't show the error and wondered if the error might occur. It didn't. Instead after about 2000 Streams with long file names another error occurred and persisted: 1450 (ERROR_NO_SYSTEM_RESOURCES).
EDIT: Here is an example for one of the used file names:
char szStreamFileName[] = "C:\\:abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnoqrstuvwxyz012345";
EDIT: Our customer uses some corporate antivirus software from Avira on this server. Maybe this is the reason (Alternate data streams can be abused by malware).
After opening a support ticket at MS I know that there was a readonly flag set which one only can set (and reset) with undocumented Windows functions. Nobody knows who set this flag and why, but I sent them an image of the drive (after I got the machine from our customer) and so they figured it out. We only have a workaround in our application (We use another location if we detect this error). Meanwhile we know that some of our customers have this problem.
Are there any compressed/spare files or alternate data streams?
Often backup applications receive ERROR_DISK_FULL errors attempting to back up compressed files and this causes quite a bit of confusion when there are still several gigabytes of free space on the drive. Other issues may also occur when copying compressed files. The goal of this blog is to give the reader a more thorough understanding of what really happens when you compress NTFS files.
From Understanding NTFS Compression
Just another possibility...
Did you check the number of currently opend files in your OS?
The OS support max. number of reserved file handles after that report ERROR_DISK_FULL or ERROR_NO_SYSTEM_RESOURCES.
And second possibility...
The root directory is limited by number of files. As I remember 512 files in older versions of OS. But the NTFS support unlimited number of files in root!
You might want to see what something like Sysinternal's Process Monitor utility captures when trying to create this file - it show the return codes of various APIs involved in the I/O stack and one of them might give you a clue as to why 112 is being returned to you. Hopefully the level of detail in ProcMon is enough - if not, I imagine there are other, more detailed I/O trace facilities for Windows (but I don't know of them off the top of my head)
The filename you give is
char szStreamFileName[] = "C:\\:abcdefghijklm...
it starts with
C:\\:
Is that a typo on the post, or is there really a colon after the slash? I think thats a illegal filename.
If you try to copy a file greater than 2GB from another filesystem (NTFS) to FAT / FAT32 which has a 2GB limit you may see this error.
Just a blind shot, but are the rights set properly?