Exemple #1
0
NTSTATUS CfixkrpJoinChildThreadsFilament(
	__in PCFIXKRP_FILAMENT Filament,
	__in_opt PLARGE_INTEGER Timeout
	)
{
	NTSTATUS Status;

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &Filament->ChildThreads.Lock );
	
	if ( Filament->ChildThreads.ThreadCount > 0 )
	{
		KWAIT_BLOCK WaitBlocks[ CFIX_MAX_THREADS ];

		Status = KeWaitForMultipleObjects(
			Filament->ChildThreads.ThreadCount,
			Filament->ChildThreads.Threads,
			WaitAll,
			Executive,
			KernelMode,
			FALSE,
			Timeout,
			WaitBlocks );
	}
	else
	{
		Status = STATUS_SUCCESS;
	}

	ExReleaseFastMutex( &Filament->ChildThreads.Lock );

	return Status;
}
Exemple #2
0
u32_t
sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
{
    LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime;
    UINT64 TimeDiff;
    NTSTATUS Status;
    PVOID Message;
    PLWIP_MESSAGE_CONTAINER Container;
    PLIST_ENTRY Entry;
    KIRQL OldIrql;
    PVOID WaitObjects[] = {&mbox->Event, &TerminationEvent};
    
    LargeTimeout.QuadPart = Int32x32To64(timeout, -10000);
    
    KeQuerySystemTime(&PreWaitTime);

    Status = KeWaitForMultipleObjects(2,
                                      WaitObjects,
                                      WaitAny,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      timeout != 0 ? &LargeTimeout : NULL,
                                      NULL);

    if (Status == STATUS_WAIT_0)
    {
        KeAcquireSpinLock(&mbox->Lock, &OldIrql);
        Entry = RemoveHeadList(&mbox->ListHead);
        ASSERT(Entry);
        if (IsListEmpty(&mbox->ListHead))
            KeClearEvent(&mbox->Event);
        KeReleaseSpinLock(&mbox->Lock, OldIrql);
        
        Container = CONTAINING_RECORD(Entry, LWIP_MESSAGE_CONTAINER, ListEntry);
        Message = Container->Message;
        ExFreePool(Container);
        
        if (msg)
            *msg = Message;

        KeQuerySystemTime(&PostWaitTime);
        TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart;
        TimeDiff /= 10000;
        
        return TimeDiff;
    }
    else if (Status == STATUS_WAIT_1)
    {
        /* DON'T remove ourselves from the thread list! */
        PsTerminateSystemThread(STATUS_SUCCESS);
        
        /* We should never get here! */
        ASSERT(FALSE);
        
        return 0;
    }
    
    return SYS_ARCH_TIMEOUT;
}
Exemple #3
0
VOID NotificationThread(__in PDokanDCB Dcb) {
  PKEVENT events[5];
  PKWAIT_BLOCK waitBlock;
  NTSTATUS status;

  DDbgPrint("==> NotificationThread\n");

  waitBlock = ExAllocatePool(sizeof(KWAIT_BLOCK) * 5);
  if (waitBlock == NULL) {
    DDbgPrint("  Can't allocate WAIT_BLOCK\n");
    return;
  }
  events[0] = &Dcb->ReleaseEvent;
  events[1] = &Dcb->NotifyEvent.NotEmpty;
  events[2] = &Dcb->PendingEvent.NotEmpty;
  events[3] = &Dcb->Global->PendingService.NotEmpty;
  events[4] = &Dcb->Global->NotifyService.NotEmpty;

  do {
    status = KeWaitForMultipleObjects(5, events, WaitAny, Executive, KernelMode,
                                      FALSE, NULL, waitBlock);

    if (status != STATUS_WAIT_0) {
      if (status == STATUS_WAIT_1 || status == STATUS_WAIT_2) {
        NotificationLoop(&Dcb->PendingEvent, &Dcb->NotifyEvent);
      } else {
        NotificationLoop(&Dcb->Global->PendingService,
                         &Dcb->Global->NotifyService);
      }
    }
  } while (status != STATUS_WAIT_0);

  ExFreePool(waitBlock);
  DDbgPrint("<== NotificationThread\n");
}
Exemple #4
0
NTSTATUS
v2v_stream_recv(struct v2v_stream *stream, void *buf, size_t buf_size,
                size_t *_bytes_received)
{
    NTSTATUS status = STATUS_SUCCESS;
    struct queued_message *qm;
    size_t bytes_received;
    size_t bytes_this_time;
    HANDLE handles[2];

    v2v_nc2_request_fast_receive(stream->channel);
    handles[0] = stream->receive_event;
    handles[1] = stream->control_event;

    for (bytes_received = 0;
         bytes_received < buf_size;
         bytes_received += bytes_this_time) {

        if (!stream->recv_state.current_message) {
            while ((status = v2v_get_next_message(stream)) != STATUS_SUCCESS) {
                if (bytes_received != 0 ||
                    status != STATUS_NO_MORE_ENTRIES)
                    goto out;

                status =
                    KeWaitForMultipleObjects(2, handles, WaitAny, Executive,
                                             KernelMode, FALSE, NULL, NULL);
                if (status == STATUS_WAIT_0 + 1 && v2v_remote_disconnect(stream)) {
                    status = STATUS_VIRTUAL_CIRCUIT_CLOSED;
                    goto out;
                }
            }         
        }

        qm = stream->recv_state.current_message;
        bytes_this_time = MIN(qm->size - qm->bytes_already_used,
                              buf_size - bytes_received);
        RtlCopyMemory((void *)((ULONG_PTR)buf + bytes_received),
                      (const void *)((ULONG_PTR)qm->payload + qm->bytes_already_used),
                      bytes_this_time);
        qm->bytes_already_used += bytes_this_time;
        if (qm->bytes_already_used == qm->size) {
            v2v_release_queued_message(stream, qm);
            stream->recv_state.current_message = NULL;
        }
    }
out:
    v2v_nc2_cancel_fast_receive(stream->channel);
    *_bytes_received = bytes_received;
    if (bytes_received == 0)
        return (!NT_SUCCESS(status) ? status : STATUS_UNSUCCESSFUL);
    else
        return STATUS_SUCCESS;
}
Exemple #5
0
NTSTATUS
v2v_stream_send(struct v2v_stream *stream, const void *buf,
                size_t buf_len, size_t *_bytes_sent)
{
    NTSTATUS status = STATUS_SUCCESS;
    unsigned bytes_sent;
    unsigned short bytes_this_time;
    unsigned bytes_avail;
    volatile void *msg;
    HANDLE handles[3];

    handles[0] = stream->send_event;
    handles[1] = stream->control_event;
    handles[2] = stream->receive_event;

    for (bytes_sent = 0; bytes_sent < buf_len; bytes_sent += bytes_this_time){
        bytes_avail = v2v_nc2_producer_bytes_available(stream->channel);
        if (v2v_nc2_remote_requested_fast_wakeup(stream->channel))
            bytes_avail = MIN(MAX_INLINE_BYTES, bytes_avail);
        bytes_this_time = (unsigned short)MIN(bytes_avail,
                                              buf_len - bytes_sent);
        status = v2v_nc2_prep_message(stream->channel, bytes_this_time,
                                      STREAM_MSG_DATA, 0, &msg);
        if (!NT_SUCCESS(status)) {
            if (status == STATUS_RETRY) {
                v2v_pull_incoming_messages(stream);
                if (bytes_sent != 0)
                    v2v_nc2_send_messages(stream->channel);
                status =
                    KeWaitForMultipleObjects(3, handles, WaitAny, Executive,
                                             KernelMode, FALSE, NULL, NULL);
                if (status == STATUS_WAIT_0 + 1 && v2v_remote_disconnect(stream)) {
                    status = STATUS_VIRTUAL_CIRCUIT_CLOSED;
                    break;
                }
                bytes_this_time = 0;
                continue;
            }
            break; /* end send with error status */
        }

        _ReadWriteBarrier();
        RtlCopyMemory((void *)msg,
                      (const void *)((ULONG_PTR)buf + bytes_sent),
                      bytes_this_time);
        _ReadWriteBarrier();
    }

    if (bytes_sent != 0)
        v2v_nc2_send_messages(stream->channel);
    *_bytes_sent = bytes_sent;

    return status;
}
Exemple #6
0
static void DDKAPI timer_thread(LPVOID arg)
{
	while (1) {
		KeWaitForMultipleObjects(2, timer_wait_objs, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);
		if (timer_done)
			break;
		lkl_trigger_irq(TIMER_IRQ);
	}

	PsTerminateSystemThread(STATUS_SUCCESS);
}
BOOLEAN KTdiStreamSocket::Accept(ULONG dwTimeOut)
{
  //KLocker locker(&m_KSynchroObject);

  BOOLEAN                      bRes = FALSE;
  NTSTATUS                     NtStatus;
  PVOID                        pkEvents[2];
  LARGE_INTEGER                TimeOut;
  PLARGE_INTEGER               pTimeOut = NULL;

  //m_KSynchroObject.Lock();

  __try
  {
    if (m_bOpen == TRUE && m_bBind == TRUE && m_bConnected == FALSE && m_bListen == TRUE)
    {
      if (dwTimeOut != 0)
      {
        pTimeOut = &TimeOut;
        TimeOut.QuadPart = dwTimeOut * 10000; // msec -> 100 nsec intervals
        TimeOut.QuadPart = -TimeOut.QuadPart;
      }
      
      pkEvents[0] = &m_kListenEvent;
      pkEvents[1] = &m_kAcceptDestroyEvent;

      NtStatus  = KeWaitForMultipleObjects(2, pkEvents, WaitAny, Suspended, KernelMode, TRUE, pTimeOut, NULL);
      
      if (NtStatus == STATUS_WAIT_0)
      {
        if (NT_SUCCESS(m_ListenStatusBlock.Status))
        {
          SetEventHandler(TDI_EVENT_CONNECT, (PVOID)NULL, (PVOID)NULL);
          m_bConnected = TRUE;
          bRes = TRUE;
        
          DbgPrint ("TdiAccept: OK (%08x : %04x)!!!\n", m_nRemoteAddress, m_nRemotePort);
        }
        else
        {
          DbgPrint ("TdiAccept: ERROR (%08x)!!!\n", NtStatus);
        }
      }
    }
  }
  __finally
  {
  }

  //m_KSynchroObject.UnLock();

  return bRes;
}
Exemple #8
0
VOID
DokanTimeoutThread(
	PDokanDCB	Dcb)
