I have a tray application that registers with the shell to receive notifications when a drive is added to the system or when media is inserted into a drive (via SHChangeNotifyRegister). Upon receipt of those notifications, I attempt to open the drive to query some properties from it. For my testing I am using a simple USB flash drive. This works fine when I am logged on at the physical console, but if I am logged on via remote desktop then the CreateFile call fails with ERROR_ACCESS_DENIED.
I am calling CreateFile as:
CreateFile(szDrive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0 NULL);
where szDrive is of the form "\\\\.\\G:". After this I make a couple of DeviceIoControl calls.
The strange thing is that I have run Process Monitor on this and in the remote desktop scenario there are NO records of CreateFile on the drive from my tray application. I know my tray app is calling it because I write a log file and I see the CreateFile calls for the log file in the Process Monitor log. It's like it's not even getting far enough to be hooked by Process Monitor.
The machine is Windows 7 with all the default settings (i.e. UAC). My account is a local administrator. In both scenarios (local and remote desktop) I am running my tray app as standard user (i.e. no elevation). However, if I elevate my tray app then the remote desktop scenario is successful in opening the drive.
This could end up being a scenario that we just won't support, but I would still like to know what's going on here. Any ideas?
EDIT 1: After looking at this again, it seems to happen for ALL drives (not just removable ones). The observed behavior is the same: CreateFile failing with ERROR_ACCESS_DENIED and no logs in Process Monitor.
EDIT 2: It seems the remote logon is being denied read access; if I replace GENERIC_READ with 0 then it successfully opens the drive (though the DeviceIoControl calls fail with ERROR_ACCESS_DENIED). I am playing around with WinObj trying to see if I can give the remote logon read access to the drives.
I believe I have found the answer. From a Microsoft white paper about removable storage devices in Vista:
I/O Manager and Removable Media Device ACLs
When the driver stack creates the device object, the I/O manager sets a default ACL that is based on the device type. The default ACL gives Full access to SYSTEM and Administrators, and it gives only Execute access to everyone else.
By default in Windows Vista, the I/O manager grants the IU group Full access for device objects for removable media devices such as CD drives and for those disk device objects that have defined FILE_REMOVABLE_MEDIA characteristics.
Note: In earlier versions of Windows, the entry for IU was not present in the ACL that was set by the I/O manager. The Windows Vistas I/O manager provides Full access to the IU group, so that applications can receive direct access to a volume without requiring elevation of privilege, as discussed earlier. However, UFD devices that do not set the Removable property do not benefit from this because the I/O manager does not treat them as removable.
The disk class driver sets the FILE_REMOVABLE_MEDIA characteristic if the identity data—received from the device in response to the SCSI INQUIRY command—has the Removable property set. Because some UFD devices set this property even though they are not truly removable media, the I/O manager treats such devices as removable disks and provides the IU group Read and Write access to the volume.
By default, the Windows Vista I/O manager gives only Execute access for remotely connected users for removable media device objects (CD devices) and for those disk device objects that have FILE_REMOVABLE_MEDIA characteristics set. Because of this, remote users cannot burn data by using a CD or DVD drive or perform backup to an optical media or format a removable disk. Administrators can set the Removable Storage Access group policy to override the default behavior. When this policy is set, the I/O manager grants Full access to remote user for these devices, allowing read and write capabilities.
So Vista sets ACLs on devices differently for the interactive user vs remote users. I figured it would be something like this.
Related
i'm running a Terminal Server (Windows Server 2012 R2)
And have a big problem accessing smart cards (in my setting German "Gesundheitskarten") on our Terminal Server in RDP Sessions. These cards are not used to provide login to a program, but to transmit data like Insurance Number, Street, Postal Code etc... to our Database.
The Problem is, that the Smart Card reader (https://www.identiv.com/products/smart-card-readers/contact-smart-card-readers/utrust-2700-r-contact-smart-card-reader) which is attached to the Server (via USB) is showing in the device manager but not accessible in an RDP Session. The manufacturers test programm says that the Smart Card Ressource Manager is NOT Running (which isn't true) which indicates the the device is not accessible.
When i logon directly on the server (without RDP) the reader works fine. (Logged in as Admin or User)
I would try to connect the reader to the client device, but there a numerous reasons against it. Just to name a few: We have all sorts of clients (Mac/Android/iOs/Windows) who need access to the reader when they are near our front desk. Mobile Devices and Macs do not support SmartCard redirection. Also the Application which reads the Cards is unknown to support the redirection setup.
(Just for clarification, i don't want to give our users direct physical access to the Server - they use the app via RDP or mainly via Remote Resources)
Is there any way to map/bind the USB Smart Card Reader to a user also in an RDP Session which is connected to the Server? Is there any group policy setting i forgot?
You have to crack WinSCard.dll and SCardSvr.dll.
Refer to this page: http://lifayk.blogspot.co.uk/2012/07/windows-smart-card-subsystem-and-remote.html
I had tested the method and it works on Windows 2012 R2 Standard and Dataceneter.
I need to call WNetGetConnection to get the UNC path and it works good when application run as standard user but it returns 1201(ERROR_CONNECTION_UNAVAIL) error code when application run as admin. According to the documentation its working as expected.
If the network connection was made using the Microsoft LAN Manager
network, and the calling application is running in a different logon
session than the application that made the connection, a call to the
WNetGetConnection function for the associated local device will fail.
The function fails with ERROR_NOT_CONNECTED or
ERROR_CONNECTION_UNAVAIL. This is because a connection made using
Microsoft LAN Manager is visible only to applications running in the
same logon session as the application that made the connection. (To
prevent the call to WNetGetConnection from failing it is not
sufficient for the application to be running in the user account that
created the connection.)
that means its not possible at all to get the UNC path from the app running as admin ? Is there some other way ?
This is by design. Network shares created by a non-elevated account are not visible under elevation, and vice versa.
See this question on Super User for discussion of the issue. There is apparently a registry setting that enables mapped drives to be shared between elevated and non-elevated accounts but I've never tried it myself.
Network connections cannot normally be shared across different Windows login sessions. This is regardless of admin account / elevation level. Each Windows login or impersonation session needs to create its own network connections.
I'm opening a drive directly via CreateFile to get a handle so I can send scsi commands via IOCtl to custom hardware (which presents as a mass storage device) from a windows service.
The problem is that in order to do this my service needs to run as an administrator (or I get access denied errors). In practice this won't be problem under most circumstances (usually we run as Local System) but under some circumstances we run as a domain account so is there a permission I can give to a domain user account to allow access that is a little finer grained than local administrator to get this working?
Device Driver access permissions for domain users in Windows 7 and SPTI/SCSI operations from a Windows 7 application are variants of the same question but don't give that finer grained answer.
I'm writing a Windows device driver for a custom USB device, but am having trouble opening the device from my user program (using CreateFile) when the user program is run as a domain user. If I run as a local user, or as an administrator (or 'Run As' administrator) I can open the driver fine, but as a domain user GetLastError returns 5 (access denied).
I originally had this problem with local users too, and found I had to add the following SDDL entry to the .inf file, which solved the problem for local users:
HKR,,Security,,"D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRGW;;;BU)
From this reference:
http://msdn.microsoft.com/en-us/library/windows/hardware/ff563667(v=vs.85).aspx
When I discovered that domain users did not have access I thought that simply adding them to this SDDL entry would give them access, but it doesn't seem to work: I still get access denied. I've even tried extreme solutions such as giving all users (everyone (WD), unauthenticated users etc.) full access, but this doesn't work either, which makes me think the problem lies elsewhere; i.e. something else is denying domain users access which takes precedent over the permit in the SDDL entry in the driver inf.
So my question is, what am I missing that is required to give domain users (or all users) access to connect to the driver? Or are there any other solutions to this problem (such as connecting to the driver as a service and then accessing this service from the user program)?
HKR,,Security,,"D:P(A;;GA;;;WD)"
set everyone can access, try it!
The title didn't scare you off. Great!
This is what I'm trying to do:
I have a service that at some point in time plays a very important sound. Because it is so important, I make sure that the mixer is ummuted and that the volume is at a proper level at startup.
This works fine when I start the service logged on locally to the computer where it's executing.
However, when I start the service from a remote desktop session it fails to get the volume control if I select "Play on this computer" when logging on.
The obvious solution is "Select 'Play on remote computer' when logging on" but for various usability reasons this is not feasible.
So; the M$ question is: "how can a service launched from remote desktop session set the local mixer main volume if 'Play on this computer' was selected at log on?"
The service runs on WinXP and I use the horrible Mixer* API from C++.
Thanks,
Rickard
The problem is that as an OS service, you can't control the volume for a TS user unless you have code running in the TS user's session. In order to remote audio from the server to the client, the TS service virtualizes all the audio APIs. Those virtualized controls aren't accessible from Windows services.
In order to solve your program, you'll need come code running in the user's session. I might suggest a scheduled task which is triggered on user logon. The task scheduler APIs allow you to create a task which causes a COM object to be created upon user logon. From that COM object, you can communicate with your service and then perform the mute operation on behalf of the user.