SafeDisc-1

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Here's (at last) the (long awaited ?) SafeDisc patch.

I want to thank Zsolt Rizsanyi who helped me with the CDROM ioctls (his 
implementation of IOCTL_SCSI_GET_ADDRESS has not been included in this patch, 
as I don't have the latest version), Alexandre Juliard for his help with the 
process suspension, Erich Pouech and Andreas Mohr for their help about how to 
handle the reentrant wine server calls (even if that has turned out not to be 
needed in the end), and all of those who answered my numerous questions on 
#winehq. To the ones I forgot (if any), please forgive me. If you help me 
with SafeDisc-1 I'll thank you twice :-)

As I don't speak 'legalese', here's the usual disclaimer in nglish:

This patch works on my system, and it will probably work for some of you. For 
those who can't get it to work, I'm really sorry, and I'll help if you ask 
nicely, but don't blame me or sue me.

Ok, on a more serious note, I split the patch into two files.

safedisc-safe.diff contains the code which doesn't infringe the DMCA (fixes 
and additions to wine).

        * dlls/ntdll/cdrom.c:
        Implementation of IOCTL_SCSI_PASS_THROUGH and
        IOCTL_SCSI_PASS_THROUGH_DIRECT.

        * dlls/ntdll/nt.c:
        Fixed NtQueryInformationProcess to return correct information and
        error code for ProcessDebugPort when no debugger is attached.

        * dlls/ntdll/signal_i386.c:
        Modified do_sigsegv to allow INSTR_EmulateInstruction to modify the
        exception code.

        * include/miscemu.h, memory/instr.c:
        Modified INSTR_EmulateInstruction so that int 0x01 emulation raises an
        EXCEPTION_ACCESS_VIOLATION instead of EXCEPTION_PRIV_INSTRUCTION.

        * include/wine/server_protocol.h, server/protocol.def, server/trace.c:
        Added a 'suspended' field to the init_process_done_reply structure.

        * memory/Makefile, memory/emulate.c:
        Preliminary implementation of the SharedUserData shared memory page,
        located at 0x7ffe0000.

        * scheduler/process.c:
        Reserves the SharedUserData page (PAGE_NOACCESS at 0x7ffe0000) at
        process initialization.
        Moved process suspension from the server to the client in
        start_process to avoid server call interruptions.

        * server/process.c, server/process.h, server/ptrace.c:
        Moved process suspension from the server to the client in
        start_process to avoid server call interruptions. This involves
        catching SIGSTOP in client processes to release the init_event.

safedisc-dmca.diff contains the code which *might* infringe the DMCA. In my 
opinion it doesn't, but I'm not a lawyer.

        * win32/device.c, win32/secdrv.c, include/secdrv.h:
        Implementation of the SafeDisc secdrv.sys NT driver.

This code has been written for what I call the 1.3.0 version of SafeDisc. I 
don't know how C-Dilla numbers the SafeDisc versions, but 1.3.0 is the 
version number used in communications between the SafeDisc main executable 
and secdrv.sys. The code might work for other versions, but might not. It 
will probably not work for SafeDisc-2 protected programs.

If you experience problems (crashes) when starting SafeDisc protected 
executables, I'd be very interested to hear about your problems, especially 
for SafeDisc-1 protected programs (SafeDisc-1 has a .ICD file on the CD).

Hope this will help someone.

Laurent Pinchart
Index: win32/Makefile.in
===================================================================
RCS file: /home/wine/wine/win32/Makefile.in,v
retrieving revision 1.11
diff -u -r1.11 Makefile.in
--- win32/Makefile.in	29 Mar 2002 18:17:35 -0000	1.11
+++ win32/Makefile.in	28 Apr 2002 21:28:54 -0000
@@ -13,6 +13,7 @@
 	init.c \
 	kernel32.c \
 	newfns.c \
+	secdrv.c \
 	time.c
 
 all: $(MODULE).o
Index: win32/device.c
===================================================================
RCS file: /home/wine/wine/win32/device.c,v
retrieving revision 1.60
diff -u -r1.60 device.c
--- win32/device.c	21 Apr 2002 22:09:47 -0000	1.60
+++ win32/device.c	28 Apr 2002 21:28:58 -0000
@@ -40,6 +40,7 @@
 #include "msdos.h"
 #include "miscemu.h"
 #include "stackframe.h"
+#include "secdrv.h"
 #include "wine/server.h"
 #include "wine/debug.h"
 
@@ -103,6 +104,12 @@
 			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
 			      LPDWORD lpcbBytesReturned,
 			      LPOVERLAPPED lpOverlapped);
+
+static BOOL DeviceIo_SECDRV (DWORD dwIoControlCode, 
+			      LPVOID lpvInBuffer, DWORD cbInBuffer,
+			      LPVOID lpvOutBuffer, DWORD cbOutBuffer,
+			      LPDWORD lpcbBytesReturned,
+			      LPOVERLAPPED lpOverlapped);
 /*
  * VxD names are taken from the Win95 DDK
  */
