1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5/*++
6
7
8
9Module Name:
10
11 shmobjectmgr.cpp
12
13Abstract:
14 Shared memory based object manager
15
16
17
18--*/
19
20#include "shmobjectmanager.hpp"
21#include "shmobject.hpp"
22#include "pal/cs.hpp"
23#include "pal/thread.hpp"
24#include "pal/procobj.hpp"
25#include "pal/dbgmsg.h"
26
27SET_DEFAULT_DEBUG_CHANNEL(PAL);
28
29#include "pal/corunix.inl"
30
31using namespace CorUnix;
32
33IPalObjectManager * CorUnix::g_pObjectManager;
34
35static
36PAL_ERROR
37CheckObjectTypeAndRights(
38 IPalObject *pobj,
39 CAllowedObjectTypes *paot,
40 DWORD dwRightsGranted,
41 DWORD dwRightsRequired
42 );
43
44/*++
45Function:
46 CSharedMemoryObjectManager::Initialize
47
48 Performs (possibly failing) startup tasks for the object manager
49
50Parameters:
51 None
52--*/
53
54PAL_ERROR
55CSharedMemoryObjectManager::Initialize(
56 void
57 )
58{
59 PAL_ERROR palError = NO_ERROR;
60
61 ENTRY("CSharedMemoryObjectManager::Initialize (this=%p)\n", this);
62
63 InitializeListHead(&m_leNamedObjects);
64 InitializeListHead(&m_leAnonymousObjects);
65
66 InternalInitializeCriticalSection(&m_csListLock);
67 m_fListLockInitialized = TRUE;
68
69 palError = m_HandleManager.Initialize();
70
71 LOGEXIT("CSharedMemoryObjectManager::Initialize returns %d", palError);
72
73 return palError;
74}
75
76/*++
77Function:
78 CSharedMemoryObjectManager::Shutdown
79
80 Cleans up the object manager. This routine will call cleanup routines
81 for all objects referenced by this process. After this routine is called
82 no attempt should be made to access an IPalObject.
83
84Parameters:
85 pthr -- thread data for calling thread
86--*/
87
88PAL_ERROR
89CSharedMemoryObjectManager::Shutdown(
90 CPalThread *pthr
91 )
92{
93 PLIST_ENTRY ple;
94 CSharedMemoryObject *pshmobj;
95
96 _ASSERTE(NULL != pthr);
97
98 ENTRY("CSharedMemoryObjectManager::Shutdown (this=%p, pthr=%p)\n",
99 this,
100 pthr
101 );
102
103 InternalEnterCriticalSection(pthr, &m_csListLock);
104 SHMLock();
105
106 while (!IsListEmpty(&m_leAnonymousObjects))
107 {
108 ple = RemoveTailList(&m_leAnonymousObjects);
109 pshmobj = CSharedMemoryObject::GetObjectFromListLink(ple);
110 pshmobj->CleanupForProcessShutdown(pthr);
111 }
112
113 while (!IsListEmpty(&m_leNamedObjects))
114 {
115 ple = RemoveTailList(&m_leNamedObjects);
116 pshmobj = CSharedMemoryObject::GetObjectFromListLink(ple);
117 pshmobj->CleanupForProcessShutdown(pthr);
118 }
119
120 SHMRelease();
121 InternalLeaveCriticalSection(pthr, &m_csListLock);
122
123 LOGEXIT("CSharedMemoryObjectManager::Shutdown returns %d\n", NO_ERROR);
124
125 return NO_ERROR;
126}
127
128/*++
129Function:
130 CSharedMemoryObjectManager::AllocateObject
131
132 Allocates a new object instance of the specified type.
133
134Parameters:
135 pthr -- thread data for calling thread
136 pot -- type of object to allocate
137 poa -- attributes (name and SD) of object to allocate
138 ppobjNew -- on success, receives a reference to the new object
139--*/
140
141PAL_ERROR
142CSharedMemoryObjectManager::AllocateObject(
143 CPalThread *pthr,
144 CObjectType *pot,
145 CObjectAttributes *poa,
146 IPalObject **ppobjNew // OUT
147 )
148{
149 PAL_ERROR palError = NO_ERROR;
150 CSharedMemoryObject *pshmobj = NULL;
151
152 _ASSERTE(NULL != pthr);
153 _ASSERTE(NULL != pot);
154 _ASSERTE(NULL != poa);
155 _ASSERTE(NULL != ppobjNew);
156
157 ENTRY("CSharedMemoryObjectManager::AllocateObject "
158 "(this=%p, pthr=%p, pot=%p, poa=%p, ppobjNew=%p)\n",
159 this,
160 pthr,
161 pot,
162 poa,
163 ppobjNew
164 );
165
166 if (CObjectType::WaitableObject == pot->GetSynchronizationSupport())
167 {
168 pshmobj = InternalNew<CSharedMemoryWaitableObject>(pot, &m_csListLock);
169 }
170 else
171 {
172 pshmobj = InternalNew<CSharedMemoryObject>(pot, &m_csListLock);
173 }
174
175 if (NULL != pshmobj)
176 {
177 palError = pshmobj->Initialize(pthr, poa);
178 if (NO_ERROR == palError)
179 {
180 *ppobjNew = static_cast<IPalObject*>(pshmobj);
181 }
182 }
183 else
184 {
185 ERROR("Unable to allocate pshmobj\n");
186 palError = ERROR_OUTOFMEMORY;
187 }
188
189 LOGEXIT("CSharedMemoryObjectManager::AllocateObject returns %d\n", palError);
190 return palError;
191}
192
193/*++
194Function:
195 CSharedMemoryObjectManager::RegisterObject
196
197 Registers a newly-allocated object instance. If the object to be registered
198 has a name, and a previously registered object has the same name the new
199 object will not be registered.
200
201Distinguished return values:
202 ERROR_ALREADY_EXISTS -- an object of a compatible type was already registered
203 with the specified name
204 ERROR_INVALID_HANDLE -- an object of an incompatible type was already
205 registered with the specified name
206
207Parameters:
208 pthr -- thread data for calling thread
209 pobjToRegister -- the object instance to register. This routine will always
210 call ReleaseReference on this instance
211 paot -- object types that are compatible with the new object instance
212 dwRightsRequested -- requested access rights for the returned handle (ignored)
213 pHandle -- on success, receives a handle to the registered object
214 ppobjRegistered -- on success, receives a reference to the registered object
215 instance.
216--*/
217
218PAL_ERROR
219CSharedMemoryObjectManager::RegisterObject(
220 CPalThread *pthr,
221 IPalObject *pobjToRegister,
222 CAllowedObjectTypes *paot,
223 DWORD dwRightsRequested,
224 HANDLE *pHandle, // OUT
225 IPalObject **ppobjRegistered // OUT
226 )
227{
228 PAL_ERROR palError = NO_ERROR;
229 CSharedMemoryObject *pshmobj = static_cast<CSharedMemoryObject*>(pobjToRegister);
230 SHMObjData *psmodNew = NULL;
231 CObjectAttributes *poa;
232 CObjectType *potObj;
233 IPalObject *pobjExisting;
234 BOOL fInherit = FALSE;
235 BOOL fShared = FALSE;
236
237 _ASSERTE(NULL != pthr);
238 _ASSERTE(NULL != pobjToRegister);
239 _ASSERTE(NULL != paot);
240 _ASSERTE(NULL != pHandle);
241 _ASSERTE(NULL != ppobjRegistered);
242
243 ENTRY("CSharedMemoryObjectManager::RegisterObject "
244 "(this=%p, pthr=%p, pobjToRegister=%p, paot=%p, "
245 "dwRightsRequested=%d, pHandle=%p, ppobjRegistered=%p)\n",
246 this,
247 pthr,
248 pobjToRegister,
249 paot,
250 dwRightsRequested,
251 pHandle,
252 ppobjRegistered
253 );
254
255 poa = pobjToRegister->GetObjectAttributes();
256 _ASSERTE(NULL != poa);
257
258 if (NULL != poa->pSecurityAttributes)
259 {
260 fInherit = poa->pSecurityAttributes->bInheritHandle;
261 }
262
263 potObj = pobjToRegister->GetObjectType();
264 fShared = (SharedObject == pshmobj->GetObjectDomain());
265
266 InternalEnterCriticalSection(pthr, &m_csListLock);
267
268 if (fShared)
269 {
270 //
271 // We only need to acquire the shared memory lock if this
272 // object is actually shared.
273 //
274
275 SHMLock();
276 }
277
278 if (0 != poa->sObjectName.GetStringLength())
279 {
280 SHMPTR shmObjectListHead = NULL;
281
282 //
283 // The object must be shared
284 //
285
286 _ASSERTE(fShared);
287
288 //
289 // Check if an object by this name alredy exists
290 //
291
292 palError = LocateObject(
293 pthr,
294 &poa->sObjectName,
295 paot,
296 &pobjExisting
297 );
298
299 if (NO_ERROR == palError)
300 {
301 //
302 // Obtain a new handle to the existing object
303 //
304
305 palError = ObtainHandleForObject(
306 pthr,
307 pobjExisting,
308 dwRightsRequested,
309 fInherit,
310 NULL,
311 pHandle
312 );
313
314 if (NO_ERROR == palError)
315 {
316 //
317 // Transfer object reference to out param
318 //
319
320 *ppobjRegistered = pobjExisting;
321 palError = ERROR_ALREADY_EXISTS;
322 }
323 else
324 {
325 pobjExisting->ReleaseReference(pthr);
326 }
327
328 goto RegisterObjectExit;
329 }
330 else if (ERROR_INVALID_NAME != palError)
331 {
332 //
333 // Something different than an object not found error
334 // occurred. This is most likely due to a type conflict.
335 //
336
337 goto RegisterObjectExit;
338 }
339
340 //
341 // Insert the object on the named object lists
342 //
343
344 InsertTailList(&m_leNamedObjects, pshmobj->GetObjectListLink());
345
346 psmodNew = SHMPTR_TO_TYPED_PTR(SHMObjData, pshmobj->GetShmObjData());
347 if (NULL == psmodNew)
348 {
349 ASSERT("Failure to map shared object data\n");
350 palError = ERROR_INTERNAL_ERROR;
351 goto RegisterObjectExit;
352 }
353
354 shmObjectListHead = SHMGetInfo(SIID_NAMED_OBJECTS);
355 if (NULL != shmObjectListHead)
356 {
357 SHMObjData *psmodListHead;
358
359 psmodListHead = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjectListHead);
360 if (NULL != psmodListHead)
361 {
362 psmodNew->shmNextObj = shmObjectListHead;
363 psmodListHead->shmPrevObj = pshmobj->GetShmObjData();
364 }
365 else
366 {
367 ASSERT("Failure to map shared object data\n");
368 palError = ERROR_INTERNAL_ERROR;
369 goto RegisterObjectExit;
370 }
371 }
372
373 psmodNew->fAddedToList = TRUE;
374
375 if (!SHMSetInfo(SIID_NAMED_OBJECTS, pshmobj->GetShmObjData()))
376 {
377 ASSERT("Failed to set shared named object list head\n");
378 palError = ERROR_INTERNAL_ERROR;
379 goto RegisterObjectExit;
380 }
381 }
382 else
383 {
384 //
385 // Place the object on the anonymous object list
386 //
387
388 InsertTailList(&m_leAnonymousObjects, pshmobj->GetObjectListLink());
389 }
390
391 //
392 // Hoist the object's immutable data (if any) into shared memory if
393 // the object is shared
394 //
395
396 if (fShared && 0 != potObj->GetImmutableDataSize())
397 {
398 VOID *pvImmutableData;
399 SHMObjData *psmod;
400
401 palError = pobjToRegister->GetImmutableData(&pvImmutableData);
402 if (NO_ERROR != palError)
403 {
404 ASSERT("Failure to obtain object immutable data\n");
405 goto RegisterObjectExit;
406 }
407
408 psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, pshmobj->GetShmObjData());
409 if (NULL != psmod)
410 {
411 VOID *pvSharedImmutableData =
412 SHMPTR_TO_TYPED_PTR(VOID, psmod->shmObjImmutableData);
413
414 if (NULL != pvSharedImmutableData)
415 {
416 CopyMemory(
417 pvSharedImmutableData,
418 pvImmutableData,
419 potObj->GetImmutableDataSize()
420 );
421
422 if (NULL != potObj->GetImmutableDataCopyRoutine())
423 {
424 (*potObj->GetImmutableDataCopyRoutine())(pvImmutableData, pvSharedImmutableData);
425 }
426
427 psmod->pCopyRoutine = potObj->GetImmutableDataCopyRoutine();
428 psmod->pCleanupRoutine = potObj->GetImmutableDataCleanupRoutine();
429 }
430 else
431 {
432 ASSERT("Failure to map psmod->shmObjImmutableData\n");
433 palError = ERROR_INTERNAL_ERROR;
434 goto RegisterObjectExit;
435 }
436 }
437 else
438 {
439 ASSERT("Failure to map pshmobj->GetShmObjData()\n");
440 palError = ERROR_INTERNAL_ERROR;
441 goto RegisterObjectExit;
442 }
443 }
444
445 //
446 // Obtain a handle for the new object
447 //
448
449 palError = ObtainHandleForObject(
450 pthr,
451 pobjToRegister,
452 dwRightsRequested,
453 fInherit,
454 NULL,
455 pHandle
456 );
457
458 if (NO_ERROR == palError)
459 {
460 //
461 // Transfer pobjToRegister reference to out param
462 //
463
464 *ppobjRegistered = pobjToRegister;
465 pobjToRegister = NULL;
466 }
467
468RegisterObjectExit:
469
470 if (fShared)
471 {
472 SHMRelease();
473 }
474
475 InternalLeaveCriticalSection(pthr, &m_csListLock);
476
477 if (NULL != pobjToRegister)
478 {
479 pobjToRegister->ReleaseReference(pthr);
480 }
481
482 LOGEXIT("CSharedMemoryObjectManager::RegisterObject return %d\n", palError);
483
484 return palError;
485}
486
487/*++
488Function:
489 CSharedMemoryObjectManager::LocateObject
490
491 Search for a previously registered object with a give name and type
492
493Distinguished return values:
494 ERROR_INVALID_NAME -- no object with the specified name was previously
495 registered
496 ERROR_INVALID_HANDLE -- an object with the specified name was previously
497 registered, but its type is not compatible
498
499Parameters:
500 pthr -- thread data for calling thread
501 psObjectToLocate -- the name of the object to locate
502 paot -- acceptable types for the object
503 ppobj -- on success, receives a reference to the object instance
504--*/
505
506PAL_ERROR
507CSharedMemoryObjectManager::LocateObject(
508 CPalThread *pthr,
509 CPalString *psObjectToLocate,
510 CAllowedObjectTypes *paot,
511 IPalObject **ppobj // OUT
512 )
513{
514 PAL_ERROR palError = NO_ERROR;
515 IPalObject *pobjExisting = NULL;
516 SHMPTR shmSharedObjectData = NULL;
517 SHMPTR shmObjectListEntry = NULL;
518 SHMObjData *psmod = NULL;
519 LPWSTR pwsz = NULL;
520
521 _ASSERTE(NULL != pthr);
522 _ASSERTE(NULL != psObjectToLocate);
523 _ASSERTE(NULL != psObjectToLocate->GetString());
524 _ASSERTE(PAL_wcslen(psObjectToLocate->GetString()) == psObjectToLocate->GetStringLength());
525 _ASSERTE(NULL != ppobj);
526
527 ENTRY("CSharedMemoryObjectManager::LocateObject "
528 "(this=%p, pthr=%p, psObjectToLocate=%p, paot=%p, "
529 "ppobj=%p)\n",
530 this,
531 pthr,
532 psObjectToLocate,
533 paot,
534 ppobj
535 );
536
537 TRACE("Searching for object name %S\n", psObjectToLocate->GetString());
538
539 InternalEnterCriticalSection(pthr, &m_csListLock);
540
541 //
542 // Search the local named object list for this object
543 //
544
545 for (PLIST_ENTRY ple = m_leNamedObjects.Flink;
546 ple != &m_leNamedObjects;
547 ple = ple->Flink)
548 {
549 CObjectAttributes *poa;
550 CSharedMemoryObject *pshmobj =
551 CSharedMemoryObject::GetObjectFromListLink(ple);
552
553 poa = pshmobj->GetObjectAttributes();
554 _ASSERTE(NULL != poa);
555
556 if (poa->sObjectName.GetStringLength() != psObjectToLocate->GetStringLength())
557 {
558 continue;
559 }
560
561 if (0 != PAL_wcscmp(poa->sObjectName.GetString(), psObjectToLocate->GetString()))
562 {
563 continue;
564 }
565
566 //
567 // This object has the name we're looking for
568 //
569
570 pobjExisting = static_cast<IPalObject*>(pshmobj);
571 break;
572 }
573
574 if (NULL != pobjExisting)
575 {
576 //
577 // Validate the located object's type
578 //
579
580 if (paot->IsTypeAllowed(
581 pobjExisting->GetObjectType()->GetId()
582 ))
583 {
584 TRACE("Local object exists with compatible type\n");
585
586 //
587 // Add a reference to the found object
588 //
589
590 pobjExisting->AddReference();
591 *ppobj = pobjExisting;
592 }
593 else
594 {
595 TRACE("Local object exists w/ incompatible type\n");
596 palError = ERROR_INVALID_HANDLE;
597 }
598
599 goto LocateObjectExit;
600 }
601
602 //
603 // Search the shared memory named object list for a matching object
604 //
605
606 SHMLock();
607
608 shmObjectListEntry = SHMGetInfo(SIID_NAMED_OBJECTS);
609 while (NULL != shmObjectListEntry)
610 {
611 psmod = SHMPTR_TO_TYPED_PTR(SHMObjData, shmObjectListEntry);
612 if (NULL != psmod)
613 {
614 if (psmod->dwNameLength == psObjectToLocate->GetStringLength())
615 {
616 pwsz = SHMPTR_TO_TYPED_PTR(WCHAR, psmod->shmObjName);
617 if (NULL != pwsz)
618 {
619 if (0 == PAL_wcscmp(pwsz, psObjectToLocate->GetString()))
620 {
621 //
622 // This is the object we were looking for.
623 //
624
625 shmSharedObjectData = shmObjectListEntry;
626 break;
627 }
628 }
629 else
630 {
631 ASSERT("Unable to map psmod->shmObjName\n");
632 break;
633 }
634 }
635
636 shmObjectListEntry = psmod->shmNextObj;
637 }
638 else
639 {
640 ASSERT("Unable to map shmObjectListEntry\n");
641 break;
642 }
643 }
644
645 if (NULL != shmSharedObjectData)
646 {
647 CSharedMemoryObject *pshmobj = NULL;
648 CObjectAttributes oa(pwsz, NULL);
649
650 //
651 // Check if the type is allowed
652 //
653
654 if (!paot->IsTypeAllowed(psmod->eTypeId))
655 {
656 TRACE("Remote object exists w/ incompatible type\n");
657 palError = ERROR_INVALID_HANDLE;
658 goto LocateObjectExitSHMRelease;
659 }
660
661 //
662 // Get the local instance of the CObjectType
663 //
664
665 CObjectType *pot = CObjectType::GetObjectTypeById(psmod->eTypeId);
666 if (NULL == pot)
667 {
668 ASSERT("Invalid object type ID in shared memory info\n");
669 goto LocateObjectExitSHMRelease;
670 }
671
672 TRACE("Remote object exists compatible type -- importing\n");
673
674 //
675 // Create the local state for the shared object
676 //
677
678 palError = ImportSharedObjectIntoProcess(
679 pthr,
680 pot,
681 &oa,
682 shmSharedObjectData,
683 psmod,
684 TRUE,
685 &pshmobj
686 );
687
688 if (NO_ERROR == palError)
689 {
690 *ppobj = static_cast<IPalObject*>(pshmobj);
691 }
692 else
693 {
694 ERROR("Failure initializing object from shared data\n");
695 goto LocateObjectExitSHMRelease;
696 }
697
698 }
699 else
700 {
701 //
702 // The object was not found
703 //
704
705 palError = ERROR_INVALID_NAME;
706 }
707
708LocateObjectExitSHMRelease:
709
710 SHMRelease();
711
712LocateObjectExit:
713
714 InternalLeaveCriticalSection(pthr, &m_csListLock);
715
716 LOGEXIT("CSharedMemoryObjectManager::LocateObject returns %d\n", palError);
717
718 return palError;
719}
720
721/*++
722Function:
723 CSharedMemoryObjectManager::ObtainHandleForObject
724
725 Allocated a new handle for an object
726
727Parameters:
728 pthr -- thread data for calling thread
729 pobj -- the object to allocate a handle for
730 dwRightsRequired -- the access rights to grant the handle; currently ignored
731 fInheritHandle -- true if the handle is inheritable; ignored for all but file
732 objects that represent pipes
733 pProcessForHandle -- the process the handle is to be used from; currently
734 must be NULL
735 pNewHandle -- on success, receives the newly allocated handle
736--*/
737
738PAL_ERROR
739CSharedMemoryObjectManager::ObtainHandleForObject(
740 CPalThread *pthr,
741 IPalObject *pobj,
742 DWORD dwRightsRequested,
743 bool fInheritHandle,
744 IPalProcess *pProcessForHandle, // IN, OPTIONAL
745 HANDLE *pNewHandle // OUT
746 )
747{
748 PAL_ERROR palError = NO_ERROR;
749
750 _ASSERTE(NULL != pthr);
751 _ASSERTE(NULL != pobj);
752 _ASSERTE(NULL != pNewHandle);
753
754 ENTRY("CSharedMemoryObjectManager::ObtainHandleForObject "
755 "(this=%p, pthr=%p, pobj=%p, dwRightsRequested=%d, "
756 "fInheritHandle=%p, pProcessForHandle=%p, pNewHandle=%p)\n",
757 this,
758 pthr,
759 pobj,
760 dwRightsRequested,
761 fInheritHandle,
762 pProcessForHandle,
763 pNewHandle
764 );
765
766 if (NULL != pProcessForHandle)
767 {
768 //
769 // Not yet supported
770 //
771
772 ASSERT("Caller to ObtainHandleForObject provided a process\n");
773 return ERROR_CALL_NOT_IMPLEMENTED;
774 }
775
776 palError = m_HandleManager.AllocateHandle(
777 pthr,
778 pobj,
779 dwRightsRequested,
780 fInheritHandle,
781 pNewHandle
782 );
783
784 LOGEXIT("CSharedMemoryObjectManager::ObtainHandleForObject return %d\n", palError);
785
786 return palError;
787}
788
789/*++
790Function:
791 CSharedMemoryObjectManager::RevokeHandle
792
793 Removes a handle from the process's handle table, which in turn releases
794 the handle's reference on the object instance it refers to
795
796Parameters:
797 pthr -- thread data for calling thread
798 hHandleToRevoke -- the handle to revoke
799--*/
800
801PAL_ERROR
802CSharedMemoryObjectManager::RevokeHandle(
803 CPalThread *pthr,
804 HANDLE hHandleToRevoke
805 )
806{
807 PAL_ERROR palError = NO_ERROR;
808
809 _ASSERTE(NULL != pthr);
810
811 ENTRY("CSharedMemoryObjectManager::RevokeHandle "
812 "(this=%p, pthr=%p, hHandleToRevoke=%p)\n",
813 this,
814 pthr,
815 hHandleToRevoke
816 );
817
818 palError = m_HandleManager.FreeHandle(pthr, hHandleToRevoke);
819
820 LOGEXIT("CSharedMemoryObjectManager::RevokeHandle returns %d\n", palError);
821
822 return palError;
823}
824
825/*++
826Function:
827 CSharedMemoryObjectManager::ReferenceObjectByHandle
828
829 Returns a referenced object instance that a handle refers to
830
831Parameters:
832 pthr -- thread data for calling thread
833 hHandleToReference -- the handle to reference
834 paot -- acceptable types for the underlying object
835 dwRightsRequired -- the access rights that the handle must have been
836 granted; currently ignored
837 ppobj -- on success, receives a reference to the object instance
838--*/
839
840PAL_ERROR
841CSharedMemoryObjectManager::ReferenceObjectByHandle(
842 CPalThread *pthr,
843 HANDLE hHandleToReference,
844 CAllowedObjectTypes *paot,
845 DWORD dwRightsRequired,
846 IPalObject **ppobj // OUT
847 )
848{
849 PAL_ERROR palError;
850 DWORD dwRightsGranted;
851 IPalObject *pobj;
852
853 _ASSERTE(NULL != pthr);
854 _ASSERTE(NULL != paot);
855 _ASSERTE(NULL != ppobj);
856
857 ENTRY("CSharedMemoryObjectManager::ReferenceObjectByHandle "
858 "(this=%p, pthr=%p, hHandleToReference=%p, paot=%p, "
859 "dwRightsRequired=%d, ppobj=%p)\n",
860 this,
861 pthr,
862 hHandleToReference,
863 paot,
864 dwRightsRequired,
865 ppobj
866 );
867
868 palError = m_HandleManager.GetObjectFromHandle(
869 pthr,
870 hHandleToReference,
871 &dwRightsGranted,
872 &pobj
873 );
874
875 if (NO_ERROR == palError)
876 {
877 palError = CheckObjectTypeAndRights(
878 pobj,
879 paot,
880 dwRightsGranted,
881 dwRightsRequired
882 );
883
884 if (NO_ERROR == palError)
885 {
886 //
887 // Transfer object reference to out parameter
888 //
889
890 *ppobj = pobj;
891 }
892 else
893 {
894 pobj->ReleaseReference(pthr);
895 }
896 }
897
898 LOGEXIT("CSharedMemoryObjectManager::ReferenceObjectByHandle returns %d\n",
899 palError
900 );
901
902 return palError;
903}
904
905/*++
906Function:
907 CSharedMemoryObjectManager::ReferenceObjectByHandleArray
908
909 Returns the referenced object instances that an array of handles
910 refer to.
911
912Parameters:
913 pthr -- thread data for calling thread
914 rgHandlesToReference -- the array of handles to reference
915 dwHandleCount -- the number of handles in the arrayu
916 paot -- acceptable types for the underlying objects
917 dwRightsRequired -- the access rights that the handles must have been
918 granted; currently ignored
919 rgpobjs -- on success, receives references to the object instances; will
920 be empty on failures
921--*/
922
923PAL_ERROR
924CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray(
925 CPalThread *pthr,
926 HANDLE rghHandlesToReference[],
927 DWORD dwHandleCount,
928 CAllowedObjectTypes *paot,
929 DWORD dwRightsRequired,
930 IPalObject *rgpobjs[] // OUT (caller allocated)
931 )
932{
933 PAL_ERROR palError = NO_ERROR;
934 IPalObject *pobj = NULL;
935 DWORD dwRightsGranted;
936 DWORD dw;
937
938 _ASSERTE(NULL != pthr);
939 _ASSERTE(NULL != rghHandlesToReference);
940 _ASSERTE(0 < dwHandleCount);
941 _ASSERTE(NULL != paot);
942 _ASSERTE(NULL != rgpobjs);
943
944 ENTRY("CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray "
945 "(this=%p, pthr=%p, rghHandlesToReference=%p, dwHandleCount=%d, "
946 "pAllowedTyped=%d, dwRightsRequired=%d, rgpobjs=%p)\n",
947 this,
948 pthr,
949 rghHandlesToReference,
950 dwHandleCount,
951 paot,
952 dwRightsRequired,
953 rgpobjs
954 );
955
956 m_HandleManager.Lock(pthr);
957
958 for (dw = 0; dw < dwHandleCount; dw += 1)
959 {
960 palError = m_HandleManager.GetObjectFromHandle(
961 pthr,
962 rghHandlesToReference[dw],
963 &dwRightsGranted,
964 &pobj
965 );
966
967 if (NO_ERROR == palError)
968 {
969 palError = CheckObjectTypeAndRights(
970 pobj,
971 paot,
972 dwRightsGranted,
973 dwRightsRequired
974 );
975
976 if (NO_ERROR == palError)
977 {
978 //
979 // Transfer reference to out array
980 //
981
982 rgpobjs[dw] = pobj;
983 pobj = NULL;
984 }
985 }
986
987 if (NO_ERROR != palError)
988 {
989 break;
990 }
991 }
992
993 //
994 // The handle manager lock must be released before releasing
995 // any object references, as ReleaseReference will acquire
996 // the object manager list lock (which needs to be acquired before
997 // the handle manager lock)
998 //
999
1000 m_HandleManager.Unlock(pthr);
1001
1002 if (NO_ERROR != palError)
1003 {
1004 //
1005 // dw's current value is the failing index, so we want
1006 // to free from dw - 1.
1007 //
1008
1009 while (dw > 0)
1010 {
1011 rgpobjs[--dw]->ReleaseReference(pthr);
1012 }
1013
1014 if (NULL != pobj)
1015 {
1016 pobj->ReleaseReference(pthr);
1017 }
1018 }
1019
1020 LOGEXIT("CSharedMemoryObjectManager::ReferenceMultipleObjectsByHandleArray"
1021 " returns %d\n",
1022 palError
1023 );
1024
1025 return palError;
1026}
1027
1028/*++
1029Function:
1030 CSharedMemoryObjectManager::ReferenceObjectByForeignHandle
1031
1032 Returns a referenced object instance that a handle belongin to
1033 another process refers to; currently unimplemented
1034
1035Parameters:
1036 pthr -- thread data for calling thread
1037 hForeignHandle -- the handle to reference
1038 pForeignProcess -- the process that hForeignHandle belongs to
1039 paot -- acceptable types for the underlying object
1040 dwRightsRequired -- the access rights that the handle must have been
1041 granted; currently ignored
1042 ppobj -- on success, receives a reference to the object instance
1043--*/
1044
1045PAL_ERROR
1046CSharedMemoryObjectManager::ReferenceObjectByForeignHandle(
1047 CPalThread *pthr,
1048 HANDLE hForeignHandle,
1049 IPalProcess *pForeignProcess,
1050 CAllowedObjectTypes *paot,
1051 DWORD dwRightsRequired,
1052 IPalObject **ppobj // OUT
1053 )
1054{
1055 //
1056 // Not implemented for basic shared memory object manager --
1057 // requires an IPC channel. (For the shared memory object manager
1058 // PAL_LocalHandleToRemote and PAL_RemoteHandleToLocal must still
1059 // be used...)
1060 //
1061
1062 ASSERT("ReferenceObjectByForeignHandle not yet supported\n");
1063 return ERROR_CALL_NOT_IMPLEMENTED;
1064}
1065
1066/*++
1067Function:
1068 CSharedMemoryObjectManager::ImportSharedObjectIntoProcess
1069
1070 Takes an object's shared memory data and from it creates the
1071 necessary in-process structures for the object
1072
1073Parameters:
1074 pthr -- thread data for calling thread
1075 pot -- the object's type
1076 poa -- attributes for the object
1077 shmSharedObjectData -- the shared memory pointer for the object's shared
1078 data
1079 psmod -- the shared memory data for the object, mapped into this process's
1080 address space
1081 fAddRefSharedData -- if TRUE, we need to add to the shared data reference
1082 count
1083 ppshmobj -- on success, receives a pointer to the newly created local
1084 object instance
1085--*/
1086
1087PAL_ERROR
1088CSharedMemoryObjectManager::ImportSharedObjectIntoProcess(
1089 CPalThread *pthr,
1090 CObjectType *pot,
1091 CObjectAttributes *poa,
1092 SHMPTR shmSharedObjectData,
1093 SHMObjData *psmod,
1094 bool fAddRefSharedData,
1095 CSharedMemoryObject **ppshmobj
1096 )
1097{
1098 PAL_ERROR palError = NO_ERROR;
1099 CSharedMemoryObject *pshmobj;
1100 PLIST_ENTRY pleObjectList;
1101
1102 _ASSERTE(NULL != pthr);
1103 _ASSERTE(NULL != pot);
1104 _ASSERTE(NULL != poa);
1105 _ASSERTE(NULL != shmSharedObjectData);
1106 _ASSERTE(NULL != psmod);
1107 _ASSERTE(NULL != ppshmobj);
1108
1109 ENTRY("CSharedMemoryObjectManager::ImportSharedObjectIntoProcess(pthr=%p, "
1110 "pot=%p, poa=%p, shmSharedObjectData=%p, psmod=%p, fAddRefSharedData=%d, "
1111 "ppshmobj=%p)\n",
1112 pthr,
1113 pot,
1114 poa,
1115 shmSharedObjectData,
1116 psmod,
1117 fAddRefSharedData,
1118 ppshmobj
1119 );
1120
1121 if (CObjectType::WaitableObject == pot->GetSynchronizationSupport())
1122 {
1123 pshmobj = InternalNew<CSharedMemoryWaitableObject>(pot,
1124 &m_csListLock,
1125 shmSharedObjectData,
1126 psmod,
1127 fAddRefSharedData);
1128 }
1129 else
1130 {
1131 pshmobj = InternalNew<CSharedMemoryObject>(pot,
1132 &m_csListLock,
1133 shmSharedObjectData,
1134 psmod,
1135 fAddRefSharedData);
1136 }
1137
1138 if (NULL != pshmobj)
1139 {
1140 palError = pshmobj->InitializeFromExistingSharedData(pthr, poa);
1141 if (NO_ERROR == palError)
1142 {
1143 if (0 != psmod->dwNameLength)
1144 {
1145 pleObjectList = &m_leNamedObjects;
1146 }
1147 else
1148 {
1149 pleObjectList = &m_leAnonymousObjects;
1150 }
1151
1152 InsertTailList(pleObjectList, pshmobj->GetObjectListLink());
1153 }
1154 else
1155 {
1156 goto ImportSharedObjectIntoProcessExit;
1157 }
1158 }
1159 else
1160 {
1161 ERROR("Unable to allocate new object\n");
1162 palError = ERROR_OUTOFMEMORY;
1163 goto ImportSharedObjectIntoProcessExit;
1164 }
1165
1166 *ppshmobj = pshmobj;
1167
1168ImportSharedObjectIntoProcessExit:
1169
1170 LOGEXIT("CSharedMemoryObjectManager::ImportSharedObjectIntoProcess returns %d\n", palError);
1171
1172 return palError;
1173}
1174
1175static PalObjectTypeId RemotableObjectTypes[] =
1176 {otiManualResetEvent, otiAutoResetEvent, otiMutex, otiProcess};
1177
1178static CAllowedObjectTypes aotRemotable(
1179 RemotableObjectTypes,
1180 sizeof(RemotableObjectTypes) / sizeof(RemotableObjectTypes[0])
1181 );
1182
1183/*++
1184Function:
1185 CheckObjectTypeAndRights
1186
1187 Helper routine that determines if:
1188 1) An object instance is of a specified type
1189 2) A set of granted access rights satisfies the required access rights
1190 (currently ignored)
1191
1192Parameters:
1193 pobj -- the object instance whose type is to be checked
1194 paot -- the acceptable type for the object instance
1195 dwRightsGranted -- the granted access rights (ignored)
1196 dwRightsRequired -- the required access rights (ignored)
1197--*/
1198
1199static
1200PAL_ERROR
1201CheckObjectTypeAndRights(
1202 IPalObject *pobj,
1203 CAllowedObjectTypes *paot,
1204 DWORD dwRightsGranted,
1205 DWORD dwRightsRequired
1206 )
1207{
1208 PAL_ERROR palError = NO_ERROR;
1209
1210 _ASSERTE(NULL != pobj);
1211 _ASSERTE(NULL != paot);
1212
1213 ENTRY("CheckObjectTypeAndRights (pobj=%p, paot=%p, "
1214 "dwRightsGranted=%d, dwRightsRequired=%d)\n",
1215 pobj,
1216 paot,
1217 dwRightsGranted,
1218 dwRightsRequired
1219 );
1220
1221 if (paot->IsTypeAllowed(pobj->GetObjectType()->GetId()))
1222 {
1223#ifdef ENFORCE_OBJECT_ACCESS_RIGHTS
1224
1225 //
1226 // This is where the access right check would occur if Win32 object
1227 // security were supported.
1228 //
1229
1230 if ((dwRightsRequired & dwRightsGranted) != dwRightsRequired)
1231 {
1232 palError = ERROR_ACCESS_DENIED;
1233 }
1234#endif
1235 }
1236 else
1237 {
1238 palError = ERROR_INVALID_HANDLE;
1239 }
1240
1241 LOGEXIT("CheckObjectTypeAndRights returns %d\n", palError);
1242
1243 return palError;
1244}
1245
1246
1247