I am attempting to write two functions that add and remove a folder from a IShellLibrary
. I started with this, but the function produces an exception in System._IntfClear
:
First chance exception at $000007FEFE 168BC4. Exception class $C0000005 with Message 'c0000005 ACCESS_VIOLATION'.
The SHAddFolderPathToLibrary
is the line that causes the exception.
I guess I need to add the library name to the function?
function AddFolderToLibrary(AFolder: string): HRESULT;
{ Add AFolder to Windows 7 library. }
var
plib: IShellLibrary;
begin
Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER,
IID_IShellLibrary, plib);
if SUCCEEDED(Result) then
begin
Result := SHAddFolderPathToLibrary(plib, PWideChar(AFolder));
end;
end;
function RemoveFolderFromLibrary(AFolder: string): HRESULT;
{ Remove AFolder from Windows 7 library. }
var
plib: IShellLibrary;
begin
Result := CoCreateInstance(CLSID_ShellLibrary, nil, CLSCTX_INPROC_SERVER,
IID_IShellLibrary, plib);
if SUCCEEDED(Result) then
begin
Result := SHRemoveFolderPathFromLibrary(plib, PWideChar(AFolder));
end;
end;
The problem here is that the Embarcadero engineer who translated
SHAddFolderPathToLibrary
does not understand COM reference counting, and how it is handled by different compilers.Here's how
SHAddFolderPathToLibrary
is implemented in the C++ header fileShobjidl.h
. It's actually an inline wrapper of other core API calls:And the Delphi translation is very faithful, indeed too faithful:
The problem is the call to
_Release
. The Delphi compiler manages reference counting, and so this explicit call to_Release
is bogus and should not be there. Since the compiler will arrange for a call to_Release
, this extra one simply unbalances the reference counting. The reason why_AddRef
and_Release
are prefixed with_
is to remind people not to call them and to let the compiler do that.The call to
Release
in the C++ version is accurate because C++ compilers don't automatically callRelease
for you unless you wrap the interface in a COM smart pointer. But the Embarcadero engineer has blindly copied it across and you are left with the consequences. Clearly this code has never even been executed by the Embarcadero engineers.You'll need to supply your own corrected implementation of this function. And also any other erroneously translated function. Search for
_Release
in theShlObj
unit, and remove them in your corrected versions. There are other bugs in the translation, so watch out. For example,SHLoadLibraryFromItem
(and others) declare local variableplib: ^IShellLibrary
which should beplib: IShellLibrary
.I submitted a QC report: QC#117351.