@@ -249,6 +256,9 @@
     /* WINE additions, ids unknown */
     { "MONODEBG.VXD", 0x4242, NULL, DeviceIo_MONODEBG },
 
+    /* SafeDisc copy protection */
+    { "SECDRV", 0xef00, NULL, NULL },
+
     { NULL,       0,      NULL, NULL }
 };
 
@@ -477,6 +487,12 @@
     			SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
     			return FALSE;
     			break;
+		case CTL_CODE( 0xef00, 0x901, METHOD_NEITHER, FILE_ANY_ACCESS ):
+			return DeviceIo_SECDRV( dwIoControlCode, 
+                                                lpvInBuffer, cbInBuffer, 
+                                                lpvOutBuffer, cbOutBuffer, 
+                                                lpcbBytesReturned, lpOverlapped );
+			break;
 		default:
     			FIXME( "ignored dwIoControlCode=%08lx\n",dwIoControlCode);
     			SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
@@ -1499,6 +1515,31 @@
 	}
 	return TRUE;
 }
+
+/* this is used by SafeDisc copy protection */
+static BOOL DeviceIo_SECDRV(DWORD dwIoControlCode, 
+			    LPVOID lpvInBuffer, DWORD cbInBuffer,
+			    LPVOID lpvOutBuffer, DWORD cbOutBuffer,
+			    LPDWORD lpcbBytesReturned,
+			    LPOVERLAPPED lpOverlapped)
+{
+	switch ((dwIoControlCode >> 2) & 0x0fff) {
+	case 0x901:	/* SafeDisc */
+		return SECDRV_DeviceIo_SafeDisc(lpvInBuffer, cbInBuffer,
+					        lpvOutBuffer, cbOutBuffer);
+	default:
+		FIXME("(%ld,%p,%ld,%p,%ld,%p,%p): stub\n",
+			dwIoControlCode,
+			lpvInBuffer,cbInBuffer,
+			lpvOutBuffer,cbOutBuffer,
+			lpcbBytesReturned,
+			lpOverlapped
+		);
+		break;
+	}
+	return FALSE;
+}
+
 /* pccard */
 static BOOL DeviceIo_PCCARD (DWORD dwIoControlCode, 
 			      LPVOID lpvInBuffer, DWORD cbInBuffer,
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ win32/secdrv.c	Sun Apr 14 16:18:36 2002
@@ -0,0 +1,189 @@
+/*
+ * SafeDisc copy protection driver
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winerror.h"
+#include "file.h"
+#include "winioctl.h"
+#include "winnt.h"
+#include "secdrv.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(vxd);
+
+static BOOL SECDRV_GetDRInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			      LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static BOOL SECDRV_GetIdtInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static BOOL SECDRV_Setup( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			  LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer );
+static VOID SECDRV_BuildVerificationData( LPVOID lpBuffer );
+
+static unsigned int contextDr1 = 0x00000000;
+static unsigned int contextDr7 = 0x00000400;
+
+BOOL SECDRV_DeviceIo_SafeDisc( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, DWORD cbOutBuffer )
+{
+	PSECDRV_IOC_IN_BUFFER pInBuffer   = (PSECDRV_IOC_IN_BUFFER)lpvInBuffer;
+	PSECDRV_IOC_OUT_BUFFER pOutBuffer = (PSECDRV_IOC_OUT_BUFFER)lpvOutBuffer;
+	BOOL retv;
+
+	if ( ! pInBuffer || ! pOutBuffer )
+		return FALSE;
+
+	if ( cbInBuffer != 0x514 || cbOutBuffer != 0x610 )
+		return FALSE;
+
+	retv = FALSE;
+
+	switch( pInBuffer->dwCommand ) {
+	case SECDRV_CMD_INFO_DR:
+		retv = SECDRV_GetDRInfo( pInBuffer->bUserData, pInBuffer->cbUserData,
+					 pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	case SECDRV_CMD_INFO_IDT:
+		retv = SECDRV_GetIdtInfo( pInBuffer->bUserData, pInBuffer->cbUserData,
+					  pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	case SECDRV_CMD_SETUP:
+		retv = SECDRV_Setup( pInBuffer->bUserData, pInBuffer->cbUserData,
+				     pOutBuffer->bUserData, &pOutBuffer->cbUserData );
+		break;
+	default:
+		FIXME( "unsupported command\n" );
+		break;
+	}
+
+	if ( retv )
+	{
+	    pOutBuffer->dwVersionMajor = 1;
+	    pOutBuffer->dwVersionMinor = 3;
+	    pOutBuffer->dwVersionPatch = 0;
+	    SECDRV_BuildVerificationData( pOutBuffer->bVerificationData );
+	}
+
+	return retv;
+}
+
+static VOID SECDRV_BuildVerificationData( LPVOID lpBuffer )
+{
+	DWORD dwRandom = 0xf367ac7f;
+	LPDWORD lpDwBuffer = (LPDWORD)lpBuffer;
+	int i;
+
+	/* lpDwBuffer[0] should be initialized with KeTickCount.LowPart.
+	 * If done, KeTickCount.LowPart should also be accessible from user
+	 * space by a read operation at address 0x7ffe0000.
+	 */
+	lpDwBuffer[0] = 0x12345678;
+
+	for ( i = 3; i != 0; --i )
+	{
+		dwRandom = 0x361962e9 - dwRandom * 0x0d5acb1b;
+		lpDwBuffer[i]  = dwRandom;
+		lpDwBuffer[0] ^= dwRandom;
+	}
+}
+
+static BOOL SECDRV_GetDRInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			      LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	unsigned int dwDebugRegister;
+
+//	FIXME( "SECDRV_GetDRInfo not supported yet\n" );
+
+	if ( cbInBuffer != 0 )
+	{
+		FIXME( "cbInBuffer != 0\n" );
+		return FALSE;
+	}
+
+	if ( contextDr1 == 0xbd331200 )
+	{
+		/* I don't understand why. It's not even a valid DR7 value */
+		dwDebugRegister = 0x3871dd10;
+	}
+	else
+	{
+		dwDebugRegister = contextDr7;
+	}
+
+	*(LPDWORD)lpvOutBuffer = dwDebugRegister & 0x00000500;
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
+			      
+static BOOL SECDRV_GetIdtInfo( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			       LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	struct _IDTR {
+		WORD limit;
+		DWORD base;
+	} idtr;
+
+	ULONGLONG *idt;
+	DWORD dwOffset;
+
+	if ( cbInBuffer != 0 )
+		return FALSE;
+
+	asm( "sidtl %0" : "=m"(idtr) );
+	idt = (ULONGLONG*)idtr.base;
+
+//	dwOffset = ( idt[3] & 0x0000ffff ) - ( idt[1] & 0x0000ffff );
+	dwOffset = 0x1000;
+
+	if ( dwOffset > 0x100 )
+	{
+		*(LPDWORD)lpvOutBuffer = 0x2c8;
+	}
+	else
+	{
+		*(LPDWORD)lpvOutBuffer = dwOffset;
+		contextDr1 = 0xbd331200;
+	}
+
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
+
+static BOOL SECDRV_Setup( LPVOID lpvInBuffer, DWORD cbInBuffer,
+			  LPVOID lpvOutBuffer, LPDWORD lpCbOutBuffer )
+{
+	if ( cbInBuffer != 0 )
+		return FALSE;
+
+	*(LPDWORD)lpvOutBuffer = 0x5278d11b;
+	*lpCbOutBuffer = 4;
+
+	return TRUE;
+}
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ include/secdrv.h	Sat Apr  6 23:32:54 2002
@@ -0,0 +1,58 @@
+/*
+ * SafeDisc copy protection driver
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_SECDRV_H
+#define __WINE_SECDRV_H
+
+#include "windef.h"
+
+typedef struct _SECDRV_IOC_IN_BUFFER
+{
+    DWORD dwVersionMajor;
+    DWORD dwVersionMinor;
+    DWORD dwVersionPatch;
+
+    DWORD dwCommand;
+    BYTE bVerificationData[0x400];
+
+    DWORD cbUserData;
+    BYTE  bUserData[0x100];
+} SECDRV_IOC_IN_BUFFER, *PSECDRV_IOC_IN_BUFFER;
+
+typedef struct _SECDRV_IOC_OUT_BUFFER
+{
+    DWORD dwVersionMajor;
+    DWORD dwVersionMinor;
+    DWORD dwVersionPatch;
+
+    BYTE  bVerificationData[0x400];
+
+    DWORD cbUserData;
+    BYTE  bUserData[0x200];
+} SECDRV_IOC_OUT_BUFFER, *PSECDRV_IOC_OUT_BUFFER;
+
+#define SECDRV_CMD_INFO_DR		(0x0000003c)
+#define SECDRV_CMD_INFO_IDT		(0x0000003d)
+#define SECDRV_CMD_SETUP		(0x0000003e)
+
+extern BOOL SECDRV_DeviceIo_SafeDisc( LPVOID lpvInBuffer, DWORD cbInBuffer,
+				      LPVOID lpvOutBuffer, DWORD cbOutBuffer );
+
+#endif /* __WINE_SECDRV_H */
Index: dlls/ntdll/cdrom.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/cdrom.c,v
retrieving revision 1.7
diff -u -r1.7 cdrom.c
--- dlls/ntdll/cdrom.c	2 Apr 2002 19:19:49 -0000	1.7
+++ dlls/ntdll/cdrom.c	28 Apr 2002 21:28:00 -0000
@@ -31,10 +31,14 @@
 #include "winioctl.h"
 #include "ntddstor.h"
 #include "ntddcdrm.h"
+#include "ntddscsi.h"
 #include "drive.h"
 #include "file.h"
 #include "wine/debug.h"
 
+//#ifdef HAVE_ASM_PARAM_H
+#include <asm/param.h>
+//#endif
 #ifdef HAVE_LINUX_CDROM_H
 # include <linux/cdrom.h>
 #endif
@@ -830,6 +834,159 @@
 }
 
 /******************************************************************
+ *		CDROM_ScsiPassThroughDirect
+ *
+ *
+ */
+static DWORD CDROM_ScsiPassThroughDirect(int dev, PSCSI_PASS_THROUGH_DIRECT pPacket)
+{
+    int ret = STATUS_NOT_SUPPORTED;
+#if defined(linux)
+    struct cdrom_generic_command cmd;
+    struct request_sense sense;
+    int io;
+
+    if (pPacket->Length < sizeof(SCSI_PASS_THROUGH_DIRECT))
+	return STATUS_BUFFER_TOO_SMALL;
+
+    if (pPacket->CdbLength > 12)
+        return STATUS_INVALID_PARAMETER;
+
+    if (pPacket->SenseInfoLength > sizeof(sense))
+        return STATUS_INVALID_PARAMETER;
+
+    memset(&cmd, 0, sizeof(cmd));
+    memset(&sense, 0, sizeof(sense));
+
+    memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength);
+
+    cmd.buffer         = pPacket->DataBuffer;
+    cmd.buflen         = pPacket->DataTransferLength;
+    cmd.sense          = &sense;
+    cmd.quiet          = 0;
+    cmd.timeout        = pPacket->TimeOutValue*HZ;
+
+    switch (pPacket->DataIn)
+    {
+    case SCSI_IOCTL_DATA_OUT:
+        cmd.data_direction = CGC_DATA_WRITE;
+	break;
+    case SCSI_IOCTL_DATA_IN:
+        cmd.data_direction = CGC_DATA_READ;
+	break;
+    case SCSI_IOCTL_DATA_UNSPECIFIED:
+        cmd.data_direction = CGC_DATA_NONE;
+	break;
+    default:
+       return STATUS_INVALID_PARAMETER;
+       break;
+    }
+
+    io = ioctl(dev, CDROM_SEND_PACKET, &cmd);
+
+    if (pPacket->SenseInfoLength != 0)
+    {
+        memcpy((char*)pPacket + pPacket->SenseInfoOffset,
+	       &sense, pPacket->SenseInfoLength);
+    }
+
+    pPacket->ScsiStatus = cmd.stat;
+
+    ret = CDROM_GetStatusCode(io);
+#endif
+    return ret;
+}
+
+/******************************************************************
+ *		CDROM_ScsiPassThrough
+ *
+ *
+ */
+static DWORD CDROM_ScsiPassThrough(int dev, PSCSI_PASS_THROUGH pPacket)
+{
+    int ret = STATUS_NOT_SUPPORTED;
+#if defined(linux)
+    struct cdrom_generic_command cmd;
+    struct request_sense sense;
+    int io;
+
+    if (pPacket->Length < sizeof(SCSI_PASS_THROUGH))
+	return STATUS_BUFFER_TOO_SMALL;
+
+    if (pPacket->CdbLength > 12)
+        return STATUS_INVALID_PARAMETER;
+
+    if (pPacket->SenseInfoLength > sizeof(sense))
+        return STATUS_INVALID_PARAMETER;
+
+    memset(&cmd, 0, sizeof(cmd));
+    memset(&sense, 0, sizeof(sense));
+
+    memcpy(&(cmd.cmd), &(pPacket->Cdb), pPacket->CdbLength);
+
+    if ( pPacket->DataBufferOffset > 0x1000 )
+    {
+        cmd.buffer     = (void*)pPacket->DataBufferOffset;
+    }
+    else
+    {
+        cmd.buffer     = ((void*)pPacket) + pPacket->DataBufferOffset;
+    }
+    cmd.buflen         = pPacket->DataTransferLength;
+    cmd.sense          = &sense;
+    cmd.quiet          = 0;
+    cmd.timeout        = pPacket->TimeOutValue*HZ;
+
+    switch (pPacket->DataIn)
+    {
+    case SCSI_IOCTL_DATA_OUT:
+        cmd.data_direction = CGC_DATA_WRITE;
+	break;
+    case SCSI_IOCTL_DATA_IN:
+        cmd.data_direction = CGC_DATA_READ;
+	break;
+    case SCSI_IOCTL_DATA_UNSPECIFIED:
+        cmd.data_direction = CGC_DATA_NONE;
+	break;
+    default:
+       return STATUS_INVALID_PARAMETER;
+       break;
+    }
+
+    io = ioctl(dev, CDROM_SEND_PACKET, &cmd);
+
+    if (pPacket->SenseInfoLength != 0)
+    {
+        memcpy((char*)pPacket + pPacket->SenseInfoOffset,
+	       &sense, pPacket->SenseInfoLength);
+    }
+
+    pPacket->ScsiStatus = cmd.stat;
+
+    ret = CDROM_GetStatusCode(io);
+#endif
+    return ret;
+}
+
+/******************************************************************
+ *		CDROM_ScsiGetAddress
+ *
+ *
+ */
+static DWORD CDROM_ScsiGetAddress(int dev, PSCSI_ADDRESS addr)
+{
+    FIXME("IOCTL_SCSI_GET_ADDRESS: stub\n");
+
+    addr->Length = sizeof(SCSI_ADDRESS);
+    addr->PortNumber = 0;
+    addr->PathId = 0;
+    addr->TargetId = 1;
+    addr->Lun = 0;
+
+    return 0;
+}
+
+/******************************************************************
  *		CDROM_DeviceIoControl
  *
  *
@@ -892,6 +1049,12 @@
         else error = CDROM_SetTray(dev, TRUE);
         break;
 
+    case IOCTL_CDROM_MEDIA_REMOVAL:
+	FIXME("IOCTL_CDROM_MEDIA_REMOVAL: stub\n");
+        sz = 0;
+	error = 0;
+	break;
+
     case IOCTL_DISK_MEDIA_REMOVAL:
     case IOCTL_STORAGE_MEDIA_REMOVAL:
     case IOCTL_STORAGE_EJECTION_CONTROL:
@@ -1009,6 +1172,26 @@
         else error = CDROM_RawRead(dev, (const RAW_READ_INFO*)lpInBuffer, 
                                    lpOutBuffer, nOutBufferSize, &sz);
         break;
+
+    case IOCTL_SCSI_PASS_THROUGH_DIRECT:
+        sz = sizeof(SCSI_PASS_THROUGH_DIRECT);
+        if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
+        else if (nOutBufferSize < sizeof(SCSI_PASS_THROUGH_DIRECT)) error = STATUS_BUFFER_TOO_SMALL;
+        else error = CDROM_ScsiPassThroughDirect(dev, (PSCSI_PASS_THROUGH_DIRECT)lpOutBuffer);
+        break;
+    case IOCTL_SCSI_PASS_THROUGH:
+        sz = sizeof(SCSI_PASS_THROUGH);
+        if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
+        else if (nOutBufferSize < sizeof(SCSI_PASS_THROUGH)) error = STATUS_BUFFER_TOO_SMALL;
+        else error = CDROM_ScsiPassThrough(dev, (PSCSI_PASS_THROUGH)lpOutBuffer);
+        break;
+    case IOCTL_SCSI_GET_ADDRESS:
+        sz = 0;
+        if (lpOutBuffer == NULL) error = STATUS_INVALID_PARAMETER;
+        else if (nOutBufferSize < sizeof(SCSI_ADDRESS)) error = STATUS_BUFFER_TOO_SMALL;
+        else error = CDROM_ScsiGetAddress(dev, (PSCSI_ADDRESS)lpOutBuffer);
+        break;
+
     default:
         FIXME("Unsupported IOCTL %lx\n", dwIoControlCode);
         sz = 0;
Index: dlls/ntdll/nt.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/nt.c,v
retrieving revision 1.38
diff -u -r1.38 nt.c
--- dlls/ntdll/nt.c	9 Mar 2002 23:39:09 -0000	1.38
+++ dlls/ntdll/nt.c	28 Apr 2002 21:28:02 -0000
@@ -116,15 +116,34 @@
 	IN ULONG ProcessInformationLength,
 	OUT PULONG ReturnLength)
 {
-	FIXME("(0x%08x,0x%08x,%p,0x%08lx,%p),stub!\n",
-		ProcessHandle,ProcessInformationClass,ProcessInformation,ProcessInformationLength,ReturnLength
-	);
-	/* "These are not the debuggers you are looking for." */
-	if (ProcessInformationClass == ProcessDebugPort)
-	    /* set it to 0 aka "no debugger" to satisfy copy protections */
-	    memset(ProcessInformation,0,ProcessInformationLength);
+	NTSTATUS ret = STATUS_SUCCESS;
+	ULONG len = 0;
 
