OpenCBM
util-reg.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 <wdm.h>
20 #include "cbm_driver.h"
21 
42 NTSTATUS
43 cbm_registry_open_for_read(OUT PHANDLE HandleKey, IN PUNICODE_STRING Path)
44 {
45  OBJECT_ATTRIBUTES objectAttributes;
46 
47  NTSTATUS ntStatus;
48 
49  FUNC_ENTER();
50 
51  FUNC_PARAM((DBG_PREFIX "'%wZ'", Path));
52 
53  // Initialize the object attributes for the registry key
54 
55  DBG_IRQL( == PASSIVE_LEVEL); //+< according to NT4 DDK; later ones do not have this restriction!
56  InitializeObjectAttributes(&objectAttributes,
57  Path, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
58 
59  // Now, open the registry key
60 
61  DBG_IRQL( == PASSIVE_LEVEL);
62  ntStatus = ZwOpenKey(HandleKey, KEY_READ, &objectAttributes);
63 
64  FUNC_LEAVE_NTSTATUS(ntStatus);
65 }
66 
94 NTSTATUS
95 cbm_registry_open_hardwarekey(OUT PHANDLE HandleKey, OUT PDEVICE_OBJECT *Pdo,
96  IN PDEVICE_EXTENSION Pdx)
97 {
98  IO_STATUS_BLOCK ioStatusBlock;
99  NTSTATUS ntStatus;
100  KEVENT event;
101  PIRP irp;
102 
103  FUNC_ENTER();
104 
105  // Initialize the event which might be needed for waiting for completion
106 
107  // no IRQL restrictions apply
108  KeInitializeEvent(&event, NotificationEvent, FALSE);
109 
110  // first of all, build an IRP with IRP_MJ_PNP/IRP_MN_QUERY_DEVICE_RELATIONS
111 
112  DBG_IRQL( == PASSIVE_LEVEL);
113  irp = IoBuildSynchronousFsdRequest(
114  IRP_MJ_PNP,
115  Pdx->ParallelPortFdo,
116  NULL,
117  0,
118  NULL,
119  &event,
120  &ioStatusBlock);
121 
122  if (!irp)
123  {
124  // Acquiring the IRP failed, report this back to the caller
125 
126  ntStatus = STATUS_INSUFFICIENT_RESOURCES;
127  }
128  else
129  {
130  PIO_STACK_LOCATION irpSp;
131 
132  // set up some values for the called driver
133 
134  // We need to write the first IRP stack location, thus, get
135  // it. On a new IRP, this means we want to write the "next"
136  // stack location.
137 
138  DBG_IRQL( <= DISPATCH_LEVEL);
139  irpSp = IoGetNextIrpStackLocation(irp);
140 
141  if (irpSp)
142  {
143  // Find the PDO of the parallel port driver
144 
145  irpSp->MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
146  irpSp->Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
147  irpSp->FileObject = Pdx->ParallelPortFileObject;
148 
149  // call the driver to get the handle for the hardware registry key
150 
151  DBG_IRQL( <= DISPATCH_LEVEL);
152  ntStatus = IoCallDriver(Pdx->ParallelPortFdo, irp);
153  }
154  else
155  {
156  // Well... We could allocate an IRP, but we could not
157  // get the appropriate stack location? Can this ever happen?
158  // I doubt it, but to be sure, mark it as an error
159 
160  ntStatus = STATUS_INSUFFICIENT_RESOURCES;
161  }
162 
163  // If the called driver pended this IRP, wait for the completion
164 
165  if (ntStatus == STATUS_PENDING)
166  {
167  DBG_IRQL( < DISPATCH_LEVEL);
168  KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
169  }
170 
171  if (NT_SUCCESS(ntStatus))
172  {
173  PDEVICE_RELATIONS deviceRelations;
174  PDEVICE_OBJECT pdo;
175 
176  // use deviceRelations for better readability
177 
178  deviceRelations = (PDEVICE_RELATIONS) ioStatusBlock.Information;
179  DBG_ASSERT(deviceRelations);
180 
181  if (deviceRelations)
182  {
183  // take the pdo out of the return value
184 
185  pdo = deviceRelations->Objects[0];
186 
187  // get a registry handle for the hardware key of the parallel port
188 
189  DBG_IRQL( == PASSIVE_LEVEL);
190  ntStatus = CbmOpenDeviceRegistryKey(
191  pdo,
192  PLUGPLAY_REGKEY_DEVICE,
193  KEY_ALL_ACCESS,
194  HandleKey);
195 
196  // give the pdo back to the caller, so that it can be dereferenced when it
197  // is not longer needed
198 
199  *Pdo = pdo;
200 
201  // free the memory which is no longer needed
202 
203  DBG_IRQL( < DISPATCH_LEVEL);
204  ExFreePool(deviceRelations);
205  }
206  }
207  }
208 
209 
210  FUNC_LEAVE_NTSTATUS(ntStatus);
211 }
212 
229 NTSTATUS
230 cbm_registry_close(IN HANDLE HandleKey)
231 {
232  NTSTATUS ntStatus;
233 
234  FUNC_ENTER();
235 
236  // Close the registry key
237 
238  DBG_IRQL( == PASSIVE_LEVEL);
239  ntStatus = ZwClose(HandleKey);
240 
241  FUNC_LEAVE_NTSTATUS(ntStatus);
242 }
243 
259 NTSTATUS
260 cbm_registry_close_hardwarekey(IN HANDLE HandleKey, IN PDEVICE_OBJECT Pdo)
261 {
262  NTSTATUS ntStatus;
263 
264  FUNC_ENTER();
265 
266  // First of all, close the registry key
267 
268  ntStatus = cbm_registry_close(HandleKey);
269 
270  // Dereference the pdo, as we do not need it anymore.
271 
272  DBG_IRQL( <= DISPATCH_LEVEL);
273  ObDereferenceObject(Pdo);
274 
275  FUNC_LEAVE_NTSTATUS(ntStatus);
276 }
277 
298 NTSTATUS
299 cbm_registry_read_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, OUT PULONG Value)
300 {
301  PKEY_VALUE_PARTIAL_INFORMATION p;
302  UNICODE_STRING keyNameUnicode;
303  NTSTATUS ntStatus;
304  ULONG retValueSize;
305  CHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG)];
306 
307  FUNC_ENTER();
308 
309  FUNC_PARAM((DBG_PREFIX "'%ws'", KeyName));
310 
311  p = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
312 
313  RtlInitUnicodeString(&keyNameUnicode, KeyName);
314 
315  ntStatus = ZwQueryValueKey(HandleKey, &keyNameUnicode,
316  KeyValuePartialInformation,
317  buffer, sizeof(buffer), &retValueSize);
318 
319  if (NT_SUCCESS(ntStatus))
320  {
321  if (p->Type == REG_DWORD && p->DataLength == sizeof(ULONG))
322  {
323  ULONG retValue = *((PULONG) &p->Data);
324 
325  FUNC_PARAM((DBG_PREFIX "Return-Value: %08x", retValue));
326 
327  if (Value)
328  {
329  *Value = retValue;
330  }
331  }
332  }
333 
334  FUNC_LEAVE_NTSTATUS(ntStatus);
335 }
336 
355 NTSTATUS
356 cbm_registry_write_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, IN ULONG Value)
357 {
358  PKEY_VALUE_PARTIAL_INFORMATION p;
359  UNICODE_STRING keyNameUnicode;
360  NTSTATUS ntStatus;
361  ULONG retValueSize;
362  CHAR buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)+sizeof(ULONG)];
363 
364  FUNC_ENTER();
365 
366  FUNC_PARAM((DBG_PREFIX "'%ws'", KeyName));
367 
368  p = (PKEY_VALUE_PARTIAL_INFORMATION) buffer;
369 
370  RtlInitUnicodeString(&keyNameUnicode, KeyName);
371 
372  ntStatus = ZwSetValueKey(HandleKey, &keyNameUnicode,
373  0, REG_DWORD, &Value, sizeof(Value));
374 
375  FUNC_LEAVE_NTSTATUS(ntStatus);
376 }
NTSTATUS cbm_registry_close_hardwarekey(IN HANDLE HandleKey, IN PDEVICE_OBJECT Pdo)
Close a hardware registry key.
Definition: util-reg.c:260
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
NTSTATUS cbm_registry_open_hardwarekey(OUT PHANDLE HandleKey, OUT PDEVICE_OBJECT *Pdo, IN PDEVICE_EXTENSION Pdx)
Open the hardware key for another driver.
Definition: util-reg.c:95
NTSTATUS cbm_registry_open_for_read(OUT PHANDLE HandleKey, IN PUNICODE_STRING Path)
Open a registry path for reading.
Definition: util-reg.c:43
#define DBG_ASSERT(_xxx)
Definition: debug.h:401
NTSTATUS cbm_registry_read_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, OUT PULONG Value)
Read a ULONG value out of a registry key.
Definition: util-reg.c:299
NTSTATUS cbm_registry_close(IN HANDLE HandleKey)
Close a registry key.
Definition: util-reg.c:230
NTSTATUS cbm_registry_write_ulong(IN HANDLE HandleKey, IN PCWSTR KeyName, IN ULONG Value)
Write a ULONG value out of a registry key.
Definition: util-reg.c:356
#define FUNC_ENTER()
Definition: debug.h:347
#define FUNC_PARAM(_xxx)
Definition: debug.h:351
Definitions for the opencbm driver.
#define DBG_PREFIX
Definition: debug.h:320