00250                    :
00251 
00252     This service dynamically unloads a device or 
file system driver from
00253     
the currently running system.  It requires that 
the caller have 
the
00254     appropriate privilege to execute 
this service.
00255 
00256 Arguments:
00257 
00258     DriverServiceName - Specifies 
the name of 
the node in 
the registry
00259         associated with 
the driver to be unloaded.
00260 
00261 Return Value:
00262 
00263     The status returned 
is the final completion status of 
the operation.
00264 
00265 --*/
00266 
00267 {
00268     
KPROCESSOR_MODE requestorMode;
00269     UNICODE_STRING driverServiceName;
00270     PWCHAR nameBuffer = (PWCHAR) 
NULL;
00271     
NTSTATUS status;
00272     OBJECT_ATTRIBUTES objectAttributes;
00273     HANDLE keyHandle;
00274     UNICODE_STRING driverName;
00275     HANDLE driverHandle;
00276     
PDRIVER_OBJECT driverObject;
00277     BOOLEAN unloadDriver;
00278 
00279     
PAGED_CODE();
00280 
00281     
00282     
00283     
00284 
00285     requestorMode = KeGetPreviousMode();
00286 
00287     
if (requestorMode != 
KernelMode) {
00288 
00289         
00290         
00291         
00292         
00293         
00294 
00295         
if (!
SeSinglePrivilegeCheck( SeLoadDriverPrivilege, requestorMode )) {
00296             
return STATUS_PRIVILEGE_NOT_HELD;
00297         }
00298 
00299         
00300         
00301         
00302         
00303         
00304 
00305         
try {
00306 
00307             driverServiceName = 
ProbeAndReadUnicodeString( DriverServiceName );
00308 
00309             
if (!driverServiceName.Length) {
00310                 
return STATUS_INVALID_PARAMETER;
00311             }
00312 
00313             
ProbeForRead( driverServiceName.Buffer,
00314                           driverServiceName.Length,
00315                           
sizeof( WCHAR ) );
00316 
00317             nameBuffer = 
ExAllocatePoolWithQuota( PagedPool,
00318                                                   driverServiceName.Length );
00319 
00320             RtlCopyMemory( nameBuffer,
00321                            driverServiceName.Buffer,
00322                            driverServiceName.Length );
00323 
00324             driverServiceName.Buffer = nameBuffer;
00325 
00326         } except(EXCEPTION_EXECUTE_HANDLER) {
00327 
00328             
00329             
00330             
00331             
00332             
00333             
00334 
00335             
if (nameBuffer) {
00336                 
ExFreePool( nameBuffer );
00337             }
00338             
return GetExceptionCode();
00339         }
00340 
00341         
00342         
00343         
00344         
00345         
00346         
00347         
00348         
00349 
00350         status = ZwUnloadDriver( &driverServiceName );
00351         
ExFreePool( nameBuffer );
00352         
return status;
00353     }
00354 
00355     
00356     
00357     
00358     
00359     
00360 
00361     status = 
IopOpenRegistryKey( &keyHandle,
00362                                  (HANDLE) NULL,
00363                                  DriverServiceName,
00364                                  KEY_READ,
00365                                  FALSE );
00366     
if (!
NT_SUCCESS( status )) {
00367         
return status;
00368     }
00369 
00370     
00371     
00372     
00373     
00374     
00375 
00376     status = 
IopGetDriverNameFromKeyNode( keyHandle,
00377                                           &driverName );
00378     
NtClose( keyHandle );
00379     
if (!
NT_SUCCESS( status )) {
00380         
return status;
00381     }
00382 
00383     
00384     
00385     
00386 
00387     InitializeObjectAttributes( &objectAttributes,
00388                                 &driverName,
00389                                 OBJ_CASE_INSENSITIVE,
00390                                 (HANDLE) NULL,
00391                                 (PSECURITY_DESCRIPTOR) NULL );
00392 
00393     status = 
ObOpenObjectByName( &objectAttributes,
00394                                  IoDriverObjectType,
00395                                  KernelMode,
00396                                  NULL,
00397                                  FILE_READ_DATA,
00398                                  (PVOID) NULL,
00399                                  &driverHandle );
00400 
00401     
00402     
00403     
00404     
00405     
00406 
00407     
ExFreePool( driverName.Buffer );
00408 
00409     
00410     
00411     
00412     
00413 
00414     
if (!
NT_SUCCESS( status )) {
00415         
return status;
00416     }
00417 
00418     
00419     
00420     
00421     
00422 
00423     status = 
ObReferenceObjectByHandle( driverHandle,
00424                                         0,
00425                                         IoDriverObjectType,
00426                                         KernelMode,
00427                                         (PVOID *) &driverObject,
00428                                         NULL );
00429     
NtClose( driverHandle );
00430 
00431     
if (!
NT_SUCCESS( status )) {
00432         
return status;
00433     }
00434 
00435     
00436     
00437     
00438     
00439     
00440     
00441 
00442     
if (driverObject->
DriverUnload == (
PDRIVER_UNLOAD) 
NULL ||
00443         !driverObject->
DriverSection) {
00444         
ObDereferenceObject( driverObject );
00445         
return STATUS_INVALID_DEVICE_REQUEST;
00446     }
00447 
00448     
00449     
00450     
00451     
00452 
00453     status = 
IopCheckUnloadDriver(driverObject,&unloadDriver);
00454 
00455     
if ( 
NT_SUCCESS(status) ) {
00456         
return status;
00457     }
00458 
00459     
if (unloadDriver) {
00460 
00461         
if (
PsGetCurrentProcess() == 
PsInitialSystemProcess) {
00462 
00463             
00464             
00465             
00466             
00467 
00468             driverObject->
DriverUnload( driverObject );
00469 
00470         } 
else {
00471 
00472             
00473             
00474             
00475             
00476             
00477             
00478             
00479 
00480             
LOAD_PACKET loadPacket;
00481 
00482             
KeInitializeEvent( &loadPacket.
Event, NotificationEvent, FALSE );
00483             loadPacket.
DriverObject = driverObject;
00484             
ExInitializeWorkItem( &loadPacket.
WorkQueueItem,
00485                                   IopLoadUnloadDriver,
00486                                   &loadPacket );
00487             
ExQueueWorkItem( &loadPacket.
WorkQueueItem, DelayedWorkQueue );
00488             (
VOID) 
KeWaitForSingleObject( &loadPacket.
Event,
00489                                           Executive,
00490                                           KernelMode,
00491                                           FALSE,
00492                                           (PLARGE_INTEGER) NULL );
00493         }
00494         
ObMakeTemporaryObject( driverObject );
00495         
ObDereferenceObject( driverObject );
00496     }
00497 
00498     
00499     
00500     
00501     
00502     
00503 
00504     
ObDereferenceObject( driverObject );
00505     
return STATUS_SUCCESS;
00506 }
}