-	return 0;
+	switch (ProcessInformationClass) {
+	case ProcessDebugPort:
+		/* "These are not the debuggers you are looking for." */
+		/* set it to 0 aka "no debugger" to satisfy copy protections */
+		if (ProcessInformationLength == 4)
+		{
+			memset(ProcessInformation,0,ProcessInformationLength);
+			len = 4;
+		}
+		else
+			ret = STATUS_INFO_LENGTH_MISMATCH;
+		break;
+	default:
+		FIXME("(0x%08x,0x%08x,%p,0x%08lx,%p),stub!\n",
+			ProcessHandle,ProcessInformationClass,
+			ProcessInformation,ProcessInformationLength,
+			ReturnLength
+		);
+		break;
+	}
+
+	if (ReturnLength)
+		*ReturnLength = len;
+
+	return ret;
 }
 
 /******************************************************************************
Index: dlls/ntdll/signal_i386.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/signal_i386.c,v
retrieving revision 1.34
diff -u -r1.34 signal_i386.c
--- dlls/ntdll/signal_i386.c	25 Apr 2002 21:40:56 -0000	1.34
+++ dlls/ntdll/signal_i386.c	28 Apr 2002 21:28:05 -0000
@@ -678,6 +678,7 @@
 {
     EXCEPTION_RECORD rec;
     DWORD page_fault_code = EXCEPTION_ACCESS_VIOLATION;
+    DWORD priv_instr_code = EXCEPTION_PRIV_INSTRUCTION;
 
 #ifdef CR2_sig
     /* we want the page-fault case to be fast */
