But I don't think this actually makes a lot of sense either. Windows SDK 10.0.17763.0 drags in windef.h -> minwindef.h -> winnt.h -> ctype.h -> corecrt.h, and also winnt.h -> guiddef.h -> string.h. By the end you're only avoiding __threadid(), __threadhandle(), offsetof(), and (for c++) std::nullptr_t, the rest of corecrt.h gets pulled in
eventually anyway.
Oh, good catch, I didn't notice that. Then maybe we could could move existing NULL define after #include <winnt.h> and guard with #ifndef NULL (instead of #undefing)?
`winecpp -fdirectives-only` is a nice way to look at how all the inclusion plays out
That would leave NULL undefined for the first portion of <winnt.h> (and thus during <basetsd.h, guiddef.h, winapifamily.h). It doesn't look like that would actually break anything currently, (I see no inlines or anything in those headers that use NULL) but differs from the Windows SDK and feels weird.
My thought was that, since the extra symbols will eventually get defined anyway, that even less risk if the libc doesn’t do __need_* and we get them early, so we can just use <stddef.h> right away (thus clearly and portably follow ODR). Even if __need_* doesn’t work as intended, we just get things early that we were eventually going to get anyway.