788 lines
19 KiB
C++
788 lines
19 KiB
C++
|
/*++
|
|||
|
|
|||
|
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>
|
|||
|
|
|||
|
#ifndef SPX_IPX_OFF
|
|||
|
#include "sap.h"
|
|||
|
#endif
|
|||
|
|
|||
|
#include "../../com/inc/secdes.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;
|
|||
|
|
|||
|
|
|||
|
#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;
|
|||
|
|
|||
|
// 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
|
|||
|
|
|||
|
// Initialize the mutex package
|
|||
|
status = RtlInitializeCriticalSection(&g_OleMutexCreationSem);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
return;
|
|||
|
|
|||
|
// Initialize TLS
|
|||
|
gLockTlsIdx = TlsAlloc();
|
|||
|
if (gLockTlsIdx == -1)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// Initialize catalog
|
|||
|
CatalogDllMain (NULL, DLL_PROCESS_ATTACH, NULL);
|
|||
|
|
|||
|
{ // Create a named event for Vista to toggle event logging
|
|||
|
|
|||
|
// Check to see if the event logging is installed and enabled
|
|||
|
//
|
|||
|
long cb = 128;
|
|||
|
char szValue[128];
|
|||
|
if (RegQueryValueA(HKEY_CLASSES_ROOT,
|
|||
|
"CLSID\\{6C736DB0-BD94-11D0-8A23-00AA00B58E10}\\EnableEvents",
|
|||
|
szValue, &cb) == ERROR_SUCCESS && !strcmp(szValue, "1"))
|
|||
|
{
|
|||
|
// [Sergei O. Ivanov (a-sergiv), 28-Jun-99]
|
|||
|
// This code here used to grant access to the whole world. But the world
|
|||
|
// tends to try and mess you up. So we'll only grant them limited access.
|
|||
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|||
|
PSID pSidEveryone = NULL;
|
|||
|
PACL pAcl = NULL;
|
|||
|
DWORD cbAcl = 0;
|
|||
|
ACCESS_ALLOWED_ACE *pAce = NULL;
|
|||
|
|
|||
|
AllocateAndInitializeSid(&SidAuthority, 1, SECURITY_WORLD_RID,
|
|||
|
0, 0, 0, 0, 0, 0, 0, &pSidEveryone);
|
|||
|
|
|||
|
if(pSidEveryone)
|
|||
|
{
|
|||
|
cbAcl = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSidEveryone);
|
|||
|
pAcl = (PACL) LocalAlloc(LMEM_FIXED, cbAcl);
|
|||
|
|
|||
|
if(pAcl)
|
|||
|
{
|
|||
|
InitializeAcl(pAcl, cbAcl, ACL_REVISION);
|
|||
|
AddAccessAllowedAce(pAcl, ACL_REVISION, EVENT_QUERY_STATE|EVENT_MODIFY_STATE|SYNCHRONIZE|READ_CONTROL, pSidEveryone);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// Create security descriptor and attach the DACL to it
|
|||
|
SECURITY_DESCRIPTOR sd;
|
|||
|
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
|||
|
SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE);
|
|||
|
|
|||
|
SECURITY_ATTRIBUTES sa;
|
|||
|
sa.nLength = sizeof(sa);
|
|||
|
sa.bInheritHandle = FALSE;
|
|||
|
sa.lpSecurityDescriptor = &sd;
|
|||
|
|
|||
|
// The toggle event, which is signaled by LEC and checked by all.
|
|||
|
|
|||
|
// The handle never closes during the process
|
|||
|
HANDLE hLeak1 = CreateEventA(
|
|||
|
&sa, /* Security */
|
|||
|
TRUE, /* Manual reset */
|
|||
|
FALSE, /* InitialState is non-signaled */
|
|||
|
"MSFT.VSA.IEC.STATUS.6c736db0" /* Name */
|
|||
|
);
|
|||
|
|
|||
|
if(pSidEveryone) FreeSid(pSidEveryone);
|
|||
|
if(pAcl) LocalFree(pAcl);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 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();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#ifndef _CHICAGO_
|
|||
|
// 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
|
|||
|
#endif
|
|||
|
|
|||
|
// 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
|
|||
|
|
|||
|
if (status == ERROR_SUCCESS)
|
|||
|
{
|
|||
|
ObjectExporterWorkerThread(0);
|
|||
|
ASSERT(0);
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|
|||
|
}
|