changed callbacks to use stdcall
authorVizzini <vizzini@plasmic.com>
Mon, 15 Sep 2003 03:58:12 +0000 (03:58 +0000)
committerVizzini <vizzini@plasmic.com>
Mon, 15 Sep 2003 03:58:12 +0000 (03:58 +0000)
made a number of changes to the protocol->miniport send path
clarified locking and irql manipulation code
added support for SendPacketsHandler
cleaned up NdisRegisterProtocol and NdisOpenAdapter

svn path=/trunk/; revision=6086

reactos/drivers/net/ndis/include/debug.h
reactos/drivers/net/ndis/ndis/SOURCES
reactos/drivers/net/ndis/ndis/enum.c
reactos/drivers/net/ndis/ndis/miniport.c
reactos/drivers/net/ndis/ndis/protocol.c
reactos/drivers/net/ndis/readme.txt
reactos/drivers/net/tcpip/tcpip/routines.c
reactos/include/net/ndis.h

index c60e136..e217a10 100644 (file)
@@ -4,7 +4,6 @@
  * FILE:        include/debug.h
  * PURPOSE:     Debugging support macros
  * DEFINES:     DBG     - Enable debug output
- *              NASSERT - Disable assertions
  */
 #ifndef __DEBUG_H
 #define __DEBUG_H
@@ -45,19 +44,6 @@ extern DWORD DebugTraceLevel;
 
 #endif /* _MSC_VER */
 
-
-/* ASSERT is in rtl.h */
-#if 0
-#ifdef ASSERT
-#undef ASSERT
-#endif
-
-#ifdef NASSERT
-#define ASSERT(x)
-#else /* NASSERT */
-#define ASSERT(x) if (!(x)) { NDIS_DbgPrint(MIN_TRACE, ("Assertion "#x" failed at %s:%d\n", __FILE__, __LINE__)); KeBugCheck(0); }
-#endif /* NASSERT */
-#endif
 #define ASSERT_IRQL(x) ASSERT(KeGetCurrentIrql() <= (x))
 
 #else /* DBG */
index 692b996..441f582 100644 (file)
@@ -1,3 +1,6 @@
+### THIS FILE IS OFFICIALLY OBSOLETE ###
+### SEE ../README.TXT ###
+
 TARGETNAME=ndis
 TARGETPATH=..\objects
 TARGETTYPE=EXPORT_DRIVER
index 47be389..7705946 100644 (file)
@@ -393,8 +393,6 @@ VOID NdisStartDevices()
               /* read class, looking for net guid */
               RtlInitUnicodeString(&ValueName, L"ClassGUID");
 
