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.

831 lines
17 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. fileio.c
  5. Abstract:
  6. This module implements server performed file io
  7. Author:
  8. Mark Lucovsky (markl) 27-Nov-1989
  9. Revision History:
  10. --*/
  11. #include <sys/stat.h>
  12. #include <time.h>
  13. #include <wchar.h>
  14. #include "psxsrv.h"
  15. BOOLEAN
  16. FileRead (
  17. IN PPSX_PROCESS p,
  18. IN OUT PPSX_API_MSG m,
  19. IN PFILEDESCRIPTOR Fd
  20. );
  21. BOOLEAN
  22. FileWrite (
  23. IN PPSX_PROCESS p,
  24. IN OUT PPSX_API_MSG m,
  25. IN PFILEDESCRIPTOR Fd
  26. );
  27. BOOLEAN
  28. FileDup (
  29. IN PPSX_PROCESS p,
  30. IN OUT PPSX_API_MSG m,
  31. IN PFILEDESCRIPTOR Fd,
  32. IN PFILEDESCRIPTOR FdDup
  33. );
  34. BOOLEAN
  35. FileLseek (
  36. IN PPSX_PROCESS p,
  37. IN OUT PPSX_API_MSG m,
  38. IN PFILEDESCRIPTOR Fd
  39. );
  40. BOOLEAN
  41. FileStat (
  42. IN PIONODE IoNode,
  43. IN HANDLE FileHandle,
  44. OUT struct stat *StatBuf,
  45. OUT NTSTATUS *pStatus
  46. );
  47. void
  48. FindOwnerModeFile(
  49. IN HANDLE FileHandle,
  50. OUT struct stat *StatBuf
  51. );
  52. VOID
  53. FileLastClose (
  54. IN PPSX_PROCESS p,
  55. IN PSYSTEMOPENFILE SystemOpenFile
  56. )
  57. {
  58. NTSTATUS st;
  59. IO_STATUS_BLOCK Iosb;
  60. FILE_DISPOSITION_INFORMATION Disp;
  61. wchar_t buf[PATH_MAX];
  62. UNICODE_STRING U;
  63. ANSI_STRING A;
  64. OBJECT_ATTRIBUTES Obj;
  65. HANDLE hDir;
  66. if (!SystemOpenFile->IoNode->Junked) {
  67. st = NtClose(SystemOpenFile->NtIoHandle);
  68. ASSERT(NT_SUCCESS(st));
  69. return;
  70. }
  71. //
  72. // This file has been moved to the junkyard, and should now
  73. // be deleted.
  74. //
  75. Disp.DeleteFile = TRUE;
  76. st = NtSetInformationFile(SystemOpenFile->NtIoHandle,
  77. &Iosb, &Disp, sizeof(Disp), FileDispositionInformation);
  78. if (!NT_SUCCESS(st)) {
  79. KdPrint(("PSXSS: FileLastClose: SetInfo: 0x%x\n", st));
  80. }
  81. st = NtClose(SystemOpenFile->NtIoHandle);
  82. ASSERT(NT_SUCCESS(st));
  83. //
  84. // Try to delete the directory that held the junked file.
  85. //
  86. swprintf(buf, L"\\DosDevices\\%wc:\\%ws",
  87. SystemOpenFile->IoNode->DeviceSerialNumber, PSX_JUNK_DIR);
  88. U.Buffer = buf;
  89. U.Length = wcslen(buf) * sizeof(wchar_t);
  90. U.MaximumLength = sizeof(buf);
  91. InitializeObjectAttributes(&Obj, &U, 0, NULL, NULL);
  92. st = NtOpenFile(&hDir, SYNCHRONIZE | DELETE,
  93. &Obj, &Iosb, SHARE_ALL,
  94. FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);
  95. if (!NT_SUCCESS(st)) {
  96. //null
  97. } else {
  98. Disp.DeleteFile = TRUE;
  99. st = NtSetInformationFile(hDir, &Iosb,
  100. &Disp, sizeof(Disp),
  101. FileDispositionInformation);
  102. NtClose(hDir);
  103. }
  104. }
  105. PSXIO_VECTORS FileVectors = {
  106. NULL,
  107. NULL,
  108. NULL,
  109. FileLastClose,
  110. NULL,
  111. FileRead,
  112. FileWrite,
  113. FileDup,
  114. FileLseek,
  115. FileStat
  116. };
  117. BOOLEAN
  118. FileWrite (
  119. IN PPSX_PROCESS p,
  120. IN OUT PPSX_API_MSG m,
  121. IN PFILEDESCRIPTOR Fd
  122. )
  123. /*++
  124. Routine Description:
  125. This procedure implements write when the device being written
  126. is a file.
  127. Arguments:
  128. p - Supplies the address of the process making the call.
  129. m - Supplies the address of the message associated with the request.
  130. Fd - supplies the address of the file descriptor being written.
  131. Return Value:
  132. --*/
  133. {
  134. PPSX_WRITE_MSG args;
  135. NTSTATUS st;
  136. IO_STATUS_BLOCK Iosb;
  137. LARGE_INTEGER ByteOffset;
  138. SIZE_T IoBufferSize;
  139. FILE_FS_SIZE_INFORMATION SizeInfo;
  140. ULONG Avail;
  141. LARGE_INTEGER Time;
  142. ULONG PosixTime;
  143. PVOID IoBuffer = NULL;
  144. args = &m->u.Write;
  145. // Allocate buffer in server
  146. IoBufferSize = args->Nbytes;
  147. st = NtAllocateVirtualMemory(NtCurrentProcess(), &IoBuffer, 0,
  148. &IoBufferSize, MEM_COMMIT, PAGE_READWRITE);
  149. if (!NT_SUCCESS(st)) {
  150. m->Error = ENOMEM;
  151. return TRUE;
  152. }
  153. // Read data from user buffer to server buffer
  154. st = NtReadVirtualMemory(p->Process, args->Buf, IoBuffer, args->Nbytes,
  155. NULL);
  156. if (!NT_SUCCESS(st)) {
  157. m->Error = PsxStatusToErrno(st);
  158. goto out;
  159. }
  160. if (Fd->SystemOpenFileDesc->Flags & PSX_FD_APPEND) {
  161. ByteOffset = RtlConvertLongToLargeInteger(
  162. FILE_WRITE_TO_END_OF_FILE);
  163. } else {
  164. ByteOffset = RtlConvertLongToLargeInteger(
  165. FILE_USE_FILE_POINTER_POSITION);
  166. }
  167. st = NtWriteFile(Fd->SystemOpenFileDesc->NtIoHandle, NULL,
  168. NULL, NULL, &Iosb, IoBuffer, args->Nbytes, &ByteOffset, NULL);
  169. if (NT_SUCCESS(st)) {
  170. NtQuerySystemTime(&Time);
  171. if (!RtlTimeToSecondsSince1970(&Time, &PosixTime)) {
  172. PosixTime = 0;
  173. }
  174. RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
  175. Fd->SystemOpenFileDesc->IoNode->ModifyDataTime = PosixTime;
  176. Fd->SystemOpenFileDesc->IoNode->ModifyIoNodeTime = PosixTime;
  177. RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
  178. m->ReturnValue = (ULONG)Iosb.Information;
  179. goto out;
  180. }
  181. switch (st) {
  182. case STATUS_DISK_FULL:
  183. while (0 != --args->Nbytes) {
  184. st = NtWriteFile(Fd->SystemOpenFileDesc->NtIoHandle,
  185. NULL, NULL, NULL, &Iosb, IoBuffer,
  186. args->Nbytes, &ByteOffset, NULL);
  187. if (NT_SUCCESS(st)) {
  188. m->ReturnValue = (ULONG)Iosb.Information;
  189. goto out;
  190. }
  191. }
  192. m->Error = ENOSPC;
  193. break;
  194. default:
  195. m->Error = EIO;
  196. break;
  197. }
  198. out:
  199. st = NtFreeVirtualMemory(NtCurrentProcess(), &IoBuffer, &IoBufferSize,
  200. MEM_RELEASE);
  201. if (!NT_SUCCESS(st) ) {
  202. m->Error = ENOMEM;
  203. }
  204. return TRUE;
  205. }
  206. BOOLEAN
  207. FileRead (
  208. IN PPSX_PROCESS p,
  209. IN OUT PPSX_API_MSG m,
  210. IN PFILEDESCRIPTOR Fd
  211. )
  212. /*++
  213. Routine Description:
  214. This procedure implements read when the device being read
  215. is a file.
  216. Arguments:
  217. p - Supplies the address of the process making the call.
  218. m - Supplies the address of the message associated with the request.
  219. Fd - supplies the address of the file descriptor being read.
  220. Return Value:
  221. --*/
  222. {
  223. PPSX_READ_MSG args;
  224. PPSX_READDIR_MSG args2;
  225. NTSTATUS st;
  226. IO_STATUS_BLOCK Iosb;
  227. LARGE_INTEGER ByteOffset;
  228. SIZE_T IoBufferSize;
  229. LARGE_INTEGER Time;
  230. ULONG PosixTime;
  231. UCHAR Buf[sizeof(FILE_NAMES_INFORMATION) +
  232. NAME_MAX * sizeof(WCHAR)];
  233. PFILE_NAMES_INFORMATION pNamesInfo = (PVOID)Buf;
  234. PVOID IoBuffer = NULL;
  235. args2 = &m->u.ReadDir;
  236. args = &m->u.Read;
  237. //
  238. // Update the access time on the ionode.
  239. //
  240. NtQuerySystemTime(&Time);
  241. if (!RtlTimeToSecondsSince1970(&Time, &PosixTime)) {
  242. PosixTime = 0;
  243. }
  244. RtlEnterCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
  245. Fd->SystemOpenFileDesc->IoNode->AccessDataTime = PosixTime;
  246. RtlLeaveCriticalSection(&Fd->SystemOpenFileDesc->IoNode->IoNodeLock);
  247. if (S_ISDIR(Fd->SystemOpenFileDesc->IoNode->Mode)) {
  248. UNICODE_STRING U;
  249. ANSI_STRING A;
  250. st = NtQueryDirectoryFile(
  251. Fd->SystemOpenFileDesc->NtIoHandle,
  252. NULL, NULL, NULL, &Iosb,
  253. &Buf, sizeof(Buf),
  254. FileNamesInformation, TRUE, NULL,
  255. args2->RestartScan
  256. );
  257. if (STATUS_BUFFER_OVERFLOW == st) {
  258. m->Error = ENAMETOOLONG;
  259. return TRUE;
  260. }
  261. if (STATUS_NO_MORE_FILES == st) {
  262. m->ReturnValue = 0;
  263. return TRUE;
  264. }
  265. if (!NT_SUCCESS(st)) {
  266. m->Error = PsxStatusToErrno(st);
  267. return TRUE;
  268. }
  269. U.Length = U.MaximumLength = (USHORT)pNamesInfo->FileNameLength;
  270. U.Buffer = pNamesInfo->FileName;
  271. st = RtlUnicodeStringToAnsiString(&A, &U, TRUE);
  272. if (!NT_SUCCESS(st)) {
  273. m->Error = ENOMEM;
  274. return TRUE;
  275. }
  276. m->ReturnValue = A.Length;
  277. st = NtWriteVirtualMemory(p->Process, args2->Buf,
  278. A.Buffer, A.Length, NULL);
  279. RtlFreeAnsiString(&A);
  280. if (!NT_SUCCESS(st)) {
  281. m->Error = EIO;
  282. return TRUE;
  283. }
  284. return TRUE;
  285. }
  286. IoBufferSize = args->Nbytes;
  287. st = NtAllocateVirtualMemory(NtCurrentProcess(), &IoBuffer, 0,
  288. &IoBufferSize, MEM_COMMIT, PAGE_READWRITE);
  289. if (!NT_SUCCESS(st)) {
  290. m->Error = ENOMEM;
  291. return TRUE;
  292. }
  293. ByteOffset = RtlConvertLongToLargeInteger(
  294. FILE_USE_FILE_POINTER_POSITION);
  295. st = NtReadFile(Fd->SystemOpenFileDesc->NtIoHandle, NULL, NULL, NULL,
  296. &Iosb, IoBuffer, args->Nbytes, &ByteOffset, NULL);
  297. if (STATUS_END_OF_FILE == st) {
  298. m->ReturnValue = 0;
  299. goto out;
  300. }
  301. if (!NT_SUCCESS(st)) {
  302. m->Error = EIO;
  303. goto out;
  304. }
  305. m->ReturnValue = (ULONG)Iosb.Information;
  306. st = NtWriteVirtualMemory(p->Process, args->Buf, IoBuffer,
  307. args->Nbytes, NULL);
  308. if (!NT_SUCCESS(st)) {
  309. m->Error = PsxStatusToErrno(st);
  310. }
  311. out:
  312. st = NtFreeVirtualMemory(NtCurrentProcess(), &IoBuffer,
  313. &IoBufferSize, MEM_RELEASE);
  314. ASSERT(NT_SUCCESS(st));
  315. return TRUE;
  316. }
  317. BOOLEAN
  318. FileDup (
  319. IN PPSX_PROCESS p,
  320. IN OUT PPSX_API_MSG m,
  321. IN PFILEDESCRIPTOR Fd,
  322. IN PFILEDESCRIPTOR FdDup
  323. )
  324. /*++
  325. Routine Description:
  326. This procedure implements dup and dup2
  327. Arguments:
  328. p - Supplies the address of the process making the call.
  329. m - Supplies the address of the message associated with the request.
  330. Fd - supplies the address of the file descriptor being duplicated.
  331. FdDup - supplies the address of the duplicate file descriptor.
  332. Return Value:
  333. ???
  334. --*/
  335. {
  336. PPSX_DUP_MSG args;
  337. args = &m->u.Dup;
  338. //
  339. // Copy contents of source file descriptor slot into new descriptor
  340. // Note that FD_CLOEXEC must be CLEAR on FdDup.
  341. //
  342. *FdDup = *Fd;
  343. FdDup->Flags &= ~PSX_FD_CLOSE_ON_EXEC;
  344. //
  345. // Increment reference count associated with the SystemOpenFile
  346. // descriptor for this file.
  347. //
  348. // Grab system open file lock
  349. RtlEnterCriticalSection(&SystemOpenFileLock);
  350. Fd->SystemOpenFileDesc->HandleCount++;
  351. RtlLeaveCriticalSection(&SystemOpenFileLock);
  352. return TRUE;
  353. }
  354. BOOLEAN
  355. FileLseek (
  356. IN PPSX_PROCESS p,
  357. IN OUT PPSX_API_MSG m,
  358. IN PFILEDESCRIPTOR Fd
  359. )
  360. /*++
  361. Routine Description:
  362. This procedure implements lseek when the device being seeked on
  363. is a file.
  364. Arguments:
  365. p - Supplies the address of the process making the call.
  366. m - Supplies the address of the message associated with the request.
  367. Fd - supplies the address of the file descriptor being seekd
  368. Return Value:
  369. ???
  370. --*/
  371. {
  372. PPSX_LSEEK_MSG args;
  373. NTSTATUS st;
  374. IO_STATUS_BLOCK Iosb;
  375. LARGE_INTEGER Offset, NewByteOffset;
  376. FILE_POSITION_INFORMATION FilePosition;
  377. FILE_STANDARD_INFORMATION StandardInfo;
  378. args = &m->u.Lseek;
  379. Offset = RtlConvertLongToLargeInteger(args->Offset);
  380. switch (args->Whence) {
  381. case SEEK_SET:
  382. NewByteOffset = Offset;
  383. break;
  384. case SEEK_CUR:
  385. st = NtQueryInformationFile(Fd->SystemOpenFileDesc->NtIoHandle,
  386. &Iosb, &FilePosition, sizeof(FilePosition),
  387. FilePositionInformation);
  388. if (!NT_SUCCESS(st)) {
  389. m->Error = PsxStatusToErrno(st);
  390. return TRUE;
  391. }
  392. NewByteOffset.QuadPart = Offset.QuadPart +
  393. FilePosition.CurrentByteOffset.QuadPart;
  394. break;
  395. case SEEK_END:
  396. st = NtQueryInformationFile(Fd->SystemOpenFileDesc->NtIoHandle,
  397. &Iosb, &StandardInfo, sizeof(StandardInfo),
  398. FileStandardInformation);
  399. if (!NT_SUCCESS(st)) {
  400. m->Error = PsxStatusToErrno(st);
  401. return TRUE;
  402. }
  403. NewByteOffset.QuadPart = Offset.QuadPart +
  404. StandardInfo.EndOfFile.QuadPart;
  405. break;
  406. default:
  407. m->Error = EINVAL;
  408. return TRUE;
  409. }
  410. // Check for overflow. POSIX limited to arithmetic data type for off_t
  411. if (NewByteOffset.HighPart != 0 || (off_t)NewByteOffset.LowPart < 0) {
  412. m->Error = EINVAL;
  413. return TRUE;
  414. }
  415. FilePosition.CurrentByteOffset = NewByteOffset;
  416. args->Offset = NewByteOffset.LowPart;
  417. st = NtSetInformationFile(Fd->SystemOpenFileDesc->NtIoHandle, &Iosb,
  418. &FilePosition, sizeof(FilePosition), FilePositionInformation);
  419. if (!NT_SUCCESS(st)) {
  420. m->Error = EINVAL;
  421. }
  422. return TRUE;
  423. }
  424. BOOLEAN
  425. FileStat (
  426. IN PIONODE IoNode,
  427. IN HANDLE FileHandle,
  428. OUT struct stat *StatBuf,
  429. OUT NTSTATUS *pStatus
  430. )
  431. /*++
  432. Routine Description:
  433. This procedure implements stat when the device being read
  434. is a file.
  435. Arguments:
  436. IoNode - supplies a pointer to the ionode of the file for which stat is
  437. requested. NULL if no active Ionode entry.
  438. FileHandle - supplies the Nt file handle of the file .
  439. StatBuf - Supplies the address of the statbuf portion of the message
  440. associated with the request.
  441. Return Value:
  442. ???
  443. --*/
  444. {
  445. IO_STATUS_BLOCK Iosb;
  446. FILE_INTERNAL_INFORMATION SerialNumber;
  447. FILE_BASIC_INFORMATION BasicInfo;
  448. FILE_STANDARD_INFORMATION StandardInfo;
  449. ULONG PosixTime;
  450. NTSTATUS st;
  451. //
  452. // First get the static information on the file from the ionode if
  453. // there is one (i.e. if the file currently open.
  454. // Open() sets the fields in the ionode.
  455. //
  456. if (NULL != IoNode) {
  457. StatBuf->st_mode = IoNode->Mode;
  458. StatBuf->st_ino = (ino_t)IoNode->FileSerialNumber;
  459. StatBuf->st_dev = IoNode->DeviceSerialNumber;
  460. StatBuf->st_uid = IoNode->OwnerId;
  461. StatBuf->st_gid = IoNode->GroupId;
  462. StatBuf->st_atime = IoNode->AccessDataTime;
  463. StatBuf->st_ctime = IoNode->ModifyIoNodeTime;
  464. StatBuf->st_mtime = IoNode->ModifyDataTime;
  465. } else {
  466. StatBuf->st_uid = 0;
  467. StatBuf->st_gid = 0;
  468. st = NtQueryInformationFile(FileHandle, &Iosb, &SerialNumber,
  469. sizeof(SerialNumber), FileInternalInformation);
  470. if (!NT_SUCCESS(st)) {
  471. KdPrint(("PSXSS: NtQueryInfoFile failed: 0x%x\n", st));
  472. *pStatus = st;
  473. return TRUE;
  474. }
  475. st = NtQueryInformationFile(FileHandle, &Iosb, &BasicInfo,
  476. sizeof(BasicInfo), FileBasicInformation);
  477. if (!NT_SUCCESS(st)) {
  478. //
  479. // can return STATUS_NO_SUCH_FILE if network
  480. // file system
  481. //
  482. *pStatus = st;
  483. return TRUE;
  484. }
  485. StatBuf->st_ino = (ino_t)SerialNumber.IndexNumber.LowPart;
  486. StatBuf->st_dev = 0;
  487. StatBuf->st_mode = PsxDetermineFileClass(FileHandle);
  488. FindOwnerModeFile(FileHandle, StatBuf);
  489. // Convert Nt file times to POSIX ones
  490. if (!RtlTimeToSecondsSince1970(&BasicInfo.LastAccessTime,
  491. &PosixTime)) {
  492. PosixTime = 0L;
  493. }
  494. StatBuf->st_atime = PosixTime;
  495. if (!RtlTimeToSecondsSince1970(&BasicInfo.LastWriteTime,
  496. &PosixTime)) {
  497. PosixTime = 0L;
  498. }
  499. StatBuf->st_mtime = PosixTime;
  500. if (!RtlTimeToSecondsSince1970(&BasicInfo.ChangeTime,
  501. &PosixTime)) {
  502. PosixTime = 0L;
  503. }
  504. StatBuf->st_ctime = PosixTime;
  505. }
  506. st = NtQueryInformationFile(FileHandle, &Iosb, &StandardInfo,
  507. sizeof(StandardInfo), FileStandardInformation);
  508. if (!NT_SUCCESS(st)) {
  509. KdPrint(("PSXSS: NtQueryInfoFile(StdInfo): 0x%x\n",
  510. st));
  511. *pStatus = st;
  512. return TRUE;
  513. }
  514. StatBuf->st_size = (off_t)StandardInfo.EndOfFile.LowPart;
  515. StatBuf->st_nlink = StandardInfo.NumberOfLinks;
  516. return TRUE;
  517. }
  518. void
  519. FindOwnerModeFile(
  520. IN HANDLE FileHandle,
  521. OUT struct stat *StatBuf
  522. )
  523. {
  524. SECURITY_INFORMATION SecurityInformation;
  525. ULONG LengthNeeded;
  526. PSID NtOwner, NtGroup;
  527. BOOLEAN OwnerDefaulted, GroupDefaulted;
  528. BOOLEAN AclPresent, AclDefaulted;
  529. PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
  530. PACL pAcl;
  531. NTSTATUS st;
  532. ACCESS_MASK UserAccess, GroupAccess, OtherAccess;
  533. //
  534. // Get the security descriptor for the file.
  535. //
  536. SecurityInformation = OWNER_SECURITY_INFORMATION |
  537. GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
  538. //
  539. // First try a guess at the necessary descriptor size.
  540. //
  541. LengthNeeded = 2048;
  542. SecurityDescriptor = RtlAllocateHeap(PsxHeap, 0, LengthNeeded);
  543. if (NULL == SecurityDescriptor) {
  544. return;
  545. }
  546. st = NtQuerySecurityObject(FileHandle, SecurityInformation,
  547. SecurityDescriptor, LengthNeeded, &LengthNeeded);
  548. if (STATUS_BUFFER_TOO_SMALL == st) {
  549. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  550. SecurityDescriptor = RtlAllocateHeap(PsxHeap, 0, LengthNeeded);
  551. if (NULL == SecurityDescriptor) {
  552. return;
  553. }
  554. st = NtQuerySecurityObject(FileHandle, SecurityInformation,
  555. SecurityDescriptor, LengthNeeded, &LengthNeeded);
  556. if (!NT_SUCCESS(st)) {
  557. KdPrint(("PSXSS: FindOwnerModeFile: NtQsObj: 0x%x\n",
  558. st));
  559. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  560. return;
  561. }
  562. } else if (!NT_SUCCESS(st)) {
  563. return;
  564. }
  565. ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor));
  566. //
  567. // Get the owner and group from the security descriptor
  568. //
  569. st = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
  570. &NtOwner, &OwnerDefaulted);
  571. if (!NT_SUCCESS(st)) {
  572. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  573. return;
  574. }
  575. st = RtlGetGroupSecurityDescriptor(SecurityDescriptor,
  576. &NtGroup, &GroupDefaulted);
  577. ASSERT(NT_SUCCESS(st));
  578. if (NULL == NtOwner || NULL == NtGroup) {
  579. //
  580. // Seems like this file doesn't have an owner or a
  581. // group. Would like to say that it's owned by 'world'
  582. // or somesuch.
  583. //
  584. StatBuf->st_uid = 0;
  585. StatBuf->st_gid = 0;
  586. //
  587. // Since we don't know who owns the file, we can't
  588. // figure out what permissions we have on it. Say
  589. // that all access is granted. We may be lying.
  590. //
  591. StatBuf->st_mode |= _S_PROT;
  592. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  593. return;
  594. }
  595. //
  596. // Translate Nt uid and gid to Posix recognizable form
  597. // and set StatBuf->st_uid and StatBuf->st_gid.
  598. //
  599. ASSERT(RtlValidSid(NtOwner));
  600. ASSERT(RtlValidSid(NtGroup));
  601. StatBuf->st_uid = MakePosixId(NtOwner);
  602. StatBuf->st_gid = MakePosixId(NtGroup);
  603. ASSERT(RtlValidSecurityDescriptor(SecurityDescriptor));
  604. st = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
  605. &AclPresent, &pAcl, &AclDefaulted);
  606. if (!NT_SUCCESS(st)) {
  607. KdPrint(("PSXSS: RtlGetDaclSD: 0x%x\n", st));
  608. }
  609. ASSERT(NT_SUCCESS(st));
  610. if (!AclPresent || (AclPresent && NULL == pAcl)) {
  611. // All access is granted.
  612. StatBuf->st_mode |= _S_PROT;
  613. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  614. return;
  615. }
  616. //
  617. // We have a Dacl
  618. //
  619. ASSERT(RtlValidAcl(pAcl));
  620. st = RtlInterpretPosixAcl(ACL_REVISION2, NtOwner, NtGroup,
  621. pAcl, &UserAccess, &GroupAccess, &OtherAccess);
  622. if (!NT_SUCCESS(st)) {
  623. //
  624. // XXX.mjb: The Acl is not a Posix acl. It might be nice to
  625. // return an error or somesuch.
  626. //
  627. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  628. return;
  629. }
  630. RtlFreeHeap(PsxHeap, 0, (PVOID)SecurityDescriptor);
  631. StatBuf->st_mode |= AccessMaskToMode(UserAccess, GroupAccess,
  632. OtherAccess);
  633. }