0

I'm using js-ctypes here to use winapi on winxp to get a button on the task bar at buton index 1. However this line here is crashing my code: var rez = SendMessage(hToolbar, 0x417 /** TB_GETBUTTON **/, 1, aButton.address());. How can I fix so it doesn't crash?

I'm following this tutorial here: http://w-shadow.com/blog/2006/10/01/manipulating-taskbar-buttons/

Here is copy paste code to scratchpad:

Components.utils.import("resource://gre/modules/ctypes.jsm");

var user32 = ctypes.open('user32.dll');
var kernel = ctypes.open("kernel32.dll");
var HMODULE = ctypes.uint32_t;
var HWND = ctypes.uint32_t;
var LPCTSTR = ctypes.jschar.ptr;
var LPCSTR = ctypes.char.ptr;
var LoadLibrary = kernel.declare("LoadLibraryW", ctypes.winapi_abi, HMODULE, LPCTSTR);
var GetProcAddress = kernel.declare("GetProcAddress", ctypes.winapi_abi, ctypes.void_t.ptr, HMODULE, LPCSTR);

var hUser = LoadLibrary("user32");

/* http://msdn.microsoft.com/en-us/library/windows/desktop/ms633500%28v=vs.85%29.aspx
*/
var funcPtr0 = GetProcAddress(hUser, "FindWindowExW");
var FindWindowExType = ctypes.FunctionType(ctypes.winapi_abi, ctypes.int32_t, [HWND, HWND, LPCTSTR, LPCTSTR]);
funcPtr0 = ctypes.cast(funcPtr0, FindWindowExType.ptr);
//funcPtr0(0, "Test1", "Test2", 0);

var funcPtr1 = GetProcAddress(hUser, "GetTaskmanWindow");
var GetTaskmanWindowType = ctypes.FunctionType(ctypes.winapi_abi, ctypes.int32_t, []);
funcPtr1 = ctypes.cast(funcPtr1, GetTaskmanWindowType.ptr);

var hHwnd = funcPtr1();
var hToolbar = funcPtr0(hHwnd, 0, 'ToolbarWindow32', null);
Services.wm.getMostRecentWindow(null).alert(hToolbar)

var struct_TBButton = ctypes.StructType('TBButton', [
    {'iBitmap': ctypes.int},
    {'idCommand': ctypes.int},
    {'fbState': ctypes.unsigned_char},
    {'fsStyle': ctypes.unsigned_char},
    {'bReserved': ctypes.unsigned_char},
    {'dwData': ctypes.unsigned_long},
    {'iString': ctypes.int}
]);


var SendMessage = user32.declare('SendMessageW', ctypes.winapi_abi, ctypes.uintptr_t,
    ctypes.int32_t,
    ctypes.unsigned_int,
    ctypes.int32_t,
    ctypes.voidptr_t
);

var Count = SendMessage(hToolbar, 0x418 /** TB_BUTTONCOUNT **/, 0, ctypes.voidptr_t(0));
Services.wm.getMostRecentWindow(null).alert(Count);

var aButton = new struct_TBButton();
var rez = SendMessage(hToolbar, 0x417 /** TB_GETBUTTON **/, 1, aButton.address());
Services.wm.getMostRecentWindow(null).alert(rez);
halfer
  • 19,824
  • 17
  • 99
  • 186
Noitidart
  • 35,443
  • 37
  • 154
  • 323

1 Answers1

1

I don't have the time/motiviation to debug this myself, but there is an apparent bug that likely causes the crashes: Your struct_TBButton definition is wrong.

{'bReserved': ctypes.unsigned_char},

vs.

#ifdef _WIN64
  BYTE      bReserved[6];
#else 
#if defined(_WIN32)
  BYTE      bReserved[2];
#endif 
#endif

bReserved should be 2 byte (unsigned chars) in a 32-bit process and 6 in a 64 bit process. (This stuff is there in the first place so that the data members are properly pointer aligned).

Also, your pointer types are wrong, which would have an effect in 64-bit processes.

Putting it all together (avoiding ArrayType because I'm lazy):

var struct_TBButton;
if (ctypes.voidptr_t.size == 4 /* 32-bit */) {
  struct_TBButton = ctypes.StructType('TBButton', [
    {'iBitmap': ctypes.int},
    {'idCommand': ctypes.int},
    {'fbState': ctypes.unsigned_char},
    {'fsStyle': ctypes.unsigned_char},
    {'bReserved': ctypes.unsigned_char},
    {'bReserved2': ctypes.unsigned_char},
    {'dwData': ctypes.uintptr_t},
    {'iString': ctypes.intptr_t}
  ]);  
}
else if (ctypes.voidptr_t.size == 8 /* 64-bit */) {
  struct_TBButton = ctypes.StructType('TBButton', [
    {'iBitmap': ctypes.int},
    {'idCommand': ctypes.int},
    {'fbState': ctypes.unsigned_char},
    {'fsStyle': ctypes.unsigned_char},
    {'bReserved': ctypes.unsigned_char},
    {'bReserved2': ctypes.unsigned_char},
    {'bReserved3': ctypes.unsigned_char},
    {'bReserved4': ctypes.unsigned_char},
    {'bReserved5': ctypes.unsigned_char},
    {'bReserved6': ctypes.unsigned_char},
    {'dwData': ctypes.uintptr_t},
    {'iString': ctypes.intptr_t}
  ]);   
}
else {
  throw new Error("wut?!");
}

console.log(struct_TBButton.size);
// 20 on 32-bit, 32 on 64-bit if I'm not mistaken

PS: The same goes for the rest of your pointer types. https://stackoverflow.com/a/18040503/484441

E.g. HWND WINAPI FindWindowEx() == void* WINAPI FindWindowEx(...) and not uint32_t WINAPI FindWindowEx(...)

Community
  • 1
  • 1
nmaier
  • 32,336
  • 5
  • 63
  • 78
  • That is so cool! I didn't know thats how you can detect if it's 64bit for 32bit!! Thanks man! – Noitidart Jun 09 '14 at 14:30
  • Making structures is so tough for me, I don't undrestand how to go from the C++ type to js type properly I just plug and chug till it works thanks so much for this fix! And expalnation on like HWND == void* – Noitidart Jun 09 '14 at 15:16
  • Btw I just tested your part and you're right I got `20` I'm `32bit`. PS: I like that `throw` hahahah :P PS PS: It's still crashing even with the structrure fix :( I'll keep looking into it – Noitidart Jun 10 '14 at 04:28
  • Doesn't crash for me, but doesn't work either... Doesn't seem to matter anyway because this hack using undocumented behavior/implementation details stopped working in Windows 7 (there is no `ToolbarWindow32` in the `TaskmanWindow` anymore). – nmaier Jun 10 '14 at 12:13
  • Oh yeah in Win7 it doesn't crash but it doesn't work for me too. This is WinXP only :( – Noitidart Jun 10 '14 at 14:54
  • [Spy++](http://msdn.microsoft.com/en-us/library/dd460760.aspx) tells me there is now a `MSTaskListWClass` window where the `ToolbarWindow32` one used to be. But it doesn't react to `TB_` messages nor does it seem to generate any usable other messages which could be appropriated (again Spy++), so no dice. – nmaier Jun 10 '14 at 14:59
  • Oh that's no problem. I have a seperate solution for Win7, but the above is my WinXP solution. I have to make it seperte. I simplified the gist a lot in the bottom most comment, i got rid of casting and functiontype: [yajd / _ff-addon-snippet-GetTaskmanWindowCTypes.js](https://gist.github.com/yajd/e49b49b4d5c3887889b9) (still no work though :( ) – Noitidart Jun 10 '14 at 15:05