windows 7 driver ioctl call - windows

I have written a windows driver for some specific functionality. It works without any issues. However, I am facing issues when invoking it through ioctl interface.
Inside my application, I call CreateFile and try to pass the name which I have given to my driver. However, it gives me an error, "unable to open device" and error code is 0x03. I am using exactly the same name which I have given to my driver.
Name to open the driver from cmd line application: \DosDevice\my_driver
Name passed to CreateFile is also the same.
Is there any way to find what is the name of my driver in windows namespace?

Win 32 error 0x03 is ERROR_PATH_NOT_FOUND. Try adding "\\.\" to the front of you device name. So it becomes "\\.\DosDevice\my_driver", or it could simply be "\\.\my_driver", Just to make that clear that is 2 slashes, a dot, then another slash. This should put you into the device namespace, otherwise i believe that CreateFile is just trying to open a file on the file system.

You can use WinObjEx utility to check if your driver creates a device and what name it has: http://www.freewebs.com/four-f/

Related

Writing a Mini-Filter Device Driver in Windows

I want to implement a Mini-Filter Driver in Windows that does the following:
Whenever a file is open, it needs to print the name of it.
If the name of a file is "testme.txt" then try to find a string "hello" in it. If it is found, then the operation needs to fail, otherwise it should print "testme.txt is clean”.
Can anyone help me to apply these requirements to write a program that fulfills these requirements?

Read / write a file in a shell namespace extension using shell APIs

I've used SHGetDesktopFolder() to get a PIDL and then walked down it's contents using IShellFolder.
I now have a particular PIDL referencing a filesystem location, and I can use BindToStorage and IStorage to .OpenStream() and .Write() a file.
This is all well and good if the interesting things live on the filesystem, but more interesting things live in "Shell Namespace Extensions".
In particular, I have a Pocket PC 2002 device (Specificly, a Symbol PDT8146) that is hooked up to my Windows 7 machine using Windows Mobile Device Center. This application creates a shell namespace folder that I can use from within explorer to read/write files to it.
What I cannot do is write files to it using the command line or win32 APIs.
Following the strategy I outlined above, I can get a PIDL and IShellFolder instance referring to the device, and I can list it's files. However, IShellFolder.BindToStorage() fails with 'No such interface supported' when I try to access IStorage.
Is there another shell interface I should investigate to read/write files on this stubborn device?
Try IShellFolder.BindToObject:
IStream *stream;
if (FAILED(shellfolder->BindToObject (pidl, NULL, IID_IStream, &stream)))
return E_FAIL;
But I'm not sure if this works with writing files as well.

What happens when "file_with_invalid_chars:<?>.txt" is passed to the MFC CFile class?

Note: Needed to edit the title and question, as initially I thought the problem is with ::CreateFile[W] - but it turns out, the error only happens on XP when I use MFC's Cfile class.
I am slightly confused by the behaviour of CFile::Open(...) (on Win7/64bit) when I pass the filename file_with_invalid_chars:<?>.txt to this function to request creation of the file.
On my Windows XP box, the call fails.
On my Win7/64 box, the call succeeds, creating a file named file_with_invalid_chars.
What's happening?
I'm guessing it's creating an alternate data stream. Seems odd that it would fail on XP, though. The documentation says that characters legal for a file name are also legal for a stream name, though I guess that doesn't necessarily mean the inverse is true. Maybe Windows 7 supports < and > in stream names and Windows XP doesn't.
It turns out that this is due to a bugfix(?) in shlwapi.dll -
MFC's CFile class does some internal processing on the filename, and happens to call the PathStripToRoot Function.
This function resides in Shlwapi.dll and Win7 is shipped with a newer version than Windows XP.
The Version in Windows XP apparently does not work correctly with file-paths containing ADS colon separated stream names.
Example:
On XP PathStripToRoot(L"C:\\temp\\file.txt:stream");yields the string C:\temp\file.txt: which is incorrect and leads to an error return from CFile::Open
On Win7, the same call yields the actual root C:\.

How to eject a USB removable disk/volume, similar to the "Eject" function in Windows Explorer?

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.