@@ -707,8 +708,8 @@
     case T_SEGNPFLT:  /* Segment not present exception */
     case T_PROTFLT:   /* General protection fault */
     case T_UNKNOWN:   /* Unknown fault code */
-        if (INSTR_EmulateInstruction( context )) return;
-        rec.ExceptionCode = EXCEPTION_PRIV_INSTRUCTION;
+        if (INSTR_EmulateInstruction( context, &priv_instr_code )) return;
+        rec.ExceptionCode = priv_instr_code;
         break;
     case T_PAGEFLT:  /* Page fault */
 #ifdef CR2_sig
Index: include/miscemu.h
===================================================================
RCS file: /home/wine/wine/include/miscemu.h,v
retrieving revision 1.46
diff -u -r1.46 miscemu.h
--- include/miscemu.h	10 Mar 2002 00:02:34 -0000	1.46
+++ include/miscemu.h	28 Apr 2002 21:28:15 -0000
@@ -167,7 +167,7 @@
 extern UINT DOSMEM_MapLinearToDos(LPVOID); /* linear Wine to DOS */
 
 /* memory/instr.c */
-extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context );
+extern BOOL INSTR_EmulateInstruction( CONTEXT86 *context, DWORD *exception_code );
 
 /* msdos/interrupts.c */
 typedef void (WINAPI *INTPROC)(CONTEXT86*);
