Do not use the PEB lock as loader lock, use a separate critical
[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 "winnls.h"
11 #include "wine/unicode.h"
12 #include "file.h"  /* for FILETIME routines */
13 #include "wine/server.h"
14
15
16 /***********************************************************************
17  *           CreateWaitableTimerA    (KERNEL32.@)
18  */
19 HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
20 {
21     WCHAR buffer[MAX_PATH];
22
23     if (!name) return CreateWaitableTimerW( sa, manual, NULL );
24
25     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
26     {
27         SetLastError( ERROR_FILENAME_EXCED_RANGE );
28         return 0;
29     }
30     return CreateWaitableTimerW( sa, manual, buffer );
31 }
32
33
34 /***********************************************************************
35  *           CreateWaitableTimerW    (KERNEL32.@)
36  */
37 HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
38 {
39     HANDLE ret;
40     DWORD len = name ? strlenW(name) : 0;
41     if (len >= MAX_PATH)
42     {
43         SetLastError( ERROR_FILENAME_EXCED_RANGE );
44         return 0;
45     }
46     SERVER_START_REQ( create_timer )
47     {
48         req->manual  = manual;
49         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
50         wine_server_add_data( req, name, len * sizeof(WCHAR) );
51         SetLastError(0);
52         wine_server_call_err( req );
53         ret = reply->handle;
54     }
55     SERVER_END_REQ;
56     return ret;
57 }
58
59
60 /***********************************************************************
61  *           OpenWaitableTimerA    (KERNEL32.@)
62  */
63 HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
64 {
65     WCHAR buffer[MAX_PATH];
66
67     if (!name) return OpenWaitableTimerW( access, inherit, NULL );
68
69     if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
70     {
71         SetLastError( ERROR_FILENAME_EXCED_RANGE );
72         return 0;
73     }
74     return OpenWaitableTimerW( access, inherit, buffer );
75 }
76
77
78 /***********************************************************************
79  *           OpenWaitableTimerW    (KERNEL32.@)
80  */
81 HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
82 {
83     HANDLE ret;
84     DWORD len = name ? strlenW(name) : 0;
85     if (len >= MAX_PATH)
86     {
87         SetLastError( ERROR_FILENAME_EXCED_RANGE );
88         return 0;
89     }
90     SERVER_START_REQ( open_timer )
91     {
92         req->access  = access;
93         req->inherit = inherit;
94         wine_server_add_data( req, name, len * sizeof(WCHAR) );
95         wine_server_call_err( req );
96         ret = reply->handle;
97     }
98     SERVER_END_REQ;
99     return ret;
100 }
101
102
103 /***********************************************************************
104  *           SetWaitableTimer    (KERNEL32.@)
105  */
106 BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
107                               PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
108 {
109     BOOL ret;
110     LARGE_INTEGER exp = *when;
111
112     if (exp.s.HighPart < 0)  /* relative time */
113     {
114         LARGE_INTEGER now;
115         NtQuerySystemTime( &now );
116         exp.QuadPart = RtlLargeIntegerSubtract( now.QuadPart, exp.QuadPart );
117     }
118
119     SERVER_START_REQ( set_timer )
120     {
121         if (!exp.s.LowPart && !exp.s.HighPart)
122         {
123             /* special case to start timeout on now+period without too many calculations */
124             req->sec  = 0;
125             req->usec = 0;
126         }
127         else
128         {
129             DWORD remainder;
130             req->sec  = DOSFS_FileTimeToUnixTime( (FILETIME *)&exp, &remainder );
131             req->usec = remainder / 10;  /* convert from 100-ns to us units */
132         }
133         req->handle   = handle;
134         req->period   = period;
135         req->callback = callback;
136         req->arg      = arg;
137         if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
138         ret = !wine_server_call_err( req );
139     }
140     SERVER_END_REQ;
141     return ret;
142 }
143
144
145 /***********************************************************************
146  *           CancelWaitableTimer    (KERNEL32.@)
147  */
148 BOOL WINAPI CancelWaitableTimer( HANDLE handle )
149 {
150     BOOL ret;
151     SERVER_START_REQ( cancel_timer )
152     {
153         req->handle = handle;
154         ret = !wine_server_call_err( req );
155     }
156     SERVER_END_REQ;
157     return ret;
158 }