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.
450 lines
11 KiB
450 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
precomp.h
|
|
|
|
Abstract:
|
|
|
|
Main header for BITS server extensions
|
|
|
|
--*/
|
|
|
|
#define INITGUID
|
|
#include<nt.h>
|
|
#include<ntrtl.h>
|
|
#include<nturtl.h>
|
|
#include <windows.h>
|
|
#include <httpfilt.h>
|
|
#include <httpext.h>
|
|
#include <objbase.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
#include <iadmw.h>
|
|
#include <iiscnfg.h>
|
|
#include <shlwapi.h>
|
|
#include <winsock2.h>
|
|
#include <iphlpapi.h>
|
|
#include <sddl.h>
|
|
#include <aclapi.h>
|
|
|
|
#include "winhttp.h"
|
|
// #include "inethttp.h"
|
|
|
|
#include <activeds.h>
|
|
#include <bitsmsg.h>
|
|
#include "resource.h"
|
|
|
|
#include <smartptr.h>
|
|
typedef StringHandleA StringHandle;
|
|
|
|
#include <bitscfg.h>
|
|
typedef SmartRefPointer<IMSAdminBase> SmartMetabasePointer;
|
|
typedef SmartRefPointer<IBITSExtensionSetupFactory> SmartBITSExtensionSetupFactoryPointer;
|
|
typedef SmartRefPointer<IBITSExtensionSetup> SmartBITSExtensionSetupPointer;
|
|
#if defined(DBG)
|
|
|
|
// check build
|
|
#define BITS_MUST_SUCCEED( expr ) ASSERT( expr )
|
|
|
|
#else
|
|
|
|
// free build
|
|
#define BITS_MUST_SUCCEED( expr ) ( expr )
|
|
|
|
#endif
|
|
|
|
const UINT32 LOG_INFO = 0x1;
|
|
const UINT32 LOG_WARNING = 0x2;
|
|
const UINT32 LOG_ERROR = 0x4;
|
|
const UINT32 LOG_CALLBEGIN = 0x8;
|
|
const UINT32 LOG_CALLEND = 0x10;
|
|
|
|
#if defined(DBG)
|
|
const UINT32 DEFAULT_LOG_FLAGS = LOG_INFO | LOG_WARNING | LOG_ERROR | LOG_CALLBEGIN | LOG_CALLEND;
|
|
#else
|
|
const UINT32 DEFAULT_LOG_FLAGS = 0;
|
|
#endif
|
|
|
|
const UINT32 DEFAULT_LOG_SIZE = 20;
|
|
|
|
// LogSetings path under HKEY_LOCAL_MACHINE
|
|
const char * const LOG_SETTINGS_PATH = "SOFTWARE\\Microsoft\\BITSServer";
|
|
|
|
// Values
|
|
// (REG_EXPAND_SZ). Contains the full path of the log file name
|
|
const char * const LOG_FILENAME_VALUE = "LogFileName";
|
|
// (REG_DWORD) Contains the log flags
|
|
const char * const LOG_FLAGS_VALUE = "LogFlags";
|
|
// (REG_DWORD) Contains the log size in MB
|
|
const char * const LOG_SIZE_VALUE = "LogSize";
|
|
// (REG_DWORD) Indicates if we will be appending the ProcessId to the log file name
|
|
const char * const PER_PROCESS_LOG_VALUE = "PerProcessLog";
|
|
|
|
extern UINT32 g_LogFlags;
|
|
|
|
HRESULT LogInit();
|
|
void LogClose();
|
|
void LogInternal( UINT32 LogFlags, char *Format, va_list arglist );
|
|
|
|
void inline Log( UINT32 LogFlags, char *Format, ... )
|
|
{
|
|
|
|
if ( !( g_LogFlags & LogFlags ) )
|
|
return;
|
|
|
|
va_list arglist;
|
|
va_start( arglist, Format );
|
|
|
|
LogInternal( LogFlags, Format, arglist );
|
|
|
|
}
|
|
|
|
const char *LookupHTTPStatusCodeText( DWORD HttpCode );
|
|
|
|
class ServerException : public ComError
|
|
{
|
|
public:
|
|
|
|
ServerException() :
|
|
ComError( 0 ),
|
|
m_HttpCode( 0 ),
|
|
m_Context( 0 )
|
|
{
|
|
}
|
|
|
|
ServerException( HRESULT Code, DWORD HttpCode = 0, DWORD Context = 0x5 ) :
|
|
ComError( Code ),
|
|
m_HttpCode( HttpCode ? HttpCode : MapStatus( Code ) ),
|
|
m_Context( Context )
|
|
{
|
|
}
|
|
ServerException( const ComError & Error ) :
|
|
ComError( Error.m_Hr ),
|
|
m_HttpCode( MapStatus( Error.m_Hr ) ),
|
|
m_Context( 0x5 )
|
|
{
|
|
}
|
|
ServerException( const ServerException & Error ) :
|
|
ComError( Error.m_Hr ),
|
|
m_HttpCode( Error.m_HttpCode ),
|
|
m_Context( Error.m_Context )
|
|
{
|
|
}
|
|
|
|
HRESULT GetCode() const
|
|
{
|
|
return m_Hr;
|
|
}
|
|
DWORD GetHttpCode() const
|
|
{
|
|
return m_HttpCode;
|
|
}
|
|
|
|
DWORD GetContext() const
|
|
{
|
|
return m_Context;
|
|
}
|
|
|
|
void SendErrorResponse( EXTENSION_CONTROL_BLOCK * ExtensionControlBlock ) const;
|
|
DWORD MapStatus( HRESULT Hr ) const;
|
|
|
|
private:
|
|
DWORD m_HttpCode;
|
|
DWORD m_Context;
|
|
};
|
|
|
|
inline UINT64 FILETIMEToUINT64( const FILETIME & FileTime )
|
|
{
|
|
ULARGE_INTEGER LargeInteger;
|
|
LargeInteger.HighPart = FileTime.dwHighDateTime;
|
|
LargeInteger.LowPart = FileTime.dwLowDateTime;
|
|
return LargeInteger.QuadPart;
|
|
}
|
|
|
|
inline FILETIME UINT64ToFILETIME( UINT64 Int64Value )
|
|
{
|
|
ULARGE_INTEGER LargeInteger;
|
|
LargeInteger.QuadPart = Int64Value;
|
|
|
|
FILETIME FileTime;
|
|
FileTime.dwHighDateTime = LargeInteger.HighPart;
|
|
FileTime.dwLowDateTime = LargeInteger.LowPart;
|
|
|
|
return FileTime;
|
|
}
|
|
|
|
|
|
// API thunks
|
|
|
|
UINT64 BITSGetFileSize(
|
|
HANDLE Handle );
|
|
|
|
UINT64 BITSSetFilePointer(
|
|
HANDLE Handle,
|
|
INT64 Distance,
|
|
DWORD MoveMethod );
|
|
|
|
DWORD
|
|
BITSWriteFile(
|
|
HANDLE Handle,
|
|
LPCVOID Buffer,
|
|
DWORD NumberOfBytesToWrite);
|
|
|
|
void
|
|
BITSCreateDirectory(
|
|
const CHAR *Path );
|
|
void
|
|
BITSRenameFile(
|
|
LPCTSTR ExistingName,
|
|
LPCTSTR NewName,
|
|
bool AllowOverwrites );
|
|
|
|
void
|
|
BITSDeleteFile(
|
|
LPCTSTR FileName );
|
|
|
|
GUID
|
|
BITSCreateGuid();
|
|
|
|
GUID
|
|
BITSGuidFromString( const char *String );
|
|
|
|
StringHandle
|
|
BITSStringFromGuid(
|
|
GUID Guid );
|
|
|
|
|
|
StringHandle
|
|
BITSUnicodeToStringHandle( const WCHAR *pStr );
|
|
|
|
StringHandle
|
|
BITSUrlCombine(
|
|
const char *Base,
|
|
const char *Relative,
|
|
DWORD dwFlags );
|
|
|
|
StringHandle
|
|
BITSUrlCanonicalize(
|
|
const char *URL,
|
|
DWORD dwFlags );
|
|
|
|
void
|
|
BITSSetCurrentThreadToken(
|
|
HANDLE hToken );
|
|
|
|
// Metadata wrappers
|
|
|
|
StringHandle
|
|
GetMetaDataString(
|
|
IMSAdminBase *IISAdminBase,
|
|
METADATA_HANDLE Handle,
|
|
LPCWSTR Path,
|
|
DWORD dwIdentifier,
|
|
LPCSTR DefaultValue );
|
|
|
|
DWORD
|
|
GetMetaDataDWORD(
|
|
IMSAdminBase *IISAdminBase,
|
|
METADATA_HANDLE Handle,
|
|
LPCWSTR Path,
|
|
DWORD dwIdentifier,
|
|
DWORD DefaultValue );
|
|
|
|
class WorkStringBufferA
|
|
{
|
|
char *Data;
|
|
|
|
public:
|
|
|
|
WorkStringBufferA( SIZE_T Size )
|
|
{
|
|
Data = new char[Size];
|
|
}
|
|
WorkStringBufferA( const char* String )
|
|
{
|
|
size_t BufferSize = strlen(String) + 1;
|
|
Data = new char[ BufferSize ];
|
|
memcpy( Data, String, BufferSize );
|
|
}
|
|
~WorkStringBufferA()
|
|
{
|
|
delete[] Data;
|
|
}
|
|
|
|
char *GetBuffer()
|
|
{
|
|
return Data;
|
|
}
|
|
};
|
|
|
|
class WorkStringBufferW
|
|
{
|
|
WCHAR *Data;
|
|
|
|
public:
|
|
|
|
WorkStringBufferW( SIZE_T Size )
|
|
{
|
|
Data = new WCHAR[Size];
|
|
}
|
|
WorkStringBufferW( const WCHAR* String )
|
|
{
|
|
size_t BufferSize = wcslen(String) + 1;
|
|
Data = new WCHAR[ BufferSize ];
|
|
memcpy( Data, String, BufferSize * sizeof( WCHAR ) );
|
|
}
|
|
~WorkStringBufferW()
|
|
{
|
|
delete[] Data;
|
|
}
|
|
|
|
WCHAR *GetBuffer()
|
|
{
|
|
return Data;
|
|
}
|
|
};
|
|
|
|
|
|
typedef WorkStringBufferA WorkStringBuffer;
|
|
|
|
const char * const BITS_CONNECTIONS_NAME_WITH_SLASH="BITS-Connections\\";
|
|
const char * const BITS_CONNECTIONS_NAME="BITS-Connections";
|
|
const UINT64 NanoSec100PerSec = 10000000; //no of 100 nanosecs per sec
|
|
const DWORD WorkerRunInterval = 1000 * 60 /*secs*/ * 60 /*mins*/ * 12; /* hours */ /* twice a day */
|
|
const UINT64 CleanupThreshold = NanoSec100PerSec * 60 /*secs*/ * 60 /*mins*/ * 24 /* hours */ * 3; // 3 days
|
|
|
|
|
|
//
|
|
// Configuration manager
|
|
//
|
|
|
|
#include "bitssrvcfg.h"
|
|
|
|
|
|
class ConfigurationManager;
|
|
class VDirConfig
|
|
{
|
|
friend ConfigurationManager;
|
|
|
|
LONG m_Refs;
|
|
FILETIME m_LastLookup;
|
|
|
|
static StringHandle GetFullPath( StringHandle Path );
|
|
|
|
public:
|
|
StringHandle m_Path;
|
|
StringHandle m_PhysicalPath;
|
|
StringHandle m_SessionDir;
|
|
StringHandle m_ConnectionsDir;
|
|
StringHandle m_RequestsDir;
|
|
StringHandle m_RepliesDir;
|
|
DWORD m_NoProgressTimeout;
|
|
UINT64 m_MaxFileSize;
|
|
BITS_SERVER_NOTIFICATION_TYPE m_NotificationType;
|
|
StringHandle m_NotificationURL;
|
|
bool m_UploadEnabled;
|
|
StringHandle m_HostId;
|
|
DWORD m_HostIdFallbackTimeout;
|
|
DWORD m_ExecutePermissions;
|
|
bool m_AllowOverwrites;
|
|
|
|
VDirConfig(
|
|
StringHandle Path,
|
|
SmartMetabasePointer AdminBase );
|
|
|
|
void AddRef()
|
|
{
|
|
InterlockedIncrement( &m_Refs );
|
|
}
|
|
|
|
void Release()
|
|
{
|
|
|
|
if (!InterlockedDecrement( &m_Refs ))
|
|
delete this;
|
|
}
|
|
};
|
|
|
|
typedef SmartRefPointer<VDirConfig> SmartVDirConfig;
|
|
|
|
class MapCacheEntry
|
|
{
|
|
friend ConfigurationManager;
|
|
FILETIME m_LastLookup;
|
|
|
|
public:
|
|
|
|
StringHandle m_InstanceMetabasePath;
|
|
StringHandle m_URL;
|
|
SmartVDirConfig m_Config;
|
|
DWORD m_URLDepth;
|
|
|
|
MapCacheEntry(
|
|
StringHandle InstanceMetabasePath,
|
|
StringHandle URL,
|
|
SmartVDirConfig Config,
|
|
DWORD URLDepth ) :
|
|
m_InstanceMetabasePath( InstanceMetabasePath ),
|
|
m_URL( URL ),
|
|
m_Config( Config ),
|
|
m_URLDepth( URLDepth )
|
|
{
|
|
GetSystemTimeAsFileTime( &m_LastLookup );
|
|
}
|
|
|
|
};
|
|
|
|
class ConfigurationManager
|
|
{
|
|
public:
|
|
|
|
ConfigurationManager();
|
|
~ConfigurationManager();
|
|
|
|
SmartVDirConfig GetConfig2( StringHandle InstanceMetabasePath, StringHandle URL,
|
|
DWORD *pURLDepth );
|
|
SmartVDirConfig GetConfig( StringHandle InstanceMetabasePath, StringHandle URL,
|
|
DWORD *pURLDepth );
|
|
|
|
static const PATH_CACHE_ENTRIES = 10;
|
|
static const MAP_CACHE_ENTRIES = 10;
|
|
|
|
private:
|
|
|
|
SmartMetabasePointer m_IISAdminBase;
|
|
CRITICAL_SECTION m_CacheCS;
|
|
DWORD m_ChangeNumber;
|
|
|
|
SmartVDirConfig m_PathCacheEntries[ PATH_CACHE_ENTRIES ];
|
|
MapCacheEntry *m_MapCacheEntries[ MAP_CACHE_ENTRIES ];
|
|
|
|
void FlushCache();
|
|
bool HandleCacheConsistency();
|
|
|
|
// L2 cache
|
|
SmartVDirConfig Lookup( StringHandle Path );
|
|
void Insert( SmartVDirConfig NewConfig );
|
|
SmartVDirConfig GetVDirConfig( StringHandle Path );
|
|
|
|
// L1 cache
|
|
SmartVDirConfig Lookup( StringHandle InstanceMetabasePath,
|
|
StringHandle URL,
|
|
DWORD *pURLDepth );
|
|
SmartVDirConfig Insert( StringHandle InstanceMetabasePath,
|
|
StringHandle URL,
|
|
StringHandle Path,
|
|
DWORD URLDepth );
|
|
|
|
StringHandle GetVDirPath( StringHandle InstanceMetabasePath,
|
|
StringHandle URL,
|
|
DWORD *pURLDepth );
|
|
|
|
};
|
|
|
|
extern ConfigurationManager *g_ConfigMan;
|
|
extern HMODULE g_hinst;
|
|
extern PropertyIDManager *g_PropertyMan;
|