mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[SVCHOST]: Implement a Windows-compatible (5.2 SP1) SvcHost.exe process, which can load Windows services according to the information at http://www.geoffchappell.com/studies/windows/win32/services/svchost/index.htm, using the same callbacks and registry settings, including support for RPC over NPIPE, NetBIOS and COM, with correct handling of Security, Threading, Locking and Stop Callbacks. Tested with the current BITS and DHCP services, which still work (although they don't take advantage of the new functionality).
svn path=/trunk/; revision=59847
This commit is contained in:
parent
bbf30d28f7
commit
3acd542293
8 changed files with 2589 additions and 283 deletions
|
@ -1,6 +1,7 @@
|
|||
|
||||
add_executable(svchost svchost.c svchost.rc)
|
||||
add_executable(svchost globals.c registry.c security.cxx rpcsrv.c netbios.c svchost.c svchost.rc)
|
||||
|
||||
target_link_libraries(svchost uuid)
|
||||
set_module_type(svchost win32cui UNICODE)
|
||||
add_importlibs(svchost advapi32 msvcrt kernel32 ntdll)
|
||||
add_importlibs(svchost advapi32 netapi32 rpcrt4 ole32 kernel32 ntdll)
|
||||
add_cd_file(TARGET svchost DESTINATION reactos/system32 FOR all)
|
||||
|
|
299
reactos/base/services/svchost/globals.c
Normal file
299
reactos/base/services/svchost/globals.c
Normal file
|
@ -0,0 +1,299 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/globals.c
|
||||
* PURPOSE: Functions to initialize global settings and support
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "svchost.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
PSID NullSid, WorldSid, LocalSid, NetworkSid, InteractiveSid, ServiceLogonSid;
|
||||
PSID LocalSystemSid, LocalServiceSid, NetworkServiceSid, BuiltinDomainSid;
|
||||
PSID AuthenticatedUserSid, AnonymousLogonSid, AliasAdminsSid, AliasUsersSid;
|
||||
PSID AliasGuestsSid, AliasPowerUsersSid, AliasAccountOpsSid, AliasSystemOpsSid;
|
||||
PSID AliasPrintOpsSid;
|
||||
PSID AliasBackupOpsSid;
|
||||
|
||||
SID_DATA SidData[12] =
|
||||
{
|
||||
{ &NullSid, { SECURITY_NULL_SID_AUTHORITY }, SECURITY_NULL_RID },
|
||||
{ &WorldSid, { SECURITY_WORLD_SID_AUTHORITY }, SECURITY_WORLD_RID },
|
||||
{ &LocalSid, { SECURITY_LOCAL_SID_AUTHORITY }, SECURITY_LOCAL_RID },
|
||||
{ &NetworkSid, { SECURITY_NT_AUTHORITY }, SECURITY_NETWORK_RID },
|
||||
{ &InteractiveSid, { SECURITY_NT_AUTHORITY }, SECURITY_INTERACTIVE_RID },
|
||||
{ &ServiceLogonSid, { SECURITY_NT_AUTHORITY }, SECURITY_SERVICE_RID },
|
||||
{ &LocalSystemSid, { SECURITY_NT_AUTHORITY }, SECURITY_LOCAL_SYSTEM_RID },
|
||||
{ &LocalServiceSid, { SECURITY_NT_AUTHORITY }, SECURITY_LOCAL_SERVICE_RID },
|
||||
{ &NetworkServiceSid, { SECURITY_NT_AUTHORITY }, SECURITY_NETWORK_SERVICE_RID },
|
||||
{ &BuiltinDomainSid, { SECURITY_NT_AUTHORITY }, SECURITY_BUILTIN_DOMAIN_RID },
|
||||
{ &AuthenticatedUserSid, { SECURITY_NT_AUTHORITY }, SECURITY_AUTHENTICATED_USER_RID },
|
||||
{ &AnonymousLogonSid, { SECURITY_NT_AUTHORITY }, SECURITY_ANONYMOUS_LOGON_RID },
|
||||
};
|
||||
|
||||
DOMAIN_SID_DATA DomainSidData[8] =
|
||||
{
|
||||
{ &AliasAdminsSid, DOMAIN_ALIAS_RID_ADMINS },
|
||||
{ &AliasUsersSid, DOMAIN_ALIAS_RID_USERS },
|
||||
{ &AliasGuestsSid, DOMAIN_ALIAS_RID_GUESTS },
|
||||
{ &AliasPowerUsersSid, DOMAIN_ALIAS_RID_POWER_USERS },
|
||||
{ &AliasAccountOpsSid, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
|
||||
{ &AliasSystemOpsSid, DOMAIN_ALIAS_RID_SYSTEM_OPS },
|
||||
{ &AliasPrintOpsSid, DOMAIN_ALIAS_RID_PRINT_OPS },
|
||||
{ &AliasBackupOpsSid, DOMAIN_ALIAS_RID_BACKUP_OPS },
|
||||
};
|
||||
|
||||
PSVCHOST_GLOBALS g_pSvchostSharedGlobals;
|
||||
DWORD g_SvchostInitFlag;
|
||||
HANDLE g_hHeap;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
MemInit (
|
||||
_In_ HANDLE Heap
|
||||
)
|
||||
{
|
||||
/* Save the heap handle */
|
||||
g_hHeap = Heap;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
MemFree (
|
||||
_In_ LPVOID lpMem
|
||||
)
|
||||
{
|
||||
/* Free memory back into the heap */
|
||||
return HeapFree(g_hHeap, 0, lpMem);
|
||||
}
|
||||
|
||||
PVOID
|
||||
WINAPI
|
||||
MemAlloc (
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ DWORD dwBytes
|
||||
)
|
||||
{
|
||||
/* Allocate memory from the heap */
|
||||
return HeapAlloc(g_hHeap, dwFlags, dwBytes);
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvchostBuildSharedGlobals (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT(g_pSvchostSharedGlobals == NULL);
|
||||
|
||||
/* Is RPC initialized? */
|
||||
if (!(g_SvchostInitFlag & SVCHOST_RPC_INIT_COMPLETE))
|
||||
{
|
||||
/* Nope, go initialize it */
|
||||
if (!NT_SUCCESS(RpcpInitRpcServer())) return;
|
||||
|
||||
/* This is now done */
|
||||
g_SvchostInitFlag |= SVCHOST_RPC_INIT_COMPLETE;
|
||||
}
|
||||
|
||||
/* Is NetBIOS initialized? */
|
||||
if (!(g_SvchostInitFlag & SVCHOST_NBT_INIT_COMPLETE))
|
||||
{
|
||||
/* Nope, set it up */
|
||||
SvcNetBiosInit();
|
||||
|
||||
/* This is now done */
|
||||
g_SvchostInitFlag |= SVCHOST_NBT_INIT_COMPLETE;
|
||||
}
|
||||
|
||||
/* Do we have the global SIDs initialized? */
|
||||
if (!(g_SvchostInitFlag & SVCHOST_SID_INIT_COMPLETE))
|
||||
{
|
||||
/* Create the SIDs we'll export in the global structure */
|
||||
if (!NT_SUCCESS(ScCreateWellKnownSids())) return;
|
||||
|
||||
/* This is now done */
|
||||
g_SvchostInitFlag |= SVCHOST_SID_INIT_COMPLETE;
|
||||
}
|
||||
|
||||
/* Allocate memory for the globals */
|
||||
g_pSvchostSharedGlobals = MemAlloc(HEAP_ZERO_MEMORY,
|
||||
sizeof(*g_pSvchostSharedGlobals));
|
||||
if (g_pSvchostSharedGlobals == NULL) return;
|
||||
|
||||
/* Write the pointers to the SIDs */
|
||||
g_pSvchostSharedGlobals->NullSid = NullSid;
|
||||
g_pSvchostSharedGlobals->WorldSid = WorldSid;
|
||||
g_pSvchostSharedGlobals->LocalSid = LocalSid;
|
||||
g_pSvchostSharedGlobals->NetworkSid = NetworkSid;
|
||||
g_pSvchostSharedGlobals->LocalSystemSid = LocalSystemSid;
|
||||
g_pSvchostSharedGlobals->LocalServiceSid = LocalServiceSid;
|
||||
g_pSvchostSharedGlobals->NetworkServiceSid = NetworkServiceSid;
|
||||
g_pSvchostSharedGlobals->BuiltinDomainSid = BuiltinDomainSid;
|
||||
g_pSvchostSharedGlobals->AuthenticatedUserSid = AuthenticatedUserSid;
|
||||
g_pSvchostSharedGlobals->AnonymousLogonSid = AnonymousLogonSid;
|
||||
g_pSvchostSharedGlobals->AliasAdminsSid = AliasAdminsSid;
|
||||
g_pSvchostSharedGlobals->AliasUsersSid = AliasUsersSid;
|
||||
g_pSvchostSharedGlobals->AliasGuestsSid = AliasGuestsSid;
|
||||
g_pSvchostSharedGlobals->AliasPowerUsersSid = AliasPowerUsersSid;
|
||||
g_pSvchostSharedGlobals->AliasAccountOpsSid = AliasAccountOpsSid;
|
||||
g_pSvchostSharedGlobals->AliasSystemOpsSid = AliasSystemOpsSid;
|
||||
g_pSvchostSharedGlobals->AliasPrintOpsSid = AliasPrintOpsSid;
|
||||
g_pSvchostSharedGlobals->AliasBackupOpsSid = AliasBackupOpsSid;
|
||||
|
||||
/* Write the pointers to the callbacks */
|
||||
g_pSvchostSharedGlobals->RpcpStartRpcServer = RpcpStartRpcServer;
|
||||
g_pSvchostSharedGlobals->RpcpStopRpcServer = RpcpStopRpcServer;
|
||||
g_pSvchostSharedGlobals->RpcpStopRpcServerEx = RpcpStopRpcServerEx;
|
||||
g_pSvchostSharedGlobals->SvcNetBiosOpen = SvcNetBiosOpen;
|
||||
g_pSvchostSharedGlobals->SvcNetBiosClose = SvcNetBiosClose;
|
||||
g_pSvchostSharedGlobals->SvcNetBiosReset = SvcNetBiosReset;
|
||||
g_pSvchostSharedGlobals->SvcRegisterStopCallback = SvcRegisterStopCallback;
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvchostCharLowerW (
|
||||
_In_ LPCWSTR lpSrcStr
|
||||
)
|
||||
{
|
||||
DWORD cchSrc;
|
||||
|
||||
/* If there's nothing to do, bail out */
|
||||
if (lpSrcStr == NULL) return;
|
||||
|
||||
/* Get the length of the input string */
|
||||
cchSrc = wcslen(lpSrcStr);
|
||||
|
||||
/* Call the locale API to lower-case it */
|
||||
if (LCMapStringW(LANG_USER_DEFAULT,
|
||||
LCMAP_LOWERCASE,
|
||||
lpSrcStr,
|
||||
cchSrc + 1,
|
||||
(LPWSTR)lpSrcStr,
|
||||
cchSrc + 1) == FALSE)
|
||||
{
|
||||
DBG_ERR("SvchostCharLowerW failed for %ws\n", lpSrcStr);
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScDomainIdToSid (
|
||||
_In_ PSID SourceSid,
|
||||
_In_ ULONG DomainId,
|
||||
_Out_ PSID *DestinationSid
|
||||
)
|
||||
{
|
||||
ULONG sidCount, sidLength;
|
||||
NTSTATUS status;
|
||||
|
||||
/* Get the length of the SID based onthe number of subauthorities */
|
||||
sidCount = *RtlSubAuthorityCountSid(SourceSid);
|
||||
sidLength = RtlLengthRequiredSid(sidCount + 1);
|
||||
|
||||
/* Allocate it */
|
||||
*DestinationSid = RtlAllocateHeap(RtlGetProcessHeap(), 0, sidLength);
|
||||
if (*DestinationSid)
|
||||
{
|
||||
/* Make a copy of it */
|
||||
status = RtlCopySid(sidLength, *DestinationSid, SourceSid);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
/* Increase the subauthority count */
|
||||
++*RtlSubAuthorityCountSid(*DestinationSid);
|
||||
|
||||
/* And add the specific domain RID we're creating */
|
||||
*RtlSubAuthoritySid(*DestinationSid, sidCount) = DomainId;
|
||||
|
||||
/* Everything worked */
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The SID copy failed, so free the SID we just allocated */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, *DestinationSid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No space for the SID, bail out */
|
||||
status = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Return back to the caller */
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScAllocateAndInitializeSid (
|
||||
_Out_ PVOID *Sid,
|
||||
_In_ PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
|
||||
_In_ ULONG SubAuthorityCount
|
||||
)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Allocare toom for the SID */
|
||||
*Sid = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
RtlLengthRequiredSid(SubAuthorityCount));
|
||||
if (*Sid)
|
||||
{
|
||||
/* Initialize it, we're done */
|
||||
RtlInitializeSid(*Sid, IdentifierAuthority, SubAuthorityCount);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No memory, we'll fail */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Return what happened */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScCreateWellKnownSids (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Loop the non-domain SIDs */
|
||||
for (i = 0; i < RTL_NUMBER_OF(SidData); i++)
|
||||
{
|
||||
/* Convert our optimized structure into an actual SID */
|
||||
Status = ScAllocateAndInitializeSid(&SidData[i].Sid,
|
||||
&SidData[i].Authority,
|
||||
1);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
|
||||
/* Write the correct sub-authority */
|
||||
*RtlSubAuthoritySid(SidData[i].Sid, 0) = SidData[i].SubAuthority;
|
||||
}
|
||||
|
||||
/* Now loop the domain SIDs */
|
||||
for (i = 0; i < RTL_NUMBER_OF(DomainSidData); i++)
|
||||
{
|
||||
/* Convert our optimized structure into an actual SID */
|
||||
Status = ScDomainIdToSid(BuiltinDomainSid,
|
||||
DomainSidData[i].SubAuthority,
|
||||
&DomainSidData[i].Sid);
|
||||
if (!NT_SUCCESS(Status)) break;
|
||||
}
|
||||
|
||||
/* If we got to the end, return success */
|
||||
return (i == RTL_NUMBER_OF(DomainSidData)) ? STATUS_SUCCESS : STATUS_NO_MEMORY;
|
||||
}
|
||||
|
158
reactos/base/services/svchost/netbios.c
Normal file
158
reactos/base/services/svchost/netbios.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/netbios.c
|
||||
* PURPOSE: NetBIOS Service Support
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "svchost.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
LONG GlobalNetBiosUseCount;
|
||||
DWORD LanaFlags[8];
|
||||
CRITICAL_SECTION SvcNetBiosCritSec;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
SvcNetBiosStatusToApiStatus (
|
||||
_In_ DWORD NetBiosError
|
||||
)
|
||||
{
|
||||
/* Convert from one status to another */
|
||||
switch (NetBiosError)
|
||||
{
|
||||
case NRC_GOODRET:
|
||||
return NERR_Success;
|
||||
case NRC_INUSE:
|
||||
case NRC_NAMCONF:
|
||||
return NERR_DuplicateName;
|
||||
case NRC_NOWILD:
|
||||
case NRC_NAMERR:
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
case NRC_NOCALL:
|
||||
return NERR_NameNotFound;
|
||||
case NRC_NORES:
|
||||
return NERR_NoNetworkResource;
|
||||
case NRC_DUPNAME:
|
||||
return NERR_AlreadyExists;
|
||||
case NRC_NAMTFUL:
|
||||
return NERR_TooManyNames;
|
||||
case NRC_ACTSES:
|
||||
return NERR_DeleteLater;
|
||||
case NRC_REMTFUL:
|
||||
return ERROR_REM_NOT_LIST;
|
||||
default:
|
||||
return NERR_NetworkError;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
LanaFlagIsSet (
|
||||
_In_ UCHAR Lana
|
||||
)
|
||||
{
|
||||
DWORD i = Lana / 32;
|
||||
|
||||
/* Clear the flag for this LANA */
|
||||
return (i <= 8) ? LanaFlags[i] & (1 << (Lana - 32 * i)) : FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SetLanaFlag (
|
||||
_In_ UCHAR Lana
|
||||
)
|
||||
{
|
||||
DWORD i = Lana / 32;
|
||||
|
||||
/* Set the flag for this LANA */
|
||||
if (i <= 8) LanaFlags[i] |= 1 << (Lana - 32 * i);
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosInit(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* Initialize NetBIOS-related structures and variables */
|
||||
InitializeCriticalSection(&SvcNetBiosCritSec);
|
||||
GlobalNetBiosUseCount = 0;
|
||||
ZeroMemory(LanaFlags, sizeof(LanaFlags));
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosClose (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* While holding the lock, drop a reference*/
|
||||
EnterCriticalSection(&SvcNetBiosCritSec);
|
||||
if ((GlobalNetBiosUseCount != 0) && (--GlobalNetBiosUseCount == 0))
|
||||
{
|
||||
/* All references are gone, clear all LANA's */
|
||||
ZeroMemory(LanaFlags, sizeof(LanaFlags));
|
||||
}
|
||||
LeaveCriticalSection(&SvcNetBiosCritSec);
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosOpen (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* Increment the reference counter while holding the lock */
|
||||
EnterCriticalSection(&SvcNetBiosCritSec);
|
||||
GlobalNetBiosUseCount++;
|
||||
LeaveCriticalSection(&SvcNetBiosCritSec);
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
SvcNetBiosReset (
|
||||
_In_ UCHAR LanaNum
|
||||
)
|
||||
{
|
||||
DWORD dwError = ERROR_SUCCESS;
|
||||
UCHAR nbtError;
|
||||
NCB ncb;
|
||||
|
||||
/* Block all other NetBIOS operations */
|
||||
EnterCriticalSection(&SvcNetBiosCritSec);
|
||||
|
||||
/* Is this LANA enabled? */
|
||||
if (!LanaFlagIsSet(LanaNum))
|
||||
{
|
||||
/* Yep, build a reset packet */
|
||||
ZeroMemory(&ncb, sizeof(ncb));
|
||||
ncb.ncb_lsn = 0;
|
||||
ncb.ncb_command = NCBRESET;
|
||||
ncb.ncb_callname[0] = 0xFE; // Max Sessions
|
||||
ncb.ncb_callname[1] = 0;
|
||||
ncb.ncb_callname[2] = 0xFD; // Max Names
|
||||
ncb.ncb_callname[3] = 0;
|
||||
ncb.ncb_lana_num = LanaNum;
|
||||
|
||||
/* Send it */
|
||||
nbtError = Netbios(&ncb);
|
||||
|
||||
/* Convert the status to Win32 format */
|
||||
dwError = SvcNetBiosStatusToApiStatus(nbtError);
|
||||
|
||||
/* Enable the LANA if the reset worked */
|
||||
if (dwError == ERROR_SUCCESS) SetLanaFlag(LanaNum);
|
||||
}
|
||||
|
||||
/* Drop the lock and return */
|
||||
LeaveCriticalSection(&SvcNetBiosCritSec);
|
||||
return dwError;
|
||||
}
|
201
reactos/base/services/svchost/registry.c
Normal file
201
reactos/base/services/svchost/registry.c
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/registry.c
|
||||
* PURPOSE: Helper functions for accessing the registry
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "svchost.h"
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryValueWithAlloc (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ DWORD dwExpectedType,
|
||||
_Out_ PBYTE* ppbData,
|
||||
_Out_ PDWORD pdwSize
|
||||
)
|
||||
{
|
||||
DWORD dwError, dwType, dwBytes;
|
||||
PBYTE pbData;
|
||||
ASSERT(hKey);
|
||||
ASSERT(pszValueName);
|
||||
ASSERT(ppbData);
|
||||
ASSERT(pdwSize);
|
||||
|
||||
/* Assume failure */
|
||||
*ppbData = NULL;
|
||||
*pdwSize = 0;
|
||||
|
||||
/* Query how big and what type the registry data is */
|
||||
dwBytes = 0;
|
||||
dwError = RegQueryValueExW(hKey,
|
||||
pszValueName,
|
||||
NULL,
|
||||
&dwType,
|
||||
NULL,
|
||||
&dwBytes);
|
||||
if (dwError != ERROR_SUCCESS) return dwError;
|
||||
|
||||
/* It if's not the right type, or it's sero bytes, fail*/
|
||||
if ((dwType != dwExpectedType) || (dwBytes == 0)) return ERROR_INVALID_DATA;
|
||||
|
||||
/* Allocate space to hold the data */
|
||||
pbData = MemAlloc(0, dwBytes);
|
||||
if (pbData == NULL) return ERROR_OUTOFMEMORY;
|
||||
|
||||
/* Now get the real registry data */
|
||||
dwError = RegQueryValueExW(hKey,
|
||||
pszValueName,
|
||||
NULL,
|
||||
&dwType,
|
||||
pbData,
|
||||
&dwBytes);
|
||||
if (dwError != ERROR_SUCCESS)
|
||||
{
|
||||
/* We failed, free the data since it won't be needed */
|
||||
MemFree(pbData);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It worked, return the data and size back to the caller */
|
||||
*ppbData = pbData;
|
||||
*pdwSize = dwBytes;
|
||||
}
|
||||
|
||||
/* All done */
|
||||
return dwError;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryDword (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_Out_ PDWORD pdwValue
|
||||
)
|
||||
{
|
||||
DWORD dwError, cbData, dwType;
|
||||
ASSERT(hKey);
|
||||
ASSERT(pszValueName);
|
||||
ASSERT(pdwValue);
|
||||
|
||||
/* Attempt to read 4 bytes */
|
||||
cbData = sizeof(DWORD);
|
||||
dwError = RegQueryValueExW(hKey, pszValueName, 0, &dwType, 0, &cbData);
|
||||
|
||||
/* If we didn't get back a DWORD... */
|
||||
if ((dwError == ERROR_SUCCESS) && (dwType != REG_DWORD))
|
||||
{
|
||||
/* Zero out the output and fail */
|
||||
*pdwValue = 0;
|
||||
dwError = ERROR_INVALID_DATATYPE;
|
||||
}
|
||||
|
||||
/* All done! */
|
||||
return dwError;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryString (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ DWORD dwExpectedType,
|
||||
_Out_ PBYTE* ppbData
|
||||
)
|
||||
{
|
||||
DWORD dwSize;
|
||||
ASSERT(hKey);
|
||||
ASSERT(pszValueName);
|
||||
|
||||
/* Call the helper function */
|
||||
return RegQueryValueWithAlloc(hKey,
|
||||
pszValueName,
|
||||
dwExpectedType,
|
||||
ppbData,
|
||||
&dwSize);
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryStringA (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ DWORD dwExpectedType,
|
||||
_Out_ LPCSTR* ppszData
|
||||
)
|
||||
{
|
||||
DWORD dwError;
|
||||
LPWSTR pbLocalData;
|
||||
DWORD cchValueName, cbMultiByte;
|
||||
LPSTR pszData;
|
||||
ASSERT(hKey);
|
||||
ASSERT(pszValueName);
|
||||
ASSERT(ppszData);
|
||||
|
||||
/* Assume failure */
|
||||
*ppszData = NULL;
|
||||
|
||||
/* Query the string in Unicode first */
|
||||
dwError = RegQueryString(hKey,
|
||||
pszValueName,
|
||||
dwExpectedType,
|
||||
(PBYTE*)&pbLocalData);
|
||||
if (dwError != ERROR_SUCCESS) return dwError;
|
||||
|
||||
/* Get the length of the Unicode string */
|
||||
cchValueName = lstrlenW(pbLocalData);
|
||||
|
||||
/* See how much space it would take to convert to ANSI */
|
||||
cbMultiByte = WideCharToMultiByte(CP_ACP,
|
||||
0,
|
||||
pbLocalData,
|
||||
cchValueName + 1,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (cbMultiByte != 0)
|
||||
{
|
||||
/* Allocate the space, assuming failure */
|
||||
dwError = ERROR_OUTOFMEMORY;
|
||||
pszData = MemAlloc(0, cbMultiByte);
|
||||
if (pszData != NULL)
|
||||
{
|
||||
/* What do you know, it worked! */
|
||||
dwError = ERROR_SUCCESS;
|
||||
|
||||
/* Now do the real conversion */
|
||||
if (WideCharToMultiByte(CP_ACP,
|
||||
0,
|
||||
pbLocalData,
|
||||
cchValueName + 1,
|
||||
pszData,
|
||||
cbMultiByte,
|
||||
NULL,
|
||||
NULL) != 0)
|
||||
{
|
||||
/* It worked, return the data back to the caller */
|
||||
*ppszData = pszData;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It failed, free our buffer and get the error code */
|
||||
MemFree(pszData);
|
||||
dwError = GetLastError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the original Unicode string and return the error */
|
||||
MemFree(pbLocalData);
|
||||
return dwError;
|
||||
}
|
||||
|
156
reactos/base/services/svchost/rpcsrv.c
Normal file
156
reactos/base/services/svchost/rpcsrv.c
Normal file
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/rpcsrv.c
|
||||
* PURPOSE: RPC Service Support
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "svchost.h"
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
LONG RpcpNumInstances;
|
||||
CRITICAL_SECTION RpcpCriticalSection;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpInitRpcServer (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* Clear the reference count and initialize the critical section */
|
||||
RpcpNumInstances = 0;
|
||||
return RtlInitializeCriticalSection((PVOID)&RpcpCriticalSection);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStopRpcServer (
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
)
|
||||
{
|
||||
RPC_STATUS rpcStatus;
|
||||
|
||||
/* Unregister the interface */
|
||||
rpcStatus = RpcServerUnregisterIf(IfSpec, NULL, TRUE);
|
||||
|
||||
/* Acquire the lock while we dereference the RPC services */
|
||||
EnterCriticalSection(&RpcpCriticalSection);
|
||||
if (--RpcpNumInstances == 0)
|
||||
{
|
||||
/* All RPC services stopped, rundown the server */
|
||||
RpcMgmtStopServerListening(NULL);
|
||||
RpcMgmtWaitServerListen();
|
||||
}
|
||||
|
||||
/* Release the lock and return the unregister result */
|
||||
LeaveCriticalSection(&RpcpCriticalSection);
|
||||
return I_RpcMapWin32Status(rpcStatus);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStopRpcServerEx (
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
)
|
||||
{
|
||||
RPC_STATUS rpcStatus;
|
||||
|
||||
/* Unregister the interface */
|
||||
rpcStatus = RpcServerUnregisterIfEx(IfSpec, NULL, TRUE);
|
||||
|
||||
/* Acquire the lock while we dereference the RPC services */
|
||||
EnterCriticalSection(&RpcpCriticalSection);
|
||||
if (--RpcpNumInstances == 0)
|
||||
{
|
||||
/* All RPC services stopped, rundown the server */
|
||||
RpcMgmtStopServerListening(NULL);
|
||||
RpcMgmtWaitServerListen();
|
||||
}
|
||||
|
||||
/* Release the lock and return the unregister result */
|
||||
LeaveCriticalSection(&RpcpCriticalSection);
|
||||
return I_RpcMapWin32Status(rpcStatus);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpAddInterface (
|
||||
_In_ LPCWSTR IfName,
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
)
|
||||
{
|
||||
PWCHAR endpointName;
|
||||
NTSTATUS ntStatus;
|
||||
RPC_STATUS rpcStatus;
|
||||
|
||||
/* Allocate space for the interface name and the \\PIPE\\ prefix */
|
||||
endpointName = LocalAlloc(0, sizeof(WCHAR) * wcslen(IfName) + 16);
|
||||
if (endpointName)
|
||||
{
|
||||
/* Copy the prefix, and then the interface name */
|
||||
wcscpy(endpointName, L"\\PIPE\\");
|
||||
wcscat(endpointName, IfName);
|
||||
|
||||
/* Create a named pipe endpoint with this name */
|
||||
rpcStatus = RpcServerUseProtseqEpW(L"ncacn_np", 10, endpointName, NULL);
|
||||
if ((rpcStatus != RPC_S_OK) && (rpcStatus != RPC_S_DUPLICATE_ENDPOINT))
|
||||
{
|
||||
/* We couldn't create it, or it already existed... */
|
||||
DbgPrint("RpcServerUseProtseqW failed! rpcstatus = %u\n", rpcStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It worked, register an interface on this endpoint now*/
|
||||
rpcStatus = RpcServerRegisterIf(IfSpec, 0, 0);
|
||||
}
|
||||
|
||||
/* In both success and failure, free the name, and convert the status */
|
||||
LocalFree(endpointName);
|
||||
ntStatus = I_RpcMapWin32Status(rpcStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No memory, bail out */
|
||||
ntStatus = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* Return back to the caller */
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStartRpcServer (
|
||||
_In_ LPCWSTR IfName,
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
|
||||
/* Acquire the lock while we instantiate a new interface */
|
||||
EnterCriticalSection(&RpcpCriticalSection);
|
||||
|
||||
/* Add this interface to the service */
|
||||
ntStatus = RpcpAddInterface(IfName, IfSpec);
|
||||
if (!ntStatus)
|
||||
{
|
||||
/* Increment the reference count to see if this was the first interface */
|
||||
if (++RpcpNumInstances == 1)
|
||||
{
|
||||
/* It was, so put the server into listening mode now */
|
||||
ntStatus = RpcServerListen(1, 12345, TRUE);
|
||||
if (ntStatus == RPC_S_ALREADY_LISTENING) ntStatus = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the lock and return back the result to the caller */
|
||||
LeaveCriticalSection(&RpcpCriticalSection);
|
||||
return I_RpcMapWin32Status(ntStatus);
|
||||
}
|
||||
|
227
reactos/base/services/svchost/security.cxx
Normal file
227
reactos/base/services/svchost/security.cxx
Normal file
|
@ -0,0 +1,227 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/security.c
|
||||
* PURPOSE: Initializes the COM Object Security Model and Parameters
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#define __callback
|
||||
extern "C"
|
||||
{
|
||||
#include "svchost.h"
|
||||
}
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
SID NtSid = { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } };
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
DwInitializeSdFromThreadToken (
|
||||
_Out_ PVOID *ppSecurityDescriptor,
|
||||
_Out_ PACL *ppAcl
|
||||
)
|
||||
{
|
||||
HANDLE hToken;
|
||||
DWORD dwGroupLength, dwUserLength, dwError, dwAlignLength;
|
||||
PTOKEN_PRIMARY_GROUP pTokenGroup;
|
||||
PTOKEN_USER pTokenUser;
|
||||
EXPLICIT_ACCESS_W pListOfExplicitEntries;
|
||||
PACL pAcl = NULL;
|
||||
PISECURITY_DESCRIPTOR pSd;
|
||||
|
||||
/* Assume failure */
|
||||
*ppSecurityDescriptor = NULL;
|
||||
*ppAcl = NULL;
|
||||
|
||||
/* Open the token of the current thread */
|
||||
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, 0, &hToken) == FALSE)
|
||||
{
|
||||
/* The thread is not impersonating, use the process token */
|
||||
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken) == FALSE)
|
||||
{
|
||||
/* No token could be queried, fail */
|
||||
return GetLastError();
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the size of the token's user */
|
||||
if ((GetTokenInformation(hToken, TokenUser, NULL, 0, &dwUserLength) == FALSE) ||
|
||||
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
/* Get the size of the token's primary group */
|
||||
if ((GetTokenInformation(hToken, TokenPrimaryGroup, NULL, 0, &dwGroupLength) == FALSE) ||
|
||||
(GetLastError() != ERROR_INSUFFICIENT_BUFFER))
|
||||
{
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
/* Allocate an SD large enough to hold the SIDs for the above */
|
||||
dwAlignLength = ALIGN_UP(dwUserLength, ULONG);
|
||||
pSd = (PISECURITY_DESCRIPTOR)MemAlloc(0,
|
||||
dwAlignLength +
|
||||
dwGroupLength +
|
||||
sizeof(*pSd));
|
||||
if (pSd == NULL) return ERROR_OUTOFMEMORY;
|
||||
|
||||
/* Assume success for now */
|
||||
dwError = ERROR_SUCCESS;
|
||||
|
||||
/* We'll put them right after the SD itself */
|
||||
pTokenUser = (PTOKEN_USER)(pSd + 1);
|
||||
pTokenGroup = (PTOKEN_PRIMARY_GROUP)((ULONG_PTR)pTokenUser + dwAlignLength);
|
||||
|
||||
/* Now initialize it */
|
||||
if (InitializeSecurityDescriptor(pSd, SECURITY_DESCRIPTOR_REVISION) == FALSE)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
}
|
||||
|
||||
/* And do the actual query for the user */
|
||||
if (GetTokenInformation(hToken,
|
||||
TokenUser,
|
||||
pTokenUser,
|
||||
dwUserLength,
|
||||
&dwUserLength) == FALSE)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
}
|
||||
|
||||
/* And then the actual query for the primary group */
|
||||
if (GetTokenInformation(hToken,
|
||||
TokenPrimaryGroup,
|
||||
pTokenGroup,
|
||||
dwGroupLength,
|
||||
&dwGroupLength) == FALSE)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
}
|
||||
|
||||
/* Set the user as owner */
|
||||
if (SetSecurityDescriptorOwner(pSd, pTokenUser->User.Sid, FALSE) == FALSE)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
}
|
||||
|
||||
/* Set the group as primary */
|
||||
if (SetSecurityDescriptorGroup(pSd, pTokenGroup->PrimaryGroup, FALSE) == FALSE)
|
||||
{
|
||||
dwError = GetLastError();
|
||||
}
|
||||
|
||||
/* Did everything so far work out? */
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
{
|
||||
/* Yes, create an ACL granting the SYSTEM account access */
|
||||
pListOfExplicitEntries.grfAccessMode = SET_ACCESS;
|
||||
pListOfExplicitEntries.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
|
||||
pListOfExplicitEntries.grfAccessPermissions = 1;
|
||||
pListOfExplicitEntries.grfInheritance = 0;
|
||||
pListOfExplicitEntries.Trustee.pMultipleTrustee = 0;
|
||||
pListOfExplicitEntries.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
pListOfExplicitEntries.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
pListOfExplicitEntries.Trustee.ptstrName = (LPWSTR)&NtSid;
|
||||
dwError = SetEntriesInAclW(1, &pListOfExplicitEntries, NULL, &pAcl);
|
||||
if (dwError == ERROR_SUCCESS)
|
||||
{
|
||||
/* Make that ACL the DACL of the SD we just built */
|
||||
if (SetSecurityDescriptorDacl(pSd, 1, pAcl, FALSE) == FALSE)
|
||||
{
|
||||
/* We failed, bail out */
|
||||
LocalFree(pAcl);
|
||||
dwError = GetLastError();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Now we have the SD and the ACL all ready to go */
|
||||
*ppSecurityDescriptor = pSd;
|
||||
*ppAcl = pAcl;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Failure path, we'll free the SD since the caller can't use it */
|
||||
MemFree(pSd);
|
||||
return dwError;
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
InitializeSecurity (
|
||||
_In_ DWORD dwParam,
|
||||
_In_ DWORD dwAuthnLevel,
|
||||
_In_ DWORD dwImpLevel,
|
||||
_In_ DWORD dwCapabilities
|
||||
)
|
||||
{
|
||||
HRESULT hr;
|
||||
PACL pAcl;
|
||||
PSECURITY_DESCRIPTOR pSecurityDescriptor;
|
||||
IGlobalOptions *pGlobalOptions;
|
||||
ASSERT(dwParam != 0);
|
||||
|
||||
/* Create a valid SD and ACL based on the current thread's token */
|
||||
if (DwInitializeSdFromThreadToken(&pSecurityDescriptor, &pAcl) == ERROR_SUCCESS)
|
||||
{
|
||||
/* It worked -- initialize COM without DDE support */
|
||||
hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't keep going if we don't have an SD */
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
/* Did we make it? */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* Indeed, initialize COM security now */
|
||||
DBG_TRACE("Calling CoInitializeSecurity (dwAuthCapabilities = 0x%08x)\n",
|
||||
dwCapabilities);
|
||||
hr = CoInitializeSecurity(pSecurityDescriptor,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
dwAuthnLevel,
|
||||
dwImpLevel,
|
||||
NULL,
|
||||
dwCapabilities,
|
||||
NULL);
|
||||
if (FAILED(hr)) DBG_ERR("CoInitializeSecurity returned hr=0x%08x\n", hr);
|
||||
}
|
||||
|
||||
/* Free the SD and ACL since we no longer need it */
|
||||
MemFree(pSecurityDescriptor);
|
||||
LocalFree(pAcl);
|
||||
|
||||
/* Did we initialize COM correctly? */
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* Get the COM Global Options Interface */
|
||||
hr = CoCreateInstance(CLSID_GlobalOptions,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IGlobalOptions,
|
||||
(LPVOID*)&pGlobalOptions);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
/* Use it to disable COM exception handling */
|
||||
hr = pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING,
|
||||
COMGLB_EXCEPTION_DONOT_HANDLE);
|
||||
pGlobalOptions->Release();
|
||||
ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Return whether all COM calls were successful or not */
|
||||
return SUCCEEDED(hr);
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,32 +1,303 @@
|
|||
/*
|
||||
* PROJECT: ReactOS SvcHost
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: /base/services/svchost/svchost.h
|
||||
* PURPOSE: Provide dll service loader
|
||||
* PROGRAMMERS: Gregor Brunmar (gregor.brunmar@home.se)
|
||||
* PROJECT: ReactOS Service Host
|
||||
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
||||
* FILE: base/services/svchost/svchost.h
|
||||
* PURPOSE: Precompiled Header for Service Host
|
||||
* PROGRAMMERS: ReactOS Portable Systems Group
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define WIN32_NO_STATUS
|
||||
#include <Windows.h>
|
||||
#include <AclAPI.h>
|
||||
#include <ntndk.h>
|
||||
#include <lmerr.h>
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
//
|
||||
// FIXME: Should go in public headers
|
||||
//
|
||||
#define DPFLTR_SVCHOST_ID 28
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winreg.h>
|
||||
#include <winsvc.h>
|
||||
#include <strsafe.h>
|
||||
//
|
||||
// This prints out a SVCHOST-specific debug print, with the PID/TID
|
||||
//
|
||||
#if _EX_
|
||||
#define SvchostDbgPrint(l, x, ...) \
|
||||
DbgPrintEx(DPFLTR_SVCHOST_ID, \
|
||||
DPFLTR_MASK | l, \
|
||||
"[SVCHOST] %lx.%lx: " # x, \
|
||||
GetCurrentProcessId(), \
|
||||
GetCurrentThreadId(), \
|
||||
__VA_ARGS__);
|
||||
#else
|
||||
#define SvchostDbgPrint(l, x, ...) \
|
||||
DbgPrint("[SVCHOST] %lx.%lx: " # x, \
|
||||
GetCurrentProcessId(), \
|
||||
GetCurrentThreadId(), \
|
||||
__VA_ARGS__);
|
||||
#endif
|
||||
#define DBG_ERR(x, ...) SvchostDbgPrint(1, x, __VA_ARGS__)
|
||||
#define DBG_TRACE(x, ...) SvchostDbgPrint(4, x, __VA_ARGS__)
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
//
|
||||
// This is the callback that a hosted service can register for stop notification
|
||||
// FIXME: GLOBAL HEADER
|
||||
//
|
||||
typedef VOID
|
||||
(*CALLBACK PSVCHOST_STOP_CALLBACK) (
|
||||
_In_ PVOID lpParameter,
|
||||
_In_ BOOLEAN TimerOrWaitFired
|
||||
);
|
||||
|
||||
typedef struct _SERVICE {
|
||||
PWSTR Name;
|
||||
HINSTANCE hServiceDll;
|
||||
LPSERVICE_MAIN_FUNCTION ServiceMainFunc;
|
||||
struct _SERVICE *Next;
|
||||
} SERVICE, *PSERVICE;
|
||||
//
|
||||
// Hosted Services and SvcHost Use this Structure
|
||||
// FIXME: GLOBAL HEADER
|
||||
//
|
||||
typedef struct _SVCHOST_GLOBALS
|
||||
{
|
||||
PVOID NullSid;
|
||||
PVOID WorldSid;
|
||||
PVOID LocalSid;
|
||||
PVOID NetworkSid;
|
||||
PVOID LocalSystemSid;
|
||||
PVOID LocalServiceSid;
|
||||
PVOID NetworkServiceSid;
|
||||
PVOID BuiltinDomainSid;
|
||||
PVOID AuthenticatedUserSid;
|
||||
PVOID AnonymousLogonSid;
|
||||
PVOID AliasAdminsSid;
|
||||
PVOID AliasUsersSid;
|
||||
PVOID AliasGuestsSid;
|
||||
PVOID AliasPowerUsersSid;
|
||||
PVOID AliasAccountOpsSid;
|
||||
PVOID AliasSystemOpsSid;
|
||||
PVOID AliasPrintOpsSid;
|
||||
PVOID AliasBackupOpsSid;
|
||||
PVOID RpcpStartRpcServer;
|
||||
PVOID RpcpStopRpcServer;
|
||||
PVOID RpcpStopRpcServerEx;
|
||||
PVOID SvcNetBiosOpen;
|
||||
PVOID SvcNetBiosClose;
|
||||
PVOID SvcNetBiosReset;
|
||||
PVOID SvcRegisterStopCallback;
|
||||
} SVCHOST_GLOBALS, *PSVCHOST_GLOBALS;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
//
|
||||
// This is the callback for them to receive it
|
||||
//
|
||||
typedef VOID
|
||||
(WINAPI *PSVCHOST_INIT_GLOBALS) (
|
||||
_In_ PSVCHOST_GLOBALS Globals
|
||||
);
|
||||
//
|
||||
// Initialization Stages
|
||||
//
|
||||
#define SVCHOST_RPC_INIT_COMPLETE 1
|
||||
#define SVCHOST_NBT_INIT_COMPLETE 2
|
||||
#define SVCHOST_SID_INIT_COMPLETE 4
|
||||
|
||||
//
|
||||
// Domain Alias SID Structure
|
||||
//
|
||||
typedef struct _DOMAIN_SID_DATA
|
||||
{
|
||||
PSID Sid;
|
||||
DWORD SubAuthority;
|
||||
} DOMAIN_SID_DATA;
|
||||
|
||||
//
|
||||
// Well-known SID Structure
|
||||
//
|
||||
typedef struct _SID_DATA
|
||||
{
|
||||
PSID Sid;
|
||||
SID_IDENTIFIER_AUTHORITY Authority;
|
||||
DWORD SubAuthority;
|
||||
} SID_DATA;
|
||||
|
||||
//
|
||||
// This contains all the settings (from the registry) for a hosted service
|
||||
//
|
||||
typedef struct _SVCHOST_OPTIONS
|
||||
{
|
||||
PWCHAR CmdLineBuffer;
|
||||
PWCHAR CmdLine;
|
||||
BOOL HasServiceGroup;
|
||||
LPWSTR ServiceGroupName;
|
||||
DWORD CoInitializeSecurityParam;
|
||||
DWORD AuthenticationLevel;
|
||||
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
|
||||
DWORD AuthenticationCapabilities;
|
||||
DWORD DefaultRpcStackSize;
|
||||
BOOLEAN SystemCritical;
|
||||
} SVCHOST_OPTIONS, *PSVCHOST_OPTIONS;
|
||||
|
||||
//
|
||||
// This represents the DLL used to hold a hosted service
|
||||
//
|
||||
typedef struct _SVCHOST_DLL
|
||||
{
|
||||
LIST_ENTRY DllList;
|
||||
HINSTANCE hModule;
|
||||
LPCWSTR pszDllPath;
|
||||
LPCWSTR pszManifestPath;
|
||||
HANDLE hActCtx;
|
||||
struct _SVCHOST_SERVICE* pService;
|
||||
} SVCHOST_DLL, *PSVCHOST_DLL;
|
||||
|
||||
//
|
||||
// This represents an actual hosted service
|
||||
//
|
||||
typedef struct _SVCHOST_SERVICE
|
||||
{
|
||||
LPCWSTR pszServiceName;
|
||||
LPCSTR pszServiceMain;
|
||||
LONG cServiceActiveThreadCount;
|
||||
PSVCHOST_DLL pDll;
|
||||
PSVCHOST_STOP_CALLBACK pfnStopCallback;
|
||||
} SVCHOST_SERVICE, *PSVCHOST_SERVICE;
|
||||
|
||||
//
|
||||
// This is the context that a hosted service with a stop callback has
|
||||
//
|
||||
typedef struct _SVCHOST_CALLBACK_CONTEXT
|
||||
{
|
||||
PVOID pContext;
|
||||
PSVCHOST_SERVICE pService;
|
||||
} SVCHOST_CALLBACK_CONTEXT, *PSVCHOST_CALLBACK_CONTEXT;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpInitRpcServer (
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStopRpcServer (
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStopRpcServerEx (
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RpcpStartRpcServer (
|
||||
_In_ LPCWSTR IfName,
|
||||
_In_ RPC_IF_HANDLE IfSpec
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvchostBuildSharedGlobals (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvchostCharLowerW (
|
||||
_In_ LPCWSTR lpSrcStr
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ScCreateWellKnownSids (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
MemInit (
|
||||
_In_ HANDLE Heap
|
||||
);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
MemFree (
|
||||
_In_ LPVOID lpMem
|
||||
);
|
||||
|
||||
PVOID
|
||||
WINAPI
|
||||
MemAlloc (
|
||||
_In_ DWORD dwFlags,
|
||||
_In_ DWORD dwBytes
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosInit (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosClose (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
SvcNetBiosOpen (
|
||||
VOID
|
||||
);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
SvcNetBiosReset (
|
||||
_In_ UCHAR LanaNum
|
||||
);
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
InitializeSecurity (
|
||||
_In_ DWORD dwParam,
|
||||
_In_ DWORD dwAuthnLevel,
|
||||
_In_ DWORD dwImpLevel,
|
||||
_In_ DWORD dwCapabilities
|
||||
);
|
||||
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryDword (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_Out_ PDWORD pdwValue
|
||||
);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryString (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ DWORD dwExpectedType,
|
||||
_Out_ PBYTE* ppbData
|
||||
);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
RegQueryStringA (
|
||||
_In_ HKEY hKey,
|
||||
_In_ LPCWSTR pszValueName,
|
||||
_In_ DWORD dwExpectedType,
|
||||
_Out_ LPCSTR* ppszData
|
||||
);
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
SvcRegisterStopCallback (
|
||||
_In_ PHANDLE phNewWaitObject,
|
||||
_In_ LPCWSTR ServiceName,
|
||||
_In_ HANDLE hObject,
|
||||
_In_ PSVCHOST_STOP_CALLBACK pfnStopCallback,
|
||||
_In_ PVOID pContext,
|
||||
_In_ ULONG dwFlags
|
||||
);
|
||||
|
||||
extern PSVCHOST_GLOBALS g_pSvchostSharedGlobals;
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue