Re: Q: Cannot control vista api "SHGetKnownFolderPath" using shell32.dll in Delphi 7 on Windows XP.



On Feb 21, 3:42 pm, Rob Kennedy <m...@xxxxxxxxxxx> wrote:
news2.homelinux.org 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.

type
TSHGetKnownFolderPath = function(FOLDERID_LocalAppDataLow: TGUID;
dwFlags: DWord; hToken: THandle; ppSzPath: pAnsiChar ) : HResult;
StdCall;

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
parameter?

type
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.

var
...

m_SHGetKnownFolderPath: TSHGetKnownFolderPath;
m_pDllData: Pointer;
m_DllDataSize: Integer;
m_pMemoryModule: PBTMemoryModule;
m_hDll: Cardinal;

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_"
sometimes.



function BT_SHGetKnownFolderPath_File : BOOL;
begin
m_hDll := LoadLibrary( 'shell32.dll' );
...
@m_SHGetKnownFolderPath := GetProcAddress( m_hDll,
'SHGetKnownFolderPath' );
...
end;

function Vista_GetEnvironment : String;
var
// szPath: pAnsiChar;
szPath: array[0..MAX_PATH] of Char;
ret: HResult;
begin
BT_SHGetKnownFolderPath_File;

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,
szPath );
...
if( m_hDll <> 0 ) then
begin
FreeLibrary( m_hDll );
end;

Make sure to set m_hDll back to zero again.

end;

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;
var
Shell: HModule;
Fn: TShGetKnownFolderPath;
begin
Shell := LoadLibrary('shell32.dll');
Win32Check(Shell <> 0);
try
@Fn := GetProcAddress(Shell, 'SHGetKnownFolderPath');
Win32Check(Assigned(Fn));
Result := Fn(rfid, dwFlags, hToken, ppszPath);
finally
FreeLibrary(Shell);
end;
end;

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:
THandle): WideString;
var
buffer: PWideChar;
ret: HResult;
begin
ret :=ShGetKnownFolderPath(rfid, dwFlags, hToken, buffer);
OleCheck(ret);
try
Result := buffer;
finally
CoTaskMemFree(buffer);
end;
end;

--
Rob

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
fault) exactly.

and, i've know "Out parameter" newly today.

thanks again.

Best Regards,
godmode2k

.