memory.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. memory.c
  9. Abstract:
  10. This module implements memory management routines.
  11. Author:
  12. Chris Stevens 6-Mar-2014
  13. Environment:
  14. User Mode C Library
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "libcp.h"
  20. #include <assert.h>
  21. #include <errno.h>
  22. #include <fcntl.h>
  23. #include <paths.h>
  24. #include <sys/ipc.h>
  25. #include <sys/mman.h>
  26. #include <sys/shm.h>
  27. #include <sys/stat.h>
  28. //
  29. // ---------------------------------------------------------------- Definitions
  30. //
  31. //
  32. // ------------------------------------------------------ Data Type Definitions
  33. //
  34. //
  35. // ----------------------------------------------- Internal Function Prototypes
  36. //
  37. KSTATUS
  38. ClpOpenSharedMemoryObject (
  39. HANDLE Directory,
  40. PCSTR Path,
  41. ULONG PathLength,
  42. ULONG Flags,
  43. FILE_PERMISSIONS CreatePermissions,
  44. PHANDLE Handle
  45. );
  46. //
  47. // -------------------------------------------------------------------- Globals
  48. //
  49. //
  50. // ------------------------------------------------------------------ Functions
  51. //
  52. LIBC_API
  53. void *
  54. mmap (
  55. void *Address,
  56. size_t Length,
  57. int ProtectionFlags,
  58. int MapFlags,
  59. int FileDescriptor,
  60. off_t Offset
  61. )
  62. /*++
  63. Routine Description:
  64. This routine maps the given file or memory object into the current process'
  65. address space.
  66. Arguments:
  67. Address - Supplies an optional suggested virtual address for the mapping.
  68. If MAP_FIXED is supplied then the routine attempts to create the
  69. mapping at the exact address supplied.
  70. Length - Supplies the length, in bytes, of the region to map.
  71. ProtectionFlags - Supplies a set of flags ORed together. See PROT_* for
  72. definitions.
  73. MapFlags - Supplies a set of flags ORed together. See MAP_* for definitions.
  74. FileDescriptor - Supplies the file descriptor of the file or memory object
  75. to map.
  76. Offset - Supplies the offset, in bytes, within the file or memory object
  77. where the mapping should begin.
  78. Return Value:
  79. Returns the address where the mapping was made on sucess.
  80. MAP_FAILED on failure. The errno variable will be set to indicate the error.
  81. --*/
  82. {
  83. PVOID MappedAddress;
  84. ULONG OsMapFlags;
  85. KSTATUS Status;
  86. MappedAddress = MAP_FAILED;
  87. OsMapFlags = 0;
  88. //
  89. // Convert the protection flags to the OS flags.
  90. //
  91. if ((ProtectionFlags & PROT_READ) != 0) {
  92. OsMapFlags |= SYS_MAP_FLAG_READ;
  93. }
  94. if ((ProtectionFlags & PROT_WRITE) != 0) {
  95. OsMapFlags |= SYS_MAP_FLAG_WRITE;
  96. }
  97. if ((ProtectionFlags & PROT_EXEC) != 0) {
  98. OsMapFlags |= SYS_MAP_FLAG_EXECUTE;
  99. }
  100. //
  101. // Convert the mapping flags to OS flags. One of MAP_SHARED or MAP_PRIVATE
  102. // must be supplied, but not both.
  103. //
  104. if ((MapFlags & MAP_SHARED) != 0) {
  105. if ((MapFlags & MAP_PRIVATE) != 0) {
  106. errno = EINVAL;
  107. goto mmapEnd;
  108. }
  109. OsMapFlags |= SYS_MAP_FLAG_SHARED;
  110. } else if ((MapFlags & MAP_PRIVATE) == 0) {
  111. errno = EINVAL;
  112. goto mmapEnd;
  113. }
  114. if ((MapFlags & MAP_FIXED) != 0) {
  115. OsMapFlags |= SYS_MAP_FLAG_FIXED;
  116. }
  117. if ((MapFlags & MAP_ANONYMOUS) != 0) {
  118. OsMapFlags |= SYS_MAP_FLAG_ANONYMOUS;
  119. }
  120. if (Length == 0) {
  121. errno = EINVAL;
  122. goto mmapEnd;
  123. }
  124. Status = OsMemoryMap((HANDLE)(UINTN)FileDescriptor,
  125. Offset,
  126. Length,
  127. OsMapFlags,
  128. &Address);
  129. if (!KSUCCESS(Status)) {
  130. errno = ClConvertKstatusToErrorNumber(Status);
  131. goto mmapEnd;
  132. }
  133. MappedAddress = Address;
  134. mmapEnd:
  135. return MappedAddress;
  136. }
  137. LIBC_API
  138. int
  139. munmap (
  140. void *Address,
  141. size_t Length
  142. )
  143. /*++
  144. Routine Description:
  145. This routine removes any mappings in the the current process' address space
  146. that are within the specified region.
  147. Arguments:
  148. Address - Supplies the start of the address region to unmap.
  149. Length - Supplies the size, in bytes, of the region to unmap.
  150. Return Value:
  151. Returns 0 on success.
  152. -1 on failure. The errno variable will be set to indicate the error.
  153. --*/
  154. {
  155. KSTATUS Status;
  156. Status = OsMemoryUnmap(Address, Length);
  157. if (!KSUCCESS(Status)) {
  158. errno = ClConvertKstatusToErrorNumber(Status);
  159. return -1;
  160. }
  161. return 0;
  162. }
  163. LIBC_API
  164. int
  165. mprotect (
  166. const void *Address,
  167. size_t Length,
  168. int ProtectionFlags
  169. )
  170. /*++
  171. Routine Description:
  172. This routine changes the memory protection attributes for the given region
  173. of memory.
  174. Arguments:
  175. Address - Supplies the starting address (inclusive) to change the memory
  176. protection for. This must be aligned to a page boundary.
  177. Length - Supplies the length, in bytes, of the region to change attributes
  178. for.
  179. ProtectionFlags - Supplies a bitfield of flags describing the desired
  180. attributes of the region. See PROT_* definitions.
  181. Return Value:
  182. 0 on success.
  183. -1 on error, and errno is set to contain more information.
  184. --*/
  185. {
  186. ULONG Flags;
  187. KSTATUS Status;
  188. //
  189. // Convert the protection flags to the OS flags.
  190. //
  191. Flags = 0;
  192. if ((ProtectionFlags & PROT_READ) != 0) {
  193. Flags |= SYS_MAP_FLAG_READ;
  194. }
  195. if ((ProtectionFlags & PROT_WRITE) != 0) {
  196. Flags |= SYS_MAP_FLAG_WRITE;
  197. }
  198. if ((ProtectionFlags & PROT_EXEC) != 0) {
  199. Flags |= SYS_MAP_FLAG_EXECUTE;
  200. }
  201. Status = OsSetMemoryProtection((PVOID)Address, Length, Flags);
  202. if (!KSUCCESS(Status)) {
  203. //
  204. // This routine is supposed to return EAGAIN if there insufficient
  205. // kernel resources.
  206. //
  207. if (Status == STATUS_INSUFFICIENT_RESOURCES) {
  208. Status = STATUS_TRY_AGAIN;
  209. }
  210. errno = ClConvertKstatusToErrorNumber(Status);
  211. return -1;
  212. }
  213. return 0;
  214. }
  215. LIBC_API
  216. int
  217. msync (
  218. const void *Address,
  219. size_t Length,
  220. int Flags
  221. )
  222. /*++
  223. Routine Description:
  224. This routine synchronizes a region of the current process' memory address
  225. space with the permanent storage that backs it. If there is no storage
  226. backing the supplied region, than this routine has no effect.
  227. Arguments:
  228. Address - Supplies the start of the address region to synchronize.
  229. Length - Supplies the size, in bytes, of the region to synchronize.
  230. Flags - Supplies a set of flags ORed together. See MS_* for definitions.
  231. Return Value:
  232. Returns 0 on success.
  233. -1 on failure. The errno variable will be set to indicate the error.
  234. --*/
  235. {
  236. ULONG OsFlags;
  237. KSTATUS Status;
  238. OsFlags = 0;
  239. if ((Flags & MS_ASYNC) != 0) {
  240. if ((Flags & MS_SYNC) != 0) {
  241. errno = EINVAL;
  242. return -1;
  243. }
  244. OsFlags |= SYS_MAP_FLUSH_FLAG_ASYNC;
  245. }
  246. Status = OsMemoryFlush((PVOID)Address, Length, OsFlags);
  247. if (!KSUCCESS(Status)) {
  248. errno = ClConvertKstatusToErrorNumber(Status);
  249. return -1;
  250. }
  251. return 0;
  252. }
  253. LIBC_API
  254. int
  255. shm_open (
  256. const char *Name,
  257. int OpenFlags,
  258. mode_t Mode
  259. )
  260. /*++
  261. Routine Description:
  262. This routine opens a shared memory object and connects it to a file
  263. descriptor.
  264. Arguments:
  265. Name - Supplies a pointer to a null terminated string containing the name
  266. of the shared memory objecet.
  267. OpenFlags - Supplies a set of flags ORed together. See O_* definitions.
  268. Mode - Supplies the permissions mask to set if the shared memory object is
  269. to be created by this call.
  270. Return Value:
  271. Returns a file descriptor on success.
  272. -1 on failure. The errno variable will be set to indicate the error.
  273. --*/
  274. {
  275. FILE_PERMISSIONS CreatePermissions;
  276. HANDLE FileHandle;
  277. ULONG NameLength;
  278. ULONG OsOpenFlags;
  279. KSTATUS Status;
  280. CreatePermissions = 0;
  281. NameLength = RtlStringLength((PSTR)Name) + 1;
  282. OsOpenFlags = 0;
  283. //
  284. // Set the access mask.
  285. //
  286. if ((OpenFlags & O_ACCMODE) == O_RDONLY) {
  287. OsOpenFlags |= SYS_OPEN_FLAG_READ;
  288. } else if ((OpenFlags & O_ACCMODE) == O_RDWR) {
  289. OsOpenFlags |= SYS_OPEN_FLAG_READ | SYS_OPEN_FLAG_WRITE;
  290. } else {
  291. errno = EINVAL;
  292. return -1;
  293. }
  294. if ((OpenFlags & O_TRUNC) != 0) {
  295. OsOpenFlags |= SYS_OPEN_FLAG_TRUNCATE;
  296. }
  297. //
  298. // Set other flags.
  299. //
  300. if ((OpenFlags & O_CREAT) != 0) {
  301. OsOpenFlags |= SYS_OPEN_FLAG_CREATE;
  302. if ((OpenFlags & O_EXCL) != 0) {
  303. OsOpenFlags |= SYS_OPEN_FLAG_FAIL_IF_EXISTS;
  304. }
  305. ASSERT_FILE_PERMISSIONS_EQUIVALENT();
  306. CreatePermissions = Mode;
  307. }
  308. OsOpenFlags |= SYS_OPEN_FLAG_SHARED_MEMORY;
  309. Status = OsOpen(INVALID_HANDLE,
  310. (PSTR)Name,
  311. NameLength,
  312. OsOpenFlags,
  313. CreatePermissions,
  314. &FileHandle);
  315. if (!KSUCCESS(Status)) {
  316. errno = ClConvertKstatusToErrorNumber(Status);
  317. return -1;
  318. }
  319. return (int)(UINTN)FileHandle;
  320. }
  321. LIBC_API
  322. int
  323. shm_unlink (
  324. const char *Name
  325. )
  326. /*++
  327. Routine Description:
  328. This routine removes the shared memory object as identified by the given
  329. name from the namespace of shared memory objects.
  330. Arguments:
  331. Name - Supplies a pointer to the name of the shared memory object to remove.
  332. Return Value:
  333. Returns 0 on success.
  334. -1 on failure. The errno variable will be set to indicate the error.
  335. --*/
  336. {
  337. KSTATUS Status;
  338. Status = OsDelete(INVALID_HANDLE,
  339. (PSTR)Name,
  340. strlen(Name) + 1,
  341. SYS_DELETE_FLAG_SHARED_MEMORY);
  342. if (!KSUCCESS(Status)) {
  343. errno = ClConvertKstatusToErrorNumber(Status);
  344. return -1;
  345. }
  346. return 0;
  347. }
  348. LIBC_API
  349. int
  350. shmget (
  351. key_t Key,
  352. size_t Size,
  353. int Flags
  354. )
  355. /*++
  356. Routine Description:
  357. This routine creates or opens a shared memory object.
  358. Arguments:
  359. Key - Supplies the key associated with the new or existing object to open.
  360. Supply IPC_PRIVATE to always create a new object.
  361. Size - Supplies the minimum number of bytes in the region.
  362. Flags - Supplies a set of flags governing how the region is created. The
  363. bottom nine bits contain permission bits for the region. See IPC_*
  364. definitions for additional flags that can be passed like IPC_CREAT and
  365. IPC_EXCL.
  366. Return Value:
  367. Returns an integer representing the new or existing shared memory object
  368. on success.
  369. -1 on failure, and errno will contain more information.
  370. --*/
  371. {
  372. FILE_PERMISSIONS CreatePermissions;
  373. FILE_CONTROL_PARAMETERS_UNION FileControl;
  374. HANDLE FileHandle;
  375. FILE_PROPERTIES FileProperties;
  376. CHAR Name[14];
  377. INT NameLength;
  378. ULONG OsOpenFlags;
  379. KSTATUS Status;
  380. struct timespec Time;
  381. FileHandle = INVALID_HANDLE;
  382. if (Key == IPC_PRIVATE) {
  383. clock_gettime(CLOCK_MONOTONIC, &Time);
  384. Key = Time.tv_sec ^ Time.tv_nsec;
  385. NameLength = snprintf(Name, sizeof(Name), "shmp_%08x", Key);
  386. } else {
  387. NameLength = snprintf(Name, sizeof(Name), "shm_%08x", Key);
  388. }
  389. CreatePermissions = 0;
  390. NameLength = RtlStringLength((PSTR)Name) + 1;
  391. CreatePermissions = Flags & FILE_PERMISSION_ALL;
  392. OsOpenFlags = SYS_OPEN_FLAG_SHARED_MEMORY |
  393. SYS_OPEN_FLAG_READ | SYS_OPEN_FLAG_WRITE |
  394. SYS_OPEN_FLAG_EXECUTE;
  395. if ((Flags & IPC_CREAT) != 0) {
  396. OsOpenFlags |= SYS_OPEN_FLAG_CREATE;
  397. }
  398. if ((Flags & IPC_EXCL) != 0) {
  399. OsOpenFlags |= SYS_OPEN_FLAG_FAIL_IF_EXISTS;
  400. }
  401. ASSERT_FILE_PERMISSIONS_EQUIVALENT();
  402. Status = ClpOpenSharedMemoryObject(INVALID_HANDLE,
  403. Name,
  404. NameLength,
  405. OsOpenFlags,
  406. CreatePermissions,
  407. &FileHandle);
  408. if (!KSUCCESS(Status)) {
  409. goto shmgetEnd;
  410. }
  411. //
  412. // Get the file information in order to set the size. The size may be
  413. // non-zero if the object already existed, in which case validated that it
  414. // is at least the requested size.
  415. //
  416. FileControl.SetFileInformation.FileProperties = &FileProperties;
  417. Status = OsFileControl(FileHandle,
  418. FileControlCommandGetFileInformation,
  419. &FileControl);
  420. if (!KSUCCESS(Status)) {
  421. goto shmgetEnd;
  422. }
  423. //
  424. // Size the new shared memory object.
  425. //
  426. if ((FileProperties.Size == 0) && (Size != 0)) {
  427. FileProperties.Size = Size;
  428. FileControl.SetFileInformation.FieldsToSet =
  429. FILE_PROPERTY_FIELD_FILE_SIZE;
  430. Status = OsFileControl(FileHandle,
  431. FileControlCommandSetFileInformation,
  432. &FileControl);
  433. if (!KSUCCESS(Status)) {
  434. goto shmgetEnd;
  435. }
  436. } else if (FileProperties.Size < Size) {
  437. Status = STATUS_INVALID_PARAMETER;
  438. goto shmgetEnd;
  439. }
  440. shmgetEnd:
  441. if (!KSUCCESS(Status)) {
  442. errno = ClConvertKstatusToErrorNumber(Status);
  443. if (FileHandle != INVALID_HANDLE) {
  444. OsDelete(INVALID_HANDLE,
  445. Name,
  446. NameLength,
  447. SYS_DELETE_FLAG_SHARED_MEMORY);
  448. OsClose(FileHandle);
  449. }
  450. return -1;
  451. }
  452. return (int)(UINTN)FileHandle;
  453. }
  454. LIBC_API
  455. void *
  456. shmat (
  457. int SharedMemoryObject,
  458. const void *Address,
  459. int Flags
  460. )
  461. /*++
  462. Routine Description:
  463. This routine attaches the current process to the given shared memory object,
  464. and maps it into the process' address space.
  465. Arguments:
  466. SharedMemoryObject - Supplies the value returned from shmget identifying
  467. the shared memory object.
  468. Address - Supplies an optional pointer to the address to map the object at.
  469. Supply NULL to allow the kernel to choose an address. If SHM_RND is
  470. supplied in the flags, this address may be rounded down to the nearest
  471. page. Otherwise, this address must be page aligned.
  472. Flags - Supplies a bitfield of flags governing the mapping.
  473. Return Value:
  474. Returns a pointer to the mapped region on success.
  475. -1 on failure, and errno will be set to contain more information.
  476. --*/
  477. {
  478. PVOID MappedAddress;
  479. ULONG OsMapFlags;
  480. UINTN PageSize;
  481. KSTATUS Status;
  482. MappedAddress = (PVOID)-1;
  483. OsMapFlags = SYS_MAP_FLAG_READ | SYS_MAP_FLAG_SHARED;
  484. if (((Flags & SHM_RND) != 0) && (Address != NULL)) {
  485. PageSize = SHMLBA;
  486. Address = ALIGN_POINTER_DOWN(Address, PageSize);
  487. }
  488. //
  489. // Convert the flags to protection flags.
  490. //
  491. if ((Flags & SHM_EXEC) != 0) {
  492. OsMapFlags |= SYS_MAP_FLAG_EXECUTE;
  493. }
  494. if ((Flags & SHM_RDONLY) == 0) {
  495. OsMapFlags |= SYS_MAP_FLAG_WRITE;
  496. }
  497. if (Address != NULL) {
  498. OsMapFlags |= SYS_MAP_FLAG_FIXED;
  499. }
  500. Status = OsMemoryMap((HANDLE)(UINTN)SharedMemoryObject,
  501. 0,
  502. 0,
  503. OsMapFlags,
  504. (PVOID *)&Address);
  505. if (!KSUCCESS(Status)) {
  506. goto shmatEnd;
  507. }
  508. MappedAddress = (PVOID)Address;
  509. shmatEnd:
  510. if (!KSUCCESS(Status)) {
  511. errno = ClConvertKstatusToErrorNumber(Status);
  512. }
  513. return MappedAddress;
  514. }
  515. LIBC_API
  516. int
  517. shmdt (
  518. const void *Address
  519. )
  520. /*++
  521. Routine Description:
  522. This routine detaches the current process from the shared memory object
  523. mapped at the given address, and unmaps the address.
  524. Arguments:
  525. Address - Supplies a pointer to the base address the shared memory object
  526. is mapped at.
  527. Return Value:
  528. 0 on success. The mapping will no longer be valid.
  529. -1 on failure, and errno will be set to contain more information.
  530. --*/
  531. {
  532. return munmap((void *)Address, 0);
  533. }
  534. LIBC_API
  535. int
  536. shmctl (
  537. int SharedMemoryObject,
  538. int Command,
  539. struct shmid_ds *Buffer
  540. )
  541. /*++
  542. Routine Description:
  543. This routine performs a control function on the given shared memory object.
  544. Arguments:
  545. SharedMemoryObject - Supplies the identifier returned by shmget.
  546. Command - Supplies the control command to execute. See IPC_* definitions.
  547. Buffer - Supplies a pointer to the shared memory information buffer.
  548. Return Value:
  549. 0 on success.
  550. -1 on error, and errno will be set to the stat error information for the
  551. given file path.
  552. --*/
  553. {
  554. KSTATUS Status;
  555. Status = OsUserControl((HANDLE)(UINTN)SharedMemoryObject,
  556. Command,
  557. Buffer,
  558. sizeof(struct shmid_ds));
  559. if (!KSUCCESS(Status)) {
  560. errno = ClConvertKstatusToErrorNumber(Status);
  561. return -1;
  562. }
  563. return 0;
  564. }
  565. LIBC_API
  566. key_t
  567. ftok (
  568. const char *Path,
  569. int ProjectId
  570. )
  571. /*++
  572. Routine Description:
  573. This routine uses the identify of the given file and the least significant
  574. 8 bits of the given project identifier to create a key suitable for use in
  575. the shmget, semget, or msgget functions.
  576. Arguments:
  577. Path - Supplies a pointer to the path to the file whose identity should be
  578. involved in the key ID.
  579. ProjectId - Supplies an identifier whose least significant 8 bits will be
  580. worked into the result.
  581. Return Value:
  582. Returns a key value suitable for use as a parameter to shmget, semget, or
  583. msgget.
  584. -1 on error, and errno will be set to the stat error information for the
  585. given file path.
  586. --*/
  587. {
  588. key_t Result;
  589. struct stat Stat;
  590. if (stat(Path, &Stat) != 0) {
  591. return -1;
  592. }
  593. Result = (Stat.st_ino & 0xFFFF) |
  594. ((Stat.st_dev & 0xFF) << 16) |
  595. ((ProjectId & 0xFF) << 24);
  596. return Result;
  597. }
  598. //
  599. // --------------------------------------------------------- Internal Functions
  600. //
  601. KSTATUS
  602. ClpOpenSharedMemoryObject (
  603. HANDLE Directory,
  604. PCSTR Path,
  605. ULONG PathLength,
  606. ULONG Flags,
  607. FILE_PERMISSIONS CreatePermissions,
  608. PHANDLE Handle
  609. )
  610. /*++
  611. Routine Description:
  612. This routine opens a shared memory object. It may try several times to get
  613. the best possible set of permissions.
  614. Arguments:
  615. Directory - Supplies an optional handle to a directory to start the
  616. search from if the supplied path is relative. Supply INVALID_HANDLE
  617. here to to use the current directory for relative paths.
  618. Path - Supplies a pointer to a string containing the path of the object
  619. to open.
  620. PathLength - Supplies the length of the path buffer, in bytes, including
  621. the null terminator.
  622. Flags - Supplies flags associated with the open operation. See
  623. SYS_OPEN_FLAG_* definitions.
  624. CreatePermissions - Supplies the permissions for create operations.
  625. Handle - Supplies a pointer where a handle will be returned on success.
  626. Return Value:
  627. Status code.
  628. --*/
  629. {
  630. KSTATUS Status;
  631. //
  632. // Open with full permissions. This routine isn't very fast, but then again
  633. // SystemV shared memory objects are pretty crusty and old, and usually
  634. // someone attempting to open them has the proper access.
  635. //
  636. Status = OsOpen(INVALID_HANDLE,
  637. Path,
  638. PathLength,
  639. Flags,
  640. CreatePermissions,
  641. Handle);
  642. if (Status == STATUS_ACCESS_DENIED) {
  643. //
  644. // Try opening without the new and more obscure execute permissions.
  645. //
  646. Flags &= ~SYS_OPEN_FLAG_EXECUTE;
  647. Status = OsOpen(INVALID_HANDLE,
  648. Path,
  649. PathLength,
  650. Flags,
  651. CreatePermissions,
  652. Handle);
  653. if (Status == STATUS_ACCESS_DENIED) {
  654. //
  655. // Okay, things are getting desperate. Try to just open for read.
  656. //
  657. Flags &= ~SYS_OPEN_FLAG_WRITE;
  658. Status = OsOpen(INVALID_HANDLE,
  659. Path,
  660. PathLength,
  661. Flags,
  662. CreatePermissions,
  663. Handle);
  664. }
  665. }
  666. return Status;
  667. }