summaryrefslogtreecommitdiff
path: root/winsup/cygwin/window.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/window.cc')
-rw-r--r--winsup/cygwin/window.cc249
1 files changed, 249 insertions, 0 deletions
diff --git a/winsup/cygwin/window.cc b/winsup/cygwin/window.cc
new file mode 100644
index 00000000000..ea9ed6e04bb
--- /dev/null
+++ b/winsup/cygwin/window.cc
@@ -0,0 +1,249 @@
+/* window.cc: hidden windows for signals/itimer support
+
+ Copyright 1997, 1998, 2000, 2001, 2002, 2003 Red Hat, Inc.
+
+ Written by Sergey Okhapkin <sos@prospect.com.ru>
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <sys/time.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <limits.h>
+#include <wingdi.h>
+#include <winuser.h>
+#define USE_SYS_TYPES_FD_SET
+#include <winsock2.h>
+#include <unistd.h>
+#include "cygerrno.h"
+#include "perprocess.h"
+#include "security.h"
+#include "cygthread.h"
+
+static NO_COPY UINT timer_active = 0;
+static NO_COPY struct itimerval itv;
+static NO_COPY DWORD start_time;
+static NO_COPY HWND ourhwnd = NULL;
+
+static LRESULT CALLBACK
+WndProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+#ifndef NOSTRACE
+ strace.wm (uMsg, wParam, lParam);
+#endif
+ switch (uMsg)
+ {
+ case WM_PAINT:
+ return 0;
+ case WM_DESTROY:
+ PostQuitMessage (0);
+ return 0;
+ case WM_TIMER:
+ if (wParam == timer_active)
+ {
+ UINT elapse = itv.it_interval.tv_sec * 1000 +
+ itv.it_interval.tv_usec / 1000;
+ KillTimer (hwnd, timer_active);
+ if (!elapse)
+ {
+ timer_active = 0;
+ }
+ else
+ {
+ timer_active = SetTimer (hwnd, 1, elapse, NULL);
+ start_time = GetTickCount ();
+ itv.it_value = itv.it_interval;
+ }
+ raise (SIGALRM);
+ }
+ return 0;
+ case WM_ASYNCIO:
+ if (WSAGETSELECTEVENT (lParam) == FD_OOB)
+ raise (SIGURG);
+ else
+ raise (SIGIO);
+ return 0;
+ default:
+ return DefWindowProc (hwnd, uMsg, wParam, lParam);
+ }
+}
+
+static HANDLE window_started;
+
+static DWORD WINAPI
+Winmain (VOID *)
+{
+ MSG msg;
+ WNDCLASS wc;
+ static NO_COPY char classname[] = "CygwinWndClass";
+
+ /* Register the window class for the main window. */
+
+ wc.style = 0;
+ wc.lpfnWndProc = (WNDPROC) WndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = user_data->hmodule;
+ wc.hIcon = NULL;
+ wc.hCursor = NULL;
+ wc.hbrBackground = NULL;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = classname;
+
+ if (!RegisterClass (&wc))
+ {
+ system_printf ("Cannot register window class");
+ return FALSE;
+ }
+
+ /* Create hidden window. */
+ ourhwnd = CreateWindow (classname, classname, WS_POPUP, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
+ (HWND) NULL, (HMENU) NULL, user_data->hmodule,
+ (LPVOID) NULL);
+
+ SetEvent (window_started);
+
+ if (!ourhwnd)
+ {
+ system_printf ("Cannot create window");
+ return FALSE;
+ }
+
+ /* Start the message loop. */
+
+ while (GetMessage (&msg, ourhwnd, 0, 0) == TRUE)
+ DispatchMessage (&msg);
+
+ ExitThread (0);
+}
+
+HWND __stdcall
+gethwnd ()
+{
+ if (ourhwnd != NULL)
+ return ourhwnd;
+
+ cygthread *h;
+
+ window_started = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
+ h = new cygthread (Winmain, NULL, "win");
+ h->SetThreadPriority (THREAD_PRIORITY_HIGHEST);
+ WaitForSingleObject (window_started, INFINITE);
+ CloseHandle (window_started);
+ h->zap_h ();
+ return ourhwnd;
+}
+
+extern "C" int
+setitimer (int which, const struct itimerval *value, struct itimerval *oldvalue)
+{
+ UINT elapse;
+
+ if (which != ITIMER_REAL)
+ {
+ set_errno (ENOSYS);
+ return -1;
+ }
+ /* Check if we will wrap */
+ if (itv.it_value.tv_sec >= (long) (UINT_MAX / 1000))
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (timer_active)
+ {
+ KillTimer (gethwnd (), timer_active);
+ timer_active = 0;
+ }
+ if (oldvalue)
+ *oldvalue = itv;
+ if (value == NULL)
+ {
+ set_errno (EFAULT);
+ return -1;
+ }
+ itv = *value;
+ elapse = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000;
+ if (elapse == 0)
+ if (itv.it_value.tv_usec)
+ elapse = 1;
+ else
+ return 0;
+ if (!(timer_active = SetTimer (gethwnd (), 1, elapse, NULL)))
+ {
+ __seterrno ();
+ return -1;
+ }
+ start_time = GetTickCount ();
+ return 0;
+}
+
+extern "C" int
+getitimer (int which, struct itimerval *value)
+{
+ UINT elapse, val;
+
+ if (which != ITIMER_REAL)
+ {
+ set_errno (EINVAL);
+ return -1;
+ }
+ if (value == NULL)
+ {
+ set_errno (EFAULT);
+ return -1;
+ }
+ *value = itv;
+ if (!timer_active)
+ {
+ value->it_value.tv_sec = 0;
+ value->it_value.tv_usec = 0;
+ return 0;
+ }
+ elapse = GetTickCount () - start_time;
+ val = itv.it_value.tv_sec * 1000 + itv.it_value.tv_usec / 1000;
+ val -= elapse;
+ value->it_value.tv_sec = val / 1000;
+ value->it_value.tv_usec = val % 1000;
+ return 0;
+}
+
+extern "C" unsigned int
+alarm (unsigned int seconds)
+{
+ int ret;
+ struct itimerval newt, oldt;
+
+ newt.it_value.tv_sec = seconds;
+ newt.it_value.tv_usec = 0;
+ newt.it_interval.tv_sec = 0;
+ newt.it_interval.tv_usec = 0;
+ setitimer (ITIMER_REAL, &newt, &oldt);
+ ret = oldt.it_value.tv_sec;
+ if (ret == 0 && oldt.it_value.tv_usec)
+ ret = 1;
+ return ret;
+}
+
+extern "C" useconds_t
+ualarm (useconds_t value, useconds_t interval)
+{
+ struct itimerval timer, otimer;
+
+ timer.it_value.tv_sec = 0;
+ timer.it_value.tv_usec = value;
+ timer.it_interval.tv_sec = 0;
+ timer.it_interval.tv_usec = interval;
+
+ if (setitimer (ITIMER_REAL, &timer, &otimer) < 0)
+ return (u_int)-1;
+
+ return (otimer.it_value.tv_sec * 1000000) + otimer.it_value.tv_usec;
+}
+