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.
14 Shared memory based file lock manager
20 #include "pal/thread.hpp"
21 #include "pal/malloc.hpp"
22 #include "pal/dbgmsg.h"
23 #include "shmfilelockmgr.hpp"
25 using namespace CorUnix;
27 SET_DEFAULT_DEBUG_CHANNEL(FILE);
31 SHMFILELOCKS* fileLocks,
32 PVOID pvControllerInstance,
33 SHMFILELOCKRGNS *insertAfter,
42 PVOID pvControllerInstance,
51 PVOID pvControllerInstance,
52 UINT64 unlockRgnStart,
53 UINT64 nbBytesToUnlock,
61 PVOID pvControllerInstance
67 SHMPTR *pshmFileLocks,
71 /* return TRUE if LockToTest region is behind lockRgn, FALSE otherwise */
72 #define IS_LOCK_BEFORE(LockToTest, lockRgn) \
73 (((LockToTest)->lockRgnStart + (LockToTest)->nbBytesLocked) <= \
74 (lockRgn)->lockRgnStart)
76 /* return TRUE if LockToTest region intersect with lockRgn, FALSE otherwise */
77 #define IS_LOCK_INTERSECT(LockToTest, lockRgn) \
78 (!IS_LOCK_BEFORE(LockToTest, lockRgn) && !IS_LOCK_BEFORE(lockRgn, LockToTest))
80 /* return TRUE if LockToTest region and lockRgn have the same file pointer and
81 the same process Id, FALSE otherwise */
82 #define IS_LOCK_HAVE_SAME_OWNER(LockToTest, lockRgn) \
83 (((LockToTest)->pvControllerInstance == (lockRgn)->pvControllerInstance) && \
84 ((LockToTest)->processId == (lockRgn)->processId))
86 /* return TRUE if LockToTest region and lockRgn represent the same lock,
88 #define IS_LOCK_EQUAL(LockToTest, lockRgn) \
89 (((LockToTest)->processId == (lockRgn)->processId) && \
90 ((LockToTest)->pvControllerInstance == (lockRgn)->pvControllerInstance) && \
91 ((LockToTest)->lockRgnStart == (lockRgn)->lockRgnStart) && \
92 ((LockToTest)->nbBytesLocked == (lockRgn)->nbBytesLocked) && \
93 ((LockToTest)->lockType == (lockRgn)->lockType))
96 CSharedMemoryFileLockMgr::GetLockControllerForFile(
97 CPalThread *pThread, // IN, OPTIONAL
101 IFileLockController **ppLockController // OUT
104 PAL_ERROR palError = NO_ERROR;
105 SHMPTR shmFileLocks = NULL;
106 SHMFILELOCKS* fileLocks = NULL;
107 CSharedMemoryFileLockController *pController = NULL;
111 palError = FILEGetSHMFileLocks(szFileName, &shmFileLocks, FALSE);
112 if (NO_ERROR != palError)
114 goto GetLockControllerForFileExit;
117 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, fileLocks, shmFileLocks) == FALSE || fileLocks == NULL)
119 ASSERT("Unable to get pointer from shm pointer.\n");
120 palError = ERROR_INTERNAL_ERROR;
121 goto GetLockControllerForFileExit;
124 if(SHARE_MODE_NOT_INITALIZED == fileLocks->share_mode)
126 /* this is the first time this file is open */
127 fileLocks->share_mode = (int) dwShareMode;
129 /* start checking for dwDesired access and dwShareMode conditions */
130 else if(0 == fileLocks->share_mode)
132 /* file is exclusively locked */
133 palError = ERROR_SHARING_VIOLATION;
134 goto GetLockControllerForFileExit;
136 /* check for if the desired access is allowed by the share mode */
137 else if( (dwAccessRights & GENERIC_READ) &&
138 !(fileLocks->share_mode & FILE_SHARE_READ) )
140 palError = ERROR_SHARING_VIOLATION;
141 goto GetLockControllerForFileExit;
143 else if( (dwAccessRights & GENERIC_WRITE) &&
144 !(fileLocks->share_mode & FILE_SHARE_WRITE) )
146 palError = ERROR_SHARING_VIOLATION;
147 goto GetLockControllerForFileExit;
149 /* The case when changing to a conflicting share mode is particular.
150 The general rule is: changing from conflicting share mode is invalid
151 (i.e changing from FILE_SHARE_WRITE to FILE_SHARE_READ is invalid).
152 However, if one of the share flags is the same
153 (i.e changing from FILE_SHARE_WRITE to FILE_SHARE_READ | FILE_SHARE_WRITE)
154 the result is valid. (Please note that FILE_SHARE_READ is ignored
157 else if( (dwShareMode & FILE_SHARE_READ) &&
158 !(dwShareMode & FILE_SHARE_WRITE) &&
159 !(fileLocks->share_mode & FILE_SHARE_READ))
162 palError = ERROR_SHARING_VIOLATION;
163 goto GetLockControllerForFileExit;
165 else if( (dwShareMode & FILE_SHARE_WRITE) &&
166 !(dwShareMode & FILE_SHARE_READ) &&
167 !(fileLocks->share_mode & FILE_SHARE_WRITE))
169 palError = ERROR_SHARING_VIOLATION;
170 goto GetLockControllerForFileExit;
172 /* Changing to a less permissive sharing permissions is valid
173 if the file handle doesn't have an access right that conflicts with
174 the sharing permissions we are trying to set
175 (ex: changing from FILE_SHARE_READ|FILE_SHARE_WRITE to FILE_SHARE_WRITE
176 isn't valid if the file descriptor still has a GENERIC_READ permission).
178 else if( (fileLocks->nbReadAccess) &&
179 !(dwShareMode & FILE_SHARE_READ) )
181 palError = ERROR_SHARING_VIOLATION;
182 goto GetLockControllerForFileExit;
184 else if( (fileLocks->nbWriteAccess) &&
185 !(dwShareMode & FILE_SHARE_WRITE) )
187 palError = ERROR_SHARING_VIOLATION;
188 goto GetLockControllerForFileExit;
191 /* we are trying to change to a less restrictive sharing permission set
192 keep the current permissions */
193 if( (dwShareMode & FILE_SHARE_READ) &&
194 !(fileLocks->share_mode & FILE_SHARE_READ) )
196 dwShareMode = fileLocks->share_mode;
199 if( (dwShareMode & FILE_SHARE_WRITE) &&
200 !(fileLocks->share_mode & FILE_SHARE_WRITE) )
202 dwShareMode = fileLocks->share_mode;
205 pController = InternalNew<CSharedMemoryFileLockController>(dwAccessRights, shmFileLocks);
206 if (NULL == pController)
208 palError = ERROR_OUTOFMEMORY;
209 goto GetLockControllerForFileExit;
213 // pController now owns the shared memory pointer, so make sure we
214 // don't attempt to free it below.
219 /* set the share mode again, it's possible that the share mode is now more
220 restrictive than the previous mode set. */
221 fileLocks->share_mode = dwShareMode;
222 if( dwAccessRights & GENERIC_READ )
224 fileLocks->nbReadAccess++;
226 if( dwAccessRights & GENERIC_WRITE )
228 fileLocks->nbWriteAccess++;
231 // ************** NOTE **************
232 // If you add any error paths after this point you must communicate the value of dwAccessRights to
233 // FILECleanUpLockedRgn() in the cleanup code below so that it can correctly undo the changes to
234 // fileLocks->nbReadAccess and nbWriteAccess made above.
235 // ************** NOTE **************
237 GetLockControllerForFileExit:
239 if (NO_ERROR == palError)
241 *ppLockController = pController;
245 if (NULL != pController)
247 pController->ReleaseController();
250 if (NULL != shmFileLocks)
252 FILECleanUpLockedRgn(
266 CSharedMemoryFileLockMgr::GetFileShareModeForFile(
270 PAL_ERROR palError = NO_ERROR;
271 *pdwShareMode = SHARE_MODE_NOT_INITALIZED;
272 SHMPTR shmFileLocks = NULL;
273 SHMFILELOCKS* fileLocks = NULL;
277 palError = FILEGetSHMFileLocks(szFileName, &shmFileLocks, TRUE);
278 if (NO_ERROR != palError || shmFileLocks == NULL)
280 goto GetLockControllerForFileExit;
283 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, fileLocks, shmFileLocks) == FALSE)
285 ASSERT("Unable to get pointer from shm pointer.\n");
286 palError = ERROR_INTERNAL_ERROR;
287 goto GetLockControllerForFileExit;
290 *pdwShareMode = fileLocks->share_mode;
292 GetLockControllerForFileExit:
294 if (NULL != shmFileLocks)
296 FILECleanUpLockedRgn(
309 CSharedMemoryFileLockController::GetTransactionLock(
310 CPalThread *pThread, // IN, OPTIONAL
311 FileTransactionLockType eLockType,
314 DWORD nNumberOfBytesToLockLow,
315 DWORD nNumberOfBytesToLockHigh,
316 IFileTransactionLock **ppTransactionLock // OUT
319 PAL_ERROR palError = NO_ERROR;
321 UINT64 nbBytesToLock;
323 lockRgnStart = ((UINT64)dwOffsetHigh) << 32 | dwOffsetLow;
324 nbBytesToLock = ((UINT64)nNumberOfBytesToLockHigh) << 32 |
325 nNumberOfBytesToLockLow;
327 palError = FILELockFileRegion(
329 reinterpret_cast<PVOID>(this),
335 if (NO_ERROR == palError)
337 *ppTransactionLock = InternalNew<CSharedMemoryFileTransactionLock>(m_shmFileLocks,
338 reinterpret_cast<PVOID>(this),
341 if (NULL == *ppTransactionLock)
343 palError = ERROR_OUTOFMEMORY;
344 FILEUnlockFileRegion(
346 reinterpret_cast<PVOID>(this),
358 CSharedMemoryFileLockController::CreateFileLock(
359 CPalThread *pThread, // IN, OPTIONAL
362 DWORD nNumberOfBytesToLockLow,
363 DWORD nNumberOfBytesToLockHigh,
364 FileLockExclusivity eFileLockExclusivity,
365 FileLockWaitMode eFileLockWaitMode
368 PAL_ERROR palError = NO_ERROR;
370 UINT64 nbBytesToLock;
372 if (ExclusiveFileLock != eFileLockExclusivity
373 || FailImmediately != eFileLockWaitMode)
375 ASSERT("LockFileEx functionality not yet supported");
376 palError = ERROR_NOT_SUPPORTED;
377 goto CreateFileLockExit;
380 lockRgnStart = ((UINT64)dwOffsetHigh) << 32 | dwOffsetLow;
381 nbBytesToLock = ((UINT64)nNumberOfBytesToLockHigh) << 32 |
382 nNumberOfBytesToLockLow;
384 palError = FILELockFileRegion(
386 reinterpret_cast<PVOID>(this),
398 CSharedMemoryFileLockController::ReleaseFileLock(
399 CPalThread *pThread, // IN, OPTIONAL
402 DWORD nNumberOfBytesToUnlockLow,
403 DWORD nNumberOfBytesToUnlockHigh
406 PAL_ERROR palError = NO_ERROR;
407 UINT64 unlockRgnStart;
408 UINT64 nbBytesToUnlock;
410 unlockRgnStart = ((UINT64)dwOffsetHigh) << 32 | dwOffsetLow;
411 nbBytesToUnlock = ((UINT64)nNumberOfBytesToUnlockHigh) << 32 |
412 nNumberOfBytesToUnlockLow;
414 palError = FILEUnlockFileRegion(
416 reinterpret_cast<PVOID>(this),
426 CSharedMemoryFileLockController::ReleaseController()
428 if (NULL != m_shmFileLocks)
430 FILECleanUpLockedRgn(
433 reinterpret_cast<PVOID>(this)
437 InternalDelete(this);
441 CSharedMemoryFileTransactionLock::ReleaseLock()
443 FILEUnlockFileRegion(
445 m_pvControllerInstance,
451 InternalDelete(this);
457 PVOID pvControllerInstance,
459 UINT64 nbBytesToLock,
463 PAL_ERROR palError = NO_ERROR;
464 SHMFILELOCKRGNS *curLock, *prevLock, *insertAfter,
465 lockRgn, fakeLock = {0,0,0,0};
466 SHMFILELOCKS *fileLocks;
470 /* nothing to do if the region to lock is empty */
471 if (nbBytesToLock == 0)
473 TRACE("Locking an empty region (%I64d, %I64d)\n", lockRgnStart, nbBytesToLock);
477 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, fileLocks, shmFileLocks) == FALSE || fileLocks == NULL)
479 ASSERT("Unable to get pointer from shm pointer.\n");
480 palError = ERROR_INTERNAL_ERROR;
484 if (fileLocks->fileLockedRgns != 0)
486 prevLock = &fakeLock;
488 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLock, fileLocks->fileLockedRgns)
491 ASSERT("Unable to get pointer from shm pointer.\n");
492 palError = ERROR_INTERNAL_ERROR;
496 lockRgn.lockRgnStart = lockRgnStart;
497 lockRgn.nbBytesLocked = nbBytesToLock;
498 lockRgn.pvControllerInstance = pvControllerInstance;
499 lockRgn.processId = GetCurrentProcessId();
500 lockRgn.lockType = lockAction;
502 while((curLock != NULL) && IS_LOCK_BEFORE(curLock, &lockRgn))
505 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLock, curLock->next) == FALSE)
507 ASSERT("Unable to get pointer from shm pointer.\n");
508 palError = ERROR_INTERNAL_ERROR;
513 while((curLock != NULL) && IS_LOCK_INTERSECT(curLock, &lockRgn))
515 /* we couldn't lock the requested region if it overlap with other
516 region locked explicitly (by LockFile call) by other file pointer */
517 if ((lockAction == USER_LOCK_RGN) ||
518 ((curLock->lockType == USER_LOCK_RGN) &&
519 !IS_LOCK_HAVE_SAME_OWNER(curLock, &lockRgn)))
521 WARN("The requested lock region overlaps an existing locked region\n");
522 palError = ERROR_LOCK_VIOLATION;
527 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLock, curLock->next) == FALSE)
529 ASSERT("Unable to get pointer from shm pointer.\n");
530 palError = ERROR_INTERNAL_ERROR;
535 /* save the previous lock in case we need to insert the requested lock */
536 insertAfter = prevLock;
538 while(((curLock != NULL) && IS_LOCK_INTERSECT(&lockRgn, curLock)))
540 /* we couldn't lock the requested region if it overlap with other region
541 locked explicitly (by LockFile call) by other file pointer */
542 if ((lockAction == USER_LOCK_RGN) ||
543 ((curLock->lockType == USER_LOCK_RGN) &&
544 !IS_LOCK_HAVE_SAME_OWNER(curLock, &lockRgn)))
546 WARN("The requested lock region overlaps an existing locked region\n");
547 palError = ERROR_LOCK_VIOLATION;
552 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLock, curLock->next) == FALSE)
554 ASSERT("Unable to get pointer from shm pointer.\n");
555 palError = ERROR_INTERNAL_ERROR;
560 if (insertAfter == &fakeLock)
565 palError = FILEAddNewLockedRgn(
567 pvControllerInstance,
574 if (NO_ERROR != palError)
576 WARN("Couldn't add the new locked region into SHM\n");
580 else /* lock region list is empty. */
582 palError = FILEAddNewLockedRgn(
584 pvControllerInstance,
591 if (NO_ERROR != palError)
593 ERROR("Couldn't add the first file locked region \n");
604 FILEUnlockFileRegion(
606 PVOID pvControllerInstance,
607 UINT64 unlockRgnStart,
608 UINT64 nbBytesToUnlock,
612 PAL_ERROR palError = NO_ERROR;
613 SHMFILELOCKRGNS *prevLock = NULL, *curLockRgn = NULL, unlockRgn;
614 SHMPTR shmcurLockRgn;
615 SHMFILELOCKS *fileLocks;
620 /* check if the region to unlock is empty or not */
621 if (nbBytesToUnlock == 0)
623 palError = ERROR_NOT_LOCKED;
624 WARN("Attempt to unlock an empty region\n");
628 if ((SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, fileLocks, shmFileLocks) == FALSE) ||
629 (fileLocks == NULL) ||
630 (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, fileLocks->fileLockedRgns) == FALSE))
632 ASSERT("Unable to get pointer from shm pointer.\n");
633 palError = ERROR_INTERNAL_ERROR;
637 unlockRgn.processId = GetCurrentProcessId();
638 unlockRgn.pvControllerInstance = pvControllerInstance;
639 unlockRgn.lockRgnStart = unlockRgnStart;
640 unlockRgn.nbBytesLocked = nbBytesToUnlock;
641 unlockRgn.lockType = unlockType;
643 shmcurLockRgn = fileLocks->fileLockedRgns;
645 while((curLockRgn != NULL) && !IS_LOCK_EQUAL(curLockRgn, &unlockRgn))
647 prevLock = curLockRgn;
648 shmcurLockRgn = curLockRgn->next;
649 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE)
651 ASSERT("Unable to get pointer from shm pointer.\n");
656 if (curLockRgn != NULL)
658 TRACE("removing the lock region (%I64u, %I64u)\n",
659 curLockRgn->lockRgnStart, curLockRgn->nbBytesLocked);
661 if (prevLock == NULL)
663 /* removing the first lock */
664 fileLocks->fileLockedRgns = curLockRgn->next;
668 prevLock->next = curLockRgn->next;
674 /* the lock doesn't exist */
675 WARN("Attempt to unlock a non locked region\n");
676 palError = ERROR_NOT_LOCKED;
689 SHMPTR *pshmFileLocks,
693 PAL_ERROR palError = NO_ERROR;
694 SHMPTR shmPtrRet = 0;
695 SHMFILELOCKS *filelocksPtr, *nextFilelocksPtr;
700 shmPtrRet = SHMGetInfo(SIID_FILE_LOCKS);
702 while(shmPtrRet != 0)
704 if ( (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, filelocksPtr, shmPtrRet) == FALSE) ||
705 (SHMPTR_TO_TYPED_PTR_BOOL(char, unix_filename, filelocksPtr->unix_filename) == FALSE))
707 ASSERT("Unable to get pointer from shm pointer.\n");
708 palError = ERROR_INTERNAL_ERROR;
712 if (unix_filename == NULL)
714 ERROR("Unexpected lock file name value.\n");
715 palError = ERROR_INTERNAL_ERROR;
719 if (strcmp(unix_filename, filename) == 0)
721 filelocksPtr->refCount++;
725 shmPtrRet = filelocksPtr->next;
728 /* the file has never been locked before.*/
735 TRACE("Create a new entry in the file lock list in SHM\n");
737 /* Create a new entry in the file lock list in SHM */
738 if ((shmPtrRet = malloc(sizeof(SHMFILELOCKS))) == 0)
740 ERROR("Can't allocate SHMFILELOCKS structure\n");
741 palError = ERROR_NOT_ENOUGH_MEMORY;
745 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, filelocksPtr, shmPtrRet) == FALSE)
747 ASSERT("Unable to get pointer from shm pointer.\n");
748 palError = ERROR_INTERNAL_ERROR;
752 filelocksPtr->unix_filename = strdup(filename);
753 if (filelocksPtr->unix_filename == 0)
755 ERROR("Can't allocate shared memory for filename\n");
756 palError = ERROR_NOT_ENOUGH_MEMORY;
760 filelocksPtr->fileLockedRgns = 0;
761 filelocksPtr->prev = 0;
762 filelocksPtr->next = SHMGetInfo(SIID_FILE_LOCKS);
763 filelocksPtr->refCount = 1;
764 filelocksPtr->share_mode = SHARE_MODE_NOT_INITALIZED;
765 filelocksPtr->nbReadAccess = 0;
766 filelocksPtr->nbWriteAccess = 0;
768 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, nextFilelocksPtr, filelocksPtr->next) == FALSE)
770 ASSERT("Unable to get pointer from shm pointer.\n");
771 palError = ERROR_INTERNAL_ERROR;
775 if (nextFilelocksPtr != NULL)
777 nextFilelocksPtr->prev = shmPtrRet;
780 SHMSetInfo(SIID_FILE_LOCKS, shmPtrRet);
784 free(filelocksPtr->unix_filename);
791 if (NO_ERROR == palError)
793 *pshmFileLocks = shmPtrRet;
801 SHMFILELOCKS* fileLocks,
802 PVOID pvControllerInstance,
803 SHMFILELOCKRGNS *insertAfter,
805 UINT64 nbBytesToLock,
809 PAL_ERROR palError = NO_ERROR;
810 SHMFILELOCKRGNS *newLockRgn, *lockRgnPtr;
811 SHMPTR shmNewLockRgn = NULL;
813 if ((fileLocks == NULL) || (pvControllerInstance == NULL))
815 ASSERT("Invalid Null parameter.\n");
821 /* Create a new entry for the new locked region */
822 TRACE("Create a new entry for the new lock region (%I64u %I64u)\n",
823 lockRgnStart, nbBytesToLock);
825 if ((shmNewLockRgn = malloc(sizeof(SHMFILELOCKRGNS))) == NULL)
827 ERROR("Can't allocate SHMFILELOCKRGNS structure\n");
828 palError = ERROR_NOT_ENOUGH_MEMORY;
832 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, newLockRgn, shmNewLockRgn) == FALSE)
834 ASSERT("Unable to get pointer from shm pointer.\n");
835 palError = ERROR_INTERNAL_ERROR;
839 newLockRgn->processId = GetCurrentProcessId();
840 newLockRgn->pvControllerInstance = pvControllerInstance;
841 newLockRgn->lockRgnStart = lockRgnStart;
842 newLockRgn->nbBytesLocked = nbBytesToLock;
843 newLockRgn->lockType = lockType;
845 /* All locked regions with the same offset should be sorted ascending */
846 /* the sort is based on the length of the locked byte range */
847 if (insertAfter != NULL)
849 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, lockRgnPtr, insertAfter->next) == FALSE)
851 ASSERT("Unable to get pointer from shm pointer.\n");
852 palError = ERROR_INTERNAL_ERROR;
858 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, lockRgnPtr, fileLocks->fileLockedRgns) == FALSE)
860 ASSERT("Unable to get pointer from shm pointer.\n");
861 palError = ERROR_INTERNAL_ERROR;
866 while(lockRgnPtr != NULL)
868 if ( (lockRgnPtr->lockRgnStart == newLockRgn->lockRgnStart) &&
869 (newLockRgn->nbBytesLocked > lockRgnPtr->nbBytesLocked))
871 insertAfter = lockRgnPtr;
872 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, lockRgnPtr, lockRgnPtr->next) == FALSE)
874 ASSERT("Unable to get pointer from shm pointer.\n");
875 palError = ERROR_INTERNAL_ERROR;
884 if (insertAfter != NULL)
886 TRACE("Adding lock after the lock rgn (%I64d %I64d)\n",
887 insertAfter->lockRgnStart,insertAfter->nbBytesLocked);
888 newLockRgn->next = insertAfter->next;
889 insertAfter->next = shmNewLockRgn;
893 TRACE("adding lock into the head of the list\n");
894 newLockRgn->next = fileLocks->fileLockedRgns;
895 fileLocks->fileLockedRgns = shmNewLockRgn;
900 if (NO_ERROR != palError && NULL != shmNewLockRgn)
911 FILECleanUpLockedRgn(
913 DWORD dwAccessRights,
914 PVOID pvControllerInstance
917 SHMFILELOCKRGNS *curLockRgn = NULL, *prevLock = NULL;
918 SHMFILELOCKS *fileLocks, *prevFileLocks, *nextFileLocks;
919 SHMPTR shmcurLockRgn;
923 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, fileLocks, shmFileLocks) == FALSE)
925 ASSERT("Unable to get pointer from shm pointer.\n");
929 if (fileLocks != NULL)
931 if(fileLocks->fileLockedRgns !=0)
933 shmcurLockRgn = fileLocks->fileLockedRgns;
934 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE)
936 ASSERT("Unable to get pointer from shm pointer.\n");
940 while(curLockRgn != NULL)
942 if ((curLockRgn->pvControllerInstance == pvControllerInstance) &&
943 (curLockRgn->processId == GetCurrentProcessId()))
945 /* found the locked rgn to remove from SHM */
946 TRACE("Removing the locked region (%I64u, %I64u) from SMH\n",
947 curLockRgn->lockRgnStart, curLockRgn->nbBytesLocked);
949 if (prevLock == NULL)
951 /* removing the first lock */
952 fileLocks->fileLockedRgns = curLockRgn->next;
954 shmcurLockRgn = fileLocks->fileLockedRgns;
955 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE)
957 ASSERT("Unable to get pointer from shm pointer.\n");
963 prevLock->next = curLockRgn->next;
965 shmcurLockRgn = prevLock->next;
966 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE)
968 ASSERT("Unable to get pointer from shm pointer.\n");
975 prevLock = curLockRgn;
976 shmcurLockRgn = curLockRgn->next;
977 if (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKRGNS, curLockRgn, shmcurLockRgn) == FALSE)
979 ASSERT("Unable to get pointer from shm pointer.\n");
985 if (dwAccessRights & GENERIC_READ)
987 fileLocks->nbReadAccess--;
989 if (dwAccessRights & GENERIC_WRITE)
991 fileLocks->nbWriteAccess--;
994 /* remove the SHMFILELOCKS structure from SHM if there's no more locked
995 region left and no more reference to it */
996 if ((--(fileLocks->refCount) == 0) && (fileLocks->fileLockedRgns == 0))
998 TRACE("Removing the SHMFILELOCKS structure from SHM\n");
1000 if ( (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, prevFileLocks, fileLocks->prev) == FALSE) ||
1001 (SHMPTR_TO_TYPED_PTR_BOOL(SHMFILELOCKS, nextFileLocks, fileLocks->next) == FALSE))
1003 ASSERT("Unable to get pointer from shm pointer.\n");
1007 if (prevFileLocks == NULL)
1009 /* removing the first lock file*/
1010 SHMSetInfo(SIID_FILE_LOCKS, fileLocks->next);
1014 prevFileLocks->next = fileLocks->next;
1017 if (nextFileLocks != NULL)
1019 nextFileLocks->prev = fileLocks->prev;
1022 if (fileLocks->unix_filename)
1023 free(fileLocks->unix_filename);