/*++

Routine Description:

	checks wheter pending IRP is timeout or not each DOKAN_CHECK_INTERVAL

--*/
{
	NTSTATUS		status;
	KTIMER			timer;
	PVOID			pollevents[2];
	LARGE_INTEGER	timeout = {0};
	BOOLEAN			waitObj = TRUE;

	DDbgPrint("==> DokanTimeoutThread\n");

	KeInitializeTimerEx(&timer, SynchronizationTimer);
	
	pollevents[0] = (PVOID)&Dcb->KillEvent;
	pollevents[1] = (PVOID)&timer;

	KeSetTimerEx(&timer, timeout, DOKAN_CHECK_INTERVAL, NULL);
	
	while (waitObj) {
		status = KeWaitForMultipleObjects(2, pollevents, WaitAny,
			Executive, KernelMode, FALSE, NULL, NULL);
		
		if (!NT_SUCCESS(status) || status ==  STATUS_WAIT_0) {
			DDbgPrint("  DokanTimeoutThread catched KillEvent\n");
			// KillEvent or something error is occured
			waitObj = FALSE;
		} else {
			ReleaseTimeoutPendingIrp(Dcb);
			if (Dcb->UseKeepAlive)
				DokanCheckKeepAlive(Dcb);
		}
	}

	KeCancelTimer(&timer);

	DDbgPrint("<== DokanTimeoutThread\n");

	PsTerminateSystemThread(STATUS_SUCCESS);
}
Exemple #9
0
u32_t
sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout)
{
    LARGE_INTEGER LargeTimeout, PreWaitTime, PostWaitTime;
    UINT64 TimeDiff;
    NTSTATUS Status;
    PVOID WaitObjects[] = {&sem->Event, &TerminationEvent};

    LargeTimeout.QuadPart = Int32x32To64(timeout, -10000);
    
    KeQuerySystemTime(&PreWaitTime);

    Status = KeWaitForMultipleObjects(2,
                                      WaitObjects,
                                      WaitAny,
                                      Executive,
                                      KernelMode,
                                      FALSE,
                                      timeout != 0 ? &LargeTimeout : NULL,
                                      NULL);
    if (Status == STATUS_WAIT_0)
    {
        KeQuerySystemTime(&PostWaitTime);
        TimeDiff = PostWaitTime.QuadPart - PreWaitTime.QuadPart;
        TimeDiff /= 10000;

        return TimeDiff;
    }
    else if (Status == STATUS_WAIT_1)
    {
        /* DON'T remove ourselves from the thread list! */
        PsTerminateSystemThread(STATUS_SUCCESS);
        
        /* We should never get here! */
        ASSERT(FALSE);
        
        return 0;
    }
    
    return SYS_ARCH_TIMEOUT;
}
Exemple #10
0
VOID
NotificationThread(
	__in PDEVICE_EXTENSION	DeviceExtension
	)
{
	PKEVENT events[5];
	NTSTATUS status;

	DDbgPrint("==> NotificationThread\n");

	events[0] = &DeviceExtension->ReleaseEvent;
	events[1] = &DeviceExtension->NotifyEvent.NotEmpty;
	events[2] = &DeviceExtension->PendingEvent.NotEmpty;
	events[3] = &DeviceExtension->Global->PendingService.NotEmpty;
	events[4] = &DeviceExtension->Global->NotifyService.NotEmpty;

	while (1) {
		status = KeWaitForMultipleObjects(
			3, events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);

		if (status == STATUS_WAIT_0) {
			;
			break;

		} else if (status == STATUS_WAIT_1 || status == STATUS_WAIT_2) {

			NotificationLoop(
					&DeviceExtension->PendingEvent,
					&DeviceExtension->NotifyEvent);

		} else {
			NotificationLoop(
				&DeviceExtension->Global->PendingService,
				&DeviceExtension->Global->NotifyService);
		}
	}

	DDbgPrint("<== NotificationThread\n");
}
Exemple #11
0
static
BOOLEAN
WaitForEventSafely(PRKEVENT Event)
{
    PVOID WaitObjects[] = {Event, &TerminationEvent};

    if (KeWaitForMultipleObjects(2,
                                 WaitObjects,
                                 WaitAny,
                                 Executive,
                                 KernelMode,
                                 FALSE,
                                 NULL,
                                 NULL) == STATUS_WAIT_0)
    {
        /* Signalled by the caller's event */
        return TRUE;
    }
    else /* if KeWaitForMultipleObjects() == STATUS_WAIT_1 */
    {
        /* Signalled by our termination event */
        return FALSE;
    }
}
Exemple #12
0
static
NTSTATUS
LspConnectBindAddrList(
		IN OUT PLANSCSI_SESSION	LSS,
		OUT PTA_LSTRANS_ADDRESS	BoundAddr,
		IN PTA_LSTRANS_ADDRESS	DestAddr,
		IN PTA_LSTRANS_ADDRESS	BindAddrList,
		IN PLARGE_INTEGER		TimeOut
){
	NTSTATUS	status;
	ULONG		idx_addr, idx_cleanup_addr;
	TA_LSTRANS_ADDRESS	bindAddr;
	PLSTRANS_OVERLAPPED	overlapped;
	PKEVENT				overlappedEvents;
	PKWAIT_BLOCK		overlappedWaitBlocks;
	PLANSCSI_SESSION	overlappedLSS;
	PKEVENT				overlappedWait[MAXIMUM_WAIT_OBJECTS];

	NDASSCSI_ASSERT( TimeOut == NULL || TimeOut->QuadPart < 0 );

	//
	//	Parameter check
	//
	if(DestAddr->TAAddressCount != 1) {
		return STATUS_INVALID_PARAMETER;
	}
	if(BindAddrList->TAAddressCount < 1) {
		return STATUS_INVALID_PARAMETER;
	}
	// Windows does not allow to wait for more than MAXIMUM_WAIT_OBJECTS
	// even using wait block buffer.
	if(BindAddrList->TAAddressCount > MAXIMUM_WAIT_OBJECTS) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	if(DestAddr->Address[0].AddressType != TDI_ADDRESS_TYPE_LPX) {
		return STATUS_NOT_IMPLEMENTED;
	}


	bindAddr.TAAddressCount = 1;
	status = STATUS_UNSUCCESSFUL;

	//
	// Allocate overlapped context.
	//
	overlapped = ExAllocatePoolWithTag(
					NonPagedPool,
					sizeof(LSTRANS_OVERLAPPED) * BindAddrList->TAAddressCount,
					LSS_OVERLAPPED_BUFFER_POOLTAG
					);
	if(overlapped == NULL)
		return STATUS_INSUFFICIENT_RESOURCES;
	//
	// Allocate completion events
	//
	overlappedEvents = ExAllocatePoolWithTag(
					NonPagedPool,
					sizeof(KEVENT) * BindAddrList->TAAddressCount,
					LSS_OVERLAPPED_EVENT_POOLTAG
					);;
	if(overlappedEvents == NULL) {
		ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG);
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	//
	// Allocate wait blocks.
	// Need this buffer to wait for more than THREAD_WAIT_OBJECTS.
	//
	overlappedWaitBlocks = ExAllocatePoolWithTag(
					NonPagedPool,
					sizeof(KWAIT_BLOCK) * BindAddrList->TAAddressCount,
					LSS_OVERLAPPED_WAITBLOCK_POOLTAG);
	if(overlappedWaitBlocks == NULL) {
		ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG);
		ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG);
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	//
	// Allocate LSSes
	//
	overlappedLSS = ExAllocatePoolWithTag(
					NonPagedPool,
					sizeof(LANSCSI_SESSION) * BindAddrList->TAAddressCount,
					LSS_OVERLAPPED_LSS_POOLTAG);
	if(overlappedLSS == NULL){
		ExFreePoolWithTag(overlappedWaitBlocks, LSS_OVERLAPPED_WAITBLOCK_POOLTAG);
		ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG);
		ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	//
	// Connect asynchronously for each binding address
	//

	for(idx_addr = 0; idx_addr < (ULONG)BindAddrList->TAAddressCount; idx_addr++) {

		RtlCopyMemory(	bindAddr.Address,
						&BindAddrList->Address[idx_addr],
						sizeof(struct  _AddrLstrans));

		KDPrintM(DBG_PROTO_ERROR, ("BindingAddr%d=%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n",
			idx_addr,
			bindAddr.Address[0].Address.Address[0],
			bindAddr.Address[0].Address.Address[1],
			bindAddr.Address[0].Address.Address[2],
			bindAddr.Address[0].Address.Address[3],
			bindAddr.Address[0].Address.Address[4],
			bindAddr.Address[0].Address.Address[5],
			bindAddr.Address[0].Address.Address[6],
			bindAddr.Address[0].Address.Address[7]
			));

		// We do not need encryption buffer for connect operation.
		overlappedLSS[idx_addr].EncryptBuffer = NULL;
		overlappedLSS[idx_addr].EncryptBufferLength = 0;

		LspCopy(&overlappedLSS[idx_addr], LSS, FALSE);

		//
		// Initialize overlapped buffer
		//

		KeInitializeEvent(&overlappedEvents[idx_addr], NotificationEvent, FALSE);
		overlappedWait[idx_addr] = &overlappedEvents[idx_addr];
		overlapped[idx_addr].IoCompleteRoutine = LstransConnectComp;
		overlapped[idx_addr].CompletionEvent = &overlappedEvents[idx_addr];
		overlapped[idx_addr].UserContext = NULL;

		//
		// Connect asynchronously
		//

		status = LspConnect(&overlappedLSS[idx_addr], &bindAddr, DestAddr, &overlapped[idx_addr], IF_NULL_TIMEOUT_THEN_DEFAULT(LSS, TimeOut));
		if(!NT_SUCCESS(status)) {
			// Set the completion event to continue with KeWaitForMultipleObjects()
			// even though this address fails.
			overlapped[idx_addr].IoStatusBlock.Status = status;
			KeSetEvent(overlapped[idx_addr].CompletionEvent, IO_NO_INCREMENT, FALSE);
			KDPrintM(DBG_PROTO_ERROR,("LspConnect() failed. idx=%d STATUS=%08lx\n", idx_addr, status));
		}
	}

	do {
		//
		// Wait for all connect completion events
		//

		status = KeWaitForMultipleObjects(
						BindAddrList->TAAddressCount,
						overlappedWait,
						WaitAll,
						Executive,
						KernelMode,
						FALSE,
						NULL,
						overlappedWaitBlocks);
		if(!NT_SUCCESS(status)) {
			ASSERT(FALSE);
			break;
		}

		//
		// Find the first connected address
		//

		for(idx_addr = 0; idx_addr < (ULONG)BindAddrList->TAAddressCount; idx_addr++) {
			status = overlapped[idx_addr].IoStatusBlock.Status;
			if(status == STATUS_SUCCESS) {
				break;
			}
		}

		//
		// Clean up unsuccessful or non-selected connections.
		//
		for(idx_cleanup_addr = 0; idx_cleanup_addr < (ULONG)BindAddrList->TAAddressCount; idx_cleanup_addr++) {
			if(idx_cleanup_addr != idx_addr)
				LspDisconnect(&overlappedLSS[idx_cleanup_addr]);
		}

		//
		// set return value
		//
		if(status == STATUS_SUCCESS) {
			if(BoundAddr) {
				LspCopy(LSS, &overlappedLSS[idx_addr], FALSE);

				BoundAddr->TAAddressCount = 1;
				RtlCopyMemory(	BoundAddr->Address,
					&BindAddrList->Address[idx_addr],
					sizeof(struct  _AddrLstrans));
			}
		} else {
			KDPrintM(DBG_PROTO_ERROR, ("Could not connect to the dest\n"));
		}

	} while(FALSE);


	ExFreePoolWithTag(overlappedLSS, LSS_OVERLAPPED_LSS_POOLTAG);
	ExFreePoolWithTag(overlappedWaitBlocks, LSS_OVERLAPPED_WAITBLOCK_POOLTAG);
	ExFreePoolWithTag(overlappedEvents, LSS_OVERLAPPED_EVENT_POOLTAG);
	ExFreePoolWithTag(overlapped, LSS_OVERLAPPED_BUFFER_POOLTAG);


	return status;
}
Exemple #13
0
VOID
RedirDataGramSvrThreadProc (
	PLFSDGRAMSVR_CTX	SvrCtx
	) 
{
	BOOLEAN				bret;
	NTSTATUS			status;
	LFSDG_Socket		ServerDatagramSocket;
	PKEVENT				Evts[3];
	PLIST_ENTRY			listEntry;
	PLFSDG_PKT			pkt;

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
				   ("[LFS] RedirDataGramSvrThreadProc: Initializing Redirection Datagram server...\n") );

	// Open server datagram port

	status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT );

	if (status == STATUS_SUCCESS) {

		// register Datagram handler

		status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket,
												 LfsSvrDatagramRecvHandler,
												 SvrCtx );
	}

	Evts[0] = &SvrCtx->ShutdownEvent;
	Evts[1] = &SvrCtx->DatagramRecvEvent;
	Evts[2] = &SvrCtx->NetworkEvent;

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
					("[LFS] RedirDataGramSvrThreadProc: Redirection Datagram server started...\n") );

	// Main loop...

	while(1) {
	
		status = KeWaitForMultipleObjects( 3,
										   Evts,
										   WaitAny,
										   Executive,
										   KernelMode,
										   TRUE,
										   NULL,
										   NULL );

		SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
					   ("[LFS] RedirDataGramSvrThreadProc: NTSTATUS:%lu\n", status) );

		if (status == 0) {

			SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
						   ("[LFS] RedirDataGramSvrThreadProc: ShutDown event received. NTSTATUS:%lu\n", status) );

			break;
		
		} else if (status == 1) {
			
			//	Datagram received.
			
			KeClearEvent( &SvrCtx->DatagramRecvEvent );

			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: DatagramRecv event received. NTSTATUS:%lu\n", status) );
		
		} else if (status == 2) {
			
			// Renew server datagram port
			
			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: Networking event received. NTSTATUS:%lu\n", status) );

			KeClearEvent( &SvrCtx->NetworkEvent );

			LfsCloseDGSocket( &ServerDatagramSocket );

			status = LfsOpenDGSocket( &ServerDatagramSocket, DEFAULT_DATAGRAM_SVRPORT );
			
			if (status == STATUS_SUCCESS) {
				
				// register Datagram handler
				
				status = LfsRegisterDatagramRecvHandler( &ServerDatagramSocket,
														 LfsSvrDatagramRecvHandler,
														 SvrCtx );
			}

			continue;

		} else {
			
			SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, 
						   ("[LFS] RedirDataGramSvrThreadProc: KeWaitForMultipleObjects() failed. NTSTATUS:%lu\n", status) );
			break;
		}

		//	get packets to the dispatch routine.

		while (1) {

			listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue,
													 &SvrCtx->RecvDGPktQSpinLock );

			if (!listEntry) {
			
				SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
							   ("[LFS] RedirDataGramSvrThreadProc: Datagram queue empty. back to waiting mode.\n") );
				break;
			}

			pkt = CONTAINING_RECORD( listEntry, LFSDG_PKT, PktListEntry );

			bret = DispatchDGReqPkt( SvrCtx, pkt );

			if (FALSE == bret) {
			
				SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, ( "[LFS] RedirDataGramSvrThreadProc: Don't send a reply.\n") );

			} else {

				SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: Send a reply.\n") );

				status = LfsSendDatagram( &ServerDatagramSocket, pkt, &pkt->SourceAddr );

				if (status != STATUS_SUCCESS) {

					SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: LfsSendDatagram() failed.\n"));
				}
			}

			//	dereference the datagram packet
	
			LfsDereferenceDGPkt( pkt );
		}
	}

	LfsCloseDGSocket( &ServerDatagramSocket );

	//	free datagram packets.

	while (1) {

		listEntry = ExInterlockedRemoveHeadList( &SvrCtx->RecvDGPktQueue,
												 &SvrCtx->RecvDGPktQSpinLock );
		
		if (!listEntry) {
		
			SPY_LOG_PRINT( LFS_DEBUG_LIB_NOISE, 
						   ("[LFS] RedirDataGramSvrThreadProc: Cleared datagram packets.\n") );
			break;
		}

		pkt = CONTAINING_RECORD(listEntry, LFSDG_PKT, PktListEntry);
		
		LfsDereferenceDGPkt( pkt );
	}

	SPY_LOG_PRINT( LFS_DEBUG_LIB_INFO, ( "[LFS] RedirDataGramSvrThreadProc: terminated..\n") );
	PsTerminateSystemThread(0);

	return;
}
Exemple #14
0
VOID
VolDoThreadProc (
	IN	PVOLUME_DEVICE_OBJECT	VolDo
	)
{
	BOOLEAN		volDoThreadTerminate = FALSE;


	DebugTrace( 0, Dbg2, ("VolDoThreadProc: Start VolDo = %p\n", VolDo) );
	
	VolDo_Reference( VolDo );
	
	VolDo->Thread.Flags = VOLDO_THREAD_FLAG_INITIALIZING;

	ExAcquireFastMutex( &VolDo->FastMutex );		
	ClearFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_INITIALIZING );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_START );
	ExReleaseFastMutex( &VolDo->FastMutex );
			
	KeSetEvent( &VolDo->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	volDoThreadTerminate = FALSE;
	
	while (volDoThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &VolDo->RequestEvent;

		timeOut.QuadPart = -NDNTFS_VOLDO_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );


		if (eventStatus == STATUS_TIMEOUT) {

			LARGE_INTEGER	currentTime;

			KeQuerySystemTime( &currentTime );

			if (FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_SHUTDOWN) || 
				!(FlagOn(VolDo->NdasNtfsFlags, NDAS_NTFS_DEVICE_FLAG_MOUNTED) /*&& !FlagOn(LfsDeviceExt->Flags, LFS_DEVICE_STOP)*/)) {
				
				continue;
			}

			if ((VolDo->NetdiskEnableMode == NETDISK_READ_ONLY && 
				 (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || 
				 (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_PURGE_DURATION)) ||

			    (VolDo->ReceiveWriteCommand == TRUE && 
				 (VolDo->TryFlushOrPurgeTime.QuadPart > currentTime.QuadPart || 
				 (currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) >= NDNTFS_TRY_FLUSH_DURATION))) {

				if (VolDo->NetdiskEnableMode != NETDISK_READ_ONLY && 
					(currentTime.QuadPart - VolDo->CommandReceiveTime.QuadPart) <=  NDNTFS_TRY_FLUSH_DURATION /*&& 
					(currentTime.QuadPart - VolDo->TryFlushOrPurgeTime.QuadPart) <= (100*NDNTFS_TRY_FLUSH_OR_PURGE_DURATION)*/) {

					continue;
				}

				do {
				
					HANDLE					eventHandle = NULL;

					HANDLE					fileHandle = NULL;
					ACCESS_MASK				desiredAccess;
					ULONG					attributes;
					OBJECT_ATTRIBUTES		objectAttributes;
					IO_STATUS_BLOCK			ioStatusBlock;
					LARGE_INTEGER			allocationSize;
					ULONG					fileAttributes;
					ULONG					shareAccess;
				    ULONG					createDisposition;
					ULONG					createOptions;
				    PVOID					eaBuffer;
					ULONG					eaLength;

					NTSTATUS				createStatus;
					NTSTATUS				fileSystemControlStatus;

					PIRP					topLevelIrp;
					PRIMARY_REQUEST_INFO	primaryRequestInfo;


					ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

					if (VolDo->NetdiskEnableMode == NETDISK_SECONDARY) {

						break;
					}

					DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, VolDo->NetdiskPartitionInformation.VolumeName = %wZ\n", 
											VolDo, &VolDo->NetdiskPartitionInformation.VolumeName) );

					desiredAccess = SYNCHRONIZE | READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_WRITE_EA 
									| FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_READ_EA;

					ASSERT( desiredAccess == 0x0012019F );

					attributes  = OBJ_KERNEL_HANDLE;
					attributes |= OBJ_CASE_INSENSITIVE;

					InitializeObjectAttributes( &objectAttributes,
											    &VolDo->NetdiskPartitionInformation.VolumeName,
												attributes,
												NULL,
												NULL );
		
					allocationSize.LowPart  = 0;
					allocationSize.HighPart = 0;

					fileAttributes	  = 0;		
					shareAccess		  = FILE_SHARE_READ | FILE_SHARE_WRITE;
					createDisposition = FILE_OPEN;
					createOptions     = FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE;
					eaBuffer		  = NULL;
					eaLength		  = 0;

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					createStatus = ZwCreateFile( &fileHandle,
												 desiredAccess,
												 &objectAttributes,
												 &ioStatusBlock,
												 &allocationSize,
												 fileAttributes,
												 shareAccess,
												 createDisposition,
												 createOptions,
												 eaBuffer,
												 eaLength );

					if (createStatus != STATUS_SUCCESS) 
						break;
						
					ASSERT( ioStatusBlock.Information == FILE_OPENED);
	
					createStatus = ZwCreateEvent( &eventHandle,
												  GENERIC_READ,
												  NULL,
												  SynchronizationEvent,
												  FALSE );

					if (createStatus != STATUS_SUCCESS) {

						ASSERT( NDASNTFS_UNEXPECTED );
						ZwClose( fileHandle );
						break;
					}

					primaryRequestInfo.PrimaryTag			  = 0xe2027482;
					primaryRequestInfo.PrimarySessionId		  = NDASNTFS_LOCAL_PRMARY_SESSION_ID;
					primaryRequestInfo.PrimarySession		  = NULL;
					primaryRequestInfo.NdfsWinxpRequestHeader = NULL;

					topLevelIrp = IoGetTopLevelIrp();
					ASSERT( topLevelIrp == NULL );
					IoSetTopLevelIrp( (PIRP)&primaryRequestInfo );

					RtlZeroMemory( &ioStatusBlock, sizeof(ioStatusBlock) );

					fileSystemControlStatus = ZwFsControlFile( fileHandle,
															   NULL, //&eventHandle,
															   NULL,
															   NULL,
															   &ioStatusBlock,
															   (VolDo->NetdiskEnableMode == NETDISK_READ_ONLY) ?
																	FSCTL_NDAS_FS_PURGE : FSCTL_NDAS_FS_FLUSH,
															   NULL,
															   0,
															   NULL,
															   0 );

					DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, createStatus = %x, ioStatusBlock = %x\n", 
											VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					if (fileSystemControlStatus == STATUS_PENDING) {
			
						LARGE_INTEGER			timeOut;
			
						timeOut.QuadPart = -3*NANO100_PER_SEC;

						ASSERT( FALSE );
						//fileSystemControlStatus = ZwWaitForSingleObject( eventHandle, TRUE,NULL /*, &timeOut*/ );
					}

					IoSetTopLevelIrp( topLevelIrp );

					if (fileSystemControlStatus != STATUS_SUCCESS)
						DebugTrace( 0, Dbg2, ("VolDoThreadProc: VolDo = %p, fileSystemControlStatus = %x, ioStatusBlock = %x\n", 
												VolDo, fileSystemControlStatus, ioStatusBlock.Information) );

					ZwClose( eventHandle );
					ZwClose( fileHandle );
					
					break;
				
				} while (0);

				KeQuerySystemTime( &VolDo->TryFlushOrPurgeTime );
				VolDo->ReceiveWriteCommand = FALSE;
			}

			continue;
		}
		
		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( NDASNTFS_UNEXPECTED );
			SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_ERROR );
			volDoThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			volDoThreadTerminate = TRUE;
			break;
		
		} else {

			NDAS_ASSERT( NDASNTFS_BUG );
		}
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &VolDo->FastMutex );

	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_STOPED );

	ExReleaseFastMutex( &VolDo->FastMutex );

	DebugTrace( 0, Dbg2, ("VolDoThreadProc: PsTerminateSystemThread VolDo = %p\n", VolDo) );
	
	ExAcquireFastMutex( &VolDo->FastMutex );
	SetFlag( VolDo->Thread.Flags, VOLDO_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &VolDo->FastMutex );
	
	VolDo_Dereference( VolDo );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
