microsoft / winfile

Original Windows File Manager (winfile) with enhancements
MIT License
6.75k stars 698 forks source link

XP build based on v141_xp #421

Closed malxau-msft closed 4 months ago

malxau-msft commented 4 months ago

Background

Ever since this code was released, one of the most common things people do is backport to older systems. There's been a few unofficial forks to do this, and one official branch in this repo. What appears to happen each time though is people start from master then backport, as opposed to starting with an older build system then applying current changes. Given that this seems to be a trend, it makes sense to just merge the changes needed for older systems into master so these backports are either unneeded or are substantially simpler.

The changes here target v141_xp; going older than XP with a Microsoft compiler would require Visual Studio 2008 or earlier and I think would require much more dramatic build system changes. If the goal is just XP, the there's not much point using an older compiler than v141_xp.

Substantive changes to do this

  1. Build system support. Craig had earlier expressed concern about not wanting to support two build systems for legacy support. This is one thing that msbuild does fairly well though - because each configuration specifies its own compiler, it's easy enough to have one configuration that targets XP where others do not, so build system changes are minimal.
  2. RegGetValue doesn't exist on XP and there had been a hand-coded replacement in wfdirrd.c. This change expands that to be more compliant with the API - to enforce registry types via flags, and to guarantee to NULL terminate strings - then switches code over to use the replacement.
  3. Previously multi language support worked by having a table of strings, and at runtime converting those into an LCID. XP doesn't have this conversion function, so the table of strings becomes a table of string with LCID. This change continues to call the API to do the conversion if it exists, although that part now seems redundant. Strings are still needed for the .ini file. Note that XP needs an LCID to find the language name, since it also doesn't have GetLocaleInfoEx.
  4. Only disable WOW64 redirection if support to do so exists.
  5. Symbolic link support is currently failed if it does not exist. I'd like to go further and disable the menu items when support is not present, but this change does not go that far.
  6. Add various defines that don't exist in the Windows 7.1 SDK which is used implicitly by the v141_xp target.

Consequences

In theory, the XP binary should be fully functional on newer systems. It probably won't be the released binary though, because I don't think it'll be possible to officially build and sign it given the tooling is no longer current.

There is one warning in the XP build that I can't see how to eliminate, saying the long path manifest entry is not recognized by the older toolchain. It still seems correct to keep though, so the warning should be benign. Note this warning does not exist for the regular build, only when targeting XP specifically.

This may introduce some pain for developers to test with v141_xp; it won't matter too much if this support regresses periodically, since it still solves the problem of reducing the work needed for people adding this support themselves.

It also seems to be the final nail in the coffin for the retro branch. I'll start an issue for discussion on that, but this PR seems to support XP better than retro does and should be easier to support going forward. 

schinagl commented 4 months ago

Three suggestions

schinagl commented 4 months ago

@wesinator should be mentioned as the one who initially created a working branch with v141_xp

https://github.com/wesinator/winfile_xp

Good that you integrate this now into main.

wesinator commented 4 months ago

Thanks for the shoutout

@malxau-msft just out of curiousity, was this inspired by my new fork, or coincidental? (My build works completely on Win10, and XP without powershell or locale support.)

A few comments/questions:

schinagl commented 4 months ago

XPSP2 is most likely rarely used in the wild. I remember when SP3 came out that days, everyone was eager to update.

If one wants to go that old she could use

https://www.schinagl.priv.at/nt/winfile/winfile_xp.zip

Which I some time ago created based on malxaus w2k build. See https://github.com/schinagl/winfile and the wxp_hardlink_junctions branch. It compiles with vs2005

malxau-msft commented 4 months ago

Thanks @schinagl for calling out @wesinator ; apologies for forgetting this in the original post.

was this inspired by my new fork, or coincidental?

I saw your fork and it's fair to say it inspired things. Note though we've been building up to this for a while:

works completely on Win10, and XP without powershell or locale support

Right, I've done these backports before a couple times, in each case sacrificing things. This time was to see if it's possible to sacrifice nothing. I verified powershell and locale support. Symbolic links don't work because XP doesn't have them. wfgoto should work (but I didn't check.) As you pointed out earlier, XP has Security support too, so in many ways it's more functional than later versions.

long path aware is explained at...

Yeah, I understand it. Originally manifests were just opaque text added to an executable, so it's possible to use Visual C++ 2 to generate an XP-manifested UI. The problem with that is the only validation exists when a binary is launched. It makes sense that tools try to be helpful now, but in cases like this it's just ... not helpful. The resulting binary contains the Win10 manifest, so it should be fully functional on any system that interprets it.

Does the VC universal runtime for XP work under XP SP2 (esp. if statically linked)?

I'm sure the answer is that it's not officially supported.

From experimentation, the redist doesn't install because it requires a newer version of Windows Installer; the statically linked one worked fine.

That said, I agree with shinagl that XP SP 2 seems like an odd choice - I'm not sure why somebody would prefer it over SP 3.

I could see a build on VS2010 to support back to XPSP2

That's a much larger change. It implies C89 variable declaration and it can't compile the C++ in wfgoto.cpp today. Some people have attempted to backport wfgoto to work on it though. To me the main advantage of VS2010 is it's possible to compile Winfile on XP.

But it quickly becomes "pulling on a string" - why stop at XPSP2? Why not SP1? Why not 2000? This starts to get into a "consensus" issue about how many language facilities people are willing to give up in order to support those older systems. The reason v141_xp seems interesting is it doesn't require giving anything up.

aggregate all Win32 output dirs beneath one common anchor like Win32 or x86

Agree this would be good to do, and the current behavior is unfortunate legacy inherited from an era where projects only targeted one architecture. Note there are changes outside of this repo (in the build pipelines) to do it, but looking now, they don't seem that bad.

introduce a {Release|Debug}Static. it would be good to use a statically linked build as the default for XP

My personal projects use a statically linked minimal CRT just to ensure everything works everywhere with no headaches, so I understand the motivation.

Microsoft's take though is that official binaries that are distributed with a statically linked CRT need to be updated along with CRT updates, and the CRT seems to be updated more than Winfile, so this seems burdensome. I doubt WinPE users will really be happy with a new compile-time configuration; it would be simple enough to change the existing configuration when compiling from source, what they really want is binaries.

For something like XP, where official binaries can't be distributed, and the CRT isn't being updated, I agree it makes sense.

Name the xp config {Release|Debug}XP instead of XP{Release|Debug}.

I don't use the IDE so don't really understand, but I'm fine with this change.

schinagl commented 4 months ago

Long path support: The manifest is just a resource in a certain format, which is respected by the loader. You could 'steal' it with eg 'resource thief'.

Anyhow long path support will not work on xp because functions do not support long path with xp unless prepended with the \?\ and being xyzW calls. So ignoring the warning during compilation is fine.

Symbolic links: just ignore it with XP, even I have a driver on my site, written by a Japanese guy, which is able to create symlinks with xp. But we don't want to go that far 😉.

Static version Yes WinPe users just want the binaries. But it would be good to have a ready made config in the .vcxproj and not have this config run through the MS pipeline. Just to be there so that everybody can compile it. Changing settings to achieve a static version is for that kind of user probably too challenging. And since you have introduced .props it is only a few lines in .vcxproj away.

clzls commented 4 months ago

XPSP2 is most likely rarely used in the wild. I remember when SP3 came out that days, everyone was eager to update.

Agree. I've done some quick searches in China, which has over 1.2% users still using XP in 2024. Almost all recent tutorials and software sites suggest upgrading to XP SP3.