xref: /reactos/drivers/network/ndisuio/misc.c (revision 34593d93)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS NDIS User I/O driver
4  * FILE:        misc.c
5  * PURPOSE:     Helper functions
6  * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
7  */
8 
9 #include "ndisuio.h"
10 
11 #define NDEBUG
12 #include <debug.h>
13 
14 NDIS_STATUS
AllocateAndChainBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,PNDIS_PACKET Packet,PVOID Buffer,ULONG BufferSize,BOOLEAN Front)15 AllocateAndChainBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
16                        PNDIS_PACKET Packet,
17                        PVOID Buffer,
18                        ULONG BufferSize,
19                        BOOLEAN Front)
20 {
21     NDIS_STATUS Status;
22     PNDIS_BUFFER NdisBuffer;
23 
24     /* Allocate the NDIS buffer mapping the pool */
25     NdisAllocateBuffer(&Status,
26                        &NdisBuffer,
27                        AdapterContext->BufferPoolHandle,
28                        Buffer,
29                        BufferSize);
30     if (Status != NDIS_STATUS_SUCCESS)
31     {
32         DPRINT1("No free buffer descriptors\n");
33         return Status;
34     }
35 
36     if (Front)
37     {
38         /* Chain the buffer to front */
39         NdisChainBufferAtFront(Packet, NdisBuffer);
40     }
41     else
42     {
43         /* Chain the buffer to back */
44         NdisChainBufferAtBack(Packet, NdisBuffer);
45     }
46 
47     /* Return success */
48     return NDIS_STATUS_SUCCESS;
49 }
50 
51 PNDIS_PACKET
CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,PVOID Buffer,ULONG BufferSize)52 CreatePacketFromPoolBuffer(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
53                            PVOID Buffer,
54                            ULONG BufferSize)
55 {
56     PNDIS_PACKET Packet;
57     NDIS_STATUS Status;
58 
59     /* Allocate a packet descriptor */
60     NdisAllocatePacket(&Status,
61                        &Packet,
62                        AdapterContext->PacketPoolHandle);
63     if (Status != NDIS_STATUS_SUCCESS)
64     {
65         DPRINT1("No free packet descriptors\n");
66         return NULL;
67     }
68 
69     /* Use the helper to chain the buffer */
70     Status = AllocateAndChainBuffer(AdapterContext, Packet,
71                                     Buffer, BufferSize, TRUE);
72     if (Status != NDIS_STATUS_SUCCESS)
73     {
74         NdisFreePacket(Packet);
75         return NULL;
76     }
77 
78     /* Return the packet */
79     return Packet;
80 }
81 
82 VOID
CleanupAndFreePacket(PNDIS_PACKET Packet,BOOLEAN FreePool)83 CleanupAndFreePacket(PNDIS_PACKET Packet, BOOLEAN FreePool)
84 {
85     PNDIS_BUFFER Buffer;
86     PVOID Data;
87     ULONG Length;
88 
89     /* Free each buffer and its backing pool memory */
90     while (TRUE)
91     {
92         /* Unchain each buffer */
93         NdisUnchainBufferAtFront(Packet, &Buffer);
94         if (!Buffer)
95             break;
96 
97         /* Get the backing memory */
98         NdisQueryBuffer(Buffer, &Data, &Length);
99 
100         /* Free the buffer */
101         NdisFreeBuffer(Buffer);
102 
103         if (FreePool)
104         {
105             /* Free the backing memory */
106             ExFreePool(Data);
107         }
108     }
109 
110     /* Free the packet descriptor */
111     NdisFreePacket(Packet);
112 }
113 
114 PNDISUIO_ADAPTER_CONTEXT
FindAdapterContextByName(PNDIS_STRING DeviceName)115 FindAdapterContextByName(PNDIS_STRING DeviceName)
116 {
117     KIRQL OldIrql;
118     PLIST_ENTRY CurrentEntry;
119     PNDISUIO_ADAPTER_CONTEXT AdapterContext;
120 
121     KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
122     CurrentEntry = GlobalAdapterList.Flink;
123     while (CurrentEntry != &GlobalAdapterList)
124     {
125         AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry);
126 
127         /* Check if the device name matches */
128         if (RtlEqualUnicodeString(&AdapterContext->DeviceName, DeviceName, TRUE))
129         {
130             KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
131             return AdapterContext;
132         }
133 
134         CurrentEntry = CurrentEntry->Flink;
135     }
136     KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
137 
138     return NULL;
139 }
140 
141 VOID
ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)142 ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
143 {
144     /* Increment the open count */
145     AdapterContext->OpenCount++;
146 }
147 
148 VOID
DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext,PNDISUIO_OPEN_ENTRY OpenEntry)149 DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext,
150                                        PNDISUIO_OPEN_ENTRY OpenEntry)
151 {
152     KIRQL OldIrql;
153 
154     /* Lock the adapter context */
155     KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
156 
157     /* Decrement the open count */
158     AdapterContext->OpenCount--;
159 
160     /* Cleanup the open entry if we were given one */
161     if (OpenEntry != NULL)
162     {
163         /* Remove the open entry */
164         RemoveEntryList(&OpenEntry->ListEntry);
165 
166         /* Invalidate the FO */
167         OpenEntry->FileObject->FsContext = NULL;
168         OpenEntry->FileObject->FsContext2 = NULL;
169 
170         /* Free the open entry */
171         ExFreePool(OpenEntry);
172     }
173 
174     /* Release the adapter context lock */
175     KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
176 }
177