NTSTATUS SrvTreeFindAsyncState( PLWIO_SRV_TREE pTree, ULONG64 ullAsyncId, PLWIO_ASYNC_STATE* ppAsyncState ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLWIO_ASYNC_STATE pAsyncState = NULL; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pTree->mutex); ntStatus = LwRtlRBTreeFind( pTree->pAsyncStateCollection, &ullAsyncId, (PVOID*)&pAsyncState); BAIL_ON_NT_STATUS(ntStatus); *ppAsyncState = SrvAsyncStateAcquire(pAsyncState); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: *ppAsyncState = NULL; goto cleanup; }
NTSTATUS SrvSession2FindTree( PLWIO_SRV_SESSION_2 pSession, ULONG ulTid, PLWIO_SRV_TREE_2* ppTree ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_TREE_2 pTree = NULL; ntStatus = SrvSession2UpdateLastActivityTime(pSession); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pSession->mutex); pTree = pSession->lruTree[ulTid % SRV_LRU_CAPACITY]; if (!pTree || (pTree->ulTid != ulTid)) { ntStatus = LwRtlRBTreeFind( pSession->pTreeCollection, &ulTid, (PVOID*)&pTree); BAIL_ON_NT_STATUS(ntStatus); pSession->lruTree[ ulTid % SRV_LRU_CAPACITY ] = pTree; } InterlockedIncrement(&pTree->refcount); *ppTree = pTree; cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_NETWORK_NAME_DELETED; } *ppTree = NULL; goto cleanup; }
NTSTATUS SrvSessionFindTree( PLWIO_SRV_SESSION pSession, USHORT tid, PLWIO_SRV_TREE* ppTree ) { NTSTATUS ntStatus = 0; BOOLEAN bInLock = FALSE; PLWIO_SRV_TREE pTree = NULL; ntStatus = SrvSessionUpdateLastActivityTime(pSession); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pSession->mutex); pTree = pSession->lruTree[tid % SRV_LRU_CAPACITY]; if (!pTree || (pTree->tid != tid)) { ntStatus = LwRtlRBTreeFind( pSession->pTreeCollection, &tid, (PVOID*)&pTree); BAIL_ON_NT_STATUS(ntStatus); pSession->lruTree[tid % SRV_LRU_CAPACITY] = pTree; } InterlockedIncrement(&pTree->refcount); *ppTree = pTree; cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pSession->mutex); return ntStatus; error: if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_INVALID_HANDLE; } *ppTree = NULL; goto cleanup; }
NTSTATUS SrvTree2FindFile( PLWIO_SRV_TREE_2 pTree, PSMB2_FID pFid, PLWIO_SRV_FILE_2* ppFile ) { NTSTATUS ntStatus = 0; PLWIO_SRV_FILE_2 pFile = NULL; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pTree->mutex); pFile = pTree->lruFile[ pFid->ullVolatileId % SRV_LRU_CAPACITY ]; if (!pFile || (pFile->fid.ullPersistentId != pFid->ullPersistentId) || (pFile->fid.ullVolatileId != pFid->ullVolatileId)) { ntStatus = LwRtlRBTreeFind( pTree->pFileCollection, pFid, (PVOID*)&pFile); BAIL_ON_NT_STATUS(ntStatus); pTree->lruFile[pFid->ullVolatileId % SRV_LRU_CAPACITY] = pFile; } InterlockedIncrement(&pFile->refcount); *ppFile = pFile; cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_FILE_CLOSED; } *ppFile = NULL; goto cleanup; }
NTSTATUS SrvTreeAddAsyncState( PLWIO_SRV_TREE pTree, PLWIO_ASYNC_STATE pAsyncState ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; PLWIO_ASYNC_STATE pAsyncState1 = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pTree->mutex); ntStatus = LwRtlRBTreeFind( pTree->pAsyncStateCollection, &pAsyncState->ullAsyncId, (PVOID*)&pAsyncState1); switch (ntStatus) { case STATUS_NOT_FOUND: ntStatus = LwRtlRBTreeAdd( pTree->pAsyncStateCollection, &pAsyncState->ullAsyncId, pAsyncState); BAIL_ON_NT_STATUS(ntStatus); SrvAsyncStateAcquire(pAsyncState); break; case STATUS_SUCCESS: ntStatus = STATUS_DUPLICATE_OBJECTID; break; default: ; } BAIL_ON_NT_STATUS(ntStatus); error: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; }
NTSTATUS SrvElementsUnregisterResource( ULONG ulResourceId, /* IN */ PSRV_RESOURCE* ppResource /* OUT OPTIONAL*/ ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; PSRV_RESOURCE pResource = NULL; LWIO_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &gSrvElements.resources.mutex); if (ppResource) { ntStatus = LwRtlRBTreeFind( gSrvElements.resources.pResources, &ulResourceId, (PVOID*)&pResource); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LwRtlRBTreeRemove( gSrvElements.resources.pResources, &ulResourceId); BAIL_ON_NT_STATUS(ntStatus); if (ppResource) { *ppResource = pResource; } cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.resources.mutex); return ntStatus; error: if (ppResource) { *ppResource = NULL; } goto cleanup; }
NTSTATUS SrvElementsFindResource( ULONG ulResourceId, SRV_RESOURCE_TYPE resourceType, PFN_ENUM_RESOURCES pfnEnumResourcesCB, PVOID pUserData ) { NTSTATUS ntStatus = STATUS_SUCCESS; BOOLEAN bInLock = FALSE; PSRV_RESOURCE pResource = NULL; BOOLEAN bContinue = FALSE; if ((resourceType == SRV_RESOURCE_TYPE_UNKNOWN) || !pfnEnumResourcesCB) { ntStatus = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(ntStatus); } LWIO_LOCK_RWMUTEX_SHARED(bInLock, &gSrvElements.resources.mutex); ntStatus = LwRtlRBTreeFind( gSrvElements.resources.pResources, &ulResourceId, (PVOID*)&pResource); BAIL_ON_NT_STATUS(ntStatus); if (pResource->resourceType != resourceType) { ntStatus = STATUS_NOT_FOUND; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = pfnEnumResourcesCB(pResource, pUserData, &bContinue); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &gSrvElements.resources.mutex); return ntStatus; error: goto cleanup; }
NTSTATUS SrvTreeFindFile( PLWIO_SRV_TREE pTree, USHORT fid, PLWIO_SRV_FILE* ppFile ) { NTSTATUS ntStatus = 0; PLWIO_SRV_FILE pFile = NULL; BOOLEAN bInLock = FALSE; LWIO_LOCK_RWMUTEX_SHARED(bInLock, &pTree->mutex); pFile = pTree->lruFile[fid % SRV_LRU_CAPACITY]; if (!pFile || (pFile->fid != fid)) { ntStatus = LwRtlRBTreeFind( pTree->pFileCollection, &fid, (PVOID*)&pFile); BAIL_ON_NT_STATUS(ntStatus); pTree->lruFile[fid % SRV_LRU_CAPACITY] = pFile; } *ppFile = SrvFileAcquire(pFile); cleanup: LWIO_UNLOCK_RWMUTEX(bInLock, &pTree->mutex); return ntStatus; error: if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_INVALID_HANDLE; } *ppFile = NULL; goto cleanup; }
NTSTATUS SrvFinderGetSearchSpace( IN HANDLE hFinderRepository, IN USHORT usSearchId, OUT PHANDLE phFinder ) { NTSTATUS ntStatus = 0; PSRV_FINDER_REPOSITORY pFinderRepository = NULL; PSRV_SEARCH_SPACE pSearchSpace = NULL; BOOLEAN bInLock = FALSE; pFinderRepository = (PSRV_FINDER_REPOSITORY)hFinderRepository; LWIO_LOCK_MUTEX(bInLock, &pFinderRepository->mutex); ntStatus = LwRtlRBTreeFind( pFinderRepository->pSearchSpaceCollection, &usSearchId, (PVOID*)&pSearchSpace); BAIL_ON_NT_STATUS(ntStatus); InterlockedIncrement(&pSearchSpace->refCount); *phFinder = pSearchSpace; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pFinderRepository->mutex); return ntStatus; error: *phFinder = NULL; goto cleanup; }
static NTSTATUS SrvSession2AcquireTreeId_inlock( PLWIO_SRV_SESSION_2 pSession, PULONG pulTid ) { NTSTATUS ntStatus = 0; ULONG ulCandidateTid = pSession->ulNextAvailableTid; BOOLEAN bFound = FALSE; do { PLWIO_SRV_TREE_2 pTree = NULL; /* 0 is never a valid tid */ if ((ulCandidateTid == 0) || (ulCandidateTid == UINT32_MAX)) { ulCandidateTid = 1; } ntStatus = LwRtlRBTreeFind( pSession->pTreeCollection, &ulCandidateTid, (PVOID*)&pTree); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { ulCandidateTid++; } BAIL_ON_NT_STATUS(ntStatus); } while ((ulCandidateTid != pSession->ulNextAvailableTid) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_LINKS; BAIL_ON_NT_STATUS(ntStatus); } *pulTid = ulCandidateTid; /* Increment by 1 by make sure tyo deal with wraparound */ ulCandidateTid++; pSession->ulNextAvailableTid = ulCandidateTid ? ulCandidateTid : 1; cleanup: return ntStatus; error: *pulTid = 0; goto cleanup; }
static NTSTATUS SrvElementsResourceAcquireId_inlock( PSRV_ELEMENTS_RESOURCES pResources, PULONG pulResourceId ) { NTSTATUS ntStatus = 0; ULONG ulResourceId = pResources->ulNextAvailableId; BOOLEAN bFound = FALSE; do { PSRV_RESOURCE pResource = NULL; /* 0 is never a valid resource id */ if ((ulResourceId == 0) || (ulResourceId == UINT32_MAX)) { ulResourceId = 1; } ntStatus = LwRtlRBTreeFind( pResources->pResources, &ulResourceId, (PVOID*)&pResource); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { ulResourceId++; } BAIL_ON_NT_STATUS(ntStatus); } while ((ulResourceId != pResources->ulNextAvailableId) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_OPENED_FILES; BAIL_ON_NT_STATUS(ntStatus); } *pulResourceId = ulResourceId; /* Increment by 1 by make sure to deal with wrap-around */ ulResourceId++; pResources->ulNextAvailableId = ulResourceId ? ulResourceId : 1; cleanup: return ntStatus; error: *pulResourceId = 0; goto cleanup; }
static NTSTATUS SrvTree2AcquireFileId_inlock( PLWIO_SRV_TREE_2 pTree, PSMB2_FID pFid ) { NTSTATUS ntStatus = 0; SMB2_FID candidateFid = { .ullPersistentId = 0xFFFFFFFFFFFFFFFFLL, .ullVolatileId = pTree->ullNextAvailableFid }; BOOLEAN bFound = FALSE; BOOLEAN bInLock = FALSE; union { ULONG64 ullFileId; struct { ULONG ulFileId1; ULONG ulFileId2; } fileIdParts; } fileId; do { PLWIO_SRV_FILE_2 pFile = NULL; /* 0 is never a valid fid */ if ((candidateFid.ullVolatileId == 0) || (candidateFid.ullVolatileId == UINT64_MAX)) { candidateFid.ullVolatileId = 1; } ntStatus = LwRtlRBTreeFind( pTree->pFileCollection, &candidateFid, (PVOID*)&pFile); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { candidateFid.ullVolatileId++; } BAIL_ON_NT_STATUS(ntStatus); } while ( (candidateFid.ullVolatileId != pTree->ullNextAvailableFid) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_OPENED_FILES; BAIL_ON_NT_STATUS(ntStatus); } LWIO_LOCK_MUTEX(bInLock, gSrvElements.pMutex); fileId.fileIdParts.ulFileId1 = mt_genrand_int32(&gSrvElements.randGen); fileId.fileIdParts.ulFileId2 = mt_genrand_int32(&gSrvElements.randGen); candidateFid.ullPersistentId = fileId.ullFileId; LWIO_UNLOCK_MUTEX(bInLock, gSrvElements.pMutex); *pFid = candidateFid; /* Increment by 1 by make sure to deal with wraparound */ candidateFid.ullVolatileId++; pTree->ullNextAvailableFid = candidateFid.ullVolatileId ? candidateFid.ullVolatileId : 1; cleanup: return ntStatus; error: pFid->ullPersistentId = 0LL; pFid->ullVolatileId = 0LL; goto cleanup; } static int SrvTree2FileCompare( PVOID pKey1, PVOID pKey2 ) { PSMB2_FID pFid1 = (PSMB2_FID)pKey1; PSMB2_FID pFid2 = (PSMB2_FID)pKey2; return memcmp((PBYTE)pFid1, (PBYTE)pFid2, sizeof(SMB2_FID)); }
static NTSTATUS SrvTreeAcquireFileId_inlock( PLWIO_SRV_TREE pTree, PUSHORT pFid ) { NTSTATUS ntStatus = 0; USHORT candidateFid = pTree->nextAvailableFid; BOOLEAN bFound = FALSE; do { PLWIO_SRV_FILE pFile = NULL; /* 0 is never a valid fid */ if ((candidateFid == 0) || (candidateFid == UINT16_MAX)) { candidateFid = 1; } ntStatus = LwRtlRBTreeFind( pTree->pFileCollection, &candidateFid, (PVOID*)&pFile); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { candidateFid++; } BAIL_ON_NT_STATUS(ntStatus); } while ((candidateFid != pTree->nextAvailableFid) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_OPENED_FILES; BAIL_ON_NT_STATUS(ntStatus); } *pFid = candidateFid; /* Increment by 1 by make sure tyo deal with wraparound */ candidateFid++; pTree->nextAvailableFid = candidateFid ? candidateFid : 1; cleanup: return ntStatus; error: *pFid = 0; goto cleanup; }
NTSTATUS SrvFinderCreateSearchSpace( IN IO_FILE_HANDLE hRootFileHandle, IN PSRV_SHARE_INFO pShareInfo, IN PIO_CREATE_SECURITY_CONTEXT pIoSecurityContext, IN HANDLE hFinderRepository, IN PWSTR pwszFilesystemPath, IN PWSTR pwszSearchPattern, IN SMB_FILE_ATTRIBUTES usSearchAttrs, IN USHORT usFlags, IN ULONG ulSearchStorageType, IN SMB_INFO_LEVEL infoLevel, IN BOOLEAN bUseLongFilenames, IN ACCESS_MASK accessMask, OUT PHANDLE phFinder, OUT PUSHORT pusSearchId ) { NTSTATUS ntStatus = 0; IO_FILE_HANDLE hFile = NULL; IO_STATUS_BLOCK ioStatusBlock = {0}; IO_FILE_NAME fileName = {0}; PVOID pSecurityDescriptor = NULL; PVOID pSecurityQOS = NULL; PSRV_FINDER_REPOSITORY pFinderRepository = NULL; PSRV_SEARCH_SPACE pSearchSpace = NULL; USHORT usCandidateSearchId = 0; BOOLEAN bFound = FALSE; BOOLEAN bInLock = FALSE; PIO_ECP_LIST pEcpList = NULL; FILE_CREATE_OPTIONS createOptions = 0; pFinderRepository = (PSRV_FINDER_REPOSITORY)hFinderRepository; fileName.RootFileHandle = hRootFileHandle; ntStatus = LwRtlUnicodeStringInitEx(&fileName.Name, pwszFilesystemPath); BAIL_ON_NT_STATUS(ntStatus); if (pShareInfo->Flags & SHARE_INFO_FLAG_ABE_ENABLED) { ntStatus = IoRtlEcpListAllocate(&pEcpList); BAIL_ON_NT_STATUS(ntStatus); ntStatus = SrvIoPrepareAbeEcpList(pEcpList); BAIL_ON_NT_STATUS(ntStatus); } if (usFlags & SMB_FIND_WITH_BACKUP_INTENT) { createOptions |= FILE_OPEN_FOR_BACKUP_INTENT; } ntStatus = SrvIoCreateFile( pShareInfo, &hFile, NULL, &ioStatusBlock, pIoSecurityContext, &fileName, pSecurityDescriptor, pSecurityQOS, accessMask, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, FILE_OPEN, createOptions, NULL, /* EA Buffer */ 0, /* EA Length */ pEcpList); BAIL_ON_NT_STATUS(ntStatus); LWIO_LOCK_MUTEX(bInLock, &pFinderRepository->mutex); usCandidateSearchId = pFinderRepository->usNextSearchId; do { PSRV_SEARCH_SPACE pSearchSpace = NULL; // 0 is not a valid search id if (!usCandidateSearchId || (usCandidateSearchId == UINT16_MAX)) { usCandidateSearchId = 1; } ntStatus = LwRtlRBTreeFind( pFinderRepository->pSearchSpaceCollection, &usCandidateSearchId, (PVOID*)&pSearchSpace); if (ntStatus == STATUS_NOT_FOUND) { ntStatus = STATUS_SUCCESS; bFound = TRUE; } else { usCandidateSearchId++; } BAIL_ON_NT_STATUS(ntStatus); } while ((usCandidateSearchId != pFinderRepository->usNextSearchId) && !bFound); if (!bFound) { ntStatus = STATUS_TOO_MANY_OPENED_FILES; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = SrvAllocateMemory( sizeof(SRV_SEARCH_SPACE), (PVOID*)&pSearchSpace); BAIL_ON_NT_STATUS(ntStatus); pSearchSpace->refCount = 1; pthread_mutex_init(&pSearchSpace->mutex, NULL); pSearchSpace->pMutex = &pSearchSpace->mutex; pSearchSpace->usSearchId = usCandidateSearchId; ntStatus = LwRtlRBTreeAdd( pFinderRepository->pSearchSpaceCollection, &pSearchSpace->usSearchId, pSearchSpace); BAIL_ON_NT_STATUS(ntStatus); pSearchSpace->hFile = hFile; hFile = NULL; pSearchSpace->infoLevel = infoLevel; pSearchSpace->usSearchAttrs = usSearchAttrs; pSearchSpace->ulSearchStorageType = ulSearchStorageType; pSearchSpace->bUseLongFilenames = bUseLongFilenames; ntStatus = SrvAllocateStringW( pwszSearchPattern, &pSearchSpace->pwszSearchPattern); BAIL_ON_NT_STATUS(ntStatus); InterlockedIncrement(&pSearchSpace->refCount); pFinderRepository->usNextSearchId = usCandidateSearchId + 1; *phFinder = pSearchSpace; *pusSearchId = usCandidateSearchId; cleanup: LWIO_UNLOCK_MUTEX(bInLock, &pFinderRepository->mutex); if (pEcpList) { IoRtlEcpListFree(&pEcpList); } return ntStatus; error: *phFinder = NULL; *pusSearchId = 0; if (pSearchSpace) { SrvFinderReleaseSearchSpace(pSearchSpace); } if (hFile) { IoCloseFile(hFile); } goto cleanup; }