Browse Source

Get fork() working on Windows

This is done without using Microsoft's internal APIs. MAP_PRIVATE
mappings are copied to the subprocess via a pipe, since Microsoft
doesn't want us to have proper COW pages. MAP_SHARED mappings are
remapped without needing to do any copying. Global variables need
copying along with the stack and the whole heap of anonymous mem.
This actually improves the reliability of the redbean http server
although one shouldn't expect 10k+ connections on a home computer
that isn't running software built to serve like Linux or FreeBSD.
main
Justine Tunney 11 months ago
parent
commit
db33973e0a
  1. 11
      ape/ape.S
  2. 2
      ape/config.h
  3. 2
      build/compile
  4. 10
      dsp/core/core.mk
  5. 10
      dsp/tty/tty.mk
  6. 16
      examples/forkrand.c
  7. 51
      examples/forky.c
  8. 2
      examples/hello.c
  9. 5
      libc/calls/commandv.c
  10. 2
      libc/calls/dup-nt.c
  11. 2
      libc/calls/hefty/dirstream.c
  12. 158
      libc/calls/hefty/fork-nt.c
  13. 11
      libc/calls/hefty/fork.c
  14. 2
      libc/calls/hefty/ntspawn.c
  15. 1
      libc/calls/hefty/spawnlp.c
  16. 4
      libc/calls/hefty/spawnve-nt.c
  17. 4
      libc/calls/hefty/vfork.S
  18. 12
      libc/calls/internal.h
  19. 9
      libc/calls/wait.c
  20. 66
      libc/calls/wait4-nt.c
  21. 7
      libc/calls/zygote.c
  22. 4
      libc/isystem/windows.h
  23. 1
      libc/libc.mk
  24. 3
      libc/log/asan.c
  25. 6
      libc/log/log.mk
  26. 54
      libc/mem/putenv.c
  27. 4
      libc/nt/dll.h
  28. 35
      libc/nt/enum/color.h
  29. 8
      libc/nt/enum/cw.h
  30. 24
      libc/nt/enum/idc.h
  31. 10
      libc/nt/enum/pwr.h
  32. 19
      libc/nt/enum/sw.h
  33. 8
      libc/nt/enum/wa.h
  34. 7
      libc/nt/enum/wait.h
  35. 185
      libc/nt/enum/wm.h
  36. 62
      libc/nt/enum/ws.h
  37. 95
      libc/nt/events.h
  38. 24
      libc/nt/master.sh
  39. 41
      libc/nt/paint.h
  40. 16
      libc/nt/struct/drawtextparams.h
  41. 4
      libc/nt/struct/msg.h
  42. 18
      libc/nt/struct/paintstruct.h
  43. 15
      libc/nt/struct/rect.h
  44. 13
      libc/nt/struct/size.h
  45. 22
      libc/nt/struct/wndclass.h
  46. 24
      libc/nt/struct/wndclassex.h
  47. 4
      libc/nt/synchronization.h
  48. 10
      libc/nt/typedef/wndproc.h
  49. 12
      libc/nt/user32/DefWindowProcA.s
  50. 12
      libc/nt/user32/DefWindowProcW.s
  51. 10
      libc/nt/user32/FillRect.s
  52. 10
      libc/nt/user32/LoadCursorA.s
  53. 10
      libc/nt/user32/LoadCursorW.s
  54. 10
      libc/nt/user32/LoadImageA.s
  55. 10
      libc/nt/user32/LoadImageW.s
  56. 13
      libc/nt/user32/RegisterClassA.s
  57. 13
      libc/nt/user32/RegisterClassExA.s
  58. 13
      libc/nt/user32/RegisterClassExW.s
  59. 13
      libc/nt/user32/RegisterClassW.s
  60. 13
      libc/nt/user32/ShowCaret.s
  61. 13
      libc/nt/user32/ShowCursor.s
  62. 323
      libc/nt/windows.h
  63. 5
      libc/runtime/_exit.S
  64. 2
      libc/runtime/arememoryintervalsok.c
  65. 32
      libc/runtime/directmap.c
  66. 1
      libc/runtime/directmap.h
  67. 51
      libc/runtime/directmapnt.c
  68. 6
      libc/runtime/getdosargv.c
  69. 1
      libc/runtime/internal.h
  70. 38
      libc/runtime/jmpstack.S
  71. 20
      libc/runtime/memtrack.c
  72. 6
      libc/runtime/memtrack.h
  73. 2
      libc/runtime/memtracknt.c
  74. 4
      libc/runtime/mmap.c
  75. 22
      libc/runtime/mmi.c
  76. 2
      libc/runtime/msync-nt.c
  77. 1
      libc/runtime/runtime.h
  78. 5
      libc/runtime/runtime.mk
  79. 106
      libc/runtime/winmain.greg.c
  80. 16
      libc/runtime/winmain.h
  81. 3
      libc/sock/accept-nt.c
  82. 1
      libc/sock/internal.h
  83. 12
      libc/sock/kntwsadata.c
  84. 1
      libc/stdio/stdio.mk
  85. 146
      libc/stdio/system.c
  86. 1
      libc/sysv/sysv.mk
  87. 10
      net/http/http.mk
  88. 6
      test/ape/lib/test.mk
  89. 10
      test/dsp/core/test.mk
  90. 6
      test/libc/intrin/test.mk
  91. 102
      test/libc/runtime/memtrack_test.c
  92. 5
      test/libc/runtime/mmap_test.c
  93. 10
      test/libc/runtime/test.mk
  94. 6
      test/net/http/parsehttprequest_test.c
  95. 6
      test/net/http/test.mk
  96. 10
      third_party/stb/stb.mk
  97. 2
      tool/build/blinkenlights.c
  98. 8
      tool/build/build.mk
  99. 14
      tool/build/lib/buildlib.mk
  100. 2
      tool/build/lib/disarg.c

11
ape/ape.S

@ -225,9 +225,14 @@ pc: cld
3: call pcread
dec %di
jnz 3b
6: mov %ax,XLM(LOADSTATE)+0
mov %cx,XLM(LOADSTATE)+2
mov %dx,XLM(LOADSTATE)+4
6: mov $XLM(LOADSTATE),%di # ax,cx,dx,es
stosw
xchg %cx,%ax
stosw
xchg %dx,%ax
stosw
mov %es,%ax
stosw
ljmp $0,$REAL(realmodeloader)
.endfn pc,globl,hidden

2
ape/config.h

@ -126,7 +126,7 @@
#define XLM_BADIDT 0x2230
#define XLM_BADIDT_SIZE 6
#define XLM_LOADSTATE 0x2240
#define XLM_LOADSTATE_SIZE 6
#define XLM_LOADSTATE_SIZE 8
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)

2
build/compile

@ -280,5 +280,5 @@ if "$@"; then
exit 0
fi
printf "$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
printf "\n$LOGFMT" "$CCNAME $CCVERSION: compile $REASON:" "$*" >&2
exit 1

10
dsp/core/core.mk

@ -58,11 +58,11 @@ o/$(MODE)/dsp/core/det3.o: \
OVERRIDE_CFLAGS += \
-ffast-math
ifeq (,$(MODE))
$(DSP_CORE_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(DSP_CORE_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
DSP_CORE_LIBS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)))
DSP_CORE_SRCS = $(foreach x,$(DSP_CORE_ARTIFACTS),$($(x)_SRCS))