Exemple #15
0
static VOID NTAPI
QueueThread(PVOID Context)
/*
 * FUNCTION: Thread that manages the queue and dispatches any queued requests
 * ARGUMENTS:
 *     Context: unused
 */
{
    PIRP Irp;
    PIO_STACK_LOCATION Stack;
    PDEVICE_OBJECT DeviceObject;
    PVOID Objects[2];

    PAGED_CODE();
    UNREFERENCED_PARAMETER(Context);

    Objects[0] = &QueueSemaphore;
    Objects[1] = &QueueThreadTerminate;

    for(;;)
    {
        KeWaitForMultipleObjects(2, Objects, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);

        if(KeReadStateEvent(&QueueThreadTerminate))
        {
            INFO_(FLOPPY, "QueueThread terminating\n");
            return;
        }

        INFO_(FLOPPY, "QueueThread: servicing an IRP\n");

        Irp = IoCsqRemoveNextIrp(&Csq, 0);

        /* we won't get an irp if it was canceled */
        if(!Irp)
        {
            INFO_(FLOPPY, "QueueThread: IRP queue empty\n");
            continue;
        }

        DeviceObject = (PDEVICE_OBJECT)Irp->Tail.Overlay.DriverContext[0];

        ASSERT(DeviceObject);

        Stack = IoGetCurrentIrpStackLocation(Irp);

        /* Decide what to do with the IRP */
        switch(Stack->MajorFunction)
        {
        case IRP_MJ_READ:
        case IRP_MJ_WRITE:
            ReadWritePassive(DeviceObject->DeviceExtension, Irp);
            break;

        case IRP_MJ_DEVICE_CONTROL:
            DeviceIoctlPassive(DeviceObject->DeviceExtension, Irp);
            break;

        default:
            WARN_(FLOPPY, "QueueThread(): Unrecognized irp: mj: 0x%x\n", Stack->MajorFunction);
            Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
            Irp->IoStatus.Information = 0;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);
        }
    }
}
Exemple #16
0
LONG
NTAPI
Send(
	__in PWSK_SOCKET	WskSocket,
	__in PVOID			Buffer,
	__in ULONG			BufferSize,
	__in ULONG			Flags,
	__in ULONG			Timeout,
	__in KEVENT			*send_buf_kill_event,
	__in struct			drbd_transport *transport,
	__in enum			drbd_stream stream
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesSent = SOCKET_ERROR; // DRBC_CHECK_WSK: SOCKET_ERROR be mixed EINVAL?
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || ((int) BufferSize <= 0))
		return SOCKET_ERROR;

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		FreeWskBuffer(&WskBuffer);
		return SOCKET_ERROR;
	}

	Flags |= WSK_FLAG_NODELAY;

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskSend(
		WskSocket,
		&WskBuffer,
		Flags,
		Irp);

	if (Status == STATUS_PENDING)
	{
		LARGE_INTEGER	nWaitTime;
		LARGE_INTEGER	*pTime;

		int retry_count = 0;
	retry:
		if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT)
		{
			pTime = NULL;
		}
		else
		{
			nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10);
			pTime = &nWaitTime;
		}
		{
			struct      task_struct *thread = current;
			PVOID       waitObjects[2];
			int         wObjCount = 1;

			waitObjects[0] = (PVOID) &CompletionEvent;
#ifndef _WIN32_SEND_BUFFING 
			// in send-buffering, Netlink , call_usermodehelper are distinguished to SendLocal
			// KILL event is only used in send-buffering thread while send block. 
			// WIN32_V9_REFACTO_:required to refactoring that input param, log message are simplized.
#else

#endif
			Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);
			switch (Status)
			{
			case STATUS_TIMEOUT:
#ifdef _WIN32_SEND_BUFFING
				if (wObjCount == 1)
				{
					retry_count++;
					WDRBD_WARN("(%s) sent timeout=%d sz=%d retry_count=%d WskSocket=%p IRP=%p\n",
						current->comm, Timeout, BufferSize, retry_count,WskSocket, Irp);

					// required to refactroing about retrying method.

					goto retry;
				}
#endif
				if (transport != NULL)
				{
					if (!drbd_stream_send_timed_out(transport, stream))
					{
						goto retry;
					}
				}

				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				BytesSent = -EAGAIN;
				break;

			case STATUS_WAIT_0:
				if (NT_SUCCESS(Irp->IoStatus.Status))
				{
					BytesSent = (LONG)Irp->IoStatus.Information;
				}
				else
				{
					WDRBD_WARN("tx error(%s) wsk(0x%p)\n", GetSockErrorString(Irp->IoStatus.Status), WskSocket);
					switch (Irp->IoStatus.Status)
					{
						case STATUS_IO_TIMEOUT:
							BytesSent = -EAGAIN;
							break;
						case STATUS_INVALID_DEVICE_STATE:
							BytesSent = -EAGAIN;
							break;
						default:
							BytesSent = -ECONNRESET;
							break;
					}
				}
				break;

			//case STATUS_WAIT_1: // common: sender or send_bufferinf thread's kill signal
			//	IoCancelIrp(Irp);
			//	KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
			//	BytesSent = -EINTR;
			//	break;

			default:
				WDRBD_ERROR("Wait failed. status 0x%x\n", Status);
				BytesSent = SOCKET_ERROR;
			}
		}
	}
	else
	{
		if (Status == STATUS_SUCCESS)
		{
			BytesSent = (LONG) Irp->IoStatus.Information;
			WDRBD_WARN("(%s) WskSend No pending: but sent(%d)!\n", current->comm, BytesSent);
		}
		else
		{
			WDRBD_WARN("(%s) WskSend error(0x%x)\n", current->comm, Status);
			BytesSent = SOCKET_ERROR;
		}
	}

	IoFreeIrp(Irp);
	FreeWskBuffer(&WskBuffer);

	return BytesSent;
}
Exemple #17
0
// Worker thread for processing all tunnel events
_Use_decl_annotations_
VOID
otLwfTunWorkerThread(
    PVOID   Context
    )
{
    PMS_FILTER pFilter = (PMS_FILTER)Context;
    NT_ASSERT(pFilter);

    LogFuncEntry(DRIVER_DEFAULT);

    PKEVENT WaitEvents[] = 
    { 
        &pFilter->TunWorkerThreadStopEvent,
        &pFilter->TunWorkerThreadAddressChangedEvent
    };

    LogFuncExit(DRIVER_DEFAULT);
    
    while (true)
    {
        // Wait for event to stop or process event to fire
        NTSTATUS status = 
            KeWaitForMultipleObjects(
                ARRAYSIZE(WaitEvents), 
                (PVOID*)WaitEvents, 
                WaitAny, 
                Executive, 
                KernelMode, 
                FALSE, 
                NULL, 
                NULL);

        // If it is the first event, then we are shutting down. Exit loop and terminate thread
        if (status == STATUS_WAIT_0)
        {
            LogInfo(DRIVER_DEFAULT, "Received tunnel worker thread shutdown event.");
            break;
        }
        else if (status == STATUS_WAIT_0 + 1) // TunWorkerThreadAddressChangedEvent fired
        {
            PVOID DataBuffer = NULL;
            const uint8_t* value_data_ptr = NULL;
            spinel_size_t value_data_len = 0;
            
            // Query the current addresses
            status = 
                otLwfCmdGetProp(
                    pFilter,
                    &DataBuffer,
                    SPINEL_PROP_IPV6_ADDRESS_TABLE,
                    SPINEL_DATATYPE_DATA_S,
                    &value_data_ptr,
                    &value_data_len);
            if (NT_SUCCESS(status))
            {
                uint32_t aNotifFlags = 0;
                otLwfTunAddressesUpdated(pFilter, value_data_ptr, value_data_len, &aNotifFlags);

                // Send notification
                if (aNotifFlags != 0)
                {
                    PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter);
                    if (NotifEntry)
                    {
                        RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY));
                        NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid;
                        NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE;
                        NotifEntry->Notif.StateChangePayload.Flags = aNotifFlags;

                        otLwfIndicateNotification(NotifEntry);
                    }
                }
            }
            else
            {
                LogWarning(DRIVER_DEFAULT, "Failed to query addresses, %!STATUS!", status);
            }

            if (DataBuffer) FILTER_FREE_MEM(DataBuffer);
        }
        else
        {
            LogWarning(DRIVER_DEFAULT, "Unexpected wait result, %!STATUS!", status);
        }
    }

    PsTerminateSystemThread(STATUS_SUCCESS);
}
Exemple #18
0
VOID
PrimaryAgentThreadProc(
	IN 	PPRIMARY	Primary
	)
{
	BOOLEAN			primaryAgentThreadExit = FALSE;
	ULONG			listenSocketIndex;
	PKWAIT_BLOCK	waitBlocks;

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: Start\n"));

	Primary->Agent.Flags |= PRIMARY_AGENT_INITIALIZING;
	
	//
	// Allocate wait block
	//
	 waitBlocks = ExAllocatePool(NonPagedPool, sizeof(KWAIT_BLOCK) * MAXIMUM_WAIT_OBJECTS);
	 if(waitBlocks == NULL) {
		 ASSERT(LFS_REQUIRED);
		 PsTerminateSystemThread(STATUS_INSUFFICIENT_RESOURCES);
	 }

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeInitializeEvent(
					&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent, 
					NotificationEvent, 
					FALSE
					);

	BindListenSockets(
		Primary
		);

	Primary->Agent.Flags |= PRIMARY_AGENT_START;
				
	KeSetEvent(&Primary->Agent.ReadyEvent, IO_DISK_INCREMENT, FALSE);


	while(primaryAgentThreadExit == FALSE)
	{
		PKEVENT				events[MAXIMUM_WAIT_OBJECTS];
		LONG				eventCnt;

		ULONG				i;

		LARGE_INTEGER		timeOut;
		NTSTATUS			ntStatus;
		PLIST_ENTRY			primaryAgentRequestEntry;


		ASSERT(MAX_SOCKETLPX_INTERFACE + 1 <= MAXIMUM_WAIT_OBJECTS);

		eventCnt = 0;
		events[eventCnt++] = &Primary->Agent.RequestEvent;

		if(!BooleanFlagOn(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN))
		{
			for(i=0; i<MAX_SOCKETLPX_INTERFACE; i++)
			{
				if(Primary->Agent.ListenSocket[i].TdiListenContext.Irp &&
					Primary->Agent.ListenSocket[i].Active)
				{
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
				else
				{
					// events[eventCnt++] = NULL; // I wanna set NULL, But It's not Work
					events[eventCnt++] = &Primary->Agent.ListenSocket[i].TdiListenContext.CompletionEvent;
				}
			}

			ASSERT(eventCnt == MAX_SOCKETLPX_INTERFACE + 1);
		}

		timeOut.QuadPart = - 5 * HZ;
		ntStatus = KeWaitForMultipleObjects(
					eventCnt,
					events,
					WaitAny,
					Executive,
					KernelMode,
					TRUE,
					&timeOut,
					waitBlocks
				);

		if(ntStatus == STATUS_TIMEOUT) 
		{
			continue;
		}

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
			("PrimaryAgentThreadProc: NTSTATUS:%lu\n", ntStatus));
		

		if(!NT_SUCCESS(ntStatus) || ntStatus >= eventCnt)
		{
			ASSERT(LFS_UNEXPECTED);
			SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

			primaryAgentThreadExit = TRUE;

			continue;
		}

		KeClearEvent(events[ntStatus]);

		if(0 == ntStatus)
		{
			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
					("PrimaryAgentThreadProc: RequestEvent received\n"));

			while(primaryAgentRequestEntry = 
					ExInterlockedRemoveHeadList(
							&Primary->Agent.RequestQueue,
							&Primary->Agent.RequestQSpinLock
							)
				) 
			{
				PPRIMARY_AGENT_REQUEST		primaryAgentRequest;

				primaryAgentRequest = CONTAINING_RECORD(
										primaryAgentRequestEntry,
										PRIMARY_AGENT_REQUEST,
										ListEntry
										);
	
				switch(primaryAgentRequest->RequestType) 
				{

				case PRIMARY_AGENT_REQ_DISCONNECT:
				{
					CloseListenSockets(
						Primary,
						FALSE
						);
				
					break;
				}

				case PRIMARY_AGENT_REQ_SHUTDOWN:
				{
					CloseListenSockets(
						Primary,
						TRUE
						);				
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_SHUTDOWN);
					break;
				}

				case PRIMARY_AGENT_REQ_DOWN:

					primaryAgentThreadExit = TRUE;
					break;

				//
				//	added to adapt network card changes.
				//
				case PRIMARY_AGENT_REQ_NIC_DISABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_DISABLED\n"));
					PrimaryAgentNICDisabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				case PRIMARY_AGENT_REQ_NIC_ENABLED:
				
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
						("PrimaryAgentThreadProc: PRIMARY_AGENT_REQ_NIC_ENABLED\n"));
					PrimaryAgentNICEnabled(Primary, &primaryAgentRequest->AddressList);
				
					break;

				default:
		
					ASSERT(LFS_BUG);
					SetFlag(Primary->Agent.Flags, PRIMARY_AGENT_ERROR);

					break;
				}

				if(primaryAgentRequest->Synchronous == TRUE)
						KeSetEvent(&primaryAgentRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
				else
					DereferencePrimaryAgentRequest(
						primaryAgentRequest
						);
			}

			continue;	
		}

		ASSERT(1 <= ntStatus && ntStatus < eventCnt); // LpxEvent 
		
		if(	1 <= ntStatus &&
			ntStatus <= MAX_SOCKETLPX_INTERFACE
			) // Connected 
		{
			NTSTATUS		tdiStatus;
			HANDLE			listenFileHandle;
			PFILE_OBJECT	listenFileObject;
			HANDLE			connFileHandle;
			PFILE_OBJECT	connFileObject;
			PPRIMARY_LISTEN_SOCKET	listenSocket;
			LPX_ADDRESS		remoteAddress;

			listenSocket = &Primary->Agent.ListenSocket[ntStatus-1];

			//
			//	retreive a connection file and remote address.
			//
			connFileHandle = listenSocket->ListenFileHandle;
			connFileObject = listenSocket->ListenFileObject;
			RtlCopyMemory(&remoteAddress, &listenSocket->TdiListenContext.RemoteAddress, sizeof(LPX_ADDRESS));

			listenSocket->TdiListenContext.Irp = NULL;
			listenSocket->ListenFileHandle = NULL;
			listenSocket->ListenFileObject = NULL;
			KeClearEvent(&listenSocket->TdiListenContext.CompletionEvent);

			if(!listenSocket->Active) 
			{
				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("ListenSocket is not active. Maybe a NIC disabled.\n"));
				continue;

			} 
			else if(listenSocket->TdiListenContext.Status != STATUS_SUCCESS) 
			{
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("Listen IRP #%d failed.\n", ntStatus));
				continue;
			}

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
					("PrimaryAgentThreadProc: Connect from %02X:%02X:%02X:%02X:%02X:%02X 0x%4X\n",
						listenSocket->TdiListenContext.RemoteAddress.Node[0], listenSocket->TdiListenContext.RemoteAddress.Node[1],
						listenSocket->TdiListenContext.RemoteAddress.Node[2], listenSocket->TdiListenContext.RemoteAddress.Node[3],
						listenSocket->TdiListenContext.RemoteAddress.Node[4], listenSocket->TdiListenContext.RemoteAddress.Node[5],
						NTOHS(listenSocket->TdiListenContext.RemoteAddress.Port)
						));

			//
			//	Make a new listen connection first of all to get another connection.
			//	It must be earlier than start a session that takes long time.
			//	Primary cannot accept a connection before it creates a new listen object.
			//
			tdiStatus = MakeConnectionObject(
							listenSocket->AddressFileHandle,
							listenSocket->AddressFileObject,
							&listenFileHandle,
							&listenFileObject
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);

				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
				goto start_session;
			}

			listenSocket->ListenFileHandle = listenFileHandle;
			listenSocket->ListenFileObject = listenFileObject;

			listenSocket->Flags	= TDI_QUERY_ACCEPT;
			tdiStatus = LpxTdiListenWithCompletionEvent(
							listenSocket->ListenFileObject,
							&listenSocket->TdiListenContext,
							&listenSocket->Flags
							);

			if(!NT_SUCCESS(tdiStatus)) 
			{
				ASSERT(LPX_BUG);
				LpxTdiDisassociateAddress(listenFileObject);
				LpxTdiCloseConnection(listenFileHandle, listenFileObject);
				LpxTdiCloseAddress (
					listenSocket->AddressFileHandle, 
					listenSocket->AddressFileObject
					);
				listenSocket->Active = FALSE;
				Primary->Agent.ActiveListenSocketCount --;
	
			}

