
function QString2JsString(qstr) {
  return ptr('0x'+qstr.readU64().toString(16)).add(0x10).readUtf16String();
}

//////////////////////////////////////////////////////////////////////////////////////////
//                          Qt5Core.dll
//////////////////////////////////////////////////////////////////////////////////////////
/*
地址=00007FFF68C67E60
类型=导出
序号=3828
符号=?fromUtf8@QString@@SA?AV1@PEBDH@Z
符号(已解码)=public: static class QString __cdecl QString::fromUtf8(char const * __ptr64,int)

地址=00007FFF68C64730
类型=导出
序号=1121
符号=??4QString@@QEAAAEAV0@PEBD@Z
符号(已解码)=public: class QString & __ptr64 __cdecl QString::operator=(char const * __ptr64) __ptr64

地址=00007FFF68E65690
类型=导出
序号=5223
符号=?objectName@QObject@@QEBA?AVQString@@XZ
符号(已解码)=public: class QString __cdecl QObject::objectName(void)const __ptr64

*/
// console.log('fnQString_fromUtf8 = ', Module.findExportByName('Qt5Core.dll', '?fromUtf8@QString@@SA?AV1@PBDH@Z'));

// 返回值大于4字节，当做第一个参数传递进去了！！！
// public: static class QString __cdecl QString::fromUtf8(char const *,int)
var fnQString_fromUtf8 = new NativeFunction(
  Module.findExportByName('Qt5Core.dll', '?fromUtf8@QString@@SA?AV1@PEBDH@Z'),
  'void', 
  ['pointer','pointer', 'int'],
  'win64'
);
function ez_fnQString_fromUtf8(jsStr){
  var retQString = Memory.alloc(Process.pointerSize);
  var cStrPointer = Memory.allocUtf8String(jsStr);
  fnQString_fromUtf8(retQString, cStrPointer, -1);
  return retQString;
}
var fn_QString_operator_asign_char = new NativeFunction(
  Module.findExportByName('Qt5Core.dll', '??4QString@@QEAAAEAV0@PEBD@Z'),
  'void', 
  ['pointer','pointer'],
  'win64'
);
function ez_fn_QString_operator_asign_char(obj, jsStr) {
  var cStrPointer = Memory.allocUtf8String(jsStr);
  fn_QString_operator_asign_char(obj, cStrPointer);
}

// using fnQObject_objectName = void* (__thiscall*)(void* pthis, void* qstr);
var fnQObject_objectName = new NativeFunction(
  Module.findExportByName('Qt5Core.dll', '?objectName@QObject@@QEBA?AVQString@@XZ'),
  'pointer', 
  ['pointer', 'pointer'],
  'win64'
);
function ez_fnQObject_objectName(obj) {
  var p = Memory.alloc(8);
  p.writeU32(0);
  fnQObject_objectName(obj, p);
  console.log('ez_fnQObject_objectName >>> ', p.toString(16))
  console.log(hexdump(p, {
    offset: 0,
    length: 0x80,
    header: true,
    ansi: false
  }));
  return p;
}


//////////////////////////////////////////////////////////////////////////////////////////
//                          Qt5Widgets - QWidget
//////////////////////////////////////////////////////////////////////////////////////////
/*
地址=00007FFF60F7AEC0
类型=导出
序号=8298
符号=?topLevelWidgets@QApplication@@SA?AV?$QList@PEAVQWidget@@@@XZ
符号(已解码)=public: static class QList<class QWidget * __ptr64> __cdecl QApplication::topLevelWidgets(void)

地址=00007FFF60FB2670
类型=导出
序号=9029
符号=?x@QWidget@@QEBAHXZ
符号(已解码)=public: int __cdecl QWidget::x(void)const __ptr64

地址=00007FFF60FB26E0
类型=导出
序号=9037
符号=?y@QWidget@@QEBAHXZ
符号(已解码)=public: int __cdecl QWidget::y(void)const __ptr64

地址=00007FFF60FA0B80
类型=导出
序号=4220
符号=?mapFromGlobal@QWidget@@QEBA?AVQPoint@@AEBV2@@Z
符号(已解码)=public: class QPoint __cdecl QWidget::mapFromGlobal(class QPoint const & __ptr64)const __ptr64

地址=00007FFF60FA0CF0
类型=导出
序号=4264
符号=?mapToGlobal@QWidget@@QEBA?AVQPoint@@AEBV2@@Z
符号(已解码)=public: class QPoint __cdecl QWidget::mapToGlobal(class QPoint const & __ptr64)const __ptr64

地址=00007FFF60F74AE0
类型=导出
序号=3953
符号=?isVisible@QWidget@@QEBA_NXZ
符号(已解码)=public: bool __cdecl QWidget::isVisible(void)const __ptr64

地址=00007FFF60FA2DE0
类型=导出
序号=5050
符号=?pos@QWidget@@QEBA?AVQPoint@@XZ
符号(已解码)=public: class QPoint __cdecl QWidget::pos(void)const __ptr64

地址=00007FFF60F84180
类型=导出
序号=7641
符号=?size@QWidget@@QEBA?AVQSize@@XZ
符号(已解码)=public: class QSize __cdecl QWidget::size(void)const __ptr64




*/
// using fnQApplication_topLevelWidgets = QListData * (_cdecl*)(void*);
var fnQApplication_topLevelWidgets = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?topLevelWidgets@QApplication@@SA?AV?$QList@PEAVQWidget@@@@XZ'),
  'pointer', 
  ['pointer'],
  'win64'
);

var fnQWidget_x = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?x@QWidget@@QEBAHXZ'),
  'int', 
  ['pointer'],
  'win64'
);
var fnQWidget_y = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?y@QWidget@@QEBAHXZ'),
  'int', 
  ['pointer'],
  'win64'
);
var fnQWidget_mapFromGlobal = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?mapFromGlobal@QWidget@@QEBA?AVQPoint@@AEBV2@@Z'),
  'pointer', 
  ['pointer', 'pointer', 'pointer'],
  'win64'
);
var fnQWidget_mapToGlobal = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?mapToGlobal@QWidget@@QEBA?AVQPoint@@AEBV2@@Z'),
  'pointer', 
  ['pointer', 'pointer', 'pointer'],
  'win64'
);

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 获取相对于顶层窗口的坐标
function ez_fnQWidget_pos(obj) {
  var qpoint_param = Memory.alloc(8);
  try {
    var ret = fnQWidget_pos(obj, qpoint_param);
    var x = ret.add(0).readS32();
    var y = ret.add(4).readS32();
    // MyLogD('\t\t ez_fnQWidget_pos', qpoint_param.readU64().toString(16), ',x=', x, ',y=', y);
  } catch (error) {
    MyLogE('【catch】 ez_fnQWidget_pos', error);
  }

  return ret;
}
function ez_fnQWidget_mapFromGlobal(obj, point) {
  var ret;
  try {
    var ret2 = Memory.alloc(8);
    ret = fnQWidget_mapFromGlobal(obj, ret2, point);
    var x = ret.add(0).readS32();
    var y = ret.add(4).readS32();
    MyLogD('\t\t ez_fnQWidget_mapFromGlobal', ret2.readU64().toString(16), ',x=', x, ',y=', y);
  } catch (error) {
    MyLogE('【catch】 ez_fnQWidget_mapFromGlobal', error, ret);
  }

  return ret;
}
function ez_fnQWidget_mapFromGlobal_x(obj) {
  try {
    var pos = ez_fnQWidget_pos(obj);
    var pos2 = ez_fnQWidget_mapFromGlobal(obj, pos);
    if (pos2) {
      return pos2.readU64();
    }    
  } catch (error) {
    
  }
  return -1;
}
function ez_fnQWidget_mapFromGlobal_y(obj) {
  try {
    var pos = ez_fnQWidget_pos(obj);
    var pos2 = ez_fnQWidget_mapFromGlobal(obj, pos);
    if (pos2) {
      return pos2.add(4).readU64();
    }    
  } catch (error) {
    
  }
  return -2;
}
function ez_fnQWidget_mapFromGlobal_xy(obj) {
  try {
    var pos = ez_fnQWidget_pos(obj);
    // MyLogD('【 111 】 ez_fnQWidget_mapFromGlobal_xy', pos);
    if(pos) {
      var pos2 = ez_fnQWidget_mapFromGlobal(obj, pos);
      // MyLogD('【 222 】 ez_fnQWidget_mapFromGlobal_xy', pos2);
      if (pos2) {
        // MyLogD('【 333 】 ez_fnQWidget_mapFromGlobal_xy', pos2);
        return `${pos2.readS32()},${pos2.add(4).readS32()}`;
      }
    } 
  } catch (error) {
    MyLogE('【catch】 ez_fnQWidget_mapFromGlobal_xy', error);
  }
  return `-1,-2`;
}
function ez_fnQWidget_mapToGlobal(obj, point) {
  var ret2 = Memory.alloc(8);
  try {
    var ret = fnQWidget_mapToGlobal(obj, point, ret2);
    // var x = ret.add(0).readS32();
    // var y = ret.add(4).readS32();
    // MyLogD('\t\t ez_fnQWidget_mapToGlobal', ret2.readU64().toString(16), ',x=', x, ',y=', y);
  } catch (error) {
    MyLogE('【catch】 ez_fnQWidget_mapToGlobal', error);
  }
  return ret2;
}
function ez_fnQWidget_mapToGlobal_xy(obj) {
  try {
    var pos = ez_fnQWidget_pos(obj);
    // MyLogD('【 111 】 ez_fnQWidget_mapToGlobal_xy', pos);
    if(pos) {
      var pos2 = ez_fnQWidget_mapToGlobal(obj, pos);
      // MyLogD('【 222 】 ez_fnQWidget_mapToGlobal_xy', pos2);
      if (pos2) {
        // MyLogD('【 333 】 ez_fnQWidget_mapToGlobal_xy', pos2);
        return `${pos2.readS32()},${pos2.add(4).readS32()}`;
      }
    } 
  } catch (error) {
    MyLogE('【catch】 ez_fnQWidget_mapToGlobal_xy', error);
  }
  return `-1,-2`;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////

var fnQWidget_isVisible = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?isVisible@QWidget@@QEBA_NXZ'),
  'bool', 
  ['pointer'],
  'win64'
);
var fnQWidget_pos = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?pos@QWidget@@QEBA?AVQPoint@@XZ'),
  'pointer', 
  ['pointer', 'pointer'],
  'win64'
);
var fnQWidget_size = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?size@QWidget@@QEBA?AVQSize@@XZ'),
  'pointer', 
  ['pointer', 'pointer'],
  'win64'
);



