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

.



Relevant Pages

  • Re: Q: Cannot control vista api "SHGetKnownFolderPath" using shell32.dll in Delphi 7 on Windows XP.
    ... Okay, i think function pointer works good, but i don't know exactly ... Misdeclaring that last parameter is probably what's causing the access violation. ... function ShGetKnownFolderPath(const rfid: TGUID; dwFlags: DWord; hToken: ... Now the rest of your program can simply call ShGetKnownFolderPath, just as though it were a normal API function. ...
    (alt.comp.lang.borland-delphi)
  • Re: [PATCH 1/2] srcu-3: RCU variant permitting read-side blocking
    ... pass a pointer is easily fixed; this problem is not so easy. ... per-CPU variables, ... least-common-multiple API that would apply to both sorts of variables. ... initialization difficulties for the static case. ...
    (Linux-Kernel)
  • Re: Conceptual, Logical, and Physical views of data
    ... >>> In that case, the API I use could have what I want, even if behind the ... >> a customer API or some such between me and the database. ... > just as you can use a foreign key to "go to" another source of data. ... > which we can gen the html, then the URL would not be a pointer, right? ...
    (comp.databases.theory)
  • Re: Using the Exchange Backup API
    ... Given that, Viraj, it seems to me that the function you are calling ... pointer, or maybe the computer name parameter is not allowed to be NULL? ... >> Given that you're getting an access violation exception, it makes me suspect that your pointer is ... You say that the GetProcAddress returned with a valid pointer, ...
    (microsoft.public.vc.mfc)
  • Re: Error in initializing ICaptureGraphBuilder2
    ... Access violation writing location 0xcdcdcdcd. ... You need to look at the stack trace. ... doesn't mean that the access violation occurs right at that statement. ... When the parameter for a function is a pointer to a pointer, ...
    (microsoft.public.win32.programmer.directx.video)