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

牽著老婆滿街逛

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

Using WM_COPYDATA

來(lái)源: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 楊粼波 閱讀(1549) 評(píng)論(0)  編輯 收藏 引用


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美性一二三区| 蘑菇福利视频一区播放| 久久久夜精品| 在线一区亚洲| 国产亚洲在线| 蜜桃av综合| 免费欧美日韩国产三级电影| 亚洲精品麻豆| 中文日韩电影网站| 国产日本亚洲高清| 免费看成人av| 欧美日韩亚洲国产精品| 欧美在线播放一区| 久久综合色播五月| 亚洲一区二区三区中文字幕在线| aa日韩免费精品视频一| 国产日产精品一区二区三区四区的观看方式| 久久国产精品99国产| 久久综合九色综合欧美就去吻| 亚洲国产99精品国自产| 欧美电影免费观看大全| 亚洲一区免费| 亚洲电影av| 欧美一区二区日韩| 亚洲人成亚洲人成在线观看图片| 国产精品欧美在线| 久久偷窥视频| 亚洲一区在线观看免费观看电影高清 | 亚洲精品视频在线| 国产欧美日韩视频一区二区三区| 美女网站久久| 欧美一区二区福利在线| 亚洲精品美女91| 久久精品国产精品亚洲精品| 日韩午夜在线视频| 又紧又大又爽精品一区二区| 欧美午夜精品电影| 欧美国产成人精品| 久久人人爽爽爽人久久久| 亚洲视频香蕉人妖| 亚洲福利视频二区| 久热这里只精品99re8久| 亚洲欧美国产日韩中文字幕| 亚洲精选中文字幕| 在线观看视频日韩| 国产欧美日韩综合一区在线观看| 欧美日韩激情网| 免费影视亚洲| 久久久国产一区二区| 亚洲永久视频| 99精品99久久久久久宅男| 亚洲第一福利在线观看| 免费欧美日韩国产三级电影| 久久精品毛片| 亚洲欧美色婷婷| 一区二区三区四区五区视频| 亚洲精品欧洲精品| 亚洲国产清纯| 亚洲二区视频| 亚洲国产精品嫩草影院| 亚洲盗摄视频| 永久久久久久| 亚洲第一福利社区| 在线视频观看日韩| 亚洲国产福利在线| 1024亚洲| 91久久精品久久国产性色也91| 亚洲电影下载| 亚洲国产综合在线| 亚洲国产一成人久久精品| 亚洲国产精品久久人人爱蜜臀| 亚洲国产毛片完整版| 亚洲激情成人| 亚洲精品在线观| 99精品免费| 亚洲女人天堂av| 欧美在线一二三区| 久热国产精品视频| 欧美成人激情视频免费观看| 欧美国产亚洲视频| 亚洲国产专区| 一区二区福利| 午夜精品视频网站| 久久久午夜视频| 欧美成人高清视频| 欧美日韩在线大尺度| 国产精品伦理| 国产自产v一区二区三区c| 伊人精品视频| 99国产精品| 先锋影音国产精品| 久久综合色播五月| 亚洲高清激情| 99热免费精品在线观看| 亚洲婷婷在线| 久久国产综合精品| 欧美激情在线观看| 国产精品午夜电影| 永久久久久久| 中文成人激情娱乐网| 久久都是精品| 亚洲成人在线视频播放 | 老司机凹凸av亚洲导航| 欧美日韩不卡视频| 国产亚洲成人一区| 亚洲精品一区二区网址| 亚洲欧美欧美一区二区三区| 久久久久高清| 91久久午夜| 亚洲欧美在线一区二区| 美女黄网久久| 国产欧美精品国产国产专区| 亚洲精品乱码久久久久| 午夜日韩av| 亚洲福利免费| 欧美一区二区成人| 欧美三级精品| 亚洲高清不卡在线观看| 欧美亚洲在线视频| 亚洲激情电影中文字幕| 性久久久久久| 欧美精品免费播放| 精品成人一区二区| 亚洲欧美日韩爽爽影院| 亚洲国产综合在线| 久久爱www久久做| 国产精品久久久久999| 亚洲欧洲午夜| 久久久久国内| 亚洲一区二区av电影| 欧美久久久久中文字幕| 影音欧美亚洲| 久久九九全国免费精品观看| 99re亚洲国产精品| 欧美91视频| 精品999在线播放| 欧美一区免费视频| 这里只有精品电影| 欧美激情亚洲自拍| 亚洲国产欧美一区二区三区久久 | 亚洲人成在线观看一区二区| 欧美在线播放| 国产免费成人av| 亚洲欧美日韩国产一区二区| 亚洲日韩第九十九页| 免费影视亚洲| 亚洲东热激情| 蜜臀av在线播放一区二区三区 | 久久久精品一区二区三区| 国产精品毛片在线| 亚洲欧美一区二区视频| 在线亚洲一区观看| 欧美午夜激情视频| 亚洲综合视频网| 一本大道av伊人久久综合| 欧美日本高清| 中文av一区二区| 日韩一区二区久久| 欧美色精品天天在线观看视频| 亚洲美女电影在线| 亚洲人精品午夜| 欧美精品v日韩精品v国产精品| 亚洲人精品午夜在线观看| 亚洲成人直播| 欧美精品一区二区三| 一区二区三区欧美成人| av成人国产| 国产精品日韩高清| 欧美在线三级| 久久久久久久综合色一本| 在线高清一区| 欧美激情免费在线| 欧美日韩视频在线| 性欧美8khd高清极品| 久久狠狠婷婷| 亚洲国产成人tv| 亚洲欧洲久久| 国产精品久久久久久久app| 午夜精品久久久久久久99黑人 | 久久久久久穴| 亚洲人午夜精品| 一区二区三区免费观看| 国产毛片精品视频| 免费在线视频一区| 欧美片第1页综合| 午夜精品三级视频福利| 久久av资源网| 亚洲欧洲免费视频| 亚洲视频一二三| 国内精品美女av在线播放| 欧美激情第二页| 欧美午夜精品一区| 久久天天躁夜夜躁狠狠躁2022| 农夫在线精品视频免费观看| 亚洲视频在线观看三级| 亚洲欧美日韩直播| 最近中文字幕日韩精品 | 欧美另类69精品久久久久9999| 亚洲女同在线| 久久亚洲国产成人|