start_session:
			//
			//	start a session.
			//
			Primary_AcceptConnection(Primary, connFileHandle, connFileObject, ntStatus-1, &remoteAddress);
			
			continue;
		}
	}

	for(listenSocketIndex=0; listenSocketIndex<MAX_SOCKETLPX_INTERFACE; listenSocketIndex++)
		KeClearEvent(&Primary->Agent.ListenSocket[listenSocketIndex].TdiListenContext.CompletionEvent);

	//
	// Free wait blocks
	//

	ExFreePool(waitBlocks);

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("PrimaryAgentThreadProc: PsTerminateSystemThread\n"));
	
	Primary->Agent.Flags |= PRIMARY_AGENT_TERMINATED;

	PsTerminateSystemThread(STATUS_SUCCESS);
}
Exemple #19
0
VOID
HvlCtxSWorkItem(
    PVOID            Context,
    NDIS_HANDLE      NdisIoWorkItemHandle
    )
{
    NTSTATUS ntStatus = STATUS_SUCCESS;
    PHVL pHvl = NULL;
    LARGE_INTEGER waitTime = {0};
    #define NUM_EVENTS  3
    PVOID EventArray[NUM_EVENTS];  
    BOOLEAN fTerminating = FALSE;
    
    UNREFERENCED_PARAMETER(NdisIoWorkItemHandle);

    if (NULL == Context)
    {
        MPASSERT(Context != NULL);
        return;
    }

    pHvl = (PHVL) Context;
    EventArray[0] = &pHvl->TerminatingEvent;
    EventArray[1] = &pHvl->CtxSEvent;
    EventArray[2] = &pHvl->ExAccessEvent;

    /*
        The waitTime should ideally be a function of the beacon period. For now 
        assume a constant
        */
    waitTime.QuadPart = HVL_DEFAULT_CONTEXT_SWITCH_PARK_TIME_MSEC * -1;
    
    do
    {
        ntStatus = KeWaitForMultipleObjects(NUM_EVENTS, EventArray, WaitAny, Executive, KernelMode, FALSE, &waitTime, NULL);
        switch (ntStatus)
        {
            case STATUS_TIMEOUT:
                // timed context switch processing. 
                HvlProcessTimedCtxSwitch(pHvl);

                // optionally set a different waitTime for the next wait
                break;

            case STATUS_WAIT_0:
                // we are terminating. Time to get rid of this work item processing
                HvlLock(pHvl);
                pHvl->ulNumThreadsPending--;
                HvlUnlock(pHvl);  
                fTerminating = TRUE;
                break;

            case STATUS_WAIT_1:
                // we are asked to do context switch processing
                HvlProcessTimedCtxSwitch(pHvl);
                break;

            case STATUS_WAIT_2:
                // we have a new request for exclusive access
                HvlProcessExAccessReq(pHvl);
                break;
                
            default:
                MpTrace(COMP_HVL, DBG_SERIOUS, ("KeWaitForMultipleObjects returned error 0x%x", ntStatus));
                break;
        }        
    } while (!fTerminating);
}
Exemple #20
0
VOID IOThread(IN PVOID Context)
{
	KIRQL			currentIrql, oldIrql;
	LARGE_INTEGER 	timeout, maxTimeout;
	NTSTATUS		status = STATUS_SUCCESS;
			
	PRING_BUFFER	pRb;
	const PCHAR 	pMsg = "messahe1";
	ULONG			size = 8;
	INT_PTR			state;
	
	PKTIMER			pTimer;
	LONG 			interval;
	
	PVOID 			pObjects[3]; // wait for
	
	KeSetEvent(&StartEvent, 0, FALSE);
	
	timeout.QuadPart = -6000 * 10000; // 10 sec
	interval = 20000; // 5 sec
	maxTimeout.QuadPart = -20000 * 10000;
	
	InitRingBuffer(&pRb);
	
	state = (INT_PTR) ExAllocatePool(NonPagedPool, sizeof(INT));	
	
	
	// Set timer for periodic flush
	pTimer=(PKTIMER) ExAllocatePool(NonPagedPool, sizeof(KTIMER));
	KeInitializeTimerEx(pTimer, SynchronizationTimer);
	KeSetTimerEx(pTimer, timeout, interval, NULL);
	
	
	pObjects[0] = pTimer;				// periodic timer
	pObjects[1] = &StopEvent;			// stop flush loop
	pObjects[2] = &FlushEvent;			// do flush, buffer is full
	
	
	// Flush loop
	while (status != STATUS_WAIT_1) {
	
		status = KeWaitForMultipleObjects(
				3,
				pObjects,
				WaitAny,
				Executive,
				KernelMode,
				FALSE,
				&maxTimeout,
				NULL);
				
				
		if (status == STATUS_WAIT_0) {
			DbgPrint("Timer flush\n");
		} else if (status == STATUS_WAIT_2) {
			DbgPrint("RB flush\n");
		} else if (status == STATUS_TIMEOUT) {
			DbgPrint("Timeout delay\n");
			break;
		}
		
		//Klog("Msg from klog %d\s", 123);
		KloggerWriteToFile();
		//DbgPrint("State: %d\n", state);
		
	}
	
	DbgPrint("klogger.sys: IOThread get stop signal\n");
	
	
	// Free resources
	KeCancelTimer(pTimer);
	ExFreePool(pTimer);
	FreeRingBuffer(pRb);
	
	PsTerminateSystemThread(status);
	
}
Exemple #21
0
VOID
ReadonlyThreadProc (
	IN	PREADONLY	Readonly
	)
{
	BOOLEAN		readonlyThreadTerminate = FALSE;
	PLIST_ENTRY	readonlyRequestEntry;

	
	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThreadProc: Start Readonly = %p\n", Readonly) );
	
	Readonly_Reference( Readonly );
	
	Readonly->Thread.Flags = READONLY_THREAD_FLAG_INITIALIZING;

	ExAcquireFastMutex( &Readonly->FastMutex );		
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_START );
	ClearFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_INITIALIZING );
	ExReleaseFastMutex( &Readonly->FastMutex );
			
	KeSetEvent( &Readonly->ReadyEvent, IO_DISK_INCREMENT, FALSE );

	readonlyThreadTerminate = FALSE;
	
	while (readonlyThreadTerminate == FALSE) {

		PKEVENT			events[2];
		LONG			eventCount;
		NTSTATUS		eventStatus;
		LARGE_INTEGER	timeOut;
		

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;
		events[eventCount++] = &Readonly->RequestEvent;

		timeOut.QuadPart = -LFS_READONLY_THREAD_FLAG_TIME_OUT;

		eventStatus = KeWaitForMultipleObjects(	eventCount,
												events,
												WaitAny,
												Executive,
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

		if (eventStatus == STATUS_TIMEOUT) {

			ReadonlyTryCloseCcb( Readonly );
			ReadonlyDismountVolumeStart( Readonly );
			continue;
		}

		ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
		ASSERT( eventCount < THREAD_WAIT_OBJECTS );
		
		if (!NT_SUCCESS( eventStatus ) || eventStatus >= eventCount) {

			ASSERT( LFS_UNEXPECTED );
			SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_ERROR );
			readonlyThreadTerminate = TRUE;
			continue;
		}
		
		KeClearEvent( events[eventStatus] );

		if (eventStatus == 0) {

			while (!FlagOn(Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED) && 
				   (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
																	    &Readonly->RequestQSpinLock))) {

				PREADONLY_REQUEST	readonlyRequest;


				InitializeListHead( readonlyRequestEntry );

				readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
													  READONLY_REQUEST,
													  ListEntry );

				if (!(readonlyRequest->RequestType == READONLY_REQ_DISCONNECT ||
					  readonlyRequest->RequestType == READONLY_REQ_DOWN		  ||
					  readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE)) {

					ASSERT( FALSE );

					ExAcquireFastMutex( &Readonly->FastMutex );
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED | READONLY_THREAD_FLAG_ERROR );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ExInterlockedInsertHeadList( &Readonly->RequestQueue,
												 &readonlyRequest->ListEntry,
												 &Readonly->RequestQSpinLock );

					readonlyThreadTerminate = TRUE;
					break;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DISCONNECT) {
				
					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent(&readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE);
					else
						DereferenceReadonlyRequest( readonlyRequest );

					continue;
				}

				if (readonlyRequest->RequestType == READONLY_REQ_DOWN) {

					SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE, ("ReadonlyThread READONLY_REQ_DOWN Readonly = %p\n", Readonly) );

					ExAcquireFastMutex( &Readonly->FastMutex );		
					SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );
					ExReleaseFastMutex( &Readonly->FastMutex );

					ASSERT( IsListEmpty(&Readonly->RequestQueue) );

					if (readonlyRequest->Synchronous == TRUE)
						KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferenceReadonlyRequest( readonlyRequest );

					readonlyThreadTerminate = TRUE;
					break;
				}

				ASSERT( readonlyRequest->RequestType == READONLY_REQ_SEND_MESSAGE );
				ASSERT( readonlyRequest->Synchronous == TRUE );

			} // while 
		
		} else {

			NDAS_ASSERT( FALSE );
		}
	}

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	ExAcquireFastMutex( &Readonly->FastMutex );

	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_STOPED );

	while (readonlyRequestEntry = ExInterlockedRemoveHeadList(&Readonly->RequestQueue,
															   &Readonly->RequestQSpinLock)) {

		PREADONLY_REQUEST readonlyRequest;

		InitializeListHead( readonlyRequestEntry );
			
		readonlyRequest = CONTAINING_RECORD( readonlyRequestEntry,
											  READONLY_REQUEST,
											  ListEntry );
        
		readonlyRequest->ExecuteStatus = STATUS_IO_DEVICE_ERROR;
		
		if (readonlyRequest->Synchronous == TRUE)
			KeSetEvent( &readonlyRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferenceReadonlyRequest( readonlyRequest );
	}

	ExReleaseFastMutex( &Readonly->FastMutex );

	SPY_LOG_PRINT( LFS_DEBUG_READONLY_TRACE,
				   ("ReadonlyThreadProc: PsTerminateSystemThread Readonly = %p, IsListEmpty(&Readonly->RequestQueue) = %d\n", 
				     Readonly, IsListEmpty(&Readonly->RequestQueue)) );
	
	ExAcquireFastMutex( &Readonly->FastMutex );
	SetFlag( Readonly->Thread.Flags, READONLY_THREAD_FLAG_TERMINATED );
	ExReleaseFastMutex( &Readonly->FastMutex );
	
	Readonly_Dereference( Readonly );

	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
	
	PsTerminateSystemThread( STATUS_SUCCESS );
}
Exemple #22
0
VOID NTAPI
MiBalancerThread(PVOID Unused)
{
   PVOID WaitObjects[2];
   NTSTATUS Status;
   ULONG i;
   ULONG NrFreedPages;
   ULONG NrPagesUsed;
   ULONG Target;
   BOOLEAN ShouldRun;


   WaitObjects[0] = &MiBalancerEvent;
   WaitObjects[1] = &MiBalancerTimer;

   while (1)
   {
      Status = KeWaitForMultipleObjects(2,
                                        WaitObjects,
                                        WaitAny,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL,
                                        NULL);

      if (Status == STATUS_SUCCESS)
      {
         /* MiBalancerEvent */
         while (MmAvailablePages < MiMinimumAvailablePages + 5)
         {
            for (i = 0; i < MC_MAXIMUM; i++)
            {
               if (MiMemoryConsumers[i].Trim != NULL)
               {
                  NrFreedPages = 0;
                  Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages);
                  if (!NT_SUCCESS(Status))
                  {
                     KeBugCheck(MEMORY_MANAGEMENT);
                  }
               }
            }
         }
         InterlockedExchange(&MiBalancerWork, 0);
      }
      else if (Status == STATUS_SUCCESS + 1)
      {
         /* MiBalancerTimer */
         ShouldRun = MmAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE;
         for (i = 0; i < MC_MAXIMUM; i++)
         {
            if (MiMemoryConsumers[i].Trim != NULL)
            {
               NrPagesUsed = MiMemoryConsumers[i].PagesUsed;
               if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun)
               {
                  if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget)
                  {
                     Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget,
                                   MiMinimumPagesPerRun);
                  }
                  else
                  {
                     Target = MiMinimumPagesPerRun;
                  }
                  NrFreedPages = 0;
                  Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
                  if (!NT_SUCCESS(Status))
                  {
                     KeBugCheck(MEMORY_MANAGEMENT);
                  }
               }
            }
         }
      }
      else
      {
         DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status);
         KeBugCheck(MEMORY_MANAGEMENT);
      }
   }
}
Exemple #23
0
PWSK_SOCKET
NTAPI
Accept(
	__in PWSK_SOCKET	WskSocket,
	__out_opt PSOCKADDR	LocalAddress,
	__out_opt PSOCKADDR	RemoteAddress,
	__out_opt NTSTATUS	*RetStaus,
	__in int			timeout
)
{
	KEVENT			CompletionEvent = { 0 };
	PIRP			Irp = NULL;
	NTSTATUS		Status = STATUS_UNSUCCESSFUL;
	PWSK_SOCKET		AcceptedSocket = NULL;
    struct task_struct *thread = current;
    PVOID waitObjects[2];
    int wObjCount = 1;

	if (g_SocketsState != INITIALIZED || !WskSocket)
	{
		*RetStaus = SOCKET_ERROR;
		return NULL;
	}

	Status = InitWskData(&Irp, &CompletionEvent);
	if (!NT_SUCCESS(Status)) {
		*RetStaus = Status;
		return NULL;
	}

	Status = ((PWSK_PROVIDER_LISTEN_DISPATCH) WskSocket->Dispatch)->WskAccept(
		WskSocket,
		0,
		NULL,
		NULL,
		LocalAddress,
		RemoteAddress,
		Irp);

	if (Status == STATUS_PENDING)
	{
		LARGE_INTEGER	nWaitTime;
		LARGE_INTEGER	*pTime;

		if (timeout <= 0 || timeout == MAX_SCHEDULE_TIMEOUT)
		{
			pTime = 0;
		}
		else
		{
			nWaitTime = RtlConvertLongToLargeInteger(-1 * timeout * 10000000);
			pTime = &nWaitTime;
		}

        waitObjects[0] = (PVOID) &CompletionEvent;
        if (thread->has_sig_event)
        {
            waitObjects[1] = (PVOID) &thread->sig_event;
            wObjCount = 2;
        }

        Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);

		switch (Status)
		{
			case STATUS_WAIT_0:
				break;

			case STATUS_WAIT_0 + 1:
				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				*RetStaus = -EINTR;	
				break;

			case STATUS_TIMEOUT:
				IoCancelIrp(Irp);
				KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
				*RetStaus = STATUS_TIMEOUT;
				break;

			default:
				WDRBD_ERROR("Unexpected Error Status=0x%x\n", Status);
				break;
		}
	}
	else
	{
		if (Status != STATUS_SUCCESS)
		{
			WDRBD_TRACE("Accept Error Status=0x%x\n", Status);
		}
	}

	AcceptedSocket = (Status == STATUS_SUCCESS) ? (PWSK_SOCKET) Irp->IoStatus.Information : NULL;
	IoFreeIrp(Irp);
	return AcceptedSocket;
}
Exemple #24
0
VOID
NTAPI
MmZeroPageThread(VOID)
{
    PKTHREAD Thread = KeGetCurrentThread();
    PVOID StartAddress, EndAddress;
    PVOID WaitObjects[2];
    KIRQL OldIrql;
    PVOID ZeroAddress;
    PFN_NUMBER PageIndex, FreePage;
    PMMPFN Pfn1;

    /* Get the discardable sections to free them */
    MiFindInitializationCode(&StartAddress, &EndAddress);
    if (StartAddress) MiFreeInitializationCode(StartAddress, EndAddress);
    DPRINT("Free non-cache pages: %lx\n", MmAvailablePages + MiMemoryConsumers[MC_CACHE].PagesUsed);

    /* Set our priority to 0 */
    Thread->BasePriority = 0;
    KeSetPriorityThread(Thread, 0);

    /* Setup the wait objects */
    WaitObjects[0] = &MmZeroingPageEvent;
//    WaitObjects[1] = &PoSystemIdleTimer; FIXME: Implement idle timer

    while (TRUE)
    {
        KeWaitForMultipleObjects(1, // 2
                                 WaitObjects,
                                 WaitAny,
                                 WrFreePage,
                                 KernelMode,
                                 FALSE,
                                 NULL,
                                 NULL);
        OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
        while (TRUE)
        {
            if (!MmFreePageListHead.Total)
            {
                MmZeroingPageThreadActive = FALSE;
                KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
                break;
            }

            PageIndex = MmFreePageListHead.Flink;
            ASSERT(PageIndex != LIST_HEAD);
            Pfn1 = MiGetPfnEntry(PageIndex);
            MI_SET_USAGE(MI_USAGE_ZERO_LOOP);
            MI_SET_PROCESS2("Kernel 0 Loop");
            FreePage = MiRemoveAnyPage(MI_GET_PAGE_COLOR(PageIndex));

            /* The first global free page should also be the first on its own list */
            if (FreePage != PageIndex)
            {
                KeBugCheckEx(PFN_LIST_CORRUPT,
                             0x8F,
                             FreePage,
                             PageIndex,
                             0);
            }

            Pfn1->u1.Flink = LIST_HEAD;
            KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);

            ZeroAddress = MiMapPagesInZeroSpace(Pfn1, 1);
            ASSERT(ZeroAddress);
            RtlZeroMemory(ZeroAddress, PAGE_SIZE);
            MiUnmapPagesInZeroSpace(ZeroAddress, 1);

            OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);

            MiInsertPageInList(&MmZeroedPageListHead, PageIndex);
        }
    }
}
Exemple #25
0
LONG NTAPI Receive(
	__in  PWSK_SOCKET	WskSocket,
	__out PVOID			Buffer,
	__in  ULONG			BufferSize,
	__in  ULONG			Flags,
	__in ULONG			Timeout
)
{
	KEVENT		CompletionEvent = { 0 };
	PIRP		Irp = NULL;
	WSK_BUF		WskBuffer = { 0 };
	LONG		BytesReceived = SOCKET_ERROR;
	NTSTATUS	Status = STATUS_UNSUCCESSFUL;

    struct      task_struct *thread = current;
    PVOID       waitObjects[2];
    int         wObjCount = 1;

	if (g_SocketsState != INITIALIZED || !WskSocket || !Buffer || !BufferSize)
		return SOCKET_ERROR;

	if ((int) BufferSize <= 0)
	{
		return SOCKET_ERROR;
	}

	Status = InitWskBuffer(Buffer, BufferSize, &WskBuffer);
	if (!NT_SUCCESS(Status)) {
		return SOCKET_ERROR;
	}

	Status = InitWskData(&Irp, &CompletionEvent);

	if (!NT_SUCCESS(Status)) {
		FreeWskBuffer(&WskBuffer);
		return SOCKET_ERROR;
	}

	Status = ((PWSK_PROVIDER_CONNECTION_DISPATCH) WskSocket->Dispatch)->WskReceive(
				WskSocket,
				&WskBuffer,
				Flags,
				Irp);

    if (Status == STATUS_PENDING)
    {
        LARGE_INTEGER	nWaitTime;
        LARGE_INTEGER	*pTime;

        if (Timeout <= 0 || Timeout == MAX_SCHEDULE_TIMEOUT)
        {
            pTime = 0;
        }
        else
        {
            nWaitTime = RtlConvertLongToLargeInteger(-1 * Timeout * 1000 * 10);
            pTime = &nWaitTime;
        }

        waitObjects[0] = (PVOID) &CompletionEvent;
        if (thread->has_sig_event)
        {
            waitObjects[1] = (PVOID) &thread->sig_event;
            wObjCount = 2;
        }
        Status = KeWaitForMultipleObjects(wObjCount, &waitObjects[0], WaitAny, Executive, KernelMode, FALSE, pTime, NULL);
        switch (Status)
        {
        case STATUS_WAIT_0: // waitObjects[0] CompletionEvent
            if (Irp->IoStatus.Status == STATUS_SUCCESS)
            {
                BytesReceived = (LONG) Irp->IoStatus.Information;
            }
            else
            {
#ifdef _WIN32_LOGLINK 
                DbgPrint("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status));
#else
				WDRBD_INFO("RECV(%s) wsk(0x%p) multiWait err(0x%x:%s)\n", thread->comm, WskSocket, Irp->IoStatus.Status, GetSockErrorString(Irp->IoStatus.Status));
#endif
				if(Irp->IoStatus.Status)
                {
                    BytesReceived = -ECONNRESET;
                }
            }
            break;

        case STATUS_WAIT_1:
            BytesReceived = -EINTR;
            break;

        case STATUS_TIMEOUT:
            BytesReceived = -EAGAIN;
            break;

        default:
            BytesReceived = SOCKET_ERROR;
            break;
        }
    }
	else
	{
		if (Status == STATUS_SUCCESS)
		{
			BytesReceived = (LONG) Irp->IoStatus.Information;
#ifdef _WIN32_LOGLINK
			DbgPrint("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived);
#else
			WDRBD_INFO("(%s) Rx No pending and data(%d) is avail\n", current->comm, BytesReceived);
#endif
		}
		else
		{
#ifdef _WIN32_LOGLINK
			DbgPrint("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG!
#else
			WDRBD_TRACE("WskReceive Error Status=0x%x\n", Status); // EVENT_LOG!
#endif
		}
	}

	if (BytesReceived == -EINTR || BytesReceived == -EAGAIN)
	{
		// cancel irp in wsk subsystem
		IoCancelIrp(Irp);
		KeWaitForSingleObject(&CompletionEvent, Executive, KernelMode, FALSE, NULL);
		if (Irp->IoStatus.Information > 0)
		{
			//WDRBD_INFO("rx canceled but rx data(%d) avaliable.\n", Irp->IoStatus.Information);
			BytesReceived = Irp->IoStatus.Information;
		}
	}

	IoFreeIrp(Irp);
	FreeWskBuffer(&WskBuffer);

	return BytesReceived;
}
Exemple #26
0
static NTSTATUS
VifMonitor(
    IN  PXENVIF_THREAD  Self,
    IN  PVOID           _Context
    )
{
    PXENVIF_VIF_CONTEXT Context = _Context;
    PXENVIF_FRONTEND    Frontend = PdoGetFrontend(Context->Pdo);
    PKEVENT             Event[EVENT_COUNT];

    Trace("====>\n");

    Event[THREAD_EVENT] = ThreadGetEvent(Self);
    Event[MAC_EVENT] = MacGetEvent(FrontendGetMac(Frontend));

    for (;;) {
        NTSTATUS    status;

        Trace("waiting...\n");

        status = KeWaitForMultipleObjects(EVENT_COUNT,
                                          Event,
                                          WaitAny,
                                          Executive,
                                          KernelMode,
                                          FALSE,
                                          NULL,
                                          NULL);

        Trace("awake\n");

        if (status >= STATUS_WAIT_0 &&
            status < STATUS_WAIT_0 + EVENT_COUNT) {
            switch (status & STATUS_MASK) {
            case MAC_EVENT: {
                KeClearEvent(Event[MAC_EVENT]);

                Trace("MAC_EVENT\n");

                if (Context->Enabled) {
                    PVIF_CALLBACK   Callback = &Context->Callback;

                    Callback->Function(Callback->Argument,
                                       XENVIF_CALLBACK_MEDIA_STATE_CHANGE);
                }

                break;
            }
            case THREAD_EVENT:
                KeClearEvent(Event[THREAD_EVENT]);

                Trace("THREAD_EVENT\n");

                if (ThreadIsAlerted(Self))
                    goto done;

                KeSetEvent(&Context->MonitorEvent, IO_NO_INCREMENT, FALSE);
                break;

            default:
                ASSERT(FALSE);
                break;
            }
        }
    }

done:
    KeSetEvent(&Context->MonitorEvent, IO_NO_INCREMENT, FALSE);

    Trace("<====\n");

    return STATUS_SUCCESS;
}
Exemple #27
0
/*++
 * @name ExpWorkerThreadBalanceManager
 *
 *     The ExpWorkerThreadBalanceManager routine is the entrypoint for the
 *     worker thread balance set manager.
 *
 * @param Context
 *        Unused.
 *
 * @return None.
 *
 * @remarks The worker thread balance set manager listens every second, but can
 *          also be woken up by an event when a new thread is needed, or by the
 *          special shutdown event. This thread runs at priority 7.
 *
 *          This routine must run at IRQL == PASSIVE_LEVEL.
 *
 *--*/
VOID
NTAPI
ExpWorkerThreadBalanceManager(IN PVOID Context)
{
    KTIMER Timer;
    LARGE_INTEGER Timeout;
    NTSTATUS Status;
    PVOID WaitEvents[3];
    PAGED_CODE();
    UNREFERENCED_PARAMETER(Context);

    /* Raise our priority above all other worker threads */
    KeSetBasePriorityThread(KeGetCurrentThread(),
                            EX_CRITICAL_QUEUE_PRIORITY_INCREMENT + 1);

    /* Setup the timer */
    KeInitializeTimer(&Timer);
    Timeout.QuadPart = Int32x32To64(-1, 10000000);

    /* We'll wait on the periodic timer and also the emergency event */
    WaitEvents[0] = &Timer;
    WaitEvents[1] = &ExpThreadSetManagerEvent;
    WaitEvents[2] = &ExpThreadSetManagerShutdownEvent;

    /* Start wait loop */
    for (;;)
    {
        /* Wait for the timer */
        KeSetTimer(&Timer, Timeout, NULL);
        Status = KeWaitForMultipleObjects(3,
                                          WaitEvents,
                                          WaitAny,
                                          Executive,
                                          KernelMode,
                                          FALSE,
                                          NULL,
                                          NULL);
        if (Status == 0)
        {
            /* Our timer expired. Check for deadlocks */
            ExpDetectWorkerThreadDeadlock();
        }
        else if (Status == 1)
        {
            /* Someone notified us, verify if we should create a new thread */
            ExpCheckDynamicThreadCount();
        }
        else if (Status == 2)
        {
            /* We are shutting down. Cancel the timer */
            DPRINT1("System shutdown\n");
            KeCancelTimer(&Timer);

            /* Make sure we have a final thread */
            ASSERT(ExpLastWorkerThread);

            /* Wait for it */
            KeWaitForSingleObject(ExpLastWorkerThread,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);

            /* Dereference it and kill us */
            ObDereferenceObject(ExpLastWorkerThread);
            PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN);
        }
    }
}
Exemple #28
0
static
VOID
TestEventConcurrent(
    IN PKEVENT Event,
    IN EVENT_TYPE Type,
    IN KIRQL OriginalIrql,
    PSET_EVENT_FUNCTION SetEvent,
    KPRIORITY PriorityIncrement,
    LONG ExpectedState,
    BOOLEAN SatisfiesAll)
{
    NTSTATUS Status;
    THREAD_DATA Threads[5];
    const INT ThreadCount = sizeof Threads / sizeof Threads[0];
    KPRIORITY Priority;
    LARGE_INTEGER LongTimeout, ShortTimeout;
    INT i;
    KWAIT_BLOCK WaitBlock[MAXIMUM_WAIT_OBJECTS];
    PVOID ThreadObjects[MAXIMUM_WAIT_OBJECTS];
    LONG State;
    PKTHREAD Thread = KeGetCurrentThread();

    LongTimeout.QuadPart = -100 * MILLISECOND;
    ShortTimeout.QuadPart = -1 * MILLISECOND;

    KeInitializeEvent(Event, Type, FALSE);

    for (i = 0; i < ThreadCount; ++i)
    {
        Threads[i].Event = Event;
        Threads[i].Signal = FALSE;
        Status = PsCreateSystemThread(&Threads[i].Handle, GENERIC_ALL, NULL, NULL, NULL, WaitForEventThread, &Threads[i]);
        ok_eq_hex(Status, STATUS_SUCCESS);
        Status = ObReferenceObjectByHandle(Threads[i].Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&Threads[i].Thread, NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        ThreadObjects[i] = Threads[i].Thread;
        Priority = KeQueryPriorityThread(Threads[i].Thread);
        ok_eq_long(Priority, 8L);
        while (!Threads[i].Signal)
        {
            Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout);
            ok_eq_hex(Status, STATUS_SUCCESS);
        }
        CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects, i + 1);
    }

    /* the threads shouldn't wake up on their own */
    Status = KeDelayExecutionThread(KernelMode, FALSE, &ShortTimeout);
    ok_eq_hex(Status, STATUS_SUCCESS);

    for (i = 0; i < ThreadCount; ++i)
    {
        CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, ThreadObjects + i, ThreadCount - i);
        State = SetEvent(Event, PriorityIncrement + i, FALSE);

        ok_eq_long(State, 0L);
        CheckEvent(Event, Type, ExpectedState, FALSE, OriginalIrql, ThreadObjects + i + 1, SatisfiesAll ? 0 : ThreadCount - i - 1);
        Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, SatisfiesAll ? WaitAll : WaitAny, Executive, KernelMode, FALSE, &LongTimeout, WaitBlock);
        ok_eq_hex(Status, STATUS_WAIT_0 + i);
        if (SatisfiesAll)
        {
            for (; i < ThreadCount; ++i)
            {
                Priority = KeQueryPriorityThread(Threads[i].Thread);
                ok_eq_long(Priority, max(min(8L + PriorityIncrement, 15L), 8L));
            }
            break;
        }
        Priority = KeQueryPriorityThread(Threads[i].Thread);
        ok_eq_long(Priority, max(min(8L + PriorityIncrement + i, 15L), 8L));
        /* replace the thread with the current thread - which will never signal */
        if (!skip((Status & 0x3F) < ThreadCount, "Index out of bounds"))
            ThreadObjects[Status & 0x3F] = Thread;
        Status = KeWaitForMultipleObjects(ThreadCount, ThreadObjects, WaitAny, Executive, KernelMode, FALSE, &ShortTimeout, WaitBlock);
        ok_eq_hex(Status, STATUS_TIMEOUT);
    }

    for (i = 0; i < ThreadCount; ++i)
    {
        ObDereferenceObject(Threads[i].Thread);
        Status = ZwClose(Threads[i].Handle);
        ok_eq_hex(Status, STATUS_SUCCESS);
    }
}
VOID
PrimarySessionThreadProc (
	IN PPRIMARY_SESSION PrimarySession
	)
{
	BOOLEAN		primarySessionTerminate = FALSE;
	NTSTATUS	status;
	UINT16		slotIndex;
	PLIST_ENTRY	primarySessionRequestEntry;


	ASSERT( SESSION_SLOT_COUNT == 1 );
	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PrimarySessionThreadProc: Start PrimarySession = %p\n", PrimarySession) );
	
	PrimarySession_Reference( PrimarySession );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	
	InitializeListHead( &PrimarySession->Thread.OpenedFileQueue );
	KeInitializeSpinLock( &PrimarySession->Thread.OpenedFileQSpinLock );

	KeInitializeEvent( &PrimarySession->Thread.WorkCompletionEvent, NotificationEvent, FALSE );

	PrimarySession->SessionContext.SessionSlotCount = SESSION_SLOT_COUNT;

	for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

		PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
		PrimarySession->Thread.IdleSlotCount ++;
	}

	ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_INITIALIZING );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_START );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );

	KeSetEvent( &PrimarySession->ReadyEvent, IO_DISK_INCREMENT, FALSE );


	status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject,
						   (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
						   sizeof(NDFS_REQUEST_HEADER),
						   0,
						   NULL,
						   &PrimarySession->ReceiveOverlapped,
						   0,
						   NULL );

	if (!NT_SUCCESS(status)) {

		LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 );

		ASSERT( LFS_BUG );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
		primarySessionTerminate = TRUE;
	} 

	while (primarySessionTerminate == FALSE) {

		PKEVENT				events[3];
		LONG				eventCount;
		NTSTATUS			eventStatus;
		LARGE_INTEGER		timeOut;


		NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

		eventCount = 0;

		events[eventCount++] = &PrimarySession->RequestEvent;

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			events[eventCount++] = &PrimarySession->Thread.WorkCompletionEvent;

			if (FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN)) {
			
				if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount) {

					CloseOpenFiles( PrimarySession, TRUE );
				
					KeSetEvent( &PrimarySession->Thread.ShutdownPrimarySessionRequest->CompleteEvent, 
								IO_DISK_INCREMENT, 
								FALSE );

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT );
					ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );
				}
			}	 
		
			if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT)) {

				if (LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) {

					ASSERT( PrimarySession->Thread.IdleSlotCount != 0 );
					events[eventCount++] = &PrimarySession->ReceiveOverlapped.Request[0].CompletionEvent;
				}
			}

			ASSERT( eventCount <= THREAD_WAIT_OBJECTS );
		}

		timeOut.QuadPart = -5*NANO100_PER_SEC;
		eventStatus = KeWaitForMultipleObjects( eventCount, 
												events, 
												WaitAny, 
												Executive, 
												KernelMode,
												TRUE,
												&timeOut,
												NULL );

		if (!FlagOn(PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING)) {

			if (eventStatus == STATUS_TIMEOUT || eventStatus == 2) {
			
				if (PrimarySession->Thread.SessionState == SESSION_TREE_CONNECT) {
				
					ASSERT( PrimarySession->NetdiskPartition );
				
					if (!(PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_PRIMARY].VolumeState == VolumeMounted || 
						  PrimarySession->NetdiskPartition->NetdiskVolume[NETDISK_SECONDARY2PRIMARY].VolumeState == VolumeMounted)) {

						SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
									   ("Netdisk Volume is unmounted\n") );

						if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT))
							primarySessionTerminate = TRUE;
		
						continue;
					}
				}
			}
		}

		if (eventStatus == STATUS_TIMEOUT) {

			continue;
		}

		if (!NT_SUCCESS(eventStatus) || eventStatus >= eventCount) {

			NDAS_ASSERT( FALSE );
			SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
			primarySessionTerminate = TRUE;
			continue;
		}

		if (eventStatus == 0) {

			KeClearEvent( events[eventStatus] );

			while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																			 &PrimarySession->RequestQSpinLock)) {

				PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
				primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
														   PRIMARY_SESSION_REQUEST,
														   ListEntry );

				if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT ||
					primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE) {

					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, 
								   ((primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT) ?
								   ("PRIMARY_SESSION_REQ_DISCONNECT: DisconnectFromSecondary\n") :
									("PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE: DisconnectFromSecondary\n")) );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DISCONNECT_AND_TERMINATE)
						primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_DOWN) {
					
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
					primarySessionTerminate = TRUE;

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );
				
				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_SHUTDOWN) {

					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySessionThreadProc: PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN\n") );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN );

					ASSERT (primarySessionRequest->Synchronous == TRUE);

					PrimarySession->Thread.ShutdownPrimarySessionRequest = primarySessionRequest;

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_STOPPING) {

					SetFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );
					
					if (PrimarySession->IsLocalAddress == FALSE) {

#if __NDAS_FS_PRIMARY_DISMOUNT__
						CloseOpenFiles( PrimarySession, FALSE );
#endif
					}

					ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );

					if (primarySessionRequest->Synchronous == TRUE) {

						primarySessionRequest->ExecuteStatus = STATUS_SUCCESS;
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					
					} else {

						DereferencePrimarySessionRequest( primarySessionRequest );
					}

					ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

				} else if (primarySessionRequest->RequestType == PRIMARY_SESSION_REQ_CANCEL_STOPPING) {

					ClearFlag( PrimarySession->Flags, PRIMARY_SESSION_FLAG_STOPPING );

					if (primarySessionRequest->Synchronous == TRUE)
						KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
					else
						DereferencePrimarySessionRequest( primarySessionRequest );

				} else {

					ASSERT( LFS_BUG );
					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
				}
			}

			continue;
		
		} else if (eventStatus == 1) {

			KeClearEvent( events[eventStatus] );

			while (TRUE) {
	
				for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex ++) {

					if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
						break;
				}

				if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
					break;
			
				PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
				PrimarySession->Thread.IdleSlotCount ++;

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					PNDFS_REPLY_HEADER		ndfsReplyHeader;

					ndfsReplyHeader = (PNDFS_REPLY_HEADER)PrimarySession->Thread.SessionSlot[slotIndex].ReplyMessageBuffer;
										
					PrimarySession->Thread.SessionSlot[slotIndex].Status
						= SendNdfsWinxpMessage( PrimarySession,
												ndfsReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].NdfsWinxpReplyHeader,
												PrimarySession->Thread.SessionSlot[slotIndex].ReplyDataSize,
												slotIndex );

				}
	
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}
		
				if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

					ExFreePool(PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool);	
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
					PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
				}

				if (!(PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS || 
					  PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_PENDING)) {

					SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
					
					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );

						PrimarySession->NetdiskPartition = NULL;
					}
					
					primarySessionTerminate = TRUE;
					break;		
				 }
				
				if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

					if (PrimarySession->NetdiskPartition) {

						NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager, 
															   PrimarySession,
															   PrimarySession->NetdiskPartition, 
															   PrimarySession->IsLocalAddress );
	
						PrimarySession->NetdiskPartition = NULL;
					}

					primarySessionTerminate = TRUE;
					break;		
				}

				if (PrimarySession->Thread.SessionSlot[slotIndex].Status == STATUS_SUCCESS) {

					if (!LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) {

						status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject,
											   (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
											   sizeof(NDFS_REQUEST_HEADER),
											   0,
											   NULL,
											   &PrimarySession->ReceiveOverlapped,
											   0,
											   NULL );

						if (!NT_SUCCESS(status)) {

							ASSERT( LFS_BUG );

							LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 );

							SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
							primarySessionTerminate = TRUE;
							break;
						}
					}
				}
			}		
		
			continue;
		
		} else {

			NDAS_ASSERT( eventStatus == 2 );  // Receive Event

			ASSERT( !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN_WAIT) &&
				    !FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_SHUTDOWN) );

			LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 );

			if (PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Status != STATUS_SUCCESS ||
				PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Information != sizeof(NDFS_REQUEST_HEADER)) {

				SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE,
							   ("DispatchRequest: Disconnected, PrimarySession = Data received:%d\n",
							   PrimarySession->ReceiveOverlapped.Request[0].IoStatusBlock.Information) );

				SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
				primarySessionTerminate = TRUE;
				
				continue;		
			}

