For the record, the proper way to call DoEnvironmentSubstA is like this:DEFLNG A-Z
DECLARE DYNAMIC LIBRARY "Shell32"
FUNCTION EnvironmentVariable& ALIAS DoEnvironmentSubstA (pszSrc$, BYVAL cchSrc AS _UNSIGNED LONG)
END DECLARE
PRINT EnvVariable("%os%")
FUNCTION EnvVariable$ (template$)
DIM size AS _UNSIGNED LONG
size = 256
IF LEN(template$) > size THEN size = LEN(template$)
DO
buf$ = SPACE$(size)
LSET buf$ = template$ + CHR$(0)
result = EnvironmentVariable(buf$, size)
size = size * 2
LOOP UNTIL _SHR(result, 16)
EnvVariable$ = LEFT$(buf$, (result AND &HFFFF&) - 1)
END FUNCTION
and even then I should really be making sure `size` doesn't overflow.
ENVIRON$ is obviously the better way to do this, but note that DoEnvironmentSubstA is deprecated in favour of ExpandEnvironmentStringsA anyway. Thankfully the latter has a far more sensible calling convention, with separate input and output buffers.
EDIT And here's an example of calling the much more sensible ExpandEnvironmentStringsA:DEFLNG A-Z
DECLARE DYNAMIC LIBRARY "Kernel32"
FUNCTION EnvironmentVariable& ALIAS ExpandEnvironmentStringsA (src$, dest$, BYVAL size AS _UNSIGNED LONG)
END DECLARE
PRINT EnvVariable("%os%")
FUNCTION EnvVariable$ (template$)
templatez$ = template$ + CHR$(0)
size = 256
buf$ = SPACE$(size)
result = EnvironmentVariable(templatez$, buf$, size)
IF result = 0 THEN ERROR 5
IF result > size THEN
size = result
buf$ = SPACE$(size)
result = EnvironmentVariable(templatez$, buf$, size)
END IF
IF result = 0 OR result > size THEN ERROR 5
EnvVariable$ = LEFT$(buf$, result - 1)
END FUNCTION