Esempio n. 1
0
CConnectionPool::~CConnectionPool()
{
    PSLIST_ENTRY entry;

    if (this->list)
    {
        while (NULL != (entry = InterlockedPopEntrySList(this->list)))
        {
            CloseHandle(((PCONNECTION_ENTRY)entry)->connection);
            _aligned_free(entry);
        }

        _aligned_free(this->list);
        this->list = NULL;
    }
}
Esempio n. 2
0
static DWORD WINAPI printer_thread_func(LPVOID arg)
{
	IRP* irp;
	PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg;
	HANDLE obj[] = {printer_dev->event, printer_dev->stopEvent};
	UINT error = CHANNEL_RC_OK;

	while (1)
	{
		DWORD rc = WaitForMultipleObjects(2, obj, FALSE, INFINITE);

		if (rc == WAIT_FAILED)
		{
			error = GetLastError();
			WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", error);
			break;
		}

		if (rc == WAIT_OBJECT_0 + 1)
			break;
		else if (rc != WAIT_OBJECT_0)
			continue;

		ResetEvent(printer_dev->event);
		irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList);

		if (irp == NULL)
		{
			WLog_ERR(TAG, "InterlockedPopEntrySList failed!");
			error = ERROR_INTERNAL_ERROR;
			break;
		}

		if ((error = printer_process_irp(printer_dev, irp)))
		{
			WLog_ERR(TAG, "printer_process_irp failed with error %"PRIu32"!", error);
			break;
		}
	}

	if (error && printer_dev->rdpcontext)
		setChannelError(printer_dev->rdpcontext, error,
		                "printer_thread_func reported an error");

	ExitThread(error);
	return error;
}
Esempio n. 3
0
static void parallel_process_irp_list(PARALLEL_DEVICE* parallel)
{
	IRP* irp;

	while (1)
	{
		if (freerdp_thread_is_stopped(parallel->thread))
			break;

		irp = (IRP*) InterlockedPopEntrySList(parallel->pIrpList);

		if (irp == NULL)
			break;

		parallel_process_irp(parallel, irp);
	}
}
Esempio n. 4
0
static void parallel_free(DEVICE* device)
{
	IRP* irp;
	PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device;

	DEBUG_SVC("freeing device");

	freerdp_thread_stop(parallel->thread);
	freerdp_thread_free(parallel->thread);

	while ((irp = (IRP*) InterlockedPopEntrySList(parallel->pIrpList)) != NULL)
		irp->Discard(irp);

	_aligned_free(parallel->pIrpList);

	free(parallel);
}
Esempio n. 5
0
static void smartcard_process_irp_list(SMARTCARD_DEVICE* smartcard)
{
	IRP* irp;

	while (1)
	{
		if (WaitForSingleObject(smartcard->stopEvent, 0) == WAIT_OBJECT_0)
			break;

		irp = (IRP*) InterlockedPopEntrySList(smartcard->pIrpList);

		if (irp == NULL)
			break;

		smartcard_process_irp(smartcard, irp);
	}
}
Esempio n. 6
0
static void drive_process_irp_list(DRIVE_DEVICE* disk)
{
	IRP* irp;

	while (1)
	{
		if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
			break;

		irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList);

		if (irp == NULL)
			break;

		drive_process_irp(disk, irp);
	}
}
Esempio n. 7
0
	// @return OVERLAPPED initialized for I/O starting at offset,
	// or 0 if all available structures have already been allocated.
	OVERLAPPED* Allocate(off_t offset)
	{
		Entry* entry = (Entry*)InterlockedPopEntrySList(&freelist);
		if(!entry)
			return 0;

		OVERLAPPED& ovl = entry->ovl;
		ovl.Internal = 0;
		ovl.InternalHigh = 0;
		ovl.Offset = u64_lo(offset);
		ovl.OffsetHigh = u64_hi(offset);
		ovl.hEvent = 0;	// (notification is via IOCP and/or polling)

		cpu_AtomicAdd(&extant, +1);

		return &ovl;
	}
