driverName.Buffer leaked when the "(!NT_SUCCESS(status) || ServiceName != NULL)"
case is taken because ServiceName != NULL, and some of the functions fail.
- Fix CID 1477246: Uninitialized pointer read (UNINIT) (happens in
the last ExFreePoolWithTag(basicInfo, TAG_IO) call when the
"(!NT_SUCCESS(status) || ServiceName != NULL)" case is not taken).
- Centralize all the ExFreePoolWithTag(basicInfo, TAG_IO) cleanups
at the end of the function.
- Both cases "(driverName.Buffer == NULL)" and "(ServiceName != NULL)"
can only be taken when basicInfo != NULL, so assert on this fact.
- Fix/add comments;
- Reduce indentation level;
- Direct copy for registry integer values;
- Use for-loops for linked lists;
- Use ULONG when the API uses it (sizes for Ob, or REG_DWORD data in registry).
- Manage the lifetime of the temporary 'PartitionBuffer' buffer where
it is locally used only, and free it as soon as possible, just after
calculating the sector checksum. No need to then free it outside of
the main for-loop.
- When the 'DriveLayout' buffer is freed, ensure the pointer is NULL-ed
(and assert this at the top of the main for-loop), since it can also
be freed at cleanup outside this for-loop, and in this case a NULL
check is performed.
This will avoid the scenario of possibly double-freeing a pointer,
in the case the 'DriveLayout' was previously freed (when e.g. reading
the sector for checksum calculation failed), then the for-loop goes to
the next disk and stops early.
The purpose of 'SingleDisk' is the same as in the IopCreateArcNames()
function. It is an optimization for that when looking up the
firmware-recognized ARC disks list, in order to match one of these with
the current NT disk being analysed (see e.g. also in IopCreateArcNamesDisk()),
we avoid a possible IopVerifyDiskSignature() call and directly build a
corresponding ARC name NT symbolic link for it.
'SingleDisk' will actually be TRUE, whether the DiskSignatureListHead
list is empty or contains only one element: Indeed in only both these
cases, 'DiskSignatureListHead.Flink->Flink' will refer to the list head.
(If the list is empty but 'SingleDisk' is TRUE, this does not matter,
because the DiskSignatureListHead looking-up loop never starts.)
In addition to that, here are some stuff done in this commit whilst testing:
- ICIF_QUERY_SIZE_VARIABLE and friends were badly misused, they should be used only when an information class whose information length size is dyanmic and not fixed. By removing such flags from erroneous classes, this fixes the STATUS_INFO_LENGTH_MISMATCH testcases.
- Use CHAR instead of UCHAR for classes that do not need alignment probing, as every other class in the table do, for the sake of consistency.
- ProcessEnableAlignmentFaultFixup uses BOOLEAN as type size, not CHAR. This fixes a testcase failure on ROS.
- Check for information length size before proceeding further on querying the process' cookie information.
- ProcessHandleTracing wants an alignment of a ULONG, not CHAR.
- Move PROCESS_LDT_INFORMATION and PROCESS_LDT_SIZE outside of NTOS_MODE_USER macro case. This fixes a compilation issue when enabling the alignment probing. My mistake of having them inside NTOS_MODE_USER case, sorry.
- On functions like NtQueryInformationThread and the Process equivalent, complete probing is not done at the beginning of the function, complete probing including if the buffer is writable alongside with datatype misalignment check that is. Instead such check is done on each information class case basis. With that said, we have to explicitly tell DefaultQueryInfoBufferCheck if we want a complete probing or not initially.
During the boot process, it makes possible to initalize the driver's
devices right after the driver is loaded. Moreover, this way one can be
sure that all critical devices are initialized before the
IopMarkBootPartition call (because we explicitly call the driver's
AddDevice routine now, after each driver is loaded)
CORE-7826
- Use DeviceNode->State field and its values, instead of
DeviceNode->Flags for tracking current node state
- Change DNF_* flags to the ones compatible with Windows XP+
- Simplify state changes for device nodes and encapsulate all the logic
inside the PiDevNodeStateMachine routine. This makes the ground for
future improvements in the device removal sequence and
resource management
- Now values inside DeviceNode->State and ->Flags are compatible with
the windbg !devnode macro and can be tracked using it
- BUGFIX: fixed cases where IRP_MN_START_DEVICE or
IRP_MN_QUERY_DEVICE_RELATIONS may be sent to a device after a
IRP_MN_REMOVE_DEVICE
CORE-7826
Add another PnPBootDriversInitialized variable to indicate a point where
both disk subsystem and SystemRoot symlink are initialized, and use it
in a PiCallDriverAddDevice call.
- Move the driver's name obtaining logic into the IopGetDriverNames
function
- Create a new PiCallDriverAddDevice instead of PipCallDriverAddDevice
and move it to pnpmgr/devaction.c file. Move around all its internal
helpers too
- Support a proper Windows-compatible driver loading order for a PDO
(lower filters, main service, upper filters, etc.)
- Set a correct Problem for the DeviceNode, in case of an error during
driver loading
- Check the Start Type for all drivers before loading
- Do not try to load drivers during the early boot stage when there is
no disk subsystem initialized
- Do not hold the IopDriverLoadResource while trying to reference a
driver object (but still acquire it when we actually need to load a
driver)
- Change IopLoadDriver and IopInitializeDriverModule to use registry
handle instead of a service name string and/or full registry path
- Do not try to reference a driver object inside IopLoadDriver. It's
supposed to be done before the function call
- Split IopLoadUnloadDriver into IopLoadDriver and calling DriverUnload
- Schedule the worker for (un)loading driver in a separate routine
(IopDoLoadUnloadDriver) this allows IopLoadDriver to be called
separately (if we are sure that we're in the system process)
- Remove IopCreateDriver and put its code into IoCreateDriver and
IopInitializeDriverModule. It's hard to extract a meaningful common
part from it
- Refactor IopInitializeDriverModule. Extend and put the DriverName
generation logic into it. Now this function frees the ModuleObject in
case of failure and returns STATUS_FAILED_DRIVER_ENTRY in case of
DriverInit failure (will be used later)
- BUGFIX: do not call IoGetRelatedTargetDevice while guarded mutex is acquired
(the function issues an APC, but they are disabled inside a critical section)
- BUGFIX: only the beginning of a structure for GUID_PNP_CUSTOM_NOTIFICATION was copied and queued.
Just pass it as-is to a subscriber, without copying
- Don't convert event GUID to string, store and compare GUID struct itself
- Split IopNotifyPlugPlayNotification into 3 functions for each type of notification
(less stack usage and for future changes)
- Move initialization code for notifications into a separate routine
- Use separate lists and locks for every type of notification
- Put "TargetDeviceChange" notifications into their place inside DEVICE_NODE
- Change INIT_FUNCTION and INIT_SECTION to CODE_SEG("INIT") and DATA_SEG("INIT") respectively
- Remove INIT_FUNCTION from function prototypes
- Remove alloc_text pragma calls as they are not needed anymore
CORE-14037
- Fix buggy retrieval of the current calling Irp->Tail.Overlay.Thread.
- The 4th argument (KernelRoutine) to the KeInitializeApc() is **NOT**
optional; however its 5th argument (RundownRoutine) is.
So use the mandatory routine for freeing the allocated APC instead.
We don't use the rundown routine yet.
- Check whether the ExAllocatePoolWithTag() call failed or not before
queueing the allocated APC.
We are doing IoCallDriver here, so the valid stack location should be
CurrentLocation <= Irp->StackCount (just a check for a completly incorrect value)
&& CurrentLocation > 1 (ensure that we have a place for another call)
CORE-17189
Co-authored-by: Thomas Faber <thomas.faber@reactos.org>
Introduce the PiPerformSyncDeviceAction routine for queuing
synchronous device actions
Change all kernel code to use PiPerformSyncDeviceAction and
PiQueueDeviceAction for device enumeration
CORE-10456
This allows querying volume information without issuing an IRP to the owner device.
The kernel is supposed to already have all the required information to return
to the caller.
Side effect: this allows querying volume information for devices not implementing
IRP_MJ_QUERY_VOLUME_INFORMATION such as null.sys
This fixes opening null device in Python.
Fix based on debugging by Maxim Smirnov in PR #1442
CORE-14551
This may look strange, since this buffer is originally allocated using
the TAG_IO_NAME tag. However, it happens that file-system drivers are
allowed to re-allocate this buffer: this is what the MS' open-sourced
CDFS driver does, see e.g. CdCommonCreate() and CdNormalizeFileNames()
in cdfs/create.c .
This fixes a pool tag mismatch 'mNoI' != 'nFdC' BSOD when resources
are freed when closing a file that has been opened with a relative name
on a CDFS-mounted volume.
* Add an NDK header to define INIT_FUNCTION/INIT_SECTION globally
* Use _declspec(allocate(x)) and _declspec(code_seg(x)) on MSVC versions that support it
* Use INIT_FUNCTION on functions only and INIT_SECTION on data only (required by MSVC)
* Place INIT_FUNCTION before the return type (required by MSVC)
* Make sure declarations and implementations share the same modifiers (required by MSVC)
* Add a global linker option to suppress warnings about defined but unused INIT section
* Merge INIT section into .text in freeldr
Also, probe the service name when unloading a driver if called from
user-mode. This will avoid that userland applications can trigger an
invalid read in the kernel (and thus, a BSOD).
CORE-15468
- Simplify the volume-deletion code in RawCheckForDismount().
- Fixes the OpenCount check in RawClose(): the VCB mutex must be
released when the volume has not been dismounted, either because
OpenCount != 0 or because RawCheckForDismount() returned FALSE.
- Explicitly use VCB_STATE_LOCKED instead of hardcoding its value.
- In IRP_MN_VERIFY_VOLUME handling, lock the volume before playing
with it, and again let the volume be dismounted only if OpenCount == 0
(and the IoDeleteDevice() call is done by RawCheckForDismount()).
This quick check based on bits and operation is for 2^ based
sector sizes (most of the cases) and will perform faster than
the modulo operation which is still used in fallback in case
the sector size wouldn't be a power of 2.