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

牽著老婆滿街逛

嚴(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>
            亚洲国产日韩欧美| 久久综合色播五月| 久久久久久久一区二区三区| 玖玖综合伊人| 日韩视频免费看| 欧美一区成人| 欧美日本精品一区二区三区| 国产日韩欧美夫妻视频在线观看| 91久久精品国产91久久| 午夜亚洲伦理| 亚洲大片av| 亚洲尤物精选| 欧美高清hd18日本| 国产欧美午夜| 99伊人成综合| 另类国产ts人妖高潮视频| 亚洲精品中文在线| 久久久噜噜噜| 国产麻豆日韩欧美久久| 99成人免费视频| 久久在线免费视频| 一区二区三区日韩欧美精品| 久久久精品久久久久| 国产精品国产三级国产普通话蜜臀 | 欧美jizzhd精品欧美巨大免费| 国产精品扒开腿做爽爽爽软件| 精品成人国产| 欧美亚洲综合久久| 亚洲国产美女久久久久| 欧美一区二视频| 欧美日韩国内自拍| 亚洲激情在线| 久久免费视频网站| 亚洲在线观看| 欧美日韩久久| 亚洲精品久久| 久久蜜桃香蕉精品一区二区三区| 一本色道久久综合一区| 农村妇女精品| 韩国免费一区| 欧美一级视频| 中文久久乱码一区二区| 欧美日本中文| 亚洲国产欧美久久| 久久综合福利| 久久爱www.| 国产日韩欧美日韩| 亚洲欧美日韩区| 99视频超级精品| 欧美激情一区二区三区在线视频观看| 在线看日韩av| 久久婷婷亚洲| 久久精品视频在线| 国内外成人在线视频| 性欧美1819性猛交| 亚洲——在线| 国产精品一区二区女厕厕| 亚洲永久精品大片| 亚洲视频成人| 欧美特黄一级| 亚洲欧美变态国产另类| 国产精品99久久久久久久久| 欧美日韩日日夜夜| 亚洲一区二三| 亚洲性感美女99在线| 欧美午夜在线视频| 亚洲一二三四久久| 亚洲视频你懂的| 国产精品久久久久一区二区三区共| 国产精品99久久久久久www| 亚洲精品美女久久7777777| 欧美精品在线观看| 在线一区二区三区四区| 亚洲精品美女久久久久| 欧美日韩无遮挡| 亚洲欧美另类在线| 亚洲欧美日韩高清| 国产亚洲欧美在线| 狂野欧美激情性xxxx| 久久在线精品| 日韩一区二区精品视频| 亚洲精品美女在线观看播放| 欧美日韩中文另类| 欧美一区三区二区在线观看| 午夜精品久久久久久久蜜桃app| 国产日本亚洲高清| 久久夜色精品亚洲噜噜国产mv| 久久久亚洲高清| 亚洲日本一区二区三区| 日韩天堂在线观看| 国产欧美短视频| 久久综合99re88久久爱| 麻豆精品网站| 一区二区三区日韩| 亚洲欧美在线aaa| 韩国一区电影| 最新成人在线| 国产精品一区二区欧美| 久久视频在线免费观看| 欧美国产一区二区三区激情无套| 亚洲视频在线一区| 久久国产天堂福利天堂| 亚洲精品欧美在线| 亚洲综合第一| 亚洲国产日韩欧美综合久久| 99国产精品久久| 国产一区二区观看| 亚洲国产精品小视频| 国产精品久久久久久久久免费樱桃| 久久久中精品2020中文| 欧美激情第三页| 欧美影院精品一区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 一本色道88久久加勒比精品| 亚洲视频久久| 亚洲国产高清一区| 亚洲天堂视频在线观看| 亚洲第一成人在线| 99热这里只有精品8| 激情综合在线| 一级成人国产| 在线精品国精品国产尤物884a| 99re成人精品视频| 在线电影国产精品| 亚洲亚洲精品三区日韩精品在线视频| 激情成人中文字幕| 一区二区三区免费观看| 在线日韩视频| 亚洲欧美www| 亚洲黄色在线| 欧美在线视频在线播放完整版免费观看| 亚洲精品四区| 久久狠狠亚洲综合| 亚洲欧美日韩一区在线观看| 裸体歌舞表演一区二区| 小辣椒精品导航| 欧美日本视频在线| 每日更新成人在线视频| 国产精品看片资源| 亚洲日韩第九十九页| 激情一区二区| 亚洲男人的天堂在线| 一区二区成人精品 | 亚洲精品乱码久久久久久蜜桃麻豆 | 伊人影院久久| 亚洲欧美精品一区| 亚洲视频免费在线| 欧美国产视频在线| 欧美成年视频| 国产一区二区三区黄| 亚洲校园激情| 亚洲无限av看| 欧美激情导航| 欧美国产视频一区二区| 国产在线不卡| 亚洲欧美另类在线观看| 亚洲一品av免费观看| 欧美激情视频网站| 欧美激情一二区| 亚洲第一在线视频| 久久久久综合网| 久久婷婷人人澡人人喊人人爽| 国产农村妇女精品一二区| 一本色道综合亚洲| 亚洲少妇诱惑| 欧美区高清在线| 亚洲国产精品久久久| 亚洲国产91色在线| 久久天天躁狠狠躁夜夜爽蜜月 | 久久久人成影片一区二区三区| 国产精一区二区三区| 亚洲午夜小视频| 亚洲一区免费视频| 国产精品国色综合久久| 在线视频日本亚洲性| 亚洲一区二区成人| 欧美午夜精品| 亚洲一区二区三区免费在线观看| 亚洲一区尤物| 国产精品国内视频| 亚洲一二三区在线观看| 午夜在线视频观看日韩17c| 国产精品久久久久久久久借妻 | 国内精品视频在线观看| 久久丁香综合五月国产三级网站| 久久精品一区二区三区不卡| 国产日韩三区| 欧美一级理论性理论a| 欧美一区二区三区四区视频| 国产视频精品网| 欧美一区二区三区四区夜夜大片 | 麻豆精品国产91久久久久久| 亚洲成人在线网站| 女同一区二区| 亚洲欧洲精品一区二区| 亚洲视频专区在线| 国产日韩欧美麻豆| 久久亚洲私人国产精品va| 欧美国产日本韩| 一本色道久久综合狠狠躁的推荐|