#if 0
			if (PrimarySession->NetdiskPartition) {

				PENABLED_NETDISK EnabledNetdisk = PrimarySession->NetdiskPartition->EnabledNetdisk;
				
				ASSERT( EnabledNetdisk );

				if (NetdiskManager_IsStoppedNetdisk(GlobalLfs.NetdiskManager, EnabledNetdisk)) {
				    
					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_ERROR,
								   ("PrimarySessionThread: %p Netdisk is stopped\n", PrimarySession) );

					SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_ERROR, ("DispatchWinXpRequest: Netdisk is stopped.\n") );

					if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) { 
					
						// no other way to notify secondary about unmount without break backward compatability.
						
						SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("IsStoppedNetdisk: DisconnectFromSecondary\n") );
						DisconnectFromSecondary( PrimarySession );
						ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
					}

					primarySessionTerminate = TRUE;
					continue;
				}
			} 

#endif

			status = DispatchRequest( PrimarySession );

			if (!(status == STATUS_SUCCESS || status == STATUS_PENDING)) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (PrimarySession->Thread.SessionState == SESSION_CLOSED) {

				primarySessionTerminate = TRUE;
				continue;		
			}

			if (status == STATUS_SUCCESS) {

				if (!LpxTdiV2IsRequestPending(&PrimarySession->ReceiveOverlapped, 0)) {

					status = LpxTdiV2Recv( PrimarySession->ConnectionFileObject,
										   (PUCHAR)&PrimarySession->Thread.NdfsRequestHeader,
										   sizeof(NDFS_REQUEST_HEADER),
										   0,
										   NULL,
										   &PrimarySession->ReceiveOverlapped,
										   0,
										   NULL );

					if (!NT_SUCCESS(status)) {

						LpxTdiV2CompleteRequest( &PrimarySession->ReceiveOverlapped, 0 );

						SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_ERROR );
						primarySessionTerminate = TRUE;
					}
				}
			}
			
			continue;
		}
	}

	ExAcquireFastMutexUnsafe( &PrimarySession->FastMutex );
	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_STOPED );
	ExReleaseFastMutexUnsafe( &PrimarySession->FastMutex );

	while (TRUE) {

		LARGE_INTEGER	timeOut;
		NTSTATUS		eventStatus;


		if (PrimarySession->Thread.IdleSlotCount == PrimarySession->SessionContext.SessionSlotCount)
			break;

		timeOut.QuadPart = -10*NANO100_PER_SEC;
		eventStatus = KeWaitForSingleObject( &PrimarySession->Thread.WorkCompletionEvent,
											 Executive,
											 KernelMode,
											 FALSE,
											 &timeOut );

		KeClearEvent( &PrimarySession->Thread.WorkCompletionEvent );

		if (eventStatus == STATUS_TIMEOUT) {

			ASSERT( LFS_UNEXPECTED );
			continue;
		}

		while (TRUE) {
	
			for (slotIndex = 0; slotIndex < PrimarySession->SessionContext.SessionSlotCount; slotIndex++) {

				if (PrimarySession->Thread.SessionSlot[slotIndex].State == SLOT_FINISH)
					break;
			}

			if (slotIndex == PrimarySession->SessionContext.SessionSlotCount)
				break;

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_TRACE, ("PrimarySessionThreadProc: eventStatus = %d\n", eventStatus) );
			
			PrimarySession->Thread.SessionSlot[slotIndex].State = SLOT_WAIT;
			PrimarySession->Thread.IdleSlotCount++;

			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpRequestMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		
			if (PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool) {

				ExFreePool( PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool );	
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePool = NULL;
				PrimarySession->Thread.SessionSlot[slotIndex].ExtendWinxpReplyMessagePoolLength = 0;
			}
		}		
	}
	
	if (!FlagOn(PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED)) {

		SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO, ("PsTerminateSystemThread: DisconnectFromSecondary\n") );
		DisconnectFromSecondary( PrimarySession );
		ClearFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_CONNECTED );
		SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_DISCONNECTED );
	}

	CloseOpenFiles( PrimarySession, TRUE );

	while (primarySessionRequestEntry = ExInterlockedRemoveHeadList( &PrimarySession->RequestQueue,
																	 &PrimarySession->RequestQSpinLock)) {

		PPRIMARY_SESSION_REQUEST	primarySessionRequest;
			
		primarySessionRequest = CONTAINING_RECORD( primarySessionRequestEntry,
												   PRIMARY_SESSION_REQUEST,
												   ListEntry );

		if (primarySessionRequest->Synchronous == TRUE)
			KeSetEvent( &primarySessionRequest->CompleteEvent, IO_DISK_INCREMENT, FALSE );
		else
			DereferencePrimarySessionRequest( primarySessionRequest );
	}

	if (PrimarySession->NetdiskPartition) {

		NetdiskManager_ReturnPrimaryPartition( GlobalLfs.NetdiskManager,
											   PrimarySession,
											   PrimarySession->NetdiskPartition, 
											   PrimarySession->IsLocalAddress );

		PrimarySession->NetdiskPartition = NULL;
	}

	SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				   ("PrimarySessionThreadProc: PsTerminateSystemThread PrimarySession = %p\n", 
				    PrimarySession) );

	SetFlag( PrimarySession->Thread.Flags, PRIMARY_SESSION_THREAD_FLAG_TERMINATED );

	PrimarySession_Dereference ( PrimarySession );

	NDAS_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	PsTerminateSystemThread( STATUS_SUCCESS );
}
Exemple #30
0
VOID
ExpWorkerThreadBalanceManager (
    IN PVOID StartContext
    )

