]>
Commit | Line | Data |
---|---|---|
1fd5e000 CF |
1 | /* fhandler_windows.cc: code to access windows message queues. |
2 | ||
bc837d22 CF |
3 | Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2009, 2011, 2012 |
4 | Red Hat, Inc. | |
1fd5e000 CF |
5 | |
6 | Written by Sergey S. Okhapkin (sos@prospect.com.ru). | |
7 | Feedback and testing by Andy Piper (andyp@parallax.co.uk). | |
8 | ||
9 | This file is part of Cygwin. | |
10 | ||
11 | This software is a copyrighted work licensed under the terms of the | |
12 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
13 | details. */ | |
14 | ||
1fd5e000 | 15 | #include "winsup.h" |
d0b178fe DD |
16 | #include <wingdi.h> |
17 | #include <winuser.h> | |
9e2baf8d | 18 | #include "cygerrno.h" |
7ac61736 | 19 | #include "path.h" |
bccd5e0d | 20 | #include "fhandler.h" |
79e741ef CV |
21 | #include "sigproc.h" |
22 | #include "thread.h" | |
23 | ||
1fd5e000 CF |
24 | |
25 | /* | |
26 | The following unix-style calls are supported: | |
27 | ||
28 | open ("/dev/windows", flags, mode=0) | |
29 | - create a unix fd for message queue. | |
1fd5e000 CF |
30 | |
31 | read (fd, buf, len) | |
32 | - return next message from queue. buf must point to MSG | |
33 | structure, len must be >= sizeof (MSG). If read is set to | |
34 | non-blocking and the queue is empty, read call returns -1 | |
35 | immediately with errno set to EAGAIN, otherwise it blocks | |
36 | untill the message will be received. | |
37 | ||
38 | write (fd, buf, len) | |
39 | - send a message pointed by buf. len argument ignored. | |
40 | ||
41 | ioctl (fd, command, *param) | |
42 | - control read()/write() behavior. | |
43 | ioctl (fd, WINDOWS_POST, NULL): write() will PostMessage(); | |
44 | ioctl (fd, WINDOWS_SEND, NULL): write() will SendMessage(); | |
45 | ioctl (fd, WINDOWS_HWND, &hWnd): read() messages for | |
46 | hWnd window. | |
47 | ||
48 | select () call marks read fd when any message posted to queue. | |
49 | */ | |
50 | ||
0476bae5 | 51 | fhandler_windows::fhandler_windows () |
7ac61736 | 52 | : fhandler_base (), hWnd_ (NULL), method_ (WINDOWS_POST) |
1fd5e000 | 53 | { |
1fd5e000 CF |
54 | } |
55 | ||
56 | int | |
7ac61736 | 57 | fhandler_windows::open (int flags, mode_t) |
1fd5e000 | 58 | { |
1bc9effd | 59 | set_flags ((flags & ~O_TEXT) | O_BINARY); |
56551a9b | 60 | close_on_exec (true); |
f3ea62a8 | 61 | set_open_status (); |
1fd5e000 CF |
62 | return 1; |
63 | } | |
64 | ||
43c23d4b | 65 | ssize_t __stdcall |
1fd5e000 CF |
66 | fhandler_windows::write (const void *buf, size_t) |
67 | { | |
68 | MSG *ptr = (MSG *) buf; | |
69 | ||
70 | if (method_ == WINDOWS_POST) | |
71 | { | |
79e741ef | 72 | if (!PostMessageW (ptr->hwnd, ptr->message, ptr->wParam, ptr->lParam)) |
1fd5e000 CF |
73 | { |
74 | __seterrno (); | |
75 | return -1; | |
76 | } | |
1fd5e000 | 77 | } |
79e741ef CV |
78 | else if (!SendNotifyMessageW (ptr->hwnd, ptr->message, ptr->wParam, |
79 | ptr->lParam)) | |
80 | { | |
81 | __seterrno (); | |
82 | return -1; | |
83 | } | |
84 | return sizeof (MSG); | |
1fd5e000 CF |
85 | } |
86 | ||
8bce0d72 CF |
87 | void __stdcall |
88 | fhandler_windows::read (void *buf, size_t& len) | |
1fd5e000 CF |
89 | { |
90 | MSG *ptr = (MSG *) buf; | |
1fd5e000 CF |
91 | |
92 | if (len < sizeof (MSG)) | |
93 | { | |
94 | set_errno (EINVAL); | |
6cce721b | 95 | len = (size_t) -1; |
8bce0d72 | 96 | return; |
1fd5e000 CF |
97 | } |
98 | ||
962f9a2c | 99 | HANDLE w4[3] = { get_handle (), }; |
44aa2292 | 100 | set_signal_arrived here (w4[1]); |
79e741ef | 101 | DWORD cnt = 2; |
a91ac4dc CV |
102 | if ((w4[cnt] = pthread::get_cancel_event ()) != NULL) |
103 | ++cnt; | |
962f9a2c | 104 | for (;;) |
79e741ef | 105 | { |
962f9a2c CF |
106 | switch (MsgWaitForMultipleObjectsEx (cnt, w4, |
107 | is_nonblocking () ? 0 : INFINITE, | |
108 | QS_ALLINPUT | QS_ALLPOSTMESSAGE, | |
109 | MWMO_INPUTAVAILABLE)) | |
79e741ef | 110 | { |
962f9a2c CF |
111 | case WAIT_OBJECT_0: |
112 | if (!PeekMessageW (ptr, hWnd_, 0, 0, PM_REMOVE)) | |
113 | { | |
114 | len = (size_t) -1; | |
115 | __seterrno (); | |
116 | } | |
117 | else if (ptr->message == WM_QUIT) | |
118 | len = 0; | |
119 | else | |
120 | len = sizeof (MSG); | |
121 | break; | |
122 | case WAIT_OBJECT_0 + 1: | |
123 | if (_my_tls.call_signal_handler ()) | |
124 | continue; | |
125 | len = (size_t) -1; | |
126 | set_errno (EINTR); | |
127 | break; | |
128 | case WAIT_OBJECT_0 + 2: | |
129 | pthread::static_cancel_self (); | |
130 | break; | |
131 | case WAIT_TIMEOUT: | |
132 | len = (size_t) -1; | |
133 | set_errno (EAGAIN); | |
134 | break; | |
135 | default: | |
79e741ef CV |
136 | len = (size_t) -1; |
137 | __seterrno (); | |
962f9a2c | 138 | break; |
79e741ef | 139 | } |
79e741ef CV |
140 | break; |
141 | } | |
1fd5e000 CF |
142 | } |
143 | ||
144 | int | |
145 | fhandler_windows::ioctl (unsigned int cmd, void *val) | |
146 | { | |
147 | switch (cmd) | |
148 | { | |
149 | case WINDOWS_POST: | |
150 | case WINDOWS_SEND: | |
151 | method_ = cmd; | |
152 | break; | |
153 | case WINDOWS_HWND: | |
154 | if (val == NULL) | |
155 | { | |
156 | set_errno (EINVAL); | |
157 | return -1; | |
158 | } | |
159 | hWnd_ = * ((HWND *) val); | |
160 | break; | |
161 | default: | |
e9b5cc32 | 162 | return fhandler_base::ioctl (cmd, val); |
1fd5e000 CF |
163 | } |
164 | return 0; | |
165 | } | |
166 | ||
167 | void | |
56551a9b | 168 | fhandler_windows::set_close_on_exec (bool val) |
1fd5e000 CF |
169 | { |
170 | if (get_handle ()) | |
335556d5 | 171 | fhandler_base::set_close_on_exec (val); |
1fd5e000 | 172 | else |
56551a9b | 173 | fhandler_base::close_on_exec (val); |
1fd5e000 CF |
174 | void *h = hWnd_; |
175 | if (h) | |
6027d26d | 176 | set_no_inheritance (h, val); |
1fd5e000 CF |
177 | } |
178 | ||
179 | void | |
180 | fhandler_windows::fixup_after_fork (HANDLE parent) | |
181 | { | |
182 | if (get_handle ()) | |
335556d5 | 183 | fhandler_base::fixup_after_fork (parent); |
1fd5e000 CF |
184 | void *h = hWnd_; |
185 | if (h) | |
186 | fork_fixup (parent, h, "hWnd_"); | |
187 | } |