Leaked source code of windows server 2003
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.
 
 
 
 
 
 

622 lines
16 KiB

#include "sacsvr.h"
#include "sacmsg.h"
#define SACSVR_SERVICE_KEY L"System\\CurrentControlSet\\Services\\SacSvr"
#define SACSVR_PARAMETERS_KEY L"System\\CurrentControlSet\\Services\\SacSvr\\Parameters"
#define SVCHOST_LOCATION L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Svchost"
#define SERVICE_NAME L"sacsvr"
#define SERVICE_IMAGEPATH L"%SystemRoot%\\System32\\svchost.exe -k "
#define SERVICE_DLL L"%SystemRoot%\\System32\\sacsvr.dll"
#define SVCHOST_GROUP L"netsvcs"
#define SERVICE_OBJECTNAME L"LocalSystem"
SERVICE_STATUS MyServiceStatus;
SERVICE_STATUS_HANDLE MyServiceStatusHandle;
VOID
MyServiceStart(
DWORD argc,
LPTSTR *argv
);
VOID
MyServiceCtrlHandler(
DWORD opcode
);
DWORD
MyServiceInitialization(
DWORD argc,
LPTSTR *argv,
DWORD *specificError
);
void WINAPI
ServiceMain(
DWORD argc,
LPTSTR *argv
)
{
DWORD status;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
MyServiceStatus.dwServiceType = SERVICE_WIN32;
MyServiceStatus.dwCurrentState = SERVICE_START_PENDING;
MyServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
MyServiceStatus.dwWin32ExitCode = 0;
MyServiceStatus.dwServiceSpecificExitCode = 0;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 3000;
MyServiceStatusHandle = RegisterServiceCtrlHandler(
L"sacsvr",
MyServiceCtrlHandler
);
if (MyServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) {
SvcDebugOut(" [MY_SERVICE] RegisterServiceCtrlHandler failed %d\n", GetLastError());
return;
}
// Initialization complete - report running status.
MyServiceStatus.dwCurrentState = SERVICE_RUNNING;
MyServiceStatus.dwCheckPoint = 0;
MyServiceStatus.dwWaitHint = 0;
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus)) {
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",status);
}
//
// Service specific code goes here
//
Run();
// Service complete - report running status.
MyServiceStatus.dwCurrentState = SERVICE_STOPPED;
if (!SetServiceStatus (MyServiceStatusHandle, &MyServiceStatus)) {
status = GetLastError();
SvcDebugOut(" [MY_SERVICE] SetServiceStatus error %ld\n",status);
}
return;
}
VOID SvcDebugOut(LPSTR String, DWORD Status)
{
#if 0
CHAR Buffer[1024];
if (strlen(String) < 1000) {
sprintf(Buffer, String, Status);
OutputDebugStringA(Buffer);
printf("%s", Buffer);
}
#else
UNREFERENCED_PARAMETER(String);
UNREFERENCED_PARAMETER(Status);
#endif
}
BOOL
pStartService(
IN PCWSTR ServiceName
)
{
SC_HANDLE hSC,hSCService;
BOOL b = FALSE;
//
// Open a handle to the service controller manager
//
hSC = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
if(hSC == NULL) {
return(FALSE);
}
hSCService = OpenService(hSC,ServiceName,SERVICE_START);
if(hSCService) {
b = StartService(hSCService,0,NULL);
if(!b && (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)) {
//
// Service is already running.
//
b = TRUE;
}
}
CloseServiceHandle(hSC);
return(b);
}
BOOL
LoadStringResource(
IN PUNICODE_STRING pUnicodeString,
IN INT MsgId
)
/*++
Routine Description:
This is a simple implementation of LoadString().
Arguments:
usString - Returns the resource string.
MsgId - Supplies the message id of the resource string.
Return Value:
FALSE - Failure.
TRUE - Success.
--*/
{
NTSTATUS Status;
PMESSAGE_RESOURCE_ENTRY MessageEntry;
ANSI_STRING AnsiString;
HANDLE myHandle = 0;
myHandle = GetModuleHandle((LPWSTR)L"sacsvr.dll");
if( !myHandle ) {
return FALSE;
}
Status = RtlFindMessage( myHandle,
(ULONG_PTR) RT_MESSAGETABLE,
0,
(ULONG)MsgId,
&MessageEntry
);
if (!NT_SUCCESS( Status )) {
return FALSE;
}
if (!(MessageEntry->Flags & MESSAGE_RESOURCE_UNICODE)) {
RtlInitAnsiString( &AnsiString, (PCSZ)&MessageEntry->Text[ 0 ] );
Status = RtlAnsiStringToUnicodeString( pUnicodeString, &AnsiString, TRUE );
if (!NT_SUCCESS( Status )) {
return FALSE;
}
} else {
RtlCreateUnicodeString(pUnicodeString, (PWSTR)MessageEntry->Text);
}
return TRUE;
}
STDAPI
DllRegisterServer(
VOID
)
/*++
Routine Description:
Add entries to the system registry.
Arguments:
NONE
Return Value:
S_OK if everything went okay.
--*/
{
UNICODE_STRING UnicodeString = {0};
HKEY hKey = INVALID_HANDLE_VALUE;
PWSTR Data = NULL;
PWSTR p = NULL;
HRESULT ReturnValue = S_OK;
ULONG dw, Size, Type, BufferSize, dwDisposition;
BOOLEAN ServiceAlreadyPresent;
HANDLE Handle = INVALID_HANDLE_VALUE;
NTSTATUS Status;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK StatusBlock;
UINT OldMode;
//
// See if the machine is running headless right now.
//
RtlInitUnicodeString(&UnicodeString,L"\\Device\\SAC");
InitializeObjectAttributes(
&ObjectAttributes,
&UnicodeString,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
Status = NtCreateFile(
&Handle,
FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&StatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
0,
NULL,
0
);
SetErrorMode(OldMode);
CloseHandle(Handle);
if (!NT_SUCCESS(Status)) {
return S_OK;
}
//
// Add our entry into HKLM\Software\Microsoft\Windows NT\CurrentVersion\Svchost\<SVCHOST_GROUP>
//
dw = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
SVCHOST_LOCATION,
0,
KEY_ALL_ACCESS,
&hKey );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
Size = 0;
dw = RegQueryValueEx( hKey,
SVCHOST_GROUP,
NULL,
&Type,
NULL,
&Size );
if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// allocate a new buffer to hold the list + possobly the new
// sacsvr entry (we may not need it)
//
BufferSize = Size + (ULONG)((wcslen(SERVICE_NAME) + 1) * sizeof(WCHAR));
Data = malloc(BufferSize);
if (Data == NULL) {
ReturnValue = E_OUTOFMEMORY;
goto DllRegisterServer_Exit;
}
dw = RegQueryValueEx( hKey,
SVCHOST_GROUP,
NULL,
&Type,
(LPBYTE)Data,
&Size );
if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// Do we need to add our entry?
//
p = Data;
ServiceAlreadyPresent = FALSE;
while( (*p != '\0') && (p < (Data+(Size/sizeof(WCHAR)))) ) {
if( !_wcsicmp( p, SERVICE_NAME ) ) {
ServiceAlreadyPresent = TRUE;
break;
}
p += wcslen(p);
p++;
}
if( !ServiceAlreadyPresent ) {
//
// Jump to the end of our buffer, append our service,
// double-terminate the MULTI_SZ structure, then write
// it all back out.
//
p = Data + (Size/sizeof(WCHAR));
p--;
wcscpy( p, SERVICE_NAME );
p = p + wcslen(SERVICE_NAME);
p++;
*p = L'\0';
dw = RegSetValueEx( hKey,
SVCHOST_GROUP,
0,
Type,
(LPBYTE)Data,
BufferSize );
if( (dw != ERROR_SUCCESS) || (Size == 0) ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
}
free( Data );
Data = NULL;
RegCloseKey( hKey );
hKey = INVALID_HANDLE_VALUE;
//
// Create/populate the sacsvr key under HKLM\System\CCS\Service
//
dw = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
SACSVR_SERVICE_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// Description Value.
//
if( LoadStringResource(&UnicodeString, SERVICE_DESCRIPTION) ) {
//
// Terminate the string at the %0 marker, if it is present
//
if( wcsstr( UnicodeString.Buffer, L"%0" ) ) {
*((PWCHAR)wcsstr( UnicodeString.Buffer, L"%0" )) = L'\0';
}
} else {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
dw = RegSetValueEx( hKey,
L"Description",
0,
REG_SZ,
(LPBYTE)UnicodeString.Buffer,
(ULONG)(wcslen( UnicodeString.Buffer) * sizeof(WCHAR) ));
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// Display Value.
//
if( LoadStringResource(&UnicodeString, SERVICE_DISPLAY_NAME) ) {
//
// Terminate the string at the %0 marker, if it is present
//
if( wcsstr( UnicodeString.Buffer, L"%0" ) ) {
*((PWCHAR)wcsstr( UnicodeString.Buffer, L"%0" )) = L'\0';
}
} else {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
dw = RegSetValueEx( hKey,
L"DisplayName",
0,
REG_SZ,
(LPBYTE)UnicodeString.Buffer,
(ULONG)(wcslen( UnicodeString.Buffer) * sizeof(WCHAR) ));
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// ErrorControl.
//
Size = 1;
dw = RegSetValueEx( hKey,
L"ErrorControl",
0,
REG_DWORD,
(LPBYTE)&Size,
sizeof(DWORD) );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// ImagePath
//
dw = RegSetValueEx( hKey,
L"ImagePath",
0,
REG_EXPAND_SZ,
(LPBYTE)(SERVICE_IMAGEPATH SVCHOST_GROUP),
(ULONG)(wcslen(SERVICE_IMAGEPATH SVCHOST_GROUP) * sizeof(WCHAR) ));
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// ObjectName
//
dw = RegSetValueEx( hKey,
L"ObjectName",
0,
REG_SZ,
(LPBYTE)SERVICE_OBJECTNAME,
(ULONG)(wcslen(SERVICE_OBJECTNAME) * sizeof(WCHAR) ));
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// Start
//
Size = 2;
dw = RegSetValueEx( hKey,
L"Start",
0,
REG_DWORD,
(LPBYTE)&Size,
sizeof(DWORD) );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// Type
//
Size = 32;
dw = RegSetValueEx( hKey,
L"Type",
0,
REG_DWORD,
(LPBYTE)&Size,
sizeof(DWORD) );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
RegCloseKey( hKey );
hKey = INVALID_HANDLE_VALUE;
//
// Create/populate the Parameters key under HKLM\System\CCS\Service\sacsvr
//
dw = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
SACSVR_PARAMETERS_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_WRITE,
NULL,
&hKey,
&dwDisposition );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
//
// ServiceDll
//
dw = RegSetValueEx( hKey,
L"ServiceDll",
0,
REG_EXPAND_SZ,
(LPBYTE)SERVICE_DLL,
(ULONG)(wcslen( SERVICE_DLL) * sizeof(WCHAR) ));
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllRegisterServer_Exit;
}
RegCloseKey( hKey );
hKey = INVALID_HANDLE_VALUE;
//
// Try to start the service.
//
if( !pStartService(SERVICE_NAME) ) {
//
// That's okay.
//
// ReturnValue = E_UNEXPECTED;
// goto DllRegisterServer_Exit;
}
DllRegisterServer_Exit:
if( hKey != INVALID_HANDLE_VALUE ) {
RegCloseKey( hKey );
}
if( Data != NULL ) {
free( Data );
}
return ReturnValue;
}
STDAPI
DllUnregisterServer(
VOID
)
/*++
Routine Description:
Delete entries to the system registry.
Arguments:
NONE
Return Value:
S_OK if everything went okay.
--*/
{
HRESULT ReturnValue = S_OK;
ULONG dw, StartType;
HKEY hKey = INVALID_HANDLE_VALUE;
//
// turn off the sacsvr start value.
//
dw = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
SACSVR_SERVICE_KEY,
0,
KEY_ALL_ACCESS,
&hKey );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllUnRegisterServer_Exit;
}
StartType = 4;
dw = RegSetValueEx( hKey,
L"Start",
0,
REG_DWORD,
(LPBYTE)&StartType,
sizeof(DWORD) );
if( dw != ERROR_SUCCESS ) {
ReturnValue = E_UNEXPECTED;
goto DllUnRegisterServer_Exit;
}
RegCloseKey( hKey );
hKey = INVALID_HANDLE_VALUE;
DllUnRegisterServer_Exit:
if( hKey != INVALID_HANDLE_VALUE ) {
RegCloseKey( hKey );
}
return ReturnValue;
}