青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

Using WM_COPYDATA

來源:http://www.flounder.com/wm_copydata.htm

I have experienced several problems, not of my own creation, in using WM_COPYDATA. Now, when I need to use it, I use a mechanism that protects me against the sort of problems I experienced. This essay describes those techniques for creating programs that can reliably and with some assurances of security use WM_COPYDATA.

 

 

Introduction to WM_COPYDATA

The WM_COPYDATA message is used to send large blocks of data across process boundaries. It is defined as 


SendMessage(target, WM_COPYDATA, (WPARAM)sender, (LPARAM)&COPYDATASTRUCT)

The WPARAM is the handle of the sending window. The LPARAM is a pointer to a structure of the form


typedef struct tagCOPYDATASTRUCT 
    ULONG_PTR dwData; 
    DWORD     cbData; 
    PVOID     lpData; 
}
 COPYDATASTRUCT, *PCOPYDATASTRUCT; 

Presumably the dwData member is a small integer that tells the receiving window how to interpret the data referenced by lpData. The cbData value tells how many bytes of data are being passed.

This message can only be sent via SendMessage, which means that it will hang indefinitely if the receiving thread is blocked, or via SendMessageTimeout, if you want reliability. However, it cannot be send via PostMessage.

The data specified appears in the receiver's address space, and is pointed to by a similar COPYDATASTRUCT seen by the receiver. The receiver can examine the dwData to determine what to do, and use at most cbData bytes of the data pointed to by the lpData pointer. The data is intact only as long as the message is being processed. When you return from the OnCopyData handler, the data will disappear from the receiver's address space, so you must not store a copy of the lpData pointer. Instead, if you need the data after the handler returns, you must, in the receiving process, copy the data to a place in the program where it will remain available.


WM_COPYDATA hazards

I don't trust WM_COPYDATA.

It is not that I don't trust it to work. Indeed, it is reliable. It is not that I don't trust it to actually deliver data. It does that, too.

What I don't trust, as the receiver, is the sender. Having the WPARAM value which tells me the sender window handle doesn't help much, because the sender window could be any window of an application, not just the main frame. I have actually been the victim of an incorrect WM_COPYDATA message. The programmer who was sending it had no idea how to find the desired target window, so instead, "cleverly" decided to broadcast the WM_COPYDATA message to all top-level windows, knowing that his window would eventually get it. Of course, mine did also.

Furthermore, sending a bogus WM_COPYDATA is something a malicious program might choose to do in order to cause other programs to crash. I want to be robust against this sort of attack.



Making WM_COPYDATA safe

What I do for security is create a GUID. In this case, I don't want the textual form, I want the binary form. I then place this GUID, which is a 128-bit value, in the first part of my data. When I code the receiver, I test the first 16 bytes of every WM_COPYDATA packet (and there must be at least 16 bytes in the WM_COPYDATA packet, or I ignore it). If the first 16 bytes of the message do not match the GUID, I simply return 0 and ignore the message. Since I started doing this, I have never been the victim of an erroneous WM_COPYDATA send to my application (even in the environment of rogue WM_COPYDATA messages).

Here's an example of the kind of message I send. In this case, I sent it to my own process, but it would work identically across process boundaries. Note the first 16 bytes are the GUID, which will be shown later. I have three other buttons, one to send a message that is too short, one to send a message with a bad GUID, and one to send a message with an unknown dwType.

This shows what happens if I send fewer than sizeof(GUID) bytes:

If I send a bad GUID (look at the 5th byte in the first line and compare it to the first version, above), I get

and if I send a bad type, I get the following result. Note that the dwData field is 2, and I was only prepared to accept 1.

Here's my set of related classes, a file I call CopyData.h.

#ifndef MAX_COPY_LENGTH
#define MAX_COPY_LENGTH 128
#endif

class CopyPacket {
    
public:
       GUID Signature;
       BYTE data[MAX_COPY_LENGTH];
    
public:
       BOOL Same(
const GUID & s)
         
return memcmp(&Signature, &s, sizeof(GUID)) == 0; }
}
;
   

class CopyData {
    
public:
       CopyData(UINT id, GUID s)
         
{ packet.Signature = s; cds.dwData = id; cds.cbData = 0; cds.lpData = &packet; }
       UINT SetLength(UINT n)
         
{ cds.cbData = sizeof(packet.Signature) + n; return cds.cbData; }
       
void SetData(LPCVOID src, size_t length)
         
{ ::CopyMemory(packet.data, src, length); }
       LRESULT Send(HWND target, HWND sender)
         
return ::SendMessage(target, WM_COPYDATA, (WPARAM)sender, (LPARAM)&cds); }
       
static UINT GetMinimumLength()
         
return sizeof(GUID); }
    
protected:
       COPYDATASTRUCT cds;
       CopyPacket packet;
}
;



To create the signature, I use GUIDGen, and create a GUID using the option shown: If you are not aware of it, a GUID is globally unique; that is, once you create one, it is the only one which will ever exist, anywhere in the world. No one else will ever re-create the same GUID.

OK, a fine point. If you don't have a network card, there is something like 1 chance in 263 or something equally large that two 128-bit GUIDs could coincide. Figure out how many computers need to create how many GUIDs at what rate and you'll see this is not a Major Issue To Be Concerned With.

The option I show is the closest one to what I want. I click on the Copy button, then I paste the text into a file called signature.h. I replace the first line with 

#define SIGNATURE \

I then declare, in my implementation files, a static global variable which defines the signature. Each module that wants to send or receive a message must contain this declaration.

 

static const GUID Signature = SIGNATURE;


I need a dwType to distinguish what kind of message I'm sending. In this case, I am only sending one type of message, which I have decided to call COPYDATA_TYPE_1, which I define as the constant 1 (a whimsical choice).

To send a message, such as the valid sending, I do something like shown below (this is simplified, because I use the various check boxes and options to derive the window handles). Also, in my case, I'm sending the message from my application to itself, so the first parameter (target) and the second parameter (sender) are both m_hWnd.

 

void CCopyDataDlg::OnSendvalid() 
   
{
    CopyData sendData(COPYDATA_TYPE_1, Signature);
    CString s;
    c_Input.GetWindowText(s);

    sendData.SetData((LPCVOID)(LPCTSTR)s, s.GetLength()
+1);
    sendData.SetLength(s.GetLength() 
+ 1);
    sendData.Send(m_hWnd, m_hWnd);
   }

The receive code, minus the code that loads the messages into the status boxes, 
is then quite simple:

BOOL CCopyDataDlg::OnCopyData(CWnd
* pWnd, COPYDATASTRUCT* cds) 
   
{
    CopyPacket 
* cp = (CopyPacket *)cds->lpData;
    BOOL result 
= TRUE;

    
if(cds->dwData != COPYDATA_TYPE_1)
       
/* bad type */
    result 
= FALSE;
       }
 /* bad type */

    
if(cds->cbData < CopyData::GetMinimumLength())
       
/* record too short */
    result 
= FALSE;
       }
 /* record too short */

    
if(!cp->Same(Signature))
       
/* record bad signature */
    result 
= FALSE;
       }
 /* record bad signature */

    
if(result)
       
/* success */
    
do something with the message
       }
 /* success */

    
return result;
    
}

 


Broadcast Usage

Note that using HWND_BROADCAST as the target window will send the message to every window. In this example, I have two copies of my program running, and the upper-left window receives the same data as the lower right window. However, every other application window in my desktop received this message. I was lucky. None of them were bothered by the WM_COPYDATA. This is not always going to be the case. So sending a message like this using HWND_BROADCAST is to be considered a seriously antisocial act. If you download my files and try to send using HWND_BROADCAST (checking the Broadcast box), you may well crash programs you have running. If so, Let That Be A Lesson To You.




Passing Pointers

Note that everything inside the WM_COPYDATA block must be part of the block. You can't use it to pass a pointer to something. For example, it would be a fatal error to pass a CString variable in the WM_COPYDATA block because the string itself would still be in the address space of the sender. If you need to pass a complex structure, you have to make all of the pointers in the WM_COPYDATA block be based pointers that reference the contents of the data block. That is an essay I may write someday.



Summary

WM_COPYDATA is a powerful and convenient means for transferring information between two processes. It is not without risks. These techniques were developed to minimize those risks.

download.gif (1234 bytes)You can download the code for my test app and my CopyData.h file. However, you should not reuse my GUID because there is always the chance someone else will have also copied it, and you lose the security that having a unique ID provides.