-              NDIS_DbgPrint(MAX_TRACE, ("About to ask for 0x%x bytes\n", VALUE_INFORMATION_SIZE));
-
               KeyValueInformation = ExAllocatePool(PagedPool, VALUE_INFORMATION_SIZE);
               if(!KeyValueInformation)
                 {
index 02b740a..4b842f4 100644 (file)
@@ -172,6 +172,26 @@ MiniIndicateData(
 
         KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
+#if DBG
+        if(!AdapterBinding)
+          {
+            NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding was null\n"));
+            return;
+          }
+
+        if(!AdapterBinding->ProtocolBinding)
+          {
+            NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding was null\n"));
+            return;
+          }
+
+        if(!AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)
+          {
+            NDIS_DbgPrint(MIN_TRACE, ("AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler was null\n"));
+            return;
+          }
+#endif
+
         (*AdapterBinding->ProtocolBinding->Chars.u4.ReceiveHandler)(
             AdapterBinding->NdisOpenBlock.ProtocolBindingContext,
             MacReceiveContext,
@@ -186,6 +206,8 @@ MiniIndicateData(
         CurrentEntry = CurrentEntry->Flink;
     }
     KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+    NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
 }
 
 
@@ -200,9 +222,51 @@ MiniIndicateReceivePacket(
  *     Miniport: Miniport handle for the adapter
  *     PacketArray: pointer to a list of packet pointers to indicate
  *     NumberOfPackets: number of packets to indicate
+ * NOTES:
+ *     - This currently is a big temporary hack.  In the future this should
+ *       call ProtocolReceivePacket() on each bound protocol if it exists.
+ *       For now it just mimics NdisMEthIndicateReceive.
  */
 {
-  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+  UINT i;
+
+  for(i = 0; i < NumberOfPackets; i++)
+    {
+      PCHAR PacketBuffer = 0;
+      UINT PacketLength = 0;
+      PNDIS_BUFFER NdisBuffer = 0;
+
+#define PACKET_TAG (('k' << 24) + ('P' << 16) + ('D' << 8) + 'N')
+
+      NdisAllocateMemoryWithTag((PVOID)&PacketBuffer, 1518, PACKET_TAG);
+      if(!PacketBuffer)
+        {
+          NDIS_DbgPrint(MIN_TRACE, ("insufficient resources\n"));
+          return;
+        }
+
+      NdisQueryPacket(PacketArray[i], NULL, NULL, &NdisBuffer, NULL);
+
+      while(NdisBuffer)
+        {
+          PNDIS_BUFFER CurrentBuffer;
+          PVOID BufferVa;
+          UINT BufferLen;
+
+          NdisQueryBuffer(NdisBuffer, &BufferVa, &BufferLen);
+          memcpy(PacketBuffer + PacketLength, BufferVa, BufferLen);
+          PacketLength += BufferLen;
+
+          CurrentBuffer = NdisBuffer;
+          NdisGetNextBuffer(CurrentBuffer, &NdisBuffer);
+        }
+
+      NDIS_DbgPrint(MID_TRACE, ("indicating a %d-byte packet\n", PacketLength));
+
+      MiniIndicateData(Miniport, 0, PacketBuffer, 14, PacketBuffer+14, PacketLength-14, PacketLength-14);
+
+      NdisFreeMemory(PacketBuffer, 0, 0);
+    }
 }
 
 
@@ -246,7 +310,7 @@ MiniEthReceiveComplete(
 
 VOID
 MiniEthReceiveIndication(
-    IN  PETH_FILTER Filter,
+    IN  PETH_FILTER Filter,     /* shouldn't be NDIS_HANDLE? */
     IN  NDIS_HANDLE MacReceiveContext,
     IN  PCHAR       Address,
     IN  PVOID       HeaderBuffer,
@@ -363,7 +427,20 @@ MiniAdapterHasAddress(
 
     NDIS_DbgPrint(DEBUG_MINIPORT, ("Called.\n"));
 
-    Start1 = (PUCHAR)&Adapter->Address;
+#if DBG
+    if(!Adapter)
+      {
+        NDIS_DbgPrint(MID_TRACE, ("Adapter object was null\n"));
+        return FALSE;
+      }
+
+    if(!Packet)
+      {
+        NDIS_DbgPrint(MID_TRACE, ("Packet was null\n"));
+        return FALSE;
+      }
+#endif
+
     NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, NULL);
     if (!NdisBuffer) {
         NDIS_DbgPrint(MID_TRACE, ("Packet contains no buffers.\n"));
@@ -391,6 +468,11 @@ MiniAdapterHasAddress(
         return FALSE;
     }
 
+    Start1 = (PUCHAR)&Adapter->Address;
+    NDIS_DbgPrint(MAX_TRACE, ("packet address: %x:%x:%x:%x:%x:%x adapter address: %x:%x:%x:%x:%x:%x\n",
+        *((char *)Start1), *(((char *)Start1)+1), *(((char *)Start1)+2), *(((char *)Start1)+3), *(((char *)Start1)+4), *(((char *)Start1)+5),
+        *((char *)Start2), *(((char *)Start2)+1), *(((char *)Start2)+2), *(((char *)Start2)+3), *(((char *)Start2)+4), *(((char *)Start2)+5)
+    ));
     return (RtlCompareMemory((PVOID)Start1, (PVOID)Start2, Length) == Length);
 }
 
@@ -696,26 +778,45 @@ VOID STDCALL MiniportDpc(
         Adapter->MiniportAdapterBinding = AdapterBinding;
         switch (WorkItemType) {
         case NdisWorkItemSend:
+          /*
+           * called by ProSend when protocols want to send packets to the miniport
+           */
 #ifdef DBG
             MiniDisplayPacket((PNDIS_PACKET)WorkItemContext);
 #endif
-            NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
-                Adapter->NdisMiniportBlock.MiniportAdapterContext,
-                (PNDIS_PACKET)WorkItemContext,
-                0);
-            if (NdisStatus != NDIS_STATUS_PENDING) {
-                MiniSendComplete((NDIS_HANDLE)Adapter,
-                                 (PNDIS_PACKET)WorkItemContext,
-                                 NdisStatus);
-            }
+            if(Adapter->Miniport->Chars.SendPacketsHandler)
+              {
+                NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
+
+                /*
+                 * XXX assumes single-packet - prolly OK since we'll call something
+                 * different on multi-packet sends
+                 */
+                (*Adapter->Miniport->Chars.SendPacketsHandler)(
+                    Adapter->NdisMiniportBlock.MiniportAdapterContext, (PPNDIS_PACKET)&WorkItemContext, 1);
+
+                NDIS_DbgPrint(MAX_TRACE, ("back from miniport's SendPackets handler\n"));
+              }
+            else
+              {
+                NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
+                NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
+                    Adapter->NdisMiniportBlock.MiniportAdapterContext, (PNDIS_PACKET)WorkItemContext, 0);
+                NDIS_DbgPrint(MAX_TRACE, ("back from miniport's Send handler\n"));
+
+                if (NdisStatus != NDIS_STATUS_PENDING) 
+                    MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
+              }
+
             break;
 
         case NdisWorkItemSendLoopback:
-            NdisStatus = ProIndicatePacket(Adapter,
-                                           (PNDIS_PACKET)WorkItemContext);
-            MiniSendComplete((NDIS_HANDLE)Adapter,
-                             (PNDIS_PACKET)WorkItemContext,
-                             NdisStatus);
+          /*
+           * called by ProSend when protocols want to send loopback packets
+           */
+            /* XXX atm ProIndicatePacket sends a packet up via the loopback adapter only */
+            NdisStatus = ProIndicatePacket(Adapter, (PNDIS_PACKET)WorkItemContext);
+            MiniSendComplete((NDIS_HANDLE)Adapter, (PNDIS_PACKET)WorkItemContext, NdisStatus);
             break;
 
         case NdisWorkItemReturnPackets:
@@ -1284,7 +1385,7 @@ NdisIStartAdapter(
   Status = ZwOpenKey(&RegKeyHandle, KEY_ALL_ACCESS, &RegKeyAttributes);
   if(Status != STATUS_SUCCESS)
     {
-      NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key %ws\n", RegKeyPath));
+      NDIS_DbgPrint(MIN_TRACE,("failed to open adapter-specific reg key %wZ\n", &RegKeyPathU));
       ExFreePool(Adapter);
       return;
     }
@@ -1697,6 +1798,7 @@ NdisMSetAttributesEx(
     if(AttributeFlags & NDIS_ATTRIBUTE_DESERIALIZE)
       {
         NDIS_DbgPrint(MIN_TRACE, ("Deserialized miniport - UNIMPLEMENTED\n"));
+        /* XXX when this is implemented, be sure to fix ProSend() to not nail the irql up to dispatch_level */
 #ifdef DBG
         __asm__("int $3\n");
 #endif
index 9f933b1..c3932a6 100644 (file)
@@ -4,18 +4,24 @@
  * FILE:        ndis/protocol.c
  * PURPOSE:     Routines used by NDIS protocol drivers
  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ *              Vizzini (vizzini@plasmic.com)
  * REVISIONS:
  *   CSH 01/08-2000 Created
+ *   09-13-2003 Vizzini Updates for SendPackets support
  */
 #include <ndissys.h>
 #include <miniport.h>
 #include <protocol.h>
 #include <buffer.h>
 
+#define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
+#define LINKAGE_KEY  L"\\Linkage"
+#define PARAMETERS_KEY L"\\Parameters\\"
 
 LIST_ENTRY ProtocolListHead;
 KSPIN_LOCK ProtocolListLock;
 
+\f
 /*
  * @implemented
  */
@@ -32,22 +38,17 @@ NdisCompleteBindAdapter(
  *     Packet  = Pointer to packet to indicate
  * RETURNS:
  *     Status of operation
+ * NOTES:
+ *     - FIXME: partially-implemented
  */
 {
-    /* 
-         * XXX partially-implemented!
-         *
-         * need to handle error conditions, and i'm not sure this is even what this func should do.
-         * be sure to fix NdisRegisterProtocol before fixing this, though.
-         */
-
-    PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
+  PROTOCOL_BINDING *Protocol = (PROTOCOL_BINDING *)BindAdapterContext;
 
-    /* Put protocol binding struct on global list */
-    ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
+  /* Put protocol binding struct on global list */
+  ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
 }
 
-
+\f
 NDIS_STATUS
 ProIndicatePacket(
     PLOGICAL_ADAPTER Adapter,
@@ -58,61 +59,52 @@ ProIndicatePacket(
  *     Adapter = Pointer to logical adapter
  *     Packet  = Pointer to packet to indicate
  * RETURNS:
- *     Status of operation
+ *     STATUS_SUCCESS in all cases
+ * NOTES:
+ *     - XXX ATM, this only handles loopback packets - is that its designed function?
  */
 {
-    KIRQL OldIrql;
-    UINT Length;
-    UINT Total;
+  KIRQL OldIrql;
+  UINT BufferedLength;
+  UINT PacketLength;
 
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
 #ifdef DBG
-    MiniDisplayPacket(Packet);
+  MiniDisplayPacket(Packet);
 #endif
 
-    NdisQueryPacket(Packet, NULL, NULL, NULL, &Total);
-
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+  NdisQueryPacket(Packet, NULL, NULL, NULL, &PacketLength);
 
-    Adapter->LoopPacket = Packet;
-
-    Length = CopyPacketToBuffer(
-        Adapter->LookaheadBuffer,
-        Packet,
-        0,
-        Adapter->CurLookaheadLength);
-
-    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-    if (Length > Adapter->MediumHeaderSize) {
-        MiniIndicateData(Adapter,
-                         NULL,
-                         Adapter->LookaheadBuffer,
-                         Adapter->MediumHeaderSize,
-                         &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize],
-                         Length - Adapter->MediumHeaderSize,
-                         Total - Adapter->MediumHeaderSize);
-    } else {
-        MiniIndicateData(Adapter,
-                         NULL,
-                         Adapter->LookaheadBuffer,
-                         Adapter->MediumHeaderSize,
-                         NULL,
-                         0,
-                         0);
+  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+    {
+      Adapter->LoopPacket = Packet;
+      BufferedLength = CopyPacketToBuffer(Adapter->LookaheadBuffer, Packet, 0, Adapter->CurLookaheadLength);
+    }
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+  if (BufferedLength > Adapter->MediumHeaderSize) 
+    {
+      /* XXX Change this to call SendPackets so we don't have to duplicate this wacky logic */
+      MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize,
+          &Adapter->LookaheadBuffer[Adapter->MediumHeaderSize], BufferedLength - Adapter->MediumHeaderSize,
+          PacketLength - Adapter->MediumHeaderSize);
+    } 
+  else 
+    {
+      MiniIndicateData(Adapter, NULL, Adapter->LookaheadBuffer, Adapter->MediumHeaderSize, NULL, 0, 0);
     }
 
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-
-    Adapter->LoopPacket = NULL;
-
-    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+    {
+      Adapter->LoopPacket = NULL;
+    }
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
 
-    return STATUS_SUCCESS;
+  return STATUS_SUCCESS;
 }
 
-
+\f
 NDIS_STATUS
 ProRequest(
     IN  NDIS_HANDLE     MacBindingHandle,
@@ -126,42 +118,59 @@ ProRequest(
  *     Status of operation
  */
 {
-    KIRQL OldIrql;
-    BOOLEAN Queue;
-    NDIS_STATUS NdisStatus;
-    PADAPTER_BINDING AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
-    PLOGICAL_ADAPTER Adapter        = AdapterBinding->Adapter;
-
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-    Queue = Adapter->MiniportBusy;
-    if (Queue) {
-        MiniQueueWorkItem(Adapter,
-                          NdisWorkItemRequest,
-                          (PVOID)NdisRequest,
-                          (NDIS_HANDLE)AdapterBinding);
-    } else {
+  KIRQL OldIrql;
+  BOOLEAN QueueWorkItem;
+  NDIS_STATUS NdisStatus;
+  PADAPTER_BINDING AdapterBinding; 
+  PLOGICAL_ADAPTER Adapter;
+
+  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+  ASSERT(MacBindingHandle);
+  AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
+
+  ASSERT(AdapterBinding->Adapter);
+  Adapter = AdapterBinding->Adapter;
+
+  /*
+   * If the miniport is already busy, queue a workitem
+   */
+  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
+    {
+      if(Adapter->MiniportBusy)
+        QueueWorkItem = TRUE;
+      else
         Adapter->MiniportBusy = TRUE;
     }
-    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-    if (!Queue) {
-        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-        NdisStatus = MiniDoRequest(Adapter, NdisRequest);
-        KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-        Adapter->MiniportBusy = FALSE;
-        if (Adapter->WorkQueueHead)
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
+
+  if (QueueWorkItem) 
+    {
+      MiniQueueWorkItem(Adapter, NdisWorkItemRequest, (PVOID)NdisRequest, (NDIS_HANDLE)AdapterBinding);
+      return NDIS_STATUS_PENDING;
+    } 
+
+  /* MiniportQueryInformation (called by MiniDoRequest) runs at DISPATCH_LEVEL */
+  /* TODO (?): move the irql raise into MiniDoRequest */
+  KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+    {
+      NdisStatus = MiniDoRequest(Adapter, NdisRequest);
+
+      KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+        {
+          Adapter->MiniportBusy = FALSE;
+
+          if (Adapter->WorkQueueHead)
             KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
-        KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-        KeLowerIrql(OldIrql);
-    } else {
-        NdisStatus = NDIS_STATUS_PENDING;
+        }
+      KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
     }
-    return NdisStatus;
-}
+  KeLowerIrql(OldIrql);
 
+  return NdisStatus;
+}
 
+\f
 NDIS_STATUS
 ProReset(
     IN  NDIS_HANDLE MacBindingHandle)
@@ -171,7 +180,7 @@ ProReset(
     return NDIS_STATUS_FAILURE;
 }
 
-
+\f
 NDIS_STATUS
 ProSend(
     IN  NDIS_HANDLE     MacBindingHandle,
@@ -181,91 +190,173 @@ ProSend(
  * ARGUMENTS:
  *     MacBindingHandle = Adapter binding handle
  *     Packet           = Pointer to NDIS packet descriptor
+ * RETURNS:
+ *     NDIS_STATUS_SUCCESS always
+ * NOTES:
+ * TODO:
+ *     - Fix return values
+ *     - Should queue packet if miniport returns NDIS_STATUS_RESOURCES
+ *     - Queue packets directly on the adapters when possible (i.e.
+ *       when miniports not busy)
+ *     - Break this up
  */
 {
-    KIRQL OldIrql;
-    BOOLEAN Queue;
-    NDIS_STATUS NdisStatus;
-    PADAPTER_BINDING AdapterBinding  = GET_ADAPTER_BINDING(MacBindingHandle);
-    PLOGICAL_ADAPTER Adapter         = AdapterBinding->Adapter;
-
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    /* FIXME: Should queue packet if miniport returns NDIS_STATUS_RESOURCES */
-
-    Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;
+  KIRQL RaiseOldIrql, SpinOldIrql;
+  BOOLEAN QueueWorkItem;
+  NDIS_STATUS NdisStatus;
+  PADAPTER_BINDING AdapterBinding;
+  PLOGICAL_ADAPTER Adapter;
+
+  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+  ASSERT(MacBindingHandle);
+  AdapterBinding = GET_ADAPTER_BINDING(MacBindingHandle);
+
+  ASSERT(AdapterBinding);
+  Adapter = AdapterBinding->Adapter;
+
+  ASSERT(Adapter);
+
+  /* if the following is not true, KeRaiseIrql() below will break */
+  ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+
+  /* XXX what is this crazy black magic? */
+  Packet->Reserved[0] = (ULONG_PTR)MacBindingHandle;
+
+  /*
+   * Acquire this lock in order to see if the miniport is busy.
+   * If it is not busy, we mark it as busy and release the lock.
+   * Else we don't do anything because we have to queue a workitem
+   * anyway.
+   */
+  KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+    {
+      /*
+       * if the miniport is marked as busy, we queue the packet as a work item,
+       * else we send the packet directly to the miniport.  Sending to the miniport
+       * makes it busy.
+       */
+      if (Adapter->MiniportBusy)
+        QueueWorkItem = TRUE;
+      else
+        Adapter->MiniportBusy = TRUE;
+    }
+  KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
+
+  /*
+   * Test the packet to see if it is a MAC loopback.
+   *
+   * We may have to loop this packet if miniport cannot. 
+   * If dest MAC address of packet == MAC address of adapter,
+   * this is a loopback frame.
+   */
+  if ((Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) &&
+      MiniAdapterHasAddress(Adapter, Packet))
+    {
+      NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));
+
+      if (QueueWorkItem) 
+        {
+          MiniQueueWorkItem(Adapter, NdisWorkItemSendLoopback, (PVOID)Packet, (NDIS_HANDLE)AdapterBinding);
+          return NDIS_STATUS_PENDING;
+        }
 
-    KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &OldIrql);
-    Queue = Adapter->MiniportBusy;
+      KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql);
+        {
+          /*
+           * atm this *only* handles loopback packets - it calls MiniIndicateData to 
+           * send back to the protocol.  FIXME: this will need to be adjusted a bit.
+           * Also, I'm not sure you really have to be at dispatch level for this.  It
+           * might use a ReceivePackets handler, which can run <= DISPATCH_LEVEL.
+           */
+          NdisStatus = ProIndicatePacket(Adapter, Packet);
+
+          KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+            {
+              Adapter->MiniportBusy = FALSE;
+
+              if (Adapter->WorkQueueHead)
+                KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
+              else
+                NDIS_DbgPrint(MID_TRACE,("Failed to insert packet into work queue\n"));
+            }
+          KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+        }
+      KeLowerIrql(RaiseOldIrql);
 
-    /* We may have to loop this packet if miniport cannot */
-    if (Adapter->NdisMiniportBlock.MacOptions & NDIS_MAC_OPTION_NO_LOOPBACK) {
-        if (MiniAdapterHasAddress(Adapter, Packet)) {
-            /* Do software loopback because miniport does not support it */
+      return NdisStatus;
+    }
+  else
+    NDIS_DbgPrint(MID_TRACE,("Not a loopback packet\n"));
+
+  /* This is a normal send packet, not a loopback packet. */
+  if (QueueWorkItem) 
+    {
+      MiniQueueWorkItem(Adapter, NdisWorkItemSend, (PVOID)Packet, (NDIS_HANDLE)AdapterBinding);
+      NDIS_DbgPrint(MAX_TRACE, ("Queued a work item and returning\n"));
+      return NDIS_STATUS_PENDING;
+    }
 
-            NDIS_DbgPrint(MIN_TRACE, ("Looping packet.\n"));
+  ASSERT(Adapter->Miniport);
+
+  /* 
+   * Call the appropriate send handler 
+   *
+   * If a miniport provides a SendPackets handler, we always call it.  If not, we call the
+   * Send handler.
+   */
+  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);
+        {
+          NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n"));
+          (*Adapter->Miniport->Chars.SendPacketsHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1);
+        }
+      KeLowerIrql(RaiseOldIrql);
 
-            if (Queue) {
+      /* XXX why the hell do we do this? */
+      KeAcquireSpinLock(&Adapter->NdisMiniportBlock.Lock, &SpinOldIrql);
+        {
+          if (Adapter->WorkQueueHead)
+            KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
+        }
+      KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, SpinOldIrql);
 
-                /* FIXME: Packets should properbly be queued directly on the adapter instead */
+      NDIS_DbgPrint(MAX_TRACE, ("MiniportDpc queued; returning NDIS_STATUS_SCUCESS\n"));
 
-                MiniQueueWorkItem(Adapter,
-                                  NdisWorkItemSendLoopback,
-                                  (PVOID)Packet,
-                                  (NDIS_HANDLE)AdapterBinding);
-            } else {
-                Adapter->MiniportBusy = TRUE;
-            }
-            KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-            if (!Queue) {
-                KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-                NdisStatus = ProIndicatePacket(Adapter, Packet);
-                KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-                Adapter->MiniportBusy = FALSE;
-                if (Adapter->WorkQueueHead)
-                    KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
-                KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-                KeLowerIrql(OldIrql);
-                return NdisStatus;
-            } else {
-                return NDIS_STATUS_PENDING;
+      /* 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... */
+
+          NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n"));
+          NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, 0);
+          NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n"));
+
+          /* XXX why the hell do we do this? */
+          KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
+            {
+              if (Adapter->WorkQueueHead)
+                KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
             }
+          KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
         }
+      KeLowerIrql(RaiseOldIrql);
     }
 
-    if (Queue) {
-
-        /* FIXME: Packets should properbly be queued directly on the adapter instead */
-
-        MiniQueueWorkItem(Adapter,
-                          NdisWorkItemSend,
-                          (PVOID)Packet,
-                          (NDIS_HANDLE)AdapterBinding);
-    } else {
-        Adapter->MiniportBusy = TRUE;
-    }
-    KeReleaseSpinLock(&Adapter->NdisMiniportBlock.Lock, OldIrql);
-
-    if (!Queue) {
-        KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
-        NdisStatus = (*Adapter->Miniport->Chars.u1.SendHandler)(
-            Adapter->NdisMiniportBlock.MiniportAdapterContext,
-            Packet,
-            0);
-        KeAcquireSpinLockAtDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-        Adapter->MiniportBusy = FALSE;
-        if (Adapter->WorkQueueHead)
-            KeInsertQueueDpc(&Adapter->MiniportDpc, NULL, NULL);
-        KeReleaseSpinLockFromDpcLevel(&Adapter->NdisMiniportBlock.Lock);
-        KeLowerIrql(OldIrql);
-    } else {
-        NdisStatus = NDIS_STATUS_PENDING;
-    }
-    return NdisStatus;
+  NDIS_DbgPrint(MAX_TRACE, ("returning 0x%x\n", NdisStatus));
+  return NdisStatus;
 }
 
-
+\f
 VOID
 ProSendPackets(
     IN  NDIS_HANDLE     NdisBindingHandle,
@@ -275,7 +366,7 @@ ProSendPackets(
     UNIMPLEMENTED
 }
 
-
+\f
 NDIS_STATUS
 ProTransferData(
     IN  NDIS_HANDLE         MacBindingHandle,
@@ -301,6 +392,7 @@ ProTransferData(
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
     /* FIXME: Interrupts must be disabled for adapter */
+    /* XXX sd - why is that true? */
 
     if (Packet == Adapter->LoopPacket) {
         /* NDIS is responsible for looping this packet */
@@ -434,6 +526,13 @@ NdisOpenAdapter(
 
     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
 
+    if(!NdisProtocolHandle)
+      {
+        NDIS_DbgPrint(MAX_TRACE, ("NdisProtocolHandle is NULL\n"));
+        *OpenErrorStatus = *Status = NDIS_STATUS_FAILURE;
+        return;
+      }
+
     Adapter = MiniLocateDevice(AdapterName);
     if (!Adapter) {
         NDIS_DbgPrint(MIN_TRACE, ("Adapter not found.\n"));
@@ -518,242 +617,249 @@ NdisRegisterProtocol(
  *     NdisProtocolHandle      = Address of buffer for handle used to identify the driver
  *     ProtocolCharacteristics = Pointer to NDIS_PROTOCOL_CHARACTERISTICS structure
  *     CharacteristicsLength   = Size of structure which ProtocolCharacteristics targets
+ * NOTES:
+ *     - you *must* set NdisProtocolHandle before doing anything that could wind up 
+ *       getting BindAdapterHandler, as it will probably call OpenAdapter with this handle
+ *     - the above implies that the initialization of the protocol block must be complete
+ *       by then
  * TODO:
- *     break this function up
- *     make this thing able to handle >1 protocol
+ *     - break this function up - probably do a 'ndisRefreshProtocolBindings' function
+ *     make this thing able to handle >1 protocol
  */
 {
-    PPROTOCOL_BINDING Protocol;
-    NTSTATUS NtStatus;
-    UINT MinSize;
-    HANDLE DriverKeyHandle = NULL;
-    PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
-        UINT DataOffset = 0;
-
-    NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
-
-    switch (ProtocolCharacteristics->MajorNdisVersion) {
-    case 0x03: /* we don't really want to support ndis3 drivers - so we complainf or now */
-                 NDIS_DbgPrint(MID_TRACE, ("Ndis 3 protocol attempting to register\n"));
-        MinSize = sizeof(NDIS30_PROTOCOL_CHARACTERISTICS_S);
-        break;
+  PPROTOCOL_BINDING Protocol;
+  NTSTATUS NtStatus;
+  UINT MinSize;
+  HANDLE DriverKeyHandle = NULL;
+  PKEY_VALUE_PARTIAL_INFORMATION KeyInformation = NULL;
+  UINT DataOffset = 0;
+
+  NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
+
+  /* first validate the PROTOCOL_CHARACTERISTICS */
+  switch (ProtocolCharacteristics->MajorNdisVersion) 
+    {
+    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);
+      break;
 
     case 0x04:
-        MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S);
-        break;
+      MinSize = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS_S);
+      break;
 
     case 0x05:
-        MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S);
-        break;
+      MinSize = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS_S);
+      break;
 
     default:
-        *Status = NDIS_STATUS_BAD_VERSION;
-                 NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
-        return;
+      *Status = NDIS_STATUS_BAD_VERSION;
+      NDIS_DbgPrint(MIN_TRACE, ("Incorrect characteristics size\n"));
+      return;
     }
 
-    if (CharacteristicsLength < MinSize) {
-        NDIS_DbgPrint(DEBUG_PROTOCOL, ("Bad protocol characteristics.\n"));
-        *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
-        return;
+  if (CharacteristicsLength < MinSize) 
+    {
+      NDIS_DbgPrint(DEBUG_PROTOCOL, ("Bad protocol characteristics.\n"));
+      *Status = NDIS_STATUS_BAD_CHARACTERISTICS;
+      return;
+    }
+
+  /* set up the protocol block */
+  Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
+  if (!Protocol) 
+    {
+      NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+      *Status = NDIS_STATUS_RESOURCES;
+      return;
     }
 
-    Protocol = ExAllocatePool(NonPagedPool, sizeof(PROTOCOL_BINDING));
-    if (!Protocol) {
+  RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
+  RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
+
+  NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name, &ProtocolCharacteristics->Name, TRUE);
+  if (!NT_SUCCESS(NtStatus)) 
+    {
+      NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+      ExFreePool(Protocol);
+      *Status = NDIS_STATUS_RESOURCES;
+      return;
+    }
+
+  KeInitializeSpinLock(&Protocol->Lock);
+
+  Protocol->RefCount = 1;
+
+  InitializeListHead(&Protocol->AdapterListHead);
+
+  /* 
+   * bind the adapter to all of its miniports 
+   *
+   * open registry path
+   * get list of devices from Bind key
+   * call BindAdapterHandler for each
+   */
+  {
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    UNICODE_STRING RegistryPath;
+    WCHAR *RegistryPathStr;
+
+    RegistryPathStr = ExAllocatePool(PagedPool, sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY));
+    if(!RegistryPathStr)
+      {
         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+        ExFreePool(Protocol);
         *Status = NDIS_STATUS_RESOURCES;
         return;
-    }
+      }
+
+    wcscpy(RegistryPathStr, SERVICES_KEY);
+    wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer), ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
+    RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
+    wcscat(RegistryPathStr, LINKAGE_KEY);
+
+    RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
+    NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
+
+    InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
+    NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
+
+    ExFreePool(RegistryPathStr);
+
+    if(!NT_SUCCESS(NtStatus))
+      {
+        NDIS_DbgPrint(MID_TRACE, ("Unable to open protocol configuration\n"));
+        ExFreePool(Protocol);
+        *Status = NDIS_STATUS_FAILURE;
+        return;
+      }
+  }
+
+  NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
+
+  {
+    UNICODE_STRING ValueName;
+    ULONG ResultLength;
 
-    RtlZeroMemory(Protocol, sizeof(PROTOCOL_BINDING));
-    RtlCopyMemory(&Protocol->Chars, ProtocolCharacteristics, MinSize);
+    RtlInitUnicodeString(&ValueName, L"Bind");
 
-    NtStatus = RtlUpcaseUnicodeString(&Protocol->Chars.Name,
-                                      &ProtocolCharacteristics->Name,
-                                      TRUE);
-    if (!NT_SUCCESS(NtStatus)) {
+    NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
+    if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL)
+      {
+        NDIS_DbgPrint(MID_TRACE, ("Unable to query the Bind value for size\n"));
+        ZwClose(DriverKeyHandle);
+        ExFreePool(Protocol);
+        *Status = NDIS_STATUS_FAILURE;
+        return;
+      }
+
+    KeyInformation = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength);
+    if(!KeyInformation)
+      {
         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
+        ZwClose(DriverKeyHandle);
         ExFreePool(Protocol);
-        *Status = NDIS_STATUS_RESOURCES;
+        *Status = NDIS_STATUS_FAILURE;
         return;
-    }
+      }
+
+    NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
+        sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
+
+    if(!NT_SUCCESS(NtStatus))
+      {
+        NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
+        ZwClose(DriverKeyHandle);
+        ExFreePool(KeyInformation);
+        ExFreePool(Protocol);
+        *Status = NDIS_STATUS_FAILURE;
+        return;
+      }
+  }
+
+  DataOffset = 0;
+  while((KeyInformation->Data)[DataOffset])
+    {
+      /* BindContext is for tracking pending binding operations */
+      VOID *BindContext = 0;
+      NDIS_STRING DeviceName;
+      NDIS_STRING RegistryPath;
+      WCHAR *RegistryPathStr = NULL;
+      ULONG PathLength = 0;
+
+      RtlInitUnicodeString(&DeviceName, (WCHAR *)KeyInformation->Data);        /* we know this is 0-term */
+
+      /*
+       * RegistryPath should be:
+       *     \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
+       *
+       *  This is constructed as follows:
+       *      SERVICES_KEY + extracted device name + Protocol name from characteristics 
+       */
+
+      PathLength = sizeof(SERVICES_KEY) +                               /* \Registry\Machine\System\CurrentControlSet\Services\ */
+          wcslen( ((WCHAR *)KeyInformation->Data)+8 ) * sizeof(WCHAR) + /* Adapter1  (extracted from \Device\Adapter1)          */
+          sizeof(PARAMETERS_KEY) +                                      /* \Parameters\                                         */
+          ProtocolCharacteristics->Name.Length;                         /* Tcpip                                                */
+
+      RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
+      if(!RegistryPathStr)
+        {
+          NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
+          ExFreePool(KeyInformation);
+          ExFreePool(Protocol);
+          *Status = NDIS_STATUS_RESOURCES;
+          return;
+        }
 
-    KeInitializeSpinLock(&Protocol->Lock);
+      wcscpy(RegistryPathStr, SERVICES_KEY);
+      wcscat(RegistryPathStr, (((WCHAR *)(KeyInformation->Data)) +8 ));
+      wcscat(RegistryPathStr, PARAMETERS_KEY);
+      wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
 
-    Protocol->RefCount = 1;
+      RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
 
-    InitializeListHead(&Protocol->AdapterListHead);
+      RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
 
-        /* 
-         * bind the adapter to all of its miniports 
-         *
-         * open registry path
-         * get list of devices from Bind key
-         * call BindAdapterHandler for each
-         */
-       {
-               OBJECT_ATTRIBUTES ObjectAttributes;
-               UNICODE_STRING RegistryPath;
-               WCHAR *RegistryPathStr;
+      NDIS_DbgPrint(MAX_TRACE, ("Calling protocol's BindAdapter handler with DeviceName %wZ and RegistryPath %wZ\n",
+          &DeviceName, &RegistryPath));
 
-#define SERVICES_KEY L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
-#define LINKAGE_KEY  L"\\Linkage"
+      /* XXX SD must do something with bind context */
+      *NdisProtocolHandle = Protocol;
 
-               RegistryPathStr = ExAllocatePool(PagedPool, 
-                       sizeof(SERVICES_KEY) + ProtocolCharacteristics->Name.Length + sizeof(LINKAGE_KEY));
-               if(!RegistryPathStr)
-               {
-                       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_RESOURCES;
-                       return;
-               }
-
-               wcscpy(RegistryPathStr, SERVICES_KEY);
-               wcsncat(RegistryPathStr, ((WCHAR *)ProtocolCharacteristics->Name.Buffer),
-                               ProtocolCharacteristics->Name.Length / sizeof(WCHAR));
-               RegistryPathStr[wcslen(SERVICES_KEY)+ProtocolCharacteristics->Name.Length/sizeof(WCHAR)] = 0;
-               wcscat(RegistryPathStr, LINKAGE_KEY);
-
-               RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
-               NDIS_DbgPrint(MAX_TRACE, ("Opening configuration key: %wZ\n", &RegistryPath));
-
-               InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
-               NtStatus = ZwOpenKey(&DriverKeyHandle, KEY_READ, &ObjectAttributes);
-
-               ExFreePool(RegistryPathStr);
-
-               if(!NT_SUCCESS(NtStatus))
-               {
-                       NDIS_DbgPrint(MID_TRACE, ("Unable to open protocol configuration\n"));
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_FAILURE;
-                       return;
-               }
-       }
-
-       NDIS_DbgPrint(MAX_TRACE, ("Successfully opened the registry configuration\n"));
-
-       {
-               UNICODE_STRING ValueName;
-               ULONG ResultLength;
-
-               RtlInitUnicodeString(&ValueName, L"Bind");
-
-               NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, NULL, 0, &ResultLength);
-               if(NtStatus != STATUS_BUFFER_OVERFLOW && NtStatus != STATUS_BUFFER_TOO_SMALL)
-               {
-                       NDIS_DbgPrint(MID_TRACE, ("Unable to query the Bind value for size\n"));
-                       ZwClose(DriverKeyHandle);
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_FAILURE;
-                       return;
-               }
-
-               KeyInformation = ExAllocatePool(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength);
-               if(!KeyInformation)
-               {
-                       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
-                       ZwClose(DriverKeyHandle);
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_FAILURE;
-                       return;
-               }
-
-               NtStatus = ZwQueryValueKey(DriverKeyHandle, &ValueName, KeyValuePartialInformation, KeyInformation,
-                               sizeof(KEY_VALUE_PARTIAL_INFORMATION) + ResultLength, &ResultLength);
-
-               if(!NT_SUCCESS(NtStatus))
-               {
-                       NDIS_DbgPrint(MIN_TRACE, ("Unable to query the Bind value\n"));
-                       ZwClose(DriverKeyHandle);
-                       ExFreePool(KeyInformation);
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_FAILURE;
-                       return;
-               }
-       }
-
-       DataOffset = 0;
-       while((KeyInformation->Data)[DataOffset])
-       {
-               /* BindContext is for tracking pending binding operations */
-               VOID *BindContext = 0;
-               NDIS_STRING DeviceName;
-               NDIS_STRING RegistryPath;
-               WCHAR *RegistryPathStr = NULL;
-               ULONG PathLength = 0;
-
-               RtlInitUnicodeString(&DeviceName, (WCHAR *)KeyInformation->Data);       /* we know this is 0-term */
-
-               /*
-                * RegistryPath should be:
-                *     \Registry\Machine\System\CurrentControlSet\Services\Nic1\Parameters\Tcpip
-                *
-                *  This is constructed as follows:
-                *      SERVICES_KEY + extracted device name + Protocol name from characteristics 
-                */
-#define PARAMETERS_KEY L"\\Parameters\\"
-               
-               PathLength = sizeof(SERVICES_KEY) +                              /* \Registry\Machine\System\CurrentControlSet\Services\ */
-                       wcslen( ((WCHAR *)KeyInformation->Data)+8 ) * sizeof(WCHAR) + /* Adapter1  (extracted from \Device\Adapter1)          */
-                       sizeof(PARAMETERS_KEY) +                                      /* \Parameters\                                         */
-                       ProtocolCharacteristics->Name.Length;                         /* Tcpip                                                */
-
-               RegistryPathStr = ExAllocatePool(PagedPool, PathLength);
-               if(!RegistryPathStr)
-               {
-                       NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
-                       ExFreePool(KeyInformation);
-                       ExFreePool(Protocol);
-                       *Status = NDIS_STATUS_RESOURCES;
-                       return;
-               }
-
-               wcscpy(RegistryPathStr, SERVICES_KEY);
-               wcscat(RegistryPathStr, (((WCHAR *)(KeyInformation->Data)) +8 ));
-               wcscat(RegistryPathStr, PARAMETERS_KEY);
-               wcsncat(RegistryPathStr, ProtocolCharacteristics->Name.Buffer, ProtocolCharacteristics->Name.Length / sizeof(WCHAR) );
-
-               RegistryPathStr[PathLength/sizeof(WCHAR) - 1] = 0;
-
-               RtlInitUnicodeString(&RegistryPath, RegistryPathStr);
-
-               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 */
-               {
-                       BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
-                       if(BindHandler)
-                               BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
-                       else
-                               NDIS_DbgPrint(MID_TRACE, ("No protocol bind handler specified\n"));
-               }
-               /*
+        {
+          BIND_HANDLER BindHandler = ProtocolCharacteristics->BindAdapterHandler;
+          if(BindHandler)
+            BindHandler(Status, BindContext, &DeviceName, &RegistryPath, 0);
+          else
+            NDIS_DbgPrint(MID_TRACE, ("No protocol bind handler specified\n"));
+        }
+
+      /*
       (*(Protocol->Chars.BindAdapterHandler))(Status, BindContext, &DeviceName, &RegistryPath, 0);
-               */
-
-               if(*Status == NDIS_STATUS_SUCCESS)
-               {
-                        /* Put protocol binding struct on global list */
-                        ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
-               }
-               /*
-               else if(*Status != NDIS_STATUS_PENDING)
-               {
-                       // what to do here?
-               }
-               */
-
-               DataOffset += wcslen((WCHAR *)KeyInformation->Data);
-       }
-
-    *NdisProtocolHandle = Protocol;
-    *Status             = NDIS_STATUS_SUCCESS;
-}
+      */
+
+      if(*Status == NDIS_STATUS_SUCCESS)
+        {
+          /* Put protocol binding struct on global list */
+          ExInterlockedInsertTailList(&ProtocolListHead, &Protocol->ListEntry, &ProtocolListLock);
+        }
 
+      /*
+      else if(*Status != NDIS_STATUS_PENDING)
+        {
+          // what to do here?
+        }
+       */
+
+      DataOffset += wcslen((WCHAR *)KeyInformation->Data);
+    }
 
+  *Status             = NDIS_STATUS_SUCCESS;
+}
+
+\f
 /*
  * @implemented
  */
@@ -774,7 +880,7 @@ NdisRequest(
     *Status = ProRequest(NdisBindingHandle, NdisRequest);
 }
 
-
+\f
 /*
  * @implemented
  */
@@ -787,7 +893,7 @@ NdisReset(
     *Status = ProReset(NdisBindingHandle);
 }
 
-
+\f
 /*
  * @implemented
  */
@@ -808,7 +914,7 @@ NdisSend(
     *Status = ProSend(NdisBindingHandle, Packet);
 }
 
-
+\f
 /*
  * @implemented
  */
@@ -822,7 +928,7 @@ NdisSendPackets(
     ProSendPackets(NdisBindingHandle, PacketArray, NumberOfPackets);
 }
 
-
+\f
 /*
  * @implemented
  */
index aeaa136..a051400 100644 (file)
@@ -1,6 +1,21 @@
 Build instructions for NDIS library
 -----------------------------------
 
+ - Building of ndis is currently only supported with the mingw gcc compiler
+
+ - from this directory:
+    'make' to make the library
+    'make clean' to clean it
+
+ - from the top level reactos directory:
+    'make ndis'
+
+ - make must be run from the top level reactos directory to update the import
+   library, unless you manually update it
+
+-----------------------------
+All of the below is outdated.
+-----------------------------
 Building with Visual C++ and Windows NT DDK:
 
 Variables:
index f49daf7..c1b77af 100644 (file)
@@ -482,6 +482,7 @@ UINT ResizePacket(
 VOID DisplayIPPacket(
     PIP_PACKET IPPacket)
 {
+#if 0
     UINT i;
     PCHAR p;
     UINT Length;
@@ -527,6 +528,7 @@ VOID DisplayIPPacket(
         }
         DbgPrint("\n");
     }
+#endif
 }
 #endif /* DBG */
 
index 040f459..37e4500 100644 (file)
  *
  * rationale:  you're never going to use *this* ndis.h to build a driver for win9x.  You'll
  * use the MS ddk.  This assumption drammatically simplifies ndis.h.
+ *
+ * There have been lots of instances of stdcall/cdecl mismatches, particularly in the
+ * callback routines.  I have now nailed them all to STDCALL, which is what they ought to
+ * be.  If you cross-check with the ndis.h from the MS DDK, you'll note that the compiler
+ * is set to a default calling conveition of stdcall with the /Gz command-line switch.
+ * There are only a few functions that should actually be cdecl:
+ *  - DbgPrint()
+ *  - DbgPrintReturnControlC()
+ *  - NdisWriteErrorLogEntry()
+ *
+ *  All other functions declared in ndis.h should be stdcall.
+ *
+ *  TODO:
+ *      - finish sanitizing NDIS40 and NDIS50; think about NDIS51
+ *      - make sure everything is stdcall
  */
 
-// TODO:  finish sanitizing NDIS40 and NDIS50; think about NDIS51
-
 #ifndef __NDIS_H
 #define __NDIS_H
 
@@ -768,7 +781,7 @@ typedef struct _NDIS_PHYSICAL_ADDRESS_UNIT
 } NDIS_PHYSICAL_ADDRESS_UNIT, *PNDIS_PHYSICAL_ADDRESS_UNIT;
 
 
-typedef VOID (*ADAPTER_SHUTDOWN_HANDLER)(
+typedef VOID STDCALL (*ADAPTER_SHUTDOWN_HANDLER)(
     IN  PVOID   ShutdownContext);
 
 
@@ -990,21 +1003,21 @@ typedef enum _NET_DEVICE_POWER_STATE
 
 /* Call Manager */
 
-typedef NDIS_STATUS (*CO_CREATE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CO_CREATE_VC_HANDLER)(
     IN  NDIS_HANDLE     ProtocolAfContext,
     IN  NDIS_HANDLE     NdisVcHandle,
     OUT PNDIS_HANDLE    ProtocolVcContext);
 
-typedef NDIS_STATUS (*CO_DELETE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CO_DELETE_VC_HANDLER)(
     IN  NDIS_HANDLE ProtocolVcContext);
 
-typedef NDIS_STATUS (*CO_REQUEST_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CO_REQUEST_HANDLER)(
     IN  NDIS_HANDLE         ProtocolAfContext,
     IN  NDIS_HANDLE         ProtocolVcContext       OPTIONAL,
     IN  NDIS_HANDLE            ProtocolPartyContext    OPTIONAL,
     IN  OUT PNDIS_REQUEST   NdisRequest);
 
-typedef VOID (*CO_REQUEST_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CO_REQUEST_COMPLETE_HANDLER)(
     IN  NDIS_STATUS     Status,
     IN  NDIS_HANDLE     ProtocolAfContext       OPTIONAL,
     IN  NDIS_HANDLE     ProtocolVcContext       OPTIONAL,
@@ -1012,7 +1025,7 @@ typedef VOID (*CO_REQUEST_COMPLETE_HANDLER)(
     IN  PNDIS_REQUEST   NdisRequest);
 
 
-typedef NDIS_STATUS (*CM_OPEN_AF_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CM_OPEN_AF_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrBindingContext,
        IN      PCO_ADDRESS_FAMILY              AddressFamily,
        IN      NDIS_HANDLE                             NdisAfHandle,
@@ -1021,13 +1034,13 @@ typedef NDIS_STATUS (*CM_OPEN_AF_HANDLER)(
 
 typedef
 NDIS_STATUS
-(*CM_CLOSE_AF_HANDLER)(
+STDCALL (*CM_CLOSE_AF_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrAfContext
        );
 
 typedef
 NDIS_STATUS
-(*CM_REG_SAP_HANDLER)(
+STDCALL (*CM_REG_SAP_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrAfContext,
        IN      PCO_SAP                                 Sap,
        IN      NDIS_HANDLE                             NdisSapHandle,
@@ -1036,13 +1049,13 @@ NDIS_STATUS
 
 typedef
 NDIS_STATUS
-(*CM_DEREG_SAP_HANDLER)(
+STDCALL (*CM_DEREG_SAP_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrSapContext
        );
 
 typedef
 NDIS_STATUS
-(*CM_MAKE_CALL_HANDLER)(
+STDCALL (*CM_MAKE_CALL_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN OUT PCO_CALL_PARAMETERS      CallParameters,
        IN      NDIS_HANDLE                             NdisPartyHandle         OPTIONAL,
@@ -1051,7 +1064,7 @@ NDIS_STATUS
 
 typedef
 NDIS_STATUS
-(*CM_CLOSE_CALL_HANDLER)(
+STDCALL (*CM_CLOSE_CALL_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN      NDIS_HANDLE                             CallMgrPartyContext     OPTIONAL,
        IN      PVOID                                   CloseData                       OPTIONAL,
@@ -1060,7 +1073,7 @@ NDIS_STATUS
 
 typedef
 VOID
-(*CM_INCOMING_CALL_COMPLETE_HANDLER)(
+STDCALL (*CM_INCOMING_CALL_COMPLETE_HANDLER)(
        IN      NDIS_STATUS                             Status,
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN      PCO_CALL_PARAMETERS             CallParameters
@@ -1068,7 +1081,7 @@ VOID
 
 typedef
 NDIS_STATUS
-(*CM_ADD_PARTY_HANDLER)(
+STDCALL (*CM_ADD_PARTY_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN OUT PCO_CALL_PARAMETERS      CallParameters,
        IN      NDIS_HANDLE                             NdisPartyHandle,
@@ -1077,7 +1090,7 @@ NDIS_STATUS
 
 typedef
 NDIS_STATUS
-(*CM_DROP_PARTY_HANDLER)(
+STDCALL (*CM_DROP_PARTY_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrPartyContext,
        IN      PVOID                                   CloseData       OPTIONAL,
        IN      UINT                                    Size            OPTIONAL
@@ -1085,7 +1098,7 @@ NDIS_STATUS
 
 typedef
 VOID
-(*CM_ACTIVATE_VC_COMPLETE_HANDLER)(
+STDCALL (*CM_ACTIVATE_VC_COMPLETE_HANDLER)(
        IN      NDIS_STATUS                             Status,
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN      PCO_CALL_PARAMETERS             CallParameters
@@ -1093,14 +1106,14 @@ VOID
 
 typedef
 VOID
-(*CM_DEACTIVATE_VC_COMPLETE_HANDLER)(
+STDCALL (*CM_DEACTIVATE_VC_COMPLETE_HANDLER)(
        IN      NDIS_STATUS                             Status,
        IN      NDIS_HANDLE                             CallMgrVcContext
        );
 
 typedef
 NDIS_STATUS
-(*CM_MODIFY_CALL_QOS_HANDLER)(
+STDCALL (*CM_MODIFY_CALL_QOS_HANDLER)(
        IN      NDIS_HANDLE                             CallMgrVcContext,
        IN      PCO_CALL_PARAMETERS             CallParameters
        );
@@ -1135,73 +1148,73 @@ typedef struct _NDIS_CALL_MANAGER_CHARACTERISTICS
 
 /* Call Manager clients */
 
-typedef VOID (*CL_OPEN_AF_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_OPEN_AF_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolAfContext,
     IN  NDIS_HANDLE NdisAfHandle);
 
-typedef VOID (*CL_CLOSE_AF_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_CLOSE_AF_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolAfContext);
 
-typedef VOID (*CL_REG_SAP_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_REG_SAP_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolSapContext,
     IN  PCO_SAP     Sap,
     IN  NDIS_HANDLE NdisSapHandle);
 
-typedef VOID (*CL_DEREG_SAP_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_DEREG_SAP_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolSapContext);
 
-typedef VOID (*CL_MAKE_CALL_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_MAKE_CALL_COMPLETE_HANDLER)(
     IN  NDIS_STATUS         Status,
     IN  NDIS_HANDLE         ProtocolVcContext,
     IN  NDIS_HANDLE         NdisPartyHandle     OPTIONAL,
     IN  PCO_CALL_PARAMETERS CallParameters);
 
-typedef VOID (*CL_MODIFY_CALL_QOS_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_MODIFY_CALL_QOS_COMPLETE_HANDLER)(
     IN  NDIS_STATUS         Status,
     IN  NDIS_HANDLE         ProtocolVcContext,
     IN  PCO_CALL_PARAMETERS CallParameters);
 
-typedef VOID (*CL_CLOSE_CALL_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_CLOSE_CALL_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolVcContext,
     IN  NDIS_HANDLE ProtocolPartyContext    OPTIONAL);
 
-typedef VOID (*CL_ADD_PARTY_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_ADD_PARTY_COMPLETE_HANDLER)(
     IN  NDIS_STATUS         Status,
     IN  NDIS_HANDLE         ProtocolPartyContext,
     IN  NDIS_HANDLE         NdisPartyHandle,
     IN  PCO_CALL_PARAMETERS CallParameters);
 
-typedef VOID (*CL_DROP_PARTY_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CL_DROP_PARTY_COMPLETE_HANDLER)(
     IN  NDIS_STATUS Status,
     IN  NDIS_HANDLE ProtocolPartyContext);
 
-typedef NDIS_STATUS (*CL_INCOMING_CALL_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CL_INCOMING_CALL_HANDLER)(
     IN  NDIS_HANDLE             ProtocolSapContext,
     IN  NDIS_HANDLE             ProtocolVcContext,
     IN  OUT PCO_CALL_PARAMETERS CallParameters);
 
-typedef VOID (*CL_INCOMING_CALL_QOS_CHANGE_HANDLER)(
+typedef VOID STDCALL (*CL_INCOMING_CALL_QOS_CHANGE_HANDLER)(
     IN  NDIS_HANDLE         ProtocolVcContext,
     IN  PCO_CALL_PARAMETERS CallParameters);
 
-typedef VOID (*CL_INCOMING_CLOSE_CALL_HANDLER)(
+typedef VOID STDCALL (*CL_INCOMING_CLOSE_CALL_HANDLER)(
     IN  NDIS_STATUS CloseStatus,
     IN  NDIS_HANDLE ProtocolVcContext,
     IN  PVOID       CloseData   OPTIONAL,
     IN  UINT        Size        OPTIONAL);
 
-typedef VOID (*CL_INCOMING_DROP_PARTY_HANDLER)(
+typedef VOID STDCALL (*CL_INCOMING_DROP_PARTY_HANDLER)(
     IN  NDIS_STATUS DropStatus,
     IN  NDIS_HANDLE ProtocolPartyContext,
     IN  PVOID       CloseData   OPTIONAL,
     IN  UINT        Size        OPTIONAL);
 
-typedef VOID (*CL_CALL_CONNECTED_HANDLER)(
+typedef VOID STDCALL (*CL_CALL_CONNECTED_HANDLER)(
     IN  NDIS_HANDLE ProtocolVcContext);
 
 
@@ -1239,53 +1252,53 @@ typedef struct _NDIS_CLIENT_CHARACTERISTICS
 
 /* Prototypes for NDIS 3.0 protocol characteristics */
 
-typedef VOID (*OPEN_ADAPTER_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*OPEN_ADAPTER_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_STATUS     Status,
     IN  NDIS_STATUS     OpenErrorStatus);
 
-typedef VOID (*CLOSE_ADAPTER_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CLOSE_ADAPTER_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_STATUS     Status);
 
-typedef VOID (*RESET_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*RESET_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_STATUS     Status);
 
-typedef VOID (*REQUEST_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*REQUEST_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  PNDIS_REQUEST   NdisRequest,
     IN  NDIS_STATUS     Status);
 
-typedef VOID (*STATUS_HANDLER)(
+typedef VOID STDCALL (*STATUS_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_STATUS     GeneralStatus,
     IN  PVOID           StatusBuffer,
     IN  UINT            StatusBufferSize);
 
-typedef VOID (*STATUS_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*STATUS_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext);
 
-typedef VOID (*SEND_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*SEND_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  PNDIS_PACKET    Packet,
     IN  NDIS_STATUS     Status);
 
-typedef VOID (*WAN_SEND_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*WAN_SEND_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE         ProtocolBindingContext,
     IN  PNDIS_WAN_PACKET    Packet,
     IN  NDIS_STATUS         Status);
 
-typedef VOID (*TRANSFER_DATA_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*TRANSFER_DATA_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  PNDIS_PACKET    Packet,
     IN  NDIS_STATUS     Status,
     IN  UINT            BytesTransferred);
 
-typedef VOID (*WAN_TRANSFER_DATA_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*WAN_TRANSFER_DATA_COMPLETE_HANDLER)(
     VOID);
 
-typedef NDIS_STATUS (*RECEIVE_HANDLER)(
+typedef NDIS_STATUS STDCALL (*RECEIVE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_HANDLE     MacReceiveContext,
     IN  PVOID           HeaderBuffer,
@@ -1294,12 +1307,12 @@ typedef NDIS_STATUS (*RECEIVE_HANDLER)(
     IN  UINT            LookaheadBufferSize,
     IN  UINT            PacketSize);
 
-typedef NDIS_STATUS (*WAN_RECEIVE_HANDLER)(
+typedef NDIS_STATUS STDCALL (*WAN_RECEIVE_HANDLER)(
     IN  NDIS_HANDLE     NdisLinkHandle,
     IN  PUCHAR          Packet,
     IN  ULONG           PacketSize);
 
-typedef VOID (*RECEIVE_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*RECEIVE_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext);
 
 
@@ -1380,30 +1393,30 @@ typedef struct _NDIS30_PROTOCOL_CHARACTERISTICS_S
 
 /* Prototypes for NDIS 4.0 protocol characteristics */
 
-typedef INT (*RECEIVE_PACKET_HANDLER)(
+typedef INT STDCALL (*RECEIVE_PACKET_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  PNDIS_PACKET    Packet);
 
-typedef VOID (*BIND_HANDLER)(
+typedef VOID STDCALL (*BIND_HANDLER)(
     OUT PNDIS_STATUS    Status,
     IN  NDIS_HANDLE     BindContext,
     IN  PNDIS_STRING    DeviceName,
     IN  PVOID           SystemSpecific1,
     IN  PVOID           SystemSpecific2);
 
-typedef VOID (*UNBIND_HANDLER)(
+typedef VOID STDCALL (*UNBIND_HANDLER)(
     OUT PNDIS_STATUS    Status,
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_HANDLE     UnbindContext);
 
-typedef VOID (*TRANSLATE_HANDLER)(
+typedef VOID STDCALL (*TRANSLATE_HANDLER)(
     OUT PNDIS_STATUS    Status,
     IN  NDIS_HANDLE     ProtocolBindingContext,
     OUT PNET_PNP_ID     IdList,
     IN  ULONG           IdListLength,
     OUT PULONG          BytesReturned);
 
-typedef VOID (*UNLOAD_PROTOCOL_HANDLER)(
+typedef VOID STDCALL (*UNLOAD_PROTOCOL_HANDLER)(
     VOID);
 
 
@@ -1439,24 +1452,24 @@ typedef struct _NDIS40_PROTOCOL_CHARACTERISTICS_S
 
 #ifdef NDIS50
 
-typedef VOID (*CO_SEND_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*CO_SEND_COMPLETE_HANDLER)(
     IN  NDIS_STATUS     Status,
     IN  NDIS_HANDLE     ProtocolVcContext,
     IN  PNDIS_PACKET    Packet);
 
-typedef VOID (*CO_STATUS_HANDLER)(
+typedef VOID STDCALL (*CO_STATUS_HANDLER)(
     IN  NDIS_HANDLE ProtocolBindingContext,
     IN  NDIS_HANDLE ProtocolVcContext   OPTIONAL,
     IN  NDIS_STATUS GeneralStatus,
     IN  PVOID       StatusBuffer,
     IN  UINT        StatusBufferSize);
 
-typedef UINT (*CO_RECEIVE_PACKET_HANDLER)(
+typedef UINT STDCALL (*CO_RECEIVE_PACKET_HANDLER)(
     IN  NDIS_HANDLE     ProtocolBindingContext,
     IN  NDIS_HANDLE     ProtocolVcContext,
     IN  PNDIS_PACKET    Packet);
 
-typedef VOID (*CO_AF_REGISTER_NOTIFY_HANDLER)(
+typedef VOID STDCALL (*CO_AF_REGISTER_NOTIFY_HANDLER)(
     IN  NDIS_HANDLE         ProtocolBindingContext,
     IN  PCO_ADDRESS_FAMILY  AddressFamily);
 
@@ -3964,18 +3977,18 @@ typedef struct _NDIS30_MINIPORT_CHARACTERISTICS_S
 
 /* Extensions for NDIS 4.0 miniports */
 
-typedef VOID (*W_SEND_PACKETS_HANDLER)(
+typedef VOID STDCALL (*W_SEND_PACKETS_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterContext,
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets);
 
 #ifdef NDIS40
 
-typedef VOID (*W_RETURN_PACKET_HANDLER)(
+typedef VOID STDCALL (*W_RETURN_PACKET_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterContext,
     IN  PNDIS_PACKET    Packet);
 
-typedef VOID (*W_ALLOCATE_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*W_ALLOCATE_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE             MiniportAdapterContext,
     IN  PVOID                   VirtualAddress,
     IN  PNDIS_PHYSICAL_ADDRESS  PhysicalAddress,
@@ -4010,27 +4023,27 @@ typedef struct _NDIS40_MINIPORT_CHARACTERISTICS_S
 
 #ifdef NDIS50
 
-typedef NDIS_STATUS (*W_CO_CREATE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*W_CO_CREATE_VC_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterContext,
     IN  NDIS_HANDLE     NdisVcHandle,
     OUT PNDIS_HANDLE    MiniportVcContext);
 
-typedef NDIS_STATUS (*W_CO_DELETE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*W_CO_DELETE_VC_HANDLER)(
     IN  NDIS_HANDLE MiniportVcContext);
 
-typedef NDIS_STATUS (*W_CO_ACTIVATE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*W_CO_ACTIVATE_VC_HANDLER)(
     IN      NDIS_HANDLE         MiniportVcContext,
     IN OUT  PCO_CALL_PARAMETERS CallParameters);
 
-typedef NDIS_STATUS (*W_CO_DEACTIVATE_VC_HANDLER)(
+typedef NDIS_STATUS STDCALL (*W_CO_DEACTIVATE_VC_HANDLER)(
     IN  NDIS_HANDLE MiniportVcContext);
 
-typedef VOID (*W_CO_SEND_PACKETS_HANDLER)(
+typedef VOID STDCALL (*W_CO_SEND_PACKETS_HANDLER)(
     IN  NDIS_HANDLE     MiniportVcContext,
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets);
 
-typedef NDIS_STATUS (*W_CO_REQUEST_HANDLER)(
+typedef NDIS_STATUS STDCALL (*W_CO_REQUEST_HANDLER)(
     IN      NDIS_HANDLE     MiniportAdapterContext,
     IN      NDIS_HANDLE     MiniportVcContext   OPTIONAL,
     IN OUT  PNDIS_REQUEST   NdisRequest);
@@ -4089,11 +4102,11 @@ typedef NDIS_MINIPORT_CHARACTERISTICS *PNDIS_MINIPORT_CHARACTERISTICS;
 
 
 
-typedef NDIS_STATUS (*SEND_HANDLER)(
+typedef NDIS_STATUS STDCALL (*SEND_HANDLER)(
     IN  NDIS_HANDLE     MacBindingHandle,
     IN  PNDIS_PACKET    Packet);
 
-typedef NDIS_STATUS (*TRANSFER_DATA_HANDLER)(
+typedef NDIS_STATUS STDCALL (*TRANSFER_DATA_HANDLER)(
     IN  NDIS_HANDLE     MacBindingHandle,
     IN  NDIS_HANDLE     MacReceiveContext,
     IN  UINT            ByteOffset,
@@ -4101,10 +4114,10 @@ typedef NDIS_STATUS (*TRANSFER_DATA_HANDLER)(
     OUT PNDIS_PACKET    Packet,
     OUT PUINT           BytesTransferred);
 
-typedef NDIS_STATUS (*RESET_HANDLER)(
+typedef NDIS_STATUS STDCALL (*RESET_HANDLER)(
     IN  NDIS_HANDLE MacBindingHandle);
 
-typedef NDIS_STATUS (*REQUEST_HANDLER)(
+typedef NDIS_STATUS STDCALL (*REQUEST_HANDLER)(
     IN  NDIS_HANDLE     MacBindingHandle,
     IN  PNDIS_REQUEST   NdisRequest);
 
@@ -4167,7 +4180,7 @@ typedef struct _NDIS_ADAPTER_INFORMATION
 
 /* Prototypes for NDIS_MAC_CHARACTERISTICS */
 
-typedef NDIS_STATUS (*OPEN_ADAPTER_HANDLER)(
+typedef NDIS_STATUS STDCALL (*OPEN_ADAPTER_HANDLER)(
     OUT PNDIS_STATUS    OpenErrorStatus,
     OUT NDIS_HANDLE *   MacBindingHandle,
     OUT PUINT           SelectedMediumIndex,
@@ -4178,25 +4191,25 @@ typedef NDIS_STATUS (*OPEN_ADAPTER_HANDLER)(
     IN  UINT            OpenOptions,
     IN  PSTRING         AddressingInformation OPTIONAL);
 
-typedef NDIS_STATUS (*CLOSE_ADAPTER_HANDLER)(
+typedef NDIS_STATUS STDCALL (*CLOSE_ADAPTER_HANDLER)(
     IN  NDIS_HANDLE MacBindingHandle);
 
-typedef NDIS_STATUS (*WAN_TRANSFER_DATA_HANDLER)(
+typedef NDIS_STATUS STDCALL (*WAN_TRANSFER_DATA_HANDLER)(
     VOID);
 
-typedef NDIS_STATUS (*QUERY_GLOBAL_STATISTICS_HANDLER)(
+typedef NDIS_STATUS STDCALL (*QUERY_GLOBAL_STATISTICS_HANDLER)(
     IN  NDIS_HANDLE     MacAdapterContext,
     IN  PNDIS_REQUEST   NdisRequest);
 
-typedef VOID (*UNLOAD_MAC_HANDLER)(
+typedef VOID STDCALL (*UNLOAD_MAC_HANDLER)(
     IN  NDIS_HANDLE MacMacContext);
 
-typedef NDIS_STATUS (*ADD_ADAPTER_HANDLER)(
+typedef NDIS_STATUS STDCALL (*ADD_ADAPTER_HANDLER)(
     IN  NDIS_HANDLE     MacMacContext,
     IN  NDIS_HANDLE     WrapperConfigurationContext,
     IN  PNDIS_STRING    AdapterName);
 
-typedef VOID (*REMOVE_ADAPTER_HANDLER)(
+typedef VOID STDCALL (*REMOVE_ADAPTER_HANDLER)(
     IN  NDIS_HANDLE MacAdapterContext);
 
 typedef struct _NDIS_MAC_CHARACTERISTICS
@@ -4424,10 +4437,10 @@ typedef struct _FILTERDBS
 } FILTERDBS, *PFILTERDBS;
 
 
-typedef VOID (*ETH_RCV_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*ETH_RCV_COMPLETE_HANDLER)(
     IN  PETH_FILTER Filter);
 
-typedef VOID (*ETH_RCV_INDICATE_HANDLER)(
+typedef VOID STDCALL (*ETH_RCV_INDICATE_HANDLER)(
     IN  PETH_FILTER Filter,
     IN  NDIS_HANDLE MacReceiveContext,
     IN  PCHAR       Address,
@@ -4437,10 +4450,10 @@ typedef VOID (*ETH_RCV_INDICATE_HANDLER)(
     IN  UINT        LookaheadBufferSize,
     IN  UINT        PacketSize);
 
-typedef VOID (*FDDI_RCV_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*FDDI_RCV_COMPLETE_HANDLER)(
     IN  PFDDI_FILTER    Filter);
 
-typedef VOID (*FDDI_RCV_INDICATE_HANDLER)(
+typedef VOID STDCALL (*FDDI_RCV_INDICATE_HANDLER)(
     IN  PFDDI_FILTER    Filter,
     IN  NDIS_HANDLE     MacReceiveContext,
     IN  PCHAR           Address,
@@ -4451,15 +4464,15 @@ typedef VOID (*FDDI_RCV_INDICATE_HANDLER)(
     IN  UINT            LookaheadBufferSize,
     IN  UINT            PacketSize);
 
-typedef VOID STDCALL (*FILTER_PACKET_INDICATION_HANDLER)(
+typedef VOID STDCALL STDCALL (*FILTER_PACKET_INDICATION_HANDLER)(
     IN  NDIS_HANDLE     Miniport,
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets);
 
-typedef VOID (*TR_RCV_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*TR_RCV_COMPLETE_HANDLER)(
     IN  PTR_FILTER  Filter);
 
-typedef VOID (*TR_RCV_INDICATE_HANDLER)(
+typedef VOID STDCALL (*TR_RCV_INDICATE_HANDLER)(
     IN  PTR_FILTER  Filter,
     IN  NDIS_HANDLE MacReceiveContext,
     IN  PVOID       HeaderBuffer,
@@ -4468,11 +4481,11 @@ typedef VOID (*TR_RCV_INDICATE_HANDLER)(
     IN  UINT        LookaheadBufferSize,
     IN  UINT        PacketSize);
 
-typedef VOID (*WAN_RCV_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*WAN_RCV_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  NDIS_HANDLE NdisLinkContext);
 
-typedef VOID (*WAN_RCV_HANDLER)(
+typedef VOID STDCALL (*WAN_RCV_HANDLER)(
     OUT PNDIS_STATUS    Status,
     IN  NDIS_HANDLE     MiniportAdapterHandle,
     IN  NDIS_HANDLE     NdisLinkContext,
@@ -4497,42 +4510,42 @@ typedef NDIS_STATUS (FASTCALL *NDIS_M_QUEUE_WORK_ITEM)(
     IN  NDIS_WORK_ITEM_TYPE     WorkItemType,
     IN  PVOID                   WorkItemContext);
 
-typedef VOID (*NDIS_M_REQ_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_REQ_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  NDIS_STATUS Status);
 
-typedef VOID (*NDIS_M_RESET_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_RESET_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  NDIS_STATUS Status,
     IN  BOOLEAN AddressingReset);
 
-typedef VOID (*NDIS_M_SEND_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_SEND_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
     IN  PNDIS_PACKET    Packet,
     IN  NDIS_STATUS     Status);
 
-typedef VOID (*NDIS_M_SEND_RESOURCES_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_SEND_RESOURCES_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle);
 
 typedef BOOLEAN (FASTCALL *NDIS_M_START_SENDS)(
     IN  PNDIS_MINIPORT_BLOCK    Miniport);
 
-typedef VOID (*NDIS_M_STATUS_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_STATUS_HANDLER)(
     IN  NDIS_HANDLE MiniportHandle,
     IN  NDIS_STATUS GeneralStatus,
     IN  PVOID       StatusBuffer,
     IN  UINT        StatusBufferSize);
 
-typedef VOID (*NDIS_M_STS_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_STS_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle);
 
-typedef VOID (*NDIS_M_TD_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_M_TD_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterHandle,
     IN  PNDIS_PACKET    Packet,
     IN  NDIS_STATUS     Status,
     IN  UINT            BytesTransferred);
 
-typedef VOID (*NDIS_WM_SEND_COMPLETE_HANDLER)(
+typedef VOID STDCALL (*NDIS_WM_SEND_COMPLETE_HANDLER)(
     IN  NDIS_HANDLE MiniportAdapterHandle,
     IN  PVOID       Packet,
     IN  NDIS_STATUS Status);
@@ -4805,14 +4818,14 @@ struct _NDIS_MINIPORT_BLOCK
 
 /* Handler prototypes for NDIS_OPEN_BLOCK */
 
-typedef NDIS_STATUS (*WAN_SEND_HANDLER)(
+typedef NDIS_STATUS STDCALL (*WAN_SEND_HANDLER)(
     IN  NDIS_HANDLE MacBindingHandle,
     IN  NDIS_HANDLE LinkHandle,
     IN  PVOID       Packet);
 
 /* NDIS 4.0 extension */
 
-typedef VOID (*SEND_PACKETS_HANDLER)(
+typedef VOID STDCALL (*SEND_PACKETS_HANDLER)(
     IN  NDIS_HANDLE     MiniportAdapterContext,
     IN  PPNDIS_PACKET   PacketArray,
     IN  UINT            NumberOfPackets);