I am working on a simple device driver I want to comunicate with the driver from user-mode using IRP.
I am having trouble opening the device driver. Using DeviceTree I am able to see the device name eg \Device\MyDevice.
But when I try to open it like this :
hand := CreateFile('\Device\MyDevice', GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
I always get INVALID_HANDLE_VALUE and GetLastError is (The System cannot find the path specified)
What I am doing wrong ? I know the driver works because I can see it running and printing stuff in DebugView. So any tips ?
Here is a good explanation by Tim Robinson, MVP (Windows SDK):
Names of the form \Device\xxx are internal NT object manager names which are
inaccessible to Win32. You will only be able to access your device if it
creates a symbolic link to \Device\MyDevice from the \??\ directory. Objects
in the \??\ kernel directory show up through \\.\ in Win32. Use Winobj in
the DDK (or download it from www.sysinternals.com) to check.
NOTE: Nowadays NT namespace root is exposed via GLOBALROOT symbolic link, so any NT path is accessible to Win32 including \Device\xxx: use \\.\GLOBALROOT\Device\xxx. A device symlink is not required in such case.
Related
I am writing a USB driver to a product which is basically a USB pen drive. Upon connecting the product to the usb port, I want to see the drive name/volume name as "XXXX Corporation". I see that by default it always gets shown as "Removable Disk" in Windows explorer or my computer.
If I use any USB detail reader tools available in the net, then I can see the vendor id and manufacturer ids and other usb details. Renaming the drive from windows works but I want this to happen by default without asking the end user to rename. Having autorun.inf in root of the drive works only on WindowsXP.
How do I get this? Are there any descriptors which needs to be coded explicitly in my usb drivers stack? There are already API's to obtain the manufacturer/Product/Serial descriptors in my usb drivers stack.
Thanks in advance.
Chandra
The name shown in file explorers is the filesystem label, it's not a USB descriptor. The tool you are using to create the filesystem (whether FAT or NTFS) probably allows you to set the label. It can also be changed on an existing filesystem. The label can also be read on any operating system.
The label entry of the autorun.inf file should also be read by modern Windows. Some Linux file explorers (Gnome's Nautilus) might use it if it's there, but the cross-platform way is the filesystem label.
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.
I would really really appreciate some help with winUSB.
I followed all the steps that were listed in msdn website
http://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx
I tried to run it on Windows 7 with Visual Studio 2010. Even though it compiles with no errors, I cannot pass the function
SetupDiEnumDeviceInfo, and it errors out (I think error #259).
I don't know how to pass this error.
However I am not sure of the few steps in the process:
What does msdn talk about with "A signed catalog file for the package. This file is required to install WinUSB on x64 versions"? What is a signed catalog package? How do I set this?
It also talks about making some directory (For example, c:\UsbDevice) to put the .inf file in there ! But how does my VS project know that I am pointing to c:\UsbDevice, and how does it know what the name of the ".inf' file should be? what should I call the .inf file? And how to point the project to it?
Inside the .inf file there are two GUID numbers. I can get the Class GUID number by going to the Device Manager. But how do I set the Device Interface GUID?
Please help.
Is is possible that the error that I am getting is because I don't have one of the following items set up correctly?
Thanks,
--Rudy
I developed an application about 2 years ago that I needed to use WinUSB, it's not fresh in my mind but looking at my code now I can see that I did use this function: SetupDiEnumDeviceInfo, but as I remember it wasn't a problem for me.
As you probably know, the WinUSB is an API of Windows for you to communicate with an usb hardware. The hardware must have it's driver already, so, you have to know the GUID of your device
Answering your steps:
1. Signed catalog is the .cat file generated from an inf, you can genarate it using inf2cat.exe, it's somwhere in your machine. This is just a step for signing your winusb driver. To sign it you will need to submit your .inf and the .cat files for the WHQL (windows hardware quality labs) http://www.microsoft.com/whdc/whql/ , this is not important at this moment, I've never signed my WinUSB driver, and it works in the x64 machines with a inelegant warning saying that my WinUSB driver might be dangerous (despite it's not!)
2. The application you are developing doens't need to know where the .inf file is, the .inf file is meant to install the WinUSB driver, the application will communicate with the driver trough the GUID number of the device after the driver is properly installed. Here is part of the code that is necessary to connect to the device after the WinUSB driver is correctly installed.
LPGUID _lpGuid = (LPGUID) malloc (sizeof(GUID));
HRESULT result = CLSIDFromString (L"{A54E04AD-E06A-4A03-95BB-25AACC4E6CCA}", _lpGuid);
...
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
_lpGuid,
0,
&interfaceData); //If the function succeeds
//the return value is nonzero.
// [1]
deviceInfo = SetupDiGetClassDevs(_lpGuid,
NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfo == INVALID_HANDLE_VALUE)
{
//lblDispStatus->Caption = "Erro 1 - deviceInfo";
return false;
}
// [2]
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
_lpGuid,
0,
&interfaceData); //If the function succeeds
//the return value is nonzero.
InterfaceData is passed as reference, so you will have the ability to call the next function, that is SetupDiGetDeviceInterfaceDetail
3.Who developed the driver? He must know the GUIDs you need.
All I know from WinUSB I fount at the poor WinUSB documentation, you will need tons of patiante to read all their messy information. And for your unlucky, it's not fresh in my mind right know, I would have to take a deep look at this subject to help you more.
This page seems important at the point you are, take a look at this: http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174%28v=vs.85%29.aspx
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/
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