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

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
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 楊粼波 閱讀(1549) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   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>
            亚洲精品韩国| 亚洲香蕉成视频在线观看| 国产精品va在线播放| 免费黄网站欧美| 国产伦理一区| 亚洲视频一区二区| 99精品福利视频| 久久综合色一综合色88| 久久高清福利视频| 欧美亚洲不卡| 一本到高清视频免费精品| 亚洲日本电影在线| 久久久免费精品| 老司机成人网| 激情欧美一区二区| 欧美在线视频观看| 久久国产精品久久w女人spa| 国产精品成人免费精品自在线观看| 亚洲人成小说网站色在线| 国内精品视频一区| 久久精品国产精品亚洲综合| 久久久久成人精品免费播放动漫| 国产乱码精品一区二区三区忘忧草 | 亚洲日本在线视频观看| 久久久久99精品国产片| 久久国产一二区| 国产日韩视频| 久久精品一二三| 蜜臀av一级做a爰片久久| 永久免费毛片在线播放不卡| 久久精品欧洲| 欧美电影美腿模特1979在线看 | 99视频有精品| 欧美激情视频在线播放| 亚洲人体1000| 中文日韩电影网站| 欧美午夜不卡视频| 亚洲欧美制服中文字幕| 久久精品日韩一区二区三区| 精品999成人| 狼狼综合久久久久综合网| 免费不卡在线观看| 亚洲精选视频免费看| 欧美偷拍一区二区| 性欧美xxxx视频在线观看| 久久免费少妇高潮久久精品99| 在线成人国产| 欧美精品日韩www.p站| 在线亚洲观看| 久久婷婷国产麻豆91天堂| 亚洲高清激情| 欧美日韩另类在线| 午夜精品久久久久久久男人的天堂| 久久久精品网| 亚洲精品黄色| 国产日韩欧美二区| 蜜桃av噜噜一区| 亚洲一区在线视频| 美女黄毛**国产精品啪啪| 一区二区三区视频在线播放| 国产伦精品一区二区三区高清版 | 亚洲欧美日韩网| 女仆av观看一区| 亚洲在线免费视频| 一区二区在线视频| 国产精品wwwwww| 麻豆av福利av久久av| 亚洲少妇最新在线视频| 免费观看一级特黄欧美大片| 亚洲一区二区三区久久 | 国产精品二区二区三区| 久久久久一区二区三区四区| 中国女人久久久| 欧美大片在线观看一区| 午夜免费久久久久| 亚洲美女毛片| 狠狠色伊人亚洲综合网站色| 欧美三级网页| 欧美.com| 久久精品中文字幕一区二区三区| 亚洲精品一二三区| 欧美11—12娇小xxxx| 欧美在线不卡| 亚洲性人人天天夜夜摸| 亚洲七七久久综合桃花剧情介绍| 国产午夜精品视频| 国产精品海角社区在线观看| 欧美凹凸一区二区三区视频| 欧美一区二区黄色| 亚洲午夜久久久久久尤物| 亚洲欧洲日本专区| 欧美成人官网二区| 久久这里只精品最新地址| 久久丁香综合五月国产三级网站| 一区二区免费在线视频| 91久久在线观看| 一区二区视频免费在线观看 | 亚洲免费成人av| 亚洲国产精品成人综合| 红桃视频一区| 国产综合一区二区| 国产在线视频欧美| 国产午夜精品在线观看| 国产欧美精品va在线观看| 国产精品视频午夜| 国产精品久久一级| 国产精品国产精品国产专区不蜜| 欧美日韩国产色视频| 欧美精品免费在线观看| 欧美激情第9页| 欧美区在线观看| 欧美日韩三区| 欧美深夜影院| 国产精品成人va在线观看| 欧美三级日本三级少妇99| 欧美视频四区| 国产精品卡一卡二| 国产视频在线观看一区 | 亚洲国产成人高清精品| 亚洲黄色在线看| 日韩午夜三级在线| 99成人精品| 午夜精品久久久久久久久久久久| 午夜日韩在线| 狂野欧美激情性xxxx| 欧美成人久久| 亚洲免费观看高清完整版在线观看| 一本色道久久综合亚洲二区三区| 亚洲一区网站| 久久这里只有| 欧美日韩一区二区视频在线观看| 国产精品国产三级国产专区53| 国产乱码精品1区2区3区| 激情综合久久| 中文网丁香综合网| 久久激情综合| 最新精品在线| 午夜伦欧美伦电影理论片| 久久久久高清| 欧美三日本三级三级在线播放| 国产毛片久久| 日韩午夜电影在线观看| 性8sex亚洲区入口| 蘑菇福利视频一区播放| 日韩午夜电影av| 久久福利毛片| 欧美日韩一区二区在线播放| 国产亚洲免费的视频看| 亚洲欧洲在线免费| 欧美一区二区高清| 欧美激情一区二区三区蜜桃视频| 亚洲午夜女主播在线直播| 久久久久久久网站| 国产精品vip| 亚洲国产成人久久综合一区| 亚洲欧美国产日韩中文字幕| 欧美高清一区二区| 亚洲在线观看| 欧美日韩一卡| 亚洲国产经典视频| 欧美一区成人| 日韩亚洲精品电影| 久久三级福利| 国产一区欧美| 亚洲免费影院| 亚洲日本视频| 免费美女久久99| 永久免费视频成人| 午夜在线视频观看日韩17c| 亚洲国产一区二区a毛片| 久久久久国产精品人| 国产精品亚洲网站| 亚洲天堂av图片| 亚洲国产mv| 久久综合久久综合这里只有精品| 国产欧美日韩视频一区二区| 亚洲一区亚洲| 亚洲免费福利视频| 欧美成人情趣视频| 亚洲第一黄色| 你懂的成人av| 久久婷婷久久| 亚洲国产精品一区二区第四页av| 久久久久久国产精品mv| 午夜精品av| 国产伦精品一区二区三区| 亚洲欧美日韩另类精品一区二区三区 | 久久久在线视频| 午夜精品久久久久久久99樱桃| 欧美亚洲不卡| 午夜宅男欧美| 亚洲欧美日韩国产综合| 国产精品亚发布| 欧美尤物巨大精品爽| 亚洲欧美国产高清va在线播| 国产欧美精品va在线观看| 欧美在线观看视频| 亚洲欧美综合网| 国内成+人亚洲| 免费在线观看一区二区|