In short: I was looking for MSDN and was thinking of creating my own SetValue , but I cannot find the source code for it. It is not in the DLL, it is like InitPropVariantFromString , it is in the header file, but I can not find it. :( If you can just show me the htat C ++ code, I will take it from there :)
The bottom is to show the effort I put on.
This is tiny C ++ code that I am 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 translated this into:
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');
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 recieved it:
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 I needed to write InitPropVariantFromString , which I did:
function InitPropVariantFromString(string , propvarPtr ) { var hr = SHStrDup(string, propvarPtr.contents.pwszVal.address()); if (!checkHRESULT(hr)) {
LITTLE VIEW OF MY SHSTRDUP DISTRIBUTE (not a question, just showing that I worked hard and made it work through inexplicable oddities)
So I needed to do SHStrDup , which I thought would take two arguments of ctypes.jschar.ptr , since this is the first argument of LPCTSTR and the second argument of LPTSTR .
For the first argument, I passed the PCWSTR callback ctypes.jschar.array()('Contoso.Scratch') . Therefore, when I first arg the definition set to ctypes.jschar.ptr will not work if it throws this error: expected type pointer, got ctypes.jschar.array(16).ptr(ctypes.UInt64("0x2855b560"))
So I change in defintion from ctypes.jschar.ptr to ctypes.voidptr_t in defintion, so it worked for this argument but then threw an error in the second argument to propvarPtr.contents.pwszVal.address() :
ctypes.jschar.ptr.ptr(ctypes.UInt64("0x20fdb3b4")) ,
So, I just set both SHStrDup arguments to ctypes.voidptr_t and it worked. I don't know why, but it worked. And also propvarPtr.contents.pwszVal definitely populated because when I console it, it shows: "propvarPtr.contents.pwszVal" CData { contents: "C" } .
So, the final SHStrDup error 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 goes through and I will return to 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 true, so now it tries pps.SetValue , and this is where it goes kaput, and I canβt figure out how to fix it. :(
I searched for MSDN and thought of creating my own SetValue , but I cannot find the source code for it. It is not in the DLL, it is like InitPropVariantFromString , it is in the header file, but I can not find it. :( If you can just show me the htat C ++ code, I will take it from there :)