//////////////////////////////////////////////////////////////////////////////////////////
//                          Qt5Widgets
// - QLineEdit
// - QCheckBox
// - QAbstractButton
// - QLabel
//////////////////////////////////////////////////////////////////////////////////////////
/*
地址=00007FFF6109A430
类型=导出
序号=7323
符号=?setText@QLineEdit@@QEAAXAEBVQString@@@Z
符号(已解码)=public: void __cdecl QLineEdit::setText(class QString const & __ptr64) __ptr64

地址=00007FFF6109A840
类型=导出
序号=8169
符号=?textChanged@QLineEdit@@QEAAXAEBVQString@@@Z
符号(已解码)=public: void __cdecl QLineEdit::textChanged(class QString const & __ptr64) __ptr64

地址=00007FFF61058010
类型=导出
序号=6254
符号=?setCheckState@QCheckBox@@QEAAXW4CheckState@Qt@@@Z
符号(已解码)=public: void __cdecl QCheckBox::setCheckState(enum Qt::CheckState) __ptr64


地址=00007FFF6104B140
类型=导出
序号=6261
符号=?setChecked@QAbstractButton@@QEAAX_N@Z
符号(已解码)=public: void __cdecl QAbstractButton::setChecked(bool) __ptr64

地址=00007FFF61049580
类型=导出
序号=1850
符号=?click@QAbstractButton@@QEAAXXZ
符号(已解码)=public: void __cdecl QAbstractButton::click(void) __ptr64

地址=00007FFF6104B780
类型=导出
序号=8145
符号=?text@QAbstractButton@@QEBA?AVQString@@XZ
符号(已解码)=public: class QString __cdecl QAbstractButton::text(void)const __ptr64


地址=00007FFF610606C0
类型=导出
序号=8150
符号=?text@QLabel@@QEBA?AVQString@@XZ
符号(已解码)=public: class QString __cdecl QLabel::text(void)const __ptr64


*/
var fnQLineEdit_setText = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?setText@QLineEdit@@QEAAXAEBVQString@@@Z'),
  'void', 
  ['pointer', 'pointer'],
  'win64'
);
var fnQLineEdit_textChanged = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?textChanged@QLineEdit@@QEAAXAEBVQString@@@Z'),
  'void', 
  ['pointer', 'pointer'],
  'win64'
);
var fnQCheckBox_setCheckState = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?setCheckState@QCheckBox@@QEAAXW4CheckState@Qt@@@Z'),
  'void', 
  ['pointer', 'int'],
  'win64'
);


