1
1
#include < ntstatus.h>
2
+ #include < winioctl.h>
3
+ #include < ntddscsi.h>
2
4
3
5
#include " hooks.h"
4
6
#include " logging.h"
5
7
#include " process.h"
6
8
#include " secdrv_ioctl.h"
7
9
10
+ template <typename T>
11
+ inline T WordSwap (T w) {
12
+ USHORT temp;
13
+
14
+ temp = ((*((USHORT*)&w) & 0xff00 ) >> 8 );
15
+ temp |= ((*((USHORT*)&w) & 0x00ff ) << 8 );
16
+
17
+ return *((T*)&temp);
18
+ }
19
+
20
+ template <typename T>
21
+ inline T DWordSwap (T dw) {
22
+ ULONG temp;
23
+
24
+ temp = *((ULONG*)&dw) >> 24 ;
25
+ temp |= ((*((ULONG*)&dw) & 0x00FF0000 ) >> 8 );
26
+ temp |= ((*((ULONG*)&dw) & 0x0000FF00 ) << 8 );
27
+ temp |= ((*((ULONG*)&dw) & 0x000000FF ) << 24 );
28
+
29
+ return *((T*)&temp);
30
+ }
31
+
8
32
NTSTATUS NTAPI hooks::NtDeviceIoControlFile_Hook (HANDLE FileHandle,
9
33
HANDLE Event,
10
34
PIO_APC_ROUTINE ApcRoutine,
@@ -19,20 +43,67 @@ NTSTATUS NTAPI hooks::NtDeviceIoControlFile_Hook(HANDLE FileHandle,
19
43
20
44
/* all IOCTLs will pass through this function, but it's probably fine since
21
45
* secdrv uses unique control codes */
22
- if ( IoControlCode == secdrvIoctl::ioctlCodeMain ) {
23
- if ( secdrvIoctl::ProcessMainIoctl (InputBuffer,
46
+ if (IoControlCode == secdrvIoctl::ioctlCodeMain) {
47
+ if (secdrvIoctl::ProcessMainIoctl (InputBuffer,
24
48
InputBufferLength,
25
49
OutputBuffer,
26
- OutputBufferLength) ) {
50
+ OutputBufferLength)) {
27
51
IoStatusBlock->Information = OutputBufferLength;
28
52
IoStatusBlock->Status = STATUS_SUCCESS;
29
53
}
30
54
else IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
31
55
}
32
- else if ( IoControlCode == 0xCA002813 ) {
56
+ else if (IoControlCode == 0xCA002813 ) {
33
57
spdlog::error (" IOCTL 0xCA002813 unhandled (please report!)" );
34
58
IoStatusBlock->Status = STATUS_UNSUCCESSFUL;
35
59
}
60
+ else if (IoControlCode == IOCTL_SCSI_PASS_THROUGH) {
61
+ // Remember input data buffer size and sense info size for later
62
+ SCSI_PASS_THROUGH* inStruct = (SCSI_PASS_THROUGH*)InputBuffer;
63
+ ULONG inSenseSize = inStruct->SenseInfoLength ;
64
+ ULONG inDataSize = inStruct->DataTransferLength ;
65
+
66
+ // Execute the original function
67
+ NTSTATUS result = NtDeviceIoControlFile_Orig (FileHandle, Event, ApcRoutine, ApcContext,
68
+ IoStatusBlock, IoControlCode, InputBuffer,
69
+ InputBufferLength, OutputBuffer,
70
+ OutputBufferLength);
71
+
72
+ // This is a workaround for a bug in Alcohol SATA controller where it doesn't return
73
+ // "LBA out of range" error for out-of-range sectors.
74
+ //
75
+ // This breaks SafeDisc disc check on later versions since it tries to read track 1 pregap
76
+ // (negative LBA) to see if the drive supports it. Alcohol doesn't return an error for these
77
+ // sectors despite not being able to output them so SafeDisc keeps happily reading pregap sectors
78
+ // and then fails the disc check since Alcohol doesn't actually output valid sector data.
79
+ if (result == STATUS_SUCCESS && inStruct && inSenseSize && inDataSize) {
80
+ UCHAR* senseBuffer = (UCHAR*)inStruct + inStruct->SenseInfoOffset ;
81
+ UCHAR cmd = inStruct->Cdb [0x00 ];
82
+
83
+ if (cmd == 0x28 || cmd == 0xBE ) { // READ (10), READ CD
84
+ LONG lba = DWordSwap (*(LONG*)(inStruct->Cdb + 2 ));
85
+
86
+ if (lba < 0 && inStruct->ScsiStatus == 0x00 && inStruct->DataTransferLength == 0x00 ) {
87
+ // If no error was returned for negative LBA but output buffer is empty, this is bugged
88
+ // Alcohol behavior and we need to manually write the error.
89
+ spdlog::info (" Incorrect output from disc drive when reading sector {}, "
90
+ " manually returning LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE" , lba);
91
+
92
+ inStruct->ScsiStatus = 0x02 ; // CHECK_CONDITION
93
+ inStruct->SenseInfoLength = std::min (0x12ul , inSenseSize);
94
+ memset (senseBuffer, 0x00 , inStruct->SenseInfoLength );
95
+
96
+ senseBuffer[0x00 ] = 0xf0 ; // response code
97
+ senseBuffer[0x02 ] = 0x05 ; // ILLEGAL_REQUEST
98
+ senseBuffer[0x07 ] = 0x0a ; // length
99
+ senseBuffer[0x0c ] = 0x21 ; // LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE
100
+ senseBuffer[0x0d ] = 0x00 ;
101
+ }
102
+ }
103
+ }
104
+
105
+ return result;
106
+ }
36
107
else {
37
108
// not a secdrv request, pass to original function
38
109
return NtDeviceIoControlFile_Orig (FileHandle, Event, ApcRoutine, ApcContext,
0 commit comments