-
Notifications
You must be signed in to change notification settings - Fork 1
/
event-win32.c
179 lines (146 loc) · 3.96 KB
/
event-win32.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/*
* event-win32.c
*
* Copyright (c) 2001 Dug Song <dugsong@monkey.org>
*
* $Id: event-win32.c,v 1.1 2002/02/25 06:21:59 dugsong Exp $
*/
#include <windows.h>
#include <winsock.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include "event.h"
#define WT_EXECUTEINIOTHREAD 0x0000001
#define WT_EXECUTEONLYONCE 0x0000006
typedef HANDLE (WINAPI *pCreateTimerQueue)(VOID);
typedef BOOL (WINAPI *pDeleteTimerQueue)(HANDLE TimerQueue);
typedef BOOL (WINAPI *pCreateTimerQueueTimer)(PHANDLE phNewTimer,
HANDLE TimerQueue, void CALLBACK (*pfnCallback)(PVOID, BOOL),
PVOID pvContext, DWORD DueTime, DWORD Period, ULONG Flags);
typedef BOOL (WINAPI *pDeleteTimerQueueTimer)(HANDLE TimerQueue, HANDLE Timer,
HANDLE CompletionEvent);
static HINSTANCE lib_inst;
static HANDLE timer_queue;
static pCreateTimerQueue create_timer_queue;
static pDeleteTimerQueue delete_timer_queue;
static pCreateTimerQueueTimer create_timer;
static pDeleteTimerQueueTimer delete_timer;
int event_gotsig;
int (*event_sigcb)(void);
int
os_version(void)
{
OSVERSIONINFO info;
info.dwOSVersionInfoSize = sizeof(info);
if (GetVersionEx(&info) == TRUE &&
info.dwPlatformId == VER_PLATFORM_WIN32_NT)
return (info.dwMajorVersion);
return (32767);
}
static int
timeval_to_ms(struct timeval *tv)
{
return ((tv->tv_sec * 1000) + (tv->tv_usec / 1000));
}
void
event_init(void)
{
if (os_version() <= 4)
errx(1, "this program must be run on Windows 2000 or greater");
lib_inst = LoadLibrary("kernel32.dll");
if (lib_inst < (HINSTANCE)HINSTANCE_ERROR)
errx(1, "couldn't load kernel32.dll");
create_timer_queue = (pCreateTimerQueue)GetProcAddress(lib_inst,
"CreateTimerQueue");
delete_timer_queue = (pDeleteTimerQueue)GetProcAddress(lib_inst,
"DeleteTimerQueue");
create_timer = (pCreateTimerQueueTimer)GetProcAddress(lib_inst,
"CreateTimerQueueTimer");
delete_timer = (pDeleteTimerQueueTimer)GetProcAddress(lib_inst,
"DeleteTimerQueueTimer");
if (create_timer_queue == NULL || delete_timer_queue == NULL ||
create_timer == NULL || delete_timer == NULL)
errx(1, "couldn't map timer functions - not Windows 2000?");
timer_queue = create_timer_queue();
}
void CALLBACK
event_callback(DWORD errcode, DWORD len, OVERLAPPED *overlap)
{
struct event *ev = (struct event *)overlap->hEvent;
struct event_iov eio;
eio.buf = ev->buf;
eio.len = len;
ev->callback((int)&eio, ev->event, ev->arg);
}
void
event_set(struct event *ev, int fd, short event,
void (*callback)(int, short, void *), void *arg)
{
memset(ev, 0, sizeof(*ev));
ev->handle = (HANDLE)fd;
ev->overlap.hEvent = (HANDLE)ev;
ev->event = event;
ev->callback = callback;
ev->arg = arg;
}
int
event_add(struct event *ev, struct timeval *tv)
{
if (tv != NULL || ev->event != EV_READ)
return (-1); /* XXX - UNIMPLEMENTED */
ReadFileEx(ev->handle, ev->buf, sizeof(ev->buf),
&ev->overlap, event_callback);
return (0);
}
int
event_initialized(struct event *ev)
{
return (ev->handle != INVALID_HANDLE_VALUE);
}
void
event_del(struct event *ev)
{
/* XXX - UNIMPLEMENTED */
}
void
timeout_set(struct event *ev, void (*callback)(int, short, void *), void *arg)
{
memset(ev, 0, sizeof(*ev));
ev->event = EV_TIMEOUT;
ev->callback = callback;
ev->arg = arg;
}
void CALLBACK
timeout_callback(PVOID arg, BOOL TimerFired)
{
struct event *ev = (struct event *)arg;
delete_timer(timer_queue, ev->handle, NULL);
ev->handle = INVALID_HANDLE_VALUE;
ev->callback(-1, EV_TIMEOUT, ev->arg);
}
void
timeout_add(struct event *ev, struct timeval *tv)
{
if (create_timer(&ev->handle, timer_queue, timeout_callback, ev,
timeval_to_ms(tv), 0, WT_EXECUTEINIOTHREAD) == 0)
errx(1, "CreateTimerQueueTimer failed");
}
int
event_dispatch(void)
{
for (;;) {
while (event_gotsig) {
event_gotsig = 0;
if (event_sigcb != NULL) {
if ((*event_sigcb)() == -1) {
delete_timer_queue(timer_queue);
return (-1);
}
}
}
/* XXX - i'm a lazy bum */
SleepEx(100, TRUE);
}
return (0);
}