buffer overflow (& invalid registry path for device) bugfix: DataPtr != KeyInformatio...
[reactos.git] / reactos / drivers / net / ndis / ndis / protocol.c
index 6cc859a..f0d61d0 100644 (file)
@@ -9,11 +9,17 @@
  *   CSH 01/08-2000 Created
  *   09-13-2003 Vizzini Updates for SendPackets support
  */
-#include <ndissys.h>
-#include <miniport.h>
-#include <protocol.h>
+#include <roscfg.h>
+#include "ndissys.h"
 #include <buffer.h>
 
+VOID
+EXPORT
+NdisMSendComplete(
+    IN  NDIS_HANDLE     MiniportAdapterHandle,
+    IN  PNDIS_PACKET    Packet,
+    IN  NDIS_STATUS     Status);
+
 #define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
 #define LINKAGE_KEY  L"\\Linkage"
 #define PARAMETERS_KEY L"\\Parameters\\"
@@ -80,7 +86,7 @@ ProIndicatePacket(
   KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
     {
       Adapter->LoopPacket = Packet;
-      BufferedLength = CopyPacketToBuffer(Adapter->LookaheadBuffer, Packet, 0, Adapter->CurLookaheadLength);
+      BufferedLength = CopyPacketToBuffer(Adapter->LookaheadBuffer, Packet, 0, Adapter->NdisMiniportBlock.CurrentLookahead);
     }
   KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
@@ -148,14 +154,16 @@ ProRequest(
           Adapter->MiniportBusy = TRUE;
         }
     }
-  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
+  /* MiniQueueWorkItem must be called at IRQL >= DISPATCH_LEVEL */
   if (QueueWorkItem) 
     {
-      MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest, (NDIS_HANDLE)AdapterBinding);
+      MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest);
       return NDIS_STATUS_PENDING;
     } 
 
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
   /* MiniportQueryInformation (called by MiniDoRequest) runs at DISPATCH_LEVEL */
   /* TODO (?): move the irql raise into MiniDoRequest */
   KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
@@ -269,7 +277,7 @@ ProSend(
 
       if (QueueWorkItem) 
         {
-          MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet, (NDIS_HANDLE)AdapterBinding);
+          MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet);
           return NDIS_STATUS_PENDING;
         }
 
@@ -306,7 +314,7 @@ ProSend(
   /* This is a normal send packet, not a loopback packet. */
   if (QueueWorkItem) 
     {
-      MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet, (NDIS_HANDLE)AdapterBinding);
+      MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet);
       NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
       return NDIS_STATUS_PENDING;
     }