Esempio n. 8
0
static void printer_process_irp_list(PRINTER_DEVICE* printer_dev)
{
    IRP* irp;

    while (1)
    {
        if (freerdp_thread_is_stopped(printer_dev->thread))
            break;

        irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList);

        if (irp == NULL)
            break;

        printer_process_irp(printer_dev, irp);
    }
}
Esempio n. 9
0
static void printer_free(DEVICE* device)
{
    IRP* irp;
    PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;

    freerdp_thread_stop(printer_dev->thread);
    freerdp_thread_free(printer_dev->thread);

    while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
        irp->Discard(irp);

    _aligned_free(printer_dev->pIrpList);

    if (printer_dev->printer)
        printer_dev->printer->Free(printer_dev->printer);

    free(printer_dev->device.name);

    free(printer_dev);
}
Esempio n. 10
0
void HttpInputQueueDrain(PHTTP_LISTENER listener)
{
	PHTTP_IO_CONTEXT context;
	PSLIST_ENTRY entry;

	PLOOKASIDE inputQueue = listener->HttpInputQueue;
	while(true)
	{
		entry = InterlockedPopEntrySList(&inputQueue->Header);
		if(entry != NULL)
		{
			context = CONTAINING_RECORD(entry, HTTP_IO_CONTEXT, LookAsideEntry);
			HttpListenerCompleteIo(context);
		}
		else
		{
			break;
		}
	}
}
Esempio n. 11
0
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    PTRANSFER_PACKET pkt;
    PSLIST_ENTRY slistEntry;

    slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
    if (slistEntry){
        slistEntry->Next = NULL;
        pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
        InterlockedDecrement(&fdoData->NumFreeTransferPackets);

        // when dequeue'ing the packet, also reset the history data
        HISTORYINITIALIZERETRYLOGS(pkt);

    }
    else {
        if (AllocIfNeeded){
            /*
             *  We are in stress and have run out of lookaside packets.
             *  In order to service the current transfer,
             *  allocate an extra packet.
             *  We will free it lazily when we are out of stress.
             */
            pkt = NewTransferPacket(Fdo);
            if (pkt){
                InterlockedIncrement(&fdoData->NumTotalTransferPackets);
                fdoData->DbgPeakNumTransferPackets = max(fdoData->DbgPeakNumTransferPackets, fdoData->NumTotalTransferPackets);
            }
            else {
                TracePrint((TRACE_LEVEL_WARNING, TRACE_FLAG_RW, "DequeueFreeTransferPacket: packet allocation failed"));
            }
        }
        else {
            pkt = NULL;
        }
    }
        
    return pkt;
}
Esempio n. 12
0
PHTTP_IO_CONTEXT GetIOContext()
{
	PHTTP_IO_CONTEXT pContext;
	PLOOKASIDE pCacheEntry;
	PSLIST_ENTRY pEntry;

	pCacheEntry = &IoContextCacheList[IO_CONTEXT_PROC_INDEX];
	pEntry = InterlockedPopEntrySList(&pCacheEntry->Header);
	if(pEntry != NULL)
	{
		// Return address of the containing structure.
		pContext = CONTAINING_RECORD(pEntry, HTTP_IO_CONTEXT, LookAsideEntry);
	}
	else
	{
		pContext = (PHTTP_IO_CONTEXT)ALLOC_MEM(sizeof(HTTP_IO_CONTEXT));			
	}

	ZeroMemory(pContext, sizeof(HTTP_IO_CONTEXT));	
	return pContext;
}
Esempio n. 13
0
PTRANSFER_PACKET DequeueFreeTransferPacket(PDEVICE_OBJECT Fdo, BOOLEAN AllocIfNeeded)
{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExt = Fdo->DeviceExtension;
    PCLASS_PRIVATE_FDO_DATA fdoData = fdoExt->PrivateFdoData;
    PTRANSFER_PACKET pkt;
    PSINGLE_LIST_ENTRY slistEntry;
    KIRQL oldIrql;

    slistEntry = InterlockedPopEntrySList(&fdoData->FreeTransferPacketsList);
    if (slistEntry){
        slistEntry->Next = NULL;
        pkt = CONTAINING_RECORD(slistEntry, TRANSFER_PACKET, SlistEntry);
        ASSERT(fdoData->NumFreeTransferPackets > 0);
        InterlockedDecrement(&fdoData->NumFreeTransferPackets);
    }
    else {
        if (AllocIfNeeded){
            /*
             *  We are in stress and have run out of lookaside packets.
             *  In order to service the current transfer, 
             *  allocate an extra packet.  
             *  We will free it lazily when we are out of stress.
             */
            pkt = NewTransferPacket(Fdo);
            if (pkt){
                InterlockedIncrement(&fdoData->NumTotalTransferPackets);
                fdoData->DbgPeakNumTransferPackets = max(fdoData->DbgPeakNumTransferPackets, fdoData->NumTotalTransferPackets);
            }
            else {
                DBGWARN(("DequeueFreeTransferPacket: packet allocation failed"));
            }
        }
        else {
            pkt = NULL;
        }
    }
    
    return pkt;
}
Esempio n. 14
0
static void drive_free(DEVICE* device)
{
	IRP* irp;
	DRIVE_FILE* file;
	DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;

	SetEvent(disk->stopEvent);
	CloseHandle(disk->thread);
	CloseHandle(disk->irpEvent);

	while ((irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList)) != NULL)
		irp->Discard(irp);

	_aligned_free(disk->pIrpList);

	while ((file = (DRIVE_FILE*) list_dequeue(disk->files)) != NULL)
		drive_file_free(file);

	list_free(disk->files);

	free(disk);
}
Esempio n. 15
0
static void cp_worker_thread(void *param)
{
	SLIST_ENTRY *entry;
	req_part    *part;
	req_item    *item;
	const char  *in;
	char        *out;
	u64          offset;
	u32          length;

	do
	{
		KeWaitForSingleObject(&pool_signal_event, Executive, KernelMode, FALSE, NULL);
		KeClearEvent(&pool_signal_event);
		
		while (entry = InterlockedPopEntrySList(&pool_head))
		{
			part = CONTAINING_RECORD(entry, req_part, entry);
			item = part->item;

			in     = item->in + part->offset;
			out    = item->out + part->offset;
			offset = item->offset + part->offset;
			length = part->length;

			if (item->is_encrypt != 0) {
				xts_encrypt(in, out, length, offset, item->key);
			} else {
				xts_decrypt(in, out, length, offset, item->key);
			}
			if (lock_xchg_add(&item->length, 0-length) == length) {
				item->on_complete(item->param);
				ExFreeToNPagedLookasideList(&pool_req_mem, item);
			}
		}	
	} while (pool_enabled != 0);

	PsTerminateSystemThread(STATUS_SUCCESS);
}
Esempio n. 16
0
void
cubeb_destroy(cubeb * ctx)
{
  DWORD rv;

  assert(!InterlockedPopEntrySList(ctx->work));

  if (ctx->thread) {
    ctx->shutdown = 1;
    SetEvent(ctx->event);
    rv = WaitForSingleObject(ctx->thread, INFINITE);
    assert(rv == WAIT_OBJECT_0);
    CloseHandle(ctx->thread);
  }

  if (ctx->event) {
    CloseHandle(ctx->event);
  }

  _aligned_free(ctx->work);

  free(ctx);
}
Esempio n. 17
0
int TestInterlockedSList(int argc, char* argv[])
{
	ULONG Count;
	WINPR_PSLIST_ENTRY pFirstEntry;
	WINPR_PSLIST_ENTRY pListEntry;
	WINPR_PSLIST_HEADER pListHead;
	PPROGRAM_ITEM pProgramItem;

	/* Initialize the list header to a MEMORY_ALLOCATION_ALIGNMENT boundary. */
	pListHead = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof(WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);

	if (!pListHead)
	{
		printf("Memory allocation failed.\n");
		return -1;
	}

	InitializeSListHead(pListHead);

	/* Insert 10 items into the list. */
	for (Count = 1; Count <= 10; Count += 1)
	{
		pProgramItem = (PPROGRAM_ITEM) _aligned_malloc(sizeof(PROGRAM_ITEM), MEMORY_ALLOCATION_ALIGNMENT);

		if (!pProgramItem)
		{
			printf("Memory allocation failed.\n");
			return -1;
		}

		pProgramItem->Signature = Count;
		pFirstEntry = InterlockedPushEntrySList(pListHead, &(pProgramItem->ItemEntry));
	}

	/* Remove 10 items from the list and display the signature. */
	for (Count = 10; Count >= 1; Count -= 1)
	{
		pListEntry = InterlockedPopEntrySList(pListHead);

		if (!pListEntry)
		{
			printf("List is empty.\n");
			return -1;
		}
  
		pProgramItem = (PPROGRAM_ITEM) pListEntry;
		printf("Signature is %d\n", (int) pProgramItem->Signature);

		/* 
		 * This example assumes that the SLIST_ENTRY structure is the 
		 * first member of the structure. If your structure does not 
		 * follow this convention, you must compute the starting address 
		 * of the structure before calling the free function.
		 */

		_aligned_free(pListEntry);
	}

	/* Flush the list and verify that the items are gone. */
	pListEntry = InterlockedFlushSList(pListHead);
	pFirstEntry = InterlockedPopEntrySList(pListHead);

	if (pFirstEntry)
	{
		printf("Error: List is not empty.\n");
		return -1;
	}

	_aligned_free(pListHead);

	return 0;
}
Esempio n. 18
0
short TamperNoServer::process(DivertPacket *& dPacket)
{

	/* Check the server rules */

	switch ((*ppNoServerConfig)->noServersType)
	{
	case NO_SERVERS_CUSTOM:
	{
		while (true)
		{
			/* Pull an entry off of the list */

			TamperNoServerEntry* listEntry = reinterpret_cast<TamperNoServerEntry*>(InterlockedPopEntrySList((*ppNoServerConfig)->noServersList));


			/* If it is null, we've reached the end of the list and should leave the loop */

			if (listEntry == nullptr)
			{
				break;
			}


			/* If our version doesn't match the entry version, we have old data and need to clear our list */

			if (serverListVersion != listEntry->version)
			{
				serverList.clear();
				serverListVersion = listEntry->version;
			}


			/* Add the port to the list and then free the list entry memory */

			serverList.push_back(reinterpret_cast<TamperNoServerEntry*>(listEntry)->server);
			_aligned_free(listEntry);
			listEntry = nullptr;


			/* Loop continues until we get a null pop entry */
		}

		break;
	}
	case NO_SERVERS_OFF:
	default:
		return 0;
	}



	/* Drop any packets traveling over blocked ports */

	WINDIVERT_IPHDR *iphdr = nullptr;
	WINDIVERT_TCPHDR *tcphdr = nullptr;
	WINDIVERT_UDPHDR *udphdr = nullptr;
	WinDivertHelperParsePacket(dPacket->packet, dPacket->packetLength, &iphdr, 0, 0, 0, &tcphdr, &udphdr, 0, 0);

	if (iphdr)
	{
		for (UINT32 server : serverList)
		{
			if (iphdr->DstAddr == server || iphdr->SrcAddr == server)
			{
				/* Drop packet */
				
				free(dPacket);
				dPacket = nullptr;
				break;
			}
		}

		return 0;
	}


	/* No IP header. Skip this packet */

	return 0;
}
Esempio n. 19
0
/*
 * @implemented
 */
