mirror of https://github.com/lianthony/NT4.0
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.
460 lines
8.2 KiB
460 lines
8.2 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
system.cxx
|
|
|
|
Abstract:
|
|
|
|
This file contains the system dependent functions for Windows NT.
|
|
|
|
Author:
|
|
|
|
Steven Zeck (stevez) 07/01/91
|
|
|
|
--*/
|
|
extern "C" {
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
}
|
|
|
|
#include <windef.h> // Base windows types
|
|
#include <winbase.h>
|
|
#include <winsvc.h>
|
|
|
|
#include <lmcons.h> // LAN Manager common definitions
|
|
#include <lmapibuf.h> // Buffer stuff
|
|
#include <lmwksta.h> // Workstation class
|
|
|
|
#include "core.hxx"
|
|
|
|
int hDebugFile = 1; // use standard out by default
|
|
TIME LoadTime; // time the locator loaded
|
|
unsigned long LoadTimeinSecs;
|
|
|
|
SERVICE_STATUS ServiceStatus;
|
|
SERVICE_STATUS_HANDLE ServiceHandle;
|
|
|
|
|
|
|
|
void
|
|
SetStatus(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set the lanman service status.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(ServiceHandle);
|
|
|
|
if (! SetServiceStatus( ServiceHandle, &ServiceStatus))
|
|
ASSERT(!"SetServiceStatus");
|
|
}
|
|
|
|
|
|
void
|
|
LocatorControl(
|
|
IN DWORD opCode // function that we are to carry out.
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function responses the service control requests.
|
|
|
|
Arguments:
|
|
|
|
opCode - Function that we are to carry out.
|
|
|
|
--*/
|
|
{
|
|
RPC_STATUS status;
|
|
|
|
switch(opCode) {
|
|
|
|
case SERVICE_CONTROL_STOP:
|
|
|
|
// Announce that the service is shutting down
|
|
|
|
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
|
ServiceStatus.dwWaitHint = 3000;
|
|
SetStatus();
|
|
status = RpcMgmtStopServerListening(0);
|
|
ASSERT(!status);
|
|
break;
|
|
|
|
case SERVICE_CONTROL_INTERROGATE:
|
|
|
|
// Do nothing; the status gets announced below
|
|
|
|
SetStatus();
|
|
break ;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
LocatorServiceMain(
|
|
DWORD argc,
|
|
LPTSTR *argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is main function for the locator service.
|
|
When we are started as a service, the service control creates a new
|
|
thread and calls this function.
|
|
|
|
Arguments:
|
|
|
|
argc - argument count
|
|
|
|
argv - vector of argument pointers
|
|
|
|
RegKeyPath - registry path for this conponet.,
|
|
|
|
--*/
|
|
{
|
|
|
|
LPTSTR *aSZParms = new LPSTR[argc+1];
|
|
char *BadArg;
|
|
|
|
// Make a Copy of the vector and 0 terminate.
|
|
|
|
memcpy(aSZParms, argv, sizeof(LPSTR) * (int) argc);
|
|
aSZParms[argc] = 0;
|
|
|
|
BadArg = ProcessArgs(aSwitchs, ++aSZParms);
|
|
|
|
// Set up the service info structure to indicate the status.
|
|
|
|
ServiceStatus.dwServiceType = SERVICE_WIN32;
|
|
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
|
|
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
|
ServiceStatus.dwWin32ExitCode = 0;
|
|
ServiceStatus.dwCheckPoint = 0;
|
|
ServiceStatus.dwWaitHint = 0;
|
|
|
|
// Set up control handler
|
|
|
|
if (! (ServiceHandle = RegisterServiceCtrlHandler (
|
|
"locator", LocatorControl)))
|
|
|
|
AbortServer("RegisterServiceCtrlHandler", (int) GetLastError());
|
|
|
|
// Bail out on bad arguments.
|
|
|
|
if (BadArg) {
|
|
char errLine[500];
|
|
|
|
ServiceStatus.dwWin32ExitCode = ERROR_INVALID_PARAMETER;
|
|
|
|
AbortServer((SZ) strcat(strcpy(
|
|
errLine, "Command Line Error: "), BadArg));
|
|
}
|
|
|
|
// Start the RPC server. We won't return until stopped.
|
|
|
|
SetStatus();
|
|
StartServer();
|
|
|
|
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
|
SetStatus();
|
|
RpcMgmtWaitServerListen();
|
|
|
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
|
SetStatus();
|
|
}
|
|
|
|
|
|
void
|
|
SystemInit (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
System dependent initialization, Initialize data structures
|
|
for Windows NT based operation.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
void * pThreadHandle;
|
|
DWORD ThreadID;
|
|
UICHAR Buffer[200];
|
|
int cbSelfName;
|
|
|
|
static SERVICE_TABLE_ENTRY ServiceEntry [] = {
|
|
"locator", (LPSERVICE_MAIN_FUNCTION) LocatorServiceMain, 0, 0
|
|
};
|
|
|
|
NtQuerySystemTime(&LoadTime);
|
|
RtlTimeToSecondsSince1980(&LoadTime, &LoadTimeinSecs);
|
|
|
|
if (! fService)
|
|
*cout << "Microsoft RPC Locator Starting..\n";
|
|
|
|
// Get the name of this work station into global buffer.
|
|
|
|
WKSTA_INFO_100 *WorkInfo;
|
|
|
|
NET_API_STATUS NetStatus = NetWkstaGetInfo(NIL, 100, (LPBYTE *) &WorkInfo);
|
|
|
|
if (NetStatus)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
|
|
DbgPrint("RPC Locator: NetWkstaGetInfo returned %lu\n", NetStatus);
|
|
DbgBreakPoint();
|
|
|
|
#endif
|
|
AbortServer("netwkstaGetInfo failed", NetStatus);
|
|
}
|
|
|
|
if (0 == WorkInfo->wki100_computername)
|
|
{
|
|
#ifdef DEBUGRPC
|
|
|
|
DbgPrint("RPC Locator: NetWkstaGetInfo returned null computer name\n");
|
|
DbgBreakPoint();
|
|
|
|
#endif
|
|
AbortServer("null computer name");
|
|
}
|
|
|
|
// put self name in global place
|
|
|
|
Buffer[0] = 0;
|
|
|
|
CatUZ(CatUZ(Buffer, (PUZ) L"\\\\"), (PUZ) WorkInfo->wki100_computername);
|
|
|
|
SelfName = (PUZ) NewCopy(Buffer, (LenUZ(Buffer)+1)*sizeof(UICHAR));
|
|
|
|
DomainName = (PUZ) NewCopy(WorkInfo->wki100_langroup,
|
|
(LenUZ((PUZ) WorkInfo->wki100_langroup)+1)*sizeof(UICHAR));
|
|
|
|
if (!SelfName || !DomainName)
|
|
AbortServer("Out of Memory");
|
|
|
|
status = NetApiBufferFree((LPBYTE) WorkInfo);
|
|
|
|
ASSERT(!status);
|
|
|
|
DLIST(2, "My workstation name: " << SelfName << nl);
|
|
|
|
pThreadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) QueryProcess, 0, 0, &ThreadID);
|
|
|
|
if (!pThreadHandle)
|
|
AbortServer("CreateThread", (int) GetLastError());
|
|
|
|
// Start the RPC service now if not running under the service controller.
|
|
|
|
if (!fService)
|
|
{
|
|
StartServer();
|
|
RpcMgmtWaitServerListen();
|
|
|
|
return;
|
|
}
|
|
|
|
// Call (give this thread) to the service controller.
|
|
|
|
StartServiceCtrlDispatcher(ServiceEntry);
|
|
}
|
|
|
|
|
|
void
|
|
AbortServer(
|
|
IN SZ szReason,
|
|
IN int code
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Die a graceful death for the server.
|
|
|
|
Arguments:
|
|
|
|
szReason - Text message for death
|
|
|
|
code - option error code
|
|
|
|
--*/
|
|
{
|
|
|
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
|
|
|
|
|
ServiceStatus.dwServiceSpecificExitCode = code;
|
|
|
|
if (code)
|
|
ServiceStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
|
|
|
|
if (fService && ServiceHandle)
|
|
SetStatus();
|
|
|
|
*cout << "Locator Aborting: " << szReason;
|
|
|
|
if (code)
|
|
*cout << ": " << code;
|
|
else
|
|
code = -1;
|
|
|
|
*cout << nl;
|
|
|
|
ExitProcess(code);
|
|
}
|
|
|
|
|
|
unsigned long
|
|
CurrentTime (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the current time in seconds.
|
|
|
|
Returns:
|
|
|
|
The time.
|
|
|
|
--*/
|
|
{
|
|
TIME time;
|
|
ULONG seconds;
|
|
|
|
// QUERY the current time; this time is in some funky Nt specific
|
|
// format and scale & Convert it into seconds since 1980.
|
|
|
|
NtQuerySystemTime(&time);
|
|
RtlTimeToSecondsSince1980(&time, &seconds);
|
|
|
|
return(seconds);
|
|
}
|
|
|
|
unsigned long
|
|
CurrentTimeMS (
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the current time in 1000th of a second.
|
|
|
|
Returns:
|
|
|
|
The time.
|
|
|
|
--*/
|
|
{
|
|
TIME time;
|
|
unsigned long TimeinSecs;
|
|
// QUERY the current time; this time is in some funky Nt specific
|
|
// format and scale (1/10,000). Form the delta between the load
|
|
// time and the current time.
|
|
|
|
NtQuerySystemTime(&time);
|
|
RtlTimeToSecondsSince1980(&time, &TimeinSecs);
|
|
|
|
/*
|
|
|
|
Alpha Compiler Chokes Here
|
|
|
|
|
|
return( RtlLargeIntegerSubtract(*(PLARGE_INTEGER) &time,
|
|
*(PLARGE_INTEGER) &LoadTime).LowPart / 10);
|
|
|
|
*/
|
|
|
|
return(TimeinSecs - LoadTimeinSecs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// *** Misc helper functions *** //
|
|
|
|
|
|
void
|
|
DEBUG_STREAM::FlushBuffer(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a buffer to the dug console.
|
|
|
|
Arguments:
|
|
|
|
--*/
|
|
{
|
|
if (fService) {
|
|
|
|
base[pptr-base] = 0;
|
|
#if DBG
|
|
DbgPrint(base);
|
|
#endif
|
|
}
|
|
else
|
|
_write(hDebugFile, base, pptr-base);
|
|
}
|
|
|
|
|
|
void
|
|
CONSOLE_STREAM::FlushBuffer(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Dump a buffer to the console.
|
|
|
|
Arguments:
|
|
|
|
--*/
|
|
{
|
|
if (fService)
|
|
((DEBUG_STREAM *)this)->DEBUG_STREAM::FlushBuffer();
|
|
else
|
|
_write(1, base, pptr-base);
|
|
}
|
|
|
|
|
|
#if DBG
|
|
|
|
int AssertHeap(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Call the NT Rtl runtime functions to check the heap.
|
|
|
|
Returns:
|
|
|
|
TRUE if the heap is NOT corrupted.
|
|
|
|
--*/
|
|
{
|
|
static BOOL fHeapTrashed;
|
|
|
|
if (!fHeapTrashed) {
|
|
fHeapTrashed = RtlValidateHeap( RtlProcessHeap(), 0, NULL ) == 0;
|
|
}
|
|
|
|
return(!fHeapTrashed);
|
|
}
|
|
|
|
#endif // DBG
|