Leaked source code of windows server 2003
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.

443 lines
10 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. datasetcache.cxx
  5. Abstract:
  6. A URL->data_set_number cache
  7. Author:
  8. Bilal Alam (balam) 8-12-2001
  9. Environment:
  10. Win32 - User Mode
  11. Project:
  12. ULW3.DLL
  13. --*/
  14. #include "precomp.hxx"
  15. DWORD DATA_SET_CACHE::sm_cMaxCacheEntries = 50;
  16. HRESULT
  17. DATA_SET_CACHE_ENTRY::Create(
  18. WCHAR * pszSubPath,
  19. DWORD dwMatchDataSetNumber,
  20. DWORD dwPrefixDataSetNumber
  21. )
  22. /*++
  23. Routine Description:
  24. Initialize a data set cache entry
  25. Arguments:
  26. pszSubPath - Sub path (based off site root)
  27. dwMatchDataSetNumber - Data set number for this entry
  28. dwPrefixDataSetNumber - Data set number for paths prefixed by this entry
  29. Return Value:
  30. HRESULT
  31. --*/
  32. {
  33. HRESULT hr;
  34. _dwMatchDataSetNumber = dwMatchDataSetNumber;
  35. _dwPrefixDataSetNumber = dwPrefixDataSetNumber;
  36. hr = _strSubPath.Copy( pszSubPath );
  37. if ( FAILED( hr ) )
  38. {
  39. return hr;
  40. }
  41. if ( _strSubPath.QueryCCH() != 0 &&
  42. _strSubPath.QueryStr()[ _strSubPath.QueryCCH() - 1 ] != L'/' )
  43. {
  44. hr = _strSubPath.Append( L"/" );
  45. if ( FAILED( hr ) )
  46. {
  47. return hr;
  48. }
  49. }
  50. return NO_ERROR;
  51. }
  52. //static
  53. HRESULT
  54. DATA_SET_CACHE::Initialize(
  55. VOID
  56. )
  57. /*++
  58. Routine Description:
  59. Initialize some data set cache globals
  60. Arguments:
  61. None
  62. Return Value:
  63. HRESULT
  64. --*/
  65. {
  66. DWORD dwError;
  67. DWORD dwType;
  68. DWORD dwValue;
  69. DWORD cbData;
  70. HKEY hKey = NULL;
  71. //
  72. // Read max DataSetCache size
  73. //
  74. dwError = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  75. L"System\\CurrentControlSet\\Services\\inetinfo\\Parameters",
  76. 0,
  77. KEY_READ,
  78. &hKey );
  79. if ( dwError == ERROR_SUCCESS )
  80. {
  81. DBG_ASSERT( hKey != NULL );
  82. //
  83. // Should we be file caching at all?
  84. //
  85. cbData = sizeof( DWORD );
  86. dwError = RegQueryValueEx( hKey,
  87. L"DataSetCacheSize",
  88. NULL,
  89. &dwType,
  90. (LPBYTE) &dwValue,
  91. &cbData );
  92. if ( dwError == ERROR_SUCCESS && dwType == REG_DWORD )
  93. {
  94. sm_cMaxCacheEntries = dwValue;
  95. }
  96. RegCloseKey( hKey );
  97. }
  98. return NO_ERROR;
  99. }
  100. HRESULT
  101. DATA_SET_CACHE::Create(
  102. STRU & strSiteRoot
  103. )
  104. /*++
  105. Routine Description:
  106. Initialize a data set number cache for the given site root path
  107. Arguments:
  108. strSiteRoot - Site root path (like /LM/W3SVC/<site-number>/Root)
  109. Return Value:
  110. HRESULT
  111. --*/
  112. {
  113. MB mb( g_pW3Server->QueryMDObject() );
  114. MB mb2( g_pW3Server->QueryMDObject() );
  115. BOOL fRet;
  116. HRESULT hr = NO_ERROR;
  117. WCHAR achSubRoot[ METADATA_MAX_NAME_LEN ];
  118. WCHAR achNextLevel[ METADATA_MAX_NAME_LEN ];
  119. STACK_STRU( strFullPath, 256 );
  120. DWORD i = 0;
  121. DWORD dwMatchDataSetNumber;
  122. DWORD dwPrefixDataSetNumber;
  123. DATA_SET_CACHE_ENTRY * pDataSetCacheEntry;
  124. BOOL fCanUseRoot = TRUE;
  125. hr = _strSiteRoot.Copy( strSiteRoot );
  126. if ( FAILED( hr ) )
  127. {
  128. goto Finished;
  129. }
  130. fRet = mb.Open( strSiteRoot.QueryStr() );
  131. if ( !fRet )
  132. {
  133. hr = HRESULT_FROM_WIN32( GetLastError() );
  134. goto Finished;
  135. }
  136. //
  137. // If there are more than sm_cMaxCacheEntries paths, then we should
  138. // not even bother with the cache
  139. //
  140. if ( mb.EnumObjects( NULL, achSubRoot, sm_cMaxCacheEntries ) )
  141. {
  142. return NO_ERROR;
  143. }
  144. //
  145. // Do a first level enumeration (we'll only handle one level for now)
  146. //
  147. while ( TRUE )
  148. {
  149. if ( !mb.EnumObjects( NULL, achSubRoot, i++ ) )
  150. {
  151. //
  152. // We've reached the end of the sub paths. If we can use the
  153. // root, then add it now (it will be the last entry)
  154. //
  155. if ( fCanUseRoot )
  156. {
  157. achSubRoot[ 0 ] = L'\0';
  158. }
  159. else
  160. {
  161. break;
  162. }
  163. }
  164. else
  165. {
  166. //
  167. // Only add an entry to data set cache if there are no sublevels
  168. //
  169. if ( mb.EnumObjects( achSubRoot, achNextLevel, 0 ) )
  170. {
  171. //
  172. // If there is a multi-level root, we cannot use the root in
  173. // getting data set number. Remember that.
  174. //
  175. fCanUseRoot = FALSE;
  176. continue;
  177. }
  178. }
  179. //
  180. // Cool. Get the data set numbers (we need to full path :-( )
  181. //
  182. hr = strFullPath.Copy( strSiteRoot );
  183. if ( FAILED( hr ) )
  184. {
  185. goto Finished;
  186. }
  187. hr = strFullPath.Append( achSubRoot );
  188. if ( FAILED( hr ) )
  189. {
  190. goto Finished;
  191. }
  192. if ( strFullPath.QueryStr()[ strFullPath.QueryCCH() - 1 ] != L'/' )
  193. {
  194. hr = strFullPath.Append( L"/" );
  195. if ( FAILED( hr ) )
  196. {
  197. goto Finished;
  198. }
  199. }
  200. //
  201. // We need two data set numbers.
  202. //
  203. // 1) One for the exact path
  204. // 2) One for the prefixed path. For this one, we'll just append
  205. // a bogus suffix and retrieve the data set number
  206. //
  207. if ( !mb2.GetDataSetNumber( strFullPath.QueryStr(),
  208. &dwMatchDataSetNumber ) )
  209. {
  210. hr = HRESULT_FROM_WIN32( GetLastError() );
  211. goto Finished;
  212. }
  213. hr = strFullPath.Append( L"foo" );
  214. if ( FAILED( hr ) )
  215. {
  216. goto Finished;
  217. }
  218. if ( !mb2.GetDataSetNumber( strFullPath.QueryStr(),
  219. &dwPrefixDataSetNumber ) )
  220. {
  221. hr = HRESULT_FROM_WIN32( GetLastError() );
  222. goto Finished;
  223. }
  224. //
  225. // Create an entry for this guy
  226. //
  227. pDataSetCacheEntry = new DATA_SET_CACHE_ENTRY;
  228. if ( pDataSetCacheEntry == NULL )
  229. {
  230. hr = HRESULT_FROM_WIN32( GetLastError() );
  231. goto Finished;
  232. }
  233. _wcsupr( achSubRoot );
  234. hr = pDataSetCacheEntry->Create( achSubRoot,
  235. dwMatchDataSetNumber,
  236. dwPrefixDataSetNumber );
  237. if ( FAILED( hr ) )
  238. {
  239. goto Finished;
  240. }
  241. //
  242. // Add to the array
  243. //
  244. if ( !_bufEntries.Resize( sizeof( DATA_SET_CACHE_ENTRY* ) *
  245. ( _cEntries + 1 ) ) )
  246. {
  247. hr = HRESULT_FROM_WIN32( GetLastError() );
  248. goto Finished;
  249. }
  250. QueryEntries()[ _cEntries ] = pDataSetCacheEntry;
  251. _cEntries++;
  252. //
  253. // If we've just added the root, we're done
  254. //
  255. if ( achSubRoot[ 0 ] == L'\0' )
  256. {
  257. break;
  258. }
  259. }
  260. Finished:
  261. return hr;
  262. }
  263. HRESULT
  264. DATA_SET_CACHE::GetDataSetNumber(
  265. STRU & strMetabasePath,
  266. DWORD * pdwDataSetNumber
  267. )
  268. /*++
  269. Routine Description:
  270. Get data set number from the cache
  271. Arguments:
  272. strMetabasePath - Metabase path to get data set number for (duh)
  273. pdwDataSetNumber - Filled with data set number (duh^2)
  274. Return Value:
  275. HRESULT
  276. --*/
  277. {
  278. DWORD i;
  279. DATA_SET_CACHE_ENTRY * pDataSetCacheEntry;
  280. STACK_STRU( strUpperPath, 256 );
  281. HRESULT hr;
  282. HANDLE hToken = NULL;
  283. if ( pdwDataSetNumber == NULL )
  284. {
  285. DBG_ASSERT( FALSE );
  286. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  287. }
  288. hr = strUpperPath.Copy( strMetabasePath.QueryStr() +
  289. _strSiteRoot.QueryCCH() );
  290. if ( FAILED( hr ) )
  291. {
  292. return hr;
  293. }
  294. _wcsupr( strUpperPath.QueryStr() );
  295. //
  296. // Add a trailing / if needed (since the entries are / suffixed)
  297. //
  298. if ( strUpperPath.QueryCCH() &&
  299. strUpperPath.QueryStr()[ strUpperPath.QueryCCH() - 1 ] != L'/' )
  300. {
  301. hr = strUpperPath.Append( L"/" );
  302. if ( FAILED( hr ) )
  303. {
  304. return hr;
  305. }
  306. }
  307. //
  308. // First check the data set number entries
  309. //
  310. for ( i = 0;
  311. i < _cEntries;
  312. i++ )
  313. {
  314. pDataSetCacheEntry = QueryEntries()[ i ];
  315. DBG_ASSERT( pDataSetCacheEntry != NULL );
  316. if ( pDataSetCacheEntry->QueryDoesMatch( strUpperPath, pdwDataSetNumber ) )
  317. {
  318. return NO_ERROR;
  319. }
  320. }
  321. //
  322. // If we're here, then we didn't find a match. Call into the metabase
  323. //
  324. MB mb( g_pW3Server->QueryMDObject() );
  325. //
  326. // If the caller is coming from an ISAPI, then the thread may
  327. // be impersonating. Temporarily discard the impersonation
  328. // token until we get the metadata.
  329. //
  330. if ( OpenThreadToken( GetCurrentThread(),
  331. TOKEN_IMPERSONATE,
  332. TRUE,
  333. &hToken ) )
  334. {
  335. DBG_ASSERT( hToken != NULL );
  336. DBG_REQUIRE( RevertToSelf() );
  337. }
  338. if ( !mb.GetDataSetNumber( strMetabasePath.QueryStr(),
  339. pdwDataSetNumber ) )
  340. {
  341. hr = HRESULT_FROM_WIN32( GetLastError() );
  342. }
  343. if ( hToken != NULL )
  344. {
  345. DBG_REQUIRE( SetThreadToken( NULL, hToken ) );
  346. DBG_REQUIRE( CloseHandle( hToken ) );
  347. hToken = NULL;
  348. }
  349. return hr;
  350. }