10
dsp/tty/tty.mk

@ -59,11 +59,11 @@ o/$(MODE)/dsp/tty/ttyraster.o: \
OVERRIDE_CFLAGS += \
$(MATHEMATICAL)
ifeq (,$(MODE))
$(DSP_TTY_OBJS): \
OVERRIDE_CFLAGS += \
-fsanitize=address
endif
# ifeq (,$(MODE))
# $(DSP_TTY_OBJS): \
# OVERRIDE_CFLAGS += \
# -fsanitize=address
# endif
DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)))
DSP_TTY_SRCS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)_SRCS))

16
examples/forkrand.c

@ -7,18 +7,20 @@
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/calls/calls.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/nt/nt/process.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/calls/calls.h"
#include "libc/time/time.h"
noinline void dostuff(void) {
int i, us;
srand(rand64()); /* seeds rand() w/ intel rdrnd, auxv, etc. */
for (unsigned i = 0; i < 5; ++i) {
int us = rand() % 500000;
for (i = 0; i < 5; ++i) {
us = rand() % 500000;
usleep(us);
printf("%s%u%s%u [%s=%d]\n", "hello no. ", i, " from ", getpid(), "us", us);
fflush(stdout);
@ -26,9 +28,8 @@ noinline void dostuff(void) {
}
int main(int argc, char *argv[]) {
fprintf(stderr, "%p\n", RtlCloneUserProcess);
int child;
if ((child = fork()) == -1) perror("fork"), exit(1);
int rc, child, wstatus;
CHECK_NE(-1, (child = fork()));
if (!child) {
/* child process */
dostuff();
@ -37,8 +38,7 @@ int main(int argc, char *argv[]) {
/* parent process */
dostuff();
/* note: abandoned children become zombies */
int rc, wstatus;
if ((rc = wait(&wstatus)) == -1) perror("wait"), exit(1);
CHECK_NE(-1, (rc = wait(&wstatus)));
return WEXITSTATUS(wstatus);
}
}

51
examples/forky.c

@ -1,51 +0,0 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
To the extent possible under law, Justine Tunney has waived
all copyright and related or neighboring rights to this file,
as it is written in the following disclaimers:
http://unlicense.org/
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/mem/mem.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/memory.h"
#include "libc/runtime/gc.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/fileno.h"
#include "libc/x/x.h"
int main(int argc, char *argv[]) {
int pid;
long *addr;
int64_t fh;
if (argc == 1) {
fh = CreateFileMappingNuma(-1, &kNtIsInheritable, kNtPageReadwrite, 0,
FRAMESIZE, NULL, kNtNumaNoPreferredNode);
addr = MapViewOfFileExNuma(fh, kNtFileMapRead | kNtFileMapWrite, 0, 0,
FRAMESIZE, NULL, kNtNumaNoPreferredNode);
*addr = 0x31337;
CHECK_NE(-1, (pid = spawnve(
0, (int[3]){STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO},
"o/examples/forky.com",
(char *const[]){"o/examples/forky.com",
gc(xasprintf("%#lx", (intptr_t)addr)),
gc(xasprintf("%#lx", fh)), NULL},
environ)));
CHECK_NE(-1, waitpid(pid, NULL, 0));
} else {
addr = (long *)(intptr_t)strtoul(argv[1], NULL, 0);
fh = strtoul(argv[2], NULL, 0);
addr = MapViewOfFileExNuma(fh, kNtFileMapRead | kNtFileMapWrite, 0, 0,
FRAMESIZE, addr, kNtNumaNoPreferredNode);
printf("%#lx\n", *addr);
}
return 0;
}

2
examples/hello.c

@ -7,8 +7,6 @@
http://creativecommons.org/publicdomain/zero/1.0/
*/
#endif
#include "libc/errno.h"
#include "libc/log/log.h"
#include "libc/stdio/stdio.h"
int main() {

5
libc/calls/commandv.c

@ -24,6 +24,7 @@
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/nt/ntdll.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ok.h"
@ -32,7 +33,7 @@
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
const char *ext) {
len = stpcpy(&pathname[len], ext) - &pathname[0];
if (access(pathname, X_OK) != -1) {
if (isexecutable(pathname)) {
return len;
} else {
return -1;
@ -48,7 +49,7 @@ static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
pathlen = strlen(path);
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
p = mempcpy(pathname, path, pathlen);
if (pathlen) *p++ = '/';
if (pathlen && pathname[pathlen - 1] != '/') *p++ = '/';
p = mempcpy(p, name, namelen);
len = p - &pathname[0];
hasdot = !!memchr(basename(name), '.', namelen);

2
libc/calls/dup-nt.c

@ -44,7 +44,7 @@ textwindows int dup$nt(int oldfd, int newfd, int flags) {
}
if (DuplicateHandle(GetCurrentProcess(), g_fds.p[oldfd].handle,
GetCurrentProcess(), &g_fds.p[newfd].handle, 0,
(flags & O_CLOEXEC), kNtDuplicateSameAccess)) {
flags & O_CLOEXEC, kNtDuplicateSameAccess)) {
g_fds.p[newfd].kind = g_fds.p[oldfd].kind;
g_fds.p[newfd].flags = flags;
return newfd;

2
libc/calls/hefty/dirstream.c

@ -134,7 +134,7 @@ DIR *opendir(const char *name) {
DIR *res;
if (!IsWindows() && !IsXnu()) {
res = NULL;
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC)) != -1) {
if (!(res = fdopendir(fd))) close(fd);
}
return res;

158
libc/calls/hefty/fork-nt.c

@ -0,0 +1,158 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/itoa.h"
#include "libc/nt/enum/filemapflags.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/ipc.h"
#include "libc/nt/memory.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/memtrack.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
static textwindows int64_t ParseInt(char16_t **p) {
uint64_t x = 0;
while ('0' <= **p && **p <= '9') {
x *= 10;
x += *(*p)++ - '0';
}
return x;
}
static textwindows void WriteAll(int64_t h, void *buf, size_t n) {
char *p;
size_t i;
uint32_t wrote;
for (p = buf, i = 0; i < n; i += wrote) {
WriteFile(h, p + i, n - i, &wrote, NULL);
}
}
static textwindows void ReadAll(int64_t h, void *buf, size_t n) {
char *p;
size_t i;
uint32_t got;
for (p = buf, i = 0; i < n; i += got) {
ReadFile(h, p + i, n - i, &got, NULL);
}
}
textwindows void WinMainForked(void) {
int64_t h;
void *addr;
jmp_buf jb;
char16_t *p;
uint64_t size;
char16_t var[21 + 1 + 21 + 1];
uint32_t i, varlen, protect, access;
varlen = GetEnvironmentVariable(u"_FORK", var, ARRAYLEN(var));
if (!varlen || varlen >= ARRAYLEN(var)) return;
p = var;
h = ParseInt(&p);
if (*p++ == ' ') CloseHandle(ParseInt(&p));
ReadAll(h, jb, sizeof(jb));
ReadAll(h, &_mmi.i, sizeof(_mmi.i));
for (i = 0; i < _mmi.i; ++i) {
ReadAll(h, &_mmi.p[i], sizeof(_mmi.p[i]));
addr = (void *)((uint64_t)_mmi.p[i].x << 16);
size = ((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE;
switch (_mmi.p[i].prot) {
case PROT_READ | PROT_WRITE | PROT_EXEC:
protect = kNtPageExecuteReadwrite;
access = kNtFileMapRead | kNtFileMapWrite | kNtFileMapExecute;
break;
case PROT_READ | PROT_WRITE:
protect = kNtPageReadwrite;
access = kNtFileMapRead | kNtFileMapWrite;
break;
case PROT_READ:
protect = kNtPageReadonly;
access = kNtFileMapRead;
break;
default:
protect = kNtPageNoaccess;
access = 0;
break;
}
if (_mmi.p[i].flags & MAP_PRIVATE) {
MapViewOfFileExNuma(
(_mmi.p[i].h = CreateFileMappingNuma(-1, NULL, protect, 0, size, NULL,
kNtNumaNoPreferredNode)),
access, 0, 0, size, addr, kNtNumaNoPreferredNode);
ReadAll(h, addr, size);
} else {
MapViewOfFileExNuma(_mmi.p[i].h, access, 0, 0, size, addr,
kNtNumaNoPreferredNode);
}
}
ReadAll(h, _edata, _end - _edata);
CloseHandle(h);
longjmp(jb, 1);
}
textwindows int fork$nt(void) {
jmp_buf jb;
int64_t reader, writer;
int i, rc, pid, fds[3];
char *p, buf[21 + 1 + 21 + 1];
if (!setjmp(jb)) {
if (CreatePipe(&reader, &writer, &kNtIsInheritable, 0)) {
p = buf;
p += uint64toarray_radix10(reader, p);
*p++ = ' ';
p += uint64toarray_radix10(writer, p);
setenv("_FORK", buf, true);
fds[0] = 0;
fds[1] = 1;
fds[2] = 2;
/* TODO: CloseHandle(g_fds.p[pid].h) if SIGCHLD is SIG_IGN */
if ((pid = spawnve(0, fds, g_argv[0], g_argv, environ)) != -1) {
CloseHandle(reader);
WriteAll(writer, jb, sizeof(jb));
WriteAll(writer, &_mmi.i, sizeof(_mmi.i));
for (i = 0; i < _mmi.i; ++i) {
WriteAll(writer, &_mmi.p[i], sizeof(_mmi.p[i]));
if (_mmi.p[i].flags & MAP_PRIVATE) {
WriteAll(writer, (void *)((uint64_t)_mmi.p[i].x << 16),
((uint64_t)(_mmi.p[i].y - _mmi.p[i].x) << 16) + FRAMESIZE);
}
}
WriteAll(writer, _edata, _end - _edata);
CloseHandle(writer);
rc = pid;
} else {
rc = -1;
}
unsetenv("_FORK");
} else {
rc = winerr();
}
} else {
rc = 0;
}
return rc;
}

11
libc/calls/fork.c → libc/calls/hefty/fork.c

@ -20,6 +20,7 @@
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
/**
* Creates new process zygote style.
@ -29,7 +30,13 @@
*/
int fork(void) {
int rc;
rc = fork$sysv();
if (rc == 0) __onfork();
if (!IsWindows()) {
rc = fork$sysv();
} else {
rc = fork$nt();
}
if (rc == 0) {
__onfork();
}
return rc;
}

2
libc/calls/hefty/ntspawn.c

@ -25,8 +25,10 @@
#include "libc/calls/hefty/ntspawn.h"
#include "libc/calls/internal.h"
#include "libc/conv/conv.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/fileno.h"

1
libc/calls/hefty/spawnlp.c

@ -21,6 +21,7 @@
#include "libc/calls/hefty/mkvarargv.h"
#include "libc/calls/hefty/spawn.h"
#include "libc/mem/mem.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
/**

4
libc/calls/hefty/spawnve-nt.c

@ -67,7 +67,7 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
}
if (handle != -1 &&
ntspawn(program, argv, envp, NULL, NULL,
ntspawn(program, argv, envp, &kNtIsInheritable, NULL,
(flags & SPAWN_TABULARASA) ? false : true,
(flags & SPAWN_DETACH)
? (kNtCreateNewProcessGroup | kNtDetachedProcess |
@ -83,7 +83,7 @@ textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
if (handle != -1) {
stdiofds[i] = tubes[i];
g_fds.p[tubes[i]].kind = kFdFile;
g_fds.p[tubes[i]].flags = O_CLOEXEC;
g_fds.p[tubes[i]].flags = 0;
CloseHandle(sti.stdiofds[i]);
} else {
CloseHandle(tubes[i]);

4
libc/sysv/vfork.S → libc/calls/hefty/vfork.S

@ -27,7 +27,9 @@
/
/ @return pid of child process or 0 if forked process
/ @returnstwice
vfork: mov __NR_vfork(%rip),%eax
vfork: testb IsWindows()
jnz fork$nt
mov __NR_vfork(%rip),%eax
cmp $-1,%eax
je systemfive.enosys
pop %rsi

12
libc/calls/internal.h

@ -56,11 +56,11 @@ struct Fds {
extern const struct Fd kEmptyFd;
extern int g_sighandrvas[NSIG] hidden;
extern struct Fds g_fds hidden;
extern struct NtSystemInfo g_ntsysteminfo hidden;
extern struct NtStartupInfo g_ntstartupinfo hidden;
extern const struct NtSecurityAttributes kNtIsInheritable hidden;
hidden extern int g_sighandrvas[NSIG];
hidden extern struct Fds g_fds;
hidden extern struct NtSystemInfo g_ntsysteminfo;
hidden extern struct NtStartupInfo g_ntstartupinfo;
hidden extern const struct NtSecurityAttributes kNtIsInheritable;
ssize_t createfd(void) hidden;
int growfds(void) hidden;
@ -218,6 +218,7 @@ void xnutrampoline(void *, i32, i32, const struct __darwin_siginfo *,
int gettimeofday$nt(struct timeval *, struct timezone *) hidden;
bool32 isatty$nt(int) hidden;
char *getcwd$nt(char *, size_t) hidden;
int fork$nt(void) hidden;
int chdir$nt(const char *) hidden;
int close$nt(int) hidden;
int dup$nt(int, int, int) hidden;
@ -258,6 +259,7 @@ int nanosleep$nt(const struct timespec *, struct timespec *) hidden;
cosmopolitan § syscalls » windows nt » support
*/
void WinMainForked(void) hidden;
int getsetpriority$nt(int, unsigned, int, int (*)(int));
void ntcontext2linux(struct ucontext *, const struct NtContext *) hidden;
struct NtOverlapped *offset2overlap(int64_t, struct NtOverlapped *) hidden;

9
libc/calls/wait.c

@ -18,9 +18,6 @@
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dce.h"
#include "libc/sysv/errfuns.h"
/**
* Waits for status to change on any child process.
@ -31,9 +28,5 @@
* @asyncsignalsafe
*/
int wait(int *opt_out_wstatus) {
if (!IsWindows()) {
return wait4$sysv(-1, opt_out_wstatus, 0, NULL);
} else {
return enosys(); /* TODO(jart) */
}
return wait4(-1, opt_out_wstatus, 0, NULL);
}

66
libc/calls/wait4-nt.c

@ -21,11 +21,14 @@
#include "libc/calls/internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/conv/conv.h"
#include "libc/macros.h"
#include "libc/nt/accounting.h"
#include "libc/nt/enum/status.h"
#include "libc/nt/enum/wait.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/filetime.h"
#include "libc/nt/synchronization.h"
#include "libc/runtime/missioncritical.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/w.h"
@ -33,34 +36,51 @@
textwindows int wait4$nt(int pid, int *opt_out_wstatus, int options,
struct rusage *opt_out_rusage) {
int pids[64];
int64_t handles[64];
uint32_t dwExitCode;
uint32_t i, count, timeout;
struct NtFileTime createfiletime, exitfiletime, kernelfiletime, userfiletime;
if (!isfdkind(pid, kFdProcess)) return esrch();
for (;;) {
dwExitCode = kNtStillActive;
if (!(options & WNOHANG)) {
WaitForSingleObject(g_fds.p[pid].handle, 0xffffffff);
if (pid != -1) {
if (!isfdkind(pid, kFdProcess)) {
return echild();
}
if (GetExitCodeProcess(g_fds.p[pid].handle, &dwExitCode)) {
if (dwExitCode != kNtStillActive) {
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
}
if (opt_out_rusage) {
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
GetProcessTimes(GetCurrentProcess(), &createfiletime, &exitfiletime,
&kernelfiletime, &userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
return pid;
} else if (options & WNOHANG) {
return pid;
} else {
continue;
handles[0] = g_fds.p[pid].handle;
pids[0] = pid;
count = 1;
} else {
for (count = 0, i = g_fds.n; i--;) {
if (g_fds.p[i].kind == kFdProcess) {
pids[count] = i;
handles[count] = g_fds.p[i].handle;
if (++count == ARRAYLEN(handles)) break;
}
}
if (!count) {
return echild();
}
}
for (;;) {
dwExitCode = kNtStillActive;
if (options & WNOHANG) {
i = WaitForMultipleObjects(count, handles, false, 0);
if (i == kNtWaitTimeout) return 0;
} else {
return winerr();
i = WaitForMultipleObjects(count, handles, false, -1);
}
if (i == kNtWaitFailed) return winerr();
if (!GetExitCodeProcess(handles[i], &dwExitCode)) return winerr();
if (dwExitCode == kNtStillActive) continue;
if (opt_out_wstatus) { /* @see WEXITSTATUS() */
*opt_out_wstatus = (dwExitCode & 0xff) << 8;
}
if (opt_out_rusage) {
memset(opt_out_rusage, 0, sizeof(*opt_out_rusage));
GetProcessTimes(GetCurrentProcess(), &createfiletime, &exitfiletime,
&kernelfiletime, &userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_utime, userfiletime);
FileTimeToTimeVal(&opt_out_rusage->ru_stime, kernelfiletime);
}
return pids[i];
}
}

7
libc/calls/zygote.c

@ -17,8 +17,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/nt/struct/securityattributes.h"
#include "libc/calls/internal.h"
#include "libc/nt/struct/securityattributes.h"
const struct NtSecurityAttributes kNtIsInheritable = {
sizeof(struct NtSecurityAttributes), NULL, true};
sizeof(struct NtSecurityAttributes),
NULL,
true,
};

4
libc/isystem/windows.h

@ -69,9 +69,9 @@
#define PINT_PTR intptr_t*
#define UINT_PTR uintptr_t
#define PUINT_PTR uintptr_t*
#define LONG_PTR int32_t*
#define LONG_PTR intptr_t
#define PLONG_PTR int32_t**
#define ULONG_PTR uint32_t*
#define ULONG_PTR uintptr_t
#define PULONG_PTR uint32_t**
#define POINTER_64_INT int64_t*
#define __int3264 int64_t

1
libc/libc.mk

@ -15,7 +15,6 @@ o/$(MODE)/libc: o/$(MODE)/libc/alg \
o/$(MODE)/libc/crt \
o/$(MODE)/libc/dns \
o/$(MODE)/libc/elf \
o/$(MODE)/libc/escape \
o/$(MODE)/libc/fmt \
o/$(MODE)/libc/intrin \
o/$(MODE)/libc/linux \

3
libc/log/asan.c

@ -401,7 +401,8 @@ void __asan_map_shadow(void *p, size_t n) {
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
if (sm.addr == MAP_FAILED ||
TrackMemoryInterval(&_mmi, a, a, sm.maphandle) == -1) {
TrackMemoryInterval(&_mmi, a, a, sm.maphandle, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED) == -1) {
abort();
}
}

6
libc/log/log.mk

@ -64,9 +64,9 @@ $(LIBC_LOG_A_OBJS): \
$(NO_MAGIC) \
-fwrapv
ifeq (,$(MODE))
LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o
endif
# ifeq (,$(MODE))
# LIBC_LOG_ASAN = o/$(MODE)/libc/log/asan.o
# endif
LIBC_LOG_ASAN_A = o/$(MODE)/libc/log/log.a
LIBC_LOG_LIBS = $(foreach x,$(LIBC_LOG_ARTIFACTS),$($(x)))

54
libc/mem/putenv.c

@ -24,53 +24,49 @@
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
static size_t g_environcap;
#define MAX_VARS 512
int PutEnvImpl(char *string, bool overwrite) {
if (!environ) {
g_environcap = 0;
if ((environ = calloc(8, sizeof(char *)))) {
g_environcap = 8;
}
}
char *equalp = strchr(string, '=');
if (!equalp) return einval();
unsigned namelen = equalp + 1 - string;
unsigned i;
int PutEnvImpl(char *s, bool overwrite) {
char *p;
unsigned i, namelen;
p = strchr(s, '=');
if (!p) goto fail;
namelen = p + 1 - s;
for (i = 0; environ[i]; ++i) {
if (strncmp(environ[i], string, namelen) == 0) {
if (strncmp(environ[i], s, namelen) == 0) {
if (!overwrite) {
free_s(&string);
free(s);
return 0;
}
goto replace;
}
}
if (i + 1 >= g_environcap) {
if (!g_environcap) g_environcap = i + 1;
if (!grow(&environ, &g_environcap, sizeof(char *), 0)) {
free_s(&string);
return -1;
}
}
if (i + 1 >= MAX_VARS) goto fail;
environ[i + 1] = NULL;
replace:
free_s(&environ[i]);
environ[i] = string;
free(environ[i]);
environ[i] = s;
return 0;
fail:
free(s);
return einval();
}
/**
* Emplaces environment key=value.
* @see setenv(), getenv()
*/
int putenv(char *string) { return PutEnvImpl(string, true); }
textexit static void putenv_fini(void) {
for (char **envp = environ; *envp; ++envp) free_s(envp);
free_s(&environ);
int putenv(char *string) {
return PutEnvImpl(strdup(string), true);
}
textstartup static void putenv_init(void) { atexit(putenv_fini); }
textstartup static void putenv_init(void) {
char **pin, **pout;
pin = environ;
pout = malloc(sizeof(char *) * MAX_VARS);
environ = pout;
while (*pin) *pout++ = strdup(*pin++);
*pout = NULL;
}
const void *const putenv_ctor[] initarray = {putenv_init};

4
libc/nt/dll.h

@ -34,8 +34,8 @@ int64_t LoadLibraryEx(const char16_t *lpLibFileName, int64_t hFile,
uint32_t dwFlags);
uint32_t GetModuleFileName(int64_t hModule, char16_t *lpFilename,
uint32_t nSize);
intptr_t GetModuleHandle(const char *lpModuleName);
intptr_t GetModuleHandleW(const char16_t *lpModuleName);
intptr_t GetModuleHandle(const char *opt_lpModuleName);
intptr_t GetModuleHandleW(const char16_t *opt_lpModuleName);
void *GetProcAddress(int64_t hModule, const char *lpProcName);
int32_t FreeResource(int64_t hResData);
intptr_t LockResource(int64_t hResData);

35
libc/nt/enum/color.h

@ -0,0 +1,35 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_
#define kNtColorScrollbar 0
#define kNtColorBackground 1
#define kNtColorActivecaption 2
#define kNtColorInactivecaption 3
#define kNtColorMenu 4
#define kNtColorWindow 5
#define kNtColorWindowframe 6
#define kNtColorMenutext 7
#define kNtColorWindowtext 8
#define kNtColorCaptiontext 9
#define kNtColorActiveborder 10
#define kNtColorInactiveborder 11
#define kNtColorAppworkspace 12
#define kNtColorHighlight 13
#define kNtColorHighlighttext 14
#define kNtColorBtnface 15
#define kNtColorBtnshadow 16
#define kNtColorGraytext 17
#define kNtColorBtntext 18
#define kNtColorInactivecaptiontext 19
#define kNtColorBtnhighlight 20
#define kNtColor3ddkshadow 21
#define kNtColor3dlight 22
#define kNtColorInfotext 23
#define kNtColorInfobk 24
#define kNtColorHotlight 26
#define kNtColorGradientactivecaption 27
#define kNtColorGradientinactivecaption 28
#define kNtColorMenuhilight 29
#define kNtColorMenubar 30
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_COLOR_H_ */

8
libc/nt/enum/cw.h

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_CW_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_CW_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define kNtCwUsedefault ((int)0x80000000)
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_CW_H_ */

24
libc/nt/enum/idc.h

@ -0,0 +1,24 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define kNtIdcArrow ((const char16_t *)32512)
#define kNtIdcIbeam ((const char16_t *)32513)
#define kNtIdcWait ((const char16_t *)32514)
#define kNtIdcCross ((const char16_t *)32515)
#define kNtIdcUparrow ((const char16_t *)32516)
#define kNtIdcSizenwse ((const char16_t *)32642)
#define kNtIdcSizenesw ((const char16_t *)32643)
#define kNtIdcSizewe ((const char16_t *)32644)
#define kNtIdcSizens ((const char16_t *)32645)
#define kNtIdcSizeall ((const char16_t *)32646)
#define kNtIdcNo ((const char16_t *)32648)
#define kNtIdcHand ((const char16_t *)32649)
#define kNtIdcHelp ((const char16_t *)32651)
#define kNtIdcPin ((const char16_t *)32671)
#define kNtIdcPerson ((const char16_t *)32672)
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_IDC_H_ */

10
libc/nt/enum/pwr.h

@ -0,0 +1,10 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_
#define kNtPwrOk 1
#define kNtPwrFail (-1)
#define kNtPwrSuspendrequest 1
#define kNtPwrSuspendresume 2
#define kNtPwrCriticalresume 3
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_PWR_H_ */

19
libc/nt/enum/sw.h

@ -0,0 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_SW_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_SW_H_
#define kNtSwHide 0
#define kNtSwShownormal 1
#define kNtSwNormal 1
#define kNtSwShowminimized 2
#define kNtSwShowmaximized 3
#define kNtSwMaximize 3
#define kNtSwShownoactivate 4
#define kNtSwShow 5
#define kNtSwMinimize 6
#define kNtSwShowminnoactive 7
#define kNtSwShowna 8
#define kNtSwRestore 9
#define kNtSwShowdefault 10
#define kNtSwForceminimize 11
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_SW_H_ */

8
libc/nt/enum/wa.h

@ -0,0 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WA_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WA_H_
#define kNtWaInactive 0
#define kNtWaActive 1
#define kNtWaClickactive 2
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WA_H_ */

7
libc/nt/enum/wait.h

@ -0,0 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_
#define kNtWaitFailed 0xffffffffu
#define kNtWaitTimeout 0x00000102u
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WAIT_H_ */

185
libc/nt/enum/wm.h

@ -0,0 +1,185 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WM_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WM_H_
#define kNtWmNull 0x0000
#define kNtWmCreate 0x0001
#define kNtWmDestroy 0x0002
#define kNtWmMove 0x0003
#define kNtWmSize 0x0005
#define kNtWmActivate 0x0006
#define kNtWmSetfocus 0x0007
#define kNtWmKillfocus 0x0008
#define kNtWmEnable 0x000A
#define kNtWmSetredraw 0x000B
#define kNtWmSettext 0x000C
#define kNtWmGettext 0x000D
#define kNtWmGettextlength 0x000E
#define kNtWmPaint 0x000F
#define kNtWmClose 0x0010
#define kNtWmQueryendsession 0x0011
#define kNtWmQueryopen 0x0013
#define kNtWmEndsession 0x0016
#define kNtWmQuit 0x0012
#define kNtWmErasebkgnd 0x0014
#define kNtWmSyscolorchange 0x0015
#define kNtWmShowwindow 0x0018
#define kNtWmWininichange 0x001A
#define kNtWmSettingchange kNtWmWininichange
#define kNtWmDevmodechange 0x001B
#define kNtWmActivateapp 0x001C
#define kNtWmFontchange 0x001D
#define kNtWmTimechange 0x001E
#define kNtWmCancelmode 0x001F
#define kNtWmSetcursor 0x0020
#define kNtWmMouseactivate 0x0021
#define kNtWmChildactivate 0x0022
#define kNtWmQueuesync 0x0023
#define kNtWmGetminmaxinfo 0x0024
#define kNtWmPainticon 0x0026
#define kNtWmIconerasebkgnd 0x0027
#define kNtWmNextdlgctl 0x0028
#define kNtWmSpoolerstatus 0x002A
#define kNtWmDrawitem 0x002B
#define kNtWmMeasureitem 0x002C
#define kNtWmDeleteitem 0x002D
#define kNtWmVkeytoitem 0x002E
#define kNtWmChartoitem 0x002F
#define kNtWmSetfont 0x0030
#define kNtWmGetfont 0x0031
#define kNtWmSethotkey 0x0032
#define kNtWmGethotkey 0x0033
#define kNtWmQuerydragicon 0x0037
#define kNtWmCompareitem 0x0039
#define kNtWmGetobject 0x003D
#define kNtWmCompacting 0x0041
#define kNtWmWindowposchanging 0x0046
#define kNtWmWindowposchanged 0x0047
#define kNtWmPower 0x0048
#define kNtWmCopydata 0x004A
#define kNtWmCanceljournal 0x004B
#define kNtWmNotify 0x004E
#define kNtWmInputlangchangerequest 0x0050
#define kNtWmInputlangchange 0x0051
#define kNtWmTcard 0x0052
#define kNtWmHelp 0x0053
#define kNtWmUserchanged 0x0054
#define kNtWmNotifyformat 0x0055
#define kNtWmContextmenu 0x007B
#define kNtWmStylechanging 0x007C
#define kNtWmStylechanged 0x007D
#define kNtWmDisplaychange 0x007E
#define kNtWmGeticon 0x007F
#define kNtWmSeticon 0x0080
#define kNtWmNccreate 0x0081
#define kNtWmNcdestroy 0x0082
#define kNtWmNccalcsize 0x0083
#define kNtWmNchittest 0x0084
#define kNtWmNcpaint 0x0085
#define kNtWmNcactivate 0x0086
#define kNtWmGetdlgcode 0x0087
#define kNtWmNcmousemove 0x00A0
#define kNtWmNclbuttondown 0x00A1
#define kNtWmNclbuttonup 0x00A2
#define kNtWmNclbuttondblclk 0x00A3
#define kNtWmNcrbuttondown 0x00A4
#define kNtWmNcrbuttonup 0x00A5
#define kNtWmNcrbuttondblclk 0x00A6
#define kNtWmNcmbuttondown 0x00A7
#define kNtWmNcmbuttonup 0x00A8
#define kNtWmNcmbuttondblclk 0x00A9
#define kNtWmNcxbuttondown 0x00AB
#define kNtWmNcxbuttonup 0x00AC
#define kNtWmNcxbuttondblclk 0x00AD
#define kNtWmKeyfirst 0x0100
#define kNtWmKeydown 0x0100
#define kNtWmKeyup 0x0101
#define kNtWmChar 0x0102
#define kNtWmDeadchar 0x0103
#define kNtWmSyskeydown 0x0104
#define kNtWmSyskeyup 0x0105
#define kNtWmSyschar 0x0106
#define kNtWmSysdeadchar 0x0107
#define kNtWmUnichar 0x0109
#define kNtWmKeylast 0x0109
#define kNtWmInitdialog 0x0110
#define kNtWmCommand 0x0111
#define kNtWmSyscommand 0x0112
#define kNtWmTimer 0x0113
#define kNtWmHscroll 0x0114
#define kNtWmVscroll 0x0115
#define kNtWmInitmenu 0x0116
#define kNtWmInitmenupopup 0x0117
#define kNtWmGesture 0x0119
#define kNtWmGesturenotify 0x011A
#define kNtWmMenuselect 0x011F
#define kNtWmMenuchar 0x0120
#define kNtWmEnteridle 0x0121
#define kNtWmMenurbuttonup 0x0122
#define kNtWmMenudrag 0x0123
#define kNtWmMenugetobject 0x0124
#define kNtWmUninitmenupopup 0x0125
#define kNtWmMenucommand 0x0126
#define kNtWmChangeuistate 0x0127
#define kNtWmUpdateuistate 0x0128
#define kNtWmQueryuistate 0x0129
#define kNtWmMousefirst 0x0200
#define kNtWmMousemove 0x0200
#define kNtWmLbuttondown 0x0201
#define kNtWmLbuttonup 0x0202
#define kNtWmLbuttondblclk 0x0203
#define kNtWmRbuttondown 0x0204
#define kNtWmRbuttonup 0x0205
#define kNtWmRbuttondblclk 0x0206
#define kNtWmMbuttondown 0x0207
#define kNtWmMbuttonup 0x0208
#define kNtWmMbuttondblclk 0x0209
#define kNtWmMousewheel 0x020A
#define kNtWmXbuttondown 0x020B
#define kNtWmXbuttonup 0x020C
#define kNtWmXbuttondblclk 0x020D
#define kNtWmMousehwheel 0x020E
#define kNtWmMouselast 0x020E
#define kNtWmParentnotify 0x0210
#define kNtWmEntermenuloop 0x0211
#define kNtWmExitmenuloop 0x0212
#define kNtWmNextmenu 0x0213
#define kNtWmSizing 0x0214
#define kNtWmCapturechanged 0x0215
#define kNtWmMoving 0x0216
#define kNtWmPowerbroadcast 0x0218
#define kNtWmMdicreate 0x0220
#define kNtWmMdidestroy 0x0221
#define kNtWmMdiactivate 0x0222
#define kNtWmMdirestore 0x0223
#define kNtWmMdinext 0x0224
#define kNtWmMdimaximize 0x0225
#define kNtWmMditile 0x0226
#define kNtWmMdicascade 0x0227
#define kNtWmMdiiconarrange 0x0228
#define kNtWmMdigetactive 0x0229
#define kNtWmMdisetmenu 0x0230
#define kNtWmEntersizemove 0x0231
#define kNtWmExitsizemove 0x0232
#define kNtWmDropfiles 0x0233
#define kNtWmMdirefreshmenu 0x0234
#define kNtWmCut 0x0300
#define kNtWmCopy 0x0301
#define kNtWmPaste 0x0302
#define kNtWmClear 0x0303
#define kNtWmUndo 0x0304
#define kNtWmRenderformat 0x0305
#define kNtWmRenderallformats 0x0306
#define kNtWmDestroyclipboard 0x0307
#define kNtWmDrawclipboard 0x0308
#define kNtWmPaintclipboard 0x0309
#define kNtWmVscrollclipboard 0x030A
#define kNtWmSizeclipboard 0x030B
#define kNtWmAskcbformatname 0x030C
#define kNtWmChangecbchain 0x030D
#define kNtWmHscrollclipboard 0x030E
#define kNtWmQuerynewpalette 0x030F
#define kNtWmPaletteischanging 0x0310
#define kNtWmPalettechanged 0x0311
#define kNtWmHotkey 0x0312
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WM_H_ */

62
libc/nt/enum/ws.h

@ -0,0 +1,62 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_WS_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_WS_H_
#define kNtWsOverlapped 0x00000000
#define kNtWsPopup 0x80000000
#define kNtWsChild 0x40000000
#define kNtWsMinimize 0x20000000
#define kNtWsVisible 0x10000000
#define kNtWsDisabled 0x08000000
#define kNtWsClipsiblings 0x04000000
#define kNtWsClipchildren 0x02000000
#define kNtWsMaximize 0x01000000
#define kNtWsCaption 0x00C00000
#define kNtWsBorder 0x00800000
#define kNtWsDlgframe 0x00400000
#define kNtWsVscroll 0x00200000
#define kNtWsHscroll 0x00100000
#define kNtWsSysmenu 0x00080000
#define kNtWsThickframe 0x00040000
#define kNtWsGroup 0x00020000
#define kNtWsTabstop 0x00010000
#define kNtWsMinimizebox 0x00020000
#define kNtWsMaximizebox 0x00010000
#define kNtWsTiled kNtWsOverlapped
#define kNtWsIconic kNtWsMinimize
#define kNtWsSizebox kNtWsThickframe
#define kNtWsTiledwindow kNtWsOverlappedwindow
#define kNtWsOverlappedwindow \
(kNtWsOverlapped | kNtWsCaption | kNtWsSysmenu | kNtWsThickframe | \
kNtWsMinimizebox | kNtWsMaximizebox)
#define kNtWsPopupwindow (kNtWsPopup | kNtWsBorder | kNtWsSysmenu)
#define kNtWsExDlgmodalframe 0x00000001
#define kNtWsExNoparentnotify 0x00000004
#define kNtWsExTopmost 0x00000008
#define kNtWsExAcceptfiles 0x00000010
#define kNtWsExTransparent 0x00000020
#define kNtWsExMdichild 0x00000040
#define kNtWsExToolwindow 0x00000080
#define kNtWsExWindowedge 0x00000100
#define kNtWsExClientedge 0x00000200
#define kNtWsExContexthelp 0x00000400
#define kNtWsExRight 0x00001000
#define kNtWsExLeft 0x00000000
#define kNtWsExRtlreading 0x00002000
#define kNtWsExLtrreading 0x00000000
#define kNtWsExLeftscrollbar 0x00004000
#define kNtWsExRightscrollbar 0x00000000
#define kNtWsExControlparent 0x00010000
#define kNtWsExStaticedge 0x00020000
#define kNtWsExAppwindow 0x00040000
#define kNtWsExNoinheritlayout 0x00100000
#define kNtWsExNoredirectionbitmap 0x00200000
#define kNtWsExLayoutrtl 0x00400000
#define kNtWsExComposited 0x02000000
#define kNtWsExNoactivate 0x08000000
#define kNtWsExOverlappedwindow (kNtWsExWindowedge | kNtWsExClientedge)
#define kNtWsExPalettewindow \
(kNtWsExWindowedge | kNtWsExToolwindow | kNtWsExTopmost)
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_WS_H_ */

95
libc/nt/events.h

@ -1,5 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_NT_EVENTS_H_
#define COSMOPOLITAN_LIBC_NT_EVENTS_H_
#include "libc/nt/struct/msg.h"
#include "libc/nt/struct/point.h"
#if 0
/* ░░░░
@ -27,64 +29,61 @@
*/
#endif
#define NT_EVENT_SYSTEM_SOUND 0x0001
#define NT_EVENT_SYSTEM_ALERT 0x0002
#define NT_EVENT_SYSTEM_FOREGROUND 0x0003
#define NT_EVENT_SYSTEM_MENUSTART 0x0004
#define NT_EVENT_SYSTEM_MENUEND 0x0005
#define NT_EVENT_SYSTEM_MENUPOPUPSTART 0x0006
#define NT_EVENT_SYSTEM_MENUPOPUPEND 0x0007
#define NT_EVENT_SYSTEM_CAPTURESTART 0x0008
#define NT_EVENT_SYSTEM_CAPTUREEND 0x0009
#define NT_EVENT_SYSTEM_MOVESIZESTART 0x000A
#define NT_EVENT_SYSTEM_MOVESIZEEND 0x000B
#define NT_EVENT_SYSTEM_SOUND 0x0001
#define NT_EVENT_SYSTEM_ALERT 0x0002
#define NT_EVENT_SYSTEM_FOREGROUND 0x0003
#define NT_EVENT_SYSTEM_MENUSTART 0x0004
#define NT_EVENT_SYSTEM_MENUEND 0x0005
#define NT_EVENT_SYSTEM_MENUPOPUPSTART 0x0006
#define NT_EVENT_SYSTEM_MENUPOPUPEND 0x0007
#define NT_EVENT_SYSTEM_CAPTURESTART 0x0008
#define NT_EVENT_SYSTEM_CAPTUREEND 0x0009
#define NT_EVENT_SYSTEM_MOVESIZESTART 0x000A
#define NT_EVENT_SYSTEM_MOVESIZEEND 0x000B
#define NT_EVENT_SYSTEM_CONTEXTHELPSTART 0x000C
#define NT_EVENT_SYSTEM_CONTEXTHELPEND 0x000D
#define NT_EVENT_SYSTEM_DRAGDROPSTART 0x000E
#define NT_EVENT_SYSTEM_DRAGDROPEND 0x000F
#define NT_EVENT_SYSTEM_DIALOGSTART 0x0010
#define NT_EVENT_SYSTEM_DIALOGEND 0x0011
#define NT_EVENT_SYSTEM_SCROLLINGSTART 0x0012
#define NT_EVENT_SYSTEM_SCROLLINGEND 0x0013
#define NT_EVENT_SYSTEM_SWITCHSTART 0x0014
#define NT_EVENT_SYSTEM_SWITCHEND 0x0015
#define NT_EVENT_SYSTEM_MINIMIZESTART 0x0016
#define NT_EVENT_SYSTEM_MINIMIZEEND 0x0017
#define NT_EVENT_SYSTEM_CONTEXTHELPEND 0x000D
#define NT_EVENT_SYSTEM_DRAGDROPSTART 0x000E
#define NT_EVENT_SYSTEM_DRAGDROPEND 0x000F
#define NT_EVENT_SYSTEM_DIALOGSTART 0x0010
#define NT_EVENT_SYSTEM_DIALOGEND 0x0011
#define NT_EVENT_SYSTEM_SCROLLINGSTART 0x0012
#define NT_EVENT_SYSTEM_SCROLLINGEND 0x0013
#define NT_EVENT_SYSTEM_SWITCHSTART 0x0014
#define NT_EVENT_SYSTEM_SWITCHEND 0x0015
#define NT_EVENT_SYSTEM_MINIMIZESTART 0x0016
#define NT_EVENT_SYSTEM_MINIMIZEEND 0x0017
#define NT_EVENT_CONSOLE_CARET 0x4001
#define NT_EVENT_CONSOLE_UPDATE_REGION 0x4002
#define NT_EVENT_CONSOLE_UPDATE_SIMPLE 0x4003
#define NT_EVENT_CONSOLE_UPDATE_SCROLL 0x4004
#define NT_EVENT_CONSOLE_LAYOUT 0x4005
#define NT_EVENT_CONSOLE_CARET 0x4001
#define NT_EVENT_CONSOLE_UPDATE_REGION 0x4002
#define NT_EVENT_CONSOLE_UPDATE_SIMPLE 0x4003
#define NT_EVENT_CONSOLE_UPDATE_SCROLL 0x4004
#define NT_EVENT_CONSOLE_LAYOUT 0x4005
#define NT_EVENT_CONSOLE_START_APPLICATION 0x4006
#define NT_EVENT_CONSOLE_END_APPLICATION 0x4007
#define NT_EVENT_CONSOLE_END_APPLICATION 0x4007
#define NT_EVENT_OBJECT_CREATE 0x8000
#define NT_EVENT_OBJECT_DESTROY 0x8001
#define NT_EVENT_OBJECT_SHOW 0x8002
#define NT_EVENT_OBJECT_HIDE 0x8003
#define NT_EVENT_OBJECT_REORDER 0x8004
#define NT_EVENT_OBJECT_FOCUS 0x8005
#define NT_EVENT_OBJECT_SELECTION 0x8006
#define NT_EVENT_OBJECT_SELECTIONADD 0x8007
#define NT_EVENT_OBJECT_SELECTIONREMOVE 0x8008
#define NT_EVENT_OBJECT_SELECTIONWITHIN 0x8009
#define NT_EVENT_OBJECT_STATECHANGE 0x800A
#define NT_EVENT_OBJECT_LOCATIONCHANGE 0x800B
#define NT_EVENT_OBJECT_NAMECHANGE 0x800C
#define NT_EVENT_OBJECT_CREATE 0x8000
#define NT_EVENT_OBJECT_DESTROY 0x8001
#define NT_EVENT_OBJECT_SHOW 0x8002
#define NT_EVENT_OBJECT_HIDE 0x8003
#define NT_EVENT_OBJECT_REORDER 0x8004
#define NT_EVENT_OBJECT_FOCUS 0x8005
#define NT_EVENT_OBJECT_SELECTION 0x8006
#define NT_EVENT_OBJECT_SELECTIONADD 0x8007
#define NT_EVENT_OBJECT_SELECTIONREMOVE 0x8008
#define NT_EVENT_OBJECT_SELECTIONWITHIN 0x8009
#define NT_EVENT_OBJECT_STATECHANGE 0x800A
#define NT_EVENT_OBJECT_LOCATIONCHANGE 0x800B
#define NT_EVENT_OBJECT_NAMECHANGE 0x800C
#define NT_EVENT_OBJECT_DESCRIPTIONCHANGE 0x800D
#define NT_EVENT_OBJECT_VALUECHANGE 0x800E
#define NT_EVENT_OBJECT_PARENTCHANGE 0x800F
#define NT_EVENT_OBJECT_HELPCHANGE 0x8010
#define NT_EVENT_OBJECT_DEFACTIONCHANGE 0x8011
#define NT_EVENT_OBJECT_VALUECHANGE 0x800E
#define NT_EVENT_OBJECT_PARENTCHANGE 0x800F
#define NT_EVENT_OBJECT_HELPCHANGE 0x8010
#define NT_EVENT_OBJECT_DEFACTIONCHANGE 0x8011
#define NT_EVENT_OBJECT_ACCELERATORCHANGE 0x8012
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct NtMsg;
struct NtPoint;
int32_t GetMessage(struct NtMsg *lpMsg, int64_t hWnd, uint32_t wMsgFilterMin,
uint32_t wMsgFilterMax);
int32_t TranslateMessage(const struct NtMsg *lpMsg);

24
libc/nt/master.sh

@ -1635,7 +1635,7 @@ imp 'FillConsoleOutputAttribute' FillConsoleOutputAttribute KernelBase 354
imp 'FillConsoleOutputCharacter' FillConsoleOutputCharacterW KernelBase 356 5
imp 'FillConsoleOutputCharacterA' FillConsoleOutputCharacterA KernelBase 355 5
imp 'FillPath' FillPath gdi32 1479
imp 'FillRect' FillRect user32 1780
imp 'FillRect' FillRect user32 1780 3
imp 'FillRgn' FillRgn gdi32 1480
imp 'FindActCtxSectionGuid' FindActCtxSectionGuid KernelBase 357
imp 'FindActCtxSectionGuidWorker' FindActCtxSectionGuidWorker kernel32 372
@ -3191,17 +3191,17 @@ imp 'LoadAlterBitmap' LoadAlterBitmap comdlg32 117
imp 'LoadAppInitDlls' LoadAppInitDlls KernelBase 971
imp 'LoadBitmapA' LoadBitmapA user32 2096
imp 'LoadBitmap' LoadBitmapW user32 2097
imp 'LoadCursorA' LoadCursorA user32 2098
imp 'LoadCursorA' LoadCursorA user32 2098 2
imp 'LoadCursorFromFileA' LoadCursorFromFileA user32 2099
imp 'LoadCursorFromFile' LoadCursorFromFileW user32 2100
imp 'LoadCursor' LoadCursorW user32 2101
imp 'LoadCursor' LoadCursorW user32 2101 2
imp 'LoadEnclaveData' LoadEnclaveData KernelBase 972
imp 'LoadEnclaveImageA' LoadEnclaveImageA KernelBase 973
imp 'LoadEnclaveImage' LoadEnclaveImageW KernelBase 974
imp 'LoadIcon' LoadIconW user32 2103 2
imp 'LoadIconA' LoadIconA user32 2102 2
imp 'LoadImageA' LoadImageA user32 2104
imp 'LoadImage' LoadImageW user32 2105
imp 'LoadImageA' LoadImageA user32 2104 6
imp 'LoadImage' LoadImageW user32 2105 6
imp 'LoadKeyboardLayoutA' LoadKeyboardLayoutA user32 2106
imp 'LoadKeyboardLayoutEx' LoadKeyboardLayoutEx user32 2107
imp 'LoadKeyboardLayout' LoadKeyboardLayoutW user32 2108
@ -3996,6 +3996,8 @@ imp 'NtWriteFileGather' NtWriteFileGather ntdll 656
imp 'NtWriteRequestData' NtWriteRequestData ntdll 657
imp 'NtWriteVirtualMemory' NtWriteVirtualMemory ntdll 658 5
imp 'NtYieldExecution' NtYieldExecution ntdll 659 0
imp 'DefWindowProcA' DefWindowProcA user32 173 4
imp 'DefWindowProc' DefWindowProcW user32 174 4
imp 'NtdllDefWindowProc_A' NtdllDefWindowProc_A ntdll 660
imp 'NtdllDefWindowProc_W' NtdllDefWindowProc_W ntdll 661
imp 'NtdllDialogWndProc_A' NtdllDialogWndProc_A ntdll 662
@ -4644,10 +4646,10 @@ imp 'RegisterApplicationRecoveryCallback' RegisterApplicationRecoveryCallback
imp 'RegisterApplicationRestart' RegisterApplicationRestart kernel32 1185
imp 'RegisterBSDRWindow' RegisterBSDRWindow user32 2247
imp 'RegisterBadMemoryNotification' RegisterBadMemoryNotification KernelBase 1384
imp 'RegisterClassA' RegisterClassA user32 2248
imp 'RegisterClassExA' RegisterClassExA user32 2249
imp 'RegisterClassEx' RegisterClassExW user32 2250
imp 'RegisterClass' RegisterClassW user32 2251
imp 'RegisterClassA' RegisterClassA user32 2248 1
imp 'RegisterClassExA' RegisterClassExA user32 2249 1
imp 'RegisterClassEx' RegisterClassExW user32 2250 1
imp 'RegisterClass' RegisterClassW user32 2251 1
imp 'RegisterClipboardFormatA' RegisterClipboardFormatA user32 2252
imp 'RegisterClipboardFormat' RegisterClipboardFormatW user32 2253
imp 'RegisterConsoleIME' RegisterConsoleIME kernel32 1187
@ -6482,9 +6484,9 @@ imp 'ShipAssert' ShipAssert ntdll 1612
imp 'ShipAssertGetBufferInfo' ShipAssertGetBufferInfo ntdll 1613
imp 'ShipAssertMsgA' ShipAssertMsgA ntdll 1614
imp 'ShipAssertMsg' ShipAssertMsgW ntdll 1615
imp 'ShowCaret' ShowCaret user32 2411
imp 'ShowCaret' ShowCaret user32 2411 1
imp 'ShowConsoleCursor' ShowConsoleCursor kernel32 1409
imp 'ShowCursor' ShowCursor user32 2412
imp 'ShowCursor' ShowCursor user32 2412 1
imp 'ShowOwnedPopups' ShowOwnedPopups user32 2413
imp 'ShowScrollBar' ShowScrollBar user32 2414
imp 'ShowStartGlass' ShowStartGlass user32 2415

41
libc/nt/paint.h

@ -1,5 +1,8 @@
#ifndef COSMOPOLITAN_LIBC_NT_PAINT_H_
#define COSMOPOLITAN_LIBC_NT_PAINT_H_
#include "libc/nt/struct/drawtextparams.h"
#include "libc/nt/struct/paintstruct.h"
#include "libc/nt/struct/rect.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#if 0
@ -8,50 +11,22 @@ COSMOPOLITAN_C_START_
*/
#endif
struct NtSize {
int32_t cx;
int32_t cy;
};