After being called, Run first stores the service's thread ID. The service will use this ID to close itself by sending a WM_QUIT message using the Win32 API function, PostThreadMessage.
Run then calls the Win32 API function, CoInitializeEx. By default, Run passes the COINIT_MULTITHREADED flag to the function. This flag indicates that the program is to be a free-threaded server.
Now you can specify security using CSecurityDescriptor. This class greatly simplifies the task of setting up and making changes to the discretionary access-control list (DACL) — a list of access-control entries (ACEs), where each ACE defines access to a Win32 object.
By default, the ATL COM AppWizard generates a call to the InitializeFromThreadToken member function of CSecurityDescriptor. This initializes the object's security descriptor to a null DACL, which means that any user has access to your object.
The easiest way to change user access is with the Deny and Allow member functions of CSecurityDescriptor. These functions add an ACE to the existing DACL. However, Deny always takes priority since Deny adds the ACE to the beginning of the DACL, while Allow adds it to the end. Both Deny and Allow pass the user name as the first parameter and the access rights (typically, COM_RIGHTS_EXECUTE) as the second.
Recall that the null DACL created by InitializeFromThreadToken grants all users access to the COM object. However, as soon as you call Allow to add an ACE, only that specified user will have access. The following code shows a call to Allow:
CSecurityDescriptor sd;
sd.InitializeFromThreadToken( );
if (bAllowOneUser)
{
sd.Allow("MYDOMAIN\\myuser", COM_RIGHTS_EXECUTE);
}
CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL, EOAC_NONE, NULL);
If the variable, bAllowOneUser
, is TRUE, then only the one specified user has access because only that user's ACE is in the DACL. If bAllowOneUser
is FALSE, then all users have access because the DACL is null.
If you do not want the service to specify its own security, remove the call to the Win32 API function, CoInitializeSecurity, and COM will then determine the security settings from the registry. A convenient way to configure registry settings is with the DCOMCNFG utility discussed later in this article.
Once security is specified, the object is registered with COM so that new clients can connect to the program. Finally, the program tells the SCM that it is running and the program enters a message loop. The program remains running until it posts a quit message upon service shutdown.
For more information about Windows NT security, see the MSDN article, "Windows NT Security in Theory and Practice."