If you call SCardEstablishContext API in a Windows service running under a specific user account (domain\user) or NETWORK SERVICE, you may get the following error on Vista/Server 2008 or Windows 7/Server 2008 R2:
0x8010001d - SCARD_E_NO_SERVICE - "The Smart card resource manager is not running.".
If the service runs as SYSTEM, the same code works. If the API is called in a standard desktop application, it works too. Additionally, the same service works fine on Windows XP. Why?
SCardEstablishContext API is returning that error because it gets an Access Denied error when trying to open an event called "Global\Microsoft Smart Card Resource Manager Started" with OpenEvent API. The default security for that event on Vista and Windows 7 specifies that only SYSTEM, LOCAL SERVICE and INTERACTIVE users have access to it. NETWORK SERVICE or non-interactive users won’t be able to access the event.
Enabling "Allow service to interact with desktop" won't help.
When looking for workarounds other than the obvious (use any of the accounts with default access to the event), I found a solution that a colleague of mine applied in a similar case in the past. They used the following code to grant users access to the event:
int _tmain(int argc, _TCHAR* argv)
DWORD result = AddAceToObjectsSecurityDescriptor (
_T("Global\\Microsoft Smart Card Resource Manager Started"),
_tprintf(_T("Result = %d\n"), result);
AddAceToObjectsSecurityDescriptor method can be found here: Modifying the ACLs of an Object in C++. Note I haven’t tried this code myself.
Additionally, this issue didn’t happen on Windows XP because on older OS versions LOCAL accounts had permissions on the event instead of INTERACTIVE accounts like on Vista/Server 2008 or Windows 7/Server 2008 R2.
I hope this helps.
Alex (Alejandro Campos Magencio)
UPDATE!!! Some customers are reporting that the code above returns Access Denied errors when running it with elevated admin accounts, with admin accounts and UAC disabled, and even with System account. But it looks like running it with LOCAL SERVICE works. Actually, I verified with Process Explorer that only LOCAL SERVICE account can modify the event (note that with that tool we can modify the security descriptor of the event too).
Now, we must take into account that the security of the event is set when the smart card service creates the event (see Synchronization Object Security and Access Rights for details). This means that when we restart the machine, we will lose the changes we made to the security descriptor.
So if changing the permissions every time you restart the machine or using one of the default accounts won't work for you, I'm afraid there is nothing we can do at the moment.