timer.c 4.98 KB
Newer Older
1 2 3 4
/*
 * Win32 waitable timers
 *
 * Copyright 1999 Alexandre Julliard
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 20 21 22 23
 */

#include <assert.h>
#include <string.h>
#include "winerror.h"
24
#include "winnls.h"
25
#include "wine/unicode.h"
26
#include "file.h"  /* for FILETIME routines */
27
#include "wine/server.h"
28 29 30


/***********************************************************************
31
 *           CreateWaitableTimerA    (KERNEL32.@)
32 33 34
 */
HANDLE WINAPI CreateWaitableTimerA( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCSTR name )
{
35 36 37 38 39
    WCHAR buffer[MAX_PATH];

    if (!name) return CreateWaitableTimerW( sa, manual, NULL );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
40 41 42 43
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
44
    return CreateWaitableTimerW( sa, manual, buffer );
45 46 47 48
}


/***********************************************************************
49
 *           CreateWaitableTimerW    (KERNEL32.@)
50 51 52
 */
HANDLE WINAPI CreateWaitableTimerW( SECURITY_ATTRIBUTES *sa, BOOL manual, LPCWSTR name )
{
53 54 55 56 57 58 59
    HANDLE ret;
    DWORD len = name ? strlenW(name) : 0;
    if (len >= MAX_PATH)
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
60
    SERVER_START_REQ( create_timer )
61 62 63
    {
        req->manual  = manual;
        req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
64
        wine_server_add_data( req, name, len * sizeof(WCHAR) );
65
        SetLastError(0);
66 67
        wine_server_call_err( req );
        ret = reply->handle;
68
    }
69
    SERVER_END_REQ;
70
    return ret;
71 72 73 74
}


/***********************************************************************
75
 *           OpenWaitableTimerA    (KERNEL32.@)
76 77 78
 */
HANDLE WINAPI OpenWaitableTimerA( DWORD access, BOOL inherit, LPCSTR name )
{
79 80 81 82 83
    WCHAR buffer[MAX_PATH];

    if (!name) return OpenWaitableTimerW( access, inherit, NULL );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
84 85 86 87
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
88
    return OpenWaitableTimerW( access, inherit, buffer );
89 90 91 92
}


/***********************************************************************
93
 *           OpenWaitableTimerW    (KERNEL32.@)
94 95 96
 */
HANDLE WINAPI OpenWaitableTimerW( DWORD access, BOOL inherit, LPCWSTR name )
{
97 98 99 100 101 102 103
    HANDLE ret;
    DWORD len = name ? strlenW(name) : 0;
    if (len >= MAX_PATH)
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
104
    SERVER_START_REQ( open_timer )
105 106 107
    {
        req->access  = access;
        req->inherit = inherit;
108 109 110
        wine_server_add_data( req, name, len * sizeof(WCHAR) );
        wine_server_call_err( req );
        ret = reply->handle;
111
    }
112
    SERVER_END_REQ;
113
    return ret;
114 115 116 117
}


/***********************************************************************
118
 *           SetWaitableTimer    (KERNEL32.@)
119 120 121 122
 */
BOOL WINAPI SetWaitableTimer( HANDLE handle, const LARGE_INTEGER *when, LONG period,
                              PTIMERAPCROUTINE callback, LPVOID arg, BOOL resume )
{
123
    BOOL ret;
124
    LARGE_INTEGER exp = *when;
125

126
    if (exp.s.HighPart < 0)  /* relative time */
127
    {
128 129 130
        LARGE_INTEGER now;
        NtQuerySystemTime( &now );
        exp.QuadPart = RtlLargeIntegerSubtract( now.QuadPart, exp.QuadPart );
131
    }
132

133
    SERVER_START_REQ( set_timer )
134
    {
135
        if (!exp.s.LowPart && !exp.s.HighPart)
136 137 138 139 140 141 142
        {
            /* special case to start timeout on now+period without too many calculations */
            req->sec  = 0;
            req->usec = 0;
        }
        else
        {
143 144
            DWORD remainder;
            req->sec  = DOSFS_FileTimeToUnixTime( (FILETIME *)&exp, &remainder );
145 146 147 148 149 150 151
            req->usec = remainder / 10;  /* convert from 100-ns to us units */
        }
        req->handle   = handle;
        req->period   = period;
        req->callback = callback;
        req->arg      = arg;
        if (resume) SetLastError( ERROR_NOT_SUPPORTED ); /* set error but can still succeed */
152
        ret = !wine_server_call_err( req );
153
    }
154 155
    SERVER_END_REQ;
    return ret;
156 157 158 159
}


/***********************************************************************
160
 *           CancelWaitableTimer    (KERNEL32.@)
161 162 163
 */
BOOL WINAPI CancelWaitableTimer( HANDLE handle )
{
164
    BOOL ret;
165
    SERVER_START_REQ( cancel_timer )
166 167
    {
        req->handle = handle;
168
        ret = !wine_server_call_err( req );
169 170 171
    }
    SERVER_END_REQ;
    return ret;
172
}