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.
 
 
 
 
 
 

407 lines
13 KiB

/*
Copyright (c) Microsoft Corporation
*/
/*
This is not really how things should be done.
Write an .inf. I need to learn how.
*/
#include <stdio.h>
#include <stdarg.h>
#include "nt.h"
#include "ntrtl.h"
#include "nturtl.h"
#include "windows.h"
#include "delayimp.h"
#include "strsafe.h"
#include "sxsvc1.h"
#include "resource.h"
#define USE_CREATESERVICE 1
#define COPY_FROM_FILE_TO_SYSTEM32 0
#define COPY_FROM_RESOURCE_TO_SYSTEM32 1
#define SERVICE_NAME L"sxsvc1"
extern const WCHAR ServiceName[] = SERVICE_NAME L"\0"; // extra nul terminal for REG_MULTI_SZ
typedef struct _REGISTRY_VALUE {
DWORD Type;
PCWSTR Name;
union {
PCWSTR String;
DWORD Dword;
} Value;
} REGISTRY_VALUE;
extern const WCHAR DescriptionValue[] = L"This is an example sidebyside installed service.";
extern const WCHAR DisplayNameValue[] = L"This is the display name.";
#define StartTypeValue SERVICE_AUTO_START
#define ServiceTypeValue SERVICE_WIN32_OWN_PROCESS /* SERVICE_WIN32_OWN_PROCESS, SERVICE_WIN32_SHARE_PROCESS */
#define ErrorControlValue SERVICE_ERROR_NORMAL
extern const WCHAR ImagePathValue[] = L"%SystemRoot%\\System32\\svchost.exe -k " SERVICE_NAME;
#if !USE_CREATESERVICE
extern const REGISTRY_VALUE RegistryValues1[] =
{
{ REG_SZ, L"Description", DescriptionValue },
{ REG_SZ, L"DisplayName", DisplayNameValue },
{ REG_EXPAND_SZ, L"ImagePath", ImagePathValue },
{ REG_DWORD, L"Start", (PCWSTR)(ULONG_PTR)StartTypeValue },
{ REG_DWORD, L"Type", (PCWSTR)(ULONG_PTR)ServiceTypeValue },
{ REG_DWORD, L"ErrorControl", (PCWSTR)(ULONG_PTR)ErrorControlValue }
};
#endif
const REGISTRY_VALUE RegistryValues2[] =
{
{ REG_EXPAND_SZ, L"ServiceManifest", L"%SystemRoot%\\System32\\" SERVICE_NAME L".manifest" },
{ REG_EXPAND_SZ, L"ServiceDll", SERVICE_NAME L".dll" },
};
LONG
SetRegistryValues(
HKEY RegistryKeyHandle,
const REGISTRY_VALUE * RegistryValues,
SIZE_T NumberOfRegistryValues
)
{
LONG RegResult = ERROR_SUCCESS;
SIZE_T i;
for (i = 0 ; i != NumberOfRegistryValues ; ++i)
{
const REGISTRY_VALUE * RegistryValue = &RegistryValues[i];
DWORD Size = 0;
const BYTE * Data = 0;
switch (RegistryValue->Type)
{
case REG_DWORD:
Size = sizeof(RegistryValue->Value.Dword);
Data = (const BYTE *)&RegistryValue->Value.Dword;
break;
case REG_SZ:
case REG_EXPAND_SZ:
Size = (wcslen(RegistryValue->Value.String) + 1) * sizeof(WCHAR);
Data = (const BYTE *)RegistryValue->Value.String;
break;
}
RegResult = RegSetValueExW(RegistryKeyHandle, RegistryValue->Name, 0, RegistryValue->Type, Data, Size);
if (RegResult != ERROR_SUCCESS)
goto RegExit;
}
RegExit:
return RegResult;
}
STDAPI DllRegisterServer(void) { return NOERROR; }
STDAPI DllUnregisterServer(void) { return NOERROR; }
STDAPI
DllInstall(
BOOL fInstall,
LPCWSTR pszCmdLine
)
{
const static WCHAR s1[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost";
const static WCHAR s2[] = L"System\\CurrentControlSet\\Services\\" SERVICE_NAME;
HANDLE ServiceControlManager = 0;
HANDLE ServiceHandle = 0;
HKEY RegistryHandles[4] = { 0 };
DWORD Disposition = 0;
LONG RegResult = ERROR_SUCCESS;
SIZE_T i = 0;
PWSTR InstallManifestFrom1 = 0;
PWSTR InstallManifestFrom2 = 0;
PWSTR InstallManifestFrom = 0;
PWSTR InstallManifestTo = 0;
HRSRC ResourceHandle = 0;
HMODULE MyModule = 0;
HGLOBAL GlobalResourceHandle = 0;
PVOID PointerToResource = 0;
DWORD ResourceSize = 0;
DWORD BytesWritten = 0;
HANDLE FileHandle = 0;
DWORD Retried = 0;
if (!fInstall)
{
return NOERROR;
}
InstallManifestFrom1 = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
InstallManifestFrom2 = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
InstallManifestTo = (PWSTR)MemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (InstallManifestFrom1 == NULL
|| InstallManifestFrom2 == NULL
|| InstallManifestTo == NULL
)
{
goto OutOfMemory;
}
InstallManifestFrom1[0] = 0;
InstallManifestFrom2[0] = 0;
ServiceControlManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (ServiceControlManager == NULL || ServiceControlManager == INVALID_HANDLE_VALUE)
{
DbgPrint("OpenSCManager failed 0x%lx\n", (ULONG)GetLastError());
goto LastErrorExit;
}
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s1, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[0], &Disposition);
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
RegResult = RegCreateKeyExW(RegistryHandles[0], ServiceName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[1], &Disposition);
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
//
// In reality this needs to append to the possibly preexisting REG_MULTI_SZE.
//
RegResult = RegSetValueExW(RegistryHandles[0], ServiceName, 0, REG_MULTI_SZ, (const BYTE*)&ServiceName, sizeof(ServiceName));
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("RegSetValueExW failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
#if !USE_CREATESERVICE
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[2], &Disposition);
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
RegResult = SetRegistryValues(RegistryHandles[2], RegistryValues1, NUMBER_OF(RegistryValues1));
if (RegResult != ERROR_SUCCESS)
goto RegExit;
#else
//
// First stop and delete the service.
//
ServiceHandle =
OpenServiceW(
ServiceControlManager,
ServiceName,
GENERIC_ALL
);
if (ServiceHandle != NULL && ServiceHandle != INVALID_HANDLE_VALUE)
{
SERVICE_STATUS ServiceStatus;
ControlService(ServiceHandle, SERVICE_STOP, &ServiceStatus);
if (!DeleteService(ServiceHandle))
{
DWORD Error = GetLastError();
if (Error != ERROR_SERVICE_MARKED_FOR_DELETE
&& Error != ERROR_KEY_DELETED
)
{
DbgPrint("sxsvc1: DeleteService failed 0x%lx\n", (ULONG)Error);
goto LastErrorExit;
}
}
CloseServiceHandle(ServiceHandle);
ServiceHandle = NULL;
//
// close and reopen to avoid use-after-delete / use-while-delete-pending errors (0x430/0x3fa) ?
//
CloseServiceHandle(ServiceControlManager);
ServiceControlManager = NULL;
ServiceControlManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (ServiceControlManager == NULL || ServiceControlManager == INVALID_HANDLE_VALUE)
{
DbgPrint("OpenSCManager failed 0x%lx\n", (ULONG)GetLastError());
goto LastErrorExit;
}
}
RetryCreate:
ServiceHandle =
CreateServiceW(
ServiceControlManager,
ServiceName,
DisplayNameValue,
GENERIC_ALL,
ServiceTypeValue,
StartTypeValue,
ErrorControlValue,
ImagePathValue,
NULL,
NULL,
NULL,
NULL,
NULL
);
if (ServiceHandle == NULL || ServiceHandle == INVALID_HANDLE_VALUE)
{
if ((Retried & 1) == 0 && GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE)
{
Sleep(500);
Retried |= 1;
goto RetryCreate;
}
DbgPrint("sxsvc1: CreateService failed 0x%lx\n", (ULONG)GetLastError());
goto LastErrorExit;
}
#endif
#if USE_CREATESERVICE
//
// close and reopen to avoid use-after-delete / use-while-delete-pending errors (0x430/0x3fa) ?
//
if (RegistryHandles[2] != NULL)
{
RegCloseKey(RegistryHandles[2]);
RegistryHandles[2] = NULL;
}
RegResult = RegCreateKeyExW(HKEY_LOCAL_MACHINE, s2, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[2], &Disposition);
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("RegCreateKeyExW failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
#endif
// But need to put in the svchost parameters ourselves.
RegResult = RegCreateKeyExW(RegistryHandles[2], L"Parameters", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &RegistryHandles[3], &Disposition);
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("sxsvc1: RegCreateKeyExW(Parameters) failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
RegResult = SetRegistryValues(RegistryHandles[3], RegistryValues2, NUMBER_OF(RegistryValues2));
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("sxsvc1: SetRegistryValues(3) failed 0x%lx\n", (ULONG)RegResult);
goto RegExit;
}
#if COPY_FROM_FILE_TO_SYSTEM32
InstallManifestFrom1[0] = 0;
InstallManifestFrom2[0] = 0;
GetMyFullPathW(InstallManifestFrom1, MAX_PATH);
CopyMemory(InstallManifestFrom2, InstallManifestFrom1, (wcslen(InstallManifestFrom1) + 1) * sizeof(WCHAR));
RegResult = ERROR_BUFFER_OVERFLOW;
if (!ChangePathExtensionW(InstallManifestFrom1, MAX_PATH, L".man"))
goto RegExit;
if (!ChangePathExtensionW(InstallManifestFrom2, MAX_PATH, L".manifest"))
goto RegExit;
if (GetFileAttributesW(InstallManifestFrom1) != 0xFFFFFFFF)
{
InstallManifestFrom = InstallManifestFrom1;
}
else if (GetFileAttributesW(InstallManifestFrom2) != 0xFFFFFFFF)
{
InstallManifestFrom = InstallManifestFrom2;
}
else
{
goto LastErrorExit;
}
#endif
#if COPY_FROM_FILE_TO_SYSTEM32 || COPY_FROM_RESOURCE_TO_SYSTEM32
InstallManifestTo[0] = 0;
if (ExpandEnvironmentStringsW(RegistryValues2[0].Value.String, InstallManifestTo, MAX_PATH) == 0)
{
goto LastErrorExit;
}
#endif
#if COPY_FROM_FILE_TO_SYSTEM32
if (!CopyFileW(InstallManifestFrom, InstallManifestTo, FALSE))
{
goto LastErrorExit;
}
#endif
#if COPY_FROM_RESOURCE_TO_SYSTEM32
ResourceHandle = FindResourceW(MyModule = GetMyModule(), MAKEINTRESOURCEW(SYSTEM32_MANIFEST_ID), MAKEINTRESOURCEW(RT_MANIFEST));
if (ResourceHandle == NULL)
{
goto LastErrorExit;
}
GlobalResourceHandle = LoadResource(MyModule, ResourceHandle);
if (GlobalResourceHandle == NULL)
{
goto LastErrorExit;
}
PointerToResource = LockResource(GlobalResourceHandle);
if (PointerToResource == NULL)
{
goto LastErrorExit;
}
ResourceSize = SizeofResource(MyModule, ResourceHandle);
if (ResourceSize == 0)
{
goto LastErrorExit;
}
FileHandle = CreateFileW(InstallManifestTo, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (FileHandle == INVALID_HANDLE_VALUE)
{
goto LastErrorExit;
}
if (!WriteFile(FileHandle, PointerToResource, ResourceSize, &BytesWritten, NULL))
{
goto LastErrorExit;
}
CloseHandle(FileHandle);
FileHandle = NULL;
#endif
RegResult = ERROR_SUCCESS;
RegExit:
#if DBG
if (RegResult != ERROR_SUCCESS)
{
DbgPrint("%ls:%s: Registry Error 0x%lx\n", ServiceName, __FUNCTION__, RegResult);
}
#endif
if (ServiceHandle != NULL)
{
CloseServiceHandle(ServiceHandle);
}
if (ServiceControlManager != NULL)
{
CloseServiceHandle(ServiceControlManager);
}
for (i = 0 ; i != NUMBER_OF(RegistryHandles) ; ++i )
{
if (RegistryHandles[i] != NULL)
{
RegCloseKey(RegistryHandles[i]);
}
}
if (FileHandle != NULL || FileHandle != INVALID_HANDLE_VALUE)
{
CloseHandle(FileHandle);
}
MemFree(InstallManifestFrom1);
MemFree(InstallManifestFrom2);
MemFree(InstallManifestTo);
if (RegResult == ERROR_SUCCESS)
{
return NOERROR;
}
else
{
return HRESULT_FROM_WIN32(RegResult);
}
LastErrorExit:
RegResult = GetLastError();
goto RegExit;
OutOfMemory:
RegResult = ERROR_OUTOFMEMORY;
goto RegExit;
}