• Welcome to Theos PowerBasic Museum 2017.

News:

Attachments are only available to registered users.
Please register using your full, real name.

Main Menu

SHGetFolderPathW Issue

Started by Michael S. Thomason, April 12, 2010, 09:02:37 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Michael S. Thomason

Has anyone tried out the SHGetFolderPathw function. I am getting it to return %S_OK but the string returned does not contain the value it's set to the same value as the string was initialized to. It's almost like the function cannot return back the value.

ShGetFolderPathA works fine but W does not. Here is the code I am using:


#COMPILE EXE
#DIM ALL

DECLARE FUNCTION SHGetFolderPathW LIB "SHELL32.DLL" ALIAS "SHGetFolderPathW" ( _
BYVAL hwnd AS DWORD _ ' __in HWND hwnd
, BYVAL csidl AS LONG _ ' __in int csidl
, BYVAL hToken AS DWORD _ ' __in HANDLE hToken
, BYVAL dwFlags AS DWORD _ ' __in DWORD dwFlags
, BYREF pszPath AS DWORD _ ' __out LPWSTR pszPath
) AS LONG ' HRESULT
%CSIDL_APPDATA = &H001a&
%NULL=0

FUNCTION PBMAIN () AS LONG

DIM strpath AS STRING
strpath=string$(300,0) 'INIT STRING
SHGetFolderPathw(%null, %CSIDL_APPDATA,%NULL, 0,STRPTR(strpath))
END FUNCTION


The function will return %S_OK but the strpath will always be filled with NULL values.

José Roca

In the unicode version, the pszPath parameter returns a pointer to a null terminated unicode string.

Therefore, you must use:


LOCAL pszPath AS DWORD
LOCAL hr AS LONG
hr = SHGetFolderPathw(%null, %CSIDL_APPDATA,%NULL, 0, pszPath)


And then, to retrieve the string and convert it to ansi:


IF hr = %S_OK THEN
   LOCAL ln AS LONG
   LOCAL strPath AS STRING
   ln = lstrlenW(BYVAL pszPath)
   IF ln THEN strPath = ACODE$(PEEK$(pszPath, ln * 2))
   CoTaskMemFree pszPath
   MSGBOX strPath
END IF


José Roca

Well, I have done some research and, in this case, you're right. It is a litle unusual for a shell function to ask for a pre-allocated buffer of a given length, because if you pass a pointer to a buffer too short then a buffer overrun will happen.

No wonder it has been deprecated in Windows Vista/Windows 7, where it is simply a wrapper for SHGetKnownFolderPath. This new function behaves like other shell functions and returns a pointer to a null terminated unicode string allocated by the called function that you must free with CoTaskMemFree.

So you must change the BYREF pszPath AS DWORD to BYVAL pszPath AS DWORD, and strpath=string$(300,0) to strpath=string$(%MAX_PATH * 2,0).

Theo Gottwald

I tried this function and whatever you do, you can not get the path for x664 programs from a 32 bit Application under Win 7/x64.
You'll always get "... programs (x64)".
Does anybody know a workaround?

Florent Heyworth

Hi Theo

the behavior of the SHGetFolderPath function on X64 when called by 32-bit programs is as designed - WOW64 is an emulation layer which simulates a 32-bit environment.. There is a workaround:

WOW64 sets the ProgramW6432 environment variable of to point to the X64 folder - have a look at http://msdn.microsoft.com/en-us/library/aa384274%28VS.85%29.aspx for details.

Cheers, Florent

Theo Gottwald

Thanks Florent, thats a good idea:

QuoteProgramW6432 environment variable of to point to the X64 folder -

I'll use this one.