Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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;
}
Ejemplo n.º 12
0
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));
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
0
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;
}