Re: Windows program detects debugger and quits

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

 



On Saturday 26 October 2002 01:45, Paul wrote:
> On Friday 25 October 2002 05:24 pm, Rizsanyi Zsolt wrote:
> > On Saturday 26 October 2002 00:50, Paul wrote:
> > > Thanks again for the response.
> > > The ACR disc is Safedisc 2 protected. I've used Winex to play a
> > > Safedisc2 protected game, so I understand that this is not an absolute
> > > limitation. Unfortunately, winex apparently doesn't have MDAC worked
> > > out (whatever that is) as the install crashes there.
> > >
> > > The document you sent suggests that safedisc 1 should work with the
> > > current wine version, and suggests trying different winverions. I
> > > edited my config file several times with different version but with no
> > > success. Error: A debugger has been detected. Unload debugger and try
> > > again.
> >
> > Current wine is not enough. You also need the patch for safedisc, which
> > was never applied to wine, because it has to be cleaned up before.
> > The patch was sent to wine-patches by Laurent Pinchart. But that patch
> > would not apply cleanly, because some things have changed in wine since
> > then.
> >
> > I have made the necessary changes to apply it to current cvs, I could
> > send you the patch.
> > Just you will have to wait some days till I get a definite answer to my
> > question on wine-devel. Currenlty I have a cvs conflict and I would like
> > to resolve it the correct way, and hope the help of the wine gurus for
> > that.
> >
> > Do you use cvs? Can the patch be against cvs or should be against a
> > release?
> >
> > > I'm not sure if installing with wine and running with winex would be
> > > very easy to do.
> >
> > That would not be that hard, but requires quite much work (making a
> > config file for wine which uses the root dir of winex).
> >
> > Regards
> > Zsolt
>
> My version of Wine is just the standard downloaded package
> (Wine-20021007.tar.gz) compiled and installed with the winetools script
> provided.  I have never used CVS or patched anything for that matter. I
> would love to give this a try when you are ready, but would also request
> instructions on how to patch, recompile and install the new version. I am
> sure its not too difficult, but I'm definitely an end user rather than a
> programmer.

Here is the patch (safedisc.patch).

And here are the instructions:
Since the patch is against current cvs you will have to update your
downloaded package (or you could wait for the next wine release).

To get a patch of the difference beetween your release and cvs wine you
need to run the next command, which will download the difference:
cvs -d :pserver:cvs:cvs@cvs.winehq.org:/home/wine rdiff -u -r Wine-20021007 wine > wine-cvsdiff.patch

Probably the easiest is to extract the sources again, and then go to the dir:
tar xfz Wine-2002...
cd wine

Then patch:
patch -p1 < /path/to/patch/wine-cvsdiff.patch
patch -p0 < /path/to/patch/safedisc.patch

After that you should do the compilation and installation as you have done without the patching.

Do not forget, if .wine/config has winver=nt40 and that the cd is mounted.

Then your program should run.

Write if you have any problems.

Regards
Zsolt
? include/secdrv.h
? memory/emulate.c
? win32/secdrv.c
Index: dlls/ntdll/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/Makefile.in,v
retrieving revision 1.38
diff -u -p -r1.38 Makefile.in
--- dlls/ntdll/Makefile.in	18 Oct 2002 23:46:29 -0000	1.38
+++ dlls/ntdll/Makefile.in	26 Oct 2002 15:25:31 -0000
@@ -32,6 +32,7 @@ C_SRCS = \
 	$(TOPOBJDIR)/loader/ne/segment.c \
 	$(TOPOBJDIR)/memory/atom.c \
 	$(TOPOBJDIR)/memory/codepage.c \
+	$(TOPOBJDIR)/memory/emulate.c \
 	$(TOPOBJDIR)/memory/environ.c \
 	$(TOPOBJDIR)/memory/global.c \
 	$(TOPOBJDIR)/memory/heap.c \
@@ -88,6 +89,7 @@ C_SRCS = \
 	$(TOPOBJDIR)/win32/init.c \
 	$(TOPOBJDIR)/win32/kernel32.c \
 	$(TOPOBJDIR)/win32/newfns.c \
+	$(TOPOBJDIR)/win32/secdrv.c \
 	$(TOPOBJDIR)/win32/time.c \
 	cdrom.c \
 	critsection.c \
