Redesign of the server communication protocol to allow arbitrary sized
[wine] / misc / system.c
1 /*
2  * SYSTEM DLL routines
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windef.h"
8 #include "wingdi.h"
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "services.h"
12 #include "callback.h"
13 #include "stackframe.h"
14 #include "builtin16.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(system);
18
19 typedef struct
20 {
21     SYSTEMTIMERPROC callback;  /* NULL if not in use */
22     INT     rate;
23     INT     ticks;
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;
31 static HANDLE SYS_Service = INVALID_HANDLE_VALUE;
32
33
34 /***********************************************************************
35  *           SYSTEM_TimerTick
36  */
37 static void CALLBACK SYSTEM_TimerTick( ULONG_PTR arg )
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;
47             SYS_Timers[i].callback( i+1 );
48         }
49     }
50 }
51
52 /**********************************************************************
53  *           SYSTEM_StartTicks
54  *
55  * Start the system tick timer.
56  */
57 static void SYSTEM_StartTicks(void)
58 {
59     if ( SYS_Service == INVALID_HANDLE_VALUE )
60         SYS_Service = SERVICE_AddTimer( (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0L );
61 }
62
63
64 /**********************************************************************
65  *           SYSTEM_StopTicks
66  *
67  * Stop the system tick timer.
68  */
69 static void SYSTEM_StopTicks(void)
70 {
71     if ( SYS_Service != INVALID_HANDLE_VALUE )
72     {
73         SERVICE_Delete( SYS_Service );
74         SYS_Service = INVALID_HANDLE_VALUE;
75     }
76 }
77
78
79 /***********************************************************************
80  *           InquireSystem   (SYSTEM.1)
81  *
82  * Note: the function always takes 2 WORD arguments, contrary to what
83  *       "Undocumented Windows" says.
84   */
85 DWORD WINAPI InquireSystem16( WORD code, WORD arg )
86 {
87     WORD drivetype;
88
89     switch(code)
90     {
91     case 0:  /* Get timer resolution */
92         return SYS_TIMER_RATE;
93
94     case 1:  /* Get drive type */
95         drivetype = GetDriveType16( arg );
96         return MAKELONG( drivetype, drivetype );
97
98     case 2:  /* Enable one-drive logic */
99         FIXME("Case %d: set single-drive %d not supported\n", code, arg );
100         return 0;
101     }
102     WARN("Unknown code %d\n", code );
103     return 0;
104 }
105
106
107 /***********************************************************************
108  *           CreateSystemTimer   (SYSTEM.2)
109  */
110 WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
111 {
112     int i;
113     for (i = 0; i < NB_SYS_TIMERS; i++)
114         if (!SYS_Timers[i].callback)  /* Found one */
115         {
116             SYS_Timers[i].rate = (UINT)rate * 1000;
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;
121             if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
122             return i + 1;  /* 0 means error */
123         }
124     return 0;
125 }
126
127 /**********************************************************************/
128
129 static void SYSTEM_CallSystemTimerProc( FARPROC16 proc, WORD timer )
130 {
131     CONTEXT86 context;
132     memset( &context, '\0', sizeof(context) );
133
134     context.SegCs = SELECTOROF( proc );
135     context.Eip   = OFFSETOF( proc );
136     context.Ebp   = OFFSETOF( NtCurrentTeb()->cur_stack )
137                           + (WORD)&((STACK16FRAME*)0)->bp;
138
139     AX_reg( &context ) = timer;
140
141     wine_call_to_16_regs_short( &context, 0 );
142 }
143
144 /**********************************************************************/
145
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
154
155 /***********************************************************************
156  *           KillSystemTimer   (SYSTEM.3)
157  *
158  * Note: do not confuse this function with USER.182
159  */
160 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
161 {
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 );
166     SYS_Timers[timer-1].callback = NULL;
167
168     if (!--SYS_NbTimers) SYSTEM_StopTicks();
169     return 0;
170 }
171
172
173 /***********************************************************************
174  *           EnableSystemTimers   (SYSTEM.4)
175  */
176 void WINAPI EnableSystemTimers16(void)
177 {
178     if ( SYS_Service != INVALID_HANDLE_VALUE )
179         SERVICE_Enable( SYS_Service );
180 }
181
182
183 /***********************************************************************
184  *           DisableSystemTimers   (SYSTEM.5)
185  */
186 void WINAPI DisableSystemTimers16(void)
187 {
188     if ( SYS_Service != INVALID_HANDLE_VALUE )
189         SERVICE_Disable( SYS_Service );
190 }
191
192
193 /***********************************************************************
194  *           Get80x87SaveSize   (SYSTEM.7)
195  */
196 WORD WINAPI Get80x87SaveSize16(void)
197 {
198     return 94;
199 }
200
201
202 /***********************************************************************
203  *           Save80x87State   (SYSTEM.8)
204  */
205 void WINAPI Save80x87State16( char *ptr )
206 {
207 #ifdef __i386__
208     __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
209 #endif
210 }
211
212
213 /***********************************************************************
214  *           Restore80x87State   (SYSTEM.9)
215  */
216 void WINAPI Restore80x87State16( const char *ptr )
217 {
218 #ifdef __i386__
219     __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
220 #endif
221 }
222