Fixed another regression in PlaySound.
[wine.git] / windows / timer.c
blob4ba0c3c032ef4643962c60e49b232c04eaac933f
1 /*
2 * Timer functions
4 * Copyright 1993 Alexandre Julliard
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.
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.
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
21 #include "windef.h"
22 #include "wingdi.h"
23 #include "wine/winuser16.h"
24 #include "winuser.h"
25 #include "winerror.h"
27 #include "winproc.h"
28 #include "message.h"
29 #include "win.h"
30 #include "wine/server.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(timer);
36 typedef struct tagTIMER
38 HWND hwnd;
39 HQUEUE16 hq;
40 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
41 UINT id;
42 UINT timeout;
43 HWINDOWPROC proc;
44 } TIMER;
46 #define NB_TIMERS 34
47 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
49 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
51 static TIMER TimersArray[NB_TIMERS];
53 static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT("csTimer");
56 /***********************************************************************
57 * TIMER_ClearTimer
59 * Clear and remove a timer.
61 static void TIMER_ClearTimer( TIMER * pTimer )
63 pTimer->hwnd = 0;
64 pTimer->msg = 0;
65 pTimer->id = 0;
66 pTimer->timeout = 0;
67 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
71 /***********************************************************************
72 * TIMER_RemoveWindowTimers
74 * Remove all timers for a given window.
76 void TIMER_RemoveWindowTimers( HWND hwnd )
78 int i;
79 TIMER *pTimer;
81 EnterCriticalSection( &csTimer );
83 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
84 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
85 TIMER_ClearTimer( pTimer );
87 LeaveCriticalSection( &csTimer );
91 /***********************************************************************
92 * TIMER_RemoveQueueTimers
94 * Remove all timers for a given queue.
96 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
98 int i;
99 TIMER *pTimer;
101 EnterCriticalSection( &csTimer );
103 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
104 if ((pTimer->hq == hqueue) && pTimer->timeout)
105 TIMER_ClearTimer( pTimer );
107 LeaveCriticalSection( &csTimer );
111 /***********************************************************************
112 * TIMER_SetTimer
114 static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
115 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
117 int i;
118 TIMER * pTimer;
119 HWINDOWPROC winproc = 0;
121 if (hwnd && !(hwnd = WIN_IsCurrentThread( hwnd )))
123 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
124 return 0;
127 if (!timeout)
128 { /* timeout==0 is a legal argument UB 990821*/
129 WARN("Timeout== 0 not implemented, using timeout=1\n");
130 timeout=1;
133 EnterCriticalSection( &csTimer );
135 /* Check if there's already a timer with the same hwnd and id */
137 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
138 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
139 (pTimer->timeout != 0))
141 TIMER_ClearTimer( pTimer );
142 break;
145 if ( i == NB_TIMERS )
147 /* Find a free timer */
149 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
150 if (!pTimer->timeout) break;
152 if ( (i >= NB_TIMERS) ||
153 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
155 LeaveCriticalSection( &csTimer );
156 return 0;
160 if (!hwnd) id = i + 1;
162 if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
164 SERVER_START_REQ( set_win_timer )
166 req->win = hwnd;
167 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
168 req->id = id;
169 req->rate = max( timeout, SYS_TIMER_RATE );
170 req->lparam = (unsigned int)winproc;
171 wine_server_call( req );
173 SERVER_END_REQ;
175 /* Add the timer */
177 pTimer->hwnd = hwnd;
178 pTimer->hq = InitThreadInput16( 0, 0 );
179 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
180 pTimer->id = id;
181 pTimer->timeout = timeout;
182 pTimer->proc = winproc;
184 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
185 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
186 (DWORD)pTimer->proc );
188 LeaveCriticalSection( &csTimer );
190 if (!id) return TRUE;
191 else return id;
195 /***********************************************************************
196 * TIMER_KillTimer
198 static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
200 int i;
201 TIMER * pTimer;
203 SERVER_START_REQ( kill_win_timer )
205 req->win = hwnd;
206 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
207 req->id = id;
208 wine_server_call( req );
210 SERVER_END_REQ;
212 EnterCriticalSection( &csTimer );
214 /* Find the timer */
216 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
217 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
218 (pTimer->timeout != 0)) break;
220 if ( (i >= NB_TIMERS) ||
221 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
222 (!sys && (pTimer->msg != WM_TIMER)) ||
223 (sys && (pTimer->msg != WM_SYSTIMER)) )
225 LeaveCriticalSection( &csTimer );
226 return FALSE;
229 /* Delete the timer */
231 TIMER_ClearTimer( pTimer );
233 LeaveCriticalSection( &csTimer );
235 return TRUE;
239 /***********************************************************************
240 * SetTimer (USER.10)
242 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
243 TIMERPROC16 proc )
245 TRACE("%04x %d %d %08lx\n",
246 hwnd, id, timeout, (LONG)proc );
247 return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
248 WIN_PROC_16, FALSE );
252 /***********************************************************************
253 * SetTimer (USER32.@)
255 UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
256 TIMERPROC proc )
258 TRACE("%04x %d %d %08lx\n",
259 hwnd, id, timeout, (LONG)proc );
260 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, FALSE );
264 /***********************************************************************
265 * TIMER_IsTimerValid
267 BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc )
269 int i;
270 TIMER *pTimer;
271 BOOL ret = FALSE;
273 hwnd = WIN_GetFullHandle( hwnd );
274 EnterCriticalSection( &csTimer );
276 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
277 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
278 (pTimer->proc == hProc))
280 ret = TRUE;
281 break;
284 LeaveCriticalSection( &csTimer );
285 return ret;
289 /***********************************************************************
290 * SetSystemTimer (USER.11)
292 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
293 TIMERPROC16 proc )
295 TRACE("%04x %d %d %08lx\n",
296 hwnd, id, timeout, (LONG)proc );
297 return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
298 WIN_PROC_16, TRUE );
302 /***********************************************************************
303 * SetSystemTimer (USER32.@)
305 UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
306 TIMERPROC proc )
308 TRACE("%04x %d %d %08lx\n",
309 hwnd, id, timeout, (LONG)proc );
310 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, TRUE );
314 /***********************************************************************
315 * KillTimer (USER32.@)
317 BOOL WINAPI KillTimer( HWND hwnd, UINT id )
319 TRACE("%04x %d\n", hwnd, id );
320 return TIMER_KillTimer( hwnd, id, FALSE );
324 /***********************************************************************
325 * KillSystemTimer (USER32.@)
327 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
329 TRACE("%04x %d\n", hwnd, id );
330 return TIMER_KillTimer( hwnd, id, TRUE );