📄 httpmain.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: HTTPMAIN.CPP
Abstract: HTTP server initialization & listener thread
--*/
#include "httpd.h"
//
//-------------------- Global data --------------
//
CGlobalVariables *g_pVars; // Global data. This is the "default" website.
CGlobalVariables *g_pWebsites; // Multiple websites.
DWORD g_cWebsites; // Number of websites (does not count the default)
HINSTANCE g_hInst; // handle to DLL
LONG g_fState; // Current Service State (running, stopped, starting, shutting down, unloading)
CRITICAL_SECTION g_CritSect; // Global lock
CWebDavFileLockManager *g_pFileLockManager; // Implements LOCK and UNLOCK support for WebDav.
SVSThreadPool *g_pTimer; // ISAPI extension unload and WebDAV file unlock timer thread (wakes up once a minute).
// We keep track of whether we've spun a thread in this function to deal with
// stopping+restarting, in the event that when we're unloa
HANDLE g_hAdminThread;
CHttpRequest *g_pRequestList; // List of active http connections.
BOOL g_fUTF8;
//------------- Const data -----------------------
//
const char cszTextHtml[] = "text/html";
const char cszOctetStream[] = "application/octet-stream";
const char cszEmpty[] = "";
const char cszMaxConnectionHeader[] = "HTTP/1.0 503 Service Unavailable\r\n\r\n";
//
//------------- Debug data -----------------------
//
#if defined(UNDER_CE) && defined (DEBUG)
DBGPARAM dpCurSettings = {
TEXT("HTTPD"), {
TEXT("Error"),TEXT("Init"),TEXT("Listen"),TEXT("Socket"),
TEXT("Request"),TEXT("Response"),TEXT("ISAPI"),TEXT("VROOTS"),
TEXT("ASP"),TEXT("Device"),TEXT("SSL"),TEXT("Verbose"),
TEXT("Authentication"),TEXT("WebDAV"),TEXT("Parser"),TEXT("Tokens") },
0x0003
};
#endif
//
//------------- Prototypes -----------------------
//
PWSTR MassageMultiString(PCWSTR wszIn, PCWSTR wszDefault=NULL);
//
//------------- Startup functions -----------------------
//
extern "C" BOOL WINAPI DllEntry( HANDLE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
DEBUGMSG(ZONE_INIT,(TEXT("HTTPD: DllMain attached\r\n")));
g_hAdminThread = 0;
g_hInst = (HINSTANCE)hInstDll;
svsutil_Initialize();
DEBUGREGISTER((HINSTANCE)hInstDll);
InitializeCriticalSection(&g_CritSect);
DisableThreadLibraryCalls((HMODULE)hInstDll);
g_fState = SERVICE_STATE_UNINITIALIZED;
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (TEXT("HTTPD: DllMain detach\r\n")));
DeleteCriticalSection(&g_CritSect);
svsutil_DeInitialize();
DEBUGCHK(g_fState == SERVICE_STATE_UNLOADING && !g_pVars && !g_pWebsites && (g_cWebsites==0) && !g_pTimer);
break;
}
return TRUE;
}
extern "C" int HttpInitialize(TCHAR *szRegPath) {
// This was to support httpd being started in CE 3.0 - in the device.exe days
// Leave the function intact because it's in httpd.def, but no longer
// do anything here. Apps need to do the right thing here and use
// standard services.exe API's to start + stop HTTPD.
DEBUGMSG(ZONE_ERROR,(L"HTTPD:HttpInitialize is no longer supported - use standard services.exe functions to use this\r\n"));
DEBUGCHK(0);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
// Routines that are called once after HTTPD.dll has been started, but are not safe to be called from DLLMain().
BOOL HttpInitializeOnce(void) {
g_pTimer = new SVSThreadPool(1);
if (!g_pTimer)
return FALSE;
svsutil_InitializeInterfaceMapperOnce();
svsutil_ResetInterfaceMapper();
DoesSystemSupportUTF8();
g_pTimer->ScheduleEvent(PeriodicWakeupThread,0,PERIODIC_TIMER_SLEEP_TIMEOUT);
return TRUE;
}
extern "C" int HttpInitializeFromExe() {
// No longer supported - HttpInitialize sets proper error code for this call
return HttpInitialize(NULL);
}
const WCHAR wszDefaultLogDirectory[] = L"\\windows\\www";
BOOL IsHttpdEnabled(void) {
CReg reg(HKEY_LOCAL_MACHINE, RK_HTTPD);
if (reg.ValueDW(RV_ISENABLED,1))
return TRUE;
SetLastError(ERROR_SERVICE_DISABLED);
DEBUGMSG(ZONE_INIT,(L"HTTPD: IsEnabled=0, will not start web server\r\n"));
DWORD dwMaxLogSize;
WCHAR wszLogDir[MAX_PATH + 1];
if (0 == (dwMaxLogSize = reg.ValueDW(RV_MAXLOGSIZE)))
return FALSE;
if ( ! reg.ValueSZ(RV_LOGDIR,wszLogDir,MAX_PATH+1))
wcscpy(wszLogDir,wszDefaultLogDirectory);
CLog cLog(dwMaxLogSize,wszLogDir);
cLog.WriteEvent(IDS_HTTPD_DISABLED);
return FALSE;
}
void CGlobalVariables::InitGlobals(CReg *pWebsite) {
DWORD dwMaxLogSize;
WCHAR wszLogDir[MAX_PATH + 1];
ZEROMEM(this);
CReg reg;
m_fRootSite = !pWebsite;
// if pWebsite==NULL, then this is initialization of default website.
if (m_fRootSite) {
DEBUGCHK(g_pVars == NULL);
// certain functions, including listen thread management and ISAPI Filters
// are managed globally by the main site.
reg.Open(HKEY_LOCAL_MACHINE, RK_HTTPD);
if (!reg.IsOK()) {
CLog cLog(DEFAULTLOGSIZE,L"\\windows\\www");
cLog.WriteEvent(IDS_HTTPD_NO_REGKEY);
DEBUGMSG(ZONE_ERROR,(L"HTTPD: No registry key setup, will not handle requests\r\n"));
return;
}
pWebsite = ®
if (! IsHttpdEnabled())
return;
// thread pool is global
m_nMaxConnections = pWebsite->ValueDW(RV_MAXCONNECTIONS,10);
m_pThreadPool = new SVSThreadPool(m_nMaxConnections + 1); // +1 for ISAPI Cache removal thread
if (!m_pThreadPool)
return;
// initial string setup only needs to be done once.
if (NULL == (m_pszStatusBodyBuf = MyRgAllocNZ(CHAR,BODYSTRINGSIZE)))
return;
InitializeResponseCodes(m_pszStatusBodyBuf);
strcpy(m_szMaxConnectionMsg,cszMaxConnectionHeader);
WCHAR wszMaxConnectionMsg[256];
LoadString(g_hInst,IDS_SERVER_BUSY,wszMaxConnectionMsg,ARRAYSIZEOF(wszMaxConnectionMsg));
MyW2A(wszMaxConnectionMsg,m_szMaxConnectionMsg + sizeof(cszMaxConnectionHeader) - 1,
sizeof(m_szMaxConnectionMsg) - sizeof(cszMaxConnectionHeader));
m_fUseDefaultSite = pWebsite->ValueDW(RV_ALLOW_DEFAULTSITE,TRUE);
// setup logging
dwMaxLogSize = pWebsite->ValueDW(RV_MAXLOGSIZE);
if ( ! pWebsite->ValueSZ(RV_LOGDIR,wszLogDir,MAX_PATH+1)) {
wcscpy(wszLogDir,wszDefaultLogDirectory);
}
WCHAR *wszBasicRealm;
if (NULL != (wszBasicRealm = (WCHAR*)pWebsite->ValueSZ(RV_BASIC_REALM))) {
if (NULL == (m_szBasicRealm = MySzDupWtoA(wszBasicRealm)))
return;
}
else {
static const CHAR cszBasicRealmDefault[] = "Microsoft-WinCE";
if (NULL == (m_szBasicRealm = MySzDupA(cszBasicRealmDefault)))
return;
}
m_pLog = new CLog(dwMaxLogSize,wszLogDir);
if (!m_pLog)
return;
// max POST/Header sizes,
m_dwPostReadSize = pWebsite->ValueDW(RV_POSTREADSIZE, 48*1024); // 48 K default
if (m_dwPostReadSize < MIN_POST_READ_SIZE) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: PostReadSize set in registry = %d, however minimum must be %d. Resetting value to minimum acceptable\r\n",m_dwPostReadSize,MIN_POST_READ_SIZE));
m_dwPostReadSize = MIN_POST_READ_SIZE;
}
m_dwMaxHeaderReadSize = pWebsite->ValueDW(RV_MAXHEADERSIZE, 48*1024); // 48 K default
m_dwSystemChangeNumber = pWebsite->ValueDW(RV_CHANGENUMBER, 1);
m_dwConnectionTimeout = pWebsite->ValueDW(RV_CONN_TIMEOUT,30*1000); // 30 second default
m_fExtensions = InitExtensions(pWebsite);
}
#if defined (DEBUG) || defined (_DEBUG)
else
DEBUGCHK(g_pVars);
#endif
m_dwListenPort = pWebsite->ValueDW(RV_PORT, IPPORT_HTTP);
DEBUGCHK(m_dwListenPort);
m_fASP = InitASP(pWebsite);
m_fWebDav = InitWebDav(pWebsite);
m_fDirBrowse = pWebsite->ValueDW(RV_DIRBROWSE, HTTPD_ALLOW_DIR_BROWSE);
m_wszDefaultPages = MassageMultiString(pWebsite->ValueSZ(RV_DEFAULTPAGE),HTTPD_DEFAULT_PAGES);
const WCHAR *sz = pWebsite->ValueSZ(RV_ADMINUSERS);
if (sz)
m_wszAdminUsers = svsutil_wcsdup((WCHAR*)sz);
else
m_wszAdminUsers = NULL;
InitAuthentication(pWebsite);
if (m_fRootSite)
InitSSL(pWebsite);
WCHAR *wszServerID;
if (NULL != (wszServerID = (WCHAR*)pWebsite->ValueSZ(RV_SERVER_ID))) {
// User specified an over-ride server ID, convert to ANSI and use it.
if (NULL == (m_szServerID = MySzDupWtoA(wszServerID)))
return;
}
else {
// Use default server ID if not overridden
static const char szDefaultServerIdFmt[] = "Microsoft-WinCE/%d.%02d";
if (NULL == (m_szServerID = MyRgAllocNZ(CHAR,CCHSIZEOF(szDefaultServerIdFmt)+20)))
return;
sprintf(m_szServerID,szDefaultServerIdFmt,CE_MAJOR_VER,CE_MINOR_VER);
}
InitMapping(*pWebsite,RV_HOSTEDSITES); // SVSInterfaceMapper does hard work here.
m_pVroots = new CVRoots(pWebsite,m_fDirBrowse,m_fBasicAuth, m_fNTLMAuth, m_fNegotiateAuth);
if (!m_pVroots)
return;
// vroot table must be initialized or web server can't return files. Warn
// user if this is not the case
if ((m_pVroots->Count() == 0) && m_fRootSite)
m_pLog->WriteEvent(IDS_HTTPD_NO_VROOTS);
m_fAcceptConnections = TRUE;
}
void CGlobalVariables::DeInitGlobals(void) {
// note that certain variables (like ISAPIs and logging) are only
// initialized on the default web site.
DEBUGCHK(g_pVars->m_nConnections == 0);
DEBUGCHK(g_fState != SERVICE_STATE_ON);
MyFree(m_wszDefaultPages);
MyFree(m_wszAdminUsers);
MyFree(m_pszStatusBodyBuf);
MyFree(m_pszSSLIssuer);
MyFree(m_pszSSLSubject);
MyFree(m_szServerID);
MyFree(m_szBasicRealm);
if (m_pVroots)
delete m_pVroots;
if (m_fRootSite) {
DEBUGCHK(this == g_pVars);
if (m_fWebDav && (g_fState == SERVICE_STATE_UNLOADING))
DeInitWebDav(); // only on unload because lock manager persists across refreshes
if (m_fFilters)
CleanupFilters();
if (m_fExtensions)
DeInitExtensions();
if (m_pISAPICache) {
// Flush all ISAPIs. This will block until everyone's unloaded.
m_pISAPICache->RemoveUnusedISAPIs(TRUE);
delete m_pISAPICache;
}
if (m_pThreadPool)
delete m_pThreadPool;
if (m_fSSL)
FreeSSLResources();
MyFreeLib(m_hSecurityLib);
// Log must be the last thing we destroy, because theoretically
// a cleanup function could make a call into it to report an error condition.
if (m_pLog)
delete m_pLog;
m_dwSystemChangeNumber++;
CReg reg(HKEY_LOCAL_MACHINE,RK_HTTPD);
reg.SetDW(RV_CHANGENUMBER,m_dwSystemChangeNumber);
}
#if defined (DEBUG)
else {
// non-root website should never have got any of this set, always use default for these settings.
DEBUGCHK(m_pISAPICache == NULL);
DEBUGCHK(m_pLog == NULL);
DEBUGCHK(m_pThreadPool == NULL);
DEBUGCHK(m_hSSLCertStore == 0);
DEBUGCHK(m_fHasSSLCreds == FALSE);
DEBUGCHK(m_hSecurityLib == NULL);
}
#endif
DeInitMapping(); // SVSInterfaceMapper call
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -