shmemobj.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. shmemobj.c
  5. Abstract:
  6. This module implements shared memory objects.
  7. Author:
  8. Chris Stevens 12-Mar-2014
  9. Environment:
  10. Kernel
  11. --*/
  12. //
  13. // ------------------------------------------------------------------- Includes
  14. //
  15. #include <minoca/kernel.h>
  16. #include "iop.h"
  17. //
  18. // ---------------------------------------------------------------- Definitions
  19. //
  20. //
  21. // TODO: This doesn't work, as Volume0 is usually a small 10MB boot partition.
  22. // Make shared memory objects work in this case and when the file system is
  23. // all read-only.
  24. //
  25. #define SHARED_MEMORY_OBJECT_DIRECTORY "/Volume/Volume0/temp"
  26. #define SHARED_MEMORY_OBJECT_DIRECTORY_LENGTH \
  27. (RtlStringLength(SHARED_MEMORY_OBJECT_DIRECTORY) + 1)
  28. #define SHARED_MEMORY_OBJECT_FORMAT_STRING "#ShmObject#%x#%d"
  29. #define MAX_SHARED_MEMORY_OBJECT_CREATE_RETRIES 10
  30. //
  31. // ------------------------------------------------------ Data Type Definitions
  32. //
  33. /*++
  34. Structure Description:
  35. This structure defines a shared memory object.
  36. Members:
  37. Header - Stores the object header.
  38. FileObject - Stores a pointer to the file object associated with the shared
  39. memory object.
  40. BackingImage - Stores a handle to the file that backs the shared memory
  41. object.
  42. --*/
  43. typedef struct _SHARED_MEMORY_OBJECT {
  44. OBJECT_HEADER Header;
  45. PFILE_OBJECT FileObject;
  46. PIO_HANDLE BackingImage;
  47. } SHARED_MEMORY_OBJECT, *PSHARED_MEMORY_OBJECT;
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. VOID
  52. IopDestroySharedMemoryObject (
  53. PVOID SharedMemoryObject
  54. );
  55. KSTATUS
  56. IopAddSharedMemoryObjectPathPrefix (
  57. PSTR Path,
  58. ULONG PathLength,
  59. PSTR *NewPath,
  60. PULONG NewPathLength
  61. );
  62. //
  63. // -------------------------------------------------------------------- Globals
  64. //
  65. POBJECT_HEADER IoSharedMemoryObjectDirectory;
  66. //
  67. // ------------------------------------------------------------------ Functions
  68. //
  69. KSTATUS
  70. IopOpenSharedMemoryObject (
  71. PSTR Path,
  72. ULONG PathLength,
  73. ULONG Access,
  74. ULONG Flags,
  75. FILE_PERMISSIONS CreatePermissions,
  76. PIO_HANDLE *Handle
  77. )
  78. /*++
  79. Routine Description:
  80. This routine opens a shared memory objeect.
  81. Arguments:
  82. Path - Supplies a pointer to the path to open.
  83. PathLength - Supplies the length of the path buffer in bytes, including the
  84. null terminator.
  85. Access - Supplies the desired access permissions to the object. See
  86. IO_ACCESS_* definitions.
  87. Flags - Supplies a bitfield of flags governing the behavior of the handle.
  88. See OPEN_FLAG_* definitions.
  89. CreatePermissions - Supplies the permissions to apply for a created file.
  90. Handle - Supplies a pointer where a pointer to the open I/O handle will be
  91. returned on success.
  92. Return Value:
  93. Status code.
  94. --*/
  95. {
  96. PSTR NewPath;
  97. ULONG NewPathLength;
  98. KSTATUS Status;
  99. NewPath = NULL;
  100. //
  101. // Append the appropriate shared memory object path to the given path
  102. // unless the path is empty and it's meant to be an anonymous object.
  103. //
  104. if (PathLength != 0) {
  105. Status = IopAddSharedMemoryObjectPathPrefix(Path,
  106. PathLength,
  107. &NewPath,
  108. &NewPathLength);
  109. if (!KSUCCESS(Status)) {
  110. goto OpenSharedMemoryObjectEnd;
  111. }
  112. Path = NewPath;
  113. PathLength = NewPathLength;
  114. }
  115. //
  116. // With the correct path in place, open the shared memory object.
  117. //
  118. Status = IopOpen(TRUE,
  119. NULL,
  120. Path,
  121. PathLength,
  122. Access,
  123. Flags,
  124. IoObjectSharedMemoryObject,
  125. NULL,
  126. CreatePermissions,
  127. Handle);
  128. if (!KSUCCESS(Status)) {
  129. goto OpenSharedMemoryObjectEnd;
  130. }
  131. OpenSharedMemoryObjectEnd:
  132. if (NewPath != NULL) {
  133. MmFreePagedPool(NewPath);
  134. }
  135. return Status;
  136. }
  137. KSTATUS
  138. IopDeleteSharedMemoryObject (
  139. PSTR Path,
  140. ULONG PathLength
  141. )
  142. /*++
  143. Routine Description:
  144. This routine deletes a shared memory object. It does not handle deletion of
  145. unnamed anonymous shared memory objects.
  146. Arguments:
  147. Path - Supplies a pointer to the path of the shared memory object within
  148. the shared memory object namespace.
  149. PathLength - Supplies the length of the path, in bytes, including the null
  150. terminator.
  151. Return Value:
  152. Status code.
  153. --*/
  154. {
  155. PSTR NewPath;
  156. ULONG NewPathLength;
  157. KSTATUS Status;
  158. NewPath = NULL;
  159. //
  160. // If the supplied path is empty, then fail the delete.
  161. //
  162. if (PathLength == 0) {
  163. Status = STATUS_PATH_NOT_FOUND;
  164. goto DeleteSharedMemroyObjectEnd;
  165. }
  166. //
  167. // Append the appropriate shared memory object path to givn path.
  168. //
  169. Status = IopAddSharedMemoryObjectPathPrefix(Path,
  170. PathLength,
  171. &NewPath,
  172. &NewPathLength);
  173. if (!KSUCCESS(Status)) {
  174. goto DeleteSharedMemroyObjectEnd;
  175. }
  176. //
  177. // With the correct path in place, delete the shared memory object. This
  178. // must be marked as a call from kernel mode even though the delete may
  179. // have come from user mode because the prefix might have created a path
  180. // outside of the calling processes root.
  181. //
  182. Status = IopDelete(TRUE, NULL, NewPath, NewPathLength, 0);
  183. if (!KSUCCESS(Status)) {
  184. goto DeleteSharedMemroyObjectEnd;
  185. }
  186. DeleteSharedMemroyObjectEnd:
  187. if (NewPath != NULL) {
  188. MmFreePagedPool(NewPath);
  189. }
  190. return Status;
  191. }
  192. POBJECT_HEADER
  193. IopGetSharedMemoryObjectDirectory (
  194. VOID
  195. )
  196. /*++
  197. Routine Description:
  198. This routine returns the shared memory objects' root directory in the
  199. object manager's system. This is the only place in the object system
  200. shared memory object creation is allowed.
  201. Arguments:
  202. None.
  203. Return Value:
  204. Returns a pointer to the shared memory object directory.
  205. --*/
  206. {
  207. return IoSharedMemoryObjectDirectory;
  208. }
  209. KSTATUS
  210. IopCreateSharedMemoryObject (
  211. PSTR Name,
  212. ULONG NameSize,
  213. ULONG Flags,
  214. FILE_PERMISSIONS Permissions,
  215. PFILE_OBJECT *FileObject
  216. )
  217. /*++
  218. Routine Description:
  219. This routine actually creates a new shared memory object.
  220. Arguments:
  221. Name - Supplies an optional pointer to the shared memory object name. This
  222. is only used for shared memory objects created in the shared memory
  223. directory.
  224. NameSize - Supplies the size of the name in bytes including the null
  225. terminator.
  226. Flags - Supplies a bitfield of flags governing the behavior of the handle.
  227. See OPEN_FLAG_* definitions.
  228. Permissions - Supplies the permissions to give to the file object.
  229. FileObject - Supplies a pointer where a pointer to a newly created pipe
  230. file object will be returned on success.
  231. Return Value:
  232. Status code.
  233. --*/
  234. {
  235. BOOL Created;
  236. ULONG DirectoryAccess;
  237. PIO_HANDLE DirectoryHandle;
  238. ULONG DirectoryOpenFlags;
  239. PSHARED_MEMORY_OBJECT ExistingObject;
  240. ULONG FileAccess;
  241. PSTR FileName;
  242. ULONG FileNameLength;
  243. ULONG FileOpenFlags;
  244. FILE_PROPERTIES FileProperties;
  245. PIO_HANDLE Handle;
  246. ULONG MaxFileNameLength;
  247. PFILE_OBJECT NewFileObject;
  248. PSHARED_MEMORY_OBJECT NewSharedMemoryObject;
  249. PSTR Path;
  250. ULONG PathLength;
  251. ULONG RetryCount;
  252. KSTATUS Status;
  253. DirectoryHandle = INVALID_HANDLE;
  254. FileName = NULL;
  255. NewFileObject = NULL;
  256. NewSharedMemoryObject = NULL;
  257. Path = NULL;
  258. //
  259. // Create an object manager object. If it is to be immediately unlinked, do
  260. // not give it a name.
  261. //
  262. if ((Flags & OPEN_FLAG_UNLINK_ON_CREATE) != 0) {
  263. Name = NULL;
  264. NameSize = 0;
  265. }
  266. //
  267. // Make sure there is not already an existing shared memory object by the
  268. // same name. The caller should have the appropriate locks to make the
  269. // check and create synchronous.
  270. //
  271. if (Name != NULL) {
  272. ExistingObject = ObFindObject(Name,
  273. NameSize,
  274. IoSharedMemoryObjectDirectory);
  275. if (ExistingObject != NULL) {
  276. ObReleaseReference(ExistingObject);
  277. Status = STATUS_FILE_EXISTS;
  278. goto CreateSharedMemoryObjectEnd;
  279. }
  280. }
  281. NewSharedMemoryObject = ObCreateObject(ObjectSharedMemoryObject,
  282. IoSharedMemoryObjectDirectory,
  283. Name,
  284. NameSize,
  285. sizeof(SHARED_MEMORY_OBJECT),
  286. IopDestroySharedMemoryObject,
  287. 0,
  288. IO_ALLOCATION_TAG);
  289. if (NewSharedMemoryObject == NULL) {
  290. Status = STATUS_INSUFFICIENT_RESOURCES;
  291. goto CreateSharedMemoryObjectEnd;
  292. }
  293. NewSharedMemoryObject->BackingImage = INVALID_HANDLE;
  294. //
  295. // Create a file object, if needed.
  296. //
  297. if (*FileObject == NULL) {
  298. RtlZeroMemory(&FileProperties, sizeof(FILE_PROPERTIES));
  299. IopFillOutFilePropertiesForObject(&FileProperties,
  300. &(NewSharedMemoryObject->Header));
  301. if ((Flags & OPEN_FLAG_UNLINK_ON_CREATE) != 0) {
  302. FileProperties.HardLinkCount = 0;
  303. }
  304. FileProperties.Permissions = Permissions;
  305. FileProperties.BlockSize = IoGetCacheEntryDataSize();
  306. FileProperties.Type = IoObjectSharedMemoryObject;
  307. Status = IopCreateOrLookupFileObject(&FileProperties,
  308. ObGetRootObject(),
  309. FILE_OBJECT_FLAG_EXTERNAL_IO_STATE,
  310. &NewFileObject,
  311. &Created);
  312. if (!KSUCCESS(Status)) {
  313. //
  314. // Release reference taken when filling out the file properties.
  315. //
  316. ObReleaseReference(NewSharedMemoryObject);
  317. NewSharedMemoryObject = NULL;
  318. goto CreateSharedMemoryObjectEnd;
  319. }
  320. ASSERT(Created != FALSE);
  321. *FileObject = NewFileObject;
  322. }
  323. //
  324. // Allocate a buffer that will be used to create the shared memory object's
  325. // backing image's file name.
  326. //
  327. MaxFileNameLength = RtlPrintToString(
  328. NULL,
  329. 0,
  330. CharacterEncodingDefault,
  331. SHARED_MEMORY_OBJECT_FORMAT_STRING,
  332. NewSharedMemoryObject,
  333. MAX_SHARED_MEMORY_OBJECT_CREATE_RETRIES);
  334. FileName = MmAllocatePagedPool(MaxFileNameLength, IO_ALLOCATION_TAG);
  335. if (FileName == NULL) {
  336. Status = STATUS_INSUFFICIENT_RESOURCES;
  337. goto CreateSharedMemoryObjectEnd;
  338. }
  339. //
  340. // Loop trying to create the backing image.
  341. //
  342. DirectoryOpenFlags = OPEN_FLAG_CREATE | OPEN_FLAG_DIRECTORY;
  343. DirectoryAccess = IO_ACCESS_READ | IO_ACCESS_WRITE;
  344. FileOpenFlags = OPEN_FLAG_NON_CACHED |
  345. OPEN_FLAG_CREATE |
  346. OPEN_FLAG_FAIL_IF_EXISTS |
  347. OPEN_FLAG_UNLINK_ON_CREATE;
  348. FileAccess = IO_ACCESS_READ | IO_ACCESS_WRITE;
  349. RetryCount = 0;
  350. while (RetryCount < MAX_SHARED_MEMORY_OBJECT_CREATE_RETRIES) {
  351. //
  352. // Make sure that the shared memory object directory exists.
  353. //
  354. Status = IoOpen(TRUE,
  355. NULL,
  356. SHARED_MEMORY_OBJECT_DIRECTORY,
  357. SHARED_MEMORY_OBJECT_DIRECTORY_LENGTH,
  358. DirectoryAccess,
  359. DirectoryOpenFlags,
  360. FILE_PERMISSION_NONE,
  361. &DirectoryHandle);
  362. if (!KSUCCESS(Status) && (Status != STATUS_FILE_EXISTS)) {
  363. goto CreateSharedMemoryObjectEnd;
  364. }
  365. if (DirectoryHandle != INVALID_HANDLE) {
  366. IoClose(DirectoryHandle);
  367. }
  368. //
  369. // Create the path to the shared memory object's backing image.
  370. //
  371. FileNameLength = RtlPrintToString(FileName,
  372. MaxFileNameLength,
  373. CharacterEncodingDefault,
  374. SHARED_MEMORY_OBJECT_FORMAT_STRING,
  375. NewSharedMemoryObject,
  376. RetryCount);
  377. if (Path != NULL) {
  378. MmFreePagedPool(Path);
  379. Path = NULL;
  380. }
  381. Status = IoPathAppend(SHARED_MEMORY_OBJECT_DIRECTORY,
  382. SHARED_MEMORY_OBJECT_DIRECTORY_LENGTH,
  383. FileName,
  384. FileNameLength,
  385. IO_ALLOCATION_TAG,
  386. &Path,
  387. &PathLength);
  388. if (!KSUCCESS(Status)) {
  389. goto CreateSharedMemoryObjectEnd;
  390. }
  391. Status = IoOpen(TRUE,
  392. NULL,
  393. Path,
  394. PathLength,
  395. FileAccess,
  396. FileOpenFlags,
  397. FILE_PERMISSION_NONE,
  398. &Handle);
  399. //
  400. // If the file already exists or the directroy got removed since it
  401. // was created above, try again.
  402. //
  403. if ((Status == STATUS_FILE_EXISTS) ||
  404. (Status == STATUS_PATH_NOT_FOUND)) {
  405. RetryCount += 1;
  406. continue;
  407. }
  408. if (!KSUCCESS(Status)) {
  409. goto CreateSharedMemoryObjectEnd;
  410. }
  411. break;
  412. }
  413. ASSERT(Handle != INVALID_HANDLE);
  414. NewSharedMemoryObject->BackingImage = Handle;
  415. //
  416. // If the shared memory object is named, then it is valid until it is
  417. // unlinked. So, add a reference to the file object to make sure the create
  418. // premissions stick around.
  419. //
  420. if (Name != NULL) {
  421. IopFileObjectAddReference(*FileObject);
  422. NewSharedMemoryObject->FileObject = *FileObject;
  423. }
  424. (*FileObject)->SpecialIo = NewSharedMemoryObject;
  425. ASSERT(Created != FALSE);
  426. Status = STATUS_SUCCESS;
  427. CreateSharedMemoryObjectEnd:
  428. //
  429. // On both success and failure, the file object's ready event needs to be
  430. // signaled. Other threads may be waiting on the event.
  431. //
  432. if (*FileObject != NULL) {
  433. KeSignalEvent((*FileObject)->ReadyEvent, SignalOptionSignalAll);
  434. }
  435. if (!KSUCCESS(Status)) {
  436. if (NewFileObject != NULL) {
  437. IopFileObjectReleaseReference(NewFileObject);
  438. NewFileObject = NULL;
  439. *FileObject = NULL;
  440. }
  441. if (NewSharedMemoryObject != NULL) {
  442. ObReleaseReference(NewSharedMemoryObject);
  443. }
  444. }
  445. if (Path != NULL) {
  446. MmFreePagedPool(Path);
  447. }
  448. if (FileName != NULL) {
  449. MmFreePagedPool(FileName);
  450. }
  451. return Status;
  452. }
  453. KSTATUS
  454. IopTruncateSharedMemoryObject (
  455. PFILE_OBJECT FileObject
  456. )
  457. /*++
  458. Routine Description:
  459. This routine truncates a shared memory object. It assumes that the file's
  460. lock is held exclusively.
  461. Arguments:
  462. FileObject - Supplies a pointer to the file object that owns the shared
  463. memory object.
  464. Return Value:
  465. Status code.
  466. --*/
  467. {
  468. PIO_HANDLE BackingImage;
  469. PFILE_OBJECT BackingImageObject;
  470. ULONGLONG BackingImageSize;
  471. ULONGLONG FileSize;
  472. PSHARED_MEMORY_OBJECT SharedMemoryObject;
  473. KSTATUS Status;
  474. ASSERT(FileObject->Properties.Type == IoObjectSharedMemoryObject);
  475. ASSERT(KeIsSharedExclusiveLockHeldExclusive(FileObject->Lock) != FALSE);
  476. SharedMemoryObject = FileObject->SpecialIo;
  477. //
  478. // There must be a backing image as long as the shared object is alive.
  479. //
  480. ASSERT(SharedMemoryObject->BackingImage != INVALID_HANDLE);
  481. //
  482. // Otherwise modify the backing image's file size to be the same as the
  483. // shared memory object's file size.
  484. //
  485. BackingImage = SharedMemoryObject->BackingImage;
  486. BackingImageObject = BackingImage->PathPoint.PathEntry->FileObject;
  487. READ_INT64_SYNC(&(FileObject->Properties.FileSize), &FileSize);
  488. READ_INT64_SYNC(&(BackingImageObject->Properties.FileSize),
  489. &BackingImageSize);
  490. ASSERT(FileSize < BackingImageSize);
  491. Status = IopModifyFileObjectSize(BackingImageObject,
  492. BackingImage->DeviceContext,
  493. FileSize);
  494. return Status;
  495. }
  496. KSTATUS
  497. IopUnlinkSharedMemoryObject (
  498. PFILE_OBJECT FileObject,
  499. PBOOL Unlinked
  500. )
  501. /*++
  502. Routine Description:
  503. This routine unlinks a shared memory object from the accessible namespace.
  504. Arguments:
  505. FileObject - Supplies a pointer to the file object that owns the shared
  506. memory object.
  507. Unlinked - Supplies a pointer to a boolean that receives whether or not the
  508. shared memory object was successfully unlinked.
  509. Return Value:
  510. Status code.
  511. --*/
  512. {
  513. PSHARED_MEMORY_OBJECT SharedMemoryObject;
  514. KSTATUS Status;
  515. ASSERT(FileObject->Properties.Type == IoObjectSharedMemoryObject);
  516. ASSERT(KeIsSharedExclusiveLockHeldExclusive(FileObject->Lock) != FALSE);
  517. SharedMemoryObject = FileObject->SpecialIo;
  518. *Unlinked = FALSE;
  519. Status = ObUnlinkObject(SharedMemoryObject);
  520. if (KSUCCESS(Status)) {
  521. ASSERT(SharedMemoryObject->FileObject == FileObject);
  522. IopFileObjectReleaseReference(SharedMemoryObject->FileObject);
  523. SharedMemoryObject->FileObject = NULL;
  524. *Unlinked = TRUE;
  525. }
  526. return Status;
  527. }
  528. KSTATUS
  529. IopPerformSharedMemoryIoOperation (
  530. PFILE_OBJECT FileObject,
  531. PIO_CONTEXT IoContext,
  532. BOOL UpdateFileSize
  533. )
  534. /*++
  535. Routine Description:
  536. This routine performs a non-cached I/O operation on a shared memory object.
  537. It is assumed that the file lock is held. This routine will always modify
  538. the file size in the the file properties and conditionally modify the file
  539. size in the file object.
  540. Arguments:
  541. FileObject - Supplies a pointer to the file object for the device or file.
  542. IoContext - Supplies a pointer to the I/O context.
  543. UpdateFileSize - Supplies a boolean indicating whether or not this routine
  544. should update the file size in the file object. Only the page cache
  545. code should supply FALSE.
  546. Return Value:
  547. Status code.
  548. --*/
  549. {
  550. ULONGLONG FileSize;
  551. PSHARED_MEMORY_OBJECT SharedMemoryObject;
  552. KSTATUS Status;
  553. ASSERT(IoContext->IoBuffer != NULL);
  554. ASSERT(KeIsSharedExclusiveLockHeld(FileObject->Lock) != FALSE);
  555. SharedMemoryObject = FileObject->SpecialIo;
  556. //
  557. // There must be a backing image as long as the shared memory object is
  558. // alive.
  559. //
  560. ASSERT(SharedMemoryObject->BackingImage != INVALID_HANDLE);
  561. //
  562. // If this is a read operation then read from the backing image.
  563. //
  564. if (IoContext->Write == FALSE) {
  565. Status = IoReadAtOffset(SharedMemoryObject->BackingImage,
  566. IoContext->IoBuffer,
  567. IoContext->Offset,
  568. IoContext->SizeInBytes,
  569. IoContext->Flags,
  570. IoContext->TimeoutInMilliseconds,
  571. &(IoContext->BytesCompleted),
  572. NULL);
  573. if (!KSUCCESS(Status)) {
  574. goto PerformSharedMemoryIoOperationEnd;
  575. }
  576. //
  577. // Write operations get passed onto the file that backs the shared memory
  578. // object. If there is no such file, then create one, save the handle, and
  579. // then unlink it.
  580. //
  581. } else {
  582. Status = IoWriteAtOffset(SharedMemoryObject->BackingImage,
  583. IoContext->IoBuffer,
  584. IoContext->Offset,
  585. IoContext->SizeInBytes,
  586. IoContext->Flags,
  587. IoContext->TimeoutInMilliseconds,
  588. &(IoContext->BytesCompleted),
  589. NULL);
  590. if (!KSUCCESS(Status)) {
  591. goto PerformSharedMemoryIoOperationEnd;
  592. }
  593. //
  594. // If bytes were written, then update the file size of the shared
  595. // memory object.
  596. //
  597. if (IoContext->BytesCompleted != 0) {
  598. FileSize = IoContext->Offset + IoContext->BytesCompleted;
  599. IopUpdateFileObjectFileSize(FileObject,
  600. FileSize,
  601. UpdateFileSize,
  602. TRUE);
  603. }
  604. }
  605. PerformSharedMemoryIoOperationEnd:
  606. return Status;
  607. }
  608. //
  609. // --------------------------------------------------------- Internal Functions
  610. VOID
  611. IopDestroySharedMemoryObject (
  612. PVOID Object
  613. )
  614. /*++
  615. Routine Description:
  616. This routine destroys the given shared memory object.
  617. Arguments:
  618. Object - Supplies a pointer to the shared memory object to be destroyed.
  619. Return Value:
  620. None.
  621. --*/
  622. {
  623. PSHARED_MEMORY_OBJECT SharedMemoryObject;
  624. SharedMemoryObject = (PSHARED_MEMORY_OBJECT)Object;
  625. if (SharedMemoryObject->BackingImage != INVALID_HANDLE) {
  626. IoIoHandleReleaseReference(SharedMemoryObject->BackingImage);
  627. SharedMemoryObject->BackingImage = INVALID_HANDLE;
  628. }
  629. ASSERT(SharedMemoryObject->FileObject == NULL);
  630. return;
  631. }
  632. KSTATUS
  633. IopAddSharedMemoryObjectPathPrefix (
  634. PSTR Path,
  635. ULONG PathLength,
  636. PSTR *NewPath,
  637. PULONG NewPathLength
  638. )
  639. /*++
  640. Routine Description:
  641. This routine adds the shared memory object directory's path as a prefix to
  642. the given path.
  643. Arguments:
  644. Path - Supplies a pointer to a path to a shared memory object.
  645. PathLength - Supplies the length of the path.
  646. NewPath - Supplies a pointer that receives a pointer to the new, complete
  647. path. The caller is expected to release this memory.
  648. NewPathLength - Supplies a pointer that receives the length of the newly
  649. allocated path.
  650. Return Value:
  651. Status code.
  652. --*/
  653. {
  654. PSTR SharedMemoryPath;
  655. ULONG SharedMemoryPathLength;
  656. KSTATUS Status;
  657. ASSERT(Path != NULL);
  658. ASSERT(PathLength != 0);
  659. SharedMemoryPath = ObGetFullPath(IoSharedMemoryObjectDirectory,
  660. IO_ALLOCATION_TAG);
  661. if (SharedMemoryPath == NULL) {
  662. Status = STATUS_INSUFFICIENT_RESOURCES;
  663. goto AddSharedMemoryObjectPathPrefixEnd;
  664. }
  665. SharedMemoryPathLength = RtlStringLength(SharedMemoryPath) + 1;
  666. Status = IoPathAppend(SharedMemoryPath,
  667. SharedMemoryPathLength,
  668. Path,
  669. PathLength,
  670. IO_ALLOCATION_TAG,
  671. NewPath,
  672. NewPathLength);
  673. if (!KSUCCESS(Status)) {
  674. goto AddSharedMemoryObjectPathPrefixEnd;
  675. }
  676. AddSharedMemoryObjectPathPrefixEnd:
  677. if (SharedMemoryPath != NULL) {
  678. MmFreePagedPool(SharedMemoryPath);
  679. }
  680. return Status;
  681. }