Hacker News new | past | comments | ask | show | jobs | submit login

> the kernel is creating a new window on behalf of a process

> The kernel forces applications to connect to the ctfmon service when they start

> the kernel invokes a callback

> the kernel still forces AppContainer processes to join the ctf session

I know next-to-nothing about Windows's architecture, but why does the kernel do all of these things? Seems like something a more purpose-built process should do?

(Aside: my browser does not allow for loading Consolas, and the code snippets don't have a fallback to monospace so they render in a serif font. It'd be nice if they didn't do this.)




To understand this, you need to go back to the original release of Windows NT 3.1 in 1993.

Most of the GUI was implemented in user mode. But again, this is 1993, and NT's most popular platform is the x86.

Windows NT 3.5 was code-named "Daytona," and the primary goal of that release was to improve performance.

One way that was achieved was to take the window manager and graphics subsystem, combine them into a device driver (win32k.sys), and run them in kernel mode.

It's not precisely accurate to say that "the kernel" does all of these things, but rather the device driver that contains the window manager performs those operations from within kernel mode.

Over time, Microsoft has been gradually moving some components back into user mode for security and stability reasons, however win32k.sys continues to exist and is frequently the culprit when it comes to Windows security vulnerabilities.


It's called Windows for a reason ;)

Even in Windows 10, the Windows kernel does a LOT of stuff that's GUI centric. Indeed the entire Windows API is totally GUI centric. The fundamental IPC primitive is window messages, which is a microkernel-esque very fast inter-thread/process context switch tool. Like in seL4 or similar you get to send two numbers this way and not more, and it's optimised heavily. Other IPC systems you'd expect to be GUI independent like DCOM end up using this under the hood.

It used to be that the entire GUI subsystem ran in kernel mode, because context switching was very slow and it made a big difference. In Vista+ large parts of it moved out into a separate privileged process, but the kernel is still involved in IPC, I believe. So when Tavis says "the kernel is creating a new window on behalf of the process" that's not quite correct, I think. Various subsystems get involved in creating windows and mostly not running in kernel mode anymore.


> The fundamental IPC primitive is window messages

That is not remotely true. Windows GUI messages are implemented as part of the win32k.sys device driver via traditional IPC and synchronization mechanisms.

> Other IPC systems you'd expect to be GUI independent like DCOM end up using this under the hood.

That's not entirely accurate either. Yes, DCOM on GUI threads use Windows messaging for IPC for compatibility reasons that go back to OLE on 16-bit Windows.

But the multithreaded apartment (ie, COM for a modern OS) is completely independent from the GUI; it is layered atop Microsoft RPC, which itself uses the NT kernel's ALPC mechanism for IPC.

If you're not creating and working with COM objects on a GUI thread, then you should not be using old-style single-threaded apartment COM. Yes, even if your program is only single threaded, you should still be initializing COM to use the multithreaded apartment.


Yes, I know how COM works. I was a Windows programmer in the past and understand its architecture just fine. You aren't really correct. DCOM doesn't use window messages only on "GUI threads". If you use it in the default way and initialise it as a STA it will create an invisible window for you and even pump the windows message loop for you during an RPC. This will happen even if you didn't create a GUI until that point. The use of window messages is in effect an implementation detail you can't ignore.

Moreover this is the default mode. The CoInitialize API puts you in a STA by default. To get the GUIless MTA you must use the replacement CoInitializeEx API. Obviously COM programmers know this and it's not a big deal, but I don't understand this resistance to accepting that an OS literally called Windows might make windows and window messages an important part of the API.

And I did that window messages run in the kernel, which you accept - even in latest versions the (mandatory) win32k.sys driver implements the message syscalls. I'm not sure how you know what the implementation looks like, but I'm pretty sure it used to be well optimised. It'd be odd if it no longer was.

Now I haven't claimed every IPC primitive in Windows is GUI based, have I? But fundamental features use it, including features like RPC that you wouldn't imagine do so, and that supports my point that it's called Windows for a reason. The GUI aspects historically integrate deeply into everything. As yet one more example, if the dynamic linker encounters a problem during program startup, you get a GUI message box telling you so, even if the program was started from a console.


> The fundamental IPC primitive is window messages, which is a microkernel-esque very fast inter-thread/process context switch tool.

A fun way to think about Windows, is that it's what Erlang would be if the kernel expected to be able to store GUI state in the process dictionary, such that every actor-process can potentially play a secondary role as a GUI element; and every GUI element is necessarily a first-class actor-process. (These actor-processes being a tree originally rooted in one actor-process holding the kernel state for an OS process—that is, until COM multi-threaded apartments came along and wrecked the abstraction.)


> Indeed the entire Windows API is totally GUI centric.

I think this is fundamentally incorrect. Windows certainly allows processes and threads to exist with no GUI. The process doesn't need to have message loop, etc.

I suggest you check your other facts as well. Windows Internals is a good book to start.


It may be different these days but it used to be the case that all kinds of things would start or require a GUI message loop behind the scenes. Most notoriously, COM STAs did, and all kinds of APIs would enter a COM "apartment" for you as part of their internal operation.

Also just look at the definition of the PEB and TEB. There's plenty of slots for GUI stuff that's just left empty for headless apps, but the space is still allocated. In the end Windows is GUI first with non GUI apps a second class citizen.

https://en.m.wikipedia.org/wiki/Win32_Thread_Information_Blo...

As you can see the primary OS per thread structure has fields like "GDI pen" and "GDI brush". There's no separation of GUI specific stuff from other kinds of apps. Even the EXE file format distinguishes between "an app that will open a window to run in the background" and "a command line app". There's no notion of a program that could be used as both a GUI or a command line app depending on how it's run.


> Most notoriously, COM STAs did, and all kinds of APIs would enter a COM "apartment" for you as part of their internal operation.

You make that sound like that was some kind of accidental leaky abstraction, when in fact it was by design. COM STAs were designed to work with GUI threads, full stop. If you aren't a GUI thread, you shouldn't be initializing yourself with STA COM.

> Also just look at the definition of the PEB and TEB. There's plenty of slots for GUI stuff that's just left empty for headless apps, but the space is still allocated.

I am perfectly fine with that, as it essentially removes thread-local GUI data from the application's TLS namespace. So a few extra pointers exist in the PEB and TEB, big deal.

> In the end Windows is GUI first with non GUI apps a second class citizen.

I don't really see how you can conclude that from STA COM and a couple of TLS slots reserved for the GUI.


You are technically correct about processes not absolutely needing to use graphical resources.

But the whole thing is nevertheless backed in and coupled with low layers, including the kernel. There is just a kind of lazy init of GDI resources and the like so that the init is skipped for those processes which don't use them ever. It is fundamentally different from a general purpose OS like Linux which does not care that much (or even at all? I haven't checked) about graphic shits for processes.