NTSTATUS
NTAPI
IoSetIoCompletion(IN PVOID IoCompletion,
                  IN PVOID KeyContext,
                  IN PVOID ApcContext,
                  IN NTSTATUS IoStatus,
                  IN ULONG_PTR IoStatusInformation,
                  IN BOOLEAN Quota)
{
    PKQUEUE Queue = (PKQUEUE)IoCompletion;
    PNPAGED_LOOKASIDE_LIST List;
    PKPRCB Prcb = KeGetCurrentPrcb();
    PIOP_MINI_COMPLETION_PACKET Packet;

    /* Get the P List */
    List = (PNPAGED_LOOKASIDE_LIST)Prcb->
            PPLookasideList[LookasideCompletionList].P;

    /* Try to allocate the Packet */
    List->L.TotalAllocates++;
    Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);

    /* Check if that failed, use the L list if it did */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Get L List */
        List = (PNPAGED_LOOKASIDE_LIST)Prcb->
                PPLookasideList[LookasideCompletionList].L;

        /* Try to allocate the Packet */
        List->L.TotalAllocates++;
        Packet = (PVOID)InterlockedPopEntrySList(&List->L.ListHead);
    }

    /* Still failed, use pool */
    if (!Packet)
    {
        /* Let the balancer know */
        List->L.AllocateMisses++;

        /* Allocate from Nonpaged Pool */
        Packet = ExAllocatePoolWithTag(NonPagedPool, sizeof(*Packet), IOC_TAG);
    }

    /* Make sure we have one by now... */
    if (Packet)
    {
        /* Set up the Packet */
        Packet->PacketType = IopCompletionPacketMini;
        Packet->KeyContext = KeyContext;
        Packet->ApcContext = ApcContext;
        Packet->IoStatus = IoStatus;
        Packet->IoStatusInformation = IoStatusInformation;

        /* Insert the Queue */
        KeInsertQueue(Queue, &Packet->ListEntry);
    }
    else
    {
        /* Out of memory, fail */
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Return Success */
    return STATUS_SUCCESS;
}
Esempio n. 20
0
PVOID
ExInitializeNBQueueHead (
    IN PSLIST_HEADER SlistHead
    )

/*++

Routine Description:

    This function initializes a non-blocking queue header.

    N.B. It is assumed that the specified SLIST has been populated with
         non-blocking queue nodes prior to calling this routine.

Arguments:

    SlistHead - Supplies a pointer to an SLIST header.

Return Value:

    If the non-blocking queue is successfully initialized, then the
    address of the queue header is returned as the function value.
    Otherwise, NULL is returned as the function value.

--*/

{

    PNBQUEUE_HEADER QueueHead;
    PNBQUEUE_NODE QueueNode;

    //
    // Attempt to allocate the queue header. If the allocation fails, then
    // return NULL.
    //

#if defined(_KERNEL_MODE)
    QueueHead = (PNBQUEUE_HEADER)ExAllocatePoolWithTag(NonPagedPool,
                                                       sizeof(NBQUEUE_HEADER),
                                                       'hqBN');

#else
    QueueHead = (PNBQUEUE_HEADER)HeapAlloc(GetProcessHeap(), 0, 
		                                   sizeof(NBQUEUE_HEADER));
#endif

    if (QueueHead == NULL) {
        return NULL;
    }

    //
    // Attempt to allocate a queue node from the specified SLIST. If a node
    // can be allocated, then initialize the non-blocking queue header and
    // return the address of the queue header. Otherwise, free the queue
    // header and return NULL.
    //

    QueueHead->SlistHead = SlistHead;
    QueueNode = (PNBQUEUE_NODE)InterlockedPopEntrySList(QueueHead->SlistHead);
    if (QueueNode != NULL) {

        //
        // Initialize the queue node next pointer and value.
        //

        QueueNode->Next.Data = 0;
        QueueNode->Value = 0;

        //
        // Initialize the head and tail pointers in the queue header.
        //

        PackNBQPointer(&QueueHead->Head, QueueNode);
        QueueHead->Head.Count = 0;
        PackNBQPointer(&QueueHead->Tail, QueueNode);
        QueueHead->Tail.Count = 0;
        return QueueHead;

    } else {

#if defined(_KERNEL_MODE)
        ExFreePool(QueueHead);
#else
		HeapFree(GetProcessHeap(), 0, QueueHead);
#endif
        return NULL;
    }
}
Esempio n. 21
0
	SListEntry* SListImpl::pop()
	{
		return reinterpret_cast<SListEntry*>(InterlockedPopEntrySList(getDetail(this)));
	}
Esempio n. 22
0
BOOLEAN
ExInsertTailNBQueue (
    IN PVOID Header,
    IN ULONG64 Value
    )

/*++

Routine Description:

    This function inserts the specific data value at the tail of the
    specified non-blocking queue.

Arguments:

    Header - Supplies an opaque pointer to a non-blocking queue header.

    Value - Supplies a pointer to an opaque data value.

Return Value:

    If the specified opaque data value is successfully inserted at the tail
    of the specified non-blocking queue, then a value of TRUE is returned as
    the function value. Otherwise, a value of FALSE is returned.

    N.B. FALSE is returned if a queue node cannot be allocated from the
         associated SLIST.

--*/