Index: include/wine/server_protocol.h
===================================================================
RCS file: /home/wine/wine/include/wine/server_protocol.h,v
retrieving revision 1.35
diff -u -r1.35 server_protocol.h
--- include/wine/server_protocol.h	25 Apr 2002 22:58:59 -0000	1.35
+++ include/wine/server_protocol.h	28 Apr 2002 21:28:21 -0000
@@ -296,6 +296,7 @@
 struct init_process_done_reply
 {
     struct reply_header __header;
+    int          suspended;
     int          debugged;
 };
 
@@ -3198,6 +3199,6 @@
     struct get_window_properties_reply get_window_properties_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 79
+#define SERVER_PROTOCOL_VERSION 80
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
Index: memory/Makefile.in
===================================================================
RCS file: /home/wine/wine/memory/Makefile.in,v
retrieving revision 1.7
diff -u -r1.7 Makefile.in
--- memory/Makefile.in	14 Nov 2000 01:54:50 -0000	1.7
+++ memory/Makefile.in	28 Apr 2002 21:28:26 -0000
@@ -8,6 +8,7 @@
 C_SRCS = \
 	atom.c \
 	codepage.c \
+	emulate.c \
 	environ.c \
 	global.c \
 	heap.c \
Index: memory/instr.c
===================================================================
RCS file: /home/wine/wine/memory/instr.c,v
retrieving revision 1.14
diff -u -r1.14 instr.c
--- memory/instr.c	10 Mar 2002 00:18:34 -0000	1.14
+++ memory/instr.c	28 Apr 2002 21:28:28 -0000
@@ -396,7 +396,7 @@
  *
  * Emulate a privileged instruction. Returns TRUE if emulation successful.
  */
