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

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
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| 久久久亚洲精品一区二区三区| 久久免费视频在线| 欧美国产日韩一区二区三区| 亚洲国产一区二区三区a毛片 | 亚洲一区999| 一本色道久久88综合亚洲精品ⅰ | 亚洲字幕在线观看| 久久精品九九| 亚洲国产小视频| 亚洲一区二区精品在线| 久久精品国产99| 欧美激情精品久久久六区热门| 欧美日韩免费观看一区=区三区| 国产精品嫩草99a| 亚洲国产另类精品专区| 亚洲欧美在线另类| 欧美高潮视频| 亚洲一区二区三区在线播放| 久久综合久久美利坚合众国| 欧美色另类天堂2015| 黄色精品一二区| 亚洲视频播放| 欧美成人在线网站| 性视频1819p久久| 欧美日韩精品免费在线观看视频| 国产亚洲一区二区三区| 一卡二卡3卡四卡高清精品视频 | 蜜臀av国产精品久久久久| 亚洲裸体俱乐部裸体舞表演av| 欧美一区二区三区在线播放| 欧美视频一区二区在线观看| 亚洲国产婷婷| 久久亚洲精品中文字幕冲田杏梨| 在线视频欧美日韩| 欧美日本一道本| 亚洲激情一区| 欧美成人激情视频免费观看| 亚洲欧美日韩成人高清在线一区| 欧美精品在线免费播放| 亚洲国产视频一区二区| 久久久国产午夜精品| 亚洲新中文字幕| 欧美视频日韩| 亚洲一区二区精品在线| 亚洲人成亚洲人成在线观看图片| 久久精品视频在线免费观看| 国产一区二区三区免费观看| 欧美一区二区三区免费看 | 亚洲免费视频成人| 国产精品美女久久久免费| 亚洲一区视频| 亚洲一级二级| 国产伦精品一区| 欧美在线999| 欧美在线视频一区二区| 国产一区二区三区精品欧美日韩一区二区三区| 国产精品免费看片| 欧美激情精品久久久久久大尺度 | 亚洲资源在线观看| 欧美日韩中文字幕综合视频| 亚洲精选91| 亚洲精品欧美日韩专区| 欧美精品成人91久久久久久久| 亚洲日本一区二区| 91久久精品国产| 欧美日韩精品二区| 亚洲视频香蕉人妖| 中文一区二区| 国产日韩欧美制服另类| 久久免费视频在线观看| 狼狼综合久久久久综合网| 91久久线看在观草草青青| 欧美激情免费在线| 欧美日本亚洲| 午夜视频一区二区| 久久av二区| 亚洲精品一区在线观看香蕉| 亚洲巨乳在线| 国产精品影音先锋| 欧美gay视频激情| 欧美激情第10页| 午夜亚洲激情| 久久久青草婷婷精品综合日韩 | 亚洲一级在线| 欲色影视综合吧| 亚洲精品乱码久久久久久蜜桃91| 国产精品成人国产乱一区| 久久久99久久精品女同性| 老司机午夜精品视频| 一本久久综合亚洲鲁鲁| 午夜精品久久久久久久99水蜜桃 | 亚洲午夜精品一区二区| 在线观看久久av| 国产精品99久久久久久久久| 一区二区视频免费完整版观看| 日韩视频欧美视频| 在线观看视频日韩| 亚洲一区二区欧美日韩| 亚洲区一区二区三区| 亚洲欧美制服另类日韩| 日韩一区二区福利| 久久精品国产成人| 亚洲欧美日本国产专区一区| 麻豆亚洲精品| 美国十次成人| 国产情人综合久久777777| 亚洲国产婷婷综合在线精品| 国产亚洲福利社区一区| av成人老司机| 亚洲精品少妇| 久久免费的精品国产v∧| 午夜一区二区三区在线观看| 欧美精品v日韩精品v国产精品| 麻豆91精品| 狠狠干狠狠久久| 午夜亚洲性色视频| 午夜视频久久久| 国产精品热久久久久夜色精品三区| 亚洲乱码国产乱码精品精98午夜| 亚洲国产精品国自产拍av秋霞| 久久高清国产| 久久精视频免费在线久久完整在线看| 欧美视频日韩视频| 日韩网站在线看片你懂的| 亚洲精品一区二区在线| 美女视频黄免费的久久| 欧美国产日韩一区二区三区| 亚洲第一色中文字幕| 久久性色av| 亚洲国产欧美在线人成| 亚洲精品综合精品自拍| 欧美日韩爆操| 中文精品在线| 欧美专区一区二区三区| 国产一区二区三区黄| 久久狠狠亚洲综合| 麻豆国产va免费精品高清在线| 黄色亚洲在线| 美乳少妇欧美精品| 亚洲高清视频在线| 中文日韩欧美| 国产精品亚洲综合| 亚洲欧美日本在线| 久久伊人亚洲| 亚洲美女在线观看| 国产精品视频一二三| 久久精品成人一区二区三区 | 久久久久久亚洲精品不卡4k岛国| 国产农村妇女精品一区二区| 欧美一区国产在线| 牛人盗摄一区二区三区视频| 亚洲精品社区| 国产精品成人午夜| 久久国产精彩视频| 亚洲国产精品第一区二区| 亚洲图片你懂的| 国产午夜精品理论片a级大结局 | 欧美一区二区三区在线视频| 你懂的亚洲视频| 亚洲一区中文| 国内成人精品一区| 欧美日本高清| 欧美伊人影院| 亚洲精品久久久久久久久久久久| 亚洲综合丁香| 在线精品视频免费观看| 欧美三级乱码| 久久久精品日韩| 一区二区三区四区蜜桃| 葵司免费一区二区三区四区五区| 一本色道**综合亚洲精品蜜桃冫| 亚洲乱码久久| 国产视频不卡| 欧美激情国产日韩| 香蕉成人啪国产精品视频综合网| 欧美激情亚洲另类| 欧美一区二区三区电影在线观看| 亚洲激情第一区| 国产一区二区av| 欧美三级视频在线观看| 麻豆成人在线观看| 小辣椒精品导航| 日韩视频不卡| 亚洲国产精品v| 久久一区视频| 欧美一区在线视频| 亚洲网站视频| 亚洲精品自在在线观看| 极品少妇一区二区| 国产精品久久久久9999吃药| 欧美xart系列高清| 久久精品一区二区| 亚洲欧美日本伦理| 亚洲午夜久久久久久尤物| 亚洲精品一区二区三区99| 欧美激情一区二区三区成人| 老牛国产精品一区的观看方式|