var fnQAbstractButton_setChecked = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?setChecked@QAbstractButton@@QEAAX_N@Z'),
  'void', 
  ['pointer', 'bool'],
  'win64'
);
var fnQAbstractButton_click = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?click@QAbstractButton@@QEAAXXZ'),
  'void', 
  ['pointer'],
  'win64'
);
// fnQAbstractButton_click(ptr(my_read_u64(ptr(0xee7178).add(0x70))))
var fnQAbstractButton_text = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?text@QAbstractButton@@QEBA?AVQString@@XZ'),
  'pointer', 
  ['pointer', 'pointer'],
  'win64'
);
function ez_fnQAbstractButton_text(obj) {
  var s = ez_fnQString_fromUtf8('')
  fnQAbstractButton_text(obj, s);
  return QString2JsString(s)
}



var fnQLabel_text = new NativeFunction(
  Module.findExportByName('Qt5Widgets.dll', '?text@QLabel@@QEBA?AVQString@@XZ'),
  'void', 
  ['pointer','pointer'],
  'win64'
);
function ez_fnQLabel_text(obj) {
  // var retQString = Memory.alloc(Process.pointerSize);
  var retQString = ez_fnQString_fromUtf8('');
  fnQLabel_text(obj, ptr(retQString));
  MyLogD(retQString);
  return my_read_u64_to_obj(retQString).add(0x10).readUtf16String();
}


var IsBadReadPtr = new NativeFunction(
  Module.findExportByName('kernel32.dll', 'IsBadReadPtr'),
  'bool', 
  ['pointer', 'int'],
  'win64'
);

function my_read_u32(addr) {
  return ptr(addr.toString()).readU32()
}
function my_read_u64(addr) {
    return ptr(addr.toString()).readU64()
}
function my_read_u64_to_obj(addr) {
    return ptr(ptr(addr.toString()).readU64());
}


function fnGetWidgetsName(obj) {
  try {
    if (IsBadReadPtr(obj, 4)) {
      return '';
    }
    if (IsBadReadPtr(
          ptr(
            '0x'+my_read_u64(obj.add(4)).toString(16)
          ), 4
        )
      ) {
      return '';
    }
    if (IsBadReadPtr(
        ptr(my_read_u64(obj.add(4))).add(0x1c),
        4)
      ) {
      return '';
    }

    var p = Memory.alloc(4);
    p.writeU32(0);
    fnQObject_objectName(obj, p);
    // console.log(typeof p, p, p.readU64(), p.readU64().toString(16), ptr(p.readU64()).readU64().toString(16))
    // console.log(hexdump(ptr('0x'+p.readU64().toString(16)), {
    //     offset: 0,
    //     length: 0x20,
    //     header: true,
    //     ansi: false
    // }));
    return ptr('0x'+p.readU64().toString(16)).add(0x10).readUtf16String();
  } catch {
    MyLogE('【catch】 fnGetWidgetsName');
  }

  return ''
}

function getWidgetPosSize(obj) {
  var qSzie_param = Memory.alloc(8);
  try {
    var qpoint_param = Memory.alloc(8);
    var qpoint = fnQWidget_pos(obj, qpoint_param);
    var x = qpoint.add(0).readU64();
    var y = qpoint.add(4).readU64();
    // MyLogD('\t\t', qpoint_param.readU64().toString(16), ',x=', x, ',y=', y);

    var qSzie = fnQWidget_size(obj, qSzie_param);
  } catch {
    MyLogE('【catch】 getWidgetPosSize');
  }

  return qSzie_param;
}

function ez_QLineEdit_setText(obj, text) {
    var qstr = ez_fnQString_fromUtf8(text);
    fnQLineEdit_setText(obj, qstr);
  // try {
    // var qstr = ez_fnQString_fromUtf8('ez_QLineEdit_setText');
    // fnQLineEdit_setText(obj, qstr);
  // } catch {
  //   console.log('【catch】 ez_QLineEdit_setText');
  // }
}
// ez_QLineEdit_setText(ptr(my_read_u64(ptr(0xe68a38).add(0x3c))))

