SetValue and Release are not functions

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'); // 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 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 /** 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; } 

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 :)

0
source share
1 answer

Solved, I had to use VTBL: https://github.com/Noitidart/_scratchpad/blob/master/IPropertyStore%20COM%20jsctypes.js

The definition order in Vtbl is of great importance. So make sure that this is correct if you want to do something with Vtbl s

 var IPropertyStoreVtbl = new ctypes.StructType('IPropertyStoreVtbl'); var IPropertyStore = new ctypes.StructType('IPropertyStore', [{ 'lpVtbl': IPropertyStoreVtbl.ptr }]); this.IPropertyStorePtr = new ctypes.PointerType(IPropertyStore); IPropertyStoreVtbl.define( [{ //start inherit from IUnknown 'QueryInterface': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr, this.REFIID, // riid this.VOIDPTR // **ppvObject ]).ptr }, { 'AddRef': ctypes.FunctionType(ctypes.stdcall_abi, this.ULONG, [ IPropertyStore.ptr ]).ptr }, { 'Release': ctypes.FunctionType(ctypes.stdcall_abi, this.ULONG, [ IPropertyStore.ptr ]).ptr }, { //end inherit from IUnknown //start IPropertyStore 'GetCount': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr, this.DWORD.ptr // *cProps ]).ptr }, { 'GetAt': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr, this.DWORD, // iProp this.PROPERTYKEY.ptr //*pkey ]).ptr }, { 'GetValue': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr, this.REFPROPERTYKEY, // key this.PROPVARIANT.ptr // *pv ]).ptr }, { 'SetValue': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr, this.REFPROPERTYKEY, // key this.REFPROPVARIANT // propvar ]).ptr }, { 'Commit': ctypes.FunctionType(ctypes.stdcall_abi, this.HRESULT, [ IPropertyStore.ptr ]).ptr }] ); 

Then, to get the IPropertyStore window:

 var ppsPtr = new ostypes.IPropertyStorePtr(); var hr_SHGetPropertyStoreForWindow = _dec('SHGetPropertyStoreForWindow')(cHwnd, IID_IPropertyStore.address(), ppsPtr.address()); checkHRESULT(hr_SHGetPropertyStoreForWindow, 'SHGetPropertyStoreForWindow'); var pps = ppsPtr.contents.lpVtbl.contents; 

now you can use IPropertyStore :: SetValue and IPropertyStore :: Release , but be sure to pass ppsPtr as the first argument, and the rest of the arguments what you expect: var hr = pps.SetValue(ppsPtr, firstArgOf_SetValue, secondArgOf_SetValue)


EDIT:

adding the copied paste runnable script from notepad. Copy and paste this: http://pastebin.mozilla.org/8429999

this will make the equivalent of this XPCOM:

  var win = Services.wm.getMostRecentWindow(null); Cc["@mozilla.org/windows-taskbar;1"].getService(Ci.nsIWinTaskbar).setGroupIdForWindow(win, 'Contoso.Scratch') 

Yes, its a long but good thing is that XPCOM does not install RelaunchCommand and RelaunchIconResource etc. That is why js-ctypes is needed.

0
source

Source: https://habr.com/ru/post/926464/


All Articles