[Wine-devel] ntoskrnl.exe: Improve IofCompleteRequest and IofCallDriver

Alexander Morozov =?iso-8859-1?q?amorozov_=CE=C1_etersoft=2Eru?=
Чт Июл 24 13:16:37 MSD 2008


В результате написания тестов оказалось, что реализованное в eterhack поведение достаточно плохо соответствует поведению Windows. Изменил IofCompleteRequest и IofCallDriver, чтобы они соответствовали тестам.
----------- следующая часть -----------
From 37c5d66d9d83ba5ef96422d95809e83d9e58c641 Mon Sep 17 00:00:00 2001
From: Alexander Morozov <amorozov на etersoft.ru>
Date: Wed, 23 Jul 2008 13:32:01 +0400
Subject: [PATCH] ntoskrnl.exe: Improve IofCompleteRequest and IofCallDriver

---
 dlls/ntoskrnl.exe/ntoskrnl.c |   74 ++++++++++++++++++++---------------------
 1 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
index 0dc8be3..0d3e360 100644
--- a/dlls/ntoskrnl.exe/ntoskrnl.c
+++ b/dlls/ntoskrnl.exe/ntoskrnl.c
@@ -621,8 +621,6 @@ NTSTATUS WINAPI IofCallDriver( DEVICE_OBJECT *device, IRP *irp )
     irpsp = --irp->Tail.Overlay.s.u.CurrentStackLocation;
     dispatch = device->DriverObject->MajorFunction[irpsp->MajorFunction];
     status = dispatch( device, irp );
-    ++irp->CurrentLocation;
-    ++irp->Tail.Overlay.s.u.CurrentStackLocation;
 
     return status;
 }
@@ -640,53 +638,53 @@ void WINAPI IofCompleteRequest( IRP *irp, UCHAR priority_boost )
 {
     IO_STACK_LOCATION *irpsp;
     PIO_COMPLETION_ROUTINE routine;
+    IO_STATUS_BLOCK *iosb;
+    struct IrpInstance *instance;
+    NTSTATUS status, stat;
+    int call_flag = 0;
 
     TRACE( "%p %u\n", irp, priority_boost );
 
-    irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
-    routine = irpsp->CompletionRoutine;
-    /* FIXME: check other stack locations */
-    if (routine)
+    iosb = irp->UserIosb;
+    status = irp->IoStatus.u.Status;
+    while (irp->CurrentLocation <= irp->StackCount)
     {
-        NTSTATUS status;
-        int call_flag = 0;
-
-        switch (irp->IoStatus.u.Status)
+        irpsp = irp->Tail.Overlay.s.u.CurrentStackLocation;
+        routine = irpsp->CompletionRoutine;
+        call_flag = 0;
+        /* FIXME: add SL_INVOKE_ON_CANCEL support */
+        if (routine)
         {
-        case STATUS_SUCCESS:
-            if (irpsp->Control & SL_INVOKE_ON_SUCCESS)
+            if ((irpsp->Control & SL_INVOKE_ON_SUCCESS) && STATUS_SUCCESS == status)
                 call_flag = 1;
-            break;
-        case STATUS_CANCELLED:
-            if (irpsp->Control & SL_INVOKE_ON_CANCEL)
-                call_flag = 1;
-            break;
-        default:
-            if (irpsp->Control & SL_INVOKE_ON_ERROR)
+            if ((irpsp->Control & SL_INVOKE_ON_ERROR) && STATUS_SUCCESS != status)
                 call_flag = 1;
         }
-
+        ++irp->CurrentLocation;
+        ++irp->Tail.Overlay.s.u.CurrentStackLocation;
         if (call_flag)
         {
-            TRACE( "calling %p( %p, %p, %p )\n", routine, irpsp->DeviceObject,
-                   irp, irpsp->Context );
-            status = routine( irpsp->DeviceObject, irp, irpsp->Context );
+            TRACE( "calling %p( %p, %p, %p )\n", routine,
+                    irpsp->DeviceObject, irp, irpsp->Context );
+            stat = routine( irpsp->DeviceObject, irp, irpsp->Context );
             TRACE( "CompletionRoutine returned %x\n", status );
-            if (status != STATUS_MORE_PROCESSING_REQUIRED)
-            {
-                struct IrpInstance *instance;
-
-                LIST_FOR_EACH_ENTRY( instance, &Irps, struct IrpInstance, entry )
-                {
-                    if (instance->irp == irp)
-                    {
-                        list_remove( &instance->entry );
-                        HeapFree( GetProcessHeap(), 0, instance );
-                        IoFreeIrp( irp );
-                        break;
-                    }
-                }
-            }
+            if (STATUS_MORE_PROCESSING_REQUIRED == stat)
+                return;
+        }
+    }
+    if (iosb && STATUS_SUCCESS == status)
+    {
+        iosb->u.Status = irp->IoStatus.u.Status;
+        iosb->Information = irp->IoStatus.Information;
+    }
+    LIST_FOR_EACH_ENTRY( instance, &Irps, struct IrpInstance, entry )
+    {
+        if (instance->irp == irp)
+        {
+            list_remove( &instance->entry );
+            HeapFree( GetProcessHeap(), 0, instance );
+            IoFreeIrp( irp );
+            break;
         }
     }
 }
-- 
1.5.4.5.GIT



Подробная информация о списке рассылки Wine-devel