ddablib / envvars

Environment Variables Unit
1 stars 2 forks source link

Potential problem with ANSI environment blocks & `TPJEnvironmentVars.GetAll` #23

Closed delphidabbler closed 2 years ago

delphidabbler commented 2 years ago

Unicode environment blocks are distinguished when calling CreateProcess by passing the CREATE_UNICODE_ENVIRONMENT flag.

This raises the question of whether we can rely upon a process' environment block being Unicode? All processes that I've seen launched from modern Windows have Unicode environment blocks, but what about child processes explicitly launched with ANSI environment blocks? Does Windows convert them to Unicode before the process is started?

This is very important to know because the TPJEnvironmentVars.GetAll method assumes that its host process has a Unicode environment block and will fail if the block is ANSI. Therefore TPJEnvironmentVars.GetAll will fail on any process that has an ANSI environment block. That would be a major bug.

Given that Windows knows an environment block is Unicode because of the CREATE_UNICODE_ENVIRONMENT flag, is there a way testing for that flag? Note that this is only important if Windows doesn't convert ANSI environment blocks to Unicode.

Tests are required.

Originally posted by @delphidabbler in https://github.com/ddablib/envvars/issues/12#issuecomment-1236528957

delphidabbler commented 2 years ago

There are two contrary pieces of evidence:

1

It would appear that a process maybe can have an ANSI environment block. This is implied in the CreateProcess documentation where, in the section on the lpEnvironment parameter it says:

If this parameter is NULL and the environment block of the parent process contains Unicode characters, you must also ensure that dwCreationFlags includes CREATE_UNICODE_ENVIRONMENT.

2

Contrary to this the documentation for GetEnvironmentStringsW implies, but is not explicit, that the function fetches a Unicode environment block.

The implication comes from the following note about the ANSI version of the function, GetEnvironmentStringsA:

Note that the ANSI version of this function, GetEnvironmentStringsA, returns OEM characters.

That could be read to imply that GetEnvironmentStringsW behaves in the opposite manner. In fact it makes sense that the function always returns a block in the same format, because it doesn't provide any way to distinguish between different formats.

All the above was extracted from comments to issue #12.

delphidabbler commented 2 years ago

Given that GetEnvironmentStringsW was mentioned in the above comment it is worth checking that, on all supported compilers, Delphi is setting GetEnvironmentStrings to GetEnvironmentStringsW.

Alternatively we could refer to GetEnvironmentStringsW explicitly.

delphidabbler commented 2 years ago

I've just tested passing both a Unicode and ANSI environment block to a child process.

In both cases TPJEnvironmentVars.GetAll works correctly, and checks show the process environment block is in Unicode format.

So, no problems!

Closing this issue now.