/*++ Copyright (c) 2001 Microsoft Corporation Module Name: precomp.h Abstract: Main header for BITS server extensions --*/ #define INITGUID #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "winhttp.h" // #include "inethttp.h" #include #include #include "resource.h" #include typedef StringHandleA StringHandle; #include typedef SmartRefPointer SmartMetabasePointer; typedef SmartRefPointer SmartBITSExtensionSetupFactoryPointer; typedef SmartRefPointer 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 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;