-BOOL INSTR_EmulateInstruction( CONTEXT86 *context )
+BOOL INSTR_EmulateInstruction( CONTEXT86 *context, DWORD *exception_code )
 {
     int prefix, segprefix, prefixlen, len, repX, long_op, long_addr;
     SEGPTR gpHandler;
@@ -686,7 +686,9 @@
         case 0xcd: /* int <XX> */
             if (long_op)
             {
-                ERR("int xx from 32-bit code is not supported.\n");
+                ERR("int 0x%02x from 32-bit code is not supported.\n", instr[1]);
+                if (instr[1] == 0x01)
+                    *exception_code = EXCEPTION_ACCESS_VIOLATION;
                 break;  /* Unable to emulate it */
             }
             else
Index: scheduler/process.c
===================================================================
RCS file: /home/wine/wine/scheduler/process.c,v
retrieving revision 1.178
diff -u -r1.178 process.c
--- scheduler/process.c	26 Apr 2002 19:05:17 -0000	1.178
+++ scheduler/process.c	28 Apr 2002 21:28:35 -0000
@@ -25,6 +25,7 @@
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -42,6 +43,7 @@
 #include "wine/server.h"
 #include "options.h"
 #include "wine/debug.h"
+#include "global.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(process);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
@@ -128,6 +130,9 @@
 /* scheduler/pthread.c */
 extern void PTHREAD_init_done(void);
 
+/* memory/emulate.c */
+extern BOOL MEMORY_SharedUserData(LPVOID, LPCVOID);
+
 extern BOOL MAIN_MainInit(void);
 
 typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 );
@@ -310,6 +315,20 @@
 	SetStdHandle( STD_ERROR_HANDLE,  current_startupinfo.hStdError  );
     }
 