function ez_fnQWidget_x(obj) {
  try {
    return fnQWidget_x(obj);
  } catch (error) {
    return -1;
  }
}

function ez_fnQWidget_y(obj) {
  try {
    return fnQWidget_y(obj);
  } catch (error) {
    return -1;
  }
}



//////////////////////////////////////////////////////////////////////////////////////////
//                          qt5webenginewidgets.dll / Qt5WebEngine.dll
// - QWebEnginePage
// - 
//////////////////////////////////////////////////////////////////////////////////////////
/*

地址=00007FFA9AA2CE80
类型=导出
序号=283
符号=?runJavaScript@QWebEnginePage@@QEAAXAEBVQString@@@Z
符号(已解码)=public: void __cdecl QWebEnginePage::runJavaScript(class QString const & __ptr64) __ptr64

地址=00007FFA9AA2ADF0
类型=导出
序号=211
符号=?loadFinished@QWebEnginePage@@QEAAX_N@Z
符号(已解码)=public: void __cdecl QWebEnginePage::loadFinished(bool) __ptr64


WebEngineView QML Type
void runJavaScript(string script, variant callback)
地址=00007FFAAAEB43F0
类型=导出
序号=339
符号=?loadFinished@QQuickWebEngineViewPrivate@@UEAAX_NAEBVQUrl@@0HAEBVQString@@@Z
符号(已解码)=public: virtual void __cdecl QQuickWebEngineViewPrivate::loadFinished(bool,class QUrl const & __ptr64,bool,int,class QString const & __ptr64) __ptr64

地址=00007FFAAAEB5280
类型=导出
序号=527
符号=?runJavaScript@QQuickWebEngineView@@QEAAXAEBVQString@@AEBVQJSValue@@@Z
符号(已解码)=public: void __cdecl QQuickWebEngineView::runJavaScript(class QString const & __ptr64,class QJSValue const & __ptr64) __ptr64



class Q_QML_EXPORT QJSValue
{
public:
    enum SpecialValue {
        NullValue,
        UndefinedValue
    };
public:
    QJSValue(SpecialValue value = UndefinedValue);

    ...
    ...
    ...
}
地址=00007FFAAAECBDD8
类型=导入
符号=qt5qml.??0QJSValue@@QEAA@W4SpecialValue@0@@Z
符号(已解码)=public: __cdecl QJSValue::QJSValue(enum QJSValue::SpecialValue) __ptr64


地址=00007FFAA1E7C450
类型=导入
符号=qt5webenginecore.?runJavaScript@WebContentsAdapter@QtWebEngineCore@@QEAAXAEBVQString@@I@Z
符号(已解码)=public: void __cdecl QtWebEngineCore::WebContentsAdapter::runJavaScript(class QString const & __ptr64,unsigned int) __ptr64

*/
var fnQWebEnginePage_runJavaScript = new NativeFunction(
  Module.findExportByName('Qt5WebEngineWidgets.dll', '?runJavaScript@QWebEnginePage@@QEAAXAEBVQString@@@Z'),
  'void', 
  ['pointer', 'pointer'],
  'win64'
);
var fnQJSValue_QJSValue = new NativeFunction(
  Module.findExportByName('Qt5Qml.dll', '??0QJSValue@@QEAA@W4SpecialValue@0@@Z'),
  'pointer', 
  ['pointer', 'int'],
  'win64'
);
function ez_gen_QJSValue_Undefined() {
  var ret = Memory.alloc(Process.pointerSize);
  fnQJSValue_QJSValue(ret, 1);
  return ret;
}
var fnQQuickWebEngineView_runJavaScript = new NativeFunction(
  Module.findExportByName('Qt5WebEngine.dll', '?runJavaScript@QQuickWebEngineView@@QEAAXAEBVQString@@AEBVQJSValue@@@Z'),
  'void', 
  ['pointer', 'pointer', 'pointer'],
  'win64'
);
var fnWebContentsAdapter_runJavaScript = new NativeFunction(
  Module.findExportByName('Qt5WebEngineCore.dll', '?runJavaScript@WebContentsAdapter@QtWebEngineCore@@QEAAXAEBVQString@@I@Z'),
  'void', 
  ['pointer', 'pointer', 'int'],
  'win64'
);

