微软向OEM厂商提供Phone Canvas机制,让我们可以修改cprog.exe的数个界面布局和UI交互行为。
我们发现多数Phone Canvas API函数的返回值列表中都存在错误值RPC_E_WRONG_THREAD,下表就是PHGetBlobPtr的返回值列表:
S_OK | Indicates success. |
E_INVALIDARG | Indicates failure. |
E_PENDING | Indicates this phone data identifier has no associated data yet. For example, PH_ID_LASTCALL_INFO before any calls have been made. |
RPC_E_WRONG_THREAD | Indicates that this function must be called from the main UI thread, since all of the phone canvas APIs are called on the main UI thread. |
理论上,Phone Canvas API函数必须在主UI线程调用,否则调用Phone Canvas API函数会返回错误值RPC_E_WRONG_THREAD。但实际使用下来,我们发现无论怎么调用Phone Canvas API函数都不会返回RPC_E_WRONG_THREAD,出于好奇我反汇编了tpcutil.dll对其调用机制一探究竟。
以下是根据笔者反汇编所得,改用C/C++描述的InitializePHCanvas函数实现,该函数用于加载Phone Canvas模块:
g_hMainCProgThread最初被赋值了GetCurrentThread()函数的返回值。
下面是PHGetBlobPtr函数的实现:
笔者注意到与g_hMainCProgThread比较的是GetCurrentThread()函数返回值,我们已知g_hMainCProgThread也是GetCurrentThread()函数的返回值,而且GetCurrentThread()函数无论在哪个线程里调用都返回一个数值相同的伪句柄。
所以,这个分支是永远进入不了的,PHGetBlobPtr函数也永远不会返回错误值RPC_E_WRONG_THREAD了。