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.
 
 
 
 
 
 

914 lines
24 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
main.c
Abstract:
This is the main entry point for the service control manager for the web
dav mini-redir service.
Author:
Rohan Kumar [RohanK] 08-Feb-2000
Environment:
User Mode - Win32
Revision History:
--*/
#include "pch.h"
#pragma hdrstop
#include <ntumrefl.h>
#include <usrmddav.h>
#include <svcs.h>
//
// Allocate global data in this file.
//
#define GLOBAL_DATA_ALLOCATE
#include "global.h"
DWORD DavStop = 0;
//
// The amount of time in seconds a server entry is cached in the ServerNotFound
// cache.
//
ULONG ServerNotFoundCacheLifeTimeInSec = 0;
//
// Should we accept/claim the OfficeWebServers and TahoeWebServers?
//
ULONG AcceptOfficeAndTahoeServers = 0;
//
// Should we LOCK (using the DAV LOCK Verb) the file on the server on the
// CreateFile path when needed? To know when exactly a LOCK is sent to the
// server, look at the (LOCKing) comments in the davcreat.c file.
//
ULONG DavSupportLockingOfFiles = 1;
PSVCHOST_GLOBAL_DATA DavSvcsGlobalData;
DWORD
DavNotRunningAsAService(
VOID
);
DWORD
WINAPI
DavFakeServiceController(
LPVOID Parameter
);
BOOL
DavCheckLUIDDeviceMapsEnabled(
VOID
);
VOID
DavReadRegistryValues(
VOID
);
VOID
WINAPI
DavServiceHandler (
DWORD dwOpcode
)
/*++
Routine Description:
This function is called by the Service Controller at various times when the
service is running.
Arguments:
dwOpcode - Reason for calling the service handler.
Return Value:
none.
--*/
{
DWORD err;
switch (dwOpcode) {
case SERVICE_CONTROL_SHUTDOWN:
//
// Lack of break is intentional!
//
case SERVICE_CONTROL_STOP:
DavPrint((DEBUG_INIT, "DavServiceHandler: WebClient service is stopping.\n"));
UpdateServiceStatus(SERVICE_STOP_PENDING);
if (g_WorkersActive) {
err = DavTerminateWorkerThreads();
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/DavTerminateWorkerThreads: "
"Error Val = %u.\n", err));
}
g_WorkersActive = FALSE;
}
if (g_RpcActive) {
DavSvcsGlobalData->StopRpcServer(davclntrpc_ServerIfHandle);
g_RpcActive = FALSE;
}
//
// Close and free up the DAV stuff.
//
DavClose();
if (g_socketinit) {
err = CleanupTheSocketInterface();
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/CleanupTheSocketInterface: "
"Error Val = %u.\n", err));
}
g_socketinit = FALSE;
}
if (DavReflectorHandle != NULL) {
err = UMReflectorStop(DavReflectorHandle);
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorStop: Error Val = %u.\n", err));
}
err = UMReflectorUnregister(DavReflectorHandle);
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorUnregister: Error Val = 0x%x.\n", err));
}
DavReflectorHandle = NULL;
}
if (g_RedirLoaded) {
err = WsUnloadRedir();
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/WsUnloadRedir: Error Val = %u.\n", err));
}
g_RedirLoaded = FALSE;
}
if (g_DavServiceLockSet) {
DeleteCriticalSection ( &(g_DavServiceLock) );
g_DavServiceLockSet = FALSE;
}
DavPrint((DEBUG_INIT, "DavServiceMain: WebClient service is stopped.\n"));
UpdateServiceStatus(SERVICE_STOPPED);
#if DBG
DebugUninitialize();
#endif
break;
case SERVICE_CONTROL_INTERROGATE:
//
// Refresh our status to the SCM.
//
SetServiceStatus(g_hStatus, &g_status);
break;
default:
//
// This may not be needed, but refresh our status to the service
// controller.
//
DavPrint((DEBUG_INIT, "DavServiceHandler: WebClient service received SCM "
"Opcode = %08lx\n", dwOpcode));
ASSERT (g_hStatus);
SetServiceStatus (g_hStatus, &g_status);
break;
}
return;
}
VOID
SvchostPushServiceGlobals(
PSVCHOST_GLOBAL_DATA pGlobals
)
{
DavSvcsGlobalData = pGlobals;
}
VOID
WINAPI
ServiceMain (
DWORD dwNumServicesArgs,
LPWSTR *lpServiceArgVectors
)
/*++
Routine Description:
This function is called by the Service Control Manager when starting this
service.
Arguments:
dwNumServicesArgs - Number of arguments.
lpServiceArgVectors - Array of arguments.
Return Value:
None.
--*/
{
DWORD err = ERROR_SUCCESS;
DWORD exitErr = ERROR_SUCCESS;
HKEY KeyHandle = NULL;
ULONG maxThreads = 0, initialThreads = 0, RedirRegisterCount = 0;
BOOL RunningAsAService = TRUE;
#if DBG
DebugInitialize();
#endif
DavReadRegistryValues();
//
// Make sure svchost.exe gave us the global data
//
ASSERT(DavSvcsGlobalData != NULL);
#if DBG
{
DWORD cbP = 0;
WCHAR m_szProfilePath[MAX_PATH];
cbP = GetEnvironmentVariable(L"USERPROFILE", m_szProfilePath, MAX_PATH);
m_szProfilePath[cbP] = L'\0';
DavPrint((DEBUG_MISC, "DavServiceMain: USERPROFILE: %ws\n", m_szProfilePath));
}
#endif
g_RedirLoaded = FALSE;
g_WorkersActive = FALSE;
g_registeredService = FALSE;
//
// Initialize the SERVICE_STATUS structure g_status.
//
ZeroMemory (&g_status, sizeof(g_status));
g_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
g_status.dwControlsAccepted = (SERVICE_ACCEPT_STOP | SERVICE_CONTROL_SHUTDOWN);
g_status.dwCheckPoint = 1;
g_status.dwWaitHint = DAV_WAIT_HINT_TIME;
DavPrint((DEBUG_MISC,
"DavServiceMain: lpServiceArgVectors[0] = %ws\n", lpServiceArgVectors[0]));
if ( lpServiceArgVectors[0] &&
( wcscmp(lpServiceArgVectors[0], L"notservice") == 0 ) ) {
DavPrint((DEBUG_MISC, "DavServiceMain: WebClient is not running as a Service.\n"));
} else {
DavPrint((DEBUG_MISC, "DavServiceMain: WebClient is running as a Service.\n"));
try {
InitializeCriticalSection ( &(g_DavServiceLock) );
} except(EXCEPTION_EXECUTE_HANDLER) {
err = GetExceptionCode();
DavPrint((DEBUG_ERRORS,
"DavServiceMain/InitializeCriticalSection: Exception Code ="
" = %08lx.\n", err));
goto exitServiceMain;
}
g_DavServiceLockSet = TRUE;
//
// Register the service control handler.
//
g_hStatus = RegisterServiceCtrlHandler(SERVICE_DAVCLIENT, DavServiceHandler);
if (g_hStatus) {
g_registeredService = TRUE;
DavPrint((DEBUG_INIT, "DavServiceMain: WebClient service is pending start.\n"));
} else {
DavPrint((DEBUG_INIT, "DavServiceMain: WebClient service failed to register.\n"));
goto exitServiceMain;
}
}
UpdateServiceStatus(SERVICE_START_PENDING);
//
// Attempt to load the mini-redir driver. If this fails, no point in us
// starting up.
//
while (TRUE) {
err = WsLoadRedir();
if (err == ERROR_SERVICE_ALREADY_RUNNING || err == ERROR_SUCCESS) {
DavPrint((DEBUG_MISC, "DavServiceMain/WsLoadRedir. Succeeded\n"));
break;
}
//
// If the transports are not ready, the MiniRedir returns an
// error STATUS_REDIRECTOR_NOT_STARTED which maps to the Win32 error
// ERROR_PATH_NOT_FOUND. In this case we sleep for 3 seconds and try
// again with the hope that the transports will be ready soon. Also,
// we update the service status to inform the SCM that we are doing
// some work. We try this 5 times (till RedirRegisterCount == 4) and
// if are unsuccessful, we give up.
//
if (err == ERROR_PATH_NOT_FOUND) {
RedirRegisterCount++;
DavPrint((DEBUG_ERRORS,
"DavServiceMain/WsLoadRedir. RedirRegisterCount = %d\n",
RedirRegisterCount));
if (RedirRegisterCount >= 4) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/WsLoadRedir(1). Error Val = %d\n",
err));
goto exitServiceMain;
}
//
// Sleep for 3 seconds.
//
Sleep(3000);
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
continue;
} else {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/WsLoadRedir(2). Error Val = %d\n",
err));
goto exitServiceMain;
}
}
g_RedirLoaded = TRUE;
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
//
// Initialize the global NT-style redirector device name string.
//
RtlInitUnicodeString(&RedirDeviceName, DD_DAV_DEVICE_NAME_U);
//
// Try to register the mini-redir.
//
err = UMReflectorRegister(DD_DAV_DEVICE_NAME_U,
UMREFLECTOR_CURRENT_VERSION,
&(DavReflectorHandle));
if ((DavReflectorHandle == NULL) || (err != ERROR_SUCCESS)) {
if (err == ERROR_SUCCESS) {
err = ERROR_BAD_DRIVER;
}
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorRegister. Error Val = %d\n",
err));
goto exitServiceMain;
}
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
//
// Try to start the mini-redir.
//
err = UMReflectorStart(UMREFLECTOR_CURRENT_VERSION, DavReflectorHandle);
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorStart. Error Val = %u.\n", err));
goto exitServiceMain;
}
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
//
// Initialize the socket interface.
//
err = InitializeTheSocketInterface();
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/InitializeTheSocketInterface: Error Val = %u.\n", err));
goto exitServiceMain;
}
//
// Setup the DAV/WinInet environment.
//
err = DavInit();
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/DavInit: Error Val = %u.\n", err));
goto exitServiceMain;
}
//
// Start the worker thread. This will handle completion routines queued
// from other worker threads and from the request ioctl threads.
//
err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
DAV_PARAMETERS_KEY,
0,
KEY_QUERY_VALUE,
&KeyHandle);
if (err == ERROR_SUCCESS) {
maxThreads = ReadDWord(KeyHandle,
DAV_MAXTHREADS_KEY,
DAV_MAXTHREADCOUNT_DEFAULT);
initialThreads = ReadDWord(KeyHandle,
DAV_THREADS_KEY,
DAV_THREADCOUNT_DEFAULT);
RegCloseKey(KeyHandle);
} else {
maxThreads = DAV_MAXTHREADCOUNT_DEFAULT;
initialThreads = DAV_THREADCOUNT_DEFAULT;
}
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
err = DavInitWorkerThreads(initialThreads, maxThreads);
if (err != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/DavInitWorkerThread: Error Val = %u.\n", err));
goto exitServiceMain;
}
g_WorkersActive = TRUE;
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
g_LUIDDeviceMapsEnabled = DavCheckLUIDDeviceMapsEnabled();
//
// Immediately report that we are running. All non-essential initialization
// is deferred until we are called by clients to do some work.
//
DavPrint((DEBUG_INIT, "DavServiceMain: WebClient service is now running.\n"));
(g_status.dwCheckPoint)++;
UpdateServiceStatus(SERVICE_START_PENDING);
//
// Setup RPC server for this service.
//
if (!g_RpcActive) {
err = DavSvcsGlobalData->StartRpcServer(L"DAV RPC SERVICE",
davclntrpc_ServerIfHandle);
if (err == STATUS_SUCCESS) {
g_RpcActive = TRUE;
} else {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/SetupRpcServer: Error Val = %u.\n", err));
}
}
UpdateServiceStatus(SERVICE_RUNNING);
return;
exitServiceMain:
if (g_WorkersActive) {
exitErr = DavTerminateWorkerThreads();
if (exitErr != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/DavTerminateWorkerThreads: "
"Error Val = %u.\n", exitErr));
}
g_WorkersActive = FALSE;
}
//
// Close and free up the DAV stuff.
//
DavClose();
if (g_socketinit) {
exitErr = CleanupTheSocketInterface();
if (exitErr != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/CleanupTheSocketInterface: "
"Error Val = %u.\n", exitErr));
}
g_socketinit = FALSE;
}
if (g_RpcActive) {
DavSvcsGlobalData->StopRpcServer(davclntrpc_ServerIfHandle);
g_RpcActive = FALSE;
}
if (DavReflectorHandle != NULL) {
exitErr = UMReflectorStop(DavReflectorHandle);
if (exitErr != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorStop: Error Val = %u.\n", exitErr));
}
exitErr = UMReflectorUnregister(DavReflectorHandle);
if (exitErr != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/UMReflectorUnregister: Error Val = 0x%x.\n", exitErr));
}
DavReflectorHandle = NULL;
}
if (g_RedirLoaded) {
exitErr = WsUnloadRedir();
if (exitErr != ERROR_SUCCESS) {
DavPrint((DEBUG_ERRORS,
"DavServiceMain/WsUnloadRedir: Error Val = %u.\n", exitErr));
}
g_RedirLoaded = FALSE;
}
if (g_DavServiceLockSet) {
DeleteCriticalSection ( &(g_DavServiceLock) );
g_DavServiceLockSet = FALSE;
}
//
// Let the SCM know why the service did not start.
//
if (err != NO_ERROR) {
g_status.dwWin32ExitCode = err;
g_status.dwServiceSpecificExitCode = NO_ERROR;
UpdateServiceStatus(SERVICE_STOPPED);
}
DavPrint((DEBUG_INIT, "DavServiceMain: WebClient service is stopped.\n"));
#if DBG
DebugUninitialize();
#endif
return;
}
DWORD
DavNotRunningAsAService(
VOID
)
/*++
Routine Description:
The DavClient is not being run as a Service.
Arguments:
None.
Return Value:
ERROR_SUCCESS - No problems.
Win32 Error Code - Something went wrong.
--*/
{
DWORD WStatus = ERROR_SUCCESS;
HANDLE Thread;
DWORD ThreadId;
PWCHAR NotSrv = L"notservice";
//
// Create a thread for the fake service controller.
//
Thread = CreateThread( NULL, 0, DavFakeServiceController, 0, 0, &ThreadId );
if (Thread == NULL) {
WStatus = GetLastError();
DavPrint((DEBUG_ERRORS,
"DavNotRunningAsAService/CreateThread: Error Val = %d.\n", WStatus));
return WStatus;
}
//
// Call the Sevice Main function of the DavClient service.
//
ServiceMain( 2, &(NotSrv) );
return WStatus;
}
DWORD
WINAPI
DavFakeServiceController(
LPVOID Parameter
)
/*++
Routine Description:
The Fake service control for the DavClient when it is not running as a
service. This is used to send a STOP signal to the DavClient.
Arguments:
Parameter - Dummy parameter.
Return Value:
ERROR_SUCCESS - No problems.
--*/
{
while (DavStop == 0) {
Sleep(1000);
}
DavServiceHandler( SERVICE_CONTROL_STOP );
return 0;
}
BOOL
DavCheckLUIDDeviceMapsEnabled(
VOID
)
/*++
Routine Description:
This function calls NtQueryInformationProcess() to determine if
LUID device maps are enabled
Arguments:
none
Return Value:
TRUE - LUID device maps are enabled
FALSE - LUID device maps are disabled
--*/
{
NTSTATUS Status;
ULONG LUIDDeviceMapsEnabled;
BOOL Result;
Status = NtQueryInformationProcess( NtCurrentProcess(),
ProcessLUIDDeviceMapsEnabled,
&LUIDDeviceMapsEnabled,
sizeof(LUIDDeviceMapsEnabled),
NULL
);
if (!NT_SUCCESS( Status )) {
Result = FALSE;
}
else {
Result = (LUIDDeviceMapsEnabled != 0);
}
return( Result );
}
VOID
_cdecl
main (
IN INT ArgC,
IN PCHAR ArgV[]
)
/*++
Routine Description:
Main (DavClient) runs as either a service or an exe.
Arguments:
ArgC - Number of arguments.
ArgV - Array of arguments.
Return Value:
ERROR_SUCCESS - No problems.
Win32 Error Code - Something went wrong.
--*/
{
BOOL RunningAsAService = TRUE;
BOOL ReturnVal = FALSE;
SERVICE_TABLE_ENTRYW DavServiceTableEntry[] = {
{ SERVICE_DAVCLIENT, ServiceMain },
{ NULL, NULL }
};
//
// Are we running as a service or an exe ?
//
if ( ArgV[1] != NULL ) {
if ( strstr(ArgV[1], "notservice") != NULL) {
RunningAsAService = FALSE;
}
}
if (RunningAsAService) {
ReturnVal = StartServiceCtrlDispatcher(DavServiceTableEntry);
if ( !ReturnVal ) {
DavPrint((DEBUG_ERRORS,
"main/StartServiceCtrlDispatcher: Error Val = %d.\n",
GetLastError()));
}
} else {
DWORD WStatus;
WStatus = DavNotRunningAsAService();
if ( WStatus != ERROR_SUCCESS ) {
DavPrint((DEBUG_ERRORS,
"main/DavNotRunningAsAService: Error Val = %d.\n",
WStatus));
}
}
return;
}
VOID
DavReadRegistryValues(
VOID
)
/*++
Routine Description:
This function reads some values from the registry and sets the globals in
the WebClient service.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG WStatus = ERROR_SUCCESS;
HKEY KeyHandle = NULL;
ULONG ValueType = 0, ValueSize = 0;
WStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
DAV_PARAMETERS_KEY,
0,
KEY_QUERY_VALUE,
&(KeyHandle));
if (WStatus != ERROR_SUCCESS) {
KeyHandle = NULL;
ServerNotFoundCacheLifeTimeInSec = 60;
AcceptOfficeAndTahoeServers = 0;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegOpenKeyExW. WStatus = %d\n", WStatus);
goto EXIT_THE_FUNCTION;
}
//
// If we fail in getting the values from the registry, set them to default
// values.
//
ValueSize = sizeof(ServerNotFoundCacheLifeTimeInSec);
WStatus = RegQueryValueExW(KeyHandle,
DAV_SERV_CACHE_VALUE,
0,
&(ValueType),
(LPBYTE)&(ServerNotFoundCacheLifeTimeInSec),
&(ValueSize));
if (WStatus != ERROR_SUCCESS) {
ServerNotFoundCacheLifeTimeInSec = 60;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegQueryValueExW(1). WStatus = %d\n", WStatus);
}
ValueSize = sizeof(AcceptOfficeAndTahoeServers);
WStatus = RegQueryValueExW(KeyHandle,
DAV_ACCEPT_TAHOE_OFFICE_SERVERS,
0,
&(ValueType),
(LPBYTE)&(AcceptOfficeAndTahoeServers),
&(ValueSize));
if (WStatus != ERROR_SUCCESS) {
AcceptOfficeAndTahoeServers = 0;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegQueryValueExW(2). WStatus = %d\n", WStatus);
}
ValueSize = sizeof(DavSupportLockingOfFiles);
WStatus = RegQueryValueExW(KeyHandle,
DAV_SUPPORT_LOCKING_OF_FILES,
0,
&(ValueType),
(LPBYTE)&(DavSupportLockingOfFiles),
&(ValueSize));
if (WStatus != ERROR_SUCCESS) {
DavSupportLockingOfFiles = 1;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegQueryValueExW(3). WStatus = %d\n", WStatus);
}
ValueSize = sizeof(DavFileSizeLimitInBytes);
WStatus = RegQueryValueExW(KeyHandle,
DAV_FILE_SIZE_LIMIT,
0,
&(ValueType),
(LPBYTE)&(DavFileSizeLimitInBytes),
&(ValueSize));
if (WStatus != ERROR_SUCCESS) {
DavFileSizeLimitInBytes = 0x2faf080;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegQueryValueExW(4). WStatus = %d\n", WStatus);
}
ValueSize = sizeof(DavFileAttributesLimitInBytes);
WStatus = RegQueryValueExW(KeyHandle,
DAV_ATTRIBUTES_SIZE_LIMIT,
0,
&(ValueType),
(LPBYTE)&(DavFileAttributesLimitInBytes),
&(ValueSize));
if (WStatus != ERROR_SUCCESS) {
DavFileAttributesLimitInBytes = 0xf4240;
WStatus = GetLastError();
DbgPrint("ERROR: DavReadRegistryValues/RegQueryValueExW(5). WStatus = %d\n", WStatus);
}
EXIT_THE_FUNCTION:
if (KeyHandle) {
RegCloseKey(KeyHandle);
}
return;
}