jeudi 22 mai 2014

c ++ - CreateFile d'ouvrir un périphérique MS-DOS créé dans une autre session terminale - Stack Overflow


I have a (sort of a filter) driver that should communicate with user-mode components. It creates a device object by calling IoCreateDevice, and then it creates a so-called MS-DOS symbolic link for it by IoCreateSymbolicLink, to make it possible to access it from user-mode code (by CreateFile). This is a standard technique more-or-less. The driver creates a symbolic link of the form \DosDevices\mydevicename, whereas the user-mode code opens a file named \\.\mydevicename.


Now, the problems start when the driver creates a device in the context of a terminal server session. The created symbolic link actually belongs to the local session directory, whereas my user-mode service runs under system account in "zero session", and it "sees" symbolic links that belong to global directory.


It's mentioned in the documentation that usually there's no problem, because drivers mostly create device objects in the context of DriverEntry or AddDevice functions, which are guaranteed to run under system account. But my case is different. And I don't want to change this, what I really need is to be able to create/destroy device objects in the context of arbitrary thread, belonging to any session.


According to the documentation there's a way to solve this. The driver may insist to create a symbolic link belonging to the global directory, by naming it this way: \DosDevices\Global\mydevicename. Moreover, if the user-mode code happens to run under some account, it may also insist to look for the link in the global directory, by naming the file this way: \\.\Global\mydevicename. Though this is not required usually, if the symbol doesn't exist in local directory, it's automatically checked in the global directory.


I've tried this trick: it doesn't work for me. I'm using Windows 2008R2, 64-bit. No success so far. I'm consistently able to open devices created in the system account, but unable to open devices created in another sessions (the error code is "file not found"). I've tried all the combinations and variations of specifying \Global in kernel/user mode - so far the result is the same.


This makes me suspect that there's one more level of symbol isolation. Perhaps using \Global creates a symbolic link that is global session-wide, but still not system-wide.


Does this make sense? Is there a way to create a system-wide symbolic link? Or is there a way to open a file whose symbolic link belongs to another session?


EDIT:


Thanks to @Hans Passant. I've tried WinObj utility to actually see which devices and symbolic links the driver actually creates.


Everything seems ok at the first glance. I see all my devices under \Device directory, and all the symbolic links are under \GLOBAL??. Symbolic links point to correct device names.


One thing is weird however. Trying to see the device properties from within WinObj: for devices created in zero session this works ok, but for devices created in other sessions WinObj responds with an error:



  • Error opening \Device\mydevicename: The system cannot find the file specified.


So, it displays this device object in its list, but OTOH it's "not found" when trying to open it. Very strange. But this explains my problem. But this is really strange.


Any ideas? Thanks in advance.




There is a \Sessions\N\DosDevices\ path, where N is a session number. I didn't try that but it should work.


Also I noticed that subst and network drive mapping create symbolic links in \Sessions\0\DosDevices\ID\, where ID is a session id. So you can check that path too.



I have a (sort of a filter) driver that should communicate with user-mode components. It creates a device object by calling IoCreateDevice, and then it creates a so-called MS-DOS symbolic link for it by IoCreateSymbolicLink, to make it possible to access it from user-mode code (by CreateFile). This is a standard technique more-or-less. The driver creates a symbolic link of the form \DosDevices\mydevicename, whereas the user-mode code opens a file named \\.\mydevicename.


Now, the problems start when the driver creates a device in the context of a terminal server session. The created symbolic link actually belongs to the local session directory, whereas my user-mode service runs under system account in "zero session", and it "sees" symbolic links that belong to global directory.


It's mentioned in the documentation that usually there's no problem, because drivers mostly create device objects in the context of DriverEntry or AddDevice functions, which are guaranteed to run under system account. But my case is different. And I don't want to change this, what I really need is to be able to create/destroy device objects in the context of arbitrary thread, belonging to any session.


According to the documentation there's a way to solve this. The driver may insist to create a symbolic link belonging to the global directory, by naming it this way: \DosDevices\Global\mydevicename. Moreover, if the user-mode code happens to run under some account, it may also insist to look for the link in the global directory, by naming the file this way: \\.\Global\mydevicename. Though this is not required usually, if the symbol doesn't exist in local directory, it's automatically checked in the global directory.


I've tried this trick: it doesn't work for me. I'm using Windows 2008R2, 64-bit. No success so far. I'm consistently able to open devices created in the system account, but unable to open devices created in another sessions (the error code is "file not found"). I've tried all the combinations and variations of specifying \Global in kernel/user mode - so far the result is the same.


This makes me suspect that there's one more level of symbol isolation. Perhaps using \Global creates a symbolic link that is global session-wide, but still not system-wide.


Does this make sense? Is there a way to create a system-wide symbolic link? Or is there a way to open a file whose symbolic link belongs to another session?


EDIT:


Thanks to @Hans Passant. I've tried WinObj utility to actually see which devices and symbolic links the driver actually creates.


Everything seems ok at the first glance. I see all my devices under \Device directory, and all the symbolic links are under \GLOBAL??. Symbolic links point to correct device names.


One thing is weird however. Trying to see the device properties from within WinObj: for devices created in zero session this works ok, but for devices created in other sessions WinObj responds with an error:



  • Error opening \Device\mydevicename: The system cannot find the file specified.


So, it displays this device object in its list, but OTOH it's "not found" when trying to open it. Very strange. But this explains my problem. But this is really strange.


Any ideas? Thanks in advance.



There is a \Sessions\N\DosDevices\ path, where N is a session number. I didn't try that but it should work.


Also I noticed that subst and network drive mapping create symbolic links in \Sessions\0\DosDevices\ID\, where ID is a session id. So you can check that path too.


0 commentaires:

Enregistrer un commentaire