Index: dlls/ntdll/signal_i386.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/signal_i386.c,v
retrieving revision 1.46
diff -u -p -r1.46 signal_i386.c
--- dlls/ntdll/signal_i386.c	12 Sep 2002 22:07:03 -0000	1.46
+++ dlls/ntdll/signal_i386.c	26 Oct 2002 15:25:44 -0000
@@ -729,6 +729,7 @@ static void do_segv( CONTEXT *context, i
 {
     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 */
@@ -758,8 +759,8 @@ static void do_segv( CONTEXT *context, i
     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.55
diff -u -p -r1.55 miscemu.h
--- include/miscemu.h	23 Oct 2002 22:24:10 -0000	1.55
+++ include/miscemu.h	26 Oct 2002 15:26:04 -0000
@@ -196,7 +196,7 @@ extern LPVOID DOSMEM_MapDosToLinear(UINT
 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.47
diff -u -p -r1.47 server_protocol.h
--- include/wine/server_protocol.h	21 Oct 2002 23:43:05 -0000	1.47
+++ include/wine/server_protocol.h	26 Oct 2002 15:26:13 -0000
@@ -220,6 +220,7 @@ struct get_new_process_info_reply
     thread_id_t  tid;
     obj_handle_t thandle;
     int          success;
+    obj_handle_t event;
 };
 
 
@@ -298,6 +299,7 @@ struct init_process_done_request
 struct init_process_done_reply
 {
     struct reply_header __header;
+    int          suspended;
     int          debugged;
 };
 
Index: memory/instr.c
===================================================================
RCS file: /home/wine/wine/memory/instr.c,v
retrieving revision 1.19
diff -u -p -r1.19 instr.c
--- memory/instr.c	23 Oct 2002 22:24:10 -0000	1.19
+++ memory/instr.c	26 Oct 2002 15:26:24 -0000
@@ -397,7 +397,7 @@ static void INSTR_outport( WORD port, in
  *
  * 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;
@@ -685,6 +685,11 @@ BOOL INSTR_EmulateInstruction( CONTEXT86
             break;  /* Unable to emulate it */
 
         case 0xcd: /* int <XX> */
+            if (long_op && instr[1] == 0x01)
+            {
+                *exception_code = EXCEPTION_ACCESS_VIOLATION;
+                break;
+            }
            if(!Dosvm.EmulateInterruptPM && !DPMI_LoadDosSystem())
                ERR("could not initialize interrupt handling\n");
            else {
Index: scheduler/process.c
===================================================================
RCS file: /home/wine/wine/scheduler/process.c,v
retrieving revision 1.202
diff -u -p -r1.202 process.c
--- scheduler/process.c	17 Oct 2002 18:24:36 -0000	1.202
+++ scheduler/process.c	26 Oct 2002 15:26:32 -0000
@@ -46,6 +46,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);
@@ -130,6 +131,9 @@ extern STARTUPINFOA current_startupinfo;
 /* scheduler/pthread.c */
 extern void PTHREAD_init_done(void);
 
+/* memory/emulate.c */
+extern BOOL MEMORY_SharedUserData(LPVOID, LPCVOID);
+
 extern void RELAY_InitDebugLists(void);
 extern BOOL MAIN_MainInit(void);
 
@@ -457,6 +461,20 @@ static BOOL process_init( char *argv[] )
 	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();
 
@@ -482,7 +500,7 @@ static BOOL process_init( char *argv[] )
  */
 static void start_process(void)
 {
-    int debugged, console_app;
+    int suspended, debugged, console_app;
     LPTHREAD_START_ROUTINE entry;
     WINE_MODREF *wm;
     HANDLE main_file = main_exe_file;
@@ -521,7 +539,8 @@ static void start_process(void)
         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;
 
@@ -554,6 +573,8 @@ static void start_process(void)
     /* 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",
                  GetCurrentThreadId(), main_exe_name, entry );
@@ -956,6 +977,7 @@ static BOOL create_process( HANDLE hFile
 {
     BOOL ret, success = FALSE;
     HANDLE process_info;
+    HANDLE load_done_evt = 0;
     startup_info_t startup_info;
 
     /* fill the startup info structure */
@@ -1040,10 +1062,25 @@ static BOOL create_process( HANDLE hFile
             info->hProcess    = reply->phandle;
             info->hThread     = reply->thandle;
             success           = reply->success;
+	    load_done_evt     = reply->event;
         }
     }
     SERVER_END_REQ;
 
+    /* Wait until process is initialized (or initialization failed) */
+    if (ret && load_done_evt)
+    {
+	DWORD res;
+	HANDLE handles[2];
+
+	handles[0] = info->hProcess;
+	handles[1] = load_done_evt;
+	res = WaitForMultipleObjects( 2, handles, FALSE, INFINITE );
+	CloseHandle( load_done_evt );
+	if (res == STATUS_WAIT_0)  /* the process died */
+	    success = 0;
+    }
+
     if (ret && !success)  /* new process failed to start */
     {
         DWORD exitcode;
@@ -1240,6 +1277,7 @@ BOOL WINAPI CreateProcessA( LPCSTR app_n
         TRACE( "starting %s as Windows binary\n", debugstr_a(name) );
         retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr,
                                inherit, flags, startup_info, info, unixdir );
+        TRACE( "starting of %s done\n", debugstr_a(name) );
         break;
     case BINARY_OS216:
         FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) );
Index: server/process.c
===================================================================
RCS file: /home/wine/wine/server/process.c,v
retrieving revision 1.91
diff -u -p -r1.91 process.c
--- server/process.c	19 Oct 2002 01:00:59 -0000	1.91
+++ server/process.c	26 Oct 2002 15:26:34 -0000
@@ -208,6 +208,7 @@ struct thread *create_process( int fd )
     process->startup_state   = STARTUP_IN_PROGRESS;
     process->startup_info    = NULL;
     process->idle_event      = NULL;
+    process->init_event      = NULL;
     process->queue           = NULL;
     process->atom_table      = NULL;
     process->ldt_copy        = NULL;
@@ -224,6 +225,8 @@ struct thread *create_process( int fd )
     if ((process->next = first_process) != NULL) process->next->prev = process;
     first_process = process;
 
+    if (!(process->init_event = create_event( NULL, 0, 1, 0 ))) goto error;
+
     /* create the main thread */
     if (pipe( request_pipe ) == -1)
     {
@@ -334,6 +337,7 @@ static void process_destroy( struct obje
     if (process->prev) process->prev->next = process->next;
     else first_process = process->next;
     if (process->idle_event) release_object( process->idle_event );
+    if (process->init_event) release_object( process->init_event );
     if (process->queue) release_object( process->queue );
     if (process->atom_table) release_object( process->atom_table );
     if (process->exe.file) release_object( process->exe.file );
@@ -396,6 +400,15 @@ static int startup_info_signaled( struct
     return info->process && is_process_init_done(info->process);
 }
 
+/* signal the parent that a process init is finished */
+void process_init_done( struct process *process )
+{
+    set_process_startup_state( process, STARTUP_DONE );
+    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( process_id_t id )
 {
@@ -840,6 +853,8 @@ DECL_HANDLER(get_new_process_info)
 {
     struct startup_info *info;
 
+    reply->event = 0;
+
     if ((info = (struct startup_info *)get_handle_obj( current->process, req->info,
                                                        0, &startup_info_ops )))
     {
@@ -849,6 +864,10 @@ DECL_HANDLER(get_new_process_info)
                                        PROCESS_ALL_ACCESS, req->pinherit );
         reply->thandle = alloc_handle( current->process, info->thread,
                                        THREAD_ALL_ACCESS, req->tinherit );
+	if (info->process->init_event)
+	    reply->event = alloc_handle( current->process, info->process->init_event,
+		    EVENT_ALL_ACCESS, 0 );
+
         reply->success = is_process_init_done( info->process );
         release_object( info );
     }
@@ -904,6 +923,12 @@ DECL_HANDLER(init_process_done)
     struct file *file = NULL;
     struct process *process = current->process;
 
+    if (!process->init_event)
+    {
+	fatal_protocol_error( current, "init_process_done: no event\n" );
+	return;
+    }
+
     if (is_process_init_done(process))
     {
         fatal_protocol_error( current, "init_process_done: called twice\n" );
@@ -926,11 +951,29 @@ DECL_HANDLER(init_process_done)
         process->exe.filename = memdup( get_req_data(), process->exe.namelen );
 
     generate_startup_debug_events( process, req->entry );
-    set_process_startup_state( process, STARTUP_DONE );
+    //set_process_startup_state( process, STARTUP_DONE );
 
     if (req->gui) process->idle_event = create_event( NULL, 0, 1, 0 );
-    if (current->suspend + process->suspend > 0) stop_thread( current );
+    //if (current->suspend + process->suspend > 0) stop_thread( current );
+    reply->suspended = 0;
     reply->debugged = (process->debugger != 0);
+    // my code
+    if (current->suspend + process->suspend > 0)
+    {
+	/* temporarily set the startup state so that ptrace functions work */
+	enum startup_state tstate = process->startup_state;
+	process->startup_state = STARTUP_DONE;
+	stop_thread( current );
+	process->startup_state = tstate;
+
+	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.34
diff -u -p -r1.34 process.h
--- server/process.h	3 Oct 2002 19:54:58 -0000	1.34
+++ server/process.h	26 Oct 2002 15:26:35 -0000
@@ -68,6 +68,7 @@ struct process
     enum startup_state   startup_state;   /* startup state */
     struct startup_info *startup_info;    /* startup info while init is in progress */
     struct event        *idle_event;      /* event for input idle */
+    struct event        *init_event;      /* event for input idle */
     struct msg_queue    *queue;           /* main message queue */
     struct atom_table   *atom_table;      /* pointer to local atom table */
     struct process_dll   exe;             /* main exe file */
@@ -97,6 +98,7 @@ struct module_snapshot
 extern struct thread *create_process( int fd );
 extern struct process *get_process_from_id( process_id_t id );
 extern struct process *get_process_from_handle( obj_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.48
diff -u -p -r1.48 protocol.def
--- server/protocol.def	21 Oct 2002 23:43:04 -0000	1.48
+++ server/protocol.def	26 Oct 2002 15:26:49 -0000
@@ -226,6 +226,7 @@ typedef struct
     thread_id_t  tid;          /* thread id */
     obj_handle_t thandle;      /* thread handle (in the current process) */
     int          success;      /* did the process start successfully? */
+    obj_handle_t event;        /* event handle to signal startup */
 @END
 
 
@@ -278,6 +279,7 @@ typedef struct
     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.15
diff -u -p -r1.15 ptrace.c
--- server/ptrace.c	24 May 2002 21:20:27 -0000	1.15
+++ server/ptrace.c	26 Oct 2002 15:26:49 -0000
@@ -79,7 +79,13 @@ static int handle_child_status( struct t
         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 (!is_process_init_done(thread->process))
+		    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.143
diff -u -p -r1.143 trace.c
--- server/trace.c	19 Oct 2002 01:00:59 -0000	1.143
+++ server/trace.c	26 Oct 2002 15:26:58 -0000
@@ -438,6 +438,7 @@ static void dump_init_process_done_reque
 
 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 );
 }
 
Index: win32/device.c
===================================================================
RCS file: /home/wine/wine/win32/device.c,v
retrieving revision 1.71
diff -u -p -r1.71 device.c
--- win32/device.c	3 Oct 2002 19:46:27 -0000	1.71
+++ win32/device.c	26 Oct 2002 15:27:18 -0000
@@ -42,6 +42,7 @@
 #include "msdos.h"
 #include "miscemu.h"
 #include "stackframe.h"
+#include "secdrv.h"
 #include "wine/server.h"
 #include "wine/debug.h"
 
@@ -107,6 +108,12 @@ static BOOL DeviceIo_HASP (DWORD dwIoCon
 			      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
  */
@@ -253,6 +260,9 @@ static const struct VxDInfo VxDList[] =
     /* WINE additions, ids unknown */
     { "MONODEBG.VXD", 0x4242, NULL, DeviceIo_MONODEBG },
 
+    /* SafeDisc copy protection */
+    { "SECDRV", 0xef00, NULL, NULL },
+
     { NULL,       0,      NULL, NULL }
 };
 
@@ -359,8 +369,15 @@ HANDLE DEVICE_Open( LPCWSTR filenameW, D
         if (!strncasecmp( info->name, filename, strlen(info->name) ))
             return FILE_CreateDevice( info->id | 0x10000, access, sa );
 
-    FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
-           filename);
+    if (FIXME_ON(file))
+    {
+	if ( strcmp("NTICE", filename) !=0 && strcmp("SICE", filename) !=0 )
+	    FIXME( "Unknown/unsupported VxD %s. Try setting Windows version to 'nt40' or 'win31'.\n",
+		    filename);
+	else
+	    TRACE( "Unsupported VxD %s. Programs with copy protection look for it, and if found "
+		    "they are not willing to run.\n", filename);
+    }
     SetLastError( ERROR_FILE_NOT_FOUND );
     return 0;
 }
@@ -489,6 +506,12 @@ BOOL WINAPI DeviceIoControl(HANDLE hDevi
     			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 );
@@ -2076,6 +2099,31 @@ static BOOL DeviceIo_MONODEBG(DWORD dwIo
 	}
 	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 Apr 11 16:25:15 2002
+++ include/secdrv.h	Tue Apr 30 17:11:03 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 */
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ memory/emulate.c	Tue Apr 30 17:08:22 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__ */
--- /dev/null	Thu Apr 11 16:25:15 2002
+++ win32/secdrv.c	Tue Apr 30 17:11:03 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;
+}

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

  Powered by Linux