Author Topic: Issue with string buffer in Shell32 WinAPI  (Read 4197 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Issue with string buffer in Shell32 WinAPI
« on: September 26, 2020, 11:07:10 pm »
I need help from someone on the forum who is used to dealing with WinAPI. I'm trying this code out and it keeps truncating values even though my buffer would definitely be able to hold the path for the variable. The max path in Windows 10 is 260 and no matter what I use, I see truncated strings. This code allows for more than one Environment variable and so this screenshot shows me trying two at the same time:

  [ You are not allowed to view this attachment ]  

And my code:
Code: QB64: [Select]
  1.     FUNCTION EnvironmentVariable& ALIAS DoEnvironmentSubstA (BYVAL pszSrc AS _OFFSET, BYVAL cchSrc AS _UNSIGNED INTEGER)
  2.  
  3. PRINT EnvVariable("%userprofile% %homepath%")
  4.  
  5. FUNCTION EnvVariable$ (variable AS STRING)
  6.     DIM size AS _UNSIGNED INTEGER
  7.     variable = variable + CHR$(0)
  8.     size = 1024
  9.     DIM a AS LONG
  10.     a = EnvironmentVariable(_OFFSET(variable), size)
  11.     EnvVariable = variable

I've tried this code in both 64 and 32 bit QB64. I'm using v1.4 on Windows 10.
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Issue with string buffer in Shell32 WinAPI
« Reply #1 on: September 26, 2020, 11:12:58 pm »
I think I might have just fixed it. I'll keep testing.
Shuwatch!

FellippeHeitor

  • Guest
Re: Issue with string buffer in Shell32 WinAPI
« Reply #2 on: September 26, 2020, 11:13:30 pm »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Issue with string buffer in Shell32 WinAPI
« Reply #3 on: September 26, 2020, 11:22:37 pm »
There's http://www.qb64.org/wiki/ENVIRON$.
@FellippeHeitor
Good grief..... I forgot all about that functionality in QB64..... Question: Does this work with User defined environment variables or ones added by programs?
Dang..... I spent all that time trying to figure out what was wrong and it exists in QB64 already. The only thing different with the WinAPI one is that it allows for multiple variables at the same time.
« Last Edit: September 26, 2020, 11:40:23 pm by SpriggsySpriggs »
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Issue with string buffer in Shell32 WinAPI
« Reply #4 on: September 26, 2020, 11:34:28 pm »
The main thing I see is a speed difference and the ENVIRON$ is not returning the username when I use the USERNAME variable. The WinAPI version does and completes listing the basic list of environment variables twice as fast as the built in ENVIRON$ function. HMMMM..... There are drawbacks to both, I reckon. One allows for multiple variables at once, one doesn't. One is accurate each time I run it, one misses the USERNAME variable (if I run ENVIRON$("USERNAME") own it works just fine.... I don't get it) . One is twice as fast. Oh well. I'll still put it in my API collection zip as a demo, I guess.
« Last Edit: September 26, 2020, 11:36:08 pm by SpriggsySpriggs »
Shuwatch!

FellippeHeitor

  • Guest
Re: Issue with string buffer in Shell32 WinAPI
« Reply #5 on: September 26, 2020, 11:52:45 pm »
ENVIRON$ uses C++'s getenv() internally.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Issue with string buffer in Shell32 WinAPI
« Reply #6 on: September 27, 2020, 12:04:51 am »
ENVIRON$ uses C++'s getenv() internally.
I see. It will just depend on the program whether or not I end up using the one I wrote or the one already there. It wasn't a total loss, I suppose. I learned a bit more about how to do that string buffer properly.
Shuwatch!

Marked as best answer by SpriggsySpriggs on September 26, 2020, 08:30:25 pm

Offline luke

  • Administrator
  • Seasoned Forum Regular
  • Posts: 324
    • View Profile
Re: Issue with string buffer in Shell32 WinAPI
« Reply #7 on: September 27, 2020, 12:05:46 am »
For the record, the proper way to call DoEnvironmentSubstA is like this:
Code: [Select]
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:
Code: [Select]
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
« Last Edit: September 27, 2020, 12:16:11 am by luke »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Issue with string buffer in Shell32 WinAPI
« Reply #8 on: September 27, 2020, 12:30:10 am »
@luke Oh well. I didn't see the newer version of that function out there when I was doing that or else I would have for sure used that one. I don't like using the deprecated ones if I can find the updated versions. When I check the MSDN documentation it says that the pszSrc variable is a pointer to a string, not a string. In your snippet you have it as a string. I guess it doesn't matter since I tested your snippet and it worked. Huh. I always thought it was strict on those things. That's cool that it didn't care.
« Last Edit: September 27, 2020, 12:33:02 am by SpriggsySpriggs »
Shuwatch!