You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
12 KiB
442 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sclgntfy.cxx
|
|
|
|
Abstract:
|
|
|
|
Notification dll for secondary logon service
|
|
|
|
Author:
|
|
|
|
Praerit Garg (Praeritg)
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#include <windows.h>
|
|
#include <winwlx.h>
|
|
#include <strsafe.h>
|
|
#include "seclogon.h"
|
|
#include <stdio.h>
|
|
|
|
#include "sclgntfy.hxx"
|
|
|
|
//
|
|
// Some helpful tips about winlogon's notify events
|
|
//
|
|
// 1) The logoff and shutdown notifications are always done
|
|
// synchronously regardless of the Asynchronous registry entry.
|
|
//
|
|
// 2) If you need to spawn child processes, you have to use
|
|
// CreateProcessAsUser() otherwise the process will start
|
|
// on winlogon's desktop (not the user's)
|
|
//
|
|
// 3) The logon notification comes before the user's network
|
|
// connections are restored. If you need the user's persisted
|
|
// net connections, use the StartShell event.
|
|
//
|
|
// 4) Don't put any UI up during either screen saver event.
|
|
// These events are intended for background processing only.
|
|
//
|
|
|
|
|
|
HINSTANCE g_hDllInstance=NULL;
|
|
|
|
#define NOTIFY_PATH TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\Notify\\sclgntfy")
|
|
|
|
BOOL
|
|
SlpCreateProcessWithLogon(
|
|
ULONG LogonIdLowPart,
|
|
LONG LogonIdHighPart
|
|
);
|
|
|
|
extern "C" void *__cdecl _alloca(size_t);
|
|
|
|
DWORD SetupLocalRPCSecurity(handle_t hRPCBinding)
|
|
{
|
|
CHAR szDomainName[128];
|
|
CHAR szName[128];
|
|
DWORD cbDomainName;
|
|
DWORD cbName;
|
|
DWORD dwResult;
|
|
PSID pSid = NULL;
|
|
RPC_SECURITY_QOS SecurityQOS;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
SID_NAME_USE SidNameUse;
|
|
|
|
// We're doing LRPC -- we need to get the account name of the service to do mutual auth
|
|
if (!AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSid)) {
|
|
dwResult = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
cbName = sizeof(szName);
|
|
cbDomainName = sizeof(szDomainName);
|
|
if (!LookupAccountSidA(NULL, pSid, szName, &cbName, szDomainName, &cbDomainName, &SidNameUse)) {
|
|
dwResult = GetLastError();
|
|
goto error;
|
|
}
|
|
|
|
// Specify quality of service parameters.
|
|
SecurityQOS.ImpersonationType = RPC_C_IMP_LEVEL_IMPERSONATE; // the server will need to impersonate us
|
|
SecurityQOS.Version = RPC_C_SECURITY_QOS_VERSION;
|
|
SecurityQOS.Capabilities = RPC_C_QOS_CAPABILITIES_MUTUAL_AUTH; // we need mutual auth
|
|
SecurityQOS.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; // calls go to the server under the identity that created the binding handle
|
|
|
|
dwResult = RpcBindingSetAuthInfoExA(hRPCBinding, (unsigned char *)szName, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_AUTHN_WINNT, NULL, 0, &SecurityQOS);
|
|
if (RPC_S_OK != dwResult)
|
|
goto error;
|
|
|
|
dwResult = ERROR_SUCCESS;
|
|
error:
|
|
if (NULL != pSid) {
|
|
FreeSid(pSid);
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SlpCreateProcessWithLogon(
|
|
ULONG LogonIdLowPart,
|
|
LONG LogonIdHighPart
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
|
|
BOOL fOk = FALSE;
|
|
DWORD dwResult;
|
|
LPWSTR pwszBinding = NULL;
|
|
RPC_BINDING_HANDLE hRPCBinding = NULL;
|
|
SECL_BLOB sbNULL = { 0, NULL };
|
|
SECL_SLI sli;
|
|
SECL_SLRI slri;
|
|
SECL_STRING ssNULL = { 0, 0, NULL };
|
|
|
|
ZeroMemory(&sli, sizeof(sli));
|
|
ZeroMemory(&slri, sizeof(slri));
|
|
|
|
__try {
|
|
sli.ulLogonIdLowPart = LogonIdLowPart;
|
|
sli.lLogonIdHighPart = LogonIdHighPart;
|
|
sli.ulProcessId = GetCurrentProcessId();
|
|
sli.ssUsername = ssNULL;
|
|
sli.ssDomain = ssNULL;
|
|
sli.ssPassword = ssNULL;
|
|
sli.ssApplicationName = ssNULL;
|
|
sli.ssCommandLine = ssNULL;
|
|
sli.ulCreationFlags = 0;
|
|
sli.sbEnvironment = sbNULL;
|
|
sli.ssCurrentDirectory = ssNULL;
|
|
sli.ssTitle = ssNULL;
|
|
sli.ssDesktop = ssNULL;
|
|
|
|
// Make the RPC call:
|
|
//
|
|
dwResult = RpcStringBindingCompose
|
|
(NULL,
|
|
(unsigned short *)L"ncalrpc",
|
|
NULL,
|
|
(unsigned short *)wszSeclogonSharedProcEndpointName,
|
|
NULL,
|
|
(unsigned short **)&pwszBinding);
|
|
if (RPC_S_OK != dwResult) { __leave; }
|
|
|
|
dwResult = RpcBindingFromStringBinding((unsigned short *)pwszBinding, &hRPCBinding);
|
|
if (0 != dwResult) { __leave; }
|
|
|
|
dwResult = SetupLocalRPCSecurity(hRPCBinding);
|
|
if (ERROR_SUCCESS != dwResult) { __leave; }
|
|
|
|
__try {
|
|
SeclCreateProcessWithLogonW
|
|
(hRPCBinding,
|
|
&sli,
|
|
&slri);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER) {
|
|
dwResult = RpcExceptionCode();
|
|
}
|
|
if (0 != dwResult) { __leave; }
|
|
|
|
fOk = (slri.ulErrorCode == NO_ERROR); // This function succeeds if the server's function succeeds
|
|
if (!fOk) {
|
|
//
|
|
// If the server function failed, set the server's
|
|
// returned eror code as this thread's error code
|
|
//
|
|
SetLastError(slri.ulErrorCode);
|
|
}
|
|
}
|
|
__finally {
|
|
if (NULL != pwszBinding) { RpcStringFree((unsigned short **)&pwszBinding); }
|
|
if (NULL != hRPCBinding) { RpcBindingFree(&hRPCBinding); }
|
|
}
|
|
return(fOk);
|
|
}
|
|
|
|
|
|
//////////////////////////////// End Of File /////////////////////////////////
|
|
|
|
|
|
BOOL WINAPI DllMain(HANDLE hInstance, ULONG dwReason, LPVOID lpReserved)
|
|
//BOOL WINAPI LibMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
|
|
{
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
{
|
|
// DisableThreadLibraryCalls (hInstance);
|
|
g_hDllInstance = (HINSTANCE)hInstance;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
UNREFERENCED_PARAMETER(lpReserved);
|
|
}
|
|
|
|
//
|
|
// WLEventLogon moved to recovery.cpp
|
|
//
|
|
|
|
|
|
VOID WLEventLogoff (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
TOKEN_STATISTICS TokenStats;
|
|
DWORD ReturnLength;
|
|
LUID LogonId;
|
|
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventLogff.\r\n"));
|
|
|
|
//
|
|
// We are interested in this event.
|
|
//
|
|
|
|
//
|
|
// We will basically call CreateProcessWithLogon
|
|
// in a specially formed message such that secondary logon
|
|
// service can cleanup processes associated with this
|
|
// logon id.
|
|
//
|
|
|
|
if(GetTokenInformation(pInfo->hToken, TokenStatistics,
|
|
(PVOID *)&TokenStats,
|
|
sizeof(TOKEN_STATISTICS),
|
|
&ReturnLength))
|
|
{
|
|
LogonId.HighPart = TokenStats.AuthenticationId.HighPart;
|
|
LogonId.LowPart = TokenStats.AuthenticationId.LowPart;
|
|
|
|
SlpCreateProcessWithLogon(
|
|
LogonId.LowPart,
|
|
LogonId.HighPart
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
VOID WLEventStartup (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventStartup.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventShutdown (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventShutdown.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventStartScreenSaver (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventStartScreenSaver.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventStopScreenSaver (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventStopScreenSaver.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventLock (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventLock.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventUnlock (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventUnlock.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
VOID WLEventStartShell (PWLX_NOTIFICATION_INFO pInfo)
|
|
{
|
|
// OutputDebugString (TEXT("NOTIFY: Entering WLEventStartShell.\r\n"));
|
|
UNREFERENCED_PARAMETER(pInfo);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllRegisterServer - Adds entries to the system registry
|
|
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
HKEY hKey;
|
|
LONG lResult;
|
|
DWORD dwDisp, dwTemp;
|
|
|
|
lResult = RegCreateKeyEx (HKEY_LOCAL_MACHINE, NOTIFY_PATH, 0, NULL,
|
|
REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
|
|
&hKey, &dwDisp);
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
//
|
|
// save the return code for EFS registration
|
|
//
|
|
LONG lEfsResult = DllRegisterServerEFS();
|
|
|
|
lResult = RegSetValueEx (hKey, TEXT("Logoff"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLogoff"),
|
|
(lstrlen(TEXT("WLEventLogoff")) + 1) * sizeof(TCHAR));
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
#if 0
|
|
|
|
RegSetValueEx (hKey, TEXT("Logon"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLogon"),
|
|
(lstrlen(TEXT("WLEventLogon")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("Startup"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartup"),
|
|
(lstrlen(TEXT("WLEventStartup")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("Shutdown"), 0, REG_SZ, (LPBYTE)TEXT("WLEventShutdown"),
|
|
(lstrlen(TEXT("WLEventShutdown")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("StartScreenSaver"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartScreenSaver"),
|
|
(lstrlen(TEXT("WLEventStartScreenSaver")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("StopScreenSaver"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStopScreenSaver"),
|
|
(lstrlen(TEXT("WLEventStopScreenSaver")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("Lock"), 0, REG_SZ, (LPBYTE)TEXT("WLEventLock"),
|
|
(lstrlen(TEXT("WLEventLock")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("Unlock"), 0, REG_SZ, (LPBYTE)TEXT("WLEventUnlock"),
|
|
(lstrlen(TEXT("WLEventUnlock")) + 1) * sizeof(TCHAR));
|
|
|
|
RegSetValueEx (hKey, TEXT("StartShell"), 0, REG_SZ, (LPBYTE)TEXT("WLEventStartShell"),
|
|
(lstrlen(TEXT("WLEventStartShell")) + 1) * sizeof(TCHAR));
|
|
#endif
|
|
|
|
dwTemp = 0;
|
|
lResult = RegSetValueEx (hKey, TEXT("Impersonate"), 0, REG_DWORD, (LPBYTE)&dwTemp, sizeof(dwTemp));
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
dwTemp = 1;
|
|
lResult = RegSetValueEx (hKey, TEXT("Asynchronous"), 0, REG_DWORD, (LPBYTE)&dwTemp, sizeof(dwTemp));
|
|
|
|
if (lResult == ERROR_SUCCESS) {
|
|
|
|
lResult = RegSetValueEx (hKey, TEXT("DllName"), 0, REG_EXPAND_SZ, (LPBYTE)TEXT("sclgntfy.dll"),
|
|
(lstrlen(TEXT("sclgntfy.dll")) + 1) * sizeof(TCHAR));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
RegCloseKey (hKey);
|
|
|
|
//
|
|
// return failure if either seclogon or EFS registration fails.
|
|
//
|
|
if ( lResult == ERROR_SUCCESS ) {
|
|
lResult = lEfsResult;
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// DllUnregisterServer - Removes entries from the system registry
|
|
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
|
|
RegDeleteKey (HKEY_LOCAL_MACHINE, NOTIFY_PATH);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL
|
|
pLoadResourceString(
|
|
IN UINT idMsg,
|
|
OUT LPTSTR lpBuffer,
|
|
IN int nBufferMax,
|
|
IN LPTSTR lpDefault
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( lpBuffer == NULL || lpDefault == NULL ) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if ( g_hDllInstance == NULL ||
|
|
!LoadString (g_hDllInstance,
|
|
idMsg,
|
|
lpBuffer,
|
|
nBufferMax)) {
|
|
|
|
hr = StringCchCopy(lpBuffer, nBufferMax, lpDefault);
|
|
if (FAILED(hr)) {
|
|
SetLastError(hr);
|
|
return FALSE;
|
|
}
|
|
lpBuffer[nBufferMax-1] = L'\0';
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|