A bit of both. The base OS itself provides way more functionality out of the box than Linux (imagine an asterisk here) and that is done through APIs that have remained backwards compatible going back to Windows 95 (of course new stuff got added in later versions). When applications want more they bundle their dependencies with them (either via static or dynamic linking) and sadly that is indeed repeated. However the base OS provides enough functionality that you do not need to, e.g, bundle an entire GUI toolkit that implements everything from scratch (ignoring Qt/Java/etc programs here - they do that for portability but they didn't
have to if they only cared about Windows).
(now the asterisk: in terms of functionality above and taking an average desktop distribution in mind you'd probably find more of it in Linux, but applications can't rely on most of that functionality being available on all distros as a "standard" and even for the stuff they could expect, way more often than not they rely on specific version ranges - e.g. an application cannot rely on "Gtk", it can only rely on "Gtk <version>.xxx", as Gtk itself isn't backwards compatible across major versions).