Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 1 | /* |
| 2 | * SYSTEM DLL routines |
| 3 | * |
| 4 | * Copyright 1996 Alexandre Julliard |
| 5 | */ |
| 6 | |
Jeremy White | d3e22d9 | 2000-02-10 19:03:02 +0000 | [diff] [blame] | 7 | #include "windef.h" |
| 8 | #include "wingdi.h" |
Marcus Meissner | 04c3e1d | 1999-02-19 10:37:02 +0000 | [diff] [blame] | 9 | #include "wine/winbase16.h" |
| 10 | #include "wine/winuser16.h" |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 11 | #include "services.h" |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 12 | #include "callback.h" |
| 13 | #include "stackframe.h" |
| 14 | #include "builtin16.h" |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 15 | #include "debugtools.h" |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 16 | |
Dimitrie O. Paun | 529da54 | 2000-11-27 23:54:25 +0000 | [diff] [blame] | 17 | DEFAULT_DEBUG_CHANNEL(system); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 18 | |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 19 | typedef struct |
| 20 | { |
Ulrich Weigand | f6c4828 | 1998-12-10 10:44:38 +0000 | [diff] [blame] | 21 | SYSTEMTIMERPROC callback; /* NULL if not in use */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 22 | INT rate; |
| 23 | INT ticks; |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 24 | } SYSTEM_TIMER; |
| 25 | |
| 26 | #define NB_SYS_TIMERS 8 |
| 27 | #define SYS_TIMER_RATE 54925 |
| 28 | |
| 29 | static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS]; |
| 30 | static int SYS_NbTimers = 0; |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 31 | static HANDLE SYS_Service = INVALID_HANDLE_VALUE; |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 32 | |
Ulrich Weigand | f6c4828 | 1998-12-10 10:44:38 +0000 | [diff] [blame] | 33 | |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 34 | /*********************************************************************** |
| 35 | * SYSTEM_TimerTick |
| 36 | */ |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 37 | static void CALLBACK SYSTEM_TimerTick( ULONG_PTR arg ) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 38 | { |
| 39 | int i; |
| 40 | |
| 41 | for (i = 0; i < NB_SYS_TIMERS; i++) |
| 42 | { |
| 43 | if (!SYS_Timers[i].callback) continue; |
| 44 | if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0) |
| 45 | { |
| 46 | SYS_Timers[i].ticks += SYS_Timers[i].rate; |
Ulrich Weigand | f6c4828 | 1998-12-10 10:44:38 +0000 | [diff] [blame] | 47 | SYS_Timers[i].callback( i+1 ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 48 | } |
| 49 | } |
| 50 | } |
| 51 | |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 52 | /********************************************************************** |
| 53 | * SYSTEM_StartTicks |
| 54 | * |
| 55 | * Start the system tick timer. |
| 56 | */ |
| 57 | static void SYSTEM_StartTicks(void) |
| 58 | { |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 59 | if ( SYS_Service == INVALID_HANDLE_VALUE ) |
Alexandre Julliard | 8c8237b | 2000-05-10 04:43:32 +0000 | [diff] [blame] | 60 | SYS_Service = SERVICE_AddTimer( (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0L ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | |
| 64 | /********************************************************************** |
| 65 | * SYSTEM_StopTicks |
| 66 | * |
| 67 | * Stop the system tick timer. |
| 68 | */ |
| 69 | static void SYSTEM_StopTicks(void) |
| 70 | { |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 71 | if ( SYS_Service != INVALID_HANDLE_VALUE ) |
| 72 | { |
| 73 | SERVICE_Delete( SYS_Service ); |
| 74 | SYS_Service = INVALID_HANDLE_VALUE; |
| 75 | } |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 76 | } |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 77 | |
| 78 | |
| 79 | /*********************************************************************** |
| 80 | * InquireSystem (SYSTEM.1) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 81 | * |
| 82 | * Note: the function always takes 2 WORD arguments, contrary to what |
| 83 | * "Undocumented Windows" says. |
| 84 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 85 | DWORD WINAPI InquireSystem16( WORD code, WORD arg ) |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 86 | { |
| 87 | WORD drivetype; |
| 88 | |
| 89 | switch(code) |
| 90 | { |
| 91 | case 0: /* Get timer resolution */ |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 92 | return SYS_TIMER_RATE; |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 93 | |
| 94 | case 1: /* Get drive type */ |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 95 | drivetype = GetDriveType16( arg ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 96 | return MAKELONG( drivetype, drivetype ); |
| 97 | |
| 98 | case 2: /* Enable one-drive logic */ |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 99 | FIXME("Case %d: set single-drive %d not supported\n", code, arg ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 100 | return 0; |
| 101 | } |
Alexandre Julliard | 61fece0 | 1999-06-26 19:09:08 +0000 | [diff] [blame] | 102 | WARN("Unknown code %d\n", code ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 103 | return 0; |
| 104 | } |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 105 | |
| 106 | |
| 107 | /*********************************************************************** |
| 108 | * CreateSystemTimer (SYSTEM.2) |
| 109 | */ |
Ulrich Weigand | f6c4828 | 1998-12-10 10:44:38 +0000 | [diff] [blame] | 110 | WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback ) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 111 | { |
| 112 | int i; |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 113 | for (i = 0; i < NB_SYS_TIMERS; i++) |
| 114 | if (!SYS_Timers[i].callback) /* Found one */ |
| 115 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 116 | SYS_Timers[i].rate = (UINT)rate * 1000; |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 117 | if (SYS_Timers[i].rate < SYS_TIMER_RATE) |
| 118 | SYS_Timers[i].rate = SYS_TIMER_RATE; |
| 119 | SYS_Timers[i].ticks = SYS_Timers[i].rate; |
| 120 | SYS_Timers[i].callback = callback; |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 121 | if (++SYS_NbTimers == 1) SYSTEM_StartTicks(); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 122 | return i + 1; /* 0 means error */ |
| 123 | } |
| 124 | return 0; |
| 125 | } |
| 126 | |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 127 | /**********************************************************************/ |
| 128 | |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 129 | static void SYSTEM_CallSystemTimerProc( FARPROC16 proc, WORD timer ) |
| 130 | { |
| 131 | CONTEXT86 context; |
| 132 | memset( &context, '\0', sizeof(context) ); |
| 133 | |
Alexandre Julliard | d8fab2e | 2000-09-25 23:53:07 +0000 | [diff] [blame] | 134 | context.SegCs = SELECTOROF( proc ); |
| 135 | context.Eip = OFFSETOF( proc ); |
| 136 | context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack ) |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 137 | + (WORD)&((STACK16FRAME*)0)->bp; |
| 138 | |
| 139 | AX_reg( &context ) = timer; |
| 140 | |
Alexandre Julliard | e296bf3 | 2000-11-29 19:39:30 +0000 | [diff] [blame] | 141 | wine_call_to_16_regs_short( &context, 0 ); |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 144 | /**********************************************************************/ |
| 145 | |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 146 | WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc ) |
| 147 | { |
| 148 | FARPROC thunk = THUNK_Alloc( proc, (RELAY)SYSTEM_CallSystemTimerProc ); |
| 149 | WORD timer = CreateSystemTimer( rate, (SYSTEMTIMERPROC)thunk ); |
| 150 | if (!timer) THUNK_Free( thunk ); |
| 151 | return timer; |
| 152 | } |
| 153 | |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 154 | |
| 155 | /*********************************************************************** |
| 156 | * KillSystemTimer (SYSTEM.3) |
| 157 | * |
| 158 | * Note: do not confuse this function with USER.182 |
| 159 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 160 | WORD WINAPI SYSTEM_KillSystemTimer( WORD timer ) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 161 | { |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 162 | if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback ) |
| 163 | return timer; /* Error */ |
| 164 | |
| 165 | THUNK_Free( (FARPROC)SYS_Timers[timer-1].callback ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 166 | SYS_Timers[timer-1].callback = NULL; |
Ulrich Weigand | 974fd10 | 1999-09-20 18:45:53 +0000 | [diff] [blame] | 167 | |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 168 | if (!--SYS_NbTimers) SYSTEM_StopTicks(); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 169 | return 0; |
| 170 | } |
| 171 | |
| 172 | |
| 173 | /*********************************************************************** |
| 174 | * EnableSystemTimers (SYSTEM.4) |
| 175 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 176 | void WINAPI EnableSystemTimers16(void) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 177 | { |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 178 | if ( SYS_Service != INVALID_HANDLE_VALUE ) |
| 179 | SERVICE_Enable( SYS_Service ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | |
| 183 | /*********************************************************************** |
| 184 | * DisableSystemTimers (SYSTEM.5) |
| 185 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 186 | void WINAPI DisableSystemTimers16(void) |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 187 | { |
Ulrich Weigand | 06bcab8 | 1999-04-11 15:04:00 +0000 | [diff] [blame] | 188 | if ( SYS_Service != INVALID_HANDLE_VALUE ) |
| 189 | SERVICE_Disable( SYS_Service ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 190 | } |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 191 | |
| 192 | |
| 193 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 194 | * Get80x87SaveSize (SYSTEM.7) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 195 | */ |
Patrik Stridvall | b8684a2 | 1999-07-31 17:32:05 +0000 | [diff] [blame] | 196 | WORD WINAPI Get80x87SaveSize16(void) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 197 | { |
| 198 | return 94; |
| 199 | } |
| 200 | |
| 201 | |
| 202 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 203 | * Save80x87State (SYSTEM.8) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 204 | */ |
Patrik Stridvall | b8684a2 | 1999-07-31 17:32:05 +0000 | [diff] [blame] | 205 | void WINAPI Save80x87State16( char *ptr ) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 206 | { |
| 207 | #ifdef __i386__ |
| 208 | __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) ); |
| 209 | #endif |
| 210 | } |
| 211 | |
| 212 | |
| 213 | /*********************************************************************** |
Patrik Stridvall | 01d5e5b | 2001-07-02 19:59:40 +0000 | [diff] [blame] | 214 | * Restore80x87State (SYSTEM.9) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 215 | */ |
Patrik Stridvall | b8684a2 | 1999-07-31 17:32:05 +0000 | [diff] [blame] | 216 | void WINAPI Restore80x87State16( const char *ptr ) |
Alexandre Julliard | 4220b29 | 1999-07-11 17:20:01 +0000 | [diff] [blame] | 217 | { |
| 218 | #ifdef __i386__ |
| 219 | __asm__(".byte 0x66; frstor %0" : : "m" (ptr) ); |
| 220 | #endif |
| 221 | } |
| 222 | |