Some APIs that support the NT namespace absolute path of the format "\Device\Xxx"

In this document,
http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#paths
To make these device objects accessible by Windows applications, the device drivers create a symbolic link (symlink) in the Win32 namespace, "Global??", to their respective device objects. For example, COM0 and COM1 under the "Global??" subdirectory are simply symlinks to Serial0 and Serial1, "C:" is a symlink to HarddiskVolume1, "Physicaldrive0" is a symlink to DR0, and so on. Without a symlink, a specified device "Xxx" will not be available to any Windows application using Win32 namespace conventions as described previously. However, a handle could be opened to that device using any APIs that support the NT namespace absolute path of the format "\Device\Xxx".
What are the APIs? Let me know some such functions please.
For example, we can have a device sitting in the GLOBAL?? namespace:
GLOBAL??\
COM227
This device we can successfully open using CreateFile:
//Note: we have to prefix it with \\.\ in order to tell CreateFile that
//we want to open something from the Global device namespace.
//Otherwise it will try to open a file
HANDLE hdev = CreateFile("\\.\COM227", GENERIC_READ, 0, null, OPEN_EXISTING, 0, 0);
if (hdev == INVALID_HANDLE_VALUE)
raise new EWin32Exception(GetLastError);
This device (along with every other device in the Win32 Global?? namespace), actually a symbolic link to the "real" device:
GLOBAL??\
COM227 (SymbolicLink) ==> \Device\VCP0
Device\
VCP0 (Device)
So we try to open this real device:
HANDLE hdev = CreateFile("\\.\Device\VCP0", GENERIC_READ, 0, null, OPEN_EXISTING, 0, 0);
if (hdev == INVALID_HANDLE_VALUE)
raise new EWin32Exception(GetLastError);
But it fails with error code 3 (The system cannot find the specified file).
Short:
Works: COM227 (which is an alias of \Device\VCP0)
Fails: \Device\VCP0
The problem is that
#paulsm4 says that CreateFile should work
#larryostermm agrees, and even gives the device path syntax (e.g. \Device\Xxx)
except that it doesn't work
Which means that CreateFile is not one of the "APIs that support the NT namespace absolute path format of \Device\Xxx".
However, a handle could be opened to that device using any APIs that support the NT namespace absolute path of the format "\Device\Xxx".
What are the APIs?
The answers provided so far are misleading at best. They do not answer your question or cover the important distinction between the NT namespace and the other namespaces.
When accessing the NT namespace you need to use the API calls that start with Nt, such as NtOpenFile, if you want to access devices that are only found in the NT namespace of the kernel. For example, a device in \Devices with no symbolic link in \GLOBAL??.
The other calls mentioned above work fine if you are accessing the Win32 device namespace but these require the driver to create a symbolic link in that namespace.
If you want to access a device that is only found in the NT namespace then use NtOpenFile. This is really a very old API call and has drifted in and out of the userpace header files. It is available again and works just fine.
Benjamin -
The simple fact is that you CAN open a "special device file" in Windows, very much as you do in *nix. This is what I tried to say in my original reply. I stand by everything I said in my first post. And I believe the MSDN link I referred to there does a very good job of explaining this, too.
The syntax for a *nix device file is "/dev/SOME_DEVICE". Multiple devices are (by convention, not necessity) distinguished as "/dev/SOME_DEVICE0", "/dev/SOME_DEVICE1", etc. Device files can also be "aliased" using *nix "symbolic links".
The syntax for a Windows device file is a UNC name.
I'm sure you're familiar with UNC shares (for example, "\\myserver\c$").
In all the examples we've discussed above, the server happens to be the local host. Hence "\\.\SOME_RESOURCE_NAME".
It's really as simple as that.
And it DOES work.
Please let me know if you have any further questions.
Thank you in advance .. PSM
The concept of treating a "device" as a "file" is common in *nix (Unix, Linux, Mac OS, etc).
Basically, the MSDN article means that any Win32 API that opens a "file" (either a local disk file, or a UNC resource) could just as easily open a "special device".
A couple of examples:
http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
CreateFile
WriteFile
ReadFile
CloseHandle

Resources