OpenCBM
nt4/PortEnum.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2004 Spiro Trikaliotis
8  *
9  */
10 
19 #include <initguid.h>
20 #include <ntddk.h>
21 
22 #define PENUMERATE_DEFINED
23 typedef struct ENUMERATE_NT4 *PENUMERATE;
24 #include "cbm_driver.h"
25 
26 #undef ExFreePool
27 
32 typedef
33 struct ENUMERATE_NT4
34 {
36  UNICODE_STRING DriverPrefix;
37 
39  UNICODE_STRING DriverNumber;
40 
42  UNICODE_STRING CompleteDriverName;
43 
45  ULONG Count;
46 
48  ULONG MaxCount;
49 
51 
52 
73 NTSTATUS
74 ParPortEnumerateOpen(PENUMERATE *EnumStruct)
75 {
76  PENUMERATE enumStruct;
77  NTSTATUS ntStatus;
78 
79  FUNC_ENTER();
80 
81  // Allocate memory for the enumStruct
82 
83  DBG_IRQL( < DISPATCH_LEVEL);
84  enumStruct = ExAllocatePoolWithTag(PagedPool,
85  sizeof(ENUMERATE), MTAG_SENUMERATE);
86 
87  if (enumStruct)
88  {
89  // Zero the complete enumStruct
90 
91  RtlZeroMemory(enumStruct, sizeof(*enumStruct));
92 
93  enumStruct->Count = 0;
94 
95  // Get the maximum number of parallel port devices
96 
97  DBG_IRQL( == PASSIVE_LEVEL);
98  enumStruct->MaxCount = IoGetConfigurationInformation()->ParallelCount;
99 
100  // If the maximum number is bigger than 999, we have a severe problem...
101  // Who would put more than 999 parallel ports into one machine?
102  // Anyway, make sure we have no problems with this.
103 
104  if (enumStruct->MaxCount > 999)
105  {
106  DBG_WARN((DBG_PREFIX "IoGetConfigurationInformation()->ParallelCount "
107  "returned %u, truncating to 999", enumStruct->MaxCount));
108 
109  enumStruct->MaxCount = 999;
110  }
111 
112  // prepare the strings for later usage
113 
114  DBG_IRQL( <= DISPATCH_LEVEL);
115  RtlInitUnicodeString(&enumStruct->DriverPrefix, L"\\Device\\" DD_PARALLEL_PORT_BASE_NAME_U);
116 
117  // Allocate memory for storing the number
118  // Assume the number is < 999, that is, not more than 3 digits big
119  // If it is bigger, make the numbers 3 and 4 greater
120  // The length has to be set here because the allocation for
121  // enumStruct->CompleteDriverName below depends upon the length!
122 
123  enumStruct->DriverNumber.Length = 3*sizeof(wchar_t);
124  enumStruct->DriverNumber.MaximumLength = 4*sizeof(wchar_t);
125  enumStruct->DriverNumber.Buffer = ExAllocatePoolWithTag(PagedPool,
126  enumStruct->DriverNumber.MaximumLength, MTAG_SENUMERATE);
127 
128  // allocate memory for the complete name
129 
130  enumStruct->CompleteDriverName.Length = 0;
131  enumStruct->CompleteDriverName.MaximumLength =
132  enumStruct->DriverPrefix.Length + enumStruct->DriverNumber.Length;
133 
134  enumStruct->CompleteDriverName.Buffer = ExAllocatePoolWithTag(PagedPool,
135  enumStruct->CompleteDriverName.MaximumLength, MTAG_SENUMERATE);
136 
137  // Test if both above allocations were successfull:
138 
139  if (enumStruct->DriverNumber.Buffer != NULL
140  && enumStruct->CompleteDriverName.Buffer != NULL)
141  {
142  ntStatus = STATUS_SUCCESS;
143  }
144  else
145  {
146  // We have not had luck with allocating both strings,
147  // thus, return an appropriate error value
148 
149  ntStatus = STATUS_INSUFFICIENT_RESOURCES;
150 
151  // Free all resources that have been successfully allocated
152 
153  ParPortEnumerateClose(enumStruct);
154 
155  // return that there was no enumStruct allocated
156 
157  enumStruct = NULL;
158  }
159  }
160  else
161  {
162  ntStatus = STATUS_INSUFFICIENT_RESOURCES;
163  }
164 
165  // return the enumStruct to the caller
166 
167  *EnumStruct = enumStruct;
168 
169  FUNC_LEAVE_NTSTATUS(ntStatus);
170 }
171 
195 NTSTATUS
196 ParPortEnumerate(PENUMERATE EnumStruct, PCWSTR *DriverName)
197 {
198  NTSTATUS ntStatus;
199  PCWSTR retDriver;
200 
201  FUNC_ENTER();
202 
203  DBG_ASSERT(EnumStruct != NULL);
204  DBG_ASSERT(EnumStruct->Count < 1000);
205 
206  retDriver = NULL;
207 
208  // Assume: There are no more entries available
209 
210  ntStatus = STATUS_NO_MORE_ENTRIES;
211 
212  if (EnumStruct->Count < EnumStruct->MaxCount)
213  {
214  // Counvert EnumStruct->Count to a UNICODE_STRING
215 
216  DBG_IRQL( == PASSIVE_LEVEL);
217  ntStatus = RtlIntegerToUnicodeString(EnumStruct->Count, 10,
218  &EnumStruct->DriverNumber);
219 
220  if (NT_SUCCESS(ntStatus))
221  {
222  // Copy the parts to form the full name:
223 
224  DBG_IRQL( < DISPATCH_LEVEL);
225  RtlCopyUnicodeString(&EnumStruct->CompleteDriverName, &EnumStruct->DriverPrefix);
226  RtlAppendUnicodeStringToString(&EnumStruct->CompleteDriverName, &EnumStruct->DriverNumber);
227 
228  retDriver = EnumStruct->CompleteDriverName.Buffer;
229 
230  // advance to the next driver
231 
232  ++EnumStruct->Count;
233  }
234  }
235  else
236  {
237  // we are after the last entry: return empty string
238 
239  EnumStruct->CompleteDriverName.Buffer[0] = 0;
240  retDriver = EnumStruct->CompleteDriverName.Buffer;
241  }
242 
243  *DriverName = retDriver;
244 
245  FUNC_LEAVE_NTSTATUS(ntStatus);
246 }
247 
263 VOID
264 ParPortEnumerateClose(PENUMERATE EnumStruct)
265 {
266  FUNC_ENTER();
267 
268  DBG_ASSERT(EnumStruct != NULL);
269 
270  DBG_IRQL( == PASSIVE_LEVEL);
271 
272  // Free the DriverNumber buffer, if that was allocated
273 
274  if (EnumStruct->DriverNumber.Buffer != NULL)
275  {
276  DBG_IRQL( < DISPATCH_LEVEL);
277  ExFreePool(EnumStruct->DriverNumber.Buffer);
278  }
279 
280  // Free the CompleteDriverName buffer, if that was allocated
281 
282  if (EnumStruct->CompleteDriverName.Buffer != NULL)
283  {
284  DBG_IRQL( < DISPATCH_LEVEL);
285  ExFreePool(EnumStruct->CompleteDriverName.Buffer);
286  }
287 
288  // Free the EnumStruct
289 
290  DBG_IRQL( < DISPATCH_LEVEL);
291  ExFreePool(EnumStruct);
292 
293  FUNC_LEAVE();
294 }
295 
302 NTSTATUS
303 CbmOpenDeviceRegistryKey(IN PDEVICE_OBJECT a, IN ULONG b, IN ACCESS_MASK c, OUT PHANDLE d)
304 {
305  FUNC_ENTER();
306 
307  DBG_ASSERT(1==0);
308 
309  FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
310 }
#define DBG_WARN(_xxx)
Definition: debug.h:395
NTSTATUS ParPortEnumerate(PENUMERATE EnumStruct, PCWSTR *DriverName)
Get next enumerated parallel port driver.
Definition: nt4/PortEnum.c:196
ULONG MaxCount
The maximum number which the functions might return.
Definition: nt4/PortEnum.c:48
ULONG Count
The actual number which the functions just returned.
Definition: nt4/PortEnum.c:45
NTSTATUS ParPortEnumerateOpen(PENUMERATE *EnumStruct)
Start enumeration of the parallel port drivers.
Definition: nt4/PortEnum.c:74
#define FUNC_LEAVE()
Definition: debug.h:349
NTSTATUS CbmOpenDeviceRegistryKey(IN PDEVICE_OBJECT a, IN ULONG b, IN ACCESS_MASK c, OUT PHANDLE d)
Stub for a function.
Definition: nt4/PortEnum.c:303
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
struct ENUMERATE_NT4 * PENUMERATE
pointer to a ENUMERATE_WDM or ENUMERATE_NT4 struct
Definition: nt4/PortEnum.c:23
#define FUNC_ENTER()
Definition: debug.h:347
#define DBG_PREFIX
Definition: debug.h:320
UNICODE_STRING DriverPrefix
Prefix of the device names to be returned.
Definition: nt4/PortEnum.c:36
VOID ParPortEnumerateClose(PENUMERATE EnumStruct)
Stop enumeration of the parallel port drivers.
Definition: nt4/PortEnum.c:264
UNICODE_STRING DriverNumber
Memory for the number in the device names.
Definition: nt4/PortEnum.c:39
#define MTAG_SENUMERATE
Definition: memtags.h:29
struct ENUMERATE_NT4 ENUMERATE
UNICODE_STRING CompleteDriverName
The complete driver name which will be returned.
Definition: nt4/PortEnum.c:42