Split signal blocking code out of SIGNAL_Reset into SIGNAL_Block.
[wine] / scheduler / timer.c
1 /*
2  * Win32 waitable timers
3  *
4  * Copyright 1999 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 #include "config.h"
22 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <string.h>
26
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "winerror.h"
30 #include "winnls.h"
31 #include "wine/unicode.h"
32 #include "file.h"  /* for FILETIME routines */
33 #include "wine/server.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(timer);
37
38
39 /***********************************************************************
40  *           CreateWaitableTimerA    (KERNEL32.@)
41  */
42 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
43 {
44     WCHAR buffer[MAX_PATH];
45
46     if (!name) return CreateWaitableTimerW( sa, manual, NULL );
47
48     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
49     {
50         SetLastError( ERROR_FILENAME_EXCED_RANGE );
51         return 0;
52     }
53     return CreateWaitableTimerW( sa, manual, buffer );
54 }
55
56
57 /***********************************************************************
58  *           CreateWaitableTimerW    (KERNEL32.@)
59  */
60 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
61 {
62     HANDLE ret;
63     DWORD len = name ? strlenW(name) : 0;
64     if (len >= MAX_PATH)
65     {
66         SetLastError( ERROR_FILENAME_EXCED_RANGE );
67         return 0;
68     }
69     SERVER_START_REQ( create_timer )
70     {
71         req->manual  = manual;
72         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
73         wine_server_add_data( req, name, len * sizeof(WCHAR) );
74         SetLastError(0);
75         wine_server_call_err( req );
76         ret = reply->handle;
77     }
78     SERVER_END_REQ;
79     return ret;
80 }
81
82
83 /***********************************************************************
84  *           OpenWaitableTimerA    (KERNEL32.@)
85  */
86 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
87 {
88     WCHAR buffer[MAX_PATH];
89
90     if (!name) return OpenWaitableTimerW( access, inherit, NULL );
91
92     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
93     {
94         SetLastError( ERROR_FILENAME_EXCED_RANGE );
95         return 0;
96     }
97     return OpenWaitableTimerW( access, inherit, buffer );
98 }
99
100
101 /***********************************************************************
102  *           OpenWaitableTimerW    (KERNEL32.@)
103  */
104 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
105 {
106     HANDLE ret;
107     DWORD len = name ? strlenW(name) : 0;
108     if (len >= MAX_PATH)
109     {
110         SetLastError( ERROR_FILENAME_EXCED_RANGE );
111         return 0;
112     }
113     SERVER_START_REQ( open_timer )
114     {
115         req->access  = access;
116         req->inherit = inherit;
117         wine_server_add_data( req, name, len * sizeof(WCHAR) );
118         wine_server_call_err( req );
119         ret = reply->handle;
120     }
121     SERVER_END_REQ;
122     return ret;
123 }
124
125
126 /***********************************************************************
127  *           SetWaitableTimer    (KERNEL32.@)
128  */
129 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
130                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
131 {
132     BOOL ret;
133     LARGE_INTEGER exp = *when;
134
135     if (exp.s.HighPart < 0)  /* relative time */
136     {
137         LARGE_INTEGER now;
138         NtQuerySystemTime( &now );
139         exp.QuadPart = RtlLargeIntegerSubtract( now.QuadPart, exp.QuadPart );
140     }
141
142     SERVER_START_REQ( set_timer )
143     {
144         if (!exp.s.LowPart && !exp.s.HighPart)
145         {
146             /* special case to start timeout on now+period without too many calculations */
147             req->sec  = 0;
148             req->usec = 0;
149         }
150         else
151         {
152             DWORD remainder;
153             FILETIME ft;
154
155             ft.dwLowDateTime    = exp.s.LowPart;
156             ft.dwHighDateTime   = exp.s.HighPart;
157             req->sec  = DOSFS_FileTimeToUnixTime( &ft, &remainder );
158             req->usec = remainder / 10;  /* convert from 100-ns to us units */
159         }
160         req->handle   = handle;
161         req->period   = period;
162         req->callback = callback;
163         req->arg      = arg;
164         if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
165         ret = !wine_server_call_err( req );
166     }
167     SERVER_END_REQ;
168     return ret;
169 }
170
171
172 /***********************************************************************
173  *           CancelWaitableTimer    (KERNEL32.@)
174  */
175 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
176 {
177     BOOL ret;
178     SERVER_START_REQ( cancel_timer )
179     {
180         req->handle = handle;
181         ret = !wine_server_call_err( req );
182     }
183     SERVER_END_REQ;
184     return ret;
185 }
186
187
188 /***********************************************************************
189  *           CreateTimerQueue  (KERNEL32.@)
190  */
191 HANDLE WINAPI CreateTimerQueue()
192 {
193     FIXME("stub\n");
194     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
195     return NULL;
196 }
197
198
199 /***********************************************************************
200  *           DeleteTimerQueueEx  (KERNEL32.@)
201  */
202 BOOL WINAPI DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent)
203 {
204     FIXME("(%p, %p): stub\n", TimerQueue, CompletionEvent);
205     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
206     return 0;
207 }
208
209 /***********************************************************************
210  *           CreateTimerQueueTimer  (KERNEL32.@)
211  *
212  * Creates a timer-queue timer. This timer expires at the specified due
213  * time (in ms), then after every specified period (in ms). When the timer
214  * expires, the callback function is called.
215  *
216  * RETURNS
217  *   nonzero on success or zero on faillure
218  *
219  * BUGS
220  *   Unimplemented
221  */
222 BOOL WINAPI CreateTimerQueueTimer( PHANDLE phNewTimer, HANDLE TimerQueue,
223                                    WAITORTIMERCALLBACK Callback, PVOID Parameter,
224                                    DWORD DueTime, DWORD Period, ULONG Flags )
225 {
226     FIXME("stub\n");
227     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
228     return TRUE;
229 }
230
231 /***********************************************************************
232  *           DeleteTimerQueueTimer  (KERNEL32.@)
233  *
234  * Cancels a timer-queue timer. 
235  *
236  * RETURNS
237  *   nonzero on success or zero on faillure
238  *
239  * BUGS
240  *   Unimplemented
241  */
242 BOOL WINAPI DeleteTimerQueueTimer( HANDLE TimerQueue, HANDLE Timer,
243                                    HANDLE CompletionEvent )
244 {
245     FIXME("stub\n");
246     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
247     return TRUE;
248 }