{

    NBQUEUE_POINTER Insert;
    NBQUEUE_POINTER Next;
    PNBQUEUE_NODE NextNode;
    PNBQUEUE_HEADER QueueHead;
    PNBQUEUE_NODE QueueNode;
    NBQUEUE_POINTER Tail;
    PNBQUEUE_NODE TailNode;

    //
    // Attempt to allocate a queue node from the SLIST associated with
    // the specified non-blocking queue. If a node can be allocated, then
    // the node is inserted at the tail of the specified non-blocking
    // queue, and TRUE is returned as the function value. Otherwise, FALSE
    // is returned.
    //

    QueueHead = (PNBQUEUE_HEADER)Header;
    QueueNode = (PNBQUEUE_NODE)InterlockedPopEntrySList(QueueHead->SlistHead);
    if (QueueNode != NULL) {

        //
        //  Initialize the queue node next pointer and value.
        //

        QueueNode->Next.Data = 0;
        QueueNode->Value = Value;

        //
        // The following loop is executed until the specified entry can
        // be safely inserted at the tail of the specified non-blocking
        // queue.
        //

        do {

            //
            // Read the tail queue pointer and the next queue pointer of
            // the tail queue pointer making sure the two pointers are
            // coherent.
            //

            Tail.Data = ReadForWriteAccess((volatile LONG64 *)(&QueueHead->Tail.Data));
            TailNode = UnpackNBQPointer(&Tail);
            Next.Data = *((volatile LONG64 *)(&TailNode->Next.Data));
            QueueNode->Next.Count = Tail.Count + 1;
            if (Tail.Data == *((volatile LONG64 *)(&QueueHead->Tail.Data))) {

                //
                // If the tail is pointing to the last node in the list,
                // then attempt to insert the new node at the end of the
                // list. Otherwise, the tail is not pointing to the last
                // node in the list and an attempt is made to move the
                // tail pointer to the next node.
                //

                NextNode = UnpackNBQPointer(&Next);
                if (NextNode == NULL) {
                    PackNBQPointer(&Insert, QueueNode);
                    Insert.Count = Next.Count + 1;
                    if (InterlockedCompareExchange64(&TailNode->Next.Data,
                                                     Insert.Data,
                                                     Next.Data) == Next.Data) {
                        break;
                    }

                } else {
                    PackNBQPointer(&Insert, NextNode);
                    Insert.Count = Tail.Count + 1;
                    InterlockedCompareExchange64(&QueueHead->Tail.Data,
                                                 Insert.Data,
                                                 Tail.Data);
                }
            }

        } while (TRUE);

        //
        // Attempt to move the tail to the new tail node.
        //

        PackNBQPointer(&Insert, QueueNode);
        Insert.Count = Tail.Count + 1;
        InterlockedCompareExchange64(&QueueHead->Tail.Data,
                                     Insert.Data,
                                     Tail.Data);

        return TRUE;

    } else {
        return FALSE;
    }
}
Esempio n. 23
0
PVOID
NTAPI
MiAllocatePoolPages(IN POOL_TYPE PoolType,
                    IN SIZE_T SizeInBytes)
{
    PFN_NUMBER PageFrameNumber;
    PFN_COUNT SizeInPages, PageTableCount;
    ULONG i;
    KIRQL OldIrql;
    PLIST_ENTRY NextEntry, NextHead, LastHead;
    PMMPTE PointerPte, StartPte;
    PMMPDE PointerPde;
    ULONG EndAllocation;
    MMPTE TempPte;
    MMPDE TempPde;
    PMMPFN Pfn1;
    PVOID BaseVa, BaseVaStart;
    PMMFREE_POOL_ENTRY FreeEntry;
    PKSPIN_LOCK_QUEUE LockQueue;

    //
    // Figure out how big the allocation is in pages
    //
    SizeInPages = (PFN_COUNT)BYTES_TO_PAGES(SizeInBytes);

    //
    // Check for overflow
    //
    if (SizeInPages == 0)
    {
        //
        // Fail
        //
        return NULL;
    }

    //
    // Handle paged pool
    //
    if ((PoolType & BASE_POOL_TYPE_MASK) == PagedPool)
    {
        //
        // If only one page is being requested, try to grab it from the S-LIST
        //
        if ((SizeInPages == 1) && (ExQueryDepthSList(&MiPagedPoolSListHead)))
        {
            BaseVa = InterlockedPopEntrySList(&MiPagedPoolSListHead);
            if (BaseVa) return BaseVa;
        }

        //
        // Lock the paged pool mutex
        //
        KeAcquireGuardedMutex(&MmPagedPoolMutex);

        //
        // Find some empty allocation space
        //
        i = RtlFindClearBitsAndSet(MmPagedPoolInfo.PagedPoolAllocationMap,
                                   SizeInPages,
                                   MmPagedPoolInfo.PagedPoolHint);
        if (i == 0xFFFFFFFF)
        {
            //
            // Get the page bit count
            //
            i = ((SizeInPages - 1) / PTE_COUNT) + 1;
            DPRINT("Paged pool expansion: %lu %x\n", i, SizeInPages);

            //
            // Check if there is enougn paged pool expansion space left
            //
            if (MmPagedPoolInfo.NextPdeForPagedPoolExpansion >
                    (PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool))
            {
                //
                // Out of memory!
                //
                DPRINT1("OUT OF PAGED POOL!!!\n");
                KeReleaseGuardedMutex(&MmPagedPoolMutex);
                return NULL;
            }

            //
            // Check if we'll have to expand past the last PTE we have available
            //
            if (((i - 1) + MmPagedPoolInfo.NextPdeForPagedPoolExpansion) >
                    (PMMPDE)MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool))
            {
                //
                // We can only support this much then
                //
                PointerPde = MiAddressToPte(MmPagedPoolInfo.LastPteForPagedPool);
                PageTableCount = (PFN_COUNT)(PointerPde + 1 -
                                             MmPagedPoolInfo.NextPdeForPagedPoolExpansion);
                ASSERT(PageTableCount < i);
                i = PageTableCount;
            }
            else
            {
                //
                // Otherwise, there is plenty of space left for this expansion
                //
                PageTableCount = i;
            }

            //
            // Get the template PDE we'll use to expand
            //
            TempPde = ValidKernelPde;

            //
            // Get the first PTE in expansion space
            //
            PointerPde = MmPagedPoolInfo.NextPdeForPagedPoolExpansion;
            BaseVa = MiPdeToPte(PointerPde);
            BaseVaStart = BaseVa;

            //
            // Lock the PFN database and loop pages
            //
            OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
            do
            {
                //
                // It should not already be valid
                //
                ASSERT(PointerPde->u.Hard.Valid == 0);

                /* Request a page */
                MI_SET_USAGE(MI_USAGE_PAGED_POOL);
                MI_SET_PROCESS2("Kernel");
                PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());
                TempPde.u.Hard.PageFrameNumber = PageFrameNumber;
#if (_MI_PAGING_LEVELS >= 3)
                /* On PAE/x64 systems, there's no double-buffering */
                ASSERT(FALSE);
#else
                //
                // Save it into our double-buffered system page directory
                //
                MmSystemPagePtes[((ULONG_PTR)PointerPde & (SYSTEM_PD_SIZE - 1)) / sizeof(MMPTE)] = TempPde;

                /* Initialize the PFN */
                MiInitializePfnForOtherProcess(PageFrameNumber,
                                               (PMMPTE)PointerPde,
                                               MmSystemPageDirectory[(PointerPde - MiAddressToPde(NULL)) / PDE_COUNT]);

                /* Write the actual PDE now */
//                MI_WRITE_VALID_PDE(PointerPde, TempPde);
#endif
                //
                // Move on to the next expansion address
                //
                PointerPde++;
                BaseVa = (PVOID)((ULONG_PTR)BaseVa + PAGE_SIZE);
                i--;
            } while (i > 0);

            //
            // Release the PFN database lock
            //
            KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);

            //
            // These pages are now available, clear their availablity bits
            //
            EndAllocation = (ULONG)(MmPagedPoolInfo.NextPdeForPagedPoolExpansion -
                                    (PMMPDE)MiAddressToPte(MmPagedPoolInfo.FirstPteForPagedPool)) *
                            PTE_COUNT;
            RtlClearBits(MmPagedPoolInfo.PagedPoolAllocationMap,
                         EndAllocation,
                         PageTableCount * PTE_COUNT);

            //
            // Update the next expansion location
            //
            MmPagedPoolInfo.NextPdeForPagedPoolExpansion += PageTableCount;

            //
            // Zero out the newly available memory
            //
            RtlZeroMemory(BaseVaStart, PageTableCount * PAGE_SIZE);

            //
            // Now try consuming the pages again
            //
            i = RtlFindClearBitsAndSet(MmPagedPoolInfo.PagedPoolAllocationMap,
                                       SizeInPages,
                                       0);
            if (i == 0xFFFFFFFF)
            {
                //
                // Out of memory!
                //
                DPRINT1("OUT OF PAGED POOL!!!\n");
                KeReleaseGuardedMutex(&MmPagedPoolMutex);
                return NULL;
            }
        }

        //
        // Update the pool hint if the request was just one page
        //
        if (SizeInPages == 1) MmPagedPoolInfo.PagedPoolHint = i + 1;

        //
        // Update the end bitmap so we know the bounds of this allocation when
        // the time comes to free it
        //
        EndAllocation = i + SizeInPages - 1;
        RtlSetBit(MmPagedPoolInfo.EndOfPagedPoolBitmap, EndAllocation);

        //
        // Now we can release the lock (it mainly protects the bitmap)
        //
        KeReleaseGuardedMutex(&MmPagedPoolMutex);

        //
        // Now figure out where this allocation starts
        //
        BaseVa = (PVOID)((ULONG_PTR)MmPagedPoolStart + (i << PAGE_SHIFT));

        //
        // Flush the TLB
        //
        KeFlushEntireTb(TRUE, TRUE);

        /* Setup a demand-zero writable PTE */
        MI_MAKE_SOFTWARE_PTE(&TempPte, MM_READWRITE);

        //
        // Find the first and last PTE, then loop them all
        //
        PointerPte = MiAddressToPte(BaseVa);
        StartPte = PointerPte + SizeInPages;
        do
        {
            //
            // Write the demand zero PTE and keep going
            //
            MI_WRITE_INVALID_PTE(PointerPte, TempPte);
        } while (++PointerPte < StartPte);

        //
        // Return the allocation address to the caller
        //
        return BaseVa;
    }

    //
    // If only one page is being requested, try to grab it from the S-LIST
    //
    if ((SizeInPages == 1) && (ExQueryDepthSList(&MiNonPagedPoolSListHead)))
    {
        BaseVa = InterlockedPopEntrySList(&MiNonPagedPoolSListHead);
        if (BaseVa) return BaseVa;
    }

    //
    // Allocations of less than 4 pages go into their individual buckets
    //
    i = SizeInPages - 1;
    if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;

    //
    // Loop through all the free page lists based on the page index
    //
    NextHead = &MmNonPagedPoolFreeListHead[i];
    LastHead = &MmNonPagedPoolFreeListHead[MI_MAX_FREE_PAGE_LISTS];

    //
    // Acquire the nonpaged pool lock
    //
    OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);
    do
    {
        //
        // Now loop through all the free page entries in this given list
        //
        NextEntry = NextHead->Flink;
        while (NextEntry != NextHead)
        {
            /* Is freed non paged pool enabled */
            if (MmProtectFreedNonPagedPool)
            {
                /* We need to be able to touch this page, unprotect it */
                MiUnProtectFreeNonPagedPool(NextEntry, 0);
            }

            //
            // Grab the entry and see if it can handle our allocation
            //
            FreeEntry = CONTAINING_RECORD(NextEntry, MMFREE_POOL_ENTRY, List);
            ASSERT(FreeEntry->Signature == MM_FREE_POOL_SIGNATURE);
            if (FreeEntry->Size >= SizeInPages)
            {
                //
                // It does, so consume the pages from here
                //
                FreeEntry->Size -= SizeInPages;

                //
                // The allocation will begin in this free page area
                //
                BaseVa = (PVOID)((ULONG_PTR)FreeEntry +
                                 (FreeEntry->Size  << PAGE_SHIFT));

                /* Remove the item from the list, depending if pool is protected */
                if (MmProtectFreedNonPagedPool)
                    MiProtectedPoolRemoveEntryList(&FreeEntry->List);
                else
                    RemoveEntryList(&FreeEntry->List);

                //
                // However, check if its' still got space left
                //
                if (FreeEntry->Size != 0)
                {
                    /* Check which list to insert this entry into */
                    i = FreeEntry->Size - 1;
                    if (i >= MI_MAX_FREE_PAGE_LISTS) i = MI_MAX_FREE_PAGE_LISTS - 1;

                    /* Insert the entry into the free list head, check for prot. pool */
                    if (MmProtectFreedNonPagedPool)
                        MiProtectedPoolInsertList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List, TRUE);
                    else
                        InsertTailList(&MmNonPagedPoolFreeListHead[i], &FreeEntry->List);

                    /* Is freed non paged pool protected? */
                    if (MmProtectFreedNonPagedPool)
                    {
                        /* Protect the freed pool! */
                        MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
                    }
                }

                //
                // Grab the PTE for this allocation
                //
                PointerPte = MiAddressToPte(BaseVa);
                ASSERT(PointerPte->u.Hard.Valid == 1);

                //
                // Grab the PFN NextEntry and index
                //
                Pfn1 = MiGetPfnEntry(PFN_FROM_PTE(PointerPte));

                //
                // Now mark it as the beginning of an allocation
                //
                ASSERT(Pfn1->u3.e1.StartOfAllocation == 0);
                Pfn1->u3.e1.StartOfAllocation = 1;

                /* Mark it as special pool if needed */
                ASSERT(Pfn1->u4.VerifierAllocation == 0);
                if (PoolType & VERIFIER_POOL_MASK)
                {
                    Pfn1->u4.VerifierAllocation = 1;
                }

                //
                // Check if the allocation is larger than one page
                //
                if (SizeInPages != 1)
                {
                    //
                    // Navigate to the last PFN entry and PTE
                    //
                    PointerPte += SizeInPages - 1;
                    ASSERT(PointerPte->u.Hard.Valid == 1);
                    Pfn1 = MiGetPfnEntry(PointerPte->u.Hard.PageFrameNumber);
                }

                //
                // Mark this PFN as the last (might be the same as the first)
                //
                ASSERT(Pfn1->u3.e1.EndOfAllocation == 0);
                Pfn1->u3.e1.EndOfAllocation = 1;

                //
                // Release the nonpaged pool lock, and return the allocation
                //
                KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);
                return BaseVa;
            }

            //
            // Try the next free page entry
            //
            NextEntry = FreeEntry->List.Flink;

            /* Is freed non paged pool protected? */
            if (MmProtectFreedNonPagedPool)
            {
                /* Protect the freed pool! */
                MiProtectFreeNonPagedPool(FreeEntry, FreeEntry->Size);
            }
        }
    } while (++NextHead < LastHead);

    //
    // If we got here, we're out of space.
    // Start by releasing the lock
    //
    KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);

    //
    // Allocate some system PTEs
    //
    StartPte = MiReserveSystemPtes(SizeInPages, NonPagedPoolExpansion);
    PointerPte = StartPte;
    if (StartPte == NULL)
    {
        //
        // Ran out of memory
        //
        DPRINT1("Out of NP Expansion Pool\n");
        return NULL;
    }

    //
    // Acquire the pool lock now
    //
    OldIrql = KeAcquireQueuedSpinLock(LockQueueMmNonPagedPoolLock);

    //
    // Lock the PFN database too
    //
    LockQueue = &KeGetCurrentPrcb()->LockQueue[LockQueuePfnLock];
    KeAcquireQueuedSpinLockAtDpcLevel(LockQueue);

    //
    // Loop the pages
    //
    TempPte = ValidKernelPte;
    do
    {
        /* Allocate a page */
        MI_SET_USAGE(MI_USAGE_PAGED_POOL);
        MI_SET_PROCESS2("Kernel");
        PageFrameNumber = MiRemoveAnyPage(MI_GET_NEXT_COLOR());

        /* Get the PFN entry for it and fill it out */
        Pfn1 = MiGetPfnEntry(PageFrameNumber);
        Pfn1->u3.e2.ReferenceCount = 1;
        Pfn1->u2.ShareCount = 1;
        Pfn1->PteAddress = PointerPte;
        Pfn1->u3.e1.PageLocation = ActiveAndValid;
        Pfn1->u4.VerifierAllocation = 0;

        /* Write the PTE for it */
        TempPte.u.Hard.PageFrameNumber = PageFrameNumber;
        MI_WRITE_VALID_PTE(PointerPte++, TempPte);
    } while (--SizeInPages > 0);

    //
    // This is the last page
    //
    Pfn1->u3.e1.EndOfAllocation = 1;

    //
    // Get the first page and mark it as such
    //
    Pfn1 = MiGetPfnEntry(StartPte->u.Hard.PageFrameNumber);
    Pfn1->u3.e1.StartOfAllocation = 1;

    /* Mark it as a verifier allocation if needed */
    ASSERT(Pfn1->u4.VerifierAllocation == 0);
    if (PoolType & VERIFIER_POOL_MASK) Pfn1->u4.VerifierAllocation = 1;

    //
    // Release the PFN and nonpaged pool lock
    //
    KeReleaseQueuedSpinLockFromDpcLevel(LockQueue);
    KeReleaseQueuedSpinLock(LockQueueMmNonPagedPoolLock, OldIrql);

    //
    // Return the address
    //
    return MiPteToAddress(StartPte);
}
Esempio n. 24
0
VOID
MiReleaseAllMemory (
    VOID
    )

