Fix declaration warnings in the test cases.
[wine] / dlls / kernel / system.c
1 /*
2  * SYSTEM DLL routines
3  *
4  * Copyright 1996 Alexandre Julliard
5  *
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
19  */
20
21 #define NONAMELESSUNION
22 #define NONAMELESSSTRUCT
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/winbase16.h"
29 #include "wine/winuser16.h"
30 #include "wownt32.h"
31 #include "winreg.h"
32 #include "winternl.h"
33 #include "kernel_private.h"
34 #include "kernel16_private.h"
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(system);
38
39 typedef struct
40 {
41     SYSTEMTIMERPROC callback;  /* NULL if not in use */
42     FARPROC16       callback16;
43     INT             rate;
44     INT             ticks;
45 } SYSTEM_TIMER;
46
47 #define NB_SYS_TIMERS   8
48 #define SYS_TIMER_RATE  54925
49
50 static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
51 static int SYS_NbTimers = 0;
52 static HANDLE SYS_timer;
53 static HANDLE SYS_thread;
54 static int SYS_timers_disabled;
55
56 /***********************************************************************
57  *           SYSTEM_TimerTick
58  */
59 static void CALLBACK SYSTEM_TimerTick( LPVOID arg, DWORD low, DWORD high )
60 {
61     int i;
62
63     if (SYS_timers_disabled) return;
64     for (i = 0; i < NB_SYS_TIMERS; i++)
65     {
66         if (!SYS_Timers[i].callback) continue;
67         if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
68         {
69             SYS_Timers[i].ticks += SYS_Timers[i].rate;
70             SYS_Timers[i].callback( i+1 );
71         }
72     }
73 }
74
75
76 /***********************************************************************
77  *           SYSTEM_TimerThread
78  */
79 static DWORD CALLBACK SYSTEM_TimerThread( void *dummy )
80 {
81     LARGE_INTEGER when;
82
83     if (!(SYS_timer = CreateWaitableTimerA( NULL, FALSE, NULL ))) return 0;
84
85     when.u.LowPart = when.u.HighPart = 0;
86     SetWaitableTimer( SYS_timer, &when, (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0, FALSE );
87     for (;;) SleepEx( INFINITE, TRUE );
88 }
89
90
91 /**********************************************************************
92  *           SYSTEM_StartTicks
93  *
94  * Start the system tick timer.
95  */
96 static void SYSTEM_StartTicks(void)
97 {
98     if (!SYS_thread) SYS_thread = CreateThread( NULL, 0, SYSTEM_TimerThread, NULL, 0, NULL );
99 }
100
101
102 /**********************************************************************
103  *           SYSTEM_StopTicks
104  *
105  * Stop the system tick timer.
106  */
107 static void SYSTEM_StopTicks(void)
108 {
109     if (SYS_thread)
110     {
111         CancelWaitableTimer( SYS_timer );
112         TerminateThread( SYS_thread, 0 );
113         CloseHandle( SYS_thread );
114         CloseHandle( SYS_timer );
115         SYS_thread = 0;
116     }
117 }
118
119
120 /***********************************************************************
121  *           InquireSystem   (SYSTEM.1)
122  *
123  * Note: the function always takes 2 WORD arguments, contrary to what
124  *       "Undocumented Windows" says.
125   */
126 DWORD WINAPI InquireSystem16( WORD code, WORD arg )
127 {
128     WORD drivetype;
129
130     switch(code)
131     {
132     case 0:  /* Get timer resolution */
133         return SYS_TIMER_RATE;
134
135     case 1:  /* Get drive type */
136         drivetype = GetDriveType16( arg );
137         return MAKELONG( drivetype, drivetype );
138
139     case 2:  /* Enable one-drive logic */
140         FIXME("Case %d: set single-drive %d not supported\n", code, arg );
141         return 0;
142     }
143     WARN("Unknown code %d\n", code );
144     return 0;
145 }
146
147
148 /***********************************************************************
149  *           CreateSystemTimer   (SYSTEM.2)
150  */
151 WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
152 {
153     int i;
154     for (i = 0; i < NB_SYS_TIMERS; i++)
155         if (!SYS_Timers[i].callback)  /* Found one */
156         {
157             SYS_Timers[i].rate = (UINT)rate * 1000;
158             if (SYS_Timers[i].rate < SYS_TIMER_RATE)
159                 SYS_Timers[i].rate = SYS_TIMER_RATE;
160             SYS_Timers[i].ticks = SYS_Timers[i].rate;
161             SYS_Timers[i].callback = callback;
162             if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
163             return i + 1;  /* 0 means error */
164         }
165     return 0;
166 }
167
168 /**********************************************************************/
169
170 static void call_timer_proc16( WORD timer )
171 {
172     CONTEXT86 context;
173     FARPROC16 proc = SYS_Timers[timer-1].callback16;
174
175     memset( &context, 0, sizeof(context) );
176
177     context.SegFs = wine_get_fs();
178     context.SegGs = wine_get_gs();
179     context.SegCs = SELECTOROF( proc );
180     context.Eip   = OFFSETOF( proc );
181     context.Ebp   = OFFSETOF(NtCurrentTeb()->WOW32Reserved) + (WORD)&((STACK16FRAME*)0)->bp;
182     context.Eax   = timer;
183
184     WOWCallback16Ex( 0, WCB16_REGS, 0, NULL, (DWORD *)&context );
185 }
186
187 /**********************************************************************/
188
189 WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc )
190 {
191     WORD ret = CreateSystemTimer( rate, call_timer_proc16 );
192     if (ret) SYS_Timers[ret - 1].callback16 = proc;
193     return ret;
194 }
195
196
197 /***********************************************************************
198  *           KillSystemTimer   (SYSTEM.3)
199  *
200  * Note: do not confuse this function with USER.182
201  */
202 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
203 {
204     if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback )
205         return timer;  /* Error */
206     SYS_Timers[timer-1].callback = NULL;
207     if (!--SYS_NbTimers) SYSTEM_StopTicks();
208     return 0;
209 }
210
211
212 /***********************************************************************
213  *           EnableSystemTimers   (SYSTEM.4)
214  */
215 void WINAPI EnableSystemTimers16(void)
216 {
217     SYS_timers_disabled = 0;
218 }
219
220
221 /***********************************************************************
222  *           DisableSystemTimers   (SYSTEM.5)
223  */
224 void WINAPI DisableSystemTimers16(void)
225 {
226     SYS_timers_disabled = 1;
227 }
228
229
230 /***********************************************************************
231  *           Get80x87SaveSize   (SYSTEM.7)
232  */
233 WORD WINAPI Get80x87SaveSize16(void)
234 {
235     return 94;
236 }
237
238
239 /***********************************************************************
240  *           Save80x87State   (SYSTEM.8)
241  */
242 void WINAPI Save80x87State16( char *ptr )
243 {
244 #ifdef __i386__
245     __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
246 #endif
247 }
248
249
250 /***********************************************************************
251  *           Restore80x87State   (SYSTEM.9)
252  */
253 void WINAPI Restore80x87State16( const char *ptr )
254 {
255 #ifdef __i386__
256     __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
257 #endif
258 }