Added WINESERVER environment variable to allow overriding the normal
[wine] / scheduler / timer.c
1 /*
2  * Win32 waitable timers
3  *
4  * Copyright 1999 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include <string.h>
9 #include "winerror.h"
10 #include "wine/unicode.h"
11 #include "file.h"  /* for FILETIME routines */
12 #include "server.h"
13
14
15 /***********************************************************************
16  *           CreateWaitableTimerA    (KERNEL32.861)
17  */
18 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
19 {
20     HANDLE ret;
21     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
22     if (len >= MAX_PATH)
23     {
24         SetLastError( ERROR_FILENAME_EXCED_RANGE );
25         return 0;
26     }
27     SERVER_START_REQ
28     {
29         struct create_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
30
31         req->manual  = manual;
32         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
33         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
34         SetLastError(0);
35         server_call( REQ_CREATE_TIMER );
36         ret = req->handle;
37     }
38     SERVER_END_REQ;
39     if (ret == -1) ret = 0; /* must return 0 on failure, not -1 */
40     return ret;
41 }
42
43
44 /***********************************************************************
45  *           CreateWaitableTimerW    (KERNEL32.862)
46  */
47 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
48 {
49     HANDLE ret;
50     DWORD len = name ? strlenW(name) : 0;
51     if (len >= MAX_PATH)
52     {
53         SetLastError( ERROR_FILENAME_EXCED_RANGE );
54         return 0;
55     }
56     SERVER_START_REQ
57     {
58         struct create_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
59
60         req->manual  = manual;
61         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
62         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
63         SetLastError(0);
64         server_call( REQ_CREATE_TIMER );
65         ret = req->handle;
66     }
67     SERVER_END_REQ;
68     if (ret == -1) ret = 0; /* must return 0 on failure, not -1 */
69     return ret;
70 }
71
72
73 /***********************************************************************
74  *           OpenWaitableTimerA    (KERNEL32.881)
75  */
76 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
77 {
78     HANDLE ret;
79     DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
80     if (len >= MAX_PATH)
81     {
82         SetLastError( ERROR_FILENAME_EXCED_RANGE );
83         return 0;
84     }
85     SERVER_START_REQ
86     {
87         struct open_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
88
89         req->access  = access;
90         req->inherit = inherit;
91         if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
92         server_call( REQ_OPEN_TIMER );
93         ret = req->handle;
94     }
95     SERVER_END_REQ;
96     if (ret == -1) ret = 0; /* must return 0 on failure, not -1 */
97     return ret;
98 }
99
100
101 /***********************************************************************
102  *           OpenWaitableTimerW    (KERNEL32.882)
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
114     {
115         struct open_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
116
117         req->access  = access;
118         req->inherit = inherit;
119         memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
120         server_call( REQ_OPEN_TIMER );
121         ret = req->handle;
122     }
123     SERVER_END_REQ;
124     if (ret == -1) ret = 0; /* must return 0 on failure, not -1 */
125     return ret;
126 }
127
128
129 /***********************************************************************
130  *           SetWaitableTimer    (KERNEL32.894)
131  */
132 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
133                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
134 {
135     BOOL ret;
136     FILETIME ft;
137     DWORD remainder;
138
139     if (when->s.HighPart < 0)  /* relative time */
140     {
141         DWORD low;
142         GetSystemTimeAsFileTime( &ft );
143         low = ft.dwLowDateTime;
144         ft.dwLowDateTime -= when->s.LowPart;
145         ft.dwHighDateTime -= when->s.HighPart;
146         if (low < ft.dwLowDateTime) ft.dwHighDateTime--; /* overflow */
147     }
148     else  /* absolute time */
149     {
150         ft.dwLowDateTime = when->s.LowPart;
151         ft.dwHighDateTime = when->s.HighPart;
152     }
153
154     SERVER_START_REQ
155     {
156         struct set_timer_request *req = server_alloc_req( sizeof(*req), 0 );
157
158         if (!ft.dwLowDateTime && !ft.dwHighDateTime)
159         {
160             /* special case to start timeout on now+period without too many calculations */
161             req->sec  = 0;
162             req->usec = 0;
163         }
164         else
165         {
166             req->sec  = DOSFS_FileTimeToUnixTime( &ft, &remainder );
167             req->usec = remainder / 10;  /* convert from 100-ns to us units */
168         }
169         req->handle   = handle;
170         req->period   = period;
171         req->callback = callback;
172         req->arg      = arg;
173         if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
174         ret = !server_call( REQ_SET_TIMER );
175     }
176     SERVER_END_REQ;
177     return ret;
178 }
179
180
181 /***********************************************************************
182  *           CancelWaitableTimer    (KERNEL32.857)
183  */
184 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
185 {
186     BOOL ret;
187     SERVER_START_REQ
188     {
189         struct cancel_timer_request *req = server_alloc_req( sizeof(*req), 0 );
190         req->handle = handle;
191         ret = !server_call( REQ_CANCEL_TIMER );
192     }
193     SERVER_END_REQ;
194     return ret;
195 }