Win7 x64下Tab Control插入标签问题

在Win7 x64环境下使用汇编语言(JWASM)开发过程中,遇到在创建Tab控件并尝试插入标签时,发送TCM_INSERTITEM消息引发0xc000005错误。经过WinDbg调试,发现在comctl32.dll的Tab_OnInsertItem函数中,TCITEM结构体的pszText字段的地址与预期不符。解决方案是将TCITEM.mask的值类型改为UINT64,修正pszText的地址,从而解决问题。此问题可能影响到其他64位程序中Tab控件的文字读取。

最近想用汇编(JWASM)写一64位的程序,没想到在创建Tab上遇到了问题,在WndProc函数里处理WM_CREATE时,用CreateWindowEX创建Tab控件后,调用SendMessage发送TCM_INSERTITEM消息时莫名其妙的报0xc000005错误


 @tieTCITEM Struct
仔细查看了代码,没发现错误,而运行时却报0xc000005错误
用WinDbg调试了下,发现最后出错在Kernel32.dlllstrcpy函数上,有点不明白,查看了下Call Stack,发现问题主要出在comctl32.dllTab_OnInsertItem函数上,其通过comctl32.dllStr_Set函数调用lstrcpyTab_OnInsertItem函数内容见下图


在第8行里,mov  rbp,r8 (将@tie地址赋予了rbp),而在此后第23、31、39行对@tie.imask值进行比较,而我之前将TCIF_TEXT(0x1)赋予@tie.imask
所以第39行
test byte ptr [rbp],1  ;; if ( @tie.imask == 1)
对比正确后开始执行第41行,
mov rdx, qword ptr [rbp+10h]    ;;将TCITEM.pszText的值赋予rdx
紧接着在第43行就调用函数Str_Set了,可以看出函数Str_Set的第二个参数为@tie.pszText
错就出在第41行mov rdx,qword ptr [rbp+10h]的[rbp+10h]上,
按MSDN上对TCITEM的定义

typedef struct tagTCITEM { 
  UINT mask;             4个字节 (因mask为JWASM的关键字,所以更改为imask)
  DWORD dwState;         4个字节
  DWORD dwStateMask;     4个字节
  LPTSTR pszText;        8个字节
  int cchTextMax ;       4个字节
  int iImage;            4个字节
  LPARAM lParam;         8个字节
} TCITEM; 

@tie.pszText的地址应该为[rbp+0ch](rbp@tie的指针),而实际在comctl32.dllTab_OnInsertItem函数中取pszText的地址为[rbp+10h],也就是说TCITEM struct中在pszText之前应该有16个字节,这个不知道算不算Bug?还是微软忘了在MSDN上更新TCITEM所以我暂时将TCITEM.mask的值类型改为UINT64(因TCM_INSERTITEM消息中dwState和dwStateMask为无效),就成了

typedef struct tagTCITEM { 
  UINT64 mask;           8个字节
  DWORD dwState;         4个字节
  DWORD dwStateMask;     4个字节
  LPTSTR pszText;        8个字节
  int cchTextMax ;       4个字节
  int iImage;            4个字节
  LPARAM lParam;         8个字节
} TCITEM; 

这样@tie.pszText的地址就成了[rbp+10h]

重新对ASM文件进行编译后,程序终于正常运行了

不清楚微软在comctl32.dll中怎么定义的TCITEM……


另:看优快云上好多人问为什么无法读取Tab上的文字(C++),按其贴出的代码来看是正确的,不知道他们是否也是在写64位程序,因TCITEM Struct问题所以无法得到正确的TCITEM.pszText地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值