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; +}