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.

2580 lines
74 KiB

  1. /*++
  2. creatfil.cxx
  3. Exports API for creating/opening a file, given the filename.
  4. The file handle and other information are cached for the given user handle.
  5. History:
  6. Heath Hunnicutt ( t-heathh) ??-??-??
  7. Murali R. Krishnan ( MuraliK) Dec 30, 1994
  8. Added SetLastError() to set error code as appropriate
  9. Murali R. Krishnan ( MuraliK) Jan 4, 1994
  10. Added ability to obtain and set the BY_HANDLE_FILE_INFORMATION
  11. as part of TS_OPEN_FILE_INFO
  12. --*/
  13. #include "TsunamiP.Hxx"
  14. #pragma hdrstop
  15. #include <lonsi.hxx>
  16. #include "auxctrs.h"
  17. #include <dbgutil.h>
  18. #include <iistypes.hxx>
  19. #include <iisver.h>
  20. #include <iiscnfg.h>
  21. #include <imd.h>
  22. #include <mb.hxx>
  23. LONG g_IISCacheAuxCounters[ AacIISCacheMaxCounters];
  24. GENERIC_MAPPING g_gmFile = {
  25. FILE_GENERIC_READ,
  26. FILE_GENERIC_WRITE,
  27. FILE_GENERIC_EXECUTE,
  28. FILE_ALL_ACCESS
  29. };
  30. //
  31. // Routines and macros for manipulating the "init complete" state of
  32. // a PHYS_OPEN_FILE_INFO structure.
  33. //
  34. VOID
  35. WaitForPhysInitComplete(
  36. IN PPHYS_OPEN_FILE_INFO lpPFInfo
  37. );
  38. #define WAIT_FOR_PHYS_INIT_COMPLETE( lpPFInfo ) \
  39. if( !lpPFInfo->fInitComplete ) { \
  40. WaitForPhysInitComplete( lpPFInfo ); \
  41. } else
  42. #define MARK_PHYS_INIT_COMPLETE( lpPFInfo ) \
  43. if( TRUE ) { \
  44. ASSERT( (lpPFInfo)->Signature == PHYS_OBJ_SIGNATURE ); \
  45. (lpPFInfo)->fInitComplete = TRUE; \
  46. } else
  47. #define PHYS_INIT_SLEEP_START 100 // ms
  48. #define PHYS_INIT_SLEEP_INCR 100 // ms
  49. #define PHYS_INIT_SLEEP_MAX 1000 // ms
  50. dllexp
  51. PSECURITY_DESCRIPTOR
  52. TsGetFileSecDesc(
  53. LPTS_OPEN_FILE_INFO pFile
  54. )
  55. /*++
  56. Routine Description:
  57. Returns the security descriptor associated to the file
  58. To be freed using LocalFree()
  59. Arguments:
  60. pFile - ptr to fie object
  61. Return Value:
  62. ptr to security descriptor or NULL if error
  63. --*/
  64. {
  65. SECURITY_INFORMATION si
  66. = OWNER_SECURITY_INFORMATION |
  67. GROUP_SECURITY_INFORMATION |
  68. DACL_SECURITY_INFORMATION;
  69. BYTE abSecDesc[ SECURITY_DESC_DEFAULT_SIZE ];
  70. DWORD dwSecDescSize;
  71. PSECURITY_DESCRIPTOR pAcl;
  72. if ( GetKernelObjectSecurity(
  73. pFile->QueryFileHandle(),
  74. si,
  75. (PSECURITY_DESCRIPTOR)abSecDesc,
  76. SECURITY_DESC_DEFAULT_SIZE,
  77. &dwSecDescSize ) )
  78. {
  79. if ( dwSecDescSize > SECURITY_DESC_DEFAULT_SIZE )
  80. {
  81. if ( !(pAcl = (PSECURITY_DESCRIPTOR)LocalAlloc( LMEM_FIXED, dwSecDescSize )) )
  82. {
  83. return NULL;
  84. }
  85. if ( !GetKernelObjectSecurity(
  86. pFile->QueryFileHandle(),
  87. si,
  88. pAcl,
  89. dwSecDescSize,
  90. &dwSecDescSize ) )
  91. {
  92. LocalFree( pAcl );
  93. return NULL;
  94. }
  95. }
  96. else
  97. {
  98. if ( dwSecDescSize = GetSecurityDescriptorLength(abSecDesc) )
  99. {
  100. if ( !(pAcl = (PSECURITY_DESCRIPTOR)LocalAlloc( LMEM_FIXED,
  101. dwSecDescSize )) )
  102. {
  103. return NULL;
  104. }
  105. memcpy( pAcl, abSecDesc, dwSecDescSize );
  106. }
  107. else
  108. {
  109. //
  110. // Security descriptor is empty : do not return ptr to security descriptor
  111. //
  112. pAcl = NULL;
  113. }
  114. }
  115. }
  116. else
  117. {
  118. pAcl = NULL;
  119. }
  120. return pAcl;
  121. }
  122. BOOL
  123. TsReInitPhysFile(
  124. IN PPHYS_OPEN_FILE_INFO pPhysFileInfo
  125. )
  126. /*+++
  127. TsReInitPhysFile
  128. Called when we get a valid, initialized phys file info structure that
  129. has an invalid file handle. We acquire the cache critical section and
  130. check to see if the file is still valid and still has an invalid handle
  131. value. If it does, we're the first to try to do this, so we'll mark
  132. the structure and initing, and let our caller try to initialize it.
  133. Otherwise we'll just return and let our caller try again.
  134. Arguments:
  135. pPhysFileInfo - Pointer to the phys file info structure.
  136. Returns:
  137. FALSE if we reinited, TRUE otherwise.
  138. ---*/
  139. {
  140. BOOL bRetVal;
  141. EnterCriticalSection( &CacheTable.CriticalSection );
  142. if ( pPhysFileInfo->fInitComplete &&
  143. pPhysFileInfo->hOpenFile == INVALID_HANDLE_VALUE
  144. )
  145. {
  146. pPhysFileInfo->fInitComplete = FALSE;
  147. bRetVal = FALSE;
  148. }
  149. else
  150. {
  151. bRetVal = TRUE;
  152. }
  153. LeaveCriticalSection( &CacheTable.CriticalSection );
  154. return bRetVal;
  155. }
  156. VOID
  157. WaitForPhysInitComplete(
  158. IN PPHYS_OPEN_FILE_INFO lpPFInfo
  159. )
  160. /*++
  161. Routine Description:
  162. Waits for the specified physical open file info structure to become
  163. fully initialized.
  164. Arguments:
  165. lpPFInfo - The PHYS_OPEN_FILE_INFO structure to wait for.
  166. Return Value:
  167. None.
  168. --*/
  169. {
  170. DWORD sleepTime;
  171. //
  172. // Sanity check.
  173. //
  174. ASSERT( lpPFInfo != NULL );
  175. //
  176. // Perform a linear backoff delay while waiting for init complete.
  177. //
  178. sleepTime = PHYS_INIT_SLEEP_START;
  179. while( !lpPFInfo->fInitComplete ) {
  180. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  181. Sleep( sleepTime );
  182. sleepTime += PHYS_INIT_SLEEP_INCR;
  183. if( sleepTime > PHYS_INIT_SLEEP_MAX ) {
  184. sleepTime = PHYS_INIT_SLEEP_MAX;
  185. }
  186. }
  187. } // WaitForPhysInitComplete
  188. VOID
  189. OplockCreateFile(
  190. PVOID Context,
  191. DWORD Status
  192. )
  193. {
  194. POPLOCK_OBJECT lpOplock = (POPLOCK_OBJECT)Context;
  195. PBLOB_HEADER pbhBlob;
  196. PCACHE_OBJECT cache;
  197. PCACHE_OBJECT pCacheTmp;
  198. PCACHE_OBJECT TmpCache;
  199. BOOL result = FALSE;
  200. LIST_ENTRY ListHead;
  201. LIST_ENTRY * pEntry;
  202. LIST_ENTRY * pNextEntry;
  203. IF_DEBUG(OPLOCKS) {
  204. DBGPRINTF( (DBG_CONTEXT,"OplockCreateFile(%08lx, %08lx) - Entered\n", Context, Status ));
  205. }
  206. if (lpOplock == NULL) {
  207. return;
  208. }
  209. ASSERT(lpOplock->Signature == OPLOCK_OBJ_SIGNATURE);
  210. if ( Status != OPLOCK_BREAK_NO_OPLOCK ) {
  211. WaitForSingleObject( lpOplock->hOplockInitComplete, (DWORD)(-1) );
  212. }
  213. if ( Status == OPLOCK_BREAK_OPEN ) {
  214. if ( lpOplock->lpPFInfo != NULL ) {
  215. pbhBlob = (( PBLOB_HEADER )lpOplock->lpPFInfo ) - 1;
  216. if ( pbhBlob->IsCached ) {
  217. cache = pbhBlob->pCache;
  218. InitializeListHead( &ListHead );
  219. EnterCriticalSection( &CacheTable.CriticalSection );
  220. EnterCriticalSection( &csVirtualRoots );
  221. for ( pEntry = CacheTable.MruList.Flink;
  222. pEntry != &CacheTable.MruList;
  223. pEntry = pNextEntry ) {
  224. pNextEntry = pEntry->Flink;
  225. pCacheTmp = CONTAINING_RECORD( pEntry, CACHE_OBJECT, MruList );
  226. ASSERT( pCacheTmp->Signature == CACHE_OBJ_SIGNATURE );
  227. if ( pCacheTmp != cache ) {
  228. continue;
  229. }
  230. result = TRUE;
  231. while ( !IsListEmpty( &lpOplock->lpPFInfo->OpenReferenceList ) ) {
  232. pEntry = RemoveHeadList( &lpOplock->lpPFInfo->OpenReferenceList );
  233. pbhBlob = CONTAINING_RECORD( pEntry, BLOB_HEADER, PFList );
  234. TmpCache = pbhBlob->pCache;
  235. if (!RemoveCacheObjFromLists( TmpCache, FALSE ) ) {
  236. IF_DEBUG(OPLOCKS) {
  237. DBGPRINTF( (DBG_CONTEXT,"OplockCreateFile(%08lx, %08lx, %08lx) - Error Processing Open Reference %08lx\n", Context, Status, pEntry, TmpCache ));
  238. }
  239. break;
  240. }
  241. IF_DEBUG(OPLOCKS) {
  242. DBGPRINTF( (DBG_CONTEXT,"OplockCreateFile(%08lx, %08lx, %08lx) - Processing Open Reference %08lx\n", Context, Status, pEntry, TmpCache ));
  243. }
  244. InsertTailList( &ListHead, pEntry );
  245. }
  246. break;
  247. }
  248. LeaveCriticalSection( &csVirtualRoots );
  249. LeaveCriticalSection( &CacheTable.CriticalSection );
  250. if ( result ) {
  251. while ( !IsListEmpty( &ListHead ) ) {
  252. pEntry = RemoveHeadList( &ListHead );
  253. pbhBlob = CONTAINING_RECORD( pEntry, BLOB_HEADER, PFList );
  254. TmpCache = pbhBlob->pCache;
  255. IF_DEBUG(OPLOCKS) {
  256. DBGPRINTF( (DBG_CONTEXT,"OplockCreateFile(%08lx, %08lx) - Processing Open Reference %08lx %08lx\n", Context, Status, pEntry, TmpCache ));
  257. }
  258. TsDereferenceCacheObj( TmpCache, TRUE );
  259. }
  260. }
  261. }
  262. }
  263. }
  264. CloseHandle( lpOplock->hOplockInitComplete );
  265. lpOplock->Signature = 0;
  266. LocalFree(lpOplock);
  267. }
  268. VOID
  269. TsRemovePhysFile(
  270. PPHYS_OPEN_FILE_INFO lpPFInfo
  271. )
  272. {
  273. PBLOB_HEADER pbhBlob;
  274. PCACHE_OBJECT cache;
  275. PCACHE_OBJECT pCacheTmp;
  276. PCACHE_OBJECT TmpCache;
  277. BOOL result = FALSE;
  278. BOOL bSuccess;
  279. LIST_ENTRY * pEntry;
  280. LIST_ENTRY * pNextEntry;
  281. IF_DEBUG(OPLOCKS) {
  282. DBGPRINTF( (DBG_CONTEXT,"TsRemovePhysFile(%08lx) - Entered\n", lpPFInfo ));
  283. }
  284. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  285. TSUNAMI_TRACE( TRACE_PHYS_REMOVE, lpPFInfo );
  286. pbhBlob = (( PBLOB_HEADER )lpPFInfo ) - 1;
  287. if ( pbhBlob->IsCached ) {
  288. cache = pbhBlob->pCache;
  289. EnterCriticalSection( &CacheTable.CriticalSection );
  290. EnterCriticalSection( &csVirtualRoots );
  291. if ( cache->references > 1 ) {
  292. TsCheckInCachedBlob( (PVOID)lpPFInfo );
  293. } else {
  294. for ( pEntry = CacheTable.MruList.Flink;
  295. pEntry != &CacheTable.MruList;
  296. pEntry = pNextEntry ) {
  297. pNextEntry = pEntry->Flink;
  298. pCacheTmp = CONTAINING_RECORD( pEntry, CACHE_OBJECT, MruList );
  299. ASSERT( pCacheTmp->Signature == CACHE_OBJ_SIGNATURE );
  300. if ( pCacheTmp != cache ) {
  301. continue;
  302. }
  303. if ( !RemoveCacheObjFromLists( cache, FALSE ) ) {
  304. ASSERT( FALSE );
  305. continue;
  306. }
  307. result = TRUE;
  308. break;
  309. }
  310. }
  311. LeaveCriticalSection( &csVirtualRoots );
  312. LeaveCriticalSection( &CacheTable.CriticalSection );
  313. if ( result ) {
  314. TsDereferenceCacheObj( cache, TRUE );
  315. }
  316. } else {
  317. if ( pbhBlob->pfnFreeRoutine ) {
  318. bSuccess = pbhBlob->pfnFreeRoutine( (PVOID)lpPFInfo );
  319. } else {
  320. bSuccess = TRUE;
  321. }
  322. if ( bSuccess ) {
  323. //
  324. // Free the memory used by the Blob.
  325. //
  326. FREE( pbhBlob );
  327. }
  328. }
  329. }
  330. dllexp
  331. BOOL
  332. TsDeleteOnClose(PW3_URI_INFO pURIInfo,
  333. HANDLE OpeningUser,
  334. BOOL *fDeleted)
  335. {
  336. PPHYS_OPEN_FILE_INFO lpPFInfo;
  337. LPTS_OPEN_FILE_INFO lpOpenFile;
  338. BYTE psFile[SIZE_PRIVILEGE_SET];
  339. DWORD dwPS;
  340. DWORD dwGrantedAccess;
  341. BOOL fAccess;
  342. if ( DisableSPUD || pURIInfo == NULL ) {
  343. return FALSE;
  344. }
  345. #if 0
  346. IF_DEBUG(OPLOCKS) {
  347. DBGPRINTF( (DBG_CONTEXT,"TsDeleteOnClose(%08lx) - Waiting On hFileEvent!\n", pURIInfo ));
  348. }
  349. WaitForSingleObject( pURIInfo->hFileEvent, (DWORD)(-1) );
  350. IF_DEBUG(OPLOCKS) {
  351. DBGPRINTF( (DBG_CONTEXT,"TsDeleteOnClose(%08lx) - Returned from Waiting On hFileEvent!\n", pURIInfo ));
  352. }
  353. lpOpenFile = pURIInfo->pOpenFileInfo;
  354. if ( lpOpenFile == NULL ) {
  355. IF_DEBUG(OPLOCKS) {
  356. DBGPRINTF( (DBG_CONTEXT,"TsDeleteOnClose(%08lx) - lpOpenFile == NULL!\n", pURIInfo ));
  357. }
  358. return FALSE;
  359. }
  360. *fDeleted = FALSE;
  361. lpPFInfo = lpOpenFile->QueryPhysFileInfo();
  362. if ( lpPFInfo->fIsCached && lpPFInfo->fSecurityDescriptor ) {
  363. dwPS = sizeof(psFile);
  364. ((PRIVILEGE_SET*)&psFile)->PrivilegeCount = 0;
  365. if ( AccessCheck(
  366. lpPFInfo->abSecurityDescriptor,
  367. OpeningUser,
  368. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  369. &g_gmFile,
  370. (PRIVILEGE_SET*)psFile,
  371. &dwPS,
  372. &dwGrantedAccess,
  373. &fAccess) ) {
  374. if ( fAccess ) {
  375. IF_DEBUG(OPLOCKS) {
  376. DBGPRINTF( (DBG_CONTEXT,"TsDeleteOnClose(%08lx) - Marking file for delete!\n", lpPFInfo ));
  377. }
  378. lpPFInfo->fDeleteOnClose = TRUE;
  379. *fDeleted = TRUE;
  380. }
  381. }
  382. } else {
  383. IF_DEBUG(OPLOCKS) {
  384. DBGPRINTF( (DBG_CONTEXT,"TsDeleteOnClose(%08lx) - !fIsCached || !fSecurityDescriptor\n", lpPFInfo ));
  385. }
  386. return FALSE;
  387. }
  388. #endif //!oplock
  389. return TRUE;
  390. }
  391. BOOL
  392. TsAccessCheck(
  393. IN PPHYS_OPEN_FILE_INFO pFile,
  394. IN HANDLE hUser
  395. )
  396. /*+++
  397. TsAccessCheck
  398. This routine validates that the user identified by hUser has permissions
  399. to access the file associated with the input physical file open structure.
  400. We use the cached security descriptor in pFile to do so if we can;
  401. otherwise we'll try and read the security descriptor first.
  402. Arguments:
  403. pFile - A pointer to the physical file open structure
  404. identifying the file.
  405. hUser - User access token to be checked.
  406. Returns:
  407. TRUE if the file can be accessed, FALSE otherwise.
  408. ---*/
  409. {
  410. PSECURITY_DESCRIPTOR pSecDesc;
  411. BOOL bHaveAccess;
  412. CHAR cBuffer[SIZE_PRIVILEGE_SET];
  413. DWORD dwPSSize;
  414. PPRIVILEGE_SET pPS;
  415. DWORD dwGrantedAccess;
  416. // See if we've got a cached security descriptor; if not, read one
  417. // from the file.
  418. if ( !pFile->fSecurityDescriptor )
  419. {
  420. DWORD dwError;
  421. DWORD dwInputSize;
  422. DWORD dwSizeNeeded;
  423. // Don't have one cached, need to read one. Allocate a buffer and
  424. // set up the basic information we need for this call.
  425. dwInputSize = SECURITY_DESC_DEFAULT_SIZE;
  426. pSecDesc = (PSECURITY_DESCRIPTOR)ALLOC( dwInputSize );
  427. if ( pSecDesc == NULL )
  428. {
  429. return FALSE;
  430. }
  431. for (;;)
  432. {
  433. // Try and read the security descriptor. If we can, then we're done
  434. // with this loop.
  435. if ( GetKernelObjectSecurity(
  436. pFile->hOpenFile,
  437. OWNER_SECURITY_INFORMATION |
  438. GROUP_SECURITY_INFORMATION |
  439. DACL_SECURITY_INFORMATION,
  440. pSecDesc,
  441. dwInputSize,
  442. &dwSizeNeeded ) )
  443. {
  444. break;
  445. }
  446. // Couldn't read it. If it happened because our buffer was too
  447. // small, allocate a bigger one and try again. Otherwise so other
  448. // error happened. In that case we can't read the descriptor, so
  449. // return failure.
  450. dwError = GetLastError();
  451. FREE( pSecDesc ); // Don't need this anymore, in any case.
  452. if ( dwError != ERROR_INSUFFICIENT_BUFFER )
  453. {
  454. // Some other error, fail.
  455. return FALSE;
  456. }
  457. // Now try and allocate a buffer of the size the API said we need.
  458. dwInputSize = dwSizeNeeded;
  459. pSecDesc = (PSECURITY_DESCRIPTOR)ALLOC( dwInputSize );
  460. if ( pSecDesc == NULL )
  461. {
  462. return FALSE;
  463. }
  464. }
  465. }
  466. else
  467. {
  468. // Have one cached, use that.
  469. pSecDesc = pFile->abSecurityDescriptor;
  470. }
  471. // Have a security descriptor now, so do the check.
  472. pPS = (PPRIVILEGE_SET)cBuffer;
  473. dwPSSize = SIZE_PRIVILEGE_SET;
  474. pPS->PrivilegeCount = 0;
  475. if (
  476. !AccessCheck(
  477. pSecDesc,
  478. hUser,
  479. FILE_GENERIC_READ,
  480. &g_gmFile,
  481. pPS,
  482. &dwPSSize,
  483. &dwGrantedAccess,
  484. &bHaveAccess )
  485. )
  486. {
  487. bHaveAccess = FALSE;
  488. }
  489. // Free our temporary buffer if neccessary.
  490. if ( !pFile->fSecurityDescriptor )
  491. {
  492. FREE( pSecDesc );
  493. }
  494. return bHaveAccess;
  495. }
  496. dllexp
  497. LPTS_OPEN_FILE_INFO
  498. TsCreateFile(
  499. IN const TSVC_CACHE &TSvcCache,
  500. IN LPCSTR pszName,
  501. IN HANDLE OpeningUser,
  502. IN DWORD dwOptions
  503. )
  504. {
  505. HANDLE hFile;
  506. PVOID pvBlob;
  507. PPHYS_OPEN_FILE_INFO lpPFInfo;
  508. LPTS_OPEN_FILE_INFO lpOpenFile;
  509. POPLOCK_OBJECT lpOplock;
  510. BOOL bSuccess;
  511. BOOL fAtRoot;
  512. BOOL fImpersonated = FALSE;
  513. DWORD dwSecDescSize;
  514. DWORD dwReadN;
  515. SECURITY_INFORMATION si
  516. = OWNER_SECURITY_INFORMATION
  517. | GROUP_SECURITY_INFORMATION
  518. | DACL_SECURITY_INFORMATION;
  519. PSECURITY_DESCRIPTOR abSecDesc;
  520. BOOL fDoReadObjectSecurity;
  521. BOOL fObjectSecurityPresent;
  522. BOOL fOplockSucceeded = TRUE;
  523. SECURITY_ATTRIBUTES sa;
  524. BOOL fPhysFileCacheHit = FALSE;
  525. BOOL fNoCanon = (dwOptions & TS_USE_WIN32_CANON) == 0;
  526. BOOL fAccess;
  527. DWORD dwGrantedAccess;
  528. DWORD dwPS;
  529. DWORD cch;
  530. DWORD cbPrefix;
  531. LPCSTR pszPath;
  532. WCHAR awchPath[MAX_PATH+8+1];
  533. BYTE psFile[SIZE_PRIVILEGE_SET];
  534. BOOL fDontUseSpud = (DisableSPUD || !fNoCanon);
  535. DWORD err;
  536. //
  537. // Mask out options that are not applicable
  538. //
  539. dwOptions &= TsValidCreateFileOptions;
  540. if ( TsIsWindows95() ) {
  541. dwOptions |= (TS_NO_ACCESS_CHECK | TS_DONT_CACHE_ACCESS_TOKEN);
  542. }
  543. //
  544. // Have we cached a handle to this file?
  545. //
  546. if ( dwOptions & TS_CACHING_DESIRED )
  547. {
  548. bSuccess = TsCheckOutCachedBlob( TSvcCache,
  549. pszName,
  550. RESERVED_DEMUX_OPEN_FILE,
  551. &pvBlob );
  552. if ( bSuccess )
  553. {
  554. ASSERT( BLOB_IS_OR_WAS_CACHED( pvBlob ) );
  555. //
  556. // The following is a brutal casting of PVOID to C++ object
  557. // Well. there is no way to extract the object clearly from the
  558. // memory map :(
  559. //
  560. lpOpenFile = (LPTS_OPEN_FILE_INFO )pvBlob;
  561. //
  562. // Make sure the user tokens match
  563. //
  564. if ( (OpeningUser == lpOpenFile->QueryOpeningUser()
  565. && NULL != lpOpenFile->QueryOpeningUser())
  566. || (dwOptions & TS_NO_ACCESS_CHECK) )
  567. {
  568. ASSERT ( lpOpenFile->IsValid());
  569. TSUNAMI_TRACE( TRACE_OPENFILE_REFERENCE, lpOpenFile );
  570. return( lpOpenFile);
  571. }
  572. //
  573. // User token doesn't match
  574. //
  575. if ( !g_fCacheSecDesc )
  576. {
  577. //
  578. // Check in object, will have to
  579. // open the file with the new user access token
  580. //
  581. bSuccess = TsCheckInCachedBlob( pvBlob );
  582. ASSERT( bSuccess );
  583. }
  584. else
  585. {
  586. //
  587. // attempt to validate access using cached
  588. // security descriptor
  589. //
  590. if ( lpOpenFile->IsSecurityDescriptorValid() )
  591. {
  592. dwPS = sizeof( psFile );
  593. ((PRIVILEGE_SET*)&psFile)->PrivilegeCount = 0;
  594. if ( !AccessCheck(
  595. lpOpenFile->GetSecurityDescriptor(),
  596. OpeningUser,
  597. FILE_GENERIC_READ,
  598. &g_gmFile,
  599. (PRIVILEGE_SET*)psFile,
  600. &dwPS,
  601. &dwGrantedAccess,
  602. &fAccess ) )
  603. {
  604. DBGPRINTF(( DBG_CONTEXT,
  605. "[TsCreateFile]: AccessCheck failed, error %d\n",
  606. GetLastError() ));
  607. fAccess = FALSE;
  608. }
  609. if ( fAccess )
  610. {
  611. return( lpOpenFile );
  612. }
  613. }
  614. //
  615. // not validated using cached information
  616. //
  617. bSuccess = TsCheckInCachedBlob( pvBlob );
  618. ASSERT( bSuccess );
  619. if ( lpOpenFile->IsSecurityDescriptorValid() )
  620. {
  621. return( NULL );
  622. }
  623. }
  624. }
  625. }
  626. if ( TsIsWindows95() )
  627. {
  628. fNoCanon = FALSE;
  629. }
  630. fDoReadObjectSecurity = FALSE;
  631. sa.nLength = sizeof(sa);
  632. sa.lpSecurityDescriptor = NULL;
  633. sa.bInheritHandle = FALSE;
  634. IF_DEBUG(OPLOCKS) {
  635. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - Calling TsCheckOutCachedPhysFile\n", pszName ));
  636. }
  637. fPhysFileCacheHit = TsCheckOutCachedPhysFile( TSvcCache,
  638. pszName,
  639. (VOID **)&lpPFInfo );
  640. while (fPhysFileCacheHit)
  641. {
  642. DWORD dwLastError;
  643. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  644. WAIT_FOR_PHYS_INIT_COMPLETE( lpPFInfo );
  645. hFile = lpPFInfo->hOpenFile;
  646. if (hFile != INVALID_HANDLE_VALUE)
  647. {
  648. break;
  649. }
  650. dwLastError = lpPFInfo->dwLastError;
  651. if (dwLastError != ERROR_FILE_NOT_FOUND &&
  652. dwLastError != ERROR_PATH_NOT_FOUND &&
  653. dwLastError != ERROR_INVALID_NAME )
  654. {
  655. fPhysFileCacheHit = TsReInitPhysFile(lpPFInfo);
  656. }
  657. else
  658. {
  659. TsRemovePhysFile(lpPFInfo);
  660. SetLastError(dwLastError);
  661. return NULL;
  662. }
  663. }
  664. if ( fPhysFileCacheHit )
  665. {
  666. DBG_ASSERT( hFile != INVALID_HANDLE_VALUE );
  667. abSecDesc = lpPFInfo->abSecurityDescriptor;
  668. dwSecDescSize = lpPFInfo->cbSecDescMaxSize;
  669. fObjectSecurityPresent = lpPFInfo->fSecurityDescriptor;
  670. //
  671. // We've got a file handle from the cache. If we're doing access
  672. // checking make sure we can use it.
  673. //
  674. if (!(dwOptions & TS_NO_ACCESS_CHECK))
  675. {
  676. if ( !TsAccessCheck(lpPFInfo, OpeningUser) )
  677. {
  678. // Don't have permission to use this handle, so fail.
  679. //
  680. TsCheckInOrFree( (PVOID)lpPFInfo );
  681. SetLastError(ERROR_ACCESS_DENIED);
  682. return NULL;
  683. }
  684. }
  685. } else {
  686. if ( lpPFInfo == NULL ) {
  687. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  688. return NULL;
  689. }
  690. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  691. if ( (dwOptions & TS_NOT_IMPERSONATED) &&
  692. !(dwOptions & TS_NO_ACCESS_CHECK) )
  693. {
  694. if ( !::ImpersonateLoggedOnUser( OpeningUser ) )
  695. {
  696. DBGPRINTF(( DBG_CONTEXT,
  697. "ImpersonateLoggedOnUser[%d] failed with %d\n",
  698. OpeningUser, GetLastError()));
  699. err = lpPFInfo->dwLastError;
  700. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  701. TsRemovePhysFile(lpPFInfo);
  702. SetLastError( err );
  703. return NULL;
  704. }
  705. fImpersonated = TRUE;
  706. }
  707. IF_DEBUG(OPLOCKS) {
  708. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - Not in cache, Opening!\n", pszName ));
  709. }
  710. abSecDesc = lpPFInfo->abSecurityDescriptor;
  711. dwSecDescSize = lpPFInfo->cbSecDescMaxSize;
  712. IF_DEBUG(OPLOCKS) {
  713. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - abSecDesc = %08lx, size = %08lx\n", pszName, abSecDesc, SECURITY_DESC_DEFAULT_SIZE ));
  714. }
  715. if ( abSecDesc == NULL ) {
  716. if( fImpersonated ) {
  717. ::RevertToSelf();
  718. fImpersonated = FALSE;
  719. }
  720. ASSERT( !fImpersonated );
  721. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  722. TsRemovePhysFile(lpPFInfo);
  723. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  724. return( NULL );
  725. }
  726. if ( fNoCanon )
  727. {
  728. if ( (pszName[0] == '\\') && (pszName[1] == '\\') )
  729. {
  730. CopyMemory(
  731. awchPath,
  732. L"\\\\?\\UNC\\",
  733. (sizeof("\\\\?\\UNC\\")-1) * sizeof(WCHAR)
  734. );
  735. cbPrefix = sizeof("\\\\?\\UNC\\")-1;
  736. pszPath = pszName + sizeof( "\\\\" ) -1;
  737. }
  738. else
  739. {
  740. CopyMemory(
  741. awchPath,
  742. L"\\\\?\\",
  743. (sizeof("\\\\?\\")-1) * sizeof(WCHAR)
  744. );
  745. cbPrefix = sizeof("\\\\?\\")-1;
  746. pszPath = pszName;
  747. }
  748. cch = MultiByteToWideChar( CP_ACP,
  749. MB_PRECOMPOSED,
  750. pszPath,
  751. -1,
  752. awchPath + cbPrefix,
  753. sizeof(awchPath)/sizeof(WCHAR) - cbPrefix );
  754. if ( !cch )
  755. {
  756. hFile = INVALID_HANDLE_VALUE;
  757. }
  758. else
  759. {
  760. if ( (pszName[1] == ':') && (pszName[2] == '\0') )
  761. {
  762. wcscat( awchPath, L"\\" );
  763. }
  764. sa.nLength = sizeof(sa);
  765. sa.lpSecurityDescriptor = NULL;
  766. sa.bInheritHandle = FALSE;
  767. #if 1
  768. // if ( fDontUseSpud ) {
  769. hFile = CreateFileW( awchPath,
  770. GENERIC_READ,
  771. TsCreateFileShareMode,
  772. &sa,
  773. OPEN_EXISTING,
  774. TsCreateFileFlags,
  775. NULL );
  776. #else
  777. } else {
  778. lpOplock = ( POPLOCK_OBJECT )LocalAlloc(LPTR, sizeof(OPLOCK_OBJECT));
  779. if ( lpOplock == NULL ) {
  780. DBGPRINTF((DBG_CONTEXT,"LocalAlloc lpOplock[%s] failed with %d\n",
  781. pszName, GetLastError()));
  782. if ( fImpersonated ) {
  783. ::RevertToSelf();
  784. fImpersonated = FALSE;
  785. }
  786. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  787. TsRemovePhysFile(lpPFInfo);
  788. ASSERT( !fImpersonated );
  789. return( NULL );
  790. }
  791. lpOplock->Signature = OPLOCK_OBJ_SIGNATURE;
  792. lpOplock->lpPFInfo = NULL;
  793. lpOplock->hOplockInitComplete = IIS_CREATE_EVENT(
  794. "OPLOCK_OBJECT::hOplockInitComplete",
  795. lpOplock,
  796. TRUE,
  797. FALSE
  798. );
  799. hFile = AtqCreateFileW( awchPath,
  800. TsCreateFileShareMode,
  801. &sa,
  802. TsCreateFileFlags,
  803. si,
  804. (PSECURITY_DESCRIPTOR)abSecDesc,
  805. ( ( g_fCacheSecDesc
  806. && !(dwOptions & TS_NO_ACCESS_CHECK)
  807. && (dwOptions & TS_CACHING_DESIRED) ) ?
  808. SECURITY_DESC_DEFAULT_SIZE : 0 ),
  809. &dwSecDescSize,
  810. OplockCreateFile,
  811. (PVOID)lpOplock );
  812. }
  813. #endif //!oplock
  814. }
  815. }
  816. else
  817. {
  818. hFile = CreateFile( pszName,
  819. GENERIC_READ,
  820. TsCreateFileShareMode,
  821. &sa,
  822. OPEN_EXISTING,
  823. TsCreateFileFlags,
  824. NULL );
  825. }
  826. //
  827. // If we're supposed to cache the security descriptor, do so now.
  828. // This should only be done once, by the thread intializing the physical
  829. // file entry.
  830. //
  831. if (DisableSPUD && hFile != INVALID_HANDLE_VALUE)
  832. {
  833. if ( g_fCacheSecDesc )
  834. {
  835. DWORD dwInputSize;
  836. dwInputSize = dwSecDescSize;
  837. // Loop, reading the security info each time, until we either
  838. // read it succesfully, are unable to allocate a big enough buffer,
  839. // or get some error other than buffer too smal.
  840. for (;;)
  841. {
  842. if ( GetKernelObjectSecurity(
  843. hFile,
  844. si,
  845. (PSECURITY_DESCRIPTOR)lpPFInfo->abSecurityDescriptor,
  846. dwInputSize,
  847. &dwSecDescSize ) )
  848. {
  849. lpPFInfo->fSecurityDescriptor = TRUE ;
  850. fObjectSecurityPresent = TRUE;
  851. abSecDesc = (PSECURITY_DESCRIPTOR)lpPFInfo->abSecurityDescriptor;
  852. dwSecDescSize = dwInputSize;
  853. break;
  854. }
  855. // Had some sort of error on the attempt to get the security
  856. // descriptor.
  857. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  858. {
  859. // Need a bigger buffer for the descriptor.
  860. IF_DEBUG(OPLOCKS) {
  861. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile() - Realloc Security Desc !!!\n" ));
  862. }
  863. FREE( lpPFInfo->abSecurityDescriptor );
  864. lpPFInfo->abSecurityDescriptor = (PSECURITY_DESCRIPTOR)ALLOC( dwSecDescSize );
  865. if ( lpPFInfo->abSecurityDescriptor == NULL )
  866. {
  867. CloseHandle( hFile );
  868. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  869. TsRemovePhysFile(lpPFInfo);
  870. if ( fImpersonated )
  871. {
  872. ::RevertToSelf();
  873. }
  874. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  875. return NULL;
  876. }
  877. dwInputSize = dwSecDescSize;
  878. } else
  879. {
  880. // This wasn't too small a buffer, so quit trying.
  881. dwSecDescSize = 0;
  882. break;
  883. }
  884. }
  885. }
  886. }
  887. }
  888. IF_DEBUG(OPLOCKS) {
  889. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - SECURITY_DESC_DEFAULT_SIZE = %08lx, dwSecDescSize = %08lx\n",
  890. pszName, SECURITY_DESC_DEFAULT_SIZE, dwSecDescSize ));
  891. }
  892. if ( hFile == INVALID_HANDLE_VALUE )
  893. {
  894. DBGPRINTF((DBG_CONTEXT,"CreateFile[%s] failed with %d\n",
  895. pszName, GetLastError()));
  896. if ( fImpersonated ) {
  897. ::RevertToSelf();
  898. fImpersonated = FALSE;
  899. }
  900. if ( !fPhysFileCacheHit ) {
  901. lpPFInfo->dwLastError = GetLastError();
  902. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  903. }
  904. ASSERT( !fImpersonated );
  905. err = lpPFInfo->dwLastError;
  906. TsRemovePhysFile(lpPFInfo);
  907. SetLastError( err );
  908. return( NULL );
  909. }
  910. if ( !fDontUseSpud ) {
  911. if ( GetLastError() != ERROR_SUCCESS || fPhysFileCacheHit ) {
  912. fOplockSucceeded = FALSE;
  913. }
  914. if ( fPhysFileCacheHit || (dwSecDescSize == SECURITY_DESC_DEFAULT_SIZE ) ) {
  915. fObjectSecurityPresent = TRUE;
  916. lpPFInfo->fSecurityDescriptor = TRUE ;
  917. } else {
  918. if ( dwSecDescSize > SECURITY_DESC_DEFAULT_SIZE ) {
  919. fDoReadObjectSecurity = TRUE;
  920. dwSecDescSize = ( (dwSecDescSize + SECURITY_DESC_GRANULARITY - 1)
  921. / SECURITY_DESC_GRANULARITY )
  922. * SECURITY_DESC_GRANULARITY;
  923. } else {
  924. dwSecDescSize = 0;
  925. }
  926. }
  927. }
  928. //
  929. // Increment the miss count after we've confirmed it's a valid resource
  930. //
  931. bSuccess = TsAllocateEx( TSvcCache,
  932. sizeof( TS_OPEN_FILE_INFO ),
  933. &pvBlob,
  934. DisposeOpenFileInfo );
  935. if ( !bSuccess )
  936. {
  937. if ( fImpersonated ) {
  938. ::RevertToSelf();
  939. fImpersonated = FALSE;
  940. }
  941. if ( !fPhysFileCacheHit ) {
  942. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  943. }
  944. ASSERT( !fImpersonated );
  945. TsRemovePhysFile(lpPFInfo);
  946. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  947. return( NULL );
  948. }
  949. lpOpenFile = (LPTS_OPEN_FILE_INFO)pvBlob;
  950. if ( !fPhysFileCacheHit )
  951. {
  952. lpPFInfo->hOpenFile = hFile;
  953. if (BLOB_IS_OR_WAS_CACHED( lpPFInfo ))
  954. {
  955. INC_COUNTER( TSvcCache.GetServiceId(), CurrentOpenFileHandles );
  956. }
  957. }
  958. #if 0
  959. if ( !fDontUseSpud && !fPhysFileCacheHit ) {
  960. if ( fOplockSucceeded ) {
  961. lpOplock->lpPFInfo = lpPFInfo;
  962. SetEvent( lpOplock->hOplockInitComplete );
  963. } else {
  964. dwOptions &= ~TS_CACHING_DESIRED;
  965. }
  966. }
  967. #endif //!oplock
  968. //
  969. // The file must be fully qualified so it must be at least three characters
  970. // plus the terminator
  971. //
  972. fAtRoot = (pszName[1] == ':' &&
  973. ((pszName[2] == '\\' && pszName[3] == '\0')
  974. || (pszName[2] == '\0')) );
  975. bSuccess = lpOpenFile->SetFileInfo( lpPFInfo,
  976. (dwOptions & TS_DONT_CACHE_ACCESS_TOKEN) ? NULL : OpeningUser,
  977. fAtRoot,
  978. dwSecDescSize );
  979. if (!fDontUseSpud)
  980. InsertHeadPhysFile( lpPFInfo, pvBlob );
  981. if ( fImpersonated ) {
  982. ::RevertToSelf();
  983. fImpersonated = FALSE;
  984. }
  985. //
  986. // Check if security descriptor to be read.
  987. // Failure to read it will not make TsCreateFile to fail :
  988. // security descriptor size may have grown since previous call
  989. //
  990. if ( fDoReadObjectSecurity )
  991. {
  992. FREE( abSecDesc );
  993. abSecDesc = (PSECURITY_DESCRIPTOR)ALLOC( dwSecDescSize );
  994. lpPFInfo->abSecurityDescriptor = abSecDesc;
  995. bSuccess = lpOpenFile->SetFileInfo( lpPFInfo,
  996. (dwOptions & TS_DONT_CACHE_ACCESS_TOKEN) ? NULL : OpeningUser,
  997. fAtRoot,
  998. dwSecDescSize );
  999. if ( GetKernelObjectSecurity(
  1000. hFile,
  1001. si,
  1002. lpOpenFile->GetSecurityDescriptor(),
  1003. dwSecDescSize,
  1004. &dwReadN ) )
  1005. {
  1006. sec_succ:
  1007. lpOpenFile->SetSecurityDescriptorValid( TRUE );
  1008. }
  1009. else
  1010. {
  1011. ASSERT( GetLastError() != 0 );
  1012. }
  1013. }
  1014. else if ( fObjectSecurityPresent )
  1015. {
  1016. goto sec_succ;
  1017. }
  1018. if ( !bSuccess)
  1019. {
  1020. //
  1021. // Error in setting up the file information.
  1022. //
  1023. if ( !fPhysFileCacheHit ) {
  1024. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1025. #if 0
  1026. if ( !fDontUseSpud && fOplockSucceeded ) {
  1027. SetEvent( lpOplock->hOplockInitComplete );
  1028. }
  1029. #endif //oplock
  1030. }
  1031. ASSERT( !fImpersonated );
  1032. err = lpPFInfo->dwLastError;
  1033. TsRemovePhysFile(lpPFInfo);
  1034. SetLastError( err );
  1035. return ( NULL);
  1036. }
  1037. //
  1038. // If this is a UNC connection check and make sure we haven't exceeded
  1039. // the maximum UNC handles we will cache (SMB FID limits count to 2048)
  1040. //
  1041. if ( !g_fDisableCaching &&
  1042. (dwOptions & TS_CACHING_DESIRED ) &&
  1043. (cCachedUNCHandles < MAX_CACHED_UNC_HANDLES ||
  1044. pszName[1] != '\\') )
  1045. {
  1046. bSuccess = TsCacheDirectoryBlob( TSvcCache,
  1047. pszName,
  1048. RESERVED_DEMUX_OPEN_FILE,
  1049. pvBlob,
  1050. TRUE );
  1051. //
  1052. // Only count it if we successfully added the item to the
  1053. // cache
  1054. //
  1055. if ( bSuccess )
  1056. {
  1057. if ( pszName[1] == '\\' )
  1058. {
  1059. InterlockedIncrement( (LONG *) &cCachedUNCHandles );
  1060. }
  1061. }
  1062. }
  1063. else
  1064. {
  1065. //
  1066. // Too many cached UNC handles, don't cache it. It would be nice
  1067. // to do an LRU for these handles but it's probably not generally
  1068. // worth it
  1069. //
  1070. bSuccess = FALSE;
  1071. }
  1072. #if DBG
  1073. if ( !bSuccess )
  1074. {
  1075. ASSERT( !BLOB_IS_OR_WAS_CACHED( pvBlob ) );
  1076. }
  1077. else
  1078. {
  1079. ASSERT( BLOB_IS_OR_WAS_CACHED( pvBlob ) );
  1080. }
  1081. #endif
  1082. if ( !fPhysFileCacheHit ) {
  1083. IF_DEBUG(OPLOCKS) {
  1084. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - Not in cache, Open Complete Causing Event!\n", pszName ));
  1085. }
  1086. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1087. #if 0
  1088. if ( !fDontUseSpud && fOplockSucceeded ) {
  1089. SetEvent( lpOplock->hOplockInitComplete );
  1090. }
  1091. #endif //!oplock
  1092. } else {
  1093. IF_DEBUG(OPLOCKS) {
  1094. DBGPRINTF( (DBG_CONTEXT,"TsCreateFile(%s) - Already in cache, Open Complete!\n", pszName ));
  1095. }
  1096. }
  1097. ASSERT( !fImpersonated );
  1098. TSUNAMI_TRACE( TRACE_OPENFILE_CREATE, lpOpenFile );
  1099. return( lpOpenFile );
  1100. } // TsCreateFile
  1101. dllexp
  1102. LPTS_OPEN_FILE_INFO
  1103. TsCreateFileFromURI(
  1104. IN const TSVC_CACHE &TSvcCache,
  1105. IN PW3_URI_INFO pURIInfo,
  1106. IN HANDLE OpeningUser,
  1107. IN DWORD dwOptions,
  1108. IN DWORD *dwError
  1109. )
  1110. /*+++
  1111. TsCreateFileFromURI
  1112. This routine takes a (checked out) URI block and retrieves a file
  1113. handle from it. If the file handle in the URI info block is valid and
  1114. we have the right security for it, we'll use that. Otherwise if it's
  1115. invalid we'll create a valid handle and save it. If it's valid but we
  1116. don't have security for it we'll open a new handle but not cache it.
  1117. Not caching a new handle may become a performance problem in the future
  1118. if authenticated file access becomes common. There are several possible
  1119. solutions to this problem if this occurs. One would be to have a list
  1120. of cached TS_OPEN_FILE_INFO class structures chained off the URI block,
  1121. one for each 'distinct' security class, and then select the best one to
  1122. return. Another would be to have a second level of cache, i.e. put the
  1123. URI blocks in a second hash table and keep one OPEN_FILE_INFO in the
  1124. URI block, looking up other in the other hash table if we need to. Any
  1125. solution would have to exhibit the property of being able to handle
  1126. mapping from a single URI to multiple file handles.
  1127. Arguments:
  1128. TsvcCache -
  1129. pURIInfo - A pointer to the URI block from which we're to derive
  1130. file information.
  1131. OpeningUser - A handle identifying the opening used.
  1132. dwOptions - A set of options indicating how we're to open the file.
  1133. Returns:
  1134. A pointer to a TS_OPEN_FILE_INFO class structure if we're succesfull,
  1135. or NULL if we're not.
  1136. ---*/
  1137. {
  1138. HANDLE hFile = INVALID_HANDLE_VALUE;
  1139. LPTS_OPEN_FILE_INFO lpOpenFile;
  1140. POPLOCK_OBJECT lpOplock;
  1141. BOOL fAtRoot;
  1142. BOOL bSuccess;
  1143. PVOID pvBlob;
  1144. PPHYS_OPEN_FILE_INFO lpPFInfo;
  1145. BOOL fImpersonated = FALSE;
  1146. BOOL SPUDdidCall = FALSE;
  1147. DWORD dwSecDescSize;
  1148. BOOL fOplockSucceeded = FALSE;
  1149. SECURITY_INFORMATION si
  1150. = OWNER_SECURITY_INFORMATION
  1151. | GROUP_SECURITY_INFORMATION
  1152. | DACL_SECURITY_INFORMATION;
  1153. SECURITY_ATTRIBUTES sa;
  1154. BOOL fPhysFileCacheHit = FALSE;
  1155. BOOL fNoCanon = (dwOptions & TS_USE_WIN32_CANON) == 0;
  1156. BOOL fAccess;
  1157. DWORD dwGrantedAccess;
  1158. DWORD dwPS;
  1159. DWORD cch;
  1160. DWORD cbPrefix;
  1161. LPCSTR pszPath;
  1162. PCHAR pName;
  1163. DWORD dwInputSize;
  1164. WCHAR awchPath[MAX_PATH+8+1];
  1165. BYTE psFile[SIZE_PRIVILEGE_SET];
  1166. AcIncrement( CacOpenURI);
  1167. ASSERT(pURIInfo != NULL);
  1168. //
  1169. // Mask out options that are not applicable
  1170. //
  1171. dwOptions &= TsValidCreateFileOptions;
  1172. if ( TsIsWindows95() ) {
  1173. dwOptions |= (TS_NO_ACCESS_CHECK | TS_DONT_CACHE_ACCESS_TOKEN);
  1174. }
  1175. *dwError = pURIInfo->dwFileOpenError;
  1176. // Check to see if the open file info is valid. If it it, try to use it.
  1177. if ( pURIInfo->bFileInfoValid )
  1178. {
  1179. // Get the open file info. If it's non-NULL (the file exists)
  1180. // see if we have permission to access it.
  1181. lpOpenFile = pURIInfo->pOpenFileInfo;
  1182. //
  1183. // Make sure the user tokens match, or that lpOpenFile is NULL.
  1184. // In the latter case the file doesn't exist - this is a negative
  1185. // hit.
  1186. //
  1187. if ( ( lpOpenFile == NULL ) ||
  1188. (OpeningUser == lpOpenFile->QueryOpeningUser()
  1189. && lpOpenFile->QueryOpeningUser() != NULL)
  1190. || (dwOptions & TS_NO_ACCESS_CHECK) )
  1191. {
  1192. return( lpOpenFile);
  1193. }
  1194. //
  1195. // User token doesn't match
  1196. //
  1197. if ( g_fCacheSecDesc )
  1198. {
  1199. //
  1200. // attempt to validate access using cached
  1201. // security descriptor
  1202. //
  1203. if ( lpOpenFile->IsSecurityDescriptorValid() )
  1204. {
  1205. dwPS = sizeof( psFile );
  1206. ((PRIVILEGE_SET*)&psFile)->PrivilegeCount = 0;
  1207. if ( !AccessCheck(
  1208. lpOpenFile->GetSecurityDescriptor(),
  1209. OpeningUser,
  1210. FILE_GENERIC_READ,
  1211. &g_gmFile,
  1212. (PRIVILEGE_SET*)psFile,
  1213. &dwPS,
  1214. &dwGrantedAccess,
  1215. &fAccess ) )
  1216. {
  1217. DBGPRINTF(( DBG_CONTEXT,
  1218. "[TsCreateFileFromURI]: AccessCheck failed, \
  1219. error %d\n",
  1220. GetLastError() ));
  1221. fAccess = FALSE;
  1222. }
  1223. // See if we have access to the file. If we get here we know
  1224. // we have a valid security descriptor, so if we didn't get
  1225. // access on this check then there's no point in attemptint to
  1226. // open the file.
  1227. if ( fAccess )
  1228. {
  1229. return( lpOpenFile );
  1230. }
  1231. else
  1232. {
  1233. *dwError = GetLastError();
  1234. return NULL;
  1235. }
  1236. }
  1237. }
  1238. }
  1239. // At this point, either the file info in the structure isn't
  1240. // valid, or we're not allowed to cache security descriptors, or
  1241. // the cache descriptor isn't valid. In any of these cases we need
  1242. // to try to open the file. If this succeeds and the file info in the
  1243. // URI block isn't valid, save the newly opened file info there.
  1244. //
  1245. // If we open the file but the file info isn't valid, we'll tag the
  1246. // open file info structure as non cached so that we won't try to
  1247. // check it in later.
  1248. //
  1249. // Since the file info isn't valid, the error we set in *dwError
  1250. // is bad also. All exits from this point on need to make sure to
  1251. // set that to the proper value. We also want to update the cached
  1252. // error in the URI info if we're going to make the file info valid.
  1253. //
  1254. //
  1255. // Now try to open the actual file.
  1256. //
  1257. if ( TsIsWindows95() )
  1258. {
  1259. fNoCanon = FALSE;
  1260. }
  1261. sa.nLength = sizeof(sa);
  1262. sa.lpSecurityDescriptor = NULL;
  1263. sa.bInheritHandle = FALSE;
  1264. IF_DEBUG(OPLOCKS) {
  1265. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - Calling TsCheckOutCachedPhysFile\n", pURIInfo->pszName ));
  1266. }
  1267. fPhysFileCacheHit = TsCheckOutCachedPhysFile( TSvcCache,
  1268. pURIInfo->pszName,
  1269. (VOID **)&lpPFInfo );
  1270. while (fPhysFileCacheHit)
  1271. {
  1272. DWORD dwLastError;
  1273. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  1274. WAIT_FOR_PHYS_INIT_COMPLETE( lpPFInfo );
  1275. hFile = lpPFInfo->hOpenFile;
  1276. if (hFile != INVALID_HANDLE_VALUE)
  1277. {
  1278. break;
  1279. }
  1280. dwLastError = lpPFInfo->dwLastError;
  1281. if (dwLastError != ERROR_FILE_NOT_FOUND &&
  1282. dwLastError != ERROR_PATH_NOT_FOUND &&
  1283. dwLastError != ERROR_INVALID_NAME )
  1284. {
  1285. fPhysFileCacheHit = TsReInitPhysFile(lpPFInfo);
  1286. }
  1287. else
  1288. {
  1289. TsRemovePhysFile(lpPFInfo);
  1290. SetLastError(dwLastError);
  1291. *dwError = dwLastError;
  1292. return NULL;
  1293. }
  1294. }
  1295. if ( fPhysFileCacheHit )
  1296. {
  1297. dwSecDescSize = lpPFInfo->cbSecDescMaxSize;
  1298. DBG_ASSERT(hFile != INVALID_HANDLE_VALUE);
  1299. //
  1300. // We've got a file handle from the cache. If we're doing access
  1301. // checking make sure we can use it.
  1302. //
  1303. if (!(dwOptions & TS_NO_ACCESS_CHECK))
  1304. {
  1305. if ( !TsAccessCheck(lpPFInfo, OpeningUser) )
  1306. {
  1307. // Don't have permission to use this handle, so fail.
  1308. //
  1309. TsCheckInOrFree( (PVOID)lpPFInfo );
  1310. SetLastError(ERROR_ACCESS_DENIED);
  1311. *dwError = ERROR_ACCESS_DENIED;
  1312. return NULL;
  1313. }
  1314. }
  1315. } else {
  1316. if ( lpPFInfo == NULL ) {
  1317. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  1318. *dwError = ERROR_NOT_ENOUGH_MEMORY;
  1319. return NULL;
  1320. }
  1321. ASSERT( lpPFInfo->Signature == PHYS_OBJ_SIGNATURE );
  1322. //
  1323. // If we're not impersonating right now, do that before we try to
  1324. // open the file.
  1325. //
  1326. if ( (dwOptions & TS_NOT_IMPERSONATED) &&
  1327. !(dwOptions & TS_NO_ACCESS_CHECK) )
  1328. {
  1329. if ( !::ImpersonateLoggedOnUser( OpeningUser ) )
  1330. {
  1331. *dwError = GetLastError();
  1332. DBGPRINTF(( DBG_CONTEXT,
  1333. "ImpersonateLoggedOnUser[%d] failed with %d\n",
  1334. OpeningUser, *dwError));
  1335. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1336. TsRemovePhysFile(lpPFInfo);
  1337. return NULL;
  1338. }
  1339. fImpersonated = TRUE;
  1340. }
  1341. IF_DEBUG(OPLOCKS) {
  1342. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - Not in Cache, Opening!\n", pURIInfo->pszName ));
  1343. }
  1344. dwSecDescSize = lpPFInfo->cbSecDescMaxSize;
  1345. IF_DEBUG(OPLOCKS) {
  1346. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - lpPFInfo->abSecurityDescriptor = %08lx, size = %08lx\n", pURIInfo->pszName, lpPFInfo->abSecurityDescriptor, SECURITY_DESC_DEFAULT_SIZE ));
  1347. }
  1348. if ( lpPFInfo->abSecurityDescriptor == NULL ) {
  1349. goto not_enough_memory;
  1350. }
  1351. if ( fNoCanon )
  1352. {
  1353. if ( (pURIInfo->pszName[0] == '\\') && (pURIInfo->pszName[1] == '\\') )
  1354. {
  1355. CopyMemory(
  1356. awchPath,
  1357. L"\\\\?\\UNC\\",
  1358. (sizeof("\\\\?\\UNC\\")-1) * sizeof(WCHAR)
  1359. );
  1360. cbPrefix = sizeof("\\\\?\\UNC\\")-1;
  1361. pszPath = pURIInfo->pszName + sizeof( "\\\\" ) -1;
  1362. }
  1363. else
  1364. {
  1365. CopyMemory(
  1366. awchPath,
  1367. L"\\\\?\\",
  1368. (sizeof("\\\\?\\")-1) * sizeof(WCHAR)
  1369. );
  1370. cbPrefix = sizeof("\\\\?\\")-1;
  1371. pszPath = pURIInfo->pszName;
  1372. }
  1373. cch = MultiByteToWideChar( CP_ACP,
  1374. MB_PRECOMPOSED,
  1375. pszPath,
  1376. -1,
  1377. awchPath + cbPrefix,
  1378. sizeof(awchPath)/sizeof(WCHAR) - cbPrefix );
  1379. if ( !cch )
  1380. {
  1381. hFile = INVALID_HANDLE_VALUE;
  1382. }
  1383. else
  1384. {
  1385. if ( (pURIInfo->pszName[1] == ':') && (pURIInfo->pszName[2] == '\0') )
  1386. {
  1387. wcscat( awchPath, L"\\" );
  1388. }
  1389. sa.nLength = sizeof(sa);
  1390. sa.lpSecurityDescriptor = NULL;
  1391. sa.bInheritHandle = FALSE;
  1392. #if 1
  1393. //if ( DisableSPUD ) {
  1394. hFile = CreateFileW( awchPath,
  1395. GENERIC_READ,
  1396. TsCreateFileShareMode,
  1397. &sa,
  1398. OPEN_EXISTING,
  1399. TsCreateFileFlags,
  1400. NULL );
  1401. #else
  1402. } else {
  1403. if ( g_fCacheSecDesc &&
  1404. !(dwOptions & TS_NO_ACCESS_CHECK) )
  1405. {
  1406. // Assume we can get by with the default size, and just allocate
  1407. // that.
  1408. lpOpenFile = ( LPTS_OPEN_FILE_INFO )LocalAlloc(LPTR,
  1409. sizeof(TS_OPEN_FILE_INFO));
  1410. IF_DEBUG(OPLOCKS) {
  1411. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - lpOpenFile = %08lx\n", pURIInfo->pszName, lpOpenFile ));
  1412. }
  1413. if (lpOpenFile == NULL)
  1414. {
  1415. // Couldn't get the memory we needed, so fail.
  1416. goto not_enough_memory;
  1417. }
  1418. lpOpenFile->SetFileInfo( lpPFInfo,
  1419. (dwOptions & TS_DONT_CACHE_ACCESS_TOKEN) ? NULL : OpeningUser,
  1420. FALSE,
  1421. dwSecDescSize );
  1422. }
  1423. SPUDdidCall = TRUE;
  1424. lpOplock = ( POPLOCK_OBJECT )LocalAlloc(LPTR, sizeof(OPLOCK_OBJECT));
  1425. if ( lpOplock == NULL ) {
  1426. LocalFree( lpOpenFile );
  1427. goto not_enough_memory;
  1428. }
  1429. lpOplock->Signature = OPLOCK_OBJ_SIGNATURE;
  1430. lpOplock->lpPFInfo = NULL;
  1431. lpOplock->hOplockInitComplete = IIS_CREATE_EVENT(
  1432. "OPLOCK_OBJECT::hOplockInitComplete",
  1433. lpOplock,
  1434. TRUE,
  1435. FALSE
  1436. );
  1437. hFile = AtqCreateFileW( awchPath,
  1438. TsCreateFileShareMode,
  1439. &sa,
  1440. TsCreateFileFlags,
  1441. si,
  1442. (PSECURITY_DESCRIPTOR)lpOpenFile->GetSecurityDescriptor(),
  1443. ( ( g_fCacheSecDesc
  1444. && !(dwOptions & TS_NO_ACCESS_CHECK)) ?
  1445. SECURITY_DESC_DEFAULT_SIZE : 0 ),
  1446. &dwSecDescSize,
  1447. OplockCreateFile,
  1448. (PVOID)lpOplock );
  1449. }
  1450. #endif //!oplock
  1451. }
  1452. }
  1453. else
  1454. {
  1455. hFile = CreateFile( pURIInfo->pszName,
  1456. GENERIC_READ,
  1457. TsCreateFileShareMode,
  1458. &sa,
  1459. OPEN_EXISTING,
  1460. TsCreateFileFlags,
  1461. NULL );
  1462. }
  1463. //
  1464. // If we're supposed to cache the security descriptor, do so now.
  1465. // This should only be done once, by the thread intializing the physical
  1466. // file entry.
  1467. //
  1468. if (DisableSPUD && hFile != INVALID_HANDLE_VALUE)
  1469. {
  1470. if ( g_fCacheSecDesc )
  1471. {
  1472. dwInputSize = dwSecDescSize;
  1473. // Loop, reading the security info each time, until we either
  1474. // read it succesfully, are unable to allocate a big enough buffer,
  1475. // or get some error other than buffer too smal.
  1476. for (;;)
  1477. {
  1478. if ( GetKernelObjectSecurity(
  1479. hFile,
  1480. si,
  1481. (PSECURITY_DESCRIPTOR)lpPFInfo->abSecurityDescriptor,
  1482. dwInputSize,
  1483. &dwSecDescSize ) )
  1484. {
  1485. lpPFInfo->fSecurityDescriptor = TRUE ;
  1486. dwSecDescSize = dwInputSize;
  1487. break;
  1488. }
  1489. // Had some sort of error on the attempt to get the security
  1490. // descriptor.
  1491. if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  1492. {
  1493. // Need a bigger buffer for the descriptor.
  1494. IF_DEBUG(OPLOCKS) {
  1495. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - Realloc Security Desc !!!\n", pURIInfo->pszName ));
  1496. }
  1497. FREE( lpPFInfo->abSecurityDescriptor );
  1498. lpPFInfo->abSecurityDescriptor = (PSECURITY_DESCRIPTOR)ALLOC( dwSecDescSize );
  1499. if ( lpPFInfo->abSecurityDescriptor == NULL )
  1500. {
  1501. CloseHandle( hFile );
  1502. goto not_enough_memory;
  1503. }
  1504. dwInputSize = dwSecDescSize;
  1505. } else
  1506. {
  1507. // This wasn't too small a buffer, so quit trying.
  1508. dwSecDescSize = 0;
  1509. break;
  1510. }
  1511. }
  1512. }
  1513. }
  1514. }
  1515. if ( hFile != INVALID_HANDLE_VALUE )
  1516. {
  1517. AcIncrement( AacOpenURIFiles);
  1518. if ( !fPhysFileCacheHit ) {
  1519. lpPFInfo->hOpenFile = hFile;
  1520. if (BLOB_IS_OR_WAS_CACHED( lpPFInfo ))
  1521. {
  1522. INC_COUNTER( TSvcCache.GetServiceId(), CurrentOpenFileHandles );
  1523. }
  1524. }
  1525. //
  1526. // If we're supposed to cache the security descriptor we'll do that
  1527. // now. In order to do this we need to allocate the OPEN_FILE_INFO
  1528. // structure that we'll use.
  1529. //
  1530. #if 1 // Oplocks are always disabled
  1531. //if ( DisableSPUD ) {
  1532. lpOpenFile = ( LPTS_OPEN_FILE_INFO )LocalAlloc(LPTR,
  1533. sizeof(TS_OPEN_FILE_INFO));
  1534. if (lpOpenFile == NULL)
  1535. {
  1536. // Couldn't get the memory we needed, so fail.
  1537. goto not_enough_memory;
  1538. }
  1539. #else
  1540. } else {
  1541. if ( !fPhysFileCacheHit ) {
  1542. if ( GetLastError() == ERROR_SUCCESS ) {
  1543. fOplockSucceeded = TRUE;
  1544. }
  1545. if ( g_fCacheSecDesc &&
  1546. !(dwOptions & TS_NO_ACCESS_CHECK) )
  1547. {
  1548. dwInputSize = dwSecDescSize;
  1549. if (dwSecDescSize > SECURITY_DESC_DEFAULT_SIZE ) {
  1550. PSECURITY_DESCRIPTOR TmpSd;
  1551. TmpSd = lpOpenFile->GetSecurityDescriptor();
  1552. FREE( TmpSd );
  1553. TmpSd = (PSECURITY_DESCRIPTOR)ALLOC( dwSecDescSize );
  1554. lpPFInfo->abSecurityDescriptor = TmpSd;
  1555. if ( TmpSd == NULL )
  1556. {
  1557. LocalFree( lpOpenFile );
  1558. goto not_enough_memory;
  1559. }
  1560. lpOpenFile->SetFileInfo( lpPFInfo,
  1561. (dwOptions & TS_DONT_CACHE_ACCESS_TOKEN) ? NULL : OpeningUser,
  1562. FALSE,
  1563. dwSecDescSize );
  1564. // Now loop, reading the security info each time, until we either
  1565. // read it succesfully, are unable to allocate a big enough buffer,
  1566. // or get some error other than buffer too smal.
  1567. if ( !GetKernelObjectSecurity(
  1568. hFile,
  1569. si,
  1570. (PSECURITY_DESCRIPTOR)lpOpenFile->GetSecurityDescriptor(),
  1571. dwInputSize,
  1572. &dwSecDescSize ) )
  1573. {
  1574. // Had some sort of error on the attempt to get the security
  1575. // descriptor.
  1576. // This wasn't too small a buffer, so quit trying.
  1577. dwSecDescSize = 0;
  1578. }
  1579. lpPFInfo->fSecurityDescriptor = TRUE ;
  1580. } else {
  1581. lpPFInfo->fSecurityDescriptor = TRUE ;
  1582. }
  1583. } else {
  1584. lpOpenFile = ( LPTS_OPEN_FILE_INFO )LocalAlloc(LPTR,
  1585. sizeof(TS_OPEN_FILE_INFO));
  1586. IF_DEBUG(OPLOCKS) {
  1587. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - lpOpenFile = %08lx\n", pURIInfo->pszName, lpOpenFile ));
  1588. }
  1589. if (lpOpenFile == NULL)
  1590. {
  1591. // Couldn't get the memory we needed, so fail.
  1592. goto not_enough_memory;
  1593. }
  1594. }
  1595. } else {
  1596. lpOpenFile = ( LPTS_OPEN_FILE_INFO )LocalAlloc(LPTR,
  1597. sizeof(TS_OPEN_FILE_INFO));
  1598. IF_DEBUG(OPLOCKS) {
  1599. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - lpOpenFile = %08lx\n", pURIInfo->pszName, lpOpenFile ));
  1600. }
  1601. if (lpOpenFile == NULL)
  1602. {
  1603. // Couldn't get the memory we needed, so fail.
  1604. goto not_enough_memory;
  1605. }
  1606. }
  1607. }
  1608. #endif //!oplock
  1609. *dwError = ERROR_SUCCESS;
  1610. lpOpenFile->SetCachedFlag(TRUE);
  1611. //
  1612. // The file must be fully qualified so it must be at least three
  1613. // characters plus the terminator
  1614. //
  1615. pName = pURIInfo->pszName;
  1616. fAtRoot = (pName[1] == ':' &&
  1617. ((pName[2] == '\\' && pName[3] == '\0')
  1618. || (pName[2] == '\0')) );
  1619. bSuccess = lpOpenFile->SetFileInfo( lpPFInfo,
  1620. (dwOptions & TS_DONT_CACHE_ACCESS_TOKEN) ? NULL : OpeningUser,
  1621. fAtRoot,
  1622. dwSecDescSize );
  1623. if ( !bSuccess )
  1624. {
  1625. if ( fImpersonated ) {
  1626. ::RevertToSelf();
  1627. fImpersonated = FALSE;
  1628. }
  1629. AcDecrement( AacOpenURIFiles);
  1630. LocalFree(lpOpenFile);
  1631. *dwError = GetLastError();
  1632. if ( !fPhysFileCacheHit ) {
  1633. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1634. #if 0 //!oplock
  1635. if ( !DisableSPUD && fOplockSucceeded ) {
  1636. SetEvent( lpOplock->hOplockInitComplete );
  1637. }
  1638. #endif
  1639. }
  1640. ASSERT( !fImpersonated );
  1641. TsRemovePhysFile(lpPFInfo);
  1642. return NULL;
  1643. }
  1644. }
  1645. else
  1646. {
  1647. if ( !fPhysFileCacheHit ) {
  1648. lpPFInfo->dwLastError = GetLastError();
  1649. } else {
  1650. SetLastError(lpPFInfo->dwLastError);
  1651. }
  1652. IF_DEBUG(ERROR) {
  1653. DBGPRINTF((DBG_CONTEXT,"Create file[%s] failed with %d\n",
  1654. pURIInfo->pszName, GetLastError()));
  1655. }
  1656. //
  1657. // Couldn't open the file! If the reason we failed was because
  1658. // the file or path didn't exist, cache this information.
  1659. //
  1660. *dwError = GetLastError();
  1661. //
  1662. // if this is win95 (does not support dir opens),
  1663. // do the right thing.
  1664. //
  1665. if ( TsNoDirOpenSupport ) {
  1666. DBG_ASSERT(TsIsWindows95());
  1667. goto no_dir_open_support;
  1668. }
  1669. if ( fImpersonated ) {
  1670. ::RevertToSelf();
  1671. fImpersonated = FALSE;
  1672. }
  1673. if (*dwError != ERROR_FILE_NOT_FOUND &&
  1674. *dwError != ERROR_PATH_NOT_FOUND &&
  1675. *dwError != ERROR_INVALID_NAME )
  1676. {
  1677. // Not a 'not found error'. We don't cache those.
  1678. lpPFInfo->hOpenFile = INVALID_HANDLE_VALUE;
  1679. if ( !fPhysFileCacheHit ) {
  1680. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1681. #if 0
  1682. if ( !DisableSPUD && fOplockSucceeded ) {
  1683. SetEvent( lpOplock->hOplockInitComplete );
  1684. }
  1685. #endif //!oplock
  1686. }
  1687. ASSERT( !fImpersonated );
  1688. TsRemovePhysFile(lpPFInfo);
  1689. return( NULL );
  1690. }
  1691. // Go ahead and set the file info structure to valid, or try to. We
  1692. // use compare and exchange to handle the race condition where the
  1693. // file is open by someone else, and has been deleted while the handle
  1694. // is still open. but we couldn't use the cached values because of
  1695. // lack of a security descriptor. In this case we could get file not
  1696. // found when the file info in the cached URI block is valid for
  1697. // someone else. We don't want to blindly stomp the information in
  1698. // that case. Note that since the cached pOpenFileInfo field is
  1699. // initialized to NULL, all we need to do is set bFileInfoValid to
  1700. // TRUE.
  1701. if (!pfnInterlockedCompareExchange( (PVOID *)&pURIInfo->bFileInfoValid,
  1702. (PVOID)TRUE,
  1703. FALSE) )
  1704. {
  1705. // The compare&exchange worked, so we now officially have
  1706. // a negatively cached file. Go ahead and save the error
  1707. // value in the URI info.
  1708. pURIInfo->dwFileOpenError = *dwError;
  1709. }
  1710. if ( !fPhysFileCacheHit ) {
  1711. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1712. #if 0
  1713. if ( !DisableSPUD && fOplockSucceeded ) {
  1714. SetEvent( lpOplock->hOplockInitComplete );
  1715. }
  1716. #endif //!oplock
  1717. }
  1718. TsRemovePhysFile( lpPFInfo );
  1719. ASSERT( !fImpersonated );
  1720. lpOpenFile = NULL;
  1721. return lpOpenFile;
  1722. }
  1723. // We're all done with file operations now, so revert back to who we were.
  1724. if ( fImpersonated ) {
  1725. ::RevertToSelf();
  1726. fImpersonated = FALSE;
  1727. }
  1728. // OK, at this point we have an LP_OPEN_FILE info, or the file doesn't
  1729. // exist. If the file info in the URI block isn't valid, save this now.
  1730. if ( !pURIInfo->bFileInfoValid )
  1731. {
  1732. PVOID Temp;
  1733. // Now that we've opened the file, set the information to valid.
  1734. Temp = pfnInterlockedCompareExchange( (PVOID *)&pURIInfo->pOpenFileInfo,
  1735. lpOpenFile,
  1736. NULL
  1737. );
  1738. if ( Temp == NULL )
  1739. {
  1740. // The exchange worked. A few notes are in order: if we're
  1741. // caching a negative hit, we wouldn't have come through
  1742. // this path, we'd have gone through the code above where
  1743. // we do a compate&exchange on bFileInfoValid. There is a
  1744. // race between that code and this - if one thread opens the
  1745. // file, the file is deleted, and another thread fails to
  1746. // open the file we have a race. In that race this code path
  1747. // always wins. Either we get here first and set bFileInfoValid
  1748. // to TRUE so the negative hit cache c&e fails, or the negative
  1749. // c&e succeeds in setting it to TRUE, and then we set the
  1750. // file info pointer to a valid file and set bFileInfo to TRUE
  1751. // also. In either case we end up with bFileInfo at TRUE and
  1752. // a valid pOpenFileInfo pointer. It is possible in this case
  1753. // that the cached file open error will be incorrect, but that's
  1754. // OK because this is valid only when the return from this
  1755. // function is NULL. In any case, this is a transitory state. A
  1756. // change notify should fire shortly after this race and clean
  1757. // all of this mess up.
  1758. pURIInfo->bFileInfoValid = TRUE;
  1759. pURIInfo->dwFileOpenError = ERROR_SUCCESS; // For debugging purposes.
  1760. if ( lpOpenFile != NULL )
  1761. {
  1762. TsIncreaseFileHandleCount( FALSE );
  1763. }
  1764. }
  1765. else
  1766. {
  1767. // The exchange didn't work, which means someone else snuck
  1768. // in and set it to valid while we were doing this. In this
  1769. // case mark our file info as not cached.
  1770. ASSERT(pURIInfo->bFileInfoValid);
  1771. if (lpOpenFile != NULL)
  1772. {
  1773. lpOpenFile->SetCachedFlag(FALSE);
  1774. *dwError = ERROR_SUCCESS;
  1775. }
  1776. }
  1777. }
  1778. else
  1779. {
  1780. // The cached file info is already valid. This could be because of a
  1781. // race and someone else got here first, or it could be because we
  1782. // had a valid cached file before but the security tokens don't match.
  1783. // Either way, mark the open file info as not cached so the handle gets
  1784. // closed when we're done.
  1785. if (lpOpenFile != NULL)
  1786. {
  1787. lpOpenFile->SetCachedFlag(FALSE);
  1788. *dwError = ERROR_SUCCESS;
  1789. }
  1790. }
  1791. #if 0
  1792. SetEvent( pURIInfo->hFileEvent );
  1793. // And now we're done.
  1794. if ( (lpOpenFile != NULL) && !DisableSPUD ) {
  1795. InsertHeadPhysFile( lpPFInfo, (PVOID)pURIInfo );
  1796. }
  1797. if ( !DisableSPUD && !fPhysFileCacheHit && fOplockSucceeded ) {
  1798. lpOplock->lpPFInfo = lpPFInfo;
  1799. SetEvent( lpOplock->hOplockInitComplete );
  1800. }
  1801. #endif //!oplock
  1802. if ( !fPhysFileCacheHit ) {
  1803. IF_DEBUG(OPLOCKS) {
  1804. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - Not in Cache, Open Complete Causing Event!\n", pURIInfo->pszName ));
  1805. }
  1806. if ( lpOpenFile != NULL ) {
  1807. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1808. }
  1809. } else {
  1810. IF_DEBUG(OPLOCKS) {
  1811. DBGPRINTF( (DBG_CONTEXT,"TsCreateFileFromURI(%s) - In Cache, Open Complete!\n", pURIInfo->pszName ));
  1812. }
  1813. }
  1814. ASSERT( !fImpersonated );
  1815. return lpOpenFile;
  1816. not_enough_memory:
  1817. if ( fImpersonated ) {
  1818. ::RevertToSelf();
  1819. fImpersonated = FALSE;
  1820. }
  1821. ASSERT( lpPFInfo != NULL );
  1822. if ( !fPhysFileCacheHit )
  1823. {
  1824. MARK_PHYS_INIT_COMPLETE( lpPFInfo );
  1825. TsRemovePhysFile(lpPFInfo);
  1826. }
  1827. else
  1828. {
  1829. TsCheckInOrFree( (PVOID)lpPFInfo );
  1830. }
  1831. ASSERT( !fImpersonated );
  1832. SetLastError( ERROR_NOT_ENOUGH_MEMORY);
  1833. *dwError = ERROR_NOT_ENOUGH_MEMORY;
  1834. return( NULL );
  1835. no_dir_open_support:
  1836. //
  1837. // This is to support win95 where opening directories are not
  1838. // allowed.
  1839. //
  1840. DWORD dwAttributes;
  1841. BOOL fDirectory = FALSE;
  1842. if ( fImpersonated ) {
  1843. ::RevertToSelf();
  1844. fImpersonated = FALSE;
  1845. }
  1846. //
  1847. // if this is not a directory, fail it.
  1848. //
  1849. dwAttributes = GetFileAttributes(pURIInfo->pszName);
  1850. if( dwAttributes != (DWORD)-1) {
  1851. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  1852. fDirectory = TRUE;
  1853. }
  1854. }
  1855. if (!fDirectory) {
  1856. IF_DEBUG(ERROR) {
  1857. DBGPRINTF((DBG_CONTEXT,"Not a directory[%x]. Fail\n",
  1858. dwAttributes ));
  1859. }
  1860. ASSERT( !fImpersonated );
  1861. return( NULL );
  1862. }
  1863. lpOpenFile = (LPTS_OPEN_FILE_INFO)LocalAlloc(LPTR,
  1864. sizeof(TS_OPEN_FILE_INFO));
  1865. if (lpOpenFile == NULL) {
  1866. //
  1867. // Couldn't get the memory we needed, so fail.
  1868. //
  1869. DBGPRINTF((DBG_CONTEXT,"Cannot allocate memory for file info[%d]\n",
  1870. GetLastError()));
  1871. goto not_enough_memory;
  1872. }
  1873. //
  1874. // set properties
  1875. //
  1876. lpPFInfo->hOpenFile = BOGUS_WIN95_DIR_HANDLE;
  1877. lpOpenFile->SetFileInfo(lpPFInfo,
  1878. NULL,
  1879. FALSE,
  1880. 0,
  1881. dwAttributes
  1882. );
  1883. ASSERT( !fImpersonated );
  1884. return lpOpenFile;
  1885. } // TsCreateFileFromURI
  1886. dllexp
  1887. BOOL
  1888. TsCloseHandle(
  1889. IN const TSVC_CACHE &TSvcCache,
  1890. IN LPTS_OPEN_FILE_INFO lpOpenFile
  1891. )
  1892. {
  1893. PVOID pvBlob;
  1894. BOOL bSuccess;
  1895. ASSERT( lpOpenFile != NULL );
  1896. TSUNAMI_TRACE( TRACE_OPENFILE_CLOSE, lpOpenFile );
  1897. pvBlob = ( PVOID )lpOpenFile;
  1898. bSuccess = TsCheckInOrFree( pvBlob );
  1899. return( bSuccess );
  1900. } // TsCloseHandle
  1901. dllexp
  1902. BOOL
  1903. TsCloseURIFile(
  1904. IN LPTS_OPEN_FILE_INFO lpOpenFile
  1905. )
  1906. {
  1907. PVOID pvBlob;
  1908. AcIncrement( CacCloseURI);
  1909. if ( lpOpenFile != NULL ) {
  1910. if ( !lpOpenFile->QueryCachedFlag() )
  1911. {
  1912. // This file isn't actually part of a URI cache block, so
  1913. // close it.
  1914. AcDecrement( AacOpenURIFiles);
  1915. if ( lpOpenFile->QueryFileHandle() != BOGUS_WIN95_DIR_HANDLE ) {
  1916. pvBlob = ( PVOID )lpOpenFile->QueryPhysFileInfo();
  1917. TsCheckInOrFree( pvBlob );
  1918. }
  1919. LocalFree( lpOpenFile);
  1920. }
  1921. }
  1922. return TRUE;
  1923. } // TsCloseURIFile
  1924. dllexp
  1925. BOOL TsCreateETagFromHandle(
  1926. IN HANDLE hFile,
  1927. IN PCHAR ETag,
  1928. IN BOOL *bWeakETag
  1929. )
  1930. /*+++
  1931. TsCreateETagFromHandle
  1932. This routine takes a file handle as input, and creates an ETag in
  1933. the supplied buffer for that file handle.
  1934. Arguments:
  1935. hFile - File handle for which to create an ETag.
  1936. ETag - Where to store the ETag. This must be long
  1937. enough to hold the maximum length ETag.
  1938. bWeakETag - Set to TRUE if the newly created ETag is weak.
  1939. Returns:
  1940. TRUE if we create an ETag, FALSE otherwise.
  1941. ---*/
  1942. {
  1943. BY_HANDLE_FILE_INFORMATION FileInfo;
  1944. BOOL bReturn;
  1945. PUCHAR Temp;
  1946. FILETIME ftNow;
  1947. SYSTEMTIME stNow;
  1948. MB mb( (IMDCOM*) IIS_SERVICE::QueryMDObject() );
  1949. DWORD dwChangeNumber;
  1950. bReturn = GetFileInformationByHandle(
  1951. hFile,
  1952. &FileInfo
  1953. );
  1954. if (!bReturn)
  1955. {
  1956. return FALSE;
  1957. }
  1958. dwChangeNumber = 0;
  1959. mb.GetSystemChangeNumber(&dwChangeNumber);
  1960. FORMAT_ETAG(ETag, FileInfo.ftLastWriteTime, dwChangeNumber );
  1961. ::GetSystemTime(&stNow);
  1962. if (::SystemTimeToFileTime((CONST SYSTEMTIME *)&stNow, &ftNow))
  1963. {
  1964. __int64 iNow, iFileTime;
  1965. iNow = (__int64)*(__int64 UNALIGNED *)&ftNow;
  1966. iFileTime = (__int64)*(__int64 UNALIGNED *)&FileInfo.ftLastWriteTime;
  1967. if ((iNow - iFileTime) > STRONG_ETAG_DELTA )
  1968. {
  1969. *bWeakETag = FALSE;
  1970. }
  1971. else
  1972. {
  1973. *bWeakETag = TRUE;
  1974. }
  1975. return TRUE;
  1976. }
  1977. return FALSE;
  1978. }
  1979. dllexp
  1980. BOOL TsLastWriteTimeFromHandle(
  1981. IN HANDLE hFile,
  1982. IN FILETIME *tm
  1983. )
  1984. /*+++
  1985. TsLastWriteTimeFromHandle
  1986. This routine takes a file handle as input, and returns the last write time
  1987. for that handle.
  1988. Arguments:
  1989. hFile - File handle for which to get the last write time.
  1990. tm - Where to return the last write time.
  1991. Returns:
  1992. TRUE if we succeed, FALSE otherwise.
  1993. ---*/
  1994. {
  1995. BY_HANDLE_FILE_INFORMATION FileInfo;
  1996. BOOL bReturn;
  1997. bReturn = GetFileInformationByHandle(
  1998. hFile,
  1999. &FileInfo
  2000. );
  2001. if (!bReturn)
  2002. {
  2003. return FALSE;
  2004. }
  2005. *tm = FileInfo.ftLastWriteTime;
  2006. return TRUE;
  2007. }
  2008. const char * g_IISAuxCounterNames[] =
  2009. {
  2010. "Aac Open URI Files",
  2011. "Cac Calls to TsOpenURI()",
  2012. "Cac Calls to TsCloseURI()",
  2013. "Max Counters"
  2014. };
  2015. extern "C"
  2016. VOID
  2017. TsDumpCacheCounters( OUT CHAR * pchBuffer, IN OUT LPDWORD lpcbBuffer )
  2018. {
  2019. DWORD cb = 0;
  2020. DBG_ASSERT( NULL != lpcbBuffer);
  2021. if ( *lpcbBuffer > 30) {
  2022. cb = wsprintf( pchBuffer, " IIS Cache Aux Counters. <p> <UL>");
  2023. } else {
  2024. cb = 30;
  2025. }
  2026. for ( DWORD i = 0; i < AacIISCacheMaxCounters; i++) {
  2027. if ( *lpcbBuffer > cb + 30) {
  2028. cb += wsprintf( pchBuffer + cb, " <LI> %s = %d",
  2029. g_IISAuxCounterNames[i],
  2030. AcCounter(i));
  2031. } else {
  2032. cb += 30;
  2033. }
  2034. } // for
  2035. if ( *lpcbBuffer > cb + 5) {
  2036. cb += wsprintf( pchBuffer + cb, " </UL> ");
  2037. } else {
  2038. cb += 5;
  2039. }
  2040. *lpcbBuffer = cb;
  2041. return ;
  2042. } // TsDumpCacheCounters()
  2043.