Hi,
I am writing a COM property handler shell extension for Windows. I am
rather confused about the creation, ownership scope and destruction of
(wide) strings that are referenced and passed between callee (my
handler) and caller (Windows Explorer) in TPropVariant structures.
My code is shown below.
TMyPropertyStore = class(TComObject, IPropertyStore, IInitializeWithStream)
private
fProperty: TPROPVARIANT;
public
function IInitializeWithStream_Initialize(const pIStream: IStream;
grfMode: DWORD): HRESULT; stdcall;
function IPropertyStore_GetValue(var aPropKey: TPropertyKey; out
aPropVar: TPropVariant): HRESULT; stdcall;
end;
TMyparser
procedure LoadFromStream(pIStream: IStream);
property SomeThing: widestring;
end;
function IInitializeWithStream_Initialize(..)
begin
parser := TMyParser.Create;
try
parser.LoadFromStream(piStream);
fProperty.vt := VT_BSTR;
fProperty.bstrVal := SysAllocString(PWideChar(parser.Something));
finally
parser.Free;
end;
end;
function IPropertyStore_GetValue(..)
begin
aPropVar := fProperty;
end;
In IInitializeWithStream_Initialize I am using SysAllocString() because
a straight PWideChar() cast seems to fail when the parser goes out of
scope. Perhaps because PWideChar() does not create a reference count
lock on the respective widestring?
In IPropertyStore_GetValue I use an assignment of my local TPropVariant
to the respective "out" argument. I am assuming that this does not
increment or decrement any reference counts on any strings?
I am assuming that the caller of IPropertyStore_GetValue (actually
Windows Explorer) makes its own local copy of the aPropVar.bstrVal and
does not increment or decrement any reference counts on my string, or
attempt to destroy the string?
I am assuming that I do not need to destroy the string created by
SysAllocString() explicitly in my destructor, since I guess it goes away
automatically when my object goes out of scope?
Finally, according to the Windows SDK, I should be using the following
rather than VT_BSTR but for some odd reason that does not seem to work
at all..
fProperty.vt := VT_LPWSTR;
fProperty.pwszVal := SysAllocString(PWideChar(parser.Something));
Also I wonder if I need to do anything explicit against the risk (is
there one?) that my object may be called simultaneously on several
threads...
Any advice would be much welcome.
Regards
AndrewFG