Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

wdm/LoadUnload.c

Go to the documentation of this file.
00001 /*
00002  *  This program is free software; you can redistribute it and/or
00003  *  modify it under the terms of the GNU General Public License
00004  *  as published by the Free Software Foundation; either version
00005  *  2 of the License, or (at your option) any later version.
00006  *
00007  *  Copyright 2004 Spiro Trikaliotis
00008  *
00009  */
00010 
00020 #include <wdm.h>
00021 #include "cbm_driver.h"
00022 #include <cbmioctl.h>
00023 
00053 NTSTATUS
00054 AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PdoUNUSED, IN PCWSTR ParallelPortName)
00055 {
00056     PDEVICE_OBJECT fdo;
00057     UNICODE_STRING deviceNameNumber;
00058     UNICODE_STRING deviceNamePrefix;
00059     UNICODE_STRING deviceName;
00060     NTSTATUS ntStatus;
00061     WCHAR deviceNameNumberBuffer[50];
00062 
00064     static SHORT no = 0;
00065 
00066     FUNC_ENTER();
00067 
00068     UNREFERENCED_PARAMETER(PdoUNUSED);
00069 
00070     // Until now, no error has occurred
00071 
00072     ntStatus = STATUS_SUCCESS;
00073 
00074     // Create the name for the fdo
00075     // thus, this is a named driver
00076 
00077     DBG_IRQL( <= DISPATCH_LEVEL);
00078     RtlInitUnicodeString(&deviceNamePrefix, CBMDEVICENAME);
00079 
00080     // Convert variable no into a UNICODE_STRING
00081 
00082     deviceNameNumber.Length = 0;
00083     deviceNameNumber.MaximumLength = sizeof(deviceNameNumberBuffer);
00084     deviceNameNumber.Buffer = deviceNameNumberBuffer;
00085     DBG_IRQL( == PASSIVE_LEVEL);
00086     RtlIntegerToUnicodeString(no, 10, &deviceNameNumber);
00087 
00088     // Increment the number for the next device
00089 
00090     ++no;
00091 
00092     // Allocate enough space for the concatenation of deviceNamePrefix
00093     // and deviceNameNumber
00094 
00095     deviceName.MaximumLength = deviceNamePrefix.Length + deviceNameNumber.Length;
00096     deviceName.Buffer = (PWCHAR) ExAllocatePoolWithTag(NonPagedPool, 
00097         deviceName.MaximumLength, MTAG_DEVNAME);
00098 
00099     if (!deviceName.Buffer)
00100     {
00101         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
00102         DBG_ERROR((DBG_PREFIX "Could not allocate memory for deviceName"))
00103         LogErrorString(NULL, CBM_START_FAILED, L"allocating memory for device name", NULL);
00104     }
00105 
00106     if (NT_SUCCESS(ntStatus))
00107     {
00108         // Concatenate both strings
00109 
00110         DBG_IRQL( < DISPATCH_LEVEL);
00111         RtlCopyUnicodeString(&deviceName, &deviceNamePrefix);
00112         DBG_IRQL( < DISPATCH_LEVEL);
00113         RtlAppendUnicodeStringToString(&deviceName, &deviceNameNumber);
00114 
00115         // create the FDO with the name just build
00116 
00117         DBG_IRQL( == PASSIVE_LEVEL);
00118         ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &deviceName,
00119             FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, TRUE, &fdo);
00120 
00121         if (!NT_SUCCESS(ntStatus))
00122         {
00123             DBG_ERROR((DBG_PREFIX "IoCreateDevice failed with 0x%08X - %s",
00124                 ntStatus, DebugNtStatus(ntStatus)));
00125             LogErrorString(NULL, CBM_START_FAILED, L"creation of the device object", NULL);
00126         }
00127     }
00128 
00129     if (NT_SUCCESS(ntStatus))
00130     {
00131         // Initialization common to WDM and NT4 driver
00132 
00133         ntStatus = AddDeviceCommonInit(fdo, &deviceName, ParallelPortName);
00134 
00135 
00136         if (!NT_SUCCESS(ntStatus))
00137         {
00138             PDEVICE_EXTENSION pdx;
00139 
00140             // An error has occurred, thus, delete the device
00141 
00142             // get the pdx of the driver
00143 
00144             pdx = fdo->DeviceExtension;
00145 
00146             // If necessary, delete the buffer for the device name
00147 
00148             if (pdx->DeviceName.Buffer)
00149             {
00150                 DBG_IRQL( < DISPATCH_LEVEL);
00151                 ExFreePool(pdx->DeviceName.Buffer);
00152             }
00153 
00154             DBG_IRQL( == PASSIVE_LEVEL);
00155             IoDeleteDevice(fdo);
00156         }
00157 
00159 /*
00160         // Now, attach our FDO to the PDO
00161         pdx->LowerDeviceObject = IoAttachDeviceToDeviceStack(fdo, Pdo);
00162         if (!pdx->LowerDeviceObject)
00163         {
00164             DBG_ERROR((DBG_PREFIX "IoAttachDeviceToDeviceStack failed"));
00165             ntStatus = STATUS_DEVICE_REMOVED;
00166         }
00167         else
00168         {
00169         // clear initializing flag: we are now ready to work
00170         fdo->Flags &= ~DO_DEVICE_INITIALIZING;
00171         }
00172 */
00173 
00174         //
00175         // Initialize PDX related parts from registry
00176         //
00177 
00178         {
00179             PDEVICE_EXTENSION pdx = fdo->DeviceExtension;
00180 
00181             cbm_init_registry(NULL, pdx);
00182         }
00183     }
00184 
00185     FUNC_LEAVE_NTSTATUS(ntStatus);
00186 }
00187 
00188 static KMUTEX MutexDriverLoadUnload;
00189 
00202 VOID
00203 DriverUnload(IN PDRIVER_OBJECT DriverObject)
00204 {
00205     PDEVICE_OBJECT currentDevice;
00206 
00207     FUNC_ENTER();
00208 
00209     // Obtain the mutex that prevents premature unloading
00210 
00211     DBG_IRQL( < DISPATCH_LEVEL);
00212     KeWaitForMutexObject(&MutexDriverLoadUnload, Executive, KernelMode,
00213         FALSE, NULL);
00214 
00215     // Make sure every device object is deleted
00216 
00217     while (currentDevice = DriverObject->DeviceObject) 
00218     {
00219         PDEVICE_EXTENSION pdx = currentDevice->DeviceExtension;
00220 
00221         DBG_ASSERT(pdx);
00222 
00223         // Unlock the parallel port, if necessary
00224 
00225         if (pdx->ParallelPortIsLocked)
00226         {
00227             cbm_unlock_parport(pdx);
00228         }
00229 
00230         // Stop the thread of that device, if necessary
00231 
00232         cbm_stop_thread(pdx);
00233 
00234         // Uninitialize the parallel port, if necessary
00235 
00236         ParPortDeinit(pdx);
00237 
00238         // If a buffer for the device name has been allocated,
00239         // release that
00240 
00241         if (pdx->DeviceName.Buffer)
00242         {
00243             DBG_IRQL( < DISPATCH_LEVEL);
00244             ExFreePool(pdx->DeviceName.Buffer);
00245         }
00246 
00247         // Delete the device
00248         // This has to be done *after* the above, as the pdx
00249         // is not allowed to be accessed anymore here.
00250 
00251         DBG_IRQL( == PASSIVE_LEVEL);
00252         IoDeleteDevice(currentDevice);
00253     }
00254 
00255     // some more uninitialization, common to WDM and NT4 driver
00256 
00257     DriverCommonUninit();
00258 
00259 #if DBG
00260 
00261     DbgFreeMemoryBuffer();
00262 
00263 #endif
00264 
00265     // From now on, it is legal to be unloaded
00266 
00267     DBG_IRQL( <= DISPATCH_LEVEL);
00268     KeReleaseMutex(&MutexDriverLoadUnload, FALSE);
00269 
00270     FUNC_LEAVE();
00271 }
00272 
00295 NTSTATUS
00296 DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
00297 {
00298     PENUMERATE enumerate;
00299     NTSTATUS ntStatus;
00300 
00301     FUNC_ENTER();
00302 
00303     // Initialize the debugging system
00304 
00305     DBG_INIT();
00306 
00307     // Initialize the mutex which should prevent premature unloading
00308 
00309     KeInitializeMutex(&MutexDriverLoadUnload, 0);
00310 
00311     // Now, obtain that mutex as first operation
00312 
00313     DBG_IRQL( < DISPATCH_LEVEL);
00314     KeWaitForMutexObject(&MutexDriverLoadUnload, Executive, KernelMode,
00315         FALSE, NULL);
00316 
00317 #if DBG
00318 
00319     DbgAllocateMemoryBuffer();
00320 
00321 #endif
00322 
00323     // Output a status message
00324 
00325     DBG_PRINT((DBG_PREFIX "CBM4WDM.SYS " __DATE__ " " __TIME__));
00326 
00327     // Perform initialization common to NT4 and WDM driver
00328 
00329     ntStatus = DriverCommonInit(DriverObject, RegistryPath);
00330 
00332 
00334 
00335     // enumerate all parallel port drivers:
00336 
00337     ntStatus = ParPortEnumerateOpen(&enumerate);
00338 
00339     if (NT_SUCCESS(ntStatus))
00340     {
00341         PCWSTR DriverName;
00342 
00343         do 
00344         {
00345             ntStatus = ParPortEnumerate(enumerate,&DriverName);
00346 
00347             if (NT_SUCCESS(ntStatus) && *DriverName)
00348             {
00349                 DBG_SUCCESS((DBG_PREFIX "Drivername = \"%ws\"", DriverName));
00350                 AddDevice(DriverObject, NULL, DriverName);
00351             }
00352         } while (NT_SUCCESS(ntStatus) && *DriverName);
00353 
00354         ParPortEnumerateClose(enumerate);
00355     }
00356 
00357     // From now on, it is legal to be unloaded
00358 
00359     DBG_IRQL( <= DISPATCH_LEVEL);
00360     KeReleaseMutex(&MutexDriverLoadUnload, FALSE);
00361 
00362     FUNC_LEAVE_NTSTATUS_CONST(STATUS_SUCCESS);
00363 }

Generated on Sun Apr 30 18:45:54 2006 for opencbm by  doxygen 1.4.2