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.
799 lines
19 KiB
799 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Start.c
|
|
|
|
Abstract:
|
|
|
|
Process init and service controller interaction for dcomss.exe
|
|
|
|
Author:
|
|
|
|
Mario Goertzel [MarioGo]
|
|
|
|
Revision History:
|
|
|
|
MarioGo 06-14-95 Cloned from the old endpoint mapper.
|
|
MazharM 10-12.98 Add pnp stuff
|
|
TarunA 12-11-98 Removed pnpmngr.h
|
|
a-sergiv 25-08-99 Defined gC2Security for process-wide use
|
|
|
|
--*/
|
|
|
|
//#define NCADG_MQ_ON
|
|
|
|
#if !defined(_M_IA64)
|
|
#define SPX_ON
|
|
#endif
|
|
|
|
//#define IPX_ON
|
|
|
|
#if !defined(SPX_ON) && !defined(IPX_ON)
|
|
#define SPX_IPX_OFF
|
|
#endif
|
|
|
|
#include <dcomss.h>
|
|
#include <debnot.h>
|
|
#include <olesem.hxx>
|
|
#include <wtypes.h>
|
|
#include <objbase.h>
|
|
#include <winioctl.h>
|
|
#include <ntddndis.h>
|
|
#include <ndispnp.h>
|
|
#include <dbt.h>
|
|
#include <initguid.h>
|
|
#include <ndisguid.h>
|
|
#include <ndispnp.h>
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
|
|
#define SAFEALLOCA_ASSERT ASSERT
|
|
#include <alloca.h>
|
|
|
|
#ifndef SPX_IPX_OFF
|
|
#include "sap.h"
|
|
#endif
|
|
|
|
#include "../../com/inc/secdes.hxx"
|
|
#include "../olescm/mach.hxx"
|
|
#include "tls.h"
|
|
#include "memapi.hxx"
|
|
|
|
extern LONG g_bInSCM; // from catalog
|
|
C2Security gC2Security;
|
|
// Array of service status blocks and pointers to service control
|
|
// functions for each component service.
|
|
|
|
#define SERVICE_NAME L"RPCSS"
|
|
#define DEVICE_PREFIX L"\\\\.\\"
|
|
|
|
VOID WINAPI ServiceMain(DWORD, PWSTR[]);
|
|
|
|
extern BOOL CatalogDllMain (
|
|
HINSTANCE hInst,
|
|
DWORD dwReason,
|
|
LPVOID lpReserved
|
|
);
|
|
void NotifyCOMOnSuspend();
|
|
void NotifyCOMOnResume();
|
|
|
|
extern DWORD gLockTlsIdx;
|
|
SERVICE_TABLE_ENTRY gaServiceEntryTable[] = {
|
|
{ SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
static SERVICE_STATUS gServiceStatus;
|
|
static SERVICE_STATUS_HANDLE ghServiceHandle;
|
|
|
|
GUID gProcessGuid = GUID_NULL;
|
|
|
|
|
|
#define OFFSET_TO_PTR(val, start) \
|
|
(val) = ((val) == NULL) ? NULL : (PWCHAR) ( (PCHAR)(val) + (ULONG_PTR)(start))
|
|
|
|
EXTERN_C const IID IID_IAssertConfig; // make the linker happy
|
|
|
|
void
|
|
CookupNodeId(PUCHAR NodeId)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is called when all else fails. Here we mix a bunch of
|
|
system parameters together for a 47bit node ID.
|
|
|
|
Arguments:
|
|
|
|
NodeId - Will be set to a value unlikly to be duplicated on another
|
|
machine. It is not guaranteed to be unique even on this machine.
|
|
But since UUIDs are (time + sequence) this is okay for
|
|
a local UUID.
|
|
|
|
It will be composed of:
|
|
The computer name.
|
|
The value of the performance counter.
|
|
The system memory status.
|
|
The total bytes and free bytes on C:
|
|
The stack pointer (value).
|
|
An LUID (locally unique ID)
|
|
Plus whatever random stuff was in the NodeId to begin with.
|
|
|
|
The NodeId returned is explicity made into a Multicast IEEE 802
|
|
address so that it will not conflict with a 'real' IEEE 802
|
|
based UUID.
|
|
--*/
|
|
{
|
|
unsigned char LocalNodeId[6]; // NOT initialized.
|
|
unsigned char ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
|
BOOL BoolResult;
|
|
ULONG i = MAX_COMPUTERNAME_LENGTH+1;
|
|
LARGE_INTEGER largeInt;
|
|
LUID luid;
|
|
ULONG UNALIGNED *NodeIdPart1 = (ULONG *)&LocalNodeId[0]; // Bytes 0 - 3
|
|
ULONG UNALIGNED *NodeIdPart2 = (ULONG *)&LocalNodeId[2]; // Bytes 2 - 5
|
|
MEMORYSTATUS memStatus;
|
|
ULONG SectorsPerCluster;
|
|
ULONG BytesPerSector;
|
|
ULONG TotalClusters;
|
|
ULONG FreeClusters;
|
|
|
|
// Initialize the LocalNodeId. Seventeen is the most random, random number.
|
|
|
|
memset(LocalNodeId, 17, sizeof(LocalNodeId));
|
|
|
|
// The computer name is xor'ed in until it runs out.
|
|
|
|
BoolResult =
|
|
GetComputerNameA((CHAR *)ComputerName, &i);
|
|
|
|
if (BoolResult)
|
|
{
|
|
unsigned char *p = ComputerName;
|
|
i = 0;
|
|
while(*p)
|
|
{
|
|
*( ((unsigned char *)LocalNodeId) + i) ^= *p++;
|
|
if (++i > 6)
|
|
{
|
|
i = 0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint ("GetComputerName failed - %d\n", GetLastError());
|
|
#endif
|
|
}
|
|
|
|
// The performance counter is xor'ed into the LocalNodeId.
|
|
|
|
BoolResult =
|
|
QueryPerformanceCounter(&largeInt);
|
|
|
|
if (BoolResult)
|
|
{
|
|
*NodeIdPart2 ^= largeInt.HighPart ^ largeInt.LowPart;
|
|
*NodeIdPart1 ^= largeInt.HighPart ^ largeInt.LowPart;
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint ("QueryPreformanceCount failed - %d\n", GetLastError());
|
|
#endif
|
|
}
|
|
|
|
// The current SP is xor'ed into both parts of the LocalNodeId.
|
|
|
|
*NodeIdPart1 ^= (ULONG_PTR)&LocalNodeId;
|
|
*NodeIdPart2 ^= (ULONG_PTR)&LocalNodeId;
|
|
|
|
// The memory status is Xor's into the LocalNodeId.
|
|
memStatus.dwLength = sizeof(MEMORYSTATUS);
|
|
|
|
GlobalMemoryStatus(&memStatus);
|
|
|
|
*NodeIdPart1 ^= memStatus.dwMemoryLoad;
|
|
*NodeIdPart2 ^= memStatus.dwTotalPhys;
|
|
*NodeIdPart1 ^= memStatus.dwAvailPhys;
|
|
*NodeIdPart1 ^= memStatus.dwTotalPageFile;
|
|
*NodeIdPart2 ^= memStatus.dwAvailPageFile;
|
|
*NodeIdPart2 ^= memStatus.dwTotalVirtual;
|
|
*NodeIdPart1 ^= memStatus.dwAvailVirtual;
|
|
|
|
// LUID's are good on this machine during this boot only.
|
|
|
|
BoolResult =
|
|
AllocateLocallyUniqueId(&luid);
|
|
|
|
if (BoolResult)
|
|
{
|
|
*NodeIdPart1 ^= luid.LowPart;
|
|
*NodeIdPart2 ^= luid.HighPart;
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint ("Status %d\n", GetLastError());
|
|
#endif
|
|
}
|
|
|
|
// Disk parameters and free space
|
|
|
|
BoolResult =
|
|
GetDiskFreeSpaceA("c:\\",
|
|
&SectorsPerCluster,
|
|
&BytesPerSector,
|
|
&FreeClusters,
|
|
&TotalClusters
|
|
);
|
|
|
|
if (BoolResult)
|
|
{
|
|
*NodeIdPart2 ^= TotalClusters * SectorsPerCluster * BytesPerSector;
|
|
*NodeIdPart1 ^= FreeClusters * SectorsPerCluster * BytesPerSector;
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint ("GetDiskFreeSpace failed - %d\n", GetLastError());
|
|
#endif
|
|
}
|
|
|
|
// Or in the 'multicast' bit to distinguish this NodeId
|
|
// from all other possible IEEE 802 addresses.
|
|
|
|
LocalNodeId[0] |= 0x80;
|
|
|
|
memcpy(NodeId, LocalNodeId, 6);
|
|
}
|
|
|
|
BOOLEAN
|
|
getMacAddress (
|
|
PUCHAR pMacAddress
|
|
)
|
|
/*++
|
|
Function Name:getMacAddress
|
|
|
|
Parameters:
|
|
|
|
Description:
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
int i;
|
|
UINT fStatus;
|
|
int Size = 1024*5;
|
|
PNDIS_ENUM_INTF Interfaces;
|
|
UCHAR OidVendData[16];
|
|
|
|
Interfaces = (PNDIS_ENUM_INTF) I_RpcAllocate (Size);
|
|
if (Interfaces == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (NdisEnumerateInterfaces(Interfaces, Size))
|
|
{
|
|
UINT i;
|
|
|
|
for (i = 0; i < Interfaces->TotalInterfaces; i++)
|
|
{
|
|
PUNICODE_STRING pDeviceName= &(Interfaces->Interface[i].DeviceName);
|
|
UCHAR PermMacAddr[6];
|
|
|
|
fStatus = NdisQueryHwAddress(pDeviceName, pMacAddress, PermMacAddr, &OidVendData[0]);
|
|
if (fStatus && (OidVendData[0] != 0xFF
|
|
|| OidVendData[1] != 0xFF
|
|
|| OidVendData[2] != 0xFF))
|
|
{
|
|
I_RpcFree (Interfaces);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
I_RpcFree (Interfaces);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
extern "C" void
|
|
DealWithDeviceEvent()
|
|
/*++
|
|
Function Name: DealWithDeviceEvent
|
|
|
|
Parameters:
|
|
|
|
Description:
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
{
|
|
UCHAR MacAddress[8];
|
|
NTSTATUS NtStatus;
|
|
|
|
if (getMacAddress(&MacAddress[0]))
|
|
{
|
|
NtStatus = NtSetUuidSeed((PCHAR) &MacAddress[0]);
|
|
}
|
|
else
|
|
{
|
|
CookupNodeId(&MacAddress[0]);
|
|
|
|
ASSERT(MacAddress[0] & 0x80);
|
|
|
|
NtStatus = NtSetUuidSeed((PCHAR) &MacAddress[0]);
|
|
}
|
|
|
|
if (!NT_SUCCESS(NtStatus))
|
|
{
|
|
#if DBG
|
|
DbgPrint("NtSetUuidSeed failed\n", NtStatus);
|
|
#endif
|
|
}
|
|
|
|
#if !defined(SPX_IPX_OFF)
|
|
UpdateSap( SAP_CTRL_UPDATE_ADDRESS );
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
void
|
|
DealWithPowerStatusEvent(DWORD dwEvent)
|
|
{
|
|
switch (dwEvent)
|
|
{
|
|
//
|
|
// First the events we care about
|
|
//
|
|
case PBT_APMSUSPEND: // System is suspending operation.
|
|
NotifyCOMOnSuspend();
|
|
break;
|
|
|
|
case PBT_APMRESUMESUSPEND: // Operation resuming after suspension.
|
|
// This is the normal, user-initiated resume after a suspend.
|
|
NotifyCOMOnResume();
|
|
break;
|
|
|
|
case PBT_APMRESUMEAUTOMATIC: // Operation resuming automatically after event.
|
|
// For our purposes this is a regular resume, since we don't have any
|
|
// direct dialogue with the user. Eg, wake-on-lan might cause this.
|
|
NotifyCOMOnResume();
|
|
break;
|
|
|
|
case PBT_APMRESUMECRITICAL: // Operation resuming after critical suspension.
|
|
// This means we're resuming w/o previously having had a suspend
|
|
// notification. May have lost state (ie, ping set timers may have
|
|
// rundown). Let's process the resume anyway, so that the ping set
|
|
// timers start from scratch (might save somebody from a transient app
|
|
// error).
|
|
NotifyCOMOnResume();
|
|
break;
|
|
|
|
//
|
|
// And then the ones we don't care about.
|
|
//
|
|
case PBT_APMBATTERYLOW: // Battery power is low.
|
|
case PBT_APMOEMEVENT: // OEM-defined event occurred.
|
|
case PBT_APMPOWERSTATUSCHANGE: // Power status has changed.
|
|
case PBT_APMQUERYSUSPEND: // Request for permission to suspend.
|
|
case PBT_APMQUERYSUSPENDFAILED: // Suspension request denied.
|
|
break;
|
|
|
|
default:
|
|
ASSERT(!"Unexpected power event. Check to see if we should be dealing with it somehow.");
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
ULONG WINAPI
|
|
ServiceHandler(
|
|
DWORD dwCode,
|
|
DWORD dwEventType,
|
|
PVOID EventData,
|
|
PVOID pData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lowest level callback from the service controller to
|
|
cause this service to change our status. (stop, start, pause, etc).
|
|
|
|
Arguments:
|
|
|
|
opCode - One of the service "Controls" value.
|
|
SERVICE_CONTROL_{STOP, PAUSE, CONTINUE, INTERROGATE, SHUTDOWN}.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
switch(dwCode) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
case SERVICE_CONTROL_PAUSE:
|
|
case SERVICE_CONTROL_CONTINUE:
|
|
default:
|
|
#if DBG
|
|
DbgPrint("%S: Unexpected service control message %d.\n", SERVICE_NAME, dwCode);
|
|
#endif
|
|
ASSERT(0);
|
|
break;
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
// Service controller wants us to call SetServiceStatus.
|
|
|
|
UpdateState(gServiceStatus.dwCurrentState);
|
|
break ;
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN:
|
|
// The machine is shutting down. We'll be killed once we return.
|
|
// Note, currently we don't register for these messages.
|
|
break;
|
|
|
|
case SERVICE_CONTROL_POWEREVENT:
|
|
DealWithPowerStatusEvent(dwEventType);
|
|
break;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
UpdateState(
|
|
DWORD dwNewState
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Updates this services state with the service controller.
|
|
|
|
Arguments:
|
|
|
|
dwNewState - The next start for this service. One of
|
|
SERVICE_START_PENDING
|
|
SERVICE_RUNNING
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
ASSERT( (dwNewState == SERVICE_RUNNING) ||
|
|
(gServiceStatus.dwCurrentState != SERVICE_RUNNING) );
|
|
|
|
switch (dwNewState)
|
|
{
|
|
|
|
case SERVICE_RUNNING:
|
|
case SERVICE_STOPPED:
|
|
gServiceStatus.dwCheckPoint = 0;
|
|
gServiceStatus.dwWaitHint = 0;
|
|
break;
|
|
|
|
case SERVICE_START_PENDING:
|
|
case SERVICE_STOP_PENDING:
|
|
++gServiceStatus.dwCheckPoint;
|
|
gServiceStatus.dwWaitHint = 30000L;
|
|
break;
|
|
|
|
default:
|
|
ASSERT(0);
|
|
status = ERROR_INVALID_SERVICE_CONTROL;
|
|
break;
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
gServiceStatus.dwCurrentState = dwNewState;
|
|
if (!SetServiceStatus(ghServiceHandle, &gServiceStatus))
|
|
{
|
|
status = GetLastError();
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DbgPrint("%S: Failed to update service state: %d\n", SERVICE_NAME, status);
|
|
}
|
|
#endif
|
|
|
|
// We could return a status but how would we recover? Ignore it, the
|
|
// worst thing is that services will kill us and there's nothing
|
|
// we can about it if this call fails.
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID WINAPI
|
|
ServiceMain(
|
|
DWORD argc,
|
|
PWSTR argv[]
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback by the service controller when starting this service.
|
|
|
|
Arguments:
|
|
|
|
argc - number of arguments, usually 1
|
|
|
|
argv - argv[0] is the name of the service.
|
|
argv[>0] are arguments passed to the service.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DWORD status = ERROR_SUCCESS;
|
|
|
|
// COM needs power standby\resume events
|
|
const DWORD RPCSS_CONTROLS = SERVICE_ACCEPT_POWEREVENT;
|
|
|
|
//
|
|
// Initialize SafeAlloca
|
|
//
|
|
SafeAllocaInitialize (
|
|
(MAX_PATH + 3) * sizeof (WCHAR), // alloca at most a MAX_PATH WCHAR buffer
|
|
SAFEALLOCA_USE_DEFAULT, // use default additional probe size
|
|
NULL, NULL); // use default heap allocators
|
|
|
|
// set the initial stack to 12K. This ensures enough commit
|
|
// so that server threads don't need to extend their stacks
|
|
RpcMgmtSetServerStackSize(3 * 4096);
|
|
|
|
DealWithDeviceEvent();
|
|
|
|
ASSERT( (argc >= 1 && lstrcmpiW(argv[0], SERVICE_NAME) == 0)
|
|
|| (argc == 0 && argv == 0));
|
|
|
|
#if DBG==1
|
|
|
|
// Note that we've completed running the static constructors
|
|
ASSERT(g_fDllState == DLL_STATE_STATIC_CONSTRUCTING);
|
|
g_fDllState = DLL_STATE_NORMAL;
|
|
|
|
#endif
|
|
|
|
// Create a secret guid for the process
|
|
RPC_STATUS sc = UuidCreate (&gProcessGuid);
|
|
if (sc != RPC_S_OK)
|
|
return;
|
|
|
|
// Initialize the mutex package
|
|
status = RtlInitializeCriticalSection(&g_OleMutexCreationSem);
|
|
if (!NT_SUCCESS(status))
|
|
return;
|
|
|
|
status = RtlInitializeCriticalSection(&g_OleGlobalLock);
|
|
if (!NT_SUCCESS(status))
|
|
return;
|
|
|
|
// Init machine name object
|
|
if (!gpMachineName->Initialize())
|
|
return;
|
|
|
|
// Initialize TLS
|
|
gLockTlsIdx = TlsAlloc();
|
|
if (gLockTlsIdx == -1)
|
|
return;
|
|
|
|
// Initialize catalog
|
|
CatalogDllMain (NULL, DLL_PROCESS_ATTACH, NULL);
|
|
|
|
// Tell catalog it's running in SCM
|
|
g_bInSCM = TRUE;
|
|
|
|
gServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
gServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
gServiceStatus.dwControlsAccepted = RPCSS_CONTROLS;
|
|
gServiceStatus.dwWin32ExitCode = 0;
|
|
gServiceStatus.dwServiceSpecificExitCode = 0;
|
|
gServiceStatus.dwCheckPoint = 0;
|
|
gServiceStatus.dwWaitHint = 3000L;
|
|
|
|
ghServiceHandle = RegisterServiceCtrlHandlerEx(SERVICE_NAME,
|
|
ServiceHandler,
|
|
UIntToPtr(0xCAFECAFE) );
|
|
|
|
if (0 == ghServiceHandle)
|
|
{
|
|
status = GetLastError();
|
|
ASSERT(status != ERROR_SUCCESS);
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_START_PENDING);
|
|
}
|
|
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// epts.c
|
|
status = InitializeEndpointManager();
|
|
}
|
|
|
|
|
|
// Start Ep Mapper.
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\epmap\server.c
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = StartEndpointMapper();
|
|
}
|
|
|
|
#ifdef NCADG_MQ_ON
|
|
// Start MQ Manager Interface
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = StartMqManagement();
|
|
}
|
|
#endif // NCADG_MQ_ON
|
|
|
|
// Do pre-listen olescm initialization
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = InitializeSCMBeforeListen();
|
|
}
|
|
|
|
// Start object resolver
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\objex\objex.cxx
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = StartObjectExporter();
|
|
}
|
|
|
|
// Start OLESCM
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_START_PENDING);
|
|
status = InitializeSCM();
|
|
}
|
|
|
|
// Start listening for RPC requests
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
status = RpcServerListen(1, 1234, TRUE);
|
|
|
|
if (status == RPC_S_OK)
|
|
{
|
|
while (RpcMgmtIsServerListening(0) == RPC_S_NOT_LISTENING)
|
|
{
|
|
Sleep(100);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// There is some initialization that must be done after we
|
|
// have done the RpcServerListen.
|
|
//
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
// ..\olescm\scmsvc.cxx
|
|
UpdateState(SERVICE_START_PENDING);
|
|
InitializeSCMAfterListen();
|
|
}
|
|
|
|
// Trim our working set - free space now at the cost of time later.
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
UpdateState(SERVICE_RUNNING);
|
|
}
|
|
|
|
#ifdef DEBUGRPC
|
|
if (status != ERROR_SUCCESS)
|
|
{
|
|
DbgPrint("RPCSS ServiceMain failed %d (%08x)\n", status, status);
|
|
}
|
|
#endif
|
|
NTSTATUS lsaStatus;
|
|
if (status == ERROR_SUCCESS)
|
|
{
|
|
lsaStatus= ConnectToLsa();
|
|
if (NT_SUCCESS(lsaStatus))
|
|
{
|
|
lsaStatus = GetDefaultDomainName();
|
|
}
|
|
}
|
|
if (status == ERROR_SUCCESS && NT_SUCCESS(lsaStatus))
|
|
{
|
|
ObjectExporterWorkerThread(0);
|
|
ASSERT(0);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void CleanupTLS()
|
|
{
|
|
if(gLockTlsIdx == -1)
|
|
return;
|
|
|
|
LockEntry* pLockEntry = reinterpret_cast<LockEntry*>(TlsGetValue(gLockTlsIdx));
|
|
TlsSetValue(gLockTlsIdx, 0);
|
|
|
|
while(pLockEntry)
|
|
{
|
|
LockEntry* pNextLockEntry = pLockEntry->pNext;
|
|
PrivMemFree(pLockEntry);
|
|
pLockEntry = pNextLockEntry;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
extern "C" BOOL WINAPI DllMain(
|
|
HANDLE hInstance,
|
|
DWORD dwReason,
|
|
LPVOID lpvReserved)
|
|
{
|
|
// Normally we would call CleanupTLS() and TlsFree()
|
|
// from withing the DLL_PROCESS_DETACH case, but
|
|
// since this is rpcss we should be running
|
|
// until the machine shuts down.
|
|
|
|
switch(dwReason)
|
|
{
|
|
case DLL_THREAD_DETACH:
|
|
CleanupTLS();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
extern HRESULT PrivGetRPCSSInfo(REFCLSID rclsid, REFIID riid, void** pIntf);
|
|
|
|
extern "C"
|
|
{
|
|
|
|
STDAPI GetRPCSSInfo(REFCLSID rclsid, REFIID riid, void** ppv)
|
|
{
|
|
return PrivGetRPCSSInfo(rclsid, riid, ppv);
|
|
};
|
|
|
|
STDAPI GetCatalogHelper(REFIID riid, void** ppv);
|
|
|
|
STDAPI CoGetComCatalog(REFIID riid, void** ppv)
|
|
{
|
|
return GetCatalogHelper (riid, ppv);
|
|
}
|
|
|
|
}
|