📄 link.c
字号:
/******************************************************************//* *//* Winpooch : Windows Watchdog *//* Copyright (C) 2004-2006 Benoit Blanchon *//* *//* This program is free software; you can redistribute it *//* and/or modify it under the terms of the GNU General Public *//* License as published by the Free Software Foundation; either *//* version 2 of the License, or (at your option) any later *//* version. *//* *//* This program is distributed in the hope that it will be *//* useful, but WITHOUT ANY WARRANTY; without even the implied *//* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR *//* PURPOSE. See the GNU General Public License for more *//* details. *//* *//* You should have received a copy of the GNU General Public *//* License along with this program; if not, write to the Free *//* Software Foundation, Inc., *//* 675 Mass Ave, Cambridge, MA 02139, USA. *//* *//******************************************************************//******************************************************************//* Build configuration *//******************************************************************/#define TRACE_LEVEL 2#define SLOT_COUNT 3#define ENABLE_TIMEOUT 1#define MAX_RESPONSE_SIZE 16 /******************************************************************//* Includes *//******************************************************************/// module's interface#include "Link.h"// project's headers#include "DrvInterface.h"#include "DrvStatus.h"#include "Trace.h"/******************************************************************//* Internal constants *//******************************************************************/#define REQUEST_TIMEOUT 60 //seconds#define RESPONSE_TIMEOUT 180 //seconds/******************************************************************//* Internal data types *//******************************************************************/typedef struct { int iSlot ;} REQUEST_HEADER ;typedef struct { int iSlot ;} RESPONSE_HEADER ;typedef struct { BOOL bSlotInUse ; KEVENT evResponseReceived ; BYTE aResponseBuffer[MAX_RESPONSE_SIZE] ; UINT nResponseSize ;} SLOT ;typedef struct { BOOL bEnabled ; KEVENT evAppWaiting ; KSEMAPHORE semFreeSlots ; KMUTEX mutReserveSlot ; PIRP pPendingIrp ;#if ENABLE_TIMEOUT LARGE_INTEGER liRequestTimeOut ; LARGE_INTEGER liResponseTimeOut ;#endif SLOT aSlots[SLOT_COUNT] ;} INTERNAL_DATA ;static INTERNAL_DATA g_data ;/******************************************************************//* Internal functions *//******************************************************************/VOID DDKAPI _Link_CancelRoutine (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) ;/******************************************************************//* Exported function *//******************************************************************/BOOL Link_IsConnected () { return g_data.bEnabled ;}/******************************************************************//* Internal function *//******************************************************************/NTSTATUS _Link_AcquireSlot (UINT * piSlot){ UINT iSlot; NTSTATUS nStatus ; // // Waiting for a free slot to be avail // { TRACE_INFO (TEXT("Waiting for a free slot...\n")) ; nStatus = KeWaitForSingleObject (&g_data.semFreeSlots, Executive, KernelMode, TRUE, NULL) ; if( nStatus != STATUS_SUCCESS ) { TRACE_BREAK (TEXT("Error while waiting for semaphore\n")) ; return nStatus ; } TRACE_INFO (TEXT("A free slot should be available\n")) ; } // // Reserve a slot number // { TRACE_INFO (TEXT("Looking for the free slot...\n")) ; KeWaitForMutexObject (&g_data.mutReserveSlot, Executive, KernelMode, TRUE, NULL) ; // look for slot number for( iSlot=0 ; iSlot<SLOT_COUNT ; iSlot++ ) if( ! g_data.aSlots[iSlot].bSlotInUse ) break ; // no slot found -> error if( iSlot >= SLOT_COUNT ) { TRACE_BREAK (TEXT("No free slot found")) ; KeReleaseMutex (&g_data.mutReserveSlot, FALSE) ; return STATUS_UNSUCCESSFUL ; } g_data.aSlots[iSlot].bSlotInUse = TRUE ; KeReleaseMutex (&g_data.mutReserveSlot, FALSE) ; TRACE_INFO (TEXT("Acquired slot %d\n"), iSlot) ; } *piSlot = iSlot ; return STATUS_SUCCESS ;} /******************************************************************//* Internal function *//******************************************************************/NTSTATUS _Link_ReleaseSlot (UINT iSlot){ ASSERT (iSlot<=SLOT_COUNT) ; ASSERT (g_data.aSlots[iSlot].bSlotInUse) ; // // Release slot // { TRACE_INFO (TEXT("Releasing slot %u...\n"), iSlot) ; KeWaitForMutexObject (&g_data.mutReserveSlot, Executive, KernelMode, TRUE, NULL) ; g_data.aSlots[iSlot].bSlotInUse = FALSE ; KeReleaseMutex (&g_data.mutReserveSlot, FALSE) ; TRACE_INFO (TEXT("Slot %u released\n"), iSlot) ; } // // Alert pending threads // KeReleaseSemaphore (&g_data.semFreeSlots, 0, 1, FALSE) ; return STATUS_SUCCESS ;}/******************************************************************//* Exported function *//******************************************************************/NTSTATUS _Link_QueryServer (UINT iSlot, LPVOID pRequestData, DWORD nRequestSize, LPVOID pResponseData, LPDWORD pnResponseSize, DWORD nMaxResponseSize) { NTSTATUS nStatus ; ASSERT (iSlot<=SLOT_COUNT) ; ASSERT (pRequestData!=NULL) ; ASSERT (nRequestSize>0) ; ASSERT (*(DWORD*)pRequestData) ; // application not connected => do nothing if( ! g_data.bEnabled ) { if( pnResponseSize!=NULL ) *pnResponseSize = 0 ; return STATUS_PORT_DISCONNECTED ; } TRACE_INFO (TEXT("Slot%d: REQUEST addr=0x%08X, pid=%d, code=%u\n"), iSlot, IoGetCurrentProcess(), PsGetCurrentProcessId(), *(DWORD*)pRequestData) ; if( *(DWORD*)pRequestData == 0 ) { TRACE_BREAK (TEXT("Request code is NULL\n")) ; } // // Wait for application to be ready to receive request // { TRACE_INFO (TEXT("Slot%d: Waiting for app to be ready...\n"), iSlot) ; // wait for app to be ready nStatus = KeWaitForSingleObject (&g_data.evAppWaiting, UserRequest, UserMode, TRUE,#if ENABLE_TIMEOUT &g_data.liRequestTimeOut) ;#else NULL) ;#endif if( nStatus!=STATUS_SUCCESS ) { DrvStatus_Trace (); TRACE_BREAK (TEXT("Time-out while waiting for app to be ready\n")) ; g_data.bEnabled = FALSE ; return STATUS_PORT_UNREACHABLE ; } TRACE_INFO (TEXT("Slot%d: Application is ready\n"), iSlot) ; } // // Send request // { PIRP pIrp ; PIO_STACK_LOCATION pStackLoc ; KIRQL nIrql ; REQUEST_HEADER header ; BYTE *pWritePtr ; TRACE_INFO (TEXT("Slot%d: Acquiring pending IRP.\n"), iSlot) ; IoAcquireCancelSpinLock (&nIrql) ; pIrp = g_data.pPendingIrp ; g_data.pPendingIrp = NULL ; if( pIrp ) IoSetCancelRoutine (pIrp, NULL) ; IoReleaseCancelSpinLock(nIrql) ; // NULL means another thread called _Link_QueryServer at the same time // or that the IRP has been cancelled if( ! pIrp ) { TRACE_WARNING (TEXT("Slot%d: Pending IRP has been cancelled.\n"), iSlot) ; g_data.bEnabled = FALSE ; return STATUS_PORT_DISCONNECTED ; } TRACE_INFO (TEXT("Slot%d: Pending IRP 0x%08X acquired.\n"), iSlot, pIrp) ; TRACE_INFO (TEXT("Slot%d: Sending request to app...\n"), iSlot) ; // write request data pStackLoc = IoGetCurrentIrpStackLocation (pIrp) ; TRACE_INFO (TEXT("Slot%d: Link buffer size = %u\n"), iSlot, pStackLoc->Parameters.DeviceIoControl.OutputBufferLength) ; TRACE_INFO (TEXT("Slot%d: Required size = %u\n"), iSlot, nRequestSize+sizeof(header)) ; ASSERT (pStackLoc->Parameters.DeviceIoControl.OutputBufferLength>=nRequestSize+sizeof(header)) ; // get buffer address pWritePtr = pIrp->AssociatedIrp.SystemBuffer ; // write header header.iSlot = iSlot ; RtlCopyMemory (pWritePtr, &header, sizeof(header)) ; pWritePtr += sizeof(header) ; // write request data RtlCopyMemory (pWritePtr, pRequestData, nRequestSize) ; // complete the request pIrp->IoStatus.Status = STATUS_SUCCESS ; pIrp->IoStatus.Information = nRequestSize+sizeof(header) ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; TRACE_INFO (TEXT("Slot%d: Request sent to app\n"), iSlot) ; } // // Wait response or Ack from application // { if( nMaxResponseSize>0 && pResponseData!=NULL ) TRACE_INFO (TEXT("Slot%d: Waiting for response...\n"), iSlot) ; else TRACE_INFO (TEXT("Slot%d: Waiting for ack...\n"), iSlot) ; // wait for response#if ENABLE_TIMEOUT nStatus = KeWaitForSingleObject (&g_data.aSlots[iSlot].evResponseReceived, UserRequest, UserMode, TRUE, &g_data.liResponseTimeOut) ;#else nStatus = KeWaitForSingleObject (&g_data.aSlots[iSlot].evResponseReceived,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -