273 lines
9.0 KiB
C++
273 lines
9.0 KiB
C++
// --------------------------------------------------------------------------
|
|
// Module Name: ThemeManagerService.cpp
|
|
//
|
|
// Copyright (c) 2000, Microsoft Corporation
|
|
//
|
|
// This file contains a class that implements the theme server service
|
|
// specifics.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
#include "StandardHeader.h"
|
|
#include "ThemeManagerService.h"
|
|
|
|
#include <lpcthemes.h>
|
|
#include <winsta.h>
|
|
|
|
#include "Access.h"
|
|
#include "StatusCode.h"
|
|
|
|
const TCHAR CThemeManagerService::s_szName[] = TEXT("Themes");
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::CThemeManagerService
|
|
//
|
|
// Arguments: pAPIConnection = CAPIConnection passed to base class.
|
|
// pServerAPI = CServerAPI passed to base class.
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Constructor for CThemeManagerService.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
CThemeManagerService::CThemeManagerService (CAPIConnection *pAPIConnection, CServerAPI *pServerAPI) :
|
|
CService(pAPIConnection, pServerAPI, GetName())
|
|
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::~CThemeManagerService
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: <none>
|
|
//
|
|
// Purpose: Destructor for CThemeManagerService.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
CThemeManagerService::~CThemeManagerService (void)
|
|
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::Signal
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: NTSTATUS
|
|
//
|
|
// Purpose: Used to signal that the service is coming up. Winlogon (via
|
|
// msgina) is listening for this event in its own session. This
|
|
// function queues a request to execute the real work done on a
|
|
// worker thread to prevent blocking the main service thread. If
|
|
// this is not possible then execute the signal inline.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
NTSTATUS CThemeManagerService::Signal (void)
|
|
|
|
{
|
|
if (QueueUserWorkItem(SignalSessionEvents, NULL, WT_EXECUTEDEFAULT) == FALSE)
|
|
{
|
|
(DWORD)SignalSessionEvents(NULL);
|
|
}
|
|
return(STATUS_SUCCESS);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::GetName
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: const TCHAR*
|
|
//
|
|
// Purpose: Returns the name of the service (ThemeService).
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
const TCHAR* CThemeManagerService::GetName (void)
|
|
|
|
{
|
|
return(s_szName);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::OpenStartEvent
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: HANDLE
|
|
//
|
|
// Purpose: Opens or creates the theme service recovery event. This allows
|
|
// a process that has registered for the event to be signaled
|
|
// when the theme server is demand started. Currently only
|
|
// winlogon listens for this event and is required so that it can
|
|
// reestablish a server connection and re-create the session data
|
|
// which holds the hooks for theming.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
HANDLE CThemeManagerService::OpenStartEvent (DWORD dwSessionID, DWORD dwDesiredAccess)
|
|
|
|
{
|
|
HANDLE hEvent;
|
|
NTSTATUS status;
|
|
UNICODE_STRING eventName;
|
|
OBJECT_ATTRIBUTES objectAttributes;
|
|
WCHAR szEventName[64];
|
|
|
|
if (dwSessionID == 0)
|
|
{
|
|
wsprintfW(szEventName, L"\\BaseNamedObjects\\%s", THEMES_START_EVENT_NAME);
|
|
}
|
|
else
|
|
{
|
|
wsprintfW(szEventName, L"\\Sessions\\%d\\BaseNamedObjects\\%s", dwSessionID, THEMES_START_EVENT_NAME);
|
|
}
|
|
RtlInitUnicodeString(&eventName, szEventName);
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&eventName,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
status = NtOpenEvent(&hEvent, dwDesiredAccess, &objectAttributes);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
|
|
// Build a security descriptor for the event that allows:
|
|
// S-1-5-18 NT AUTHORITY\SYSTEM EVENT_ALL_ACCESS
|
|
// S-1-5-32-544 <local administrators> SYNCHRONIZE | READ_CONTROL
|
|
// S-1-1-0 <everyone> SYNCHRONIZE
|
|
|
|
static SID_IDENTIFIER_AUTHORITY s_SecurityNTAuthority = SECURITY_NT_AUTHORITY;
|
|
static SID_IDENTIFIER_AUTHORITY s_SecurityWorldAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|
|
|
static const CSecurityDescriptor::ACCESS_CONTROL s_AccessControl[] =
|
|
{
|
|
{
|
|
&s_SecurityNTAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
EVENT_ALL_ACCESS
|
|
},
|
|
{
|
|
&s_SecurityNTAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
SYNCHRONIZE | READ_CONTROL
|
|
},
|
|
{
|
|
&s_SecurityWorldAuthority,
|
|
1,
|
|
SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
SYNCHRONIZE
|
|
},
|
|
};
|
|
|
|
PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
|
|
|
// Build a security descriptor that allows the described access above.
|
|
|
|
pSecurityDescriptor = CSecurityDescriptor::Create(ARRAYSIZE(s_AccessControl), s_AccessControl);
|
|
|
|
InitializeObjectAttributes(&objectAttributes,
|
|
&eventName,
|
|
0,
|
|
NULL,
|
|
pSecurityDescriptor);
|
|
status = NtCreateEvent(&hEvent,
|
|
EVENT_ALL_ACCESS,
|
|
&objectAttributes,
|
|
NotificationEvent,
|
|
FALSE);
|
|
ReleaseMemory(pSecurityDescriptor);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
hEvent = NULL;
|
|
SetLastError(CStatusCode::ErrorCodeOfStatusCode(status));
|
|
}
|
|
}
|
|
return(hEvent);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------
|
|
// CThemeManagerService::SignalSessionEvents
|
|
//
|
|
// Arguments: <none>
|
|
//
|
|
// Returns: HANDLE
|
|
//
|
|
// Purpose: Opens or creates the theme service recovery event. This allows
|
|
// a process that has registered for the event to be signaled
|
|
// when the theme server is demand started.
|
|
//
|
|
// History: 2000-11-29 vtan created
|
|
// --------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI CThemeManagerService::SignalSessionEvents (void *pParameter)
|
|
|
|
{
|
|
UNREFERENCED_PARAMETER(pParameter);
|
|
|
|
HANDLE hEvent;
|
|
HANDLE hServer;
|
|
|
|
// First try and use terminal server to enumerate the sessions available.
|
|
|
|
hServer = WinStationOpenServerW(reinterpret_cast<WCHAR*>(SERVERNAME_CURRENT));
|
|
if (hServer != NULL)
|
|
{
|
|
ULONG ulEntries;
|
|
PLOGONID pLogonIDs;
|
|
|
|
if (WinStationEnumerate(hServer, &pLogonIDs, &ulEntries))
|
|
{
|
|
ULONG ul;
|
|
PLOGONID pLogonID;
|
|
|
|
for (ul = 0, pLogonID = pLogonIDs; ul < ulEntries; ++ul, ++pLogonID)
|
|
{
|
|
if ((pLogonID->State == State_Active) || (pLogonID->State == State_Connected) || (pLogonID->State == State_Disconnected))
|
|
{
|
|
hEvent = OpenStartEvent(pLogonID->SessionId, EVENT_MODIFY_STATE);
|
|
if (hEvent != NULL)
|
|
{
|
|
TBOOL(SetEvent(hEvent));
|
|
TBOOL(CloseHandle(hEvent));
|
|
}
|
|
}
|
|
}
|
|
(BOOLEAN)WinStationFreeMemory(pLogonIDs);
|
|
}
|
|
(BOOLEAN)WinStationCloseServer(hServer);
|
|
}
|
|
else
|
|
{
|
|
|
|
// If terminal services is not available then assume session 0 only.
|
|
|
|
hEvent = OpenStartEvent(0, EVENT_MODIFY_STATE);
|
|
if (hEvent != NULL)
|
|
{
|
|
TBOOL(SetEvent(hEvent));
|
|
TBOOL(CloseHandle(hEvent));
|
|
}
|
|
}
|
|
return(0);
|
|
}
|
|
|