PeLdrCheckForLoadedDll():
- Use a for-loop to iterate over the linked list.
- Adjust few comments.
- Use SAL2 annotations.
PeLdrpCompareDllName():
- Make its input paramters const.
- Use SAL2 annotations.
Use the PE import table's OriginalFirstThunk array when scanning and
resolving imports during DLL binding.
It points to an array of pointer-sized IMAGE_THUNK_DATA structures
which describe the functions being imported. On the other hand, the
FirstThunk points to an array of pointers, whose initial values are
a copy of those pointed to by OriginalFirstThunk, but are replaced
by the actual function pointers determined at runtime, when a DLL
is loaded (see PeLdrpBindImportName() function).
If we were to use the FirstThunk array to find again later the imports
by name or ordinal, we would fail because these are replaced by the
addresses of the corresponding functions.
This fixes loading kdcom.dll from Windows XP x64 with FreeLDR when
testing on ReactOS x64.
```diff
(freeldr\freeldr\lib\peloader.c:498) trace: PeLdrpScanImportAddressTable() ---- Calling PeLdrpBindImportName() in a loop
(freeldr\freeldr\lib\peloader.c:501) trace: *** ThunkName->u1.AddressOfData = 00000000000070F0
(freeldr\freeldr\lib\peloader.c:502) trace: *** ThunkData->u1.AddressOfData = 0000000000573780
(freeldr\freeldr\lib\peloader.c:209) trace: !!! ExportDirectory->NumberOfNames 1504
-(freeldr\freeldr\lib\peloader.c:210) trace: !!! ImportHint 0 - ExportName 'CcCanIWrite' - ImportDataName ''
+(freeldr\freeldr\lib\peloader.c:210) trace: !!! ImportHint 282 - ExportName 'HalPrivateDispatchTable' - ImportDataName 'HalPrivateDispatchTable'
....
-(freeldr\freeldr\lib\peloader.c:268) err: Did not find export ''!
-(freeldr\freeldr\lib\peloader.c:709) err: PeLdrpScanImportAddressTable() failed: ImportName = 'ntoskrnl.exe', DirectoryPath = 'multi(0)disk(0)rdisk(0)partition(2)\ReactOS\system32\'
```
('-': lines before the fix; '+': lines after the fix)
Code has been adapted based from the following functions:
ntdll/ldr/ldrpe.c!LdrpSnapThunk() and LdrpSnapIAT()
ntoskrnl/mm/ARM3/sysldr.c!MiSnapThunk() and MiResolveImageReferences()
References:
https://devblogs.microsoft.com/oldnewthing/20231129-00/?p=109077https://devblogs.microsoft.com/oldnewthing/20231130-00/?p=109084https://stackoverflow.com/questions/42413937/why-pe-need-original-first-thunkoft
This allows to load an image as freeldr extension code.
TODO:
- Add global bootloader DTE list
- Add wrapper function that also processes imports
- Use this for scsiport
- The original code was just incrementing the reference counts (RefCounts)
of the device objects or the device/file handles, without decrementing
them when closing the handles. This is now fixed.
Notice the following:
* When opening a file on a device (disk), the device's (and its
handle's) RefCount is incremented, and the file handle's RefCount
is incremented as well.
* When closing a file, the file handle's RefCount is decremented
(and the file closed if the RefCount reaches zero), and the file's
parent device handle is also closed, recursively.
This has the effect of decrementing the parent device handle's
RefCount, and the device's own RefCount is decremented as well.
IMPORTANT NOTE: The usefulness of handle-level RefCount is still
under question, and might be (consistently) removed in the future.
- Fix opening a device (disk) in direct access, when this device is
already opened. Indeed, we previously allowed direct access only if
the device was opened as such for the very first time (its RefCount
= 0 originally); no filesystem mounting was attempted as well.
Then for any later open-operations on this device (while keeping an
already-opened handle to it), filesystem access was assumed.
Thus, this problem would show up in two ways:
* Either the device is first opened for direct access, this succeeded
and no filesystem was mounted. Then, for any other open-operations,
the filesystem was NOT mounted, and opening files on it would fail.
Direct accesses would succeed but would create an unnecessary second
file handle.
* Or, the device is first opened for file-access: a filesystem was
mounted and file opening would succeed. Any other file opening
operation would succeed as well (if the file exists). But, a direct
access open-operation would fail, because now any open-operations on
the device would be assumed to be a file opening.
This is now correctly fixed. If direct-open is requested, just do it.
If this is a file opening, we open the device, then try to mount a
filesystem on it (if not already done), then we try to open the file.
If file opening fails, derereference the device.
- Pass the file path to the filesystem-specific Open() functions without
truncating the leading path separator, if any. This has to be handled
by the filesystem routines themselves.
Those haven't been groomed anymore for more than 10 years. We had many thousands of
different freeldr builds with different behavior and bugs each, but nobody ever
did have the slightest motivation to update those hardcoded
FREELOADER_MAJOR_VERSION, FREELOADER_MINOR_VERSION, FREELOADER_PATCH_VERSION
from ver.h. And that is logical, because touching other modules will change the behavior
of freeldr as well, so it is absolutely impossible to groom anything like that correctly.
Instead we should simply do what we started to do in PR7383, which will at least give
some information (the actual sources it was built from) instead of some misleading voodoo-version.
This might slightly shrink the size of freeldr as well, but I was too lazy to measure by how much.
- `ArcOpen()`: flatten the registered-device search for-loop.
Limit it to just the device search, and exit early.
The rest of the initialization is now done outside the loop.
- The `DeviceName` string pointer may have been allocated from
the heap, for path normalization (see `NormalizeArcDeviceName()`).
This pointer is then only used in the device search loop and not
nused anymore afterwards. The old code didn't free this pointer
and memory could leak. This is now fixed easily, thanks to the
loop flattening.
- Rename `DEVICE` member `Prefix` to `DeviceName`; SAL-annotate
`FsRegisterDevice()`.
- Replace a lot of `MAX_FDS` by `_countof(FileData)`;
- The duplicated FileId validation logic is wrapped with
the `IS_VALID_FILEID()` macro.
- When returning an invalid FileId value on purpose, use
`INVALID_FILE_ID` instead of `MAX_FDS` (that could vary
if the file handle table gets extended).
And replace the `(ULONG)-1` also used for that purpose
by `INVALID_FILE_ID`.
- Add missing DeviceId invalidation:
* when failing to open a file handle in `ArcOpen()`;
* when registering a new device in `FsRegisterDevice()`.
There, having DeviceId always set to zero would tell
the code that the corresponding device's file ID is
the first one in the table, which is a BUG. (Many devices
would have the same file ID...)
- In addition: massage a bit some indicial for-loops.
This allows to make the code better extendable: adding a new FS
mount routine into the table, instead of duplicating also a whole
`if (!FileFuncTable) ...` check.
Later, this table will be made dynamic, so that new filesystems could be
dynamically registered at runtime, and a filesystem could be forced to
be mounted by the user (using a specific syntax).
----
Thanks to the following testers!
- Dmitry Borisov (@disean) for testing on NEC PC-98 emulator;
- Justin Miller (@DarkFire01) for testing on UEFI platform;
- Stanislav Motylkov (@binarymaster) for testing on Xbox emulator
(xemu), both livecd and bootcd.
----
"SectorsPerTrack" is for the legacy Cylinders/Heads/Sectors(PerTrack)
scheme.
- On BIOS-based PCs, INT 13h can return (for LBA-only drives) an invalid
geometry, like: C/H/S = (-1)/(-1)/(-1). This is also what happens in
our hwide.c driver (see IdentifyDevice() for ATAPI devices):
db419efbf2/boot/freeldr/freeldr/arch/drivers/hwide.c (L918-L928)
as well as on VirtualBox for CD-ROMs:
https://www.virtualbox.org/browser/vbox/trunk/src/VBox/Devices/PC/BIOS/disk.c#L155
- Therefore, we cannot reliably calculate a valid total number of sectors
by multiplying the Cylinders*Heads*SectorsPerTrack values. In addition,
such a multiplication could overflow a 32-bit ULONG.
Thus, a separate ULONGLONG Sectors member is required to hold such a
value, that is retrieved differently. For example for ATAPI devices,
our hwide.c driver does return a valid TotalSectors value, even though
CHS values are invalid. Other platforms, like UEFI, just work using
logical block addressing (LBA) values (see EFI_BLOCK_IO_MEDIA).
- uefidisk.c : Per the spec, EFI_BLOCK_IO_MEDIA::LastBlock contains
"The last LBA on the device. [...] For ATA devices, this is reported
in IDENTIFY DEVICE data words 60-61 (i.e., Total number of user
addressable logical sectors) _minus one_.
For SCSI devices, this is reported in the READ CAPACITY parameter
data 'Returned Logical Block Address field' _minus one_."
In other words, LastBlock is a zero-based LBA index quantity. The
corresponding total number of valid "sectors"/blocks of the device
is therefore, (LastBlock + 1).
- Cleanup some old disabled code.
We do have 22 rc files. Strip a hardcoded version in all of them.
Which hasn't been groomed by anyone for longer than the year 2005 already (SVN r18478).
What a waste of bytes!
This commit tries to improve the quality of the screenshots that we do get posted in JIRA,
where we couldn't even see up to now which build and arch was run.
This is in the wider context of CORE6762
(I intentionally left out the minus in the CORE-ID to prevent auto-linkage to that ticket)
When the Int 13h AH=42h "Extended read" function fails, the disk address
packet's LBA block count is reset to the number of blocks that have been
successfully transferred. This is more or less fine, unless one wants to
ensure the exact number of sectors gets read.
If the function fails so that zero sectors were read, the retry loop is
restarted, but with the packet's LBA block count member reset, as per
the documentation. (In this example, it is reset to zero.) Then, at the
next retry attempt, zero sectors are requested to be read, and this time
of course, the call succeeds... Wrongly, of course, this is not what's
expected.
Therefore, for each retry, the LBA block count member should be set
again to the correct number of sectors to read. There are maximum 3
retries, so the retry loop will stop anyway, but the LBA read will now
correctly fail and return FALSE, as expected.
This problem doesn't exist in the retry loop for the Int 13h, AH=02h
"Read Disk Sectors" CHS function, because here, the call is made only
using registers, and we use a pair of RegsIn/RegsOut. RegsOut receives
the modified register values, but the input RegsIn stays unchanged.
For reference, see the cdfs/cd.h RAW_ISO_VD structure.
Each of the old "VolumeSetSize", "VolumeSequenceNumber" and "LogicalBlockSize"
ULONG fields actually correspond to pairs of USHORT fields:
"VolumeSetSizeL" and "VolumeSetSizeM", etc., where the "L" one contains
the value in little-endian format, while the "M" one contains the same
value in big-endian format.
Additionally, use UCHARs for the character arrays.
This moves the IExplore registration from cmd.exe (established in 4a4060ce3c (r52196) for CORE-1370) to syssetup.inf to avoid console popups on first boot.
Improve compatibility.
JIRA issue: CORE-8002
- Fix the default values of AutoCompletionChar
and PathCompletionChar in cmd.exe.
- Populate "SOFTWARE\Microsoft\Command
Processor" registry key like Win2k3 does.
If East Asian people were unable
to see the Latin characters, it
becomes a barrier to mutual
understanding.
FontLink will break that barrier.
JIRA issue: CORE-9616
JIRA issue: CORE-15480
- Modify font substitutes.
- Unify the lock variables.
- Add FONTLINK and
FONTLINK_CHAIN structures.
- Add FontLink_Create and
FontLink_Destroy functions.
- Add FontLink_Chain_Init,
FontLink_Chain_Free,
FontLink_Chain_LoadReg,
FontLink_Chain_Populate, and
FontLink_Chain_FindGlyph
functions.
- Implement FontLink.
- Add font file DroidSansFallback.ttf
for LiveCD.