📄 httpddev.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*--
Module Name: httpddev.cpp
Abstract: HTTP device driver exports, and routines that are
exposed to facilitate their manipulation.
--*/
#include "httpd.h"
BOOL HttpStopAndRestart(void);
//
// Functions exported from HTTPD.
//
extern "C" void HttpdStart() {
HANDLE hFile;
DWORD dwBytesReturned;
hFile = CreateFile(HTTPD_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,
NULL,OPEN_EXISTING,0,NULL);
if (INVALID_HANDLE_VALUE == hFile)
return;
DeviceIoControl(hFile,IOCTL_SERVICE_START,0,0,0,0,&dwBytesReturned,0);
CloseHandle(hFile);
}
extern "C" void HttpdStop() {
HANDLE hFile;
DWORD dwBytesReturned;
hFile = CreateFile(HTTPD_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,
NULL,OPEN_EXISTING,0,NULL);
if (INVALID_HANDLE_VALUE == hFile)
return;
DeviceIoControl(hFile,IOCTL_SERVICE_STOP,0,0,0,0,&dwBytesReturned,0);
CloseHandle(hFile);
}
// This call must NOT block! It's possible for an ISAPI extension to
// call this function, in which case we want the ISAPI extension to continue
// executing so that request (along with any others) can terminate.
// Only after the request has terminated can we start up again.
extern "C" void HttpdStopAndRestart() {
HANDLE hFile;
DWORD dwBytesReturned;
hFile = CreateFile(HTTPD_DEV_NAME,GENERIC_READ|GENERIC_WRITE,0,
NULL,OPEN_EXISTING,0,NULL);
if (INVALID_HANDLE_VALUE == hFile)
return;
DeviceIoControl(hFile,IOCTL_SERVICE_REFRESH,0,0,0,0,&dwBytesReturned,0);
CloseHandle(hFile);
}
//
// Internal helper functions to handle state changes.
//
void WaitForHttpToShutDown(void) {
CloseAllConnections();
g_pVars->m_fAcceptConnections = FALSE;
WaitForConnectionThreadsToEnd();
CleanupGlobalMemory(g_cWebsites);
}
// lpv = NULL when we don't want to start up again, lpv=1 when we'll restart immediatly.
DWORD WINAPI HttpdStopThread(LPVOID lpv) {
MyWaitForAdminThreadReadyState();
DEBUGCHK(g_fState == SERVICE_STATE_SHUTTING_DOWN && g_hAdminThread);
WaitForHttpToShutDown();
DEBUGCHK(g_fState == SERVICE_STATE_SHUTTING_DOWN);
DEBUGCHK(!g_pVars && !g_pWebsites && (g_cWebsites==0));
if (!lpv) {
g_fState = SERVICE_STATE_OFF;
CloseHandle(g_hAdminThread);
g_hAdminThread = 0;
}
return 0;
}
// This thread stops the server and restarts it.
DWORD WINAPI HttpdStopAndRestartThread(LPVOID lpv) {
MyWaitForAdminThreadReadyState();
HttpdStopThread((void*)1);
g_fState = SERVICE_STATE_STARTING_UP;
InitializeGlobals();
CloseHandle(g_hAdminThread);
g_hAdminThread = 0;
return 0;
}
BOOL HttpStopAndRestart(void) {
if (InterlockedCompareExchange(&g_fState,(INTERLOCKED_COMP) SERVICE_STATE_SHUTTING_DOWN, (INTERLOCKED_COMP) SERVICE_STATE_ON) != (INTERLOCKED_RESULT)SERVICE_STATE_ON) {
SetLastError(ERROR_SERVICE_NOT_ACTIVE);
return FALSE;
}
DEBUGCHK(!g_hAdminThread);
g_hAdminThread = MyCreateThread(HttpdStopAndRestartThread,0);
return g_hAdminThread ? TRUE : FALSE;
}
// Called to shutdown all HTTPD threads.
BOOL HttpShutDown(void) {
// persist our shutdown state to registry.
CReg reg(HKEY_LOCAL_MACHINE, RK_HTTPD);
reg.SetDW(RV_ISENABLED,0);
if (InterlockedCompareExchange(&g_fState,SERVICE_STATE_SHUTTING_DOWN,
SERVICE_STATE_ON) != (INTERLOCKED_RESULT)SERVICE_STATE_ON) {
SetLastError(ERROR_SERVICE_NOT_ACTIVE);
return FALSE;
}
DEBUGCHK(!g_hAdminThread);
g_hAdminThread = MyCreateThread(HttpdStopThread,0);
return g_hAdminThread ? TRUE : FALSE;
}
BOOL HttpUnload(void) {
LONG fOldState;
DEBUGMSG(ZONE_INIT,(L"HTTPD: Starting to unload service\r\n"));
// If a stop/start/restart thread is running already, then wait for it before continuing.
if (g_hAdminThread)
WaitForSingleObject(g_hAdminThread,INFINITE);
Sleep(100);
// If the service is either shutting down or starting up then we can't unload.
// Succeeding on unload but not really unloading is NOT an option, lib will get freed by services.exe or device.exe
// when this function returns and running threads in httpd's context will crash, so keep polling as long as it takes.
while (1) {
if ((fOldState = (long)InterlockedCompareExchange(&g_fState,SERVICE_STATE_UNLOADING,SERVICE_STATE_ON)) == SERVICE_STATE_ON ||
(fOldState = (long)InterlockedCompareExchange(&g_fState,SERVICE_STATE_UNLOADING,SERVICE_STATE_OFF)) == SERVICE_STATE_OFF)
{
break;
}
DEBUGMSG(ZONE_INIT,(L"HTTPD: HttpUnload can't unload service, HTTPD state must be on or off, current state = %d, sleep for 2 seconds\r\n",g_fState));
Sleep(2000);
}
DEBUGCHK(!g_hAdminThread);
if (fOldState == SERVICE_STATE_ON) {
WaitForHttpToShutDown();
}
if (g_pTimer) {
g_pTimer->Shutdown();
delete g_pTimer;
g_pTimer = NULL;
}
svsutil_DeInitializeInterfaceMapperOnce(); // not DLLMain safe.
DEBUGCHK(g_fState == SERVICE_STATE_UNLOADING);
DEBUGCHK(!g_pVars && !g_hAdminThread && !g_pWebsites && (g_cWebsites==0));
DEBUGMSG(ZONE_INIT,(L"HTTPD: Done unloading service\r\n"));
return TRUE;
}
// Certain operations may only be performed by trusted caller (mostly services.exe itself)
BOOL CheckCallerTrusted(void) {
// Currently not tied into ACLs.
return TRUE;
}
// @func BOOL | HTP_IOControl | Device IO control routine
// @parm DWORD | dwOpenData | value returned from HTP_Open call
// @parm DWORD | dwCode | io control code to be performed
// @parm PBYTE | pBufIn | input data to the device
// @parm DWORD | dwLenIn | number of bytes being passed in
// @parm PBYTE | pBufOut | output data from the device
// @parm DWORD | dwLenOut |maximum number of bytes to receive from device
// @parm PDWORD | pdwActualOut | actual number of bytes received from device
// @rdesc Returns TRUE for success, FALSE for failure
// @remark Routine exported by a device driver. "PRF" is the string passed
// in as lpszType in RegisterDevice
extern "C" BOOL HTP_IOControl(DWORD dwData, DWORD dwCode, PBYTE pBufIn,
DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut,
PDWORD pdwActualOut) {
DEBUGMSG (ZONE_DEVICE, (TEXT("HTP_IOControl(dwCode = 0x%X)\r\n"), dwCode));
DWORD dwOut;
switch (dwCode)
{
case IOCTL_SERVICE_START:
{
CReg reg;
reg.Open(HKEY_LOCAL_MACHINE,RK_HTTPD);
reg.SetDW(RV_ISENABLED,1);
if (InterlockedCompareExchange(&g_fState, SERVICE_STATE_STARTING_UP,
SERVICE_STATE_OFF) == SERVICE_STATE_OFF) {
DEBUGCHK(!g_hAdminThread);
g_hAdminThread = MyCreateThread(InitializeGlobalsThread,0);
if (g_hAdminThread) {
return TRUE;
}
g_fState = SERVICE_STATE_OFF;
return FALSE;
}
SetLastError(ERROR_SERVICE_ALREADY_RUNNING);
DEBUGMSG(ZONE_INIT,(L"HTTPD: HTP_IOControl cannot process, IOCTL_SERVICE_START, state != starting up, serviceState=%d\r\n",g_fState));
return FALSE;
}
break;
case IOCTL_SERVICE_STOP:
return HttpShutDown();
break;
case IOCTL_SERVICE_REFRESH:
return HttpStopAndRestart();
break;
case IOCTL_SERVICE_STATUS:
__try {
if (!pBufOut || dwLenOut < sizeof(DWORD)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*(DWORD *)pBufOut = g_fState;
if (pdwActualOut)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -