Last active
August 29, 2015 14:03
-
-
Save yajd/862832b07a1d46caef8b to your computer and use it in GitHub Desktop.
_ff-addon-snippet-RelaunchCommand - Working on Relaunch properties of Win7.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Cu.import('resource://gre/modules/ctypes.jsm'); | |
var shell32 = ctypes.open('shell32.dll'); | |
var ole32 = ctypes.open('Ole32.dll'); | |
var shlwapi = ctypes.open('Shlwapi.dll'); | |
/* http://msdn.microsoft.com/en-us/library/ff718266.aspx | |
* typedef struct { | |
* unsigned long Data1; | |
* unsigned short Data2; | |
* unsigned short Data3; | |
* byte Data4[8]; | |
* } GUID, UUID, *PGUID; | |
*/ | |
var struct_GUID = ctypes.StructType('GUID', [ | |
{'Data1': ctypes.unsigned_long}, | |
{'Data2': ctypes.unsigned_short}, | |
{'Data3': ctypes.unsigned_short}, | |
{'Data4': ctypes.char.array(8)} | |
]); | |
/* http://msdn.microsoft.com/en-us/library/cc237652.aspx | |
* typedef GUID IID; | |
*/ | |
var IID = struct_GUID; | |
/* http://msdn.microsoft.com/en-us/library/cc237816.aspx | |
* typedef IID* REFIID; | |
*/ | |
var REFIID = new ctypes.PointerType(IID); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms680589%28v=vs.85%29.aspx | |
* HRESULT CLSIDFromString( | |
* __in_ LPCOLESTR lpsz, | |
* __out_ LPCLSID pclsid | |
); | |
*/ | |
var CLSIDFromString = ole32.declare('CLSIDFromString', ctypes.winapi_abi, ctypes.long, // HRESULT | |
new ctypes.PointerType(ctypes.jschar), // LPCOLESTR | |
struct_GUID.ptr // LPCLSID | |
); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/dd378430%28v=vs.85%29.aspx | |
* HRESULT SHGetPropertyStoreForWindow( | |
* __in_ HWND hwnd, | |
* __in_ REFIID riid, | |
* __out_ void **ppv | |
* ); | |
*/ | |
var SHGetPropertyStoreForWindow = shell32.declare('SHGetPropertyStoreForWindow', ctypes.winapi_abi, ctypes.long, // HRESULT | |
ctypes.voidptr_t, // HWND | |
REFIID, // REFIID | |
ctypes.voidptr_t // VOID | |
); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381%28v=vs.85%29.aspx | |
* typedef struct { | |
* GUID fmtid; | |
* DWORD pid; | |
* } PROPERTYKEY; | |
*/ | |
var struct_PROPERTYKEY = ctypes.StructType('PROPERTYKEY', [ // this is also known as PKEY i learned from seeing this: https://github.com/truonghinh/TnX/blob/260a8a623751ffbce14bad6018ea48febbc21bc6/TnX-v8/Microsoft.Windows.Shell/Standard/ShellProvider.cs#L345 | |
{'fmtid': struct_GUID}, // GUID | |
{'pid': ctypes.unsigned_long} // DWORD | |
]); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/bb773381%28v=vs.85%29.aspx | |
* typedef struct PROPVARIANT { | |
* VARTYPE vt; | |
* WORD wReserved1; | |
* WORD wReserved2; | |
* WORD wReserved3; | |
* union { | |
* CHAR cVal; | |
* UCHAR bVal; | |
* SHORT iVal; | |
* USHORT uiVal; | |
* LONG lVal; | |
* ULONG ulVal; | |
* INT intVal; | |
* UINT uintVal; | |
* LARGE_INTEGER hVal; | |
* ULARGE_INTEGER uhVal; | |
* FLOAT fltVal; | |
* DOUBLE dblVal; | |
* VARIANT_BOOL boolVal; | |
* SCODE scode; | |
* CY cyVal; | |
* DATE date; | |
* FILETIME filetime; | |
* CLSID *puuid; | |
* CLIPDATA *pclipdata; | |
* BSTR bstrVal; | |
* BSTRBLOB bstrblobVal; | |
* BLOB blob; | |
* LPSTR pszVal; | |
* LPWSTR pwszVal; | |
* IUnknown *punkVal; | |
* IDispatch *pdispVal; | |
* IStream *pStream; | |
* IStorage *pStorage; | |
* LPVERSIONEDSTREAM pVersionedStream; | |
* LPSAFEARRAY parray; | |
* CAC cac; | |
* CAUB caub; | |
* CAI cai; | |
* CAUI caui; | |
* CAL cal; | |
* CAUL caul; | |
* CAH cah; | |
* CAUH cauh; | |
* CAFLT caflt; | |
* CADBL cadbl; | |
* CABOOL cabool; | |
* CASCODE cascode; | |
* CACY cacy; | |
* CADATE cadate; | |
* CAFILETIME cafiletime; | |
* CACLSID cauuid; | |
* CACLIPDATA caclipdata; | |
* CABSTR cabstr; | |
* CABSTRBLOB cabstrblob; | |
* CALPSTR calpstr; | |
* CALPWSTR calpwstr; | |
* CAPROPVARIANT capropvar; | |
* CHAR *pcVal; | |
* UCHAR *pbVal; | |
* SHORT *piVal; | |
* USHORT *puiVal; | |
* LONG *plVal; | |
* ULONG *pulVal; | |
* INT *pintVal; | |
* UINT *puintVal; | |
* FLOAT *pfltVal; | |
* DOUBLE *pdblVal; | |
* VARIANT_BOOL *pboolVal; | |
* DECIMAL *pdecVal; | |
* SCODE *pscode; | |
* CY *pcyVal; | |
* DATE *pdate; | |
* BSTR *pbstrVal; | |
* IUnknown **ppunkVal; | |
* IDispatch **ppdispVal; | |
* LPSAFEARRAY *pparray; | |
* PROPVARIANT *pvarVal; | |
* }; | |
* } PROPVARIANT; | |
*/ | |
var struct_PROPVARIANT = ctypes.StructType('PROPVARIANT', [ | |
{'fntud': struct_GUID}, // GUID | |
{'pid': ctypes.unsigned_long}, // DWORD | |
// 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" | |
{'pwszVal': new ctypes.PointerType(ctypes.jschar)} // LPWSTR | |
]); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/bb762305%28v=vs.85%29.aspx | |
* REMARKS: This is an inline function, with its source code provided in the header. It is not included in any .dll or .lib file. | |
* HRESULT InitPropVariantFromString( | |
* __in_ PCWSTR psz, | |
* __out_ PROPVARIANT *ppropvar | |
* ); | |
SOURCE2: https://github.com/dreamsxin/qutIM/blob/f4c4e4da3f82f14d82cfd42a16f31219c9e5cacb/plugins/docktile/qtdocktile/src/plugins/windows/wrapper/_winapi.h#L17 | |
inline HRESULT InitPropVariantFromString(PCWSTR string, PROPVARIANT *propvar) | |
{ | |
propvar->vt = VT_LPWSTR; | |
HRESULT hr = SHStrDupW(string, &propvar->pwszVal); | |
if (FAILED(hr)) { | |
WinApi::PropVariantInit(propvar); | |
} | |
return hr; | |
} | |
*/ | |
/* | |
* var InitPropVariantFromString = propsys.declare('InitPropVariantFromString', ctypes.winapi_abi, ctypes.long, // HRESULT | |
* ctypes.jschar.ptr, // PCWSTR | |
* struct_PROPVARIANT.ptr // PROPVARIANT | |
* ); | |
*/ | |
function InitPropVariantFromString(string /** PCWSTR **/, propvarPtr /** PROPVARIANT pointer **/) { | |
//console.log('propvarPtr.contents.pwszVal', propvarPtr.contents.pwszVal, propvarPtr.contents.pwszVal.toSource(), uneval(propvarPtr.contents.pwszVal)); | |
//console.log('propvarPtr', propvarPtr); | |
console.log('propvarPtr.contents.pwszVal', propvarPtr.contents.pwszVal); | |
console.log('propvarPtr.contents.pwszVal.address()', propvarPtr.contents.pwszVal.address()); | |
var hr = SHStrDup(string, propvarPtr.contents.pwszVal.address()); | |
console.error('hr = ', hr, hr.toSource(), uneval(hr), hr.toString()); | |
console.log('propvarPtr.contents.pwszVal', propvarPtr.contents.pwszVal); | |
if (!checkHRESULT(hr)) { | |
console.log('having to PropVariantInit'); | |
PropVariantInit(propvarPtr); | |
} else { | |
console.info('YAHOO SUCESSS'); | |
} | |
return true; | |
} | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa380293%28v=vs.85%29.aspx | |
* REMARKS: Probably no dll for this one... | |
* void PropVariantInit( | |
* __out_ PROPVARIANT *pvar | |
* ); | |
SOURCE2: https://github.com/dreamsxin/qutIM/blob/f4c4e4da3f82f14d82cfd42a16f31219c9e5cacb/plugins/docktile/qtdocktile/src/plugins/windows/wrapper/_winapi.h#L12 | |
void PropVariantInit(PROPVARIANT *variant) | |
{ | |
memset(variant, 0, sizeof(PROPVARIANT)); | |
} | |
*/ | |
var PropVariantInit = function(variantPointer) { | |
//memset(variantPointer, 0, variantPointer.size); //no need for this in js-ctypes because things always initialized at 0 | |
return true; | |
} | |
/* 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 // can possibly also make this ctypes.char.ptr // im trying to pass PCWSTR here, i am making it as `ctypes.jschar.array()('blah blah').address()` | |
ctypes.voidptr_t // LPTSTR // can possibly also make this ctypes.char.ptr | |
); | |
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa380073%28v=vs.85%29.aspx | |
* WINOLEAPI PropVariantClear( | |
* __in_ PROPVARIANT *pvar | |
* ); | |
*/ | |
var PropVariantClear = ole32.declare('PropVariantClear', ctypes.winapi_abi, ctypes.voidptr_t, // WINOLEAPI | |
struct_PROPVARIANT.ptr // PROPVARIANT | |
); | |
/*http://msdn.microsoft.com/en-us/library/windows/desktop/ee330727%28v=vs.85%29.aspx | |
* void IID_PPV_ARGS( | |
* T **pType | |
* ); | |
*/ | |
// maybe: http://blogs.msdn.com/b/yvesdolc/archive/2006/12/27/iid-ppv-args-macro.aspx | |
// var IID_PPV_ARGS = shell32.declare('IID_PPV_ARGS', ctypes.winapi_abi, ctypes.voidptr_t, // void | |
// ctypes.voidptr_t // T | |
// ); | |
/* SOURCE1: http://msdn.microsoft.com/en-us/library/windows/desktop/bb761475%28v=vs.85%29.aspx | |
* HRESULT SetValue( | |
* __in_ REFPROPERTYKEY key, | |
* __in_ REFPROPVARIANT propvar | |
* ); | |
* SOURCE2: http://blogs.msdn.com/b/oldnewthing/archive/2011/06/01/10170113.aspx | |
* 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; | |
* } | |
*/ | |
var IPropertyStore_SetValue = function(pps /** IPopertyStore pointer **/, pkey /** PROPERTYKEY **/, pszValue /** PCWSTR **/) { | |
//pps must be passed in as reference | |
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; | |
} | |
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa378137%28v=vs.85%29.aspx | |
var S_OK = 0; | |
var S_FALSE = 1; | |
function onCreate(hwnd) { | |
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'); | |
} | |
//console.log('pps', pps.toSource()); | |
var hr = SHGetPropertyStoreForWindow(hwnd, pps.address(), ppv.address()); | |
console.error('hr = ', hr, hr.toSource(), uneval(hr), hr.toString()); | |
if (!checkHRESULT(hr)) { //this throws so no need to do an if on hr brelow, im not sure that was possible anyways as hr is now `-2147467262` and its throwing, before thi, with my `if (hr)` it would continue thinking it passed | |
throw new Error('checkHRESULT error'); | |
} | |
var pszValue = ctypes.jschar.array()('Contoso.Scratch'); // PCWSTR | |
IPropertyStore_SetValue(pps.address(), PKEY_AppUserModel_ID, pszValue.address()); | |
var pszValue = ctypes.jschar.array()('notepad.exe %windir%\\system.ini'); // PCWSTR | |
IPropertyStore_SetValue(pps.address(), PKEY_AppUserModel_RelaunchCommand, pszValue.address()); //relaucnhcommand and relaunchdispnameresc must both be set otherise if just do one, then it will not take | |
var pszValue = ctypes.jschar.array()('C:\\full\\path\\to\\scratch.exe,-1'); // PCWSTR; | |
IPropertyStore_SetValue(pps.address(), PKEY_AppUserModel_RelaunchDisplayNameResource, pszValue.address()); //relaucnhcommand and relaunchdispnameresc must both be set otherise if just do one, then it will not take | |
//var pszValue = ctypes.jschar.array()('C:\\full\\path\\to\\scratch.ico'); // PCWSTR; | |
//IPropertyStore_SetValue(pps, PKEY_AppUserModel_RelaunchIconResource, pszValue.address()); //optional | |
return true; | |
} | |
// start - error handling funcs (Source: https://github.com/FunkMonkey/Loomo/blob/2c0a7a042b91c430ca89fd22d5003ccb7dbf57dd/Loomo/chrome/content/modules/Utils/COM/COM.jsm) | |
function checkHRESULT(hr) { | |
if (hr != S_OK) { | |
//throw new Error("TESTERR"); | |
console.error('checkHRESULT error = ', new COMError(hr)); | |
return false; | |
} | |
return true; | |
} | |
function COMError(hr) { | |
// Well, we don't subclass, cause for some reason that fucks up the callstack | |
var name = "COMError " + hr + " (0x" + decimalToHexString(parseInt(hr.toString())) + ")"; | |
var err = new Error(name); | |
err.isCOMError = true; | |
err.name = name; | |
err.message = name + " Well, go and bing!!!"; | |
return err; | |
} | |
function decimalToHexString(number) { | |
if (number < 0) { | |
number = 0xFFFFFFFF + number + 1; | |
} | |
return number.toString(16).toUpperCase(); | |
} | |
// end : error handling funcs | |
var me = Services.wm.getMostRecentWindow(null); | |
var baseWindow = me.QueryInterface(Ci.nsIInterfaceRequestor) | |
.getInterface(Ci.nsIWebNavigation) | |
.QueryInterface(Ci.nsIDocShellTreeItem) | |
.treeOwner | |
.QueryInterface(Ci.nsIInterfaceRequestor) | |
.nsIBaseWindow; | |
var nativeHandle = baseWindow.nativeHandle; | |
var targetWindow_handle = ctypes.voidptr_t(ctypes.UInt64(nativeHandle)); | |
/* pid's and guid string's for my 4 properties above (PKEY_AppUserModel_ID, PKEY_AppUserModel_RelaunchIconResource, etc) and more found at following two sources: | |
* setting pkey = https://github.com/truonghinh/TnX/blob/260a8a623751ffbce14bad6018ea48febbc21bc6/TnX-v8/Microsoft.Windows.Shell/Standard/ShellProvider.cs#L358 | |
* setting pkey in py = https://github.com/liuheng/byp/blob/28c26f8903dc122237982e2c19b58dce35612ad8/thirdlib/pywin32/com/win32comext/propsys/pscon.py#L712 | |
*/ | |
var myGUID = new struct_GUID(); | |
var HR_myGUID = CLSIDFromString('{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}', myGUID.address()); // same for guid for: id, relaubchcommand, relaunchdisp, and relaunchicon | |
if (!checkHRESULT(HR_myGUID)) { | |
throw new Error('checkHRESULT error'); | |
} | |
console.log('myGUID', myGUID); | |
// Create PKEY for AppUserModel_ID | |
var PKEY_AppUserModel_ID = new struct_PROPERTYKEY(); | |
PKEY_AppUserModel_ID.fmtid = myGUID; | |
PKEY_AppUserModel_ID.pid = 5; | |
// Create PKEY for AppUserModel_RelaunchCommand | |
var PKEY_AppUserModel_RelaunchCommand = new struct_PROPERTYKEY(); | |
PKEY_AppUserModel_RelaunchCommand.fmtid = myGUID; | |
PKEY_AppUserModel_RelaunchCommand.pid = 2; | |
// Create PKEY for AppUserModel_RelaunchDisplayNameResource | |
var PKEY_AppUserModel_RelaunchDisplayNameResource = new struct_PROPERTYKEY(); | |
PKEY_AppUserModel_RelaunchDisplayNameResource.fmtid = myGUID; | |
PKEY_AppUserModel_RelaunchDisplayNameResource.pid = 4; | |
// Create PKEY for AppUserModel_RelaunchIconResource | |
var PKEY_AppUserModel_RelaunchIconResource = new struct_PROPERTYKEY(); | |
PKEY_AppUserModel_RelaunchIconResource.fmtid = myGUID; | |
PKEY_AppUserModel_RelaunchIconResource.pid = 3; | |
onCreate(targetWindow_handle); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's how to QI IPropertyStore from ShelLink to set properties on a shortcut I would think:
https://github.com/dlunch/foo_alsong_lyric/blob/aba6c9061213d37980c010025263ffae31a752de/src/foo_alsong_lyric/UIWnd.cpp#L211