+    /* Reserves a PAGE_NOACCESS at 0x7ffe0000. That page is used as shared
+     * memory between kernel space and user space (see SharedUserData in
+     * ntddk.h). It looks like it is at 0xffdf0000 on NT5. That is still to
+     * be checked.
+     */
+    if ( VirtualAlloc( (LPVOID)0x7ffe0000, 0x10000, MEM_RESERVE|MEM_COMMIT, PAGE_NOACCESS ) == (LPCVOID)0x07ffe0000 )
+    {
+	VIRTUAL_SetFaultHandler( (LPCVOID)0x7ffe0000, MEMORY_SharedUserData, 0 );
+    }
+    else
+    {
+	WARN( "Unable to map SharedUserData, SafeDisc protection won't be supported\n" );
+    }
+
     /* Now we can use the pthreads routines */
     PTHREAD_init_done();
 
@@ -336,7 +355,7 @@
  */
 static void start_process(void)
 {
-    int debugged, console_app;
+    int suspended, debugged, console_app;
     LPTHREAD_START_ROUTINE entry;
     WINE_MODREF *wm;
     HFILE main_file = main_exe_file;
@@ -377,7 +396,8 @@
         req->gui      = !console_app;
         wine_server_add_data( req, main_exe_name, strlen(main_exe_name) );
         wine_server_call( req );
-        debugged = reply->debugged;
+        suspended = reply->suspended;
+        debugged  = reply->debugged;
     }
     SERVER_END_REQ;
 
@@ -409,6 +429,8 @@
     PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 );
     /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
     if (console_app) PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
+
+    if (suspended) raise( SIGSTOP );
 
     if (TRACE_ON(relay))
         DPRINTF( "%08lx:Starting process %s (entryproc=%p)\n",
Index: server/process.c
===================================================================
RCS file: /home/wine/wine/server/process.c,v
retrieving revision 1.83
diff -u -r1.83 process.c
--- server/process.c	26 Apr 2002 19:05:18 -0000	1.83
+++ server/process.c	28 Apr 2002 21:28:40 -0000
@@ -382,6 +382,14 @@
 }
 
 
+/* signal the parent that a process init is finished */
+void process_init_done( struct process *process )
+{
+    set_event( process->init_event );
+    release_object( process->init_event );
+    process->init_event = NULL;
+}
+
 /* get a process from an id (and increment the refcount) */
 struct process *get_process_from_id( void *id )
 {
@@ -896,13 +904,27 @@
     if ((process->exe.namelen = get_req_data_size()))
         process->exe.filename = memdup( get_req_data(), process->exe.namelen );
 
-    generate_startup_debug_events( current->process, req->entry );
-    set_event( process->init_event );
-    release_object( process->init_event );
-    process->init_event = NULL;
+    generate_startup_debug_events( process, req->entry );
     if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
-    if (current->suspend + current->process->suspend > 0) stop_thread( current );
-    reply->debugged = (current->process->debugger != 0);
+
+    reply->suspended = 0;
+    reply->debugged  = (current->process->debugger != 0);
+    if (current->suspend + current->process->suspend > 0)
+    {
+        /* temporarily clear the init event so that ptrace functions work */
+        struct event *init_event = process->init_event;
+        process->init_event = NULL;
+        stop_thread( current );
+        process->init_event = init_event;
+
+        if (current->attached)
+        {
+            reply->suspended = 1;
+            continue_thread( current );  /* it will suspend itself */
+            return;
+        }
+    }
+    process_init_done( process );
 }
 
 /* open a handle to a process */
Index: server/process.h
===================================================================
RCS file: /home/wine/wine/server/process.h,v
retrieving revision 1.27
diff -u -r1.27 process.h
--- server/process.h	22 Mar 2002 00:21:23 -0000	1.27
+++ server/process.h	28 Apr 2002 21:28:40 -0000
@@ -90,6 +90,7 @@
 extern struct thread *create_process( int fd );
 extern struct process *get_process_from_id( void *id );
 extern struct process *get_process_from_handle( handle_t handle, unsigned int access );
+extern void process_init_done( struct process *process );
 extern int process_set_debugger( struct process *process, struct thread *thread );
 extern int debugger_detach( struct process* process, struct thread* debugger );
 
Index: server/protocol.def
===================================================================
RCS file: /home/wine/wine/server/protocol.def,v
retrieving revision 1.36
diff -u -r1.36 protocol.def
--- server/protocol.def	25 Apr 2002 22:58:59 -0000	1.36
+++ server/protocol.def	28 Apr 2002 21:28:45 -0000
@@ -276,6 +276,7 @@
     int          gui;          /* is it a GUI process? */
     VARARG(filename,string);   /* file name of main exe */
 @REPLY
+    int          suspended;    /* created suspended? */
     int          debugged;     /* being debugged? */
 @END
 