Your assessment is wildly inaccurate. Windows NT is a general purpose OS like Linux and the lower layers really don't know or care about the GUI.

The Windows NT kernel has been carefully designed like that from the start. In fact, the Windows part of NT is called a Windows subsystem. Windows kernel DOES NOT do windowing. The Executive, Kernel, Device drivers and the HAL are cleanly separated.

In fact, Microsoft provides Windows Nano Server which is a totally headless installation with no GUI components.


You are talking about mostly source code organization. Which every sane project does.

So of course it is unlikely there is something that e.g. draws pixels in the scheduler.

But for example there is still some space reserved in the TEB for GDI things. And kernel space code for graphic purposes related to processes and threads -- a kind of graphic "kernel" if you want. I mean: you just cannot take Windows and change all the low level graphics support code to a kind of WinWayland or WinAndroid. Even just programming raw NT processes is not officially supported IIUC, so you are bound to using e.g. Win32, and there definitively are some pieces of code all over Win32 (and not just in trivially graphic related APIs) which is aware of the existence of graphics related features on the OS.

So while it might be possible to recompile and/or rewrite parts of NT if you work at Microsoft to actually obtain a graphic agnostic OS (which is not even exactly what Nano Server is despite the re-engineering effort, because it is explicitly graphicless, not just graphic agnostic, and actually it now does not even exist anymore in a standalone form but only for containers, so you stick with your regular host kernel), that's not what I had in mind.


https://scorpiosoftware.net/2019/02/17/windows-10-desktops-v...

It depends what level of the OS you’re talking about, but the clean separation is not so clear.


Yeah, the Linux kernel has no idea what a window is. Someone even made a module adding windows to the kernel to fix that "flaw".


Neither does the Windows kernel.


Sure it does - CreateWindowEx, for example, is a kernel function implemented by win32k.sys. See: https://blogs.msdn.microsoft.com/dsui_team/2012/11/05/troubl...


In the Windows operating system there are multiple components running in kernel-space. One of them is the Kernel.

CreateWindowEx does not run in the Kernel, yet it has parts that run in kernel space.


It's all linked as a single module. Just because they call one subcomponent of that "the kernel", doesn't mean the whole thing isn't the OS kernel, as the general definition means.

Linux also implements most features as separate modules that are linked together, that doesn't mean they aren't all part of the kernel.




Applications are open for YC Winter 2020

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: