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.

1026 lines
26 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. lsaux.cxx
  5. Abstract:
  6. This modules defines the functions supporting list processing.
  7. Author:
  8. Murali R. Krishnan ( MuraliK ) 2-May-1995
  9. Environment:
  10. User Mode -- Win32
  11. Project:
  12. FTP Server DLL
  13. Functions Exported:
  14. Revision History:
  15. --*/
  16. /************************************************************
  17. * Include Headers
  18. ************************************************************/
  19. # include "ftpdp.hxx"
  20. # include "lsaux.hxx"
  21. /************************************************************
  22. * Functions
  23. ************************************************************/
  24. const FILETIME *
  25. PickFileTime(IN const WIN32_FIND_DATA * pfdInfo,
  26. IN const LS_OPTIONS * pOptions)
  27. /*++
  28. This function selects and returns proper FILETIME structure
  29. to display based on the current sort method and filesystem
  30. capabilities.
  31. Arguments:
  32. pfdInfo pointer to file information for a directory entry.
  33. pOptions the current ls options
  34. Returns:
  35. FILETIME -- pointer to proper time required
  36. History:
  37. MuraliK 25-Apr-1995
  38. This is a costly operation too. Given that this one is called once every
  39. directory entry is getting formatted. Can we avoid the cost ?
  40. YES, if we can use the offsets in the pfdInfo to chose the time object.
  41. NYI
  42. --*/
  43. {
  44. const FILETIME * pliTime;
  45. switch ( pOptions->SortMethod) {
  46. case LsSortByName:
  47. case LsSortByWriteTime:
  48. pliTime = &pfdInfo->ftLastWriteTime;
  49. break;
  50. case LsSortByCreationTime:
  51. pliTime = &pfdInfo->ftCreationTime;
  52. break;
  53. case LsSortByAccessTime:
  54. pliTime = &pfdInfo->ftLastAccessTime;
  55. break;
  56. default:
  57. IF_DEBUG( ERROR) {
  58. DBGPRINTF(( DBG_CONTEXT,
  59. "Invalid Sort %d!\n", pOptions->SortMethod ));
  60. }
  61. DBG_ASSERT( FALSE );
  62. pliTime = &pfdInfo->ftLastWriteTime;
  63. break;
  64. } // switch()
  65. //
  66. // If the selected time field is not supported on
  67. // the current filesystem, default to ftLastWriteTime
  68. // (all filesystems support this field).
  69. //
  70. if( NULL_FILE_TIME( *pliTime ) ) {
  71. pliTime = &pfdInfo->ftLastWriteTime;
  72. }
  73. return ( pliTime);
  74. } // PickFileTime()
  75. BOOL __cdecl
  76. FtpFilterFileInfo(
  77. IN const WIN32_FIND_DATA * pfdInfo,
  78. IN LPVOID pContext
  79. )
  80. /*++
  81. This function tries to filter out the file information using
  82. Ftp service "ls" specific filter.
  83. Arguments:
  84. pfdInfo pointer to file information that contains the current
  85. file information object for filtering.
  86. pContext pointer to FTP_LS_FILTER_INFO used for filtering.
  87. Returns:
  88. TRUE if there is a match and that this file info should not be
  89. eliminated.
  90. FALSE if this file info object can be dropped out of generated list.
  91. --*/
  92. {
  93. register FTP_LS_FILTER_INFO * pfls = (FTP_LS_FILTER_INFO *) pContext;
  94. DWORD dwAttribs;
  95. if ( pfdInfo == NULL ||
  96. pfdInfo->dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
  97. return ( FALSE);
  98. }
  99. //
  100. // We dont need to expose hidden/system files unless necessary.
  101. //
  102. dwAttribs = pfdInfo->dwFileAttributes;
  103. if (pfls->fFilterHidden && IS_HIDDEN( dwAttribs) ||
  104. pfls->fFilterSystem && IS_SYSTEM( dwAttribs)) {
  105. return ( FALSE); // unwanted files.
  106. }
  107. // Always filter away "." and ".."
  108. const CHAR * pszFileName = ( pfdInfo->cFileName);
  109. if (pfls->fFilterDotDot && pszFileName[0] == '.' ||
  110. strcmp( pszFileName, ".") == 0 ||
  111. strcmp( pszFileName, "..") == 0) {
  112. return ( FALSE);
  113. }
  114. DBG_ASSERT( pfls->pszExpression == NULL || *pfls->pszExpression != '\0');
  115. //
  116. // Check about the file name.
  117. // If the expression is not a regular expression, use simple StringCompare
  118. // else use a regular expression comparison.
  119. // Return TRUE if there is a match else return FALSE.
  120. //
  121. return ( pfls->pszExpression == NULL || // null-expr ==> all match.
  122. (( pfls->fRegExpression)
  123. ? IsNameInRegExpressionA(pfls->pszExpression, pszFileName,
  124. pfls->fIgnoreCase)
  125. : !strcmp(pszFileName, pfls->pszExpression)
  126. ));
  127. } // FtpFilterFileInfo()
  128. APIERR
  129. GetDirectoryInfo(
  130. IN LPUSER_DATA pUserData,
  131. OUT TS_DIRECTORY_INFO * pTsDirInfo,
  132. IN CHAR * pszSearchPath,
  133. IN const FTP_LS_FILTER_INFO * pfls,
  134. IN PFN_CMP_WIN32_FIND_DATA pfnCompare
  135. )
  136. /*++
  137. This function creates a directory listing for given directory,
  138. filters out unmatched files and sorts the resulting elements
  139. using the sort function.
  140. Arguments:
  141. pUserData pointer to UserData structure.
  142. pTsDirInfo pointer to Directory Information object that will be
  143. filled in with the directory information.
  144. pszSearchPath pointer to null-terminated string containing
  145. the absolute path for directory along with
  146. the possible filter specification.
  147. eg: d:\foo\bar
  148. pfls pointer to filter information used for filtering.
  149. pfnCompare pointer to function used for sorting.
  150. Returns:
  151. NO_ERROR on success and Win32 error code if there are any failure.
  152. History:
  153. MuraliK 25-Apr-1995
  154. --*/
  155. {
  156. DWORD dwError = NO_ERROR;
  157. DBG_ASSERT( pTsDirInfo != NULL && pszSearchPath != NULL);
  158. DBG_ASSERT( !pTsDirInfo->IsValid()); // no dir list yet.
  159. IF_DEBUG(DIR_LIST) {
  160. DBGPRINTF((DBG_CONTEXT,
  161. "GetDirListing( dir=%s, Filter=%08x (Sz=%s), "
  162. "user=%08x, cmp=%08x)\n",
  163. pszSearchPath, pfls, pfls->pszExpression,
  164. pUserData->QueryUserToken(), pfnCompare));
  165. }
  166. CHAR rgDirPath[MAX_PATH+10];
  167. CHAR * pszDirPath;
  168. DWORD len = strlen( pszSearchPath);
  169. // check to see if the last character is a "\" in the dir path
  170. // if not append one to make sure GetDirectoryListing works fine.
  171. if ( *CharPrev( pszSearchPath, pszSearchPath + len ) != '\\') {
  172. DBG_ASSERT( len < sizeof(rgDirPath) - 2);
  173. DBG_REQUIRE( _snprintf( rgDirPath, sizeof( rgDirPath ) - 1, "%s\\", pszSearchPath) > 0);
  174. rgDirPath[ sizeof( rgDirPath ) - 1] = '\0';
  175. pszDirPath = rgDirPath;
  176. } else {
  177. pszDirPath = pszSearchPath;
  178. }
  179. if ( !pTsDirInfo->GetDirectoryListingA(pszDirPath,
  180. pUserData->QueryUserToken())
  181. ) {
  182. dwError = GetLastError();
  183. }
  184. if ( dwError == NO_ERROR) {
  185. //
  186. // we got the directory listing.
  187. // We need to apply filters to restrict the directory listing.
  188. // Next we need to sort the resulting mix based on the
  189. // sorting options requested by the list command.
  190. //
  191. //
  192. // We need to identify the appropriate filter
  193. // file spec to be applied. For present use *.*
  194. // Filtering should not fail unless tsDirInfo is invalid.
  195. //
  196. if ( pfls != NULL) {
  197. DBG_REQUIRE(pTsDirInfo->FilterFiles(FtpFilterFileInfo,
  198. (LPVOID )pfls)
  199. );
  200. }
  201. //
  202. // Sort only if sort function specified
  203. //
  204. if ( pfnCompare != NULL) {
  205. DBG_REQUIRE( pTsDirInfo->SortFileInfoPointers( pfnCompare));
  206. }
  207. }
  208. return ( dwError);
  209. } // GetDirectoryInfo()
  210. /**************************************************
  211. * Comparison Functions
  212. **************************************************/
  213. int __cdecl
  214. CompareNamesInFileInfo(
  215. IN const void * pvFileInfo1,
  216. IN const void * pvFileInfo2)
  217. /*++
  218. Compares the two directory entries by name of the files.
  219. Arguments:
  220. pvFileInfo1 pointer to FileBothDirInfo object 1.
  221. pvFileInfo2 pointer to FileBothDirInfo object 2.
  222. Returns:
  223. 0 if they are same
  224. +1 if pvFileInfo1 > pvFileInfo2
  225. -1 if pvFileInfo1 < pvFileInfo2
  226. History:
  227. MuraliK 25-Apr-1995
  228. --*/
  229. {
  230. const WIN32_FIND_DATA * pFileInfo1 =
  231. *((const WIN32_FIND_DATA **) pvFileInfo1);
  232. const WIN32_FIND_DATA * pFileInfo2 =
  233. *((const WIN32_FIND_DATA **) pvFileInfo2);
  234. ASSERT( pFileInfo1 != NULL && pFileInfo2 != NULL);
  235. return ( lstrcmpi((LPCSTR )pFileInfo1->cFileName,
  236. (LPCSTR )pFileInfo2->cFileName));
  237. } // CompareNamesInFileInfo()
  238. int __cdecl
  239. CompareNamesRevInFileInfo(
  240. IN const void * pvFileInfo1,
  241. IN const void * pvFileInfo2)
  242. /*++
  243. Compares the two directory entries by name of the files.
  244. Arguments:
  245. pvFileInfo1 pointer to FileBothDirInfo object 1.
  246. pvFileInfo2 pointer to FileBothDirInfo object 2.
  247. Returns:
  248. 0 if they are same
  249. -1 if pvFileInfo1 > pvFileInfo2
  250. +1 if pvFileInfo1 < pvFileInfo2
  251. History:
  252. MuraliK 25-Apr-1995
  253. --*/
  254. {
  255. return -CompareNamesInFileInfo( pvFileInfo1, pvFileInfo2);
  256. } // CompareNamesRevInFileInfo()
  257. int __cdecl
  258. CompareWriteTimesInFileInfo(
  259. IN const void * pvFileInfo1,
  260. IN const void * pvFileInfo2)
  261. /*++
  262. Compares the write times of two directory entries.
  263. Arguments:
  264. pvFileInfo1 pointer to FileBothDirInfo object 1.
  265. pvFileInfo2 pointer to FileBothDirInfo object 2.
  266. Returns:
  267. 0 if they are same
  268. +1 if pvFileInfo1 > pvFileInfo2
  269. -1 if pvFileInfo1 < pvFileInfo2
  270. History:
  271. MuraliK 25-Apr-1995
  272. --*/
  273. {
  274. const WIN32_FIND_DATA * pFileInfo1 =
  275. *((const WIN32_FIND_DATA **) pvFileInfo1);
  276. const WIN32_FIND_DATA * pFileInfo2 =
  277. *((const WIN32_FIND_DATA **) pvFileInfo2);
  278. ASSERT( pFileInfo1 != NULL && pFileInfo2 != NULL);
  279. INT nResult;
  280. nResult = CompareFileTime(&pFileInfo1->ftLastWriteTime,
  281. &pFileInfo2->ftLastWriteTime );
  282. if( nResult == 0 ) {
  283. nResult = CompareNamesInFileInfo( pvFileInfo1, pvFileInfo2);
  284. }
  285. return nResult;
  286. } // CompareWriteTimesInFileInfo()
  287. int __cdecl
  288. CompareWriteTimesRevInFileInfo(
  289. IN const void * pvFileInfo1,
  290. IN const void * pvFileInfo2)
  291. /*++
  292. Compares the write times of two directory entries.
  293. Arguments:
  294. pvFileInfo1 pointer to FileBothDirInfo object 1.
  295. pvFileInfo2 pointer to FileBothDirInfo object 2.
  296. Returns:
  297. 0 if they are same
  298. -1 if pvFileInfo1 > pvFileInfo2
  299. +1 if pvFileInfo1 < pvFileInfo2
  300. History:
  301. MuraliK 25-Apr-1995
  302. --*/
  303. {
  304. return -CompareWriteTimesInFileInfo( pvFileInfo1, pvFileInfo2);
  305. } // CompareWriteTimesRevInFileInfo()
  306. int __cdecl
  307. CompareCreationTimesInFileInfo(
  308. IN const void * pvFileInfo1,
  309. IN const void * pvFileInfo2)
  310. /*++
  311. Compares the creation times of two directory entries.
  312. Arguments:
  313. pvFileInfo1 pointer to FileBothDirInfo object 1.
  314. pvFileInfo2 pointer to FileBothDirInfo object 2.
  315. Returns:
  316. 0 if they are same
  317. +1 if pvFileInfo1 > pvFileInfo2
  318. -1 if pvFileInfo1 < pvFileInfo2
  319. History:
  320. MuraliK 25-Apr-1995
  321. --*/
  322. {
  323. const WIN32_FIND_DATA * pFileInfo1 =
  324. *((const WIN32_FIND_DATA **) pvFileInfo1);
  325. const WIN32_FIND_DATA * pFileInfo2 =
  326. *((const WIN32_FIND_DATA **) pvFileInfo2);
  327. ASSERT( pFileInfo1 != NULL && pFileInfo2 != NULL);
  328. INT nResult;
  329. if ( NULL_FILE_TIME( pFileInfo1->ftCreationTime)) {
  330. nResult = CompareFileTime(&pFileInfo1->ftLastWriteTime,
  331. &pFileInfo2->ftLastWriteTime );
  332. } else {
  333. nResult = CompareFileTime(&pFileInfo1->ftCreationTime,
  334. &pFileInfo2->ftCreationTime );
  335. }
  336. if( nResult == 0 ) {
  337. nResult = CompareNamesInFileInfo( pvFileInfo1, pvFileInfo2);
  338. }
  339. return nResult;
  340. } // CompareCreationTimesInFileInfo()
  341. int __cdecl
  342. CompareCreationTimesRevInFileInfo(
  343. IN const void * pvFileInfo1,
  344. IN const void * pvFileInfo2)
  345. /*++
  346. Compares the creation times of two directory entries.
  347. Arguments:
  348. pvFileInfo1 pointer to FileBothDirInfo object 1.
  349. pvFileInfo2 pointer to FileBothDirInfo object 2.
  350. Returns:
  351. 0 if they are same
  352. +1 if pvFileInfo1 > pvFileInfo2
  353. -1 if pvFileInfo1 < pvFileInfo2
  354. History:
  355. MuraliK 25-Apr-1995
  356. --*/
  357. {
  358. return -CompareCreationTimesInFileInfo( pvFileInfo1, pvFileInfo2 );
  359. } // CompareCreationTimesRevInFileInfo()
  360. int __cdecl
  361. CompareAccessTimesInFileInfo(
  362. IN const void * pvFileInfo1,
  363. IN const void * pvFileInfo2)
  364. /*++
  365. Compares the last access times of two directory entries.
  366. Arguments:
  367. pvFileInfo1 pointer to FileBothDirInfo object 1.
  368. pvFileInfo2 pointer to FileBothDirInfo object 2.
  369. Returns:
  370. 0 if they are same
  371. +1 if pvFileInfo1 > pvFileInfo2
  372. -1 if pvFileInfo1 < pvFileInfo2
  373. History:
  374. MuraliK 25-Apr-1995
  375. --*/
  376. {
  377. const WIN32_FIND_DATA * pFileInfo1 =
  378. *((const WIN32_FIND_DATA **) pvFileInfo1);
  379. const WIN32_FIND_DATA * pFileInfo2 =
  380. *((const WIN32_FIND_DATA **) pvFileInfo2);
  381. ASSERT( pFileInfo1 != NULL && pFileInfo2 != NULL);
  382. INT nResult;
  383. if ( NULL_FILE_TIME( pFileInfo1->ftLastAccessTime)) {
  384. nResult = CompareFileTime(&pFileInfo1->ftLastWriteTime,
  385. &pFileInfo2->ftLastWriteTime );
  386. } else {
  387. nResult = CompareFileTime(&pFileInfo1->ftLastAccessTime,
  388. &pFileInfo2->ftLastAccessTime );
  389. }
  390. if( nResult == 0 ) {
  391. nResult = CompareNamesInFileInfo( pvFileInfo1, pvFileInfo2);
  392. }
  393. return nResult;
  394. } // CompareAccessTimesInFileInfo()
  395. int __cdecl
  396. CompareAccessTimesRevInFileInfo(
  397. IN const void * pvFileInfo1,
  398. IN const void * pvFileInfo2)
  399. /*++
  400. Compares the last access times of two directory entries.
  401. Arguments:
  402. pvFileInfo1 pointer to FileBothDirInfo object 1.
  403. pvFileInfo2 pointer to FileBothDirInfo object 2.
  404. Returns:
  405. 0 if they are same
  406. +1 if pvFileInfo1 > pvFileInfo2
  407. -1 if pvFileInfo1 < pvFileInfo2
  408. History:
  409. MuraliK 25-Apr-1995
  410. --*/
  411. {
  412. return -CompareAccessTimesInFileInfo( pvFileInfo1, pvFileInfo2 );
  413. } // CompareAccessTimesRevInFileInfo()
  414. DWORD
  415. ComputeModeBits(
  416. IN HANDLE hUserToken,
  417. IN const CHAR * pszPathPart,
  418. IN const WIN32_FIND_DATA * pfdInfo,
  419. IN DWORD * pcLinks,
  420. IN BOOL fVolumeReadable,
  421. IN BOOL fVolumeWritable
  422. )
  423. /*++
  424. This function computes the mode buts r-w-x for a specific file.
  425. Arguments:
  426. hUserToken - The security token of the user that initiated the request.
  427. pszPathPart - contains the search path for this directory.
  428. pfdInfo - pointer to File information
  429. pcLinks - will receive the count of symbolic links to this file.
  430. fVolumeReadable - TRUE if volume is readable
  431. fVolumeWritable - TRUE if volume is writable
  432. Returns:
  433. DWORD - A combination of FILE_MODE_R, FILE_MODE_W, and FILE_MODE_X bits.
  434. HISTORY:
  435. KeithMo 01-Jun-1993 Created.
  436. MuraliK 26-Apr-1995 Modified to support new pfdInfo
  437. --*/
  438. {
  439. APIERR err;
  440. DWORD dwAccess;
  441. DWORD dwMode = 0;
  442. DBG_ASSERT( hUserToken != NULL );
  443. DBG_ASSERT( pszPathPart != NULL );
  444. DBG_ASSERT( pfdInfo != NULL );
  445. DBG_ASSERT( pcLinks != NULL );
  446. DBG_ASSERT( pszPathPart[1] == ':' );
  447. DBG_ASSERT( pszPathPart[2] == '\\' );
  448. if( !( GetFsFlags( *pszPathPart ) & FS_PERSISTENT_ACLS ) )
  449. {
  450. //
  451. // Short-circuit if on a non-NTFS partition.
  452. //
  453. *pcLinks = 1;
  454. dwAccess = FILE_ALL_ACCESS;
  455. err = NO_ERROR;
  456. }
  457. else
  458. {
  459. CHAR szPath[MAX_PATH*2];
  460. CHAR * pszEnd;
  461. INT len1 = strlen( pszPathPart );
  462. INT len2 = strlen( pfdInfo->cFileName);
  463. //
  464. // Determine the maximum file access allowed.
  465. //
  466. DBG_ASSERT( strlen( pszPathPart) +
  467. strlen( pfdInfo->cFileName) < MAX_PATH * 2);
  468. if ((len1 + len2 + 2) <= sizeof(szPath)) {
  469. memcpy( szPath, pszPathPart, len1+1 );
  470. pszEnd = CharPrev( szPath, szPath + len1 );
  471. if( *pszEnd != '\\' && *pszEnd != '/' ) {
  472. pszEnd = szPath + len1;
  473. *pszEnd = '\\';
  474. }
  475. memcpy( pszEnd + 1, pfdInfo->cFileName, len2+1 );
  476. err = ComputeFileInfo( hUserToken,
  477. szPath,
  478. &dwAccess,
  479. pcLinks );
  480. } else {
  481. err = ERROR_INSUFFICIENT_BUFFER;
  482. }
  483. }
  484. if( err == NO_ERROR )
  485. {
  486. //
  487. // Map various NT access to unix-like mode bits.
  488. //
  489. if( fVolumeReadable && ( dwAccess & FILE_READ_DATA ) )
  490. {
  491. dwMode |= FILE_MODE_R;
  492. }
  493. if( fVolumeReadable && ( dwAccess & FILE_EXECUTE ) )
  494. {
  495. dwMode |= FILE_MODE_X;
  496. }
  497. if( fVolumeWritable &&
  498. !( pfdInfo->dwFileAttributes & FILE_ATTRIBUTE_READONLY ) &&
  499. ( dwAccess & FILE_WRITE_DATA ) &&
  500. ( dwAccess & FILE_APPEND_DATA ) )
  501. {
  502. dwMode |= FILE_MODE_W;
  503. }
  504. }
  505. return dwMode;
  506. } // ComputeModeBits()
  507. #define DEFAULT_SECURITY_DESC_SIZE ( 2048)
  508. #define DEFAULT_PRIV_SET_SIZE ( 1024)
  509. APIERR
  510. ComputeFileInfo(
  511. HANDLE hUserToken,
  512. CHAR * pszFile,
  513. DWORD * pdwAccessGranted,
  514. DWORD * pcLinks
  515. )
  516. /*++
  517. This function uses internal Nt security api's to determine if the
  518. valid access is granted.
  519. BEWARE: this function is extremely costly! We need to simplify the cost.
  520. ==>> NYI
  521. Arguments:
  522. hUserToken - handle for the user, for whom we are determining the
  523. access and links
  524. pszFile - full path for the file.
  525. pdwAccessGranted - pointer to DWORD which will receive the granted access.
  526. pcLinks - pointer to count of links for the file.
  527. Returns:
  528. Win32 Error code if there is any failure.
  529. NO_ERROR on success.
  530. --*/
  531. {
  532. BY_HANDLE_FILE_INFORMATION FileInfo;
  533. APIERR err;
  534. SECURITY_DESCRIPTOR * psd = NULL;
  535. PRIVILEGE_SET * pps = NULL;
  536. DWORD cbsd;
  537. DWORD cbps;
  538. GENERIC_MAPPING mapping = { 0, 0, 0, FILE_ALL_ACCESS };
  539. HANDLE hFile = INVALID_HANDLE_VALUE;
  540. BOOL fStatus;
  541. DBG_ASSERT( hUserToken != NULL );
  542. DBG_ASSERT( pszFile != NULL );
  543. DBG_ASSERT( pdwAccessGranted != NULL );
  544. DBG_ASSERT( pcLinks != NULL );
  545. //
  546. // Setup.
  547. //
  548. *pdwAccessGranted = 0;
  549. *pcLinks = 1;
  550. //
  551. // Open the target file/directory.
  552. //
  553. err = OpenPathForAccess( &hFile,
  554. pszFile,
  555. GENERIC_READ,
  556. ( FILE_SHARE_READ | FILE_SHARE_WRITE |
  557. FILE_SHARE_DELETE),
  558. hUserToken
  559. );
  560. if( err != NO_ERROR )
  561. {
  562. return err;
  563. }
  564. //
  565. // Determine the number of symbolic links.
  566. //
  567. if ( GetFileInformationByHandle( hFile,
  568. &FileInfo)
  569. ) {
  570. *pcLinks = FileInfo.nNumberOfLinks;
  571. } else {
  572. //
  573. // We won't let this be serious enough to abort
  574. // the entire operation.
  575. //
  576. *pcLinks = 1;
  577. }
  578. //
  579. // Get the file's security descriptor.
  580. //
  581. cbsd = DEFAULT_SECURITY_DESC_SIZE;
  582. psd = (SECURITY_DESCRIPTOR *)TCP_ALLOC( cbsd );
  583. if( psd == NULL )
  584. {
  585. err = GetLastError();
  586. goto Cleanup;
  587. }
  588. do
  589. {
  590. err = NO_ERROR;
  591. //
  592. // Replace NtQuerySecurityObject() by GetFileSecurity()
  593. //
  594. if (!GetFileSecurity( pszFile,
  595. OWNER_SECURITY_INFORMATION
  596. | GROUP_SECURITY_INFORMATION
  597. | DACL_SECURITY_INFORMATION,
  598. psd,
  599. cbsd,
  600. &cbsd )
  601. ) {
  602. err = GetLastError();
  603. }
  604. if( err == ERROR_INSUFFICIENT_BUFFER )
  605. {
  606. TCP_FREE( psd );
  607. psd = (SECURITY_DESCRIPTOR *)TCP_ALLOC( cbsd );
  608. if( psd == NULL )
  609. {
  610. err = GetLastError();
  611. break;
  612. }
  613. }
  614. } while( err == ERROR_INSUFFICIENT_BUFFER );
  615. if( err != NO_ERROR ) {
  616. IF_DEBUG( DIR_LIST) {
  617. DBGPRINTF(( DBG_CONTEXT,
  618. "cannot get security for %s, error %lu\n",
  619. pszFile,
  620. err ));
  621. }
  622. goto Cleanup;
  623. }
  624. //
  625. // Check access.
  626. //
  627. cbps = DEFAULT_PRIV_SET_SIZE;
  628. pps = (PRIVILEGE_SET *)TCP_ALLOC( cbps );
  629. if( pps == NULL )
  630. {
  631. err = GetLastError();
  632. goto Cleanup;
  633. }
  634. do
  635. {
  636. if( AccessCheck( psd,
  637. hUserToken,
  638. MAXIMUM_ALLOWED,
  639. &mapping,
  640. pps,
  641. &cbps,
  642. pdwAccessGranted,
  643. &fStatus ) )
  644. {
  645. err = fStatus ? NO_ERROR : GetLastError();
  646. if( err != NO_ERROR )
  647. {
  648. IF_DEBUG( DIR_LIST) {
  649. DBGPRINTF(( DBG_CONTEXT,
  650. "AccessCheck() failure. Error=%d\n", err ));
  651. }
  652. break;
  653. }
  654. }
  655. else
  656. {
  657. err = GetLastError();
  658. if( err == ERROR_INSUFFICIENT_BUFFER )
  659. {
  660. TCP_FREE( pps );
  661. pps = (PRIVILEGE_SET *)TCP_ALLOC( cbps );
  662. if( pps == NULL )
  663. {
  664. err = GetLastError();
  665. break;
  666. }
  667. }
  668. }
  669. } while( err == ERROR_INSUFFICIENT_BUFFER );
  670. if( err != NO_ERROR )
  671. {
  672. IF_DEBUG(DIR_LIST) {
  673. DBGPRINTF(( DBG_CONTEXT,
  674. "cannot get check access for %s, error %lu\n",
  675. pszFile,
  676. err ));
  677. }
  678. goto Cleanup;
  679. }
  680. Cleanup:
  681. if( psd != NULL )
  682. {
  683. TCP_FREE( psd );
  684. }
  685. if( pps != NULL )
  686. {
  687. TCP_FREE( pps );
  688. }
  689. if( hFile != INVALID_HANDLE_VALUE )
  690. {
  691. CloseHandle( hFile );
  692. }
  693. return err;
  694. } // ComputeFileInfo()
  695. # define INVALID_FS_FLAGS ((DWORD ) -1L)
  696. DWORD
  697. GetFsFlags( IN CHAR chDrive)
  698. /*++
  699. This function uses GetVolumeInformation to retrieve the file system
  700. flags for the given drive.
  701. Arguments:
  702. chDrive the drive letter to check for. Must be A-Z.
  703. Returns:
  704. DWORD containing the FS flags. 0 if unknown.
  705. History:
  706. MuraliK 25-Apr-1995
  707. --*/
  708. {
  709. INT iDrive;
  710. DWORD Flags = INVALID_FS_FLAGS;
  711. static DWORD p_FsFlags[26] = {
  712. // One per DOS drive (A - Z).
  713. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  714. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  715. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  716. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  717. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  718. INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS, INVALID_FS_FLAGS,
  719. INVALID_FS_FLAGS, INVALID_FS_FLAGS
  720. };
  721. //
  722. // Validate the parameter & map to uppercase.
  723. //
  724. chDrive = (INT)toupper( chDrive );
  725. DBG_ASSERT( ( chDrive >= 'A' ) && ( chDrive <= 'Z' ) );
  726. iDrive = (INT)( chDrive - 'A' );
  727. //
  728. // If we've already touched this drive, use the
  729. // cached value.
  730. //
  731. Flags = p_FsFlags[iDrive];
  732. if( Flags == INVALID_FS_FLAGS )
  733. {
  734. CHAR szRoot[] = "d:\\";
  735. //
  736. // Retrieve the flags.
  737. //
  738. szRoot[0] = chDrive;
  739. GetVolumeInformation( szRoot, // lpRootPathName
  740. NULL, // lpVolumeNameBuffer
  741. 0, // nVolumeNameSize
  742. NULL, // lpVolumeSerialNumber
  743. NULL, // lpMaximumComponentLength
  744. &Flags, // lpFileSystemFlags
  745. NULL, // lpFileSYstemNameBuffer,
  746. 0 ); // nFileSystemNameSize
  747. p_FsFlags[iDrive] = Flags;
  748. }
  749. return ( Flags == INVALID_FS_FLAGS ) ? 0 : Flags;
  750. } // GetFsFlags()
  751. /************************ End of File ***********************/