posted on 2009-09-28 21:04 楊粼波 閱讀(1541) 評論(0)  編輯 收藏 引用

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区二区三区在线视频| 99国产精品视频免费观看| 亚洲欧美日韩精品久久奇米色影视| 亚洲美女视频网| 欧美私人网站| 久久精品国产成人| 亚洲丶国产丶欧美一区二区三区 | 久久婷婷丁香| 亚洲国产精品电影在线观看| 免费观看30秒视频久久| 亚洲国产人成综合网站| 午夜精品福利一区二区三区av| 国产欧美日韩中文字幕在线| 久久久伊人欧美| 久久成年人视频| 国产精品久久久久秋霞鲁丝| 久久久久www| 亚洲日本黄色| 蜜桃久久av一区| 欧美在线视频一区| 日韩亚洲一区在线播放| 国产日本欧美一区二区三区在线| 欧美激情欧美激情在线五月| 亚洲欧美一区二区原创| 一区二区三区精密机械公司| 免费黄网站欧美| 久久精品欧洲| 久久不射电影网| 欧美一区在线直播| 午夜精品一区二区三区在线播放| 91久久久亚洲精品| 激情91久久| 在线观看三级视频欧美| 国产一区二区日韩精品欧美精品| 欧美三级小说| 国产精品推荐精品| 国产精品捆绑调教| 国产九区一区在线| 国产精品豆花视频| 国产欧美精品一区二区色综合 | 欧美极品在线观看| 欧美二区在线| 欧美久久久久久蜜桃| 国产精品久久久久免费a∨| 国产午夜亚洲精品羞羞网站| 国产欧美视频在线观看| 国产在线观看精品一区二区三区 | 久久成人免费网| 久久久精品免费视频| 亚洲第一成人在线| 亚洲看片一区| 久久精品国产免费观看| 欧美高清视频一区二区| 国产精品视频免费观看www| 国产一区二区三区网站| 国内外成人免费视频| 国产九九精品| 91久久精品视频| 午夜精品视频一区| 欧美不卡视频| 亚洲欧美三级在线| 欧美高清视频在线播放| 国产欧美日韩亚州综合| 日韩亚洲欧美中文三级| 久久久久综合| 99re这里只有精品6| 免费观看成人| 在线日韩精品视频| 老色鬼精品视频在线观看播放| 亚洲美女性视频| 欧美激情一区二区三区| 伊人成人在线| 欧美高清在线一区二区| 久久国产免费| 韩日视频一区| 免费看亚洲片| 久久久久久久久久久成人| 国语自产精品视频在线看抢先版结局| 99pao成人国产永久免费视频| 欧美激情成人在线| 蜜臀91精品一区二区三区| 亚洲国产欧美一区| 亚洲国内精品| 欧美视频中文一区二区三区在线观看 | 欧美国产日产韩国视频| 久久亚洲色图| 亚洲精品日韩激情在线电影| 亚洲国产专区| 国产女主播一区二区| 噜噜噜噜噜久久久久久91| 狂野欧美激情性xxxx欧美| 亚洲国产视频a| 亚洲一区二区三区激情| 久热综合在线亚洲精品| 欧美黄免费看| 久久国产精品一区二区三区| 久久亚洲欧美| 欧美一区二区三区四区夜夜大片| 久久九九免费视频| 亚洲小少妇裸体bbw| 久久久久久一区二区| 亚洲欧美999| 乱人伦精品视频在线观看| 亚洲免费婷婷| 亚洲欧洲av一区二区三区久久| 国产精品国产a| 亚洲激情黄色| 亚洲高清免费| 午夜精品国产| 欧美一区二区三区免费大片| 欧美a级理论片| 欧美激情一区二区三区不卡| 国产一区美女| 欧美专区中文字幕| 久久激情久久| 国产拍揄自揄精品视频麻豆| 亚洲精品一区二区三区av| 亚洲精品日产精品乱码不卡| 久久亚洲国产成人| 老司机亚洲精品| 亚洲电影网站| 欧美成人免费播放| 亚洲激情视频在线| av成人动漫| 欧美性猛交xxxx乱大交蜜桃| 日韩一级在线| 久久精品国产一区二区三区| 国产在线日韩| 欧美日韩第一页| 亚洲综合国产精品| 欧美大尺度在线观看| 亚洲美女av电影| 国产精品亚洲产品| 久久伊伊香蕉| 一区二区三区精品久久久| 久久狠狠久久综合桃花| 亚洲国产精品成人综合| 国产精品成人一区| 另类av导航| 午夜精品美女自拍福到在线 | 欧美中文字幕在线观看| 美女主播精品视频一二三四| 这里只有精品视频在线| 国产主播精品在线| 国产精品草草| 欧美激情国产日韩| 久久久亚洲精品一区二区三区 | 亚洲免费视频网站| 亚洲精品一区在线观看| 国产亚洲人成a一在线v站 | 欧美一区二区三区免费视频 | 欧美jizz19hd性欧美| 一区二区精品在线| 亚洲国产精品福利| 蜜桃av久久久亚洲精品| 久久久亚洲综合| 欧美电影专区| 艳妇臀荡乳欲伦亚洲一区| 欧美视频在线观看| 欧美成人精品在线| 免费在线一区二区| 老司机精品视频网站| 老司机一区二区| 欧美精品在线一区二区三区| 欧美高清不卡在线| 欧美一区免费视频| 欧美一区二区三区在线视频| 欧美一级二区| 午夜久久久久久| 老色鬼精品视频在线观看播放| 久久精品国产清高在天天线| 久久午夜av| 亚洲第一区在线观看| 夜色激情一区二区| 久久国产乱子精品免费女| 久久久亚洲精品一区二区三区| 免费看的黄色欧美网站| 国产精品久久久久久久久婷婷 | 亚洲一级免费视频| 久久成人一区| 亚洲精品一二三区| 久久精品国产成人| 国产精品扒开腿爽爽爽视频 | 久久精品一二三| 欧美日韩久久久久久| 在线看片一区| 亚洲欧美一区二区原创| 亚洲国产精品女人久久久| 亚洲午夜国产一区99re久久| 久久综合狠狠综合久久综合88| 欧美视频1区| av成人手机在线| 亚洲国产精彩中文乱码av在线播放| 一本色道久久综合亚洲91| 麻豆精品在线观看| 一区二区在线观看av| 久久久久久久久久看片| 亚洲专区一二三| 国产九九视频一区二区三区| 午夜日韩激情|