Re: Q: Cannot control vista api "SHGetKnownFolderPath" using shell32.dll in Delphi 7 on Windows XP.
- From: godmode2k@xxxxxxxxx
- Date: 21 Feb 2007 22:21:05 -0800
On Feb 21, 3:42 pm, Rob Kennedy <m...@xxxxxxxxxxx> wrote:
Below code which vista api in shell32.dll as dynamic-loading has
access violation error.
I wanna get user's (shared) folder full path so,
i've coded using vista api "SHGetKnownFolderPath" as a function
pointer by dynamic-load "shell32.dll".
Okay, i think function pointer works good, but i don't know exactly
why write to my array variable(call-by-reference)
at "SHGetKnownFolderPath" in "shell32.dll".
Are you sure you can't just use ShGetFolderPath instead? It's available
on all OS versions, so you won't need special code for Windows Vista.
TSHGetKnownFolderPath = function(FOLDERID_LocalAppDataLow: TGUID;
dwFlags: DWord; hToken: THandle; ppSzPath: pAnsiChar ) : HResult;
The declaration in MSDN has the final parameter as a PWSTR*. That's a
pointer to a pointer to a wide character. InDelphi, that would be a
PPWideChar, or an "out PWideChar." And why that name for the first
TShGetKnownFolderPath = function(const rfid: TGUID; dwFlags: DWord;
hToken: THandle; out ppszPath: PWideChar): HResult; stdcall;
The last parameter is passed by reference because the function allocates
the memory for you. That's why it tells you to free the memory with
CoTaskMemFree. Misdeclaring that last parameter is probably what's
causing the access violation.
By C++ convention, the "m_" prefix denotes a member variable, a field of
a class. It's just confusing to other readers when they're actually
global variables.Delphiconvention uses a prefix of "F" for fields. A
prefix for global variables isn't as widespread, but I see "G" and "g_"
function BT_SHGetKnownFolderPath_File : BOOL;
m_hDll := LoadLibrary( 'shell32.dll' );
@m_SHGetKnownFolderPath := GetProcAddress( m_hDll,
function Vista_GetEnvironment : String;
// szPath: pAnsiChar;
szPath: array[0..MAX_PATH] of Char;
You're ignoring the return value.
// Occurs error below line
// Message: Access Violation at address 75F15324 in module
'shell32.dll'. Write of address 16AFC543.
ret := m_SHGetKnownFolderPath( FOLDERID_LocalAppDataLow, 0, 0,
if( m_hDll <> 0 ) then
FreeLibrary( m_hDll );
Make sure to set m_hDll back to zero again.
Usually, if a function is being loaded dynamically for every call, the
load and the call occur in the same function. It would look like this:
functionShGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken:
THandle; out ppszPath: PWideChar): HResult;
Shell := LoadLibrary('shell32.dll');
Win32Check(Shell <> 0);
@Fn := GetProcAddress(Shell, 'SHGetKnownFolderPath');
Result := Fn(rfid, dwFlags, hToken, ppszPath);
Now the rest of your program can simply callShGetKnownFolderPath, just
as though it were a normal API function. All the loading and linking
takes place local to that function instead of cluttering the environment
with global variables and support functions that need to be called in
just the right order.
You can wrap the API function in aDelphifunction like the following.
It will raise an exception if the API function fails. Otherwise, it will
return a WideString with the path you ask for. This saves you from
having to call CoTaskMemFree later.
function GetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken:
ret :=ShGetKnownFolderPath(rfid, dwFlags, hToken, buffer);
Result := buffer;
I do truly appreciate you.
I've solve it today from your advice.
I'll always be memorize your advice that what is problem(correct my
and, i've know "Out parameter" newly today.
- Prev by Date: Re: Borland C++ 5.02 and WinXP
- Next by Date: Re: Borland C++ 5.02 and WinXP
- Previous by thread: Re: Q: Cannot control vista api "SHGetKnownFolderPath" using shell32.dll in Delphi 7 on Windows XP.
- Next by thread: Re: Q: Cannot control vista api "SHGetKnownFolderPath" using shell32.dll in Delphi 7 on Windows XP.