📄 link.c
字号:
UserRequest, UserMode, TRUE, NULL) ;#endif if( nStatus!=STATUS_SUCCESS ) { DrvStatus_Trace () ; TRACE_BREAK (TEXT("Slot%d: Time-out while waiting for app response\n"), iSlot) ; g_data.bEnabled = FALSE ; return STATUS_REQUEST_ABORTED ; } if( g_data.aSlots[iSlot].nResponseSize > nMaxResponseSize ) { TRACE_WARNING (TEXT("Slot%u: Response size (%u bytes) bigger than expected (%u bytes)\n"), iSlot, g_data.aSlots[iSlot].nResponseSize, nMaxResponseSize) ; g_data.aSlots[iSlot].nResponseSize = nMaxResponseSize ; } // read response data if( pResponseData!=NULL ) RtlCopyMemory (pResponseData, g_data.aSlots[iSlot].aResponseBuffer, g_data.aSlots[iSlot].nResponseSize) ; // set response size if( pnResponseSize ) *pnResponseSize = g_data.aSlots[iSlot].nResponseSize; if( g_data.aSlots[iSlot].nResponseSize>0 ) TRACE_INFO (TEXT("Slot%d: Response received (size=%u)\n"), iSlot, *pnResponseSize) ; else TRACE_INFO (TEXT("Slot%d: Ack received\n"), iSlot) ; } TRACE_INFO (TEXT("Slot%d: REQUEST FINISHED\n"), iSlot) ; return STATUS_SUCCESS ;}/******************************************************************//* Exported function *//******************************************************************/NTSTATUS Link_QueryServer (LPVOID pRequestData, DWORD nRequestSize, LPVOID pResponseData, LPDWORD pnResponseSize, DWORD nMaxResponseSize) { NTSTATUS nStatus ; UINT iSlot ; TRACE ; nStatus = _Link_AcquireSlot (&iSlot) ; if( nStatus == STATUS_SUCCESS ) { nStatus = _Link_QueryServer (iSlot, pRequestData, nRequestSize, pResponseData, pnResponseSize, nMaxResponseSize) ; _Link_ReleaseSlot (iSlot) ; } return nStatus ;}/******************************************************************//* Exported function *//******************************************************************/NTSTATUS Link_CatchIrpApp2Drv (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { NTSTATUS nStatus = STATUS_SUCCESS ; PIO_STACK_LOCATION pStackLoc ; TRACE_INFO (TEXT("Message received from application\n")) ; if( ! g_data.bEnabled ) { TRACE_ERROR (TEXT("Rejecting ioctl from app because app-link not initialized\n")) ; nStatus = STATUS_PORT_CONNECTION_REFUSED ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ; } pStackLoc = IoGetCurrentIrpStackLocation (pIrp) ; // is there a message from app ? if( pIrp->AssociatedIrp.SystemBuffer==NULL || pStackLoc->Parameters.DeviceIoControl.InputBufferLength<sizeof(RESPONSE_HEADER) ) { TRACE_ERROR (TEXT("Empty response from application\n")) ; nStatus = STATUS_UNSUCCESSFUL ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ; } { BYTE *pReadPtr = pIrp->AssociatedIrp.SystemBuffer ; UINT nSize = pStackLoc->Parameters.DeviceIoControl.InputBufferLength ; UINT iSlot ; RESPONSE_HEADER * pHeader = (VOID*)pReadPtr ; pReadPtr += sizeof(RESPONSE_HEADER) ; nSize -= sizeof(RESPONSE_HEADER) ; iSlot = pHeader->iSlot ; TRACE_INFO (TEXT("Message belongs to slot %u\n"), iSlot) ; // check slot number if( iSlot>=SLOT_COUNT ) { TRACE_ERROR (TEXT("Invalid slot number %u\n"), iSlot) ; nStatus = STATUS_UNSUCCESSFUL ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ; } if( ! g_data.aSlots[iSlot].bSlotInUse ) { TRACE_ERROR (TEXT("Slot%u: neither response nor ask was expected\n"), iSlot) ; nStatus = STATUS_UNSUCCESSFUL ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ; } if( nSize > MAX_RESPONSE_SIZE ) { TRACE_WARNING (TEXT("Slot%u: Response size (%u) bigger than MAX_RESPONSE_SIZE (%u)\n"), iSlot, nSize, MAX_RESPONSE_SIZE) ; nSize = MAX_RESPONSE_SIZE ; } // read response data RtlCopyMemory (g_data.aSlots[iSlot].aResponseBuffer, pReadPtr, nSize) ; g_data.aSlots[iSlot].nResponseSize = nSize ; // tell the other thread that the response has been received KeSetEvent (&g_data.aSlots[iSlot].evResponseReceived, 0, FALSE) ; } nStatus = STATUS_SUCCESS ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = pStackLoc->Parameters.DeviceIoControl.InputBufferLength ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ;} /******************************************************************//* Exported function *//******************************************************************/NTSTATUS Link_CatchIrpDrv2App (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { NTSTATUS nStatus = STATUS_SUCCESS ; KIRQL nIrql ; PIO_STACK_LOCATION pStackLoc ; pStackLoc = IoGetCurrentIrpStackLocation (pIrp) ; // app doesn't want to receive a message ? if( pStackLoc->Parameters.DeviceIoControl.OutputBufferLength==0 ) { TRACE_WARNING (TEXT("No output buffer provided\n")) ; nStatus = STATUS_SUCCESS ; pIrp->IoStatus.Status = nStatus ; pIrp->IoStatus.Information = 0 ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; return nStatus ; } TRACE_INFO (TEXT("Registering pending IRP 0x%08X\n"), pIrp) ; IoAcquireCancelSpinLock (&nIrql) ; if( pIrp->Cancel ) { nStatus = STATUS_CANCELLED ; } else if( g_data.pPendingIrp ) { nStatus = STATUS_DEVICE_BUSY ; TRACE_ERROR (TEXT("Rejecting an IRP because another one is pending\n")) ; } else { IoMarkIrpPending (pIrp) ; IoSetCancelRoutine (pIrp, _Link_CancelRoutine) ; g_data.pPendingIrp = pIrp ; nStatus = STATUS_PENDING ; } IoReleaseCancelSpinLock(nIrql) ; if( nStatus==STATUS_PENDING ) { TRACE_INFO (TEXT("IRP 0x%08X registered, notify other threads\n"), pIrp) ; KeSetEvent (&g_data.evAppWaiting, 0, FALSE) ; } else { TRACE_ERROR (TEXT("Failed to register pending IRP 0x%08X (status=0x%08X)\n"), pIrp, nStatus) ; pIrp->IoStatus.Status = nStatus; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; } return nStatus ;}/******************************************************************//* Exported function *//******************************************************************/NTSTATUS Link_Init () { UINT iSlot ; TRACE ;#if ENABLE_TIMEOUT g_data.liRequestTimeOut.QuadPart = - REQUEST_TIMEOUT *1000*1000*10 ; g_data.liResponseTimeOut.QuadPart = - RESPONSE_TIMEOUT *1000*1000*10 ;#endif KeInitializeMutex (&g_data.mutReserveSlot, 0) ; KeInitializeSemaphore (&g_data.semFreeSlots, SLOT_COUNT, SLOT_COUNT) ; KeInitializeEvent (&g_data.evAppWaiting, SynchronizationEvent, FALSE) ; for( iSlot=0 ; iSlot<SLOT_COUNT ; iSlot++ ) { g_data.aSlots[iSlot].bSlotInUse = FALSE ; KeInitializeEvent (&g_data.aSlots[iSlot].evResponseReceived, SynchronizationEvent, FALSE) ; } g_data.pPendingIrp = NULL ; g_data.bEnabled = TRUE ; TRACE_INFO (TEXT("App-link connected\n")) ; return STATUS_SUCCESS ;}/******************************************************************//* Exported function *//******************************************************************/NTSTATUS Link_Uninit () { PIRP pIrp ; KIRQL nIrql ; TRACE ; g_data.bEnabled = FALSE ; TRACE_INFO (TEXT("App-link disconnected\n")) ; IoAcquireCancelSpinLock (&nIrql) ; pIrp = g_data.pPendingIrp ; g_data.pPendingIrp = NULL ; if( pIrp ) IoSetCancelRoutine (pIrp, NULL) ; IoReleaseCancelSpinLock(nIrql) ; // cancel pending IRP if( pIrp ) { TRACE_INFO (TEXT("Cancelling pending IRP\n")) ; pIrp->IoStatus.Status = STATUS_CANCELLED ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; } return STATUS_SUCCESS ;}/******************************************************************//* Internal function *//******************************************************************/VOID DDKAPI _Link_CancelRoutine (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { TRACE_INFO (TEXT("Cancelling IRP 0x%08X\n"), pIrp) ; g_data.pPendingIrp = NULL ; IoReleaseCancelSpinLock (pIrp->CancelIrql); pIrp->IoStatus.Status = STATUS_CANCELLED ; IoCompleteRequest (pIrp, IO_NO_INCREMENT) ; KeSetEvent (&g_data.evAppWaiting, 0, FALSE) ; TRACE_INFO (TEXT("IRP 0x%08X cancelled\n"), pIrp) ;}/******************************************************************//* Internal function *//******************************************************************/BOOL Link_IsRequesting () { return KeReadStateSemaphore(&g_data.semFreeSlots)!=SLOT_COUNT ;}/******************************************************************//* Internal function *//******************************************************************/BOOL Link_IsAppWaiting () { return 0!=KeReadStateEvent(&g_data.evAppWaiting) ;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -