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.

981 lines
24 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. blio.c
  5. Abstract:
  6. This module contains the code that implements the switch function for
  7. I/O operations between then operating system loader, the target file
  8. system, and the target device.
  9. Author:
  10. David N. Cutler (davec) 10-May-1991
  11. Revision History:
  12. --*/
  13. #include "bootlib.h"
  14. #include "stdio.h"
  15. //
  16. // Define file table.
  17. //
  18. BL_FILE_TABLE BlFileTable[BL_FILE_TABLE_SIZE];
  19. #if DBG
  20. ULONG BlFilesOpened = 0;
  21. #endif
  22. #ifdef CACHE_DEVINFO
  23. //
  24. // Device close notification routines, are registered by the file system
  25. // which are interested in device close events. This is primarily used for
  26. // invalidating the internal cache, which the file system maintains
  27. // using DeviceId as one of the keys
  28. //
  29. PARC_DEVICE_CLOSE_NOTIFICATION DeviceCloseNotify[MAX_DEVICE_CLOSE_NOTIFICATION_SIZE] = {0};
  30. //
  31. // Device to filesystem cache table
  32. //
  33. DEVICE_TO_FILESYS DeviceFSCache[BL_FILE_TABLE_SIZE];
  34. ARC_STATUS
  35. ArcCacheClose(
  36. IN ULONG DeviceId
  37. )
  38. /*++
  39. Routine Description:
  40. This routine invalidates the file system information
  41. cached for the given device ID.
  42. Arguments:
  43. DeviceId : Device to close
  44. Return Value:
  45. ESUCCESS is returned if the close is successful. Otherwise,
  46. return an unsuccessful status.
  47. --*/
  48. {
  49. ULONG Index;
  50. //
  51. // Notify all the registered file system about the device close
  52. //
  53. for (Index = 0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
  54. if (DeviceCloseNotify[Index]) {
  55. (DeviceCloseNotify[Index])(DeviceId);
  56. }
  57. }
  58. //
  59. // Update device to file system cache
  60. //
  61. for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index++) {
  62. if (DeviceFSCache[Index].DeviceId == DeviceId){
  63. DeviceFSCache[Index].DeviceId = UNINITIALIZED_DEVICE_ID;
  64. }
  65. }
  66. return ((FIRMWARE_VECTOR_BLOCK->CloseRoutine)(DeviceId));
  67. }
  68. ARC_STATUS
  69. ArcRegisterForDeviceClose(
  70. PARC_DEVICE_CLOSE_NOTIFICATION FlushRoutine
  71. )
  72. {
  73. ARC_STATUS Status = EINVAL;
  74. if (FlushRoutine) {
  75. ULONG Index;
  76. Status = ENOENT;
  77. for (Index=0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
  78. if (!DeviceCloseNotify[Index]) {
  79. DeviceCloseNotify[Index] = FlushRoutine;
  80. Status = ESUCCESS;
  81. break;
  82. }
  83. }
  84. }
  85. return Status;
  86. }
  87. ARC_STATUS
  88. ArcDeRegisterForDeviceClose(
  89. PARC_DEVICE_CLOSE_NOTIFICATION FlushRoutine
  90. )
  91. {
  92. ARC_STATUS Status = EINVAL;
  93. if (FlushRoutine) {
  94. ULONG Index;
  95. Status = ENOENT;
  96. for (Index=0; Index < MAX_DEVICE_CLOSE_NOTIFICATION_SIZE; Index++) {
  97. if (DeviceCloseNotify[Index] == FlushRoutine) {
  98. DeviceCloseNotify[Index] = NULL;
  99. Status = ESUCCESS;
  100. break;
  101. }
  102. }
  103. }
  104. return Status;
  105. }
  106. #endif // CACHE_DEVINFO
  107. ARC_STATUS
  108. BlIoInitialize (
  109. VOID
  110. )
  111. /*++
  112. Routine Description:
  113. This routine initializes the file table used by the OS loader and
  114. initializes the boot loader filesystems.
  115. Arguments:
  116. None.
  117. Return Value:
  118. ESUCCESS is returned if the initialization is successful. Otherwise,
  119. return an unsuccessful status.
  120. --*/
  121. {
  122. ULONG Index;
  123. ARC_STATUS Status;
  124. #ifdef CACHE_DEVINFO
  125. RtlZeroMemory(DeviceCloseNotify, sizeof(DeviceCloseNotify));
  126. #endif
  127. //
  128. // Initialize the file table.
  129. //
  130. for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index += 1) {
  131. BlFileTable[Index].Flags.Open = 0;
  132. BlFileTable[Index].StructureContext = NULL;
  133. #ifdef CACHE_DEVINFO
  134. DeviceFSCache[Index].DeviceId = UNINITIALIZED_DEVICE_ID;
  135. DeviceFSCache[Index].Context = NULL;
  136. DeviceFSCache[Index].DevMethods = NULL;
  137. #endif // for CACHE_DEVINFO
  138. }
  139. if((Status = NetInitialize()) != ESUCCESS) {
  140. return Status;
  141. }
  142. if((Status = FatInitialize()) != ESUCCESS) {
  143. return Status;
  144. }
  145. if((Status = NtfsInitialize()) != ESUCCESS) {
  146. return Status;
  147. }
  148. #ifndef DONT_USE_UDF
  149. if((Status = UDFSInitialize()) != ESUCCESS) {
  150. return Status;
  151. }
  152. #endif
  153. if((Status = CdfsInitialize()) != ESUCCESS) {
  154. return Status;
  155. }
  156. return ESUCCESS;
  157. }
  158. PBOOTFS_INFO
  159. BlGetFsInfo(
  160. IN ULONG DeviceId
  161. )
  162. /*++
  163. Routine Description:
  164. Returns filesystem information for the filesystem on the specified device
  165. Arguments:
  166. FileId - Supplies the file table index of the device
  167. Return Value:
  168. PBOOTFS_INFO - Pointer to the BOOTFS_INFO structure for the filesystem
  169. NULL - unknown filesystem
  170. --*/
  171. {
  172. FS_STRUCTURE_CONTEXT FsStructure;
  173. PBL_DEVICE_ENTRY_TABLE Table;
  174. if ((Table = IsNetFileStructure(DeviceId, &FsStructure)) != NULL) {
  175. return(Table->BootFsInfo);
  176. }
  177. if ((Table = IsFatFileStructure(DeviceId, &FsStructure)) != NULL) {
  178. return(Table->BootFsInfo);
  179. }
  180. if ((Table = IsNtfsFileStructure(DeviceId, &FsStructure)) != NULL) {
  181. return(Table->BootFsInfo);
  182. }
  183. if ((Table = IsCdfsFileStructure(DeviceId, &FsStructure)) != NULL) {
  184. return(Table->BootFsInfo);
  185. }
  186. return(NULL);
  187. }
  188. ARC_STATUS
  189. BlClose (
  190. IN ULONG FileId
  191. )
  192. /*++
  193. Routine Description:
  194. This function closes a file or a device that is open.
  195. Arguments:
  196. FileId - Supplies the file table index.
  197. Return Value:
  198. If the specified file is open, then a close is attempted and
  199. the status of the operation is returned. Otherwise, return an
  200. unsuccessful status.
  201. --*/
  202. {
  203. //
  204. // If the file is open, then attempt to close it. Otherwise return an
  205. // access error.
  206. //
  207. if (BlFileTable[FileId].Flags.Open == 1) {
  208. return (BlFileTable[FileId].DeviceEntryTable->Close)(FileId);
  209. } else {
  210. return EACCES;
  211. }
  212. }
  213. ARC_STATUS
  214. BlMount (
  215. IN PCHAR MountPath,
  216. IN MOUNT_OPERATION Operation
  217. )
  218. /*++
  219. Routine Description:
  220. Arguments:
  221. Return Value:
  222. --*/
  223. {
  224. UNREFERENCED_PARAMETER(MountPath);
  225. UNREFERENCED_PARAMETER(Operation);
  226. return ESUCCESS;
  227. }
  228. ARC_STATUS
  229. _BlOpen (
  230. IN ULONG DeviceId,
  231. IN PCHAR OpenPath,
  232. IN OPEN_MODE OpenMode,
  233. OUT PULONG FileId
  234. )
  235. /*++
  236. Routine Description:
  237. This function opens a file on the specified device. The type of file
  238. system is automatically recognized.
  239. Arguments:
  240. DeviceId - Supplies the file table index of the device.
  241. OpenPath - Supplies a pointer to the name of the file to be opened.
  242. OpenMode - Supplies the mode of the open.
  243. FileId - Supplies a pointer to a variable that receives the file
  244. table index of the open file.
  245. Return Value:
  246. If a free file table entry is available and the file structure on
  247. the specified device is recognized, then an open is attempted and
  248. the status of the operation is returned. Otherwise, return an
  249. unsuccessful status.
  250. --*/
  251. {
  252. ULONG Index;
  253. FS_STRUCTURE_CONTEXT FsStructureTemp;
  254. ULONG ContextSize;
  255. ARC_STATUS Status;
  256. #ifdef CACHE_DEVINFO
  257. ULONG CacheIndex;
  258. for (CacheIndex = 0; CacheIndex < BL_FILE_TABLE_SIZE; CacheIndex++) {
  259. if (DeviceFSCache[CacheIndex].DeviceId == DeviceId){
  260. break;
  261. }
  262. }
  263. #endif // for CACHE_DEVINFO
  264. //
  265. // Search for a free file table entry.
  266. //
  267. for (Index = 0; Index < BL_FILE_TABLE_SIZE; Index += 1) {
  268. if (BlFileTable[Index].Flags.Open == 0) {
  269. #ifdef CACHE_DEVINFO
  270. if (CacheIndex >= BL_FILE_TABLE_SIZE) {
  271. #endif // for CACHE_DEVINFO
  272. //
  273. // Attempt to recognize the file system on the specified
  274. // device. If no one recognizes it then return an unsuccessful
  275. // status.
  276. //
  277. if ((BlFileTable[Index].DeviceEntryTable =
  278. IsNetFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  279. ContextSize = sizeof(NET_STRUCTURE_CONTEXT);
  280. } else if ((BlFileTable[Index].DeviceEntryTable =
  281. IsFatFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  282. ContextSize = sizeof(FAT_STRUCTURE_CONTEXT);
  283. } else if ((BlFileTable[Index].DeviceEntryTable =
  284. IsNtfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  285. ContextSize = sizeof(NTFS_STRUCTURE_CONTEXT);
  286. #ifndef DONT_USE_UDF
  287. } else if ((BlFileTable[Index].DeviceEntryTable =
  288. IsUDFSFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  289. ContextSize = sizeof(UDFS_STRUCTURE_CONTEXT);
  290. #endif
  291. #if defined(ELTORITO)
  292. //
  293. // This must go before the check for Cdfs; otherwise Cdfs will be detected.
  294. // Since BIOS calls already set up to use EDDS, reads will succeed, and checks
  295. // against ISO will succeed. We check El Torito-specific fields here as well as ISO
  296. //
  297. } else if ((BlFileTable[Index].DeviceEntryTable =
  298. IsEtfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  299. ContextSize = sizeof(ETFS_STRUCTURE_CONTEXT);
  300. #endif
  301. } else if ((BlFileTable[Index].DeviceEntryTable =
  302. IsCdfsFileStructure(DeviceId, &FsStructureTemp)) != NULL) {
  303. ContextSize = sizeof(CDFS_STRUCTURE_CONTEXT);
  304. } else {
  305. return EACCES;
  306. }
  307. #ifndef CACHE_DEVINFO
  308. //
  309. // Cut down on the amount of heap we use by attempting to reuse
  310. // the fs structure context instead of always allocating a
  311. // new one. The NTFS structure context is over 4K; the FAT one
  312. // is almost 2K. In the setup case we're loading dozens of files.
  313. // Add in compression, where diamond may open each file multiple
  314. // times, and we waste a lot of heap.
  315. //
  316. if(BlFileTable[Index].StructureContext == NULL) {
  317. BlFileTable[Index].StructureContext = BlAllocateHeap(sizeof(FS_STRUCTURE_CONTEXT));
  318. if(BlFileTable[Index].StructureContext == NULL) {
  319. return ENOMEM;
  320. }
  321. RtlZeroMemory(BlFileTable[Index].StructureContext, sizeof(FS_STRUCTURE_CONTEXT));
  322. }
  323. RtlCopyMemory(
  324. BlFileTable[Index].StructureContext,
  325. &FsStructureTemp,
  326. ContextSize
  327. );
  328. #else
  329. //
  330. // save the collected info in cache for future use
  331. //
  332. for (CacheIndex = 0; CacheIndex < BL_FILE_TABLE_SIZE; CacheIndex++) {
  333. if (DeviceFSCache[CacheIndex].DeviceId == UNINITIALIZED_DEVICE_ID){
  334. PVOID Context = DeviceFSCache[CacheIndex].Context;
  335. DeviceFSCache[CacheIndex].DeviceId = DeviceId;
  336. //
  337. // Cut down on the amount of heap we use by attempting to reuse
  338. // the fs structure context instead of always allocating a
  339. // new one. The NTFS structure context is over 4K; the FAT one
  340. // is almost 2K. In the setup case we're loading dozens of files.
  341. // Add in compression, where diamond may open each file multiple
  342. // times, and we waste a lot of heap.
  343. //
  344. if(Context == NULL) {
  345. Context = BlAllocateHeap(sizeof(FS_STRUCTURE_CONTEXT));
  346. if(Context == NULL) {
  347. DeviceFSCache[CacheIndex].DeviceId = UNINITIALIZED_DEVICE_ID;
  348. return ENOMEM;
  349. }
  350. RtlZeroMemory(Context, sizeof(FS_STRUCTURE_CONTEXT));
  351. DeviceFSCache[CacheIndex].Context = Context;
  352. }
  353. RtlCopyMemory(Context,
  354. &FsStructureTemp,
  355. ContextSize);
  356. BlFileTable[Index].StructureContext = Context;
  357. //
  358. // save the device table from the filetable entry
  359. //
  360. DeviceFSCache[CacheIndex].DevMethods = BlFileTable[Index].DeviceEntryTable;
  361. break;
  362. }
  363. }
  364. if (CacheIndex >= BL_FILE_TABLE_SIZE)
  365. return ENOSPC;
  366. } else {
  367. #if 0
  368. {
  369. char Msg[128] = {0};
  370. BlPositionCursor(1, 5);
  371. sprintf(Msg,
  372. "Using %d cached info %p, %p for device %d, %s",
  373. CacheIndex,
  374. DeviceFSCache[CacheIndex].Context,
  375. DeviceFSCache[CacheIndex].DevMethods,
  376. DeviceFSCache[CacheIndex].DeviceId,
  377. OpenPath);
  378. BlPrint(" ");
  379. BlPositionCursor(1, 5);
  380. BlPrint(Msg);
  381. }
  382. #endif
  383. //
  384. // Reuse the already cached entry
  385. //
  386. BlFileTable[Index].DeviceEntryTable = DeviceFSCache[CacheIndex].DevMethods;
  387. BlFileTable[Index].StructureContext = DeviceFSCache[CacheIndex].Context;
  388. }
  389. #endif // for ! CACHE_DEVINFO
  390. //
  391. // Someone has mounted the volume so now attempt to open the file.
  392. //
  393. *FileId = Index;
  394. BlFileTable[Index].DeviceId = DeviceId;
  395. Status = EBADF;
  396. #if DBG
  397. //
  398. // Check and see if a user wants to replace this binary
  399. // via a transfer through the kernel debugger. If this
  400. // fails just continue on with the existing file.
  401. //
  402. if( BdDebuggerEnabled ) {
  403. Status = BdPullRemoteFile( OpenPath,
  404. FILE_ATTRIBUTE_NORMAL,
  405. FILE_OVERWRITE_IF,
  406. FILE_SYNCHRONOUS_IO_NONALERT,
  407. *FileId );
  408. if( Status == ESUCCESS ) {
  409. DbgPrint( "BlLoadImageEx: Pulled %s from Kernel Debugger\r\n", OpenPath );
  410. //
  411. // Make absolutely sure we don't reuse this device filesystem cache
  412. // entry because we've piggybacked on the net filesystem to bring
  413. // the kdfile over the serial point. That means we really don't
  414. // want to reuse this entry unless we're booting off the net, in which
  415. // case we'll take the perf hit (slight) on DBG builds.
  416. //
  417. #ifdef CACHE_DEVINFO
  418. DeviceFSCache[*FileId].DeviceId = UNINITIALIZED_DEVICE_ID;
  419. #endif
  420. }
  421. }
  422. #endif
  423. if( Status != ESUCCESS ) {
  424. Status = (BlFileTable[Index].DeviceEntryTable->Open)(OpenPath,
  425. OpenMode,
  426. FileId);
  427. }
  428. return(Status);
  429. }
  430. }
  431. //
  432. // No free file table entry could be found.
  433. //
  434. return EACCES;
  435. }
  436. ARC_STATUS
  437. BlOpen (
  438. IN ULONG DeviceId,
  439. IN PCHAR OpenPath,
  440. IN OPEN_MODE OpenMode,
  441. OUT PULONG FileId
  442. )
  443. /*++
  444. Routine Description:
  445. Wrapper routine for BlOpen that attempts to locate the compressed
  446. form of a filename before trying to locate the filename itself.
  447. Callers need not know or care that a file x.exe actually exists
  448. as a compressed file x.ex_. If the file is being opened for
  449. read-only access and the decompressor indicates that it wants
  450. to try locating the compressed form of the file, we transparently
  451. locate that one instead of the one requested.
  452. Arguments:
  453. Same as _BlOpen().
  454. Return Value:
  455. Same as _BlOpen().
  456. --*/
  457. {
  458. CHAR CompressedName[256];
  459. ARC_STATUS Status;
  460. if((OpenMode == ArcOpenReadOnly) && DecompGenerateCompressedName(OpenPath,CompressedName)) {
  461. //
  462. // Attempt to locate the compressed form of the filename.
  463. //
  464. Status = _BlOpen(DeviceId,CompressedName,OpenMode,FileId);
  465. if(Status == ESUCCESS) {
  466. Status = DecompPrepareToReadCompressedFile(CompressedName,*FileId);
  467. if(Status == (ARC_STATUS)(-1)) {
  468. //
  469. // This is a special status indicating that the file is not
  470. // to be processed for decompression. This typically happens
  471. // when the decompressor opens the file to read the compressed
  472. // data out of it.
  473. //
  474. Status = ESUCCESS;
  475. #if DBG
  476. BlFilesOpened++;
  477. #endif
  478. }
  479. return(Status);
  480. }
  481. }
  482. Status = (_BlOpen(DeviceId,OpenPath,OpenMode,FileId));
  483. #if DBG
  484. if (Status == ESUCCESS)
  485. BlFilesOpened++;
  486. #endif
  487. return Status;
  488. }
  489. ARC_STATUS
  490. BlRead (
  491. IN ULONG FileId,
  492. OUT PVOID Buffer,
  493. IN ULONG Length,
  494. OUT PULONG Count
  495. )
  496. /*++
  497. Routine Description:
  498. This function reads from a file or a device that is open.
  499. Arguments:
  500. FileId - Supplies the file table index.
  501. Buffer - Supplies a pointer to the buffer that receives the data
  502. read.
  503. Length - Supplies the number of bytes that are to be read.
  504. Count - Supplies a pointer to a variable that receives the number of
  505. bytes actually transfered.
  506. Return Value:
  507. If the specified file is open for read, then a read is attempted
  508. and the status of the operation is returned. Otherwise, return an
  509. unsuccessful status.
  510. --*/
  511. {
  512. //
  513. // If the file is open for read, then attempt to read from it. Otherwise
  514. // return an access error.
  515. //
  516. if ((BlFileTable[FileId].Flags.Open == 1) &&
  517. (BlFileTable[FileId].Flags.Read == 1)) {
  518. return (BlFileTable[FileId].DeviceEntryTable->Read)(FileId,
  519. Buffer,
  520. Length,
  521. Count);
  522. } else {
  523. return EACCES;
  524. }
  525. }
  526. ARC_STATUS
  527. BlReadAtOffset(
  528. IN ULONG FileId,
  529. IN ULONG Offset,
  530. IN ULONG Length,
  531. OUT PVOID Data
  532. )
  533. /*++
  534. Routine Description:
  535. This routine seeks to the proper place in FileId and extracts Length bytes of data into
  536. Data.
  537. Arguments:
  538. FileId - Supplies the file id where read operations are to be performed.
  539. Offset - The absolute byte offset to start reading at.
  540. Length - The number of bytes to read.
  541. Data - Buffer to hold the read results.
  542. --*/
  543. {
  544. ARC_STATUS Status;
  545. LARGE_INTEGER LargeOffset;
  546. ULONG Count;
  547. LargeOffset.HighPart = 0;
  548. LargeOffset.LowPart = Offset;
  549. Status = BlSeek(FileId, &LargeOffset, SeekAbsolute);
  550. if (Status != ESUCCESS) {
  551. return Status;
  552. }
  553. Status = BlRead(FileId, Data, Length, &Count);
  554. if ((Status == ESUCCESS) && (Count != Length)) {
  555. return EINVAL;
  556. }
  557. return Status;
  558. }
  559. ARC_STATUS
  560. BlGetReadStatus (
  561. IN ULONG FileId
  562. )
  563. /*++
  564. Routine Description:
  565. Arguments:
  566. Return Value:
  567. --*/
  568. {
  569. UNREFERENCED_PARAMETER( FileId );
  570. return ESUCCESS;
  571. }
  572. ARC_STATUS
  573. BlSeek (
  574. IN ULONG FileId,
  575. IN PLARGE_INTEGER Offset,
  576. IN SEEK_MODE SeekMode
  577. )
  578. /*++
  579. Routine Description:
  580. Arguments:
  581. Return Value:
  582. If the specified file is open, then a seek is attempted and
  583. the status of the operation is returned. Otherwise, return an
  584. unsuccessful status.
  585. --*/
  586. {
  587. //
  588. // If the file is open, then attempt to seek on it. Otherwise return an
  589. // access error.
  590. //
  591. if (BlFileTable[FileId].Flags.Open == 1) {
  592. return (BlFileTable[FileId].DeviceEntryTable->Seek)(FileId,
  593. Offset,
  594. SeekMode);
  595. } else {
  596. return EACCES;
  597. }
  598. }
  599. ARC_STATUS
  600. BlWrite (
  601. IN ULONG FileId,
  602. IN PVOID Buffer,
  603. IN ULONG Length,
  604. OUT PULONG Count
  605. )
  606. /*++
  607. Routine Description:
  608. Arguments:
  609. Return Value:
  610. --*/
  611. {
  612. //
  613. // If the file is open for write, then attempt to write to it. Otherwise
  614. // return an access error.
  615. //
  616. if ((BlFileTable[FileId].Flags.Open == 1) &&
  617. (BlFileTable[FileId].Flags.Write == 1)) {
  618. return (BlFileTable[FileId].DeviceEntryTable->Write)(FileId,
  619. Buffer,
  620. Length,
  621. Count);
  622. } else {
  623. return EACCES;
  624. }
  625. }
  626. ARC_STATUS
  627. BlGetFileInformation (
  628. IN ULONG FileId,
  629. IN PFILE_INFORMATION FileInformation
  630. )
  631. /*++
  632. Routine Description:
  633. Arguments:
  634. Return Value:
  635. --*/
  636. {
  637. //
  638. // If the file is open, then attempt to get file information. Otherwise
  639. // return an access error.
  640. //
  641. if (BlFileTable[FileId].Flags.Open == 1) {
  642. return (BlFileTable[FileId].DeviceEntryTable->GetFileInformation)(FileId,
  643. FileInformation);
  644. } else {
  645. return EACCES;
  646. }
  647. }
  648. ARC_STATUS
  649. BlSetFileInformation (
  650. IN ULONG FileId,
  651. IN ULONG AttributeFlags,
  652. IN ULONG AttributeMask
  653. )
  654. /*++
  655. Routine Description:
  656. Arguments:
  657. Return Value:
  658. --*/
  659. {
  660. //
  661. // If the file is open, then attempt to Set file information. Otherwise
  662. // return an access error.
  663. //
  664. if (BlFileTable[FileId].Flags.Open == 1) {
  665. return (BlFileTable[FileId].DeviceEntryTable->SetFileInformation)(FileId,
  666. AttributeFlags,
  667. AttributeMask);
  668. } else {
  669. return EACCES;
  670. }
  671. }
  672. ARC_STATUS
  673. BlRename(
  674. IN ULONG FileId,
  675. IN PCHAR NewName
  676. )
  677. /*++
  678. Routine Description:
  679. Rename an open file or directory.
  680. Arguments:
  681. FileId - supplies a handle to an open file or directory. The file
  682. need not be open for write access.
  683. NewName - New name to give the file or directory (filename part only).
  684. Return Value:
  685. Status indicating result of the operation.
  686. --*/
  687. {
  688. if(BlFileTable[FileId].Flags.Open == 1) {
  689. return(BlFileTable[FileId].DeviceEntryTable->Rename(FileId,
  690. NewName
  691. )
  692. );
  693. } else {
  694. return(EACCES);
  695. }
  696. }