static BOOLEAN TestZwLoad( IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING DriverRegistryPath, IN PWCHAR NewDriverRegPath) { UNICODE_STRING RegPath; NTSTATUS Status; /* Try to load ourself */ Status = ZwLoadDriver((PUNICODE_STRING)DriverRegistryPath); ok (Status == STATUS_IMAGE_ALREADY_LOADED, "Expected NTSTATUS STATUS_IMAGE_ALREADY_LOADED, got 0x%lX\n", Status); if (Status != STATUS_IMAGE_ALREADY_LOADED) { DbgPrint("WARNING: Loading this a second time will cause BUGCHECK!\n"); } /* Try to load with a Registry Path that doesnt exist */ RtlInitUnicodeString(&RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\deadbeef"); Status = ZwLoadDriver(&RegPath); ok (Status == STATUS_OBJECT_NAME_NOT_FOUND, "Expected NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND, got 0x%lX\n", Status); /* Load the driver */ RtlInitUnicodeString(&RegPath, NewDriverRegPath); Status = ZwLoadDriver(&RegPath); ok(Status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got 0x%lX\n", Status); return NT_SUCCESS(Status); }
NTSTATUS NTAPI FsRecLoadFileSystem(IN PDEVICE_OBJECT DeviceObject, IN PWCHAR DriverServiceName) { UNICODE_STRING DriverName; PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; NTSTATUS Status = STATUS_IMAGE_ALREADY_LOADED; PAGED_CODE(); /* Make sure we haven't already been called */ if (DeviceExtension->State != Loaded) { /* Acquire the load lock */ KeWaitForSingleObject(FsRecLoadSync, Executive, KernelMode, FALSE, NULL); KeEnterCriticalRegion(); /* Make sure we're active */ if (DeviceExtension->State == Pending) { /* Load the FS driver */ RtlInitUnicodeString(&DriverName, DriverServiceName); Status = ZwLoadDriver(&DriverName); /* Loop all the linked recognizer objects */ while (DeviceExtension->State != Unloading) { /* Set them to the unload state */ DeviceExtension->State = Unloading; /* Go to the next one */ DeviceObject = DeviceExtension->Alternate; DeviceExtension = DeviceObject->DeviceExtension; } } /* Make sure that we haven't already loaded the FS */ if (DeviceExtension->State != Loaded) { /* Unregiser us, and set us as loaded */ IoUnregisterFileSystem(DeviceObject); DeviceExtension->State = Loaded; } /* Release the lock */ KeSetEvent(FsRecLoadSync, 0, FALSE); KeLeaveCriticalRegion(); } /* Return */ return Status; }
int main() { GetDrvCopyBits (); if (!DrvCopyBits) return 0; if(!EnableLoadDriverPrivilege()) return printf("Could not enable SeLoadDriverPrivilege\n"); char DriverPath [MAX_PATH]; GetSystemDirectory (DriverPath, MAX_PATH-1); lstrcat (DriverPath, "\\drivers\\ngvid.sys"); if(!CopyFile ("ngvid.sys", DriverPath, FALSE)) return printf("Cannot copy driver file\n"); SC_HANDLE hManager = OpenSCManager (0, 0, SC_MANAGER_CONNECT|SC_MANAGER_CREATE_SERVICE); if (!hManager) return printf("Cannot open SC manager\n"); SC_HANDLE hService = CreateService (hManager, "ngvid2", "ngvid2", SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath, 0, 0, 0, 0, 0); CloseServiceHandle (hService); CloseServiceHandle (hManager); HKEY hk; if(RegCreateKeyEx (HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\ngvid2\\Parameters", 0, 0, 0, KEY_SET_VALUE, 0, &hk, 0)) return 0; if (RegSetValueEx (hk, "DrvCopyBits", 0, REG_DWORD, (PBYTE)&DrvCopyBits, 4)) return 0; if (RegSetValueEx (hk, "pTblDrvCopyBits", 0, REG_DWORD, (PBYTE)&pTblDrvCopyBits, 4)) return 0; RegCloseKey (hk); UNICODE_STRING Path; NTSTATUS st; RtlInitUnicodeString (&Path, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\ngvid2"); st = ZwLoadDriver (&Path); if (!NT_SUCCESS(st) && st != STATUS_IMAGE_ALREADY_LOADED) return printf("ZwLoadDriver failed with status %X\n", st); return 0; }
NTSTATUS FsRtlRegisterUncProvider( __inout PHANDLE MupHandle, __in PUNICODE_STRING RedirDevName, __in BOOLEAN MailslotsSupported ) /*++ Routine Description: This routine registers a redir as a UNC provider. Arguments: Handle - Pointer to a handle. The handle is returned by the routine to be used when calling FsRtlDeregisterUncProvider. It is valid only if the routines returns STATUS_SUCCESS. RedirDevName - The device name of the redir. MailslotsSupported - If TRUE, this redir supports mailslots. Return Value: NTSTATUS - The status of the operation. --*/ { NTSTATUS status; HANDLE mupHandle = (HANDLE)-1; UNICODE_STRING mupDriverName; BOOLEAN dfsEnabled; PAGED_CODE(); KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL ); if (FsRtlpRedirs == 0) { dfsEnabled = FsRtlpIsDfsEnabled(); if (dfsEnabled) { FsRtlpRedirs = 1; RtlZeroMemory((PVOID) &FsRtlpDRD, sizeof(FsRtlpDRD)); } } switch( FsRtlpRedirs ) { case 0: // // Ok, the MUP isn't there and we don't need to use the // MUP for the first redir. // // We need to return a handle, but we're not really using the MUP yet. // And we may never use it (if there's only 1 redir). Return // a handle to the NULL device object, since we're committed to returning // a handle to our caller. Our caller isn't supposed to do anything with // the handle except to call FsRtlDeregisterUncProvider() with it. // status = FsRtlpOpenDev( &mupHandle, DevNull ); if( !NT_SUCCESS( status ) ) break; // // Save up enough state to allow us to call the MUP later with // this registration info if necessary. // FsRtlpDRD.RedirDevName.Buffer = ExAllocatePoolWithTag( NonPagedPool, RedirDevName->MaximumLength, MODULE_POOL_TAG ); if( FsRtlpDRD.RedirDevName.Buffer == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; break; } FsRtlpDRD.RedirDevName.Length = RedirDevName->Length; FsRtlpDRD.RedirDevName.MaximumLength = RedirDevName->MaximumLength; RtlCopyMemory( (PCHAR)FsRtlpDRD.RedirDevName.Buffer, RedirDevName->Buffer, RedirDevName->MaximumLength ); FsRtlpDRD.MailslotsSupported = MailslotsSupported; FsRtlpDRD.ReturnedHandle = mupHandle; FsRtlpDRD.MupHandle = (HANDLE)-1; // // Set the UNC symbolic link to point to the redir we just loaded // FsRtlpSetSymbolicLink( RedirDevName ); break; default: // // This is the second or later redir load -- MUST use the MUP // status = FsRtlpOpenDev( &mupHandle, DevMup ); if( !NT_SUCCESS( status ) ) { RtlInitUnicodeString( &mupDriverName, MupRegKey ); (VOID)ZwLoadDriver( &mupDriverName ); status = FsRtlpOpenDev( &mupHandle, DevMup ); if( !NT_SUCCESS( status ) ) break; } // // See if we need to tell the MUP about the first redir that registered // if( FsRtlpDRD.RedirDevName.Buffer ) { status = FsRtlpRegisterProviderWithMUP( mupHandle, &FsRtlpDRD.RedirDevName, FsRtlpDRD.MailslotsSupported ); if( !NT_SUCCESS( status ) ) break; FsRtlpDRD.MupHandle = mupHandle; ExFreePool( FsRtlpDRD.RedirDevName.Buffer ); FsRtlpDRD.RedirDevName.Buffer = NULL; // // Set the UNC symbolic link to point to the MUP // RtlInitUnicodeString( &mupDriverName, DevMup ); FsRtlpSetSymbolicLink( &mupDriverName ); status = FsRtlpOpenDev( &mupHandle, DevMup ); if( !NT_SUCCESS( status ) ) break; } // // Pass the request to the MUP for this redir // status = FsRtlpRegisterProviderWithMUP( mupHandle, RedirDevName, MailslotsSupported ); break; } if( NT_SUCCESS( status ) ) { FsRtlpRedirs++; *MupHandle = mupHandle; } else { if( mupHandle != (HANDLE)-1 && mupHandle != NULL ) { ZwClose( mupHandle ); } *MupHandle = (HANDLE)-1; } KeReleaseSemaphore(&FsRtlpUncSemaphore, 0, 1, FALSE ); return status; }
VOID NtfsLoadAddOns ( IN PDRIVER_OBJECT DriverObject, IN PVOID Context, IN ULONG Count ) /*++ Routine Description: This routine attempts to load any NTFS add-ons and notify them about any previously mounted volumes. Arguments: DriverObject - Driver object for NTFS Context - Unused, required by I/O system. Count - Unused, required by I/O system. Return Value: None. --*/ { NTSTATUS Status; UNICODE_STRING UnicodeString; ULONG i; WCHAR Buffer[80]; TOP_LEVEL_CONTEXT TopLevelContext; PTOP_LEVEL_CONTEXT ThreadTopLevelContext; IRP_CONTEXT LocalIrpContext; IRP LocalIrp; PIRP_CONTEXT IrpContext; PLIST_ENTRY Links; PVCB Vcb; PVCB VcbForTearDown = NULL; BOOLEAN AcquiredGlobal = FALSE; PAGED_CODE(); UNREFERENCED_PARAMETER(Context); UNREFERENCED_PARAMETER(Count); UNREFERENCED_PARAMETER(DriverObject); // // For each add-on try to load it. // for (i = 0; NtfsAddonNames[i] != NULL; i++) { wcscpy(Buffer, NTFS_SERVICE_KEY); wcscat(Buffer, NtfsAddonNames[i]); RtlInitUnicodeString( &UnicodeString, Buffer); Status = ZwLoadDriver( &UnicodeString ); #if DBG DbgPrint("NtfsLoadAddOns: Loaded module %ws. Status = 0x%lx\n", Buffer, Status); #endif } RtlZeroMemory( &LocalIrpContext, sizeof(LocalIrpContext) ); RtlZeroMemory( &LocalIrp, sizeof(LocalIrp) ); IrpContext = &LocalIrpContext; IrpContext->NodeTypeCode = NTFS_NTC_IRP_CONTEXT; IrpContext->NodeByteSize = sizeof(IRP_CONTEXT); IrpContext->OriginatingIrp = &LocalIrp; SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT); InitializeListHead( &IrpContext->ExclusiveFcbList ); // // Make sure we don't get any pop-ups // ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, TRUE, FALSE ); ASSERT( ThreadTopLevelContext == &TopLevelContext ); (VOID) ExAcquireResourceShared( &NtfsData.Resource, TRUE ); AcquiredGlobal = TRUE; __try { NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext ); __try { for (Links = NtfsData.VcbQueue.Flink; Links != &NtfsData.VcbQueue; Links = Links->Flink) { Vcb = CONTAINING_RECORD(Links, VCB, VcbLinks); IrpContext->Vcb = Vcb; if (FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) { Status = CiMountVolume( Vcb, IrpContext); // Bugbug: What should we do if this fails? // BugBug: add call out for views. NtfsCommitCurrentTransaction( IrpContext ); } } } __except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) { NOTHING; } } __finally { if (AcquiredGlobal) { ExReleaseResource( &NtfsData.Resource ); } NtfsRestoreTopLevelIrp( ThreadTopLevelContext ); } // // And return to our caller // return; }
/*++ * @name FsRtlRegisterUncProvider * @implemented * * FILLME * * @param Handle * FILLME * * @param RedirectorDeviceName * FILLME * * @param MailslotsSupported * FILLME * * @return None * * @remarks None * *--*/ NTSTATUS NTAPI FsRtlRegisterUncProvider(OUT PHANDLE Handle, IN PCUNICODE_STRING RedirectorDeviceName, IN BOOLEAN MailslotsSupported) { NTSTATUS Status; HANDLE DeviceHandle; UNICODE_STRING MupString; PAGED_CODE(); DPRINT1("FsRtlRegisterUncProvider(%p, %wZ, %u)\n", Handle, RedirectorDeviceName, MailslotsSupported); KeWaitForSingleObject(&FsRtlpUncSemaphore, Executive, KernelMode, FALSE, NULL); /* In case no provider was registered yet, check for DFS present. * If DFS is present, we need to go with MUP, whatever the case */ if (FsRtlpRedirs == 0) { if (FsRtlpIsDfsEnabled()) { DPRINT1("DFS is not disabled. Going through MUP\n"); /* We've to go with MUP, make sure our internal structure doesn't * contain any leftover data and raise redirs to one, to make sure * we use MUP. */ RtlZeroMemory(&FsRtlpDRD, sizeof(FsRtlpDRD)); FsRtlpRedirs = 1; } } /* In case no UNC provider was already registered, * We'll proceed without MUP and directly redirect * UNC to the provider. */ if (FsRtlpRedirs == 0) { /* As we don't provide MUP, just give a handle to NULL device */ Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Null"); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Allocate a buffer big enough to keep a local copy of UNC provider device */ FsRtlpDRD.RedirectorDeviceName.Buffer = ExAllocatePoolWithTag(NonPagedPool, RedirectorDeviceName->MaximumLength, TAG_UNC); if (FsRtlpDRD.RedirectorDeviceName.Buffer == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } FsRtlpDRD.RedirectorDeviceName.Length = RedirectorDeviceName->Length; FsRtlpDRD.RedirectorDeviceName.MaximumLength = RedirectorDeviceName->MaximumLength; RtlCopyMemory(FsRtlpDRD.RedirectorDeviceName.Buffer, RedirectorDeviceName->Buffer, RedirectorDeviceName->MaximumLength); /* We don't have MUP, and copy provider information */ FsRtlpDRD.MupHandle = INVALID_HANDLE_VALUE; FsRtlpDRD.MailslotsSupported = MailslotsSupported; FsRtlpDRD.NullHandle = DeviceHandle; /* Set DOS device UNC to use provider device */ FsRtlpSetSymbolicLink(RedirectorDeviceName); } else { /* We (will) have several providers, MUP is required */ Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup"); if (!NT_SUCCESS(Status)) { /* Opening MUP may have failed because the driver was not loaded, so load it and retry */ RtlInitUnicodeString(&MupString, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Mup"); ZwLoadDriver(&MupString); Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup"); if (!NT_SUCCESS(Status)) { goto Cleanup; } } /* In case we had a single provider till now, we have to forward the old provider to MUP * And then, register the new one to MUP as well */ if (FsRtlpDRD.RedirectorDeviceName.Buffer != NULL) { /* We will only continue if we can register previous provider in MUP */ Status = FsRtlpRegisterProviderWithMUP(DeviceHandle, &FsRtlpDRD.RedirectorDeviceName, FsRtlpDRD.MailslotsSupported); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* Save our Mup handle for later usage */ FsRtlpDRD.MupHandle = DeviceHandle; /* Release information about previous provider */ ExFreePoolWithTag(FsRtlpDRD.RedirectorDeviceName.Buffer, TAG_UNC); FsRtlpDRD.RedirectorDeviceName.Buffer = NULL; /* Re-open MUP to have a handle to give back to the user */ Status = FsRtlpOpenDev(&DeviceHandle, L"\\Device\\Mup"); if (!NT_SUCCESS(Status)) { goto Cleanup; } } /* Redirect UNC DOS device to MUP */ RtlInitUnicodeString(&MupString, L"\\Device\\Mup"); FsRtlpSetSymbolicLink(&MupString); /* Register new provider */ Status = FsRtlpRegisterProviderWithMUP(DeviceHandle, RedirectorDeviceName, MailslotsSupported); } Cleanup: /* In case of success, increment number of providers and return handle * to the device pointed by UNC DOS device */ if (NT_SUCCESS(Status)) { ++FsRtlpRedirs; *Handle = DeviceHandle; } else { /* Cleanup in case of failure */ if (DeviceHandle != INVALID_HANDLE_VALUE && DeviceHandle != 0) { ZwClose(DeviceHandle); } *Handle = INVALID_HANDLE_VALUE; } KeReleaseSemaphore(&FsRtlpUncSemaphore, IO_NO_INCREMENT, 1, FALSE); return Status; }
NTSTATUS AFSLoadLibrary( IN ULONG Flags, IN UNICODE_STRING *ServicePath) { UNREFERENCED_PARAMETER(Flags); NTSTATUS ntStatus = STATUS_SUCCESS; AFSDeviceExt *pDevExt = (AFSDeviceExt *)AFSDeviceObject->DeviceExtension; UNICODE_STRING uniLibraryName; AFSDeviceExt *pLibDevExt = NULL; PFILE_OBJECT pLibraryFileObject = NULL; PDEVICE_OBJECT pLibraryDeviceObject = NULL; __Enter { // // Wait on the load library event so we don't race with any // other requests coming through // AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY, AFS_TRACE_LEVEL_VERBOSE, "%s Start load library\n", __FUNCTION__)); ntStatus = KeWaitForSingleObject( &pDevExt->Specific.Control.LoadLibraryEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary Wait for LoadLibraryEvent failure %08lX\n", ntStatus)); try_return( ntStatus); } // // Check our current state to ensure we currently do not have a library loaded // if( BooleanFlagOn( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Library already loaded\n", __FUNCTION__)); try_return( ntStatus = STATUS_DEVICE_NOT_READY); } pDevExt->Specific.Control.LibraryServicePath.Buffer = (WCHAR *)AFSExAllocatePoolWithTag( PagedPool, ServicePath->Length, AFS_GENERIC_MEMORY_25_TAG); if( pDevExt->Specific.Control.LibraryServicePath.Buffer == NULL) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary AFS_GENERIC_MEMORY_25_TAG allocation error\n")); try_return( ntStatus = STATUS_INSUFFICIENT_RESOURCES); } RtlZeroMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, ServicePath->Length); pDevExt->Specific.Control.LibraryServicePath.Length = ServicePath->Length; pDevExt->Specific.Control.LibraryServicePath.MaximumLength = pDevExt->Specific.Control.LibraryServicePath.Length; RtlCopyMemory( pDevExt->Specific.Control.LibraryServicePath.Buffer, ServicePath->Buffer, pDevExt->Specific.Control.LibraryServicePath.Length); // // Load the library // ntStatus = ZwLoadDriver( ServicePath); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "%s Failed to load library Status %08lX\n", __FUNCTION__, ntStatus)); try_return( ntStatus); } // // Open up the control device and grab teh entry points for the library // RtlInitUnicodeString( &uniLibraryName, AFS_LIBRARY_CONTROL_DEVICE_NAME); ntStatus = IoGetDeviceObjectPointer( &uniLibraryName, FILE_ALL_ACCESS, &pLibraryFileObject, &pLibraryDeviceObject); if( !NT_SUCCESS( ntStatus)) { AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_ERROR, "AFSLoadLibrary IoGetDeviceObjectPointer failure %08lX\n", ntStatus)); try_return( ntStatus); } // // We have our reference to the library device object. Grab the // device extension and setup our callbacks // pLibDevExt = (AFSDeviceExt *)pLibraryDeviceObject->DeviceExtension; // // Save off our references // pDevExt->Specific.Control.LibraryFileObject = pLibraryFileObject; pDevExt->Specific.Control.LibraryDeviceObject = pLibraryDeviceObject; // // Reset the state for our library // AFSAcquireExcl( &pDevExt->Specific.Control.LibraryStateLock, TRUE); SetFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_LOADED); ClearFlag( pDevExt->Specific.Control.LibraryState, AFS_LIBRARY_QUEUE_CANCELLED); AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Completed load library, processing queued requests\n", __FUNCTION__)); AFSReleaseResource( &pDevExt->Specific.Control.LibraryStateLock); // // Process the queued requests // AFSProcessQueuedResults( FALSE); try_exit: AFSDbgTrace(( AFS_SUBSYSTEM_LOAD_LIBRARY | AFS_SUBSYSTEM_INIT_PROCESSING, AFS_TRACE_LEVEL_VERBOSE, "%s Library load complete Status %08lX\n", __FUNCTION__, ntStatus)); if( !NT_SUCCESS( ntStatus)) { if( pDevExt->Specific.Control.LibraryServicePath.Buffer != NULL) { ZwUnloadDriver( &pDevExt->Specific.Control.LibraryServicePath); ExFreePool( pDevExt->Specific.Control.LibraryServicePath.Buffer); pDevExt->Specific.Control.LibraryServicePath.Buffer = NULL; pDevExt->Specific.Control.LibraryServicePath.Length = 0; pDevExt->Specific.Control.LibraryServicePath.MaximumLength = 0; } } KeSetEvent( &pDevExt->Specific.Control.LoadLibraryEvent, 0, FALSE); } return ntStatus; }