In summary: I searched MSDN and thought to create my own SetValue
but I can't find any sourcecode for it. It's not in a DLL, its like InitPropVariantFromString
, it's in a header file, but I can't find it. :( If you can please just show me htat C++ code I'll take it from there :)
Bottom stuff is to show the efforts I put on it.
This is the tiny C++ code I'm converting:
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
IPropertyStore *pps;
HRESULT hr = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pps));
if (SUCCEEDED(hr)) {
IPropertyStore_SetValue(pps, PKEY_AppUserModel_ID, L"Contoso.Scratch");
}
}
I have translated this to:
var ppv = ctypes.voidptr_t(0);
var pps = new IID();
var HR_pps = CLSIDFromString('{886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}', pps.address());
if (!checkHRESULT(HR_pps)) { throw new Error('checkHRESULT error'); }
var hr = SHGetPropertyStoreForWindow(hwnd, pps.address(), ppv.address());
if (!checkHRESULT(hr)) { throw new Error('checkHRESULT error'); }
var pszValue = ctypes.jschar.array()('Contoso.Scratch'); // PCWSTR
IPropertyStore_SetValue(pps.address(), PKEY_AppUserModel_ID, pszValue.address());
This IPropertyStore_SetValue
I converted from this C++:
HRESULT IPropertyStore_SetValue(IPropertyStore *pps, REFPROPERTYKEY pkey, PCWSTR pszValue)
{
PROPVARIANT var;
HRESULT hr = InitPropVariantFromString(pszValue, &var);
if (SUCCEEDED(hr)) {
hr = pps->SetValue(pkey, var);
PropVariantClear(&var);
}
return hr;
}
I got it to:
var struct_PROPVARIANT = ctypes.StructType('PROPVARIANT', [
{'fntud': struct_GUID}, // GUID
{'pid': ctypes.unsigned_long}, // DWORD
// comment from loomo on union :: union not supported by js-ctypes https://bugzilla.mozilla.org/show_bug.cgi?id=535378 "You can always typecast pointers, at least as long as you know which type is the biggest"
// so now in my case i know that InitPropVariantFromString is looking to se the pwszVal so forget all the other crap in the union and just leave this one
{'pwszVal': new ctypes.PointerType(ctypes.jschar)} // LPWSTR
]);
var IPropertyStore_SetValue = function(pps /** IPopertyStore pointer **/, pkey /** PROPERTYKEY **/, pszValue /** PCWSTR **/) {
var v = new struct_PROPVARIANT(); // PROPVARIANT
var rez = InitPropVariantFromString(pszValue, v.address());
if (rez) {
console.info('pps.SetValue', pps.SetValue);
pps.SetValue(pkey, v);
} else {
throw new Error('failed InitPropVariantFromString');
}
return true;
}
So this required me to write InitPropVariantFromString
which I did:
function InitPropVariantFromString(string /** PCWSTR **/, propvarPtr /** PROPVARIANT pointer **/) {
var hr = SHStrDup(string, propvarPtr.contents.pwszVal.address());
if (!checkHRESULT(hr)) {
//PropVariantInit(propvarPtr); //can skip this, it just does a memset
}
return true;
}
A SMALL ASIDE ON MY SHSTRDUP DILEMMA (not a question just showing i worked hard and through unexplainable weirdness got it to work)
So this required me to do
SHStrDup
which I thought would take two arguments ofctypes.jschar.ptr
as it is first argument ofLPCTSTR
and second arg ofLPTSTR
.For the first argument, i was passing the PCWSTR of recall
ctypes.jschar.array()('Contoso.Scratch')
. So when I the first arg definition set toctypes.jschar.ptr
it wouldn't work use it throws this error:expected type pointer, got ctypes.jschar.array(16).ptr(ctypes.UInt64("0x2855b560"))
So I change in the defintion from
ctypes.jschar.ptr
toctypes.voidptr_t
in defintion so then it worked for this argument but then threw error on second argument recall thepropvarPtr.contents.pwszVal.address()
:
ctypes.jschar.ptr.ptr(ctypes.UInt64("0x20fdb3b4"))
,So then I just ended up setting both arguments of
SHStrDup
toctypes.voidptr_t
and it worked. Don't know why but it worked. AndpropvarPtr.contents.pwszVal
is definitely getting populated, because when I console.log it it shows:"propvarPtr.contents.pwszVal" CData { contents: "C" }
.So the final
SHStrDup
defintion looked like this:/* http://msdn.microsoft.com/en-us/library/windows/desktop/bb759924%28v=vs.85%29.aspx * HRESULT SHStrDup( * __in_ LPCTSTR pszSource, * __out_ LPTSTR *ppwsz * ); */ var SHStrDup = shlwapi.declare('SHStrDupW', ctypes.winapi_abi, ctypes.long, // HRESULT ctypes.voidptr_t, // LPCTSTR // should be ctypes.jschar.ptr OR ctypes.char.ptr // im trying to pass PCWSTR here, which is `ctypes.jschar.array()('blah blah').address()` ctypes.voidptr_t // LPTSTR // should be ctypes.jschar.ptr OR ctypes.char.ptr // im trying to pass address to struct_PROPVARIANT.pwszVal which is new ctypes.PointerType(ctypes.jschar) );
So now all that is passing and I end up back in IPropertyStore_SetValue
in this if:
var rez = InitPropVariantFromString(pszValue, v.address());
if (rez) {
console.info('pps.SetValue', pps.SetValue);
pps.SetValue(pkey, v);
} else {
throw new Error('failed InitPropVariantFromString');
}
Now rez
is true, so then it now tries pps.SetValue
and this is where it goes kaput and I can't figure out how to fix it. :(
I searched MSDN and thought to create my own SetValue
but I can't find any sourcecode for it. It's not in a DLL, its like InitPropVariantFromString
, it's in a header file, but I can't find it. :( If you can please just show me htat C++ code I'll take it from there :)