Moved various DLLs to dlls/
[wine/hacks.git] / windows / timer.c
blobcc7192254725fb53c82510e82cbb3c14450c6719
1 /*
2 * Timer functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "wine/winuser16.h"
8 #include "winuser.h"
9 #include "queue.h"
10 #include "task.h"
11 #include "winproc.h"
12 #include "services.h"
13 #include "message.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(timer)
19 typedef struct tagTIMER
21 HWND hwnd;
22 HQUEUE16 hq;
23 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
24 UINT id;
25 UINT timeout;
26 HANDLE hService;
27 BOOL expired;
28 HWINDOWPROC proc;
29 } TIMER;
31 #define NB_TIMERS 34
32 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
34 static TIMER TimersArray[NB_TIMERS];
36 static CRITICAL_SECTION csTimer;
39 /***********************************************************************
40 * TIMER_Init
42 * Initialize critical section for the timer.
44 BOOL TIMER_Init( void )
46 InitializeCriticalSection( &csTimer );
47 MakeCriticalSectionGlobal( &csTimer );
49 return TRUE;
53 /***********************************************************************
54 * TIMER_ClearTimer
56 * Clear and remove a timer.
58 static void TIMER_ClearTimer( TIMER * pTimer )
60 if ( pTimer->hService != INVALID_HANDLE_VALUE )
62 SERVICE_Delete( pTimer->hService );
63 pTimer->hService = INVALID_HANDLE_VALUE;
66 if ( pTimer->expired )
68 QUEUE_DecTimerCount( pTimer->hq );
69 pTimer->expired = FALSE;
72 pTimer->hwnd = 0;
73 pTimer->msg = 0;
74 pTimer->id = 0;
75 pTimer->timeout = 0;
76 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
80 /***********************************************************************
81 * TIMER_RemoveWindowTimers
83 * Remove all timers for a given window.
85 void TIMER_RemoveWindowTimers( HWND hwnd )
87 int i;
88 TIMER *pTimer;
90 EnterCriticalSection( &csTimer );
92 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
93 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
94 TIMER_ClearTimer( pTimer );
96 LeaveCriticalSection( &csTimer );
100 /***********************************************************************
101 * TIMER_RemoveQueueTimers
103 * Remove all timers for a given queue.
105 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
107 int i;
108 TIMER *pTimer;
110 EnterCriticalSection( &csTimer );
112 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
113 if ((pTimer->hq == hqueue) && pTimer->timeout)
114 TIMER_ClearTimer( pTimer );
116 LeaveCriticalSection( &csTimer );
120 /***********************************************************************
121 * TIMER_CheckTimer
123 static void CALLBACK TIMER_CheckTimer( ULONG_PTR timer_ptr )
125 TIMER *pTimer = (TIMER *)timer_ptr;
126 HQUEUE16 wakeQueue = 0;
128 EnterCriticalSection( &csTimer );
130 /* Paranoid check to prevent a race condition ... */
131 if ( !pTimer->timeout )
133 LeaveCriticalSection( &csTimer );
134 return;
137 if ( !pTimer->expired )
139 TRACE("Timer expired: %04x, %04x, %04x, %08lx\n",
140 pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
142 pTimer->expired = TRUE;
143 wakeQueue = pTimer->hq;
146 LeaveCriticalSection( &csTimer );
148 /* Note: This has to be done outside the csTimer critical section,
149 otherwise we'll get deadlocks. */
151 if ( wakeQueue )
152 QUEUE_IncTimerCount( wakeQueue );
156 /***********************************************************************
157 * TIMER_GetTimerMsg
159 * Build a message for an expired timer.
161 BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
162 HQUEUE16 hQueue, BOOL remove )
164 TIMER *pTimer;
165 int i;
167 EnterCriticalSection( &csTimer );
169 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
170 if ( pTimer->timeout != 0 && pTimer->expired
171 && (hwnd? (pTimer->hwnd == hwnd) : (pTimer->hq == hQueue)) )
172 break;
174 if ( i == NB_TIMERS )
176 LeaveCriticalSection( &csTimer );
177 return FALSE; /* No timer */
180 TRACE("Timer got message: %04x, %04x, %04x, %08lx\n",
181 pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
183 if (remove)
184 pTimer->expired = FALSE;
186 /* Build the message */
187 msg->hwnd = pTimer->hwnd;
188 msg->message = pTimer->msg;
189 msg->wParam = pTimer->id;
190 msg->lParam = (LONG)pTimer->proc;
191 msg->time = GetTickCount();
193 LeaveCriticalSection( &csTimer );
195 return TRUE;
199 /***********************************************************************
200 * TIMER_SetTimer
202 static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
203 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
205 int i;
206 TIMER * pTimer;
208 if (!timeout) return 0;
210 EnterCriticalSection( &csTimer );
212 /* Check if there's already a timer with the same hwnd and id */
214 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
215 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
216 (pTimer->timeout != 0))
218 TIMER_ClearTimer( pTimer );
219 break;
222 if ( i == NB_TIMERS )
224 /* Find a free timer */
226 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
227 if (!pTimer->timeout) break;
229 if ( (i >= NB_TIMERS) ||
230 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
232 LeaveCriticalSection( &csTimer );
233 return 0;
237 if (!hwnd) id = i + 1;
239 /* Add the timer */
241 pTimer->hwnd = hwnd;
242 pTimer->hq = (hwnd) ? GetThreadQueue16( GetWindowThreadProcessId( hwnd, NULL ) )
243 : GetFastQueue16( );
244 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
245 pTimer->id = id;
246 pTimer->timeout = timeout;
247 pTimer->proc = (HWINDOWPROC)0;
248 if (proc) WINPROC_SetProc( &pTimer->proc, proc, type, WIN_PROC_TIMER );
250 pTimer->expired = FALSE;
251 pTimer->hService = SERVICE_AddTimer( timeout * 1000L,
252 TIMER_CheckTimer, (ULONG_PTR)pTimer );
254 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
255 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
256 (DWORD)pTimer->proc );
258 LeaveCriticalSection( &csTimer );
260 if (!id) return TRUE;
261 else return id;
265 /***********************************************************************
266 * TIMER_KillTimer
268 static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
270 int i;
271 TIMER * pTimer;
273 EnterCriticalSection( &csTimer );
275 /* Find the timer */
277 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
278 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
279 (pTimer->timeout != 0)) break;
281 if ( (i >= NB_TIMERS) ||
282 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
283 (!sys && (pTimer->msg != WM_TIMER)) ||
284 (sys && (pTimer->msg != WM_SYSTIMER)) )
286 LeaveCriticalSection( &csTimer );
287 return FALSE;
290 /* Delete the timer */
292 TIMER_ClearTimer( pTimer );
294 LeaveCriticalSection( &csTimer );
296 return TRUE;
300 /***********************************************************************
301 * SetTimer16 (USER.10)
303 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
304 TIMERPROC16 proc )
306 TRACE("%04x %d %d %08lx\n",
307 hwnd, id, timeout, (LONG)proc );
308 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
309 WIN_PROC_16, FALSE );
313 /***********************************************************************
314 * SetTimer32 (USER32.511)
316 UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
317 TIMERPROC proc )
319 TRACE("%04x %d %d %08lx\n",
320 hwnd, id, timeout, (LONG)proc );
321 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
322 WIN_PROC_32A, FALSE );
326 /***********************************************************************
327 * SetSystemTimer16 (USER.11)
329 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
330 TIMERPROC16 proc )
332 TRACE("%04x %d %d %08lx\n",
333 hwnd, id, timeout, (LONG)proc );
334 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
335 WIN_PROC_16, TRUE );
339 /***********************************************************************
340 * SetSystemTimer32 (USER32.509)
342 UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
343 TIMERPROC proc )
345 TRACE("%04x %d %d %08lx\n",
346 hwnd, id, timeout, (LONG)proc );
347 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
348 WIN_PROC_32A, TRUE );
352 /***********************************************************************
353 * KillTimer16 (USER.12)
355 BOOL16 WINAPI KillTimer16( HWND16 hwnd, UINT16 id )
357 TRACE("%04x %d\n", hwnd, id );
358 return TIMER_KillTimer( hwnd, id, FALSE );
362 /***********************************************************************
363 * KillTimer32 (USER32.354)
365 BOOL WINAPI KillTimer( HWND hwnd, UINT id )
367 TRACE("%04x %d\n", hwnd, id );
368 return TIMER_KillTimer( hwnd, id, FALSE );
372 /***********************************************************************
373 * KillSystemTimer16 (USER.182)
375 BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id )
377 TRACE("%04x %d\n", hwnd, id );
378 return TIMER_KillTimer( hwnd, id, TRUE );
382 /***********************************************************************
383 * KillSystemTimer32 (USER32.353)
385 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
387 TRACE("%04x %d\n", hwnd, id );
388 return TIMER_KillTimer( hwnd, id, TRUE );