blob: 1cc64bd6ffbcb44c7f6ea8cbab32ad4707dfafe9 [file] [log] [blame]
Alexandre Julliardef702d81996-05-28 18:54:58 +00001/*
2 * SYSTEM DLL routines
3 *
4 * Copyright 1996 Alexandre Julliard
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliardef702d81996-05-28 18:54:58 +000019 */
20
Jeremy Whited3e22d92000-02-10 19:03:02 +000021#include "windef.h"
22#include "wingdi.h"
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000023#include "wine/winbase16.h"
24#include "wine/winuser16.h"
Ulrich Weigand974fd101999-09-20 18:45:53 +000025#include "stackframe.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000026#include "wine/debug.h"
Alexandre Julliard641ee761997-08-04 16:34:36 +000027
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000028WINE_DEFAULT_DEBUG_CHANNEL(system);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000029
Alexandre Julliard641ee761997-08-04 16:34:36 +000030typedef struct
31{
Ulrich Weigandf6c48281998-12-10 10:44:38 +000032 SYSTEMTIMERPROC callback; /* NULL if not in use */
Alexandre Julliard88ff58e2001-12-17 22:13:31 +000033 FARPROC16 callback16;
34 INT rate;
35 INT ticks;
Alexandre Julliard641ee761997-08-04 16:34:36 +000036} SYSTEM_TIMER;
37
38#define NB_SYS_TIMERS 8
39#define SYS_TIMER_RATE 54925
40
41static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
42static int SYS_NbTimers = 0;
Alexandre Julliardac0e1372002-03-23 18:48:53 +000043static HANDLE SYS_timer;
44static HANDLE SYS_thread;
45static int SYS_timers_disabled;
Ulrich Weigandf6c48281998-12-10 10:44:38 +000046
Alexandre Julliard641ee761997-08-04 16:34:36 +000047/***********************************************************************
48 * SYSTEM_TimerTick
49 */
Alexandre Julliardac0e1372002-03-23 18:48:53 +000050static void CALLBACK SYSTEM_TimerTick( LPVOID arg, DWORD low, DWORD high )
Alexandre Julliard641ee761997-08-04 16:34:36 +000051{
52 int i;
53
Alexandre Julliardac0e1372002-03-23 18:48:53 +000054 if (SYS_timers_disabled) return;
Alexandre Julliard641ee761997-08-04 16:34:36 +000055 for (i = 0; i < NB_SYS_TIMERS; i++)
56 {
57 if (!SYS_Timers[i].callback) continue;
58 if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
59 {
60 SYS_Timers[i].ticks += SYS_Timers[i].rate;
Ulrich Weigandf6c48281998-12-10 10:44:38 +000061 SYS_Timers[i].callback( i+1 );
Alexandre Julliard641ee761997-08-04 16:34:36 +000062 }
63 }
64}
65
Alexandre Julliardac0e1372002-03-23 18:48:53 +000066
67/***********************************************************************
68 * SYSTEM_TimerThread
69 */
70static DWORD CALLBACK SYSTEM_TimerThread( void *dummy )
71{
72 LARGE_INTEGER when;
73
74 if (!(SYS_timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0;
75
76 when.s.LowPart = when.s.HighPart = 0;
77 SetWaitableTimer( SYS_timer, &when, (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0, FALSE );
78 for (;;) WaitForMultipleObjectsEx( 0, NULL, FALSE, INFINITE, TRUE );
79}
80
81
Alexandre Julliard641ee761997-08-04 16:34:36 +000082/**********************************************************************
83 * SYSTEM_StartTicks
84 *
85 * Start the system tick timer.
86 */
87static void SYSTEM_StartTicks(void)
88{
Alexandre Julliardac0e1372002-03-23 18:48:53 +000089 if (!SYS_thread) SYS_thread = CreateThread( NULL, 0, SYSTEM_TimerThread, NULL, 0, NULL );
Alexandre Julliard641ee761997-08-04 16:34:36 +000090}
91
92
93/**********************************************************************
94 * SYSTEM_StopTicks
95 *
96 * Stop the system tick timer.
97 */
98static void SYSTEM_StopTicks(void)
99{
Alexandre Julliardac0e1372002-03-23 18:48:53 +0000100 if (SYS_thread)
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000101 {
Alexandre Julliardac0e1372002-03-23 18:48:53 +0000102 CancelWaitableTimer( SYS_timer );
103 TerminateThread( SYS_thread, 0 );
104 CloseHandle( SYS_thread );
105 CloseHandle( SYS_timer );
106 SYS_thread = 0;
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000107 }
Alexandre Julliard641ee761997-08-04 16:34:36 +0000108}
Alexandre Julliardef702d81996-05-28 18:54:58 +0000109
110
111/***********************************************************************
112 * InquireSystem (SYSTEM.1)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000113 *
114 * Note: the function always takes 2 WORD arguments, contrary to what
115 * "Undocumented Windows" says.
116 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000117DWORD WINAPI InquireSystem16( WORD code, WORD arg )
Alexandre Julliardef702d81996-05-28 18:54:58 +0000118{
119 WORD drivetype;
120
121 switch(code)
122 {
123 case 0: /* Get timer resolution */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000124 return SYS_TIMER_RATE;
Alexandre Julliardef702d81996-05-28 18:54:58 +0000125
126 case 1: /* Get drive type */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000127 drivetype = GetDriveType16( arg );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000128 return MAKELONG( drivetype, drivetype );
129
130 case 2: /* Enable one-drive logic */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000131 FIXME("Case %d: set single-drive %d not supported\n", code, arg );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000132 return 0;
133 }
Alexandre Julliard61fece01999-06-26 19:09:08 +0000134 WARN("Unknown code %d\n", code );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000135 return 0;
136}
Alexandre Julliard641ee761997-08-04 16:34:36 +0000137
138
139/***********************************************************************
140 * CreateSystemTimer (SYSTEM.2)
141 */
Ulrich Weigandf6c48281998-12-10 10:44:38 +0000142WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000143{
144 int i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000145 for (i = 0; i < NB_SYS_TIMERS; i++)
146 if (!SYS_Timers[i].callback) /* Found one */
147 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000148 SYS_Timers[i].rate = (UINT)rate * 1000;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000149 if (SYS_Timers[i].rate < SYS_TIMER_RATE)
150 SYS_Timers[i].rate = SYS_TIMER_RATE;
151 SYS_Timers[i].ticks = SYS_Timers[i].rate;
152 SYS_Timers[i].callback = callback;
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000153 if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
Alexandre Julliard641ee761997-08-04 16:34:36 +0000154 return i + 1; /* 0 means error */
155 }
156 return 0;
157}
158
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000159/**********************************************************************/
160
Alexandre Julliard88ff58e2001-12-17 22:13:31 +0000161static void call_timer_proc16( WORD timer )
Ulrich Weigand974fd101999-09-20 18:45:53 +0000162{
163 CONTEXT86 context;
Alexandre Julliard88ff58e2001-12-17 22:13:31 +0000164 FARPROC16 proc = SYS_Timers[timer-1].callback16;
165
Ulrich Weigand974fd101999-09-20 18:45:53 +0000166 memset( &context, '\0', sizeof(context) );
167
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000168 context.SegCs = SELECTOROF( proc );
169 context.Eip = OFFSETOF( proc );
170 context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack )
Ulrich Weigand974fd101999-09-20 18:45:53 +0000171 + (WORD)&((STACK16FRAME*)0)->bp;
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000172 context.Eax = timer;
Ulrich Weigand974fd101999-09-20 18:45:53 +0000173
Alexandre Julliarde296bf32000-11-29 19:39:30 +0000174 wine_call_to_16_regs_short( &context, 0 );
Ulrich Weigand974fd101999-09-20 18:45:53 +0000175}
176
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000177/**********************************************************************/
178
Ulrich Weigand974fd101999-09-20 18:45:53 +0000179WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc )
180{
Alexandre Julliard88ff58e2001-12-17 22:13:31 +0000181 WORD ret = CreateSystemTimer( rate, call_timer_proc16 );
182 if (ret) SYS_Timers[ret - 1].callback16 = proc;
183 return ret;
Ulrich Weigand974fd101999-09-20 18:45:53 +0000184}
185
Alexandre Julliard641ee761997-08-04 16:34:36 +0000186
187/***********************************************************************
188 * KillSystemTimer (SYSTEM.3)
189 *
190 * Note: do not confuse this function with USER.182
191 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000192WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000193{
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000194 if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback )
Ulrich Weigand974fd101999-09-20 18:45:53 +0000195 return timer; /* Error */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000196 SYS_Timers[timer-1].callback = NULL;
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000197 if (!--SYS_NbTimers) SYSTEM_StopTicks();
Alexandre Julliard641ee761997-08-04 16:34:36 +0000198 return 0;
199}
200
201
202/***********************************************************************
203 * EnableSystemTimers (SYSTEM.4)
204 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000205void WINAPI EnableSystemTimers16(void)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000206{
Alexandre Julliardac0e1372002-03-23 18:48:53 +0000207 SYS_timers_disabled = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000208}
209
210
211/***********************************************************************
212 * DisableSystemTimers (SYSTEM.5)
213 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000214void WINAPI DisableSystemTimers16(void)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000215{
Alexandre Julliardac0e1372002-03-23 18:48:53 +0000216 SYS_timers_disabled = 1;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000217}
Alexandre Julliard4220b291999-07-11 17:20:01 +0000218
219
220/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000221 * Get80x87SaveSize (SYSTEM.7)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000222 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000223WORD WINAPI Get80x87SaveSize16(void)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000224{
225 return 94;
226}
227
228
229/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000230 * Save80x87State (SYSTEM.8)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000231 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000232void WINAPI Save80x87State16( char *ptr )
Alexandre Julliard4220b291999-07-11 17:20:01 +0000233{
234#ifdef __i386__
235 __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
236#endif
237}
238
239
240/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000241 * Restore80x87State (SYSTEM.9)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000242 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000243void WINAPI Restore80x87State16( const char *ptr )
Alexandre Julliard4220b291999-07-11 17:20:01 +0000244{
245#ifdef __i386__
246 __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
247#endif
248}