@@ -321,52 +329,61 @@ ProSend(
    */
   if(Adapter->Miniport->Chars.SendPacketsHandler)
     {
-      /* TODO: support deserialized miniports by checking for attributes */
-      /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
-      KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+      if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
         {
           NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
           (*Adapter->Miniport->Chars.SendPacketsHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
         }
-      KeLowerIrql(RaiseOldIrql);
-
-      /* XXX why the hell do we do this? */
-      NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
-      KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+      else
         {
-          if (Adapter->WorkQueueHead)
-            KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
+          /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */
+          KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+            {
+              NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
+              (*Adapter->Miniport->Chars.SendPacketsHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
+            }
+          KeLowerIrql(RaiseOldIrql);
         }
-      KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
-
-      NDIS_DbgPrint(MAX_TRACE, ("MiniportDpc queued; returning NDIS_STATUS_SCUCESS\n"));
 
       /* SendPackets handlers return void - they always "succeed" */
       NdisStatus = NDIS_STATUS_SUCCESS;
     }
   else
     {
-      /* Send handlers always run at DISPATCH_LEVEL so we raise here */
-      KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+      /* XXX FIXME THIS IS WRONG */
+      /* uh oh... forgot why i thought that... */
+      if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE)
         {
-          /* XXX FIXME THIS IS WRONG */
-          /* uh oh... forgot why i thought that... */
-
           NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
-          NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
+          NdisStatus = (*Adapter->Miniport->Chars.SendHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
           NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+        }
+      else
+        {
+          /* Send handlers always run at DISPATCH_LEVEL so we raise here */
+          KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
 
-          /* XXX why the hell do we do this? */
-          NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
-          KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-            {
-              if (Adapter->WorkQueueHead)
-                KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
-            }
-          KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+          NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
+          NdisStatus = (*Adapter->Miniport->Chars.SendHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
+          NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+         if( NdisStatus != NDIS_STATUS_PENDING ) {
+             Adapter->MiniportBusy = FALSE;
+         }
+          KeLowerIrql(RaiseOldIrql);
+        }
+    }
+  
+  /* XXX why the hell do we do this? */
+  NDIS_DbgPrint(MAX_TRACE, ("acquiring miniport block lock\n"));
+  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+    {
+      if (Adapter->WorkQueueHead)
+        {
+          KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
+          NDIS_DbgPrint(MAX_TRACE, ("MiniportDpc queued; returning NDIS_STATUS_SUCCESS\n"));
         }
-      KeLowerIrql(RaiseOldIrql);
     }
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
 
   NDIS_DbgPrint(MAX_TRACE, ("returning 0x%x\n", NdisStatus));
   return NdisStatus;
@@ -389,7 +406,7 @@ ProTransferData(
     IN  NDIS_HANDLE         MacReceiveContext,
     IN  UINT                ByteOffset,
     IN  UINT                BytesToTransfer,
-    IN  OUT    PNDIS_PACKET    Packet,
+    IN  OUT PNDIS_PACKET    Packet,
     OUT PUINT               BytesTransferred)
 /*
  * FUNCTION: Forwards a request to copy received data into a protocol-supplied packet
@@ -411,6 +428,7 @@ ProTransferData(
     /* XXX sd - why is that true? */
 
     if (Packet == Adapter->LoopPacket) {
+       NDIS_DbgPrint(MAX_TRACE, ("LoopPacket\n"));
         /* NDIS is responsible for looping this packet */
         NdisCopyFromPacketToPacket(Packet,
                                    ByteOffset,
@@ -421,7 +439,7 @@ ProTransferData(
         return NDIS_STATUS_SUCCESS;
     }
 
-    return (*Adapter->Miniport->Chars.u2.TransferDataHandler)(
+    return (*Adapter->Miniport->Chars.TransferDataHandler)(
         Packet,
         BytesTransferred,
         Adapter->NdisMiniportBlock.MiniportAdapterContext,
@@ -591,18 +609,18 @@ NdisOpenAdapter(
 
   AdapterBinding->ProtocolBinding        = Protocol;
   AdapterBinding->Adapter                = Adapter;
-  AdapterBinding->NdisOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.ProtocolBindingContext = ProtocolBindingContext;
 
   /* Set fields required by some NDIS macros */
-  AdapterBinding->NdisOpenBlock.MacBindingHandle = (NDIS_HANDLE)AdapterBinding;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.BindingHandle = (NDIS_HANDLE)AdapterBinding;
     
   /* Set handlers (some NDIS macros require these) */
 
-  AdapterBinding->NdisOpenBlock.RequestHandler      = ProRequest;
-  AdapterBinding->NdisOpenBlock.ResetHandler        = ProReset;
-  AdapterBinding->NdisOpenBlock.u1.SendHandler      = ProSend;
-  AdapterBinding->NdisOpenBlock.SendPacketsHandler  = ProSendPackets;
-  AdapterBinding->NdisOpenBlock.TransferDataHandler = ProTransferData;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.RequestHandler      = ProRequest;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.ResetHandler        = ProReset;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.SendHandler         = ProSend;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.SendPacketsHandler  = ProSendPackets;
+  AdapterBinding->NdisOpenBlock.NdisCommonOpenBlock.TransferDataHandler = ProTransferData;
 
 #if 0
   /* XXX this looks fishy */
@@ -654,7 +672,7 @@ NdisRegisterProtocol(
   UINT MinSize;
   HANDLE DriverKeyHandle = NULL;
   PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
-  UINT DataOffset = 0;
+  WCHAR *DataPtr;
 
   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
@@ -664,15 +682,15 @@ NdisRegisterProtocol(
     case 0x03: 
       /* we don't really want to support ndis3 drivers - so we complain for now */
       NDIS_DbgPrint(MID_TRACE, ("NDIS 3 protocol attempting to register\n"));
-      MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS_S);
+      MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS);
       break;
 
     case 0x04:
-      MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S);
+      MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
       break;
 
     case 0x05:
-      MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S);
+      MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
       break;
 
     default:
@@ -727,7 +745,7 @@ NdisRegisterProtocol(
     UNICODE_STRING RegistryPath;
     WCHAR *RegistryPathStr;
 
-    RegistryPathStr = ExAllocatePool(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY));
+    RegistryPathStr = ExAllocatePoolWithTag(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY), NDIS_TAG + __LINE__);
     if(!RegistryPathStr)
       {
         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -776,7 +794,7 @@ NdisRegisterProtocol(
         return;
       }
 
-    KeyInformation = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength);
+    KeyInformation = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, NDIS_TAG + __LINE__);
     if(!KeyInformation)
       {
         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
@@ -800,8 +818,9 @@ NdisRegisterProtocol(
       }
   }
 
-  DataOffset = 0;
-  while((KeyInformation->Data)[DataOffset])
+  for (DataPtr = (WCHAR *)KeyInformation->Data;
+       *DataPtr != 0;
+       DataPtr += wcslen(DataPtr) + 1)
     {
       /* BindContext is for tracking pending binding operations */
       VOID *BindContext = 0;
@@ -810,7 +829,7 @@ NdisRegisterProtocol(
       WCHAR *RegistryPathStr = NULL;
       ULONG PathLength = 0;
 
-      RtlInitUnicodeString(&DeviceName, (WCHAR *)KeyInformation->Data);        /* we know this is 0-term */
+      RtlInitUnicodeString(&DeviceName, DataPtr);      /* we know this is 0-term */
 
       /*
        * RegistryPath should be:
@@ -821,9 +840,9 @@ NdisRegisterProtocol(
        */
 
       PathLength = sizeof(SERVICES_KEY) +                               /* \Registry\Machine\System\CurrentControlSet\Services\ */
-          wcslen( ((WCHAR *)KeyInformation->Data)+8 ) * sizeof(WCHAR) + /* Adapter1  (extracted from \Device\Adapter1)          */
+          wcslen( DataPtr + 8 ) * sizeof(WCHAR) + /* Adapter1  (extracted from \Device\Adapter1)          */
           sizeof(PARAMETERS_KEY) +                                      /* \Parameters\                                         */
-          ProtocolCharacteristics->Name.Length;                         /* Tcpip                                                */
+          ProtocolCharacteristics->Name.Length + sizeof(WCHAR);                         /* Tcpip                                                */
 
       RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
       if(!RegistryPathStr)
@@ -836,7 +855,7 @@ NdisRegisterProtocol(
         }
 
       wcscpy(RegistryPathStr, SERVICES_KEY);
-      wcscat(RegistryPathStr, (((WCHAR *)(KeyInformation->Data)) +8 ));
+      wcscat(RegistryPathStr, DataPtr + 8 );
       wcscat(RegistryPathStr, PARAMETERS_KEY);
       wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
 
@@ -846,7 +865,7 @@ NdisRegisterProtocol(
 
       NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
           &DeviceName, &RegistryPath));
-
+      
       /* XXX SD must do something with bind context */
       *NdisProtocolHandle = Protocol;
 
@@ -874,8 +893,6 @@ NdisRegisterProtocol(
           // what to do here?
         }
        */
-
-      DataOffset += wcslen((WCHAR *)KeyInformation->Data);
     }
 
   *Status             = NDIS_STATUS_SUCCESS;