Source code of Windows XP (NT5)
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.

796 lines
18 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. precomp.h
  5. Abstract:
  6. Main header for BITS server extensions
  7. --*/
  8. #define INITGUID
  9. #include<nt.h>
  10. #include<ntrtl.h>
  11. #include<nturtl.h>
  12. #include <windows.h>
  13. #include <httpfilt.h>
  14. #include <httpext.h>
  15. #include <objbase.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <malloc.h>
  19. #include <iadmw.h>
  20. #include <iiscnfg.h>
  21. #include <shlwapi.h>
  22. #include <winsock2.h>
  23. #include <iphlpapi.h>
  24. #ifdef USE_WININET
  25. #include <wininet.h>
  26. #else
  27. #include "winhttp.h"
  28. #include "inethttp.h"
  29. #endif
  30. #include <activeds.h>
  31. #include <bitsmsg.h>
  32. #include "resource.h"
  33. #include <strsafe.h>
  34. #if defined(DBG)
  35. // check build
  36. #define BITS_MUST_SUCCEED( expr ) ASSERT( expr )
  37. #else
  38. // free build
  39. #define BITS_MUST_SUCCEED( expr ) ( expr )
  40. #endif
  41. const UINT32 LOG_INFO = 0x1;
  42. const UINT32 LOG_WARNING = 0x2;
  43. const UINT32 LOG_ERROR = 0x4;
  44. const UINT32 LOG_CALLBEGIN = 0x8;
  45. const UINT32 LOG_CALLEND = 0x10;
  46. #if defined(DBG)
  47. const UINT32 DEFAULT_LOG_FLAGS = LOG_INFO | LOG_WARNING | LOG_ERROR | LOG_CALLBEGIN | LOG_CALLEND;
  48. #else
  49. const UINT32 DEFAULT_LOG_FLAGS = 0;
  50. #endif
  51. const UINT32 DEFAULT_LOG_SIZE = 20;
  52. // LogSetings path under HKEY_LOCAL_MACHINE
  53. const char * const LOG_SETTINGS_PATH = "SOFTWARE\\Microsoft\\BITSServer";
  54. // Values
  55. // (REG_EXPAND_SZ). Contains the full path of the log file name
  56. const char * const LOG_FILENAME_VALUE = "LogFileName";
  57. // (REG_DWORD) Contains the log flags
  58. const char * const LOG_FLAGS_VALUE = "LogFlags";
  59. // (REG_DWORD) Contains the log size in MB
  60. const char * const LOG_SIZE_VALUE = "LogSize";
  61. extern UINT32 g_LogFlags;
  62. HRESULT LogInit();
  63. void LogClose();
  64. void LogInternal( UINT32 LogFlags, char *Format, va_list arglist );
  65. void inline Log( UINT32 LogFlags, char *Format, ... )
  66. {
  67. if ( !( g_LogFlags & LogFlags ) )
  68. return;
  69. va_list arglist;
  70. va_start( arglist, Format );
  71. LogInternal( LogFlags, Format, arglist );
  72. }
  73. const char *LookupHTTPStatusCodeText( DWORD HttpCode );
  74. class ServerException
  75. {
  76. public:
  77. ServerException() :
  78. m_Code( 0 ),
  79. m_HttpCode( 0 ),
  80. m_Context( 0 )
  81. {
  82. }
  83. ServerException( HRESULT Code, DWORD HttpCode = 0, DWORD Context = 0x5 ) :
  84. m_Code( Code ),
  85. m_HttpCode( HttpCode ? HttpCode : MapStatus( Code ) ),
  86. m_Context( Context )
  87. {
  88. }
  89. HRESULT GetCode() const
  90. {
  91. return m_Code;
  92. }
  93. DWORD GetHttpCode() const
  94. {
  95. return m_HttpCode;
  96. }
  97. DWORD GetContext() const
  98. {
  99. return m_Context;
  100. }
  101. void SendErrorResponse( EXTENSION_CONTROL_BLOCK * ExtensionControlBlock ) const;
  102. DWORD MapStatus( HRESULT Hr ) const;
  103. private:
  104. HRESULT m_Code;
  105. DWORD m_HttpCode;
  106. DWORD m_Context;
  107. };
  108. class CharStringRoutines
  109. {
  110. public:
  111. static int strcmp( const char *str1, const char *str2 )
  112. {
  113. return ::strcmp( str1, str2 );
  114. }
  115. static HRESULT StringCchCopy( char *str1, size_t cchDest, const char *str2 )
  116. {
  117. return ::StringCchCopyA( str1, cchDest, str2 );
  118. }
  119. static size_t strlen( const char *str )
  120. {
  121. return ::strlen( str );
  122. }
  123. static void* ConvertToInternal( SIZE_T Pad, const char *String, SIZE_T & Size )
  124. {
  125. Size = ::strlen( String );
  126. char *Ret = new char[ Pad + Size + 1 ];
  127. ::StringCchCopyA( Ret + Pad, Size + 1, String );
  128. return (void*)Ret;
  129. }
  130. static void* ConvertToInternal( SIZE_T Pad, const WCHAR *String, SIZE_T & Size )
  131. {
  132. int Alloc =
  133. WideCharToMultiByte(
  134. CP_THREAD_ACP, // code page
  135. 0, // performance and mapping flags
  136. String, // wide-character string
  137. -1, // number of chars in string
  138. NULL, // buffer for new string
  139. 0, // size of buffer
  140. NULL, // default for unmappable chars
  141. NULL // set when default char used
  142. );
  143. if ( !Alloc )
  144. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  145. char *Ret = new char[ Pad + Alloc ];
  146. int Actual =
  147. WideCharToMultiByte(
  148. CP_THREAD_ACP, // code page
  149. 0, // performance and mapping flags
  150. String, // wide-character string
  151. -1, // number of chars in string
  152. Ret + Pad, // buffer for new string
  153. Alloc, // size of buffer
  154. NULL, // default for unmappable chars
  155. NULL // set when default char used
  156. );
  157. if ( !Actual )
  158. {
  159. HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
  160. delete[] Ret;
  161. throw ServerException( Hr );
  162. }
  163. Size = Actual - 1;
  164. return Ret;
  165. }
  166. };
  167. class WCHARStringRoutines
  168. {
  169. public:
  170. static int strcmp( const WCHAR *str1, const WCHAR *str2 )
  171. {
  172. return ::wcscmp( str1, str2 );
  173. }
  174. static HRESULT StringCchCopy( WCHAR *str1, size_t cchDest, const WCHAR *str2 )
  175. {
  176. return ::StringCchCopyW( str1, cchDest, str2 );
  177. }
  178. static size_t strlen( const wchar_t *str )
  179. {
  180. return ::wcslen( str );
  181. }
  182. static void* ConvertToInternal( SIZE_T Pad, const WCHAR *String, SIZE_T & Size )
  183. {
  184. Size = ::wcslen( String );
  185. char *Ret = new char[ Pad + ( ( Size + 1 ) * sizeof(WCHAR) ) ];
  186. ::StringCchCopyW( (WCHAR*)(Ret + Pad), Size + 1, String );
  187. return (void*)Ret;
  188. }
  189. static void* ConvertToInternal( SIZE_T Pad, const char *String, SIZE_T & Size )
  190. {
  191. int Alloc =
  192. MultiByteToWideChar(
  193. CP_THREAD_ACP, // code page
  194. 0, // character-type options
  195. String, // string to map
  196. -1, // number of bytes in string
  197. NULL, // wide-character buffer
  198. 0 // size of buffer
  199. );
  200. if ( !Alloc )
  201. throw ServerException( HRESULT_FROM_WIN32( GetLastError() ) );
  202. char *Ret = new char[ Pad + ( Alloc * sizeof(WCHAR) ) ];
  203. int Actual =
  204. MultiByteToWideChar(
  205. CP_THREAD_ACP, // code page
  206. 0, // character-type options
  207. String, // string to map
  208. -1, // number of bytes in string
  209. (WCHAR*)( Ret + Pad ), // wide-character buffer
  210. Alloc // size of buffer
  211. );
  212. if ( !Actual )
  213. {
  214. HRESULT Hr = HRESULT_FROM_WIN32( GetLastError() );
  215. delete[] Ret;
  216. throw ServerException( Hr );
  217. }
  218. Size = Actual - 1;
  219. return Ret;
  220. }
  221. };
  222. template<class T, class CONV>
  223. class StringHandleTemplate : private CONV
  224. {
  225. struct StringData
  226. {
  227. SIZE_T m_Count;
  228. long m_Refs;
  229. };
  230. struct EmptyStringData
  231. {
  232. StringData m_StringData;
  233. T m_Data;
  234. };
  235. static EmptyStringData s_EmptyString;
  236. StringData *m_Value;
  237. void NewString( const char *String, bool ReplaceExisting = false );
  238. void NewString( const WCHAR *String, bool ReplaceExisting = false );
  239. StringData * RefIt() const
  240. {
  241. InterlockedIncrement( &m_Value->m_Refs );
  242. return m_Value;
  243. }
  244. void FreeIt()
  245. {
  246. if ( InterlockedDecrement( &m_Value->m_Refs ) == 0 )
  247. delete[] (char*)m_Value;
  248. }
  249. // Create String by concating 2 strings
  250. StringHandleTemplate( const StringData *LeftValue, const T *RightValue, SIZE_T RightSize );
  251. public:
  252. StringHandleTemplate()
  253. {
  254. NewString( (T*)NULL );
  255. }
  256. StringHandleTemplate( const char *String )
  257. {
  258. NewString( String );
  259. }
  260. StringHandleTemplate( const WCHAR *String )
  261. {
  262. NewString( String );
  263. }
  264. StringHandleTemplate( const StringHandleTemplate & Other ) :
  265. m_Value( Other.RefIt() )
  266. {
  267. }
  268. ~StringHandleTemplate()
  269. {
  270. FreeIt();
  271. }
  272. void SetStringSize()
  273. {
  274. m_Value->m_Count = strlen( (T*)(m_Value + 1) );
  275. }
  276. T *AllocBuffer( SIZE_T Size );
  277. StringHandleTemplate & operator=( const StringHandleTemplate & r )
  278. {
  279. FreeIt();
  280. m_Value = r.RefIt();
  281. return *this;
  282. }
  283. StringHandleTemplate & operator=( const T * r )
  284. {
  285. NewString( r, true );
  286. return *this;
  287. }
  288. SIZE_T Size() const
  289. {
  290. return m_Value->m_Count;
  291. }
  292. operator const T*() const
  293. {
  294. return (const T*)(m_Value + 1);
  295. }
  296. bool operator <( const StringHandleTemplate & r ) const
  297. {
  298. if ( m_Value == r.m_Value)
  299. return false;
  300. return (strcmp( (const T*)*this, (const T*)r ) < 0);
  301. }
  302. StringHandleTemplate operator+( const StringHandleTemplate & r ) const
  303. {
  304. return StringHandleTemplate( m_Value, (T*)(r.m_Value+1), r.m_Value->m_Count );
  305. }
  306. StringHandleTemplate operator+( const T * p ) const
  307. {
  308. static const T EmptyChar = '\0';
  309. if ( !p )
  310. return StringHandleTemplate( m_Value, &EmptyChar, 0 );
  311. return StringHandleTemplate( m_Value, p, strlen(p) );
  312. }
  313. StringHandleTemplate & operator+=( const StringHandleTemplate & r )
  314. {
  315. return (*this = (*this + r ) );
  316. }
  317. StringHandleTemplate & operator+=( const T * p )
  318. {
  319. return (*this = (*this + p ) );
  320. }
  321. };
  322. template<class T,class CONV>
  323. void
  324. StringHandleTemplate<T,CONV>::NewString( const char *String, bool ReplaceExisting )
  325. {
  326. if ( !String )
  327. {
  328. InterlockedIncrement( &s_EmptyString.m_StringData.m_Refs );
  329. StringData* Value = (StringData*)&s_EmptyString;
  330. if ( ReplaceExisting )
  331. FreeIt();
  332. m_Value = Value;
  333. return;
  334. }
  335. SIZE_T Size;
  336. StringData* Value = (StringData*)ConvertToInternal( sizeof(StringData), String, Size );
  337. Value->m_Count = Size;
  338. Value->m_Refs = 1;
  339. if ( ReplaceExisting )
  340. FreeIt();
  341. m_Value = Value;
  342. }
  343. template<class T,class CONV>
  344. void
  345. StringHandleTemplate<T,CONV>::NewString( const WCHAR *String, bool ReplaceExisting )
  346. {
  347. if ( !String )
  348. {
  349. InterlockedIncrement( &s_EmptyString.m_StringData.m_Refs );
  350. StringData* Value = (StringData*)&s_EmptyString;
  351. if ( ReplaceExisting )
  352. FreeIt();
  353. m_Value = Value;
  354. return;
  355. }
  356. SIZE_T Size;
  357. StringData* Value = (StringData*)ConvertToInternal( sizeof(StringData), String, Size );
  358. Value->m_Count = Size;
  359. Value->m_Refs = 1;
  360. if ( ReplaceExisting )
  361. FreeIt();
  362. m_Value = Value;
  363. }
  364. // Create String by concating 2 strings
  365. template<class T,class CONV>
  366. StringHandleTemplate<T,CONV>::StringHandleTemplate( const StringData *LeftValue, const T *RightValue, SIZE_T RightSize )
  367. {
  368. SIZE_T Size = LeftValue->m_Count + RightSize;
  369. m_Value = (StringData*)new char[ sizeof(StringData) + (Size*sizeof(T)) + sizeof(T) ];
  370. m_Value->m_Count = Size;
  371. m_Value->m_Refs = 1;
  372. T *DestData = (T*)( m_Value + 1 );
  373. memcpy( DestData, (T*)(LeftValue + 1), sizeof(T) * LeftValue->m_Count );
  374. memcpy( DestData + LeftValue->m_Count, RightValue, sizeof( T ) * RightSize );
  375. DestData[ Size ] = 0;
  376. }
  377. template<class T,class CONV>
  378. T *
  379. StringHandleTemplate<T,CONV>::AllocBuffer( SIZE_T Size )
  380. {
  381. StringData *Data = (StringData*)new T[sizeof(StringData)+(Size*sizeof(T))+sizeof(T)];
  382. Data->m_Count = 0;
  383. Data->m_Refs = 1;
  384. T *String = (T*)(Data + 1);
  385. String[0] = '\0';
  386. FreeIt(); // Free old string
  387. m_Value = Data;
  388. // Whoever fills in the string needs to call SetStringSize
  389. return String;
  390. }
  391. template<class T,class CONV>
  392. StringHandleTemplate<T,CONV>::EmptyStringData StringHandleTemplate<T,CONV>::s_EmptyString =
  393. {
  394. 0, 1, L'\0' // Initialize with 1 ref so it is never deleted
  395. };
  396. typedef StringHandleTemplate<char, CharStringRoutines> StringHandleA;
  397. typedef StringHandleTemplate<WCHAR, WCHARStringRoutines> StringHandleW;
  398. typedef StringHandleA StringHandle;
  399. inline UINT64 FILETIMEToUINT64( const FILETIME & FileTime )
  400. {
  401. ULARGE_INTEGER LargeInteger;
  402. LargeInteger.HighPart = FileTime.dwHighDateTime;
  403. LargeInteger.LowPart = FileTime.dwLowDateTime;
  404. return LargeInteger.QuadPart;
  405. }
  406. inline FILETIME UINT64ToFILETIME( UINT64 Int64Value )
  407. {
  408. ULARGE_INTEGER LargeInteger;
  409. LargeInteger.QuadPart = Int64Value;
  410. FILETIME FileTime;
  411. FileTime.dwHighDateTime = LargeInteger.HighPart;
  412. FileTime.dwLowDateTime = LargeInteger.LowPart;
  413. return FileTime;
  414. }
  415. // API thunks
  416. UINT64 BITSGetFileSize(
  417. HANDLE Handle );
  418. UINT64 BITSSetFilePointer(
  419. HANDLE Handle,
  420. INT64 Distance,
  421. DWORD MoveMethod );
  422. DWORD
  423. BITSWriteFile(
  424. HANDLE Handle,
  425. LPCVOID Buffer,
  426. DWORD NumberOfBytesToWrite);
  427. void
  428. BITSCreateDirectory(
  429. LPCTSTR DirectoryName
  430. );
  431. void
  432. BITSRenameFile(
  433. LPCTSTR ExistingName,
  434. LPCTSTR NewName );
  435. void
  436. BITSDeleteFile(
  437. LPCTSTR FileName );
  438. GUID
  439. BITSCreateGuid();
  440. GUID
  441. BITSGuidFromString( const char *String );
  442. StringHandle
  443. BITSStringFromGuid(
  444. GUID Guid );
  445. StringHandle
  446. BITSUnicodeToStringHandle( const WCHAR *pStr );
  447. StringHandle
  448. BITSUrlCombine(
  449. const char *Base,
  450. const char *Relative,
  451. DWORD dwFlags );
  452. StringHandle
  453. BITSUrlCanonicalize(
  454. const char *URL,
  455. DWORD dwFlags );
  456. void
  457. BITSSetCurrentThreadToken(
  458. HANDLE hToken );
  459. // Metadata wrappers
  460. StringHandle
  461. GetMetaDataString(
  462. IMSAdminBase *IISAdminBase,
  463. METADATA_HANDLE Handle,
  464. LPCWSTR Path,
  465. DWORD dwIdentifier,
  466. LPCSTR DefaultValue );
  467. DWORD
  468. GetMetaDataDWORD(
  469. IMSAdminBase *IISAdminBase,
  470. METADATA_HANDLE Handle,
  471. LPCWSTR Path,
  472. DWORD dwIdentifier,
  473. DWORD DefaultValue );
  474. class WorkStringBufferA
  475. {
  476. char *Data;
  477. public:
  478. WorkStringBufferA( SIZE_T Size )
  479. {
  480. Data = new char[Size];
  481. }
  482. WorkStringBufferA( const char* String )
  483. {
  484. size_t BufferSize = strlen(String) + 1;
  485. Data = new char[ BufferSize ];
  486. memcpy( Data, String, BufferSize );
  487. }
  488. ~WorkStringBufferA()
  489. {
  490. delete[] Data;
  491. }
  492. char *GetBuffer()
  493. {
  494. return Data;
  495. }
  496. };
  497. class WorkStringBufferW
  498. {
  499. WCHAR *Data;
  500. public:
  501. WorkStringBufferW( SIZE_T Size )
  502. {
  503. Data = new WCHAR[Size];
  504. }
  505. WorkStringBufferW( const WCHAR* String )
  506. {
  507. size_t BufferSize = wcslen(String) + 1;
  508. Data = new WCHAR[ BufferSize ];
  509. memcpy( Data, String, BufferSize * sizeof( WCHAR ) );
  510. }
  511. ~WorkStringBufferW()
  512. {
  513. delete[] Data;
  514. }
  515. WCHAR *GetBuffer()
  516. {
  517. return Data;
  518. }
  519. };
  520. typedef WorkStringBufferA WorkStringBuffer;
  521. const char * const BITS_CONNECTIONS_NAME_WITH_SLASH="BITS-Connections\\";
  522. const char * const BITS_CONNECTIONS_NAME="BITS-Connections";
  523. const UINT64 NanoSec100PerSec = 10000000; //no of 100 nanosecs per sec
  524. const DWORD WorkerRunInterval = 1000 * 60 /*secs*/ * 60 /*mins*/ * 12; /* hours */ /* twice a day */
  525. const UINT64 CleanupThreshold = NanoSec100PerSec * 60 /*secs*/ * 60 /*mins*/ * 24 /* hours */ * 3; // 3 days
  526. //
  527. // Configuration manager
  528. //
  529. #include "bitssrvcfg.h"
  530. class ConfigurationManager;
  531. class VDirConfig
  532. {
  533. friend ConfigurationManager;
  534. LONG m_Refs;
  535. FILETIME m_LastLookup;
  536. public:
  537. StringHandle m_Path;
  538. StringHandle m_PhysicalPath;
  539. StringHandle m_ConnectionsDir;
  540. DWORD m_NoProgressTimeout;
  541. UINT64 m_MaxFileSize;
  542. BITS_SERVER_NOTIFICATION_TYPE m_NotificationType;
  543. StringHandle m_NotificationURL;
  544. bool m_UploadEnabled;
  545. StringHandle m_HostId;
  546. DWORD m_HostIdFallbackTimeout;
  547. DWORD m_ExecutePermissions;
  548. VDirConfig(
  549. StringHandle Path,
  550. IMSAdminBase *AdminBase );
  551. void AddRef()
  552. {
  553. InterlockedIncrement( &m_Refs );
  554. }
  555. void Release()
  556. {
  557. if (!InterlockedDecrement( &m_Refs ))
  558. delete this;
  559. }
  560. };
  561. class MapCacheEntry
  562. {
  563. friend ConfigurationManager;
  564. FILETIME m_LastLookup;
  565. public:
  566. StringHandle m_InstanceMetabasePath;
  567. StringHandle m_URL;
  568. VDirConfig *m_Config;
  569. MapCacheEntry(
  570. StringHandle InstanceMetabasePath,
  571. StringHandle URL,
  572. VDirConfig * Config ) :
  573. m_InstanceMetabasePath( InstanceMetabasePath ),
  574. m_URL( URL ),
  575. m_Config( Config )
  576. {
  577. m_Config->AddRef();
  578. GetSystemTimeAsFileTime( &m_LastLookup );
  579. }
  580. ~MapCacheEntry()
  581. {
  582. m_Config->Release();
  583. }
  584. };
  585. class ConfigurationManager
  586. {
  587. public:
  588. ConfigurationManager();
  589. ~ConfigurationManager();
  590. VDirConfig* GetConfig( StringHandle InstanceMetabasePath, StringHandle URL );
  591. static const PATH_CACHE_ENTRIES = 10;
  592. static const MAP_CACHE_ENTRIES = 10;
  593. private:
  594. IMSAdminBase *m_IISAdminBase;
  595. CRITICAL_SECTION m_CacheCS;
  596. DWORD m_ChangeNumber;
  597. VDirConfig *m_PathCacheEntries[ PATH_CACHE_ENTRIES ];
  598. MapCacheEntry *m_MapCacheEntries[ MAP_CACHE_ENTRIES ];
  599. void FlushCache();
  600. bool HandleCacheConsistency();
  601. // L2 cache
  602. VDirConfig* Lookup( StringHandle Path );
  603. void Insert( VDirConfig *NewConfig );
  604. VDirConfig* GetVDirConfig( StringHandle Path );
  605. // L1 cache
  606. VDirConfig* Lookup( StringHandle InstanceMetabasePath,
  607. StringHandle URL );
  608. VDirConfig* Insert( StringHandle InstanceMetabasePath,
  609. StringHandle URL,
  610. StringHandle Path );
  611. StringHandle GetVDirPath( StringHandle InstanceMetabasePath,
  612. StringHandle URL );
  613. };
  614. extern ConfigurationManager *g_ConfigMan;
  615. extern HMODULE g_hinst;
  616. extern PropertyIDManager *g_PropertyMan;