Search code examples
javascriptfirefox-addonjsctypes

setConsoleIcon throwing weird error (Undocumented WinAPI to JS-Ctypes)


There's this undocumend winapi fetarue called setConsoleIcon. I discussed with this guy here:

https://github.com/john-peterson/john-peterson/issues/1#issuecomment-47852560

The C++ code is this:

void SetIcon(LPCTSTR icon) {
    HMODULE hMainMod = GetModuleHandle(NULL);
    HICON hMainIcon = ::LoadIcon(hMainMod, icon);
    HMODULE hMod = LoadLibraryA("Kernel32.dll");
    typedef BOOL (CALLBACK *InsHook)(unsigned long, HANDLE);
    typedef DWORD (__stdcall *SCI)(HICON);
    SCI pfnSetConsoleIcon = reinterpret_cast<SCI>(GetProcAddress(hMod, "SetConsoleIcon"));
    pfnSetConsoleIcon(hMainIcon);
    FreeLibrary(hMod);
}

I converted it to this:

Cu.import('resource://gre/modules/ctypes.jsm');

var kernel32 = ctypes.open('kernel32.dll');
var user32 = ctypes.open('user32.dll');

var SetConsoleIcon = kernel32.declare('SetConsoleIcon', ctypes.winapi_abi, ctypes.voidptr_t, // i have no idea what return value is so made it voidptr_t
    ctypes.voidptr_t // HICON
);

 /* http://msdn.microsoft.com/en-us/library/windows/desktop/ms648045%28v=vs.85%29.aspx
* HANDLE WINAPI LoadImage(
* __in_opt_ HINSTANCE hinst,
* __in_ LPCTSTR lpszName,
* __in_ UINT uType,
* __in_ int cxDesired,
* __in_ int cyDesired,
* __in_ UINT fuLoad
* );
*/
var LoadImage = user32.declare('LoadImageA', ctypes.winapi_abi, ctypes.voidptr_t,
    ctypes.voidptr_t,
    ctypes.char.ptr,
    ctypes.unsigned_int,
    ctypes.int,
    ctypes.int,
    ctypes.unsigned_int
);

var IMAGE_BITMAP = 0;
var IMAGE_ICON = 1;
var LR_LOADFROMFILE = 16;


var aDOMWindow = window;
var baseWindow = aDOMWindow.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));


var hIconBig = LoadImage(targetWindow_handle, 'C:\\Users\\noit\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\1agqx535.default2\\profilist32.ico', IMAGE_ICON, 256, 256, LR_LOADFROMFILE);
var hIconBigNull = LoadImage(null, 'C:\\Users\\noit\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\1agqx535.default2\\profilist32.ico', IMAGE_ICON, 256, 256, LR_LOADFROMFILE);
var void = SetConsoleIcon(hIconBig); //SetConsoleIcon(hIconBigNull);

If you comment out the final line and copy and run this you get no problems.

However if you uncomment it and use it with hIconBig or hIconBigNull you get this error: (difference between two, is to hIconBig I pass window handle and to hIconBigNull i pass null as handle)

/*
"missing variable name
WCA_evalWithDebugger@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/webconsole.js:1069:7
WCA_onEvaluateJS@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/actors/webconsole.js:734:9
DSC_onPacket@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/server/main.js:1098:9
LDT_send/<@resource://gre/modules/devtools/dbg-client.jsm -> resource://gre/modules/devtools/server/transport.js:279:11
makeInfallible/<@resource://gre/modules/commonjs/toolkit/loader.js -> resource://gre/modules/devtools/DevToolsUtils.js:84:7"
*/

I can't explain this missing variable name. Any ideas?


Solution

  • The problem here is your var void = .... void is a reserved keyword in Javascript and therefore cannot be used in as a variable name.

    Other random observations:

    • Use ctypes.void_t when declaring functions that are void or where you don't care about the return value.
    • Never call LoadImage with a window handle. It is supposed to be called with a module handle or null. You'll want to call it with null, since you're loading stand-alone images.
    • Using undocumented APIs is not a very good idea in general, and should be avoided if feasible. I know that first getting the console window handle with GetConsoleWindow() and then sending WM_SETICON works just fine, and that is using documented functionality.
    • I have no idea what you're trying to do here anyway. Firefox has (normally) no console window at all.