Пример #1
0
VOID PkUpdateArchiveExtractCallback::SetNewJob(IInArchive *NewInArchive, ULONG NewItemIndex, IOutStream *NewOutStream)
{
    PhAcquireQueuedLockExclusive(&Lock);

    // Wait for the current job to finish.
    while (!ThreadStopping && ItemIndex != -1)
        PhWaitForCondition(&Condition, &Lock, NULL);

    if (ThreadStopping)
        return;

    if (NewInArchive)
        NewInArchive->AddRef();
    if (InArchive)
        InArchive->Release();

    InArchive = NewInArchive;

    ItemIndex = NewItemIndex;

    if (NewOutStream)
        NewOutStream->AddRef();
    if (OutStream)
        OutStream->Release();

    OutStream = NewOutStream;

    PhPulseCondition(&Condition);

    PhReleaseQueuedLockExclusive(&Lock);
}
Пример #2
0
VOID PkUpdateArchiveExtractCallback::StopThread()
{
    SetNewJob(NULL, -1, NULL);

    PhAcquireQueuedLockExclusive(&Lock);
    ThreadStopping = TRUE;
    PhPulseCondition(&Condition);
    PhReleaseQueuedLockExclusive(&Lock);
}
Пример #3
0
HRESULT PkUpdateArchiveExtractCallback::GetStream(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode)
{
    IInArchive *currentArchive;

    // This code executes with the lock held.

    currentArchive = InArchive;

    // Wait until we get a job or the archive has changed.
    while (!ThreadStopping && InArchive == currentArchive && ItemIndex == -1)
    {
        PhWaitForCondition(&Condition, &Lock, NULL);
    }

    if (InArchive != currentArchive)
        return E_ABORT;

    if (index < ItemIndex)
    {
        // Keep searching.
        *outStream = &(new PkFileStream(PkZeroFileStream, NULL))->OutStream;
        return S_OK;
    }
    else if (index == ItemIndex)
    {
        *outStream = OutStream;
        OutStream = NULL;
        ItemIndex = -1;
        PhPulseCondition(&Condition);

        return S_OK;
    }
    else
    {
        // We've gone past the item.
        return E_ABORT;
    }
}
Пример #4
0
NTSTATUS PhpWorkQueueThreadStart(
    _In_ PVOID Parameter
    )
{
    PPH_WORK_QUEUE workQueue = (PPH_WORK_QUEUE)Parameter;

    while (TRUE)
    {
        NTSTATUS status;
        HANDLE semaphoreHandle;
        LARGE_INTEGER timeout;
        PPH_WORK_QUEUE_ITEM workQueueItem = NULL;

        // Check if we have more threads than the limit.
        if (workQueue->CurrentThreads > workQueue->MaximumThreads)
        {
            BOOLEAN terminate = FALSE;

            // Lock and re-check.
            PhAcquireQueuedLockExclusive(&workQueue->StateLock);

            // Check the minimum as well.
            if (workQueue->CurrentThreads > workQueue->MaximumThreads &&
                workQueue->CurrentThreads > workQueue->MinimumThreads)
            {
                workQueue->CurrentThreads--;
                terminate = TRUE;
            }

            PhReleaseQueuedLockExclusive(&workQueue->StateLock);

            if (terminate)
                break;
        }

        semaphoreHandle = PhpGetSemaphoreWorkQueue(workQueue);

        if (!workQueue->Terminating)
        {
            // Wait for work.
            status = NtWaitForSingleObject(
                semaphoreHandle,
                FALSE,
                PhTimeoutFromMilliseconds(&timeout, workQueue->NoWorkTimeout)
                );
        }
        else
        {
            status = STATUS_UNSUCCESSFUL;
        }

        if (status == STATUS_WAIT_0 && !workQueue->Terminating)
        {
            PLIST_ENTRY listEntry;

            // Dequeue the work item.

            PhAcquireQueuedLockExclusive(&workQueue->QueueLock);

            listEntry = RemoveHeadList(&workQueue->QueueListHead);

            if (IsListEmpty(&workQueue->QueueListHead))
                PhPulseCondition(&workQueue->QueueEmptyCondition);

            PhReleaseQueuedLockExclusive(&workQueue->QueueLock);

            // Make sure we got work.
            if (listEntry != &workQueue->QueueListHead)
            {
                workQueueItem = CONTAINING_RECORD(listEntry, PH_WORK_QUEUE_ITEM, ListEntry);

                PhpExecuteWorkQueueItem(workQueueItem);
                _InterlockedDecrement(&workQueue->BusyCount);

                PhpDestroyWorkQueueItem(workQueueItem);
            }
        }
        else
        {
            BOOLEAN terminate = FALSE;

            // No work arrived before the timeout passed, or we are terminating, or some error occurred.
            // Terminate the thread.

            PhAcquireQueuedLockExclusive(&workQueue->StateLock);

            if (workQueue->Terminating || workQueue->CurrentThreads > workQueue->MinimumThreads)
            {
                workQueue->CurrentThreads--;
                terminate = TRUE;
            }

            PhReleaseQueuedLockExclusive(&workQueue->StateLock);

            if (terminate)
                break;
        }
    }

    PhReleaseRundownProtection(&workQueue->RundownProtect);

    return STATUS_SUCCESS;
}
Пример #5
0
HRESULT PkFileInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
    NTSTATUS status;

    if (Parent->Mode == PkPipeReaderFileStream)
    {
        PkFileStream *parentPipe;
        PCHAR currentData;
        ULONG remainingSize;
        ULONG availableSize;

        parentPipe = Parent->ParentPipe;
        currentData = (PCHAR)data;
        remainingSize = size;

        PhAcquireQueuedLockExclusive(&parentPipe->PipeLock);

        while (remainingSize != 0 && parentPipe->RemainingStreamSize != 0)
        {
            if (parentPipe->ReadPosition == parentPipe->ReadableSize)
            {
                if (parentPipe->RemainingStreamSize == 0 || parentPipe->WriteReferenceCount == 0)
                    break;

                PhPulseCondition(&parentPipe->PipeCondition);
                // Wait for the writer to fill up our buffer.
                PhWaitForCondition(&parentPipe->PipeCondition, &parentPipe->PipeLock, NULL);
                continue;
            }

            availableSize = (ULONG)(parentPipe->ReadableSize - parentPipe->ReadPosition);

            if (remainingSize >= availableSize)
            {
                memcpy(currentData, (PCHAR)parentPipe->Buffer + parentPipe->ReadPosition, availableSize);
                currentData += availableSize;
                parentPipe->ReadPosition += availableSize;

                if (parentPipe->RemainingStreamSize >= availableSize)
                    parentPipe->RemainingStreamSize -= availableSize;
                else
                    parentPipe->RemainingStreamSize = 0;

                remainingSize -= availableSize;
            }
            else
            {
                memcpy(currentData, (PCHAR)parentPipe->Buffer + parentPipe->ReadPosition, remainingSize);
                currentData += availableSize;
                parentPipe->ReadPosition += remainingSize;

                if (parentPipe->RemainingStreamSize >= remainingSize)
                    parentPipe->RemainingStreamSize -= remainingSize;
                else
                    parentPipe->RemainingStreamSize = 0;

                remainingSize = 0;
            }
        }

        PhReleaseQueuedLockExclusive(&parentPipe->PipeLock);

        *processedSize = size - remainingSize;

        return S_OK;
    }
    else if (Parent->Mode == PkPipeWriterFileStream)
    {
        return E_FAIL;
    }

    if (!Parent->FileStream)
    {
        *processedSize = 0;
        return S_OK;
    }

    *processedSize = 0;
    status = PhReadFileStream(Parent->FileStream, data, size, (PULONG)processedSize);

    if (status == STATUS_END_OF_FILE)
    {
        *processedSize = 0;
        return S_OK;
    }

    if (NT_SUCCESS(status))
        return S_OK;
    else
        return E_FAIL;
}
Пример #6
0
HRESULT PkFileOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
    NTSTATUS status;

    if (Parent->Mode == PkPipeWriterFileStream)
    {
        PkFileStream *parentPipe;
        PCHAR currentData;
        SIZE_T remainingSize;

        parentPipe = Parent->ParentPipe;
        currentData = (PCHAR)data;
        remainingSize = size;

        PhAcquireQueuedLockExclusive(&parentPipe->PipeLock);

        while (remainingSize != 0)
        {
            if (parentPipe->ReadPosition != parentPipe->ReadableSize)
            {
                if (parentPipe->ReadReferenceCount == 0)
                    break;

                // Wait for the reader to read everything.
                PhWaitForCondition(&parentPipe->PipeCondition, &parentPipe->PipeLock, NULL);
                continue;
            }

            if (remainingSize >= parentPipe->BufferSize)
            {
                memcpy(parentPipe->Buffer, currentData, parentPipe->BufferSize);
                currentData += parentPipe->BufferSize;
                parentPipe->ReadableSize = parentPipe->BufferSize;
                remainingSize -= parentPipe->BufferSize;
            }
            else
            {
                memcpy(parentPipe->Buffer, currentData, remainingSize);
                currentData += remainingSize;
                parentPipe->ReadableSize = remainingSize;
                remainingSize = 0;
            }

            parentPipe->ReadPosition = 0;
            PhPulseCondition(&parentPipe->PipeCondition);
        }

        PhReleaseQueuedLockExclusive(&parentPipe->PipeLock);

        *processedSize = size;

        return S_OK;
    }
    else if (Parent->Mode == PkPipeReaderFileStream)
    {
        return E_FAIL;
    }

    if (!Parent->FileStream)
    {
        *processedSize = size;
        return S_OK;
    }

    status = PhWriteFileStream(Parent->FileStream, (PVOID)data, size);
    *processedSize = size;

    if (NT_SUCCESS(status))
        return S_OK;
    else
        return E_FAIL;
}