/*++

Routine Description:

    This function is the startup code for the worker thread manager thread.
    The worker thread manager thread is created during system initialization
    and begins execution in this function.

    This thread is responsible for detecting and breaking circular deadlocks
    in the system worker thread queues.  It will also create and destroy
    additional worker threads as needed based on loading.

Arguments:

    Context - Supplies a pointer to an arbitrary data structure (NULL).

Return Value:

    None.

--*/
{
    KTIMER PeriodTimer;
    LARGE_INTEGER DueTime;
    PVOID WaitObjects[MaximumBalanceObject];
    NTSTATUS Status;

    PAGED_CODE();

    UNREFERENCED_PARAMETER (StartContext);

    //
    // Raise the thread priority to just higher than the priority of the
    // critical work queue.
    //

    KeSetBasePriorityThread (KeGetCurrentThread(),
                             CRITICAL_WORK_QUEUE_PRIORITY + 1);

    //
    // Initialize the periodic timer and set the manager period.
    //

    KeInitializeTimer (&PeriodTimer);
    DueTime.QuadPart = - THREAD_SET_INTERVAL;

    //
    // Initialize the wait object array.
    //

    WaitObjects[TimerExpiration] = (PVOID)&PeriodTimer;
    WaitObjects[ThreadSetManagerEvent] = (PVOID)&ExpThreadSetManagerEvent;
    WaitObjects[ShutdownEvent] = (PVOID)&ExpThreadSetManagerShutdownEvent;

    //
    // Loop forever processing events.
    //

    while (TRUE) {

        //
        // Set the timer to expire at the next periodic interval.
        //

        KeSetTimer (&PeriodTimer, DueTime, NULL);

        //
        // Wake up when the timer expires or the set manager event is
        // signaled.
        //

        Status = KeWaitForMultipleObjects (MaximumBalanceObject,
                                           WaitObjects,
                                           WaitAny,
                                           Executive,
                                           KernelMode,
                                           FALSE,
                                           NULL,
                                           NULL);

        switch (Status) {

            case TimerExpiration:

                //
                // Periodic timer expiration - go see if any work queues
                // are deadlocked.
                //

                ExpDetectWorkerThreadDeadlock ();
                break;

            case ThreadSetManagerEvent:

                //
                // Someone has asked us to check some metrics to determine
                // whether we should create another worker thread.
                //

                ExpCheckDynamicThreadCount ();
                break;

            case ShutdownEvent:

                //
                // Time to exit...
                //

                KeCancelTimer (&PeriodTimer);

                ASSERT (ExpLastWorkerThread);

                //
                // Wait for the last worker thread to terminate
                //

                KeWaitForSingleObject (ExpLastWorkerThread,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL);

                ObDereferenceObject (ExpLastWorkerThread);

                PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN);

                break;
        }

        //
        // Special debugger support.
        //
        // This checks if special debugging routines need to be run on the
        // behalf of the debugger.
        //

        if (ExpDebuggerWork == 1) {

             ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL);
             ExpDebuggerWork = 2;
             ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue);
        }
    }
}