Over the past several weeks I've been working on and off on this. I didn't track the hours but I'm sure that I've spent 80+ hours on the feature. I've tested and retested all known scenarios and it seems to be working as expected.
--
v51: cmd: Implement tab completion for command line entry.
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843
SCSI command 0xAD (GPCMD_READ_DVD_STRUCTURE) with the eighth byte of the
command set to 0x00 (DVD_STRUCT_PHYSICAL) returns physical disc
information for DVDs and blu-rays. On success, the command returns
status 0, and for ordinary CDs, the command returns the error status
0x02 (SAM_STAT_CHECK_CONDITION). The format of the data returned is
different for blu-rays than for DVDs, and the second byte of the command
indicates whether to return DVD information or blu-ray information. (My
LG WH16NS40 drive actually ignores the second byte when there is a DVD
in the drive, but it returns SAM_STAT_CHECK_CONDITION when there is a
blu-ray in the drive and the second byte is not 0x01.) Windows does not
distinguish between DVDs and blu-rays in IOCTL_DISK_GET_MEDIA_TYPES, so
if the SCSI command succeeds for either disc type, report
FILE_DEVICE_DVD.
More specific media information is still not implemented.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57790
--
v3: ntdll: Detect the optical disc type on Linux using a SCSI command.
https://gitlab.winehq.org/wine/wine/-/merge_requests/7747
Function GdipGetImageAttributesAdjustedPalette gets [called with type = -1](https://gitlab.winehq.org/wine/wine/-/blob/22af42ac22279e6c0c671f033661f95c1761b4bb/dlls/gdiplus/tests/image.c?page=6#L5649) and therefore accesses several arrays at index -1.
This patch adds a helper which additionally checks for `type >= ColorAdjustTypeDefault`.
<details>
<summary>ASan output</summary>
```
=================================================================
==gdiplus_test.exe==308==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x7f21342c57f8 at pc 0x6ffffadfd25b bp 0x7ffffe1ff750 sp 0x7ffffe1ff798
READ of size 4 at 0x7f21342c57f8 thread T0
#0 0x6ffffadfd25a in apply_image_attributes .../dlls/gdiplus/graphics.c:929:41
#1 0x6ffffae5c2f2 in GdipGetImageAttributesAdjustedPalette .../dlls/gdiplus/imageattributes.c:123:5
#2 0x000140084b59 in test_getadjustedpalette .../dlls/gdiplus/tests/image.c:5649:12
#3 0x000140062be6 in func_image .../dlls/gdiplus/tests/image.c:6719:5
#4 0x0001400c9132 in run_test .../include/wine/test.h:765:5
#5 0x0001400c8b50 in main .../include/wine/test.h:884:12
#6 0x0001400cad3a in mainCRTStartup .../dlls/msvcrt/crt_main.c:60:11
#7 0x6fffffc45aa0 in BaseThreadInitThunk .../dlls/kernel32/thread.c:61:24
#8 0x6fffffdcc776 in RtlUserThreadStart (C:\windows\system32\ntdll.dll+0x17004c776)
0x7f21342c57f8 is located 144 bytes after 1256-byte region [0x7f21342c5280,0x7f21342c5768)
freed by thread T0 here:
#0 0x6ffffe88aab1 in free C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan\asan_malloc_win.cpp:71:3
#1 0x6ffffae5c21d in GdipDisposeImageAttributes .../dlls/gdiplus/imageattributes.c:109:5
#2 0x000140083598 in test_colorkey .../dlls/gdiplus/tests/image.c:3709:5
#3 0x000140062bd7 in func_image .../dlls/gdiplus/tests/image.c:6716:5
#4 0x0001400c9132 in run_test .../include/wine/test.h:765:5
#5 0x0001400c8b50 in main .../include/wine/test.h:884:12
#6 0x0001400cad3a in mainCRTStartup .../dlls/msvcrt/crt_main.c:60:11
#7 0x6fffffc45aa0 in BaseThreadInitThunk .../dlls/kernel32/thread.c:61:24
#8 0x6fffffdcc776 in RtlUserThreadStart (C:\windows\system32\ntdll.dll+0x17004c776)
previously allocated by thread T0 here:
#0 0x6ffffe88ace6 in calloc C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan\asan_malloc_win.cpp:91:3
#1 0x6ffffae5c0fc in GdipCreateImageAttributes .../dlls/gdiplus/imageattributes.c:87:18
#2 0x000140082bf9 in test_colorkey .../dlls/gdiplus/tests/image.c:3629:12
#3 0x000140062bd7 in func_image .../dlls/gdiplus/tests/image.c:6716:5
#4 0x0001400c9132 in run_test .../include/wine/test.h:765:5
#5 0x0001400c8b50 in main .../include/wine/test.h:884:12
#6 0x0001400cad3a in mainCRTStartup .../dlls/msvcrt/crt_main.c:60:11
#7 0x6fffffc45aa0 in BaseThreadInitThunk .../dlls/kernel32/thread.c:61:24
#8 0x6fffffdcc776 in RtlUserThreadStart (C:\windows\system32\ntdll.dll+0x17004c776)
SUMMARY: AddressSanitizer: heap-buffer-overflow .../dlls/gdiplus/graphics.c:929:41 in apply_image_attributes
Shadow bytes around the buggy address:
0x7f21342c5500: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7f21342c5580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7f21342c5600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7f21342c5680: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
0x7f21342c5700: fd fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa
=>0x7f21342c5780: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]
0x7f21342c5800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x7f21342c5880: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7f21342c5900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7f21342c5980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x7f21342c5a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
==gdiplus_test.exe==308==ABORTING
```
</details>
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/8141
On Fri May 23 04:23:45 2025 +0000, Alex Henrie wrote:
> Linux has only three [DVD
> ioctls](https://docs.kernel.org/userspace-api/ioctl/cdrom.html):
> DVD_READ_STRUCT, DVD_WRITE_STRUCT, and DVD_AUTH. It has no blu-ray
> ioctls. Of the three DVD ioctls, only DVD_READ_STRUCT would be suitable
> for disc type detection.
> DVD_READ_STRUCT can read five kinds of information: DVD_STRUCT_PHYSICAL,
> DVD_STRUCT_COPYRIGHT, DVD_STRUCT_DISCKEY, DVD_STRUCT_BCA, and
> DVD_STRUCT_MANUFACT. Of those five, only DVD_STRUCT_PHYSICAL would be
> suitable for disc type detection.
> At least on my LG WH16NS40 drive, DVD_STRUCT_PHYSICAL succeeds when
> there is a DVD in the drive, but it fails when there is a CD or a
> blu-ray in the drive. That means that we could use DVD_STRUCT_PHYSICAL
> to accurately detect whether there is a DVD in the drive, but we would
> still need another way to detect blu-rays.
> Is there another ioctl that you had in mind, or something else that I
> missed? Do you want to try DVD_STRUCT_PHYSICAL first and fall back to
> guessing based on the data size if it fails? Please let me know how to proceed.
Any chance it could be a driver bug?
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7747#note_104478
eric pouech (@epo) commented about programs/cmd/wcmdmain.c:
> +
> + /* Calculate cursor position at beginning of prompt, accounting for lines scrolled
> + * due to length of input.
> + */
> + GetConsoleScreenBufferInfo(hOutput, ¤tConsoleInfo);
> + currentConsoleInfo.dwCursorPosition.X = startConsoleInfo.dwCursorPosition.X;
> + len2 -= (currentConsoleInfo.dwSize.X - currentConsoleInfo.dwCursorPosition.X);
> + if (len2 > 0) {
> + currentConsoleInfo.dwCursorPosition.Y -= ((len2 / currentConsoleInfo.dwSize.X) + 1);
> + }
> + SetConsoleCursorPosition(hOutput, currentConsoleInfo.dwCursorPosition);
> +
> + WriteConsoleW(hOutput, inputBuffer, len, &numWritten, NULL);
> + if (maxLen > len) {
> + clear_console_characters(hOutput, maxLen - len, lastConsoleInfo.dwSize.X); /* width at time of last console update */
> + }
and likely you could do 'maxLen = len;' here: as screen is "cleared" after 'len' position, there's no need to clear it again (unless a wider string is needed, but you'll catch that later)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/7843#note_104474