blob: a0aa575fcd08ad70a99601b2dfb588a4be79e8cf [file] [log] [blame]
Alexandre Julliardad47a301999-11-29 01:58:35 +00001/*
2 * Win32 waitable timers
3 *
4 * Copyright 1999 Alexandre Julliard
5 */
6
7#include <assert.h>
8#include <string.h>
9#include "winerror.h"
Alexandre Julliard072dfb52000-09-25 23:30:56 +000010#include "winnls.h"
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000011#include "wine/unicode.h"
Alexandre Julliardad47a301999-11-29 01:58:35 +000012#include "file.h" /* for FILETIME routines */
13#include "server.h"
14
15
16/***********************************************************************
17 * CreateWaitableTimerA (KERNEL32.861)
18 */
19HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
20{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000021 HANDLE ret;
22 DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
23 if (len >= MAX_PATH)
24 {
25 SetLastError( ERROR_FILENAME_EXCED_RANGE );
26 return 0;
27 }
28 SERVER_START_REQ
29 {
30 struct create_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
Alexandre Julliardad47a301999-11-29 01:58:35 +000031
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000032 req->manual = manual;
33 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
34 if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
35 SetLastError(0);
36 server_call( REQ_CREATE_TIMER );
37 ret = req->handle;
38 }
39 SERVER_END_REQ;
Alexandre Julliard908464d2000-11-01 03:11:12 +000040 if (ret == INVALID_HANDLE_VALUE) ret = 0; /* must return 0 on failure, not -1 */
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000041 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +000042}
43
44
45/***********************************************************************
46 * CreateWaitableTimerW (KERNEL32.862)
47 */
48HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
49{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000050 HANDLE ret;
51 DWORD len = name ? strlenW(name) : 0;
52 if (len >= MAX_PATH)
53 {
54 SetLastError( ERROR_FILENAME_EXCED_RANGE );
55 return 0;
56 }
57 SERVER_START_REQ
58 {
59 struct create_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
Alexandre Julliardad47a301999-11-29 01:58:35 +000060
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000061 req->manual = manual;
62 req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
63 memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
64 SetLastError(0);
65 server_call( REQ_CREATE_TIMER );
66 ret = req->handle;
67 }
68 SERVER_END_REQ;
Alexandre Julliard908464d2000-11-01 03:11:12 +000069 if (ret == INVALID_HANDLE_VALUE) ret = 0; /* must return 0 on failure, not -1 */
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000070 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +000071}
72
73
74/***********************************************************************
75 * OpenWaitableTimerA (KERNEL32.881)
76 */
77HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
78{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000079 HANDLE ret;
80 DWORD len = name ? MultiByteToWideChar( CP_ACP, 0, name, strlen(name), NULL, 0 ) : 0;
81 if (len >= MAX_PATH)
82 {
83 SetLastError( ERROR_FILENAME_EXCED_RANGE );
84 return 0;
85 }
86 SERVER_START_REQ
87 {
88 struct open_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
Alexandre Julliardad47a301999-11-29 01:58:35 +000089
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000090 req->access = access;
91 req->inherit = inherit;
92 if (len) MultiByteToWideChar( CP_ACP, 0, name, strlen(name), server_data_ptr(req), len );
93 server_call( REQ_OPEN_TIMER );
94 ret = req->handle;
95 }
96 SERVER_END_REQ;
Alexandre Julliard908464d2000-11-01 03:11:12 +000097 if (ret == INVALID_HANDLE_VALUE) ret = 0; /* must return 0 on failure, not -1 */
Alexandre Julliard9c2370b2000-08-30 00:00:48 +000098 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +000099}
100
101
102/***********************************************************************
103 * OpenWaitableTimerW (KERNEL32.882)
104 */
105HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
106{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000107 HANDLE ret;
108 DWORD len = name ? strlenW(name) : 0;
109 if (len >= MAX_PATH)
110 {
111 SetLastError( ERROR_FILENAME_EXCED_RANGE );
112 return 0;
113 }
114 SERVER_START_REQ
115 {
116 struct open_timer_request *req = server_alloc_req( sizeof(*req), len * sizeof(WCHAR) );
Alexandre Julliardad47a301999-11-29 01:58:35 +0000117
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000118 req->access = access;
119 req->inherit = inherit;
120 memcpy( server_data_ptr(req), name, len * sizeof(WCHAR) );
121 server_call( REQ_OPEN_TIMER );
122 ret = req->handle;
123 }
124 SERVER_END_REQ;
Alexandre Julliard908464d2000-11-01 03:11:12 +0000125 if (ret == INVALID_HANDLE_VALUE) ret = 0; /* must return 0 on failure, not -1 */
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000126 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +0000127}
128
129
130/***********************************************************************
131 * SetWaitableTimer (KERNEL32.894)
132 */
133BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
134 PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
135{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000136 BOOL ret;
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000137 LARGE_INTEGER exp = *when;
Alexandre Julliardad47a301999-11-29 01:58:35 +0000138
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000139 if (exp.s.HighPart < 0) /* relative time */
Alexandre Julliardad47a301999-11-29 01:58:35 +0000140 {
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000141 LARGE_INTEGER now;
142 NtQuerySystemTime( &now );
143 exp.QuadPart = RtlLargeIntegerSubtract( now.QuadPart, exp.QuadPart );
Alexandre Julliardad47a301999-11-29 01:58:35 +0000144 }
Alexandre Julliard000c9801999-12-13 01:42:03 +0000145
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000146 SERVER_START_REQ
Alexandre Julliard000c9801999-12-13 01:42:03 +0000147 {
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000148 struct set_timer_request *req = server_alloc_req( sizeof(*req), 0 );
149
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000150 if (!exp.s.LowPart && !exp.s.HighPart)
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000151 {
152 /* special case to start timeout on now+period without too many calculations */
153 req->sec = 0;
154 req->usec = 0;
155 }
156 else
157 {
Alexandre Julliardd76f9f92000-10-01 01:40:42 +0000158 DWORD remainder;
159 req->sec = DOSFS_FileTimeToUnixTime( (FILETIME *)&exp, &remainder );
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000160 req->usec = remainder / 10; /* convert from 100-ns to us units */
161 }
162 req->handle = handle;
163 req->period = period;
164 req->callback = callback;
165 req->arg = arg;
166 if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
167 ret = !server_call( REQ_SET_TIMER );
Alexandre Julliard000c9801999-12-13 01:42:03 +0000168 }
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000169 SERVER_END_REQ;
170 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +0000171}
172
173
174/***********************************************************************
175 * CancelWaitableTimer (KERNEL32.857)
176 */
177BOOL WINAPI CancelWaitableTimer( HANDLE handle )
178{
Alexandre Julliard9c2370b2000-08-30 00:00:48 +0000179 BOOL ret;
180 SERVER_START_REQ
181 {
182 struct cancel_timer_request *req = server_alloc_req( sizeof(*req), 0 );
183 req->handle = handle;
184 ret = !server_call( REQ_CANCEL_TIMER );
185 }
186 SERVER_END_REQ;
187 return ret;
Alexandre Julliardad47a301999-11-29 01:58:35 +0000188}