/*++

Routine Description:

    This function performs the final release of memory management allocations.

Arguments:

    None.

Return Value:

    None.

Environment:

    No references to paged pool or pageable code/data are allowed.

--*/

{
    ULONG i;
    ULONG j;
    PEVENT_COUNTER EventSupport;
    PUNLOADED_DRIVERS Entry;
    PLIST_ENTRY NextEntry;
    PKLDR_DATA_TABLE_ENTRY DataTableEntry;
    PLOAD_IMPORTS ImportList;
    PMI_VERIFIER_DRIVER_ENTRY Verifier;
    PMMINPAGE_SUPPORT Support;
    PSLIST_ENTRY SingleListEntry;
    PDRIVER_SPECIFIED_VERIFIER_THUNKS ThunkTableBase;
    PMMMOD_WRITER_MDL_ENTRY ModWriterEntry;

    ASSERT (MmUnusedSegmentList.Flink == &MmUnusedSegmentList);

    //
    // Don't clear free pages so problems can be debugged.
    //

    MiZeroingDisabled = TRUE;

    //
    // Free the unloaded driver list.
    //

    if (MmUnloadedDrivers != NULL) {
        Entry = &MmUnloadedDrivers[0];
        for (i = 0; i < MI_UNLOADED_DRIVERS; i += 1) {
            if (Entry->Name.Buffer != NULL) {
                RtlFreeUnicodeString (&Entry->Name);
            }
            Entry += 1;
        }
        ExFreePool (MmUnloadedDrivers);
    }

    NextEntry = MmLoadedUserImageList.Flink;
    while (NextEntry != &MmLoadedUserImageList) {

        DataTableEntry = CONTAINING_RECORD (NextEntry,
                                            KLDR_DATA_TABLE_ENTRY,
                                            InLoadOrderLinks);

        NextEntry = NextEntry->Flink;

        ExFreePool ((PVOID)DataTableEntry);
    }

    //
    // Release the loaded module list entries.
    //

    NextEntry = PsLoadedModuleList.Flink;
    while (NextEntry != &PsLoadedModuleList) {

        DataTableEntry = CONTAINING_RECORD (NextEntry,
                                            KLDR_DATA_TABLE_ENTRY,
                                            InLoadOrderLinks);

        ImportList = (PLOAD_IMPORTS)DataTableEntry->LoadedImports;

        if ((ImportList != (PVOID)LOADED_AT_BOOT) &&
            (ImportList != (PVOID)NO_IMPORTS_USED) &&
            (!SINGLE_ENTRY(ImportList))) {

                ExFreePool (ImportList);
        }

        if (DataTableEntry->FullDllName.Buffer != NULL) {
            ASSERT (DataTableEntry->FullDllName.Buffer == DataTableEntry->BaseDllName.Buffer);
        }

        NextEntry = NextEntry->Flink;

        ExFreePool ((PVOID)DataTableEntry);
    }

    //
    // Free the physical memory descriptor block.
    //

    ExFreePool (MmPhysicalMemoryBlock);

    ExFreePool (MiPfnBitMap.Buffer);

    //
    // Free the system views structure.
    //

    if (MmSession.SystemSpaceViewTable != NULL) {
        ExFreePool (MmSession.SystemSpaceViewTable);
    }

    if (MmSession.SystemSpaceBitMap != NULL) {
        ExFreePool (MmSession.SystemSpaceBitMap);
    }

    //
    // Free the pagefile structures - note the PageFileName buffer was freed
    // earlier as it resided in paged pool and may have needed an inpage
    // to be freed.
    //

    for (i = 0; i < MmNumberOfPagingFiles; i += 1) {
        ASSERT (MmPagingFile[i]->PageFileName.Buffer == NULL);
        for (j = 0; j < MM_PAGING_FILE_MDLS; j += 1) {
            ExFreePool (MmPagingFile[i]->Entry[j]);
        }
        ExFreePool (MmPagingFile[i]->Bitmap);
        ExFreePool (MmPagingFile[i]);
    }

    ASSERT (MmNumberOfMappedMdlsInUse == 0);

    i = 0;
    while (IsListEmpty (&MmMappedFileHeader.ListHead) != 0) {

        ModWriterEntry = (PMMMOD_WRITER_MDL_ENTRY)RemoveHeadList (
                                    &MmMappedFileHeader.ListHead);

        ExFreePool (ModWriterEntry);
        i += 1;
    }
    ASSERT (i == MmNumberOfMappedMdls);

    //
    // Free the paged pool bitmaps.
    //

    ExFreePool (MmPagedPoolInfo.PagedPoolAllocationMap);
    ExFreePool (MmPagedPoolInfo.EndOfPagedPoolBitmap);

    if (VerifierLargePagedPoolMap != NULL) {
        ExFreePool (VerifierLargePagedPoolMap);
    }

    //
    // Free the inpage structures.
    //

    while (ExQueryDepthSList (&MmInPageSupportSListHead) != 0) {

        SingleListEntry = InterlockedPopEntrySList (&MmInPageSupportSListHead);

        if (SingleListEntry != NULL) {
            Support = CONTAINING_RECORD (SingleListEntry,
                                         MMINPAGE_SUPPORT,
                                         ListEntry);

            ASSERT (Support->u1.e1.PrefetchMdlHighBits == 0);
            ExFreePool (Support);
        }
    }

    while (ExQueryDepthSList (&MmEventCountSListHead) != 0) {

        EventSupport = (PEVENT_COUNTER) InterlockedPopEntrySList (&MmEventCountSListHead);

        if (EventSupport != NULL) {
            ExFreePool (EventSupport);
        }
    }

    //
    // Free the verifier list last because it must be consulted to debug
    // any bugchecks.
    //

    NextEntry = MiVerifierDriverAddedThunkListHead.Flink;
    if (NextEntry != NULL) {
        while (NextEntry != &MiVerifierDriverAddedThunkListHead) {

            ThunkTableBase = CONTAINING_RECORD (NextEntry,
                                                DRIVER_SPECIFIED_VERIFIER_THUNKS,
                                                ListEntry );

            NextEntry = NextEntry->Flink;
            ExFreePool (ThunkTableBase);
        }
    }

    NextEntry = MiSuspectDriverList.Flink;
    while (NextEntry != &MiSuspectDriverList) {

        Verifier = CONTAINING_RECORD(NextEntry,
                                     MI_VERIFIER_DRIVER_ENTRY,
                                     Links);

        NextEntry = NextEntry->Flink;
        ExFreePool (Verifier);
    }
}