Index: server/ptrace.c
===================================================================
RCS file: /home/wine/wine/server/ptrace.c,v
retrieving revision 1.14
diff -u -r1.14 ptrace.c
--- server/ptrace.c	10 Mar 2002 00:18:36 -0000	1.14
+++ server/ptrace.c	28 Apr 2002 21:28:46 -0000
@@ -79,7 +79,12 @@
         switch(sig)
         {
         case SIGSTOP:  /* continue at once if not suspended */
-            if (thread && (thread->process->suspend + thread->suspend)) break;
+            if (thread && (thread->process->suspend + thread->suspend))
+            {
+                /* check if this was the self-suspend upon process init */
+                if (thread->process->init_event) process_init_done( thread->process );
+                break;
+            }
             /* fall through */
         default:  /* ignore other signals for now */
             if (thread && get_thread_single_step( thread ))
Index: server/trace.c
===================================================================
RCS file: /home/wine/wine/server/trace.c,v
retrieving revision 1.132
diff -u -r1.132 trace.c
--- server/trace.c	26 Apr 2002 19:05:18 -0000	1.132
+++ server/trace.c	28 Apr 2002 21:28:53 -0000
@@ -441,6 +441,7 @@
 
 static void dump_init_process_done_reply( const struct init_process_done_reply *req )
 {
+    fprintf( stderr, " suspended=%d,", req->suspended );
     fprintf( stderr, " debugged=%d", req->debugged );
 }
 
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ include/ntddscsi.h	Sat Apr 13 17:35:12 2002
@@ -0,0 +1,89 @@
+/*
+ * DDK definitions for scsi media access
+ *
+ * Copyright (C) 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef _NTDDSCSI_H_
+#define _NTDDSCSI_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IOCTL_SCSI_BASE FILE_DEVICE_CONTROLLER
+
+#define IOCTL_SCSI_PASS_THROUGH         CTL_CODE(IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_SCSI_MINIPORT             CTL_CODE(IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_SCSI_GET_INQUIRY_DATA     CTL_CODE(IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_GET_CAPABILITIES     CTL_CODE(IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_PASS_THROUGH_DIRECT  CTL_CODE(IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+#define IOCTL_SCSI_GET_ADDRESS          CTL_CODE(IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_RESCAN_BUS           CTL_CODE(IOCTL_SCSI_BASE, 0x0407, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_GET_DUMP_POINTERS    CTL_CODE(IOCTL_SCSI_BASE, 0x0408, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_SCSI_FREE_DUMP_POINTERS   CTL_CODE(IOCTL_SCSI_BASE, 0x0409, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_IDE_PASS_THROUGH          CTL_CODE(IOCTL_SCSI_BASE, 0x040a, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define SCSI_IOCTL_DATA_OUT             0
+#define SCSI_IOCTL_DATA_IN              1
+#define SCSI_IOCTL_DATA_UNSPECIFIED     2
+
+typedef struct _SCSI_PASS_THROUGH {
+    USHORT       Length;
+    UCHAR        ScsiStatus;
+    UCHAR        PathId;
+    UCHAR        TargetId;
+    UCHAR        Lun;
+    UCHAR        CdbLength;
+    UCHAR        SenseInfoLength;
+    UCHAR        DataIn;
+    ULONG        DataTransferLength;
+    ULONG        TimeOutValue;
+    ULONG_PTR    DataBufferOffset;
+    ULONG        SenseInfoOffset;
+    UCHAR        Cdb[16];
+} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
+
+typedef struct _SCSI_PASS_THROUGH_DIRECT {
+    USHORT       Length;
+    UCHAR        ScsiStatus;
+    UCHAR        PathId;
+    UCHAR        TargetId;
+    UCHAR        Lun;
+    UCHAR        CdbLength;
+    UCHAR        SenseInfoLength;
+    UCHAR        DataIn;
+    ULONG        DataTransferLength;
+    ULONG        TimeOutValue;
+    PVOID        DataBuffer;
+    ULONG        SenseInfoOffset;
+    UCHAR        Cdb[16];
+} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
+
+typedef struct _SCSI_ADDRESS {
+    ULONG        Length;
+    UCHAR        PortNumber;
+    UCHAR        PathId;
+    UCHAR        TargetId;
+    UCHAR        Lun;
+} SCSI_ADDRESS, *PSCSI_ADDRESS;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _NTDDSCSI_H_ */
--- /dev/null	Thu Jan  1 01:00:00 1970
+++ memory/emulate.c	Fri Apr  5 00:41:44 2002
@@ -0,0 +1,53 @@
+/*
+ * Emulation of privileged memory
+ *
+ * Copyright 2002 Laurent Pinchart
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "windef.h"
+#include "wingdi.h"
+#include "wine/winuser16.h"
+#include "module.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(virtual);
+
+#ifdef __i386__
+
+/***********************************************************************
+ *           MEMORY_SharedUserData
+ *
+ * Handles exceptions for the SharedUserData access.
+ */
+BOOL MEMORY_SharedUserData( LPVOID arg, LPCVOID addr )
+{
+    DWORD dwProtection;
+    BOOL ret;
+
+    TRACE( "MEMORY_SharedUserData\n" );
+
+    ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READWRITE, &dwProtection );
+    if ( ret )
+    {
+	*(LPDWORD)0x7ffe0000 = 0x12345678;
+	ret = VirtualProtect( (LPVOID)0x7ffe0000, 0x10000, PAGE_READONLY, &dwProtection );
+    }
+
+    return ret;
+}
+
+#endif  /* __i386__ */

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux