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

牽著老婆滿街逛

嚴以律己,寬以待人. 三思而后行.
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 楊粼波 閱讀(1544) 評論(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>
            欧美日韩精品是欧美日韩精品| 午夜精品福利电影| 欧美日韩一区二区在线播放| 久久美女艺术照精彩视频福利播放| 欧美一级成年大片在线观看| 午夜亚洲性色视频| 久久大逼视频| 玖玖在线精品| 欧美精品一区二区三区在线播放 | 亚洲国产精品一区| 亚洲精华国产欧美| 一区二区国产精品| 欧美一级久久久| 久久九九热re6这里有精品| 久久久午夜电影| 亚洲国产高清自拍| 亚洲人成人99网站| 亚洲小说欧美另类社区| 午夜精品一区二区三区在线播放| 欧美一区二区久久久| 久久综合色综合88| 国产精品福利网| **网站欧美大片在线观看| 亚洲无线观看| 久久综合网hezyo| 日韩午夜在线视频| 久久久999精品免费| 欧美日韩综合在线| 亚洲成色精品| 欧美亚洲综合网| 欧美国产欧美亚洲国产日韩mv天天看完整 | 亚洲卡通欧美制服中文| 亚洲欧美视频| 欧美日韩小视频| 极品日韩久久| 久久福利资源站| 99xxxx成人网| 久久字幕精品一区| 国产在线精品自拍| 亚洲欧美激情四射在线日 | 亚洲自拍偷拍视频| 欧美成人a视频| 午夜久久一区| 国产精品男女猛烈高潮激情| 亚洲激情精品| 免费成人毛片| 久久国产高清| 亚洲一区二区欧美| 欧美日韩精品一区二区| 影音先锋一区| 久久免费视频观看| 欧美一区二区三区喷汁尤物| 国产精品网站在线播放| 亚洲欧美日韩精品在线| 亚洲免费av观看| 欧美激情视频网站| 亚洲青涩在线| 亚洲国产免费看| 免费在线亚洲| 99re成人精品视频| 亚洲黄色有码视频| 欧美裸体一区二区三区| 9国产精品视频| 夜夜嗨av一区二区三区中文字幕 | 亚洲九九九在线观看| 欧美激情第五页| aa级大片欧美| 亚洲精品日韩久久| 欧美视频四区| 亚洲欧美自拍偷拍| 亚洲一区在线播放| 国产精品一区视频| 久久精品国产91精品亚洲| 欧美一区免费视频| 一区免费观看| 亚洲激情偷拍| 国产精品久久久久一区二区三区| 欧美一区二区在线免费播放| 性伦欧美刺激片在线观看| 韩国成人精品a∨在线观看| 免费在线一区二区| 欧美精品一区在线播放| 亚洲一区尤物| 久久精品国产精品 | 欧美一区二区免费| 久久精品国产欧美亚洲人人爽| 在线成人激情| 亚洲第一网站免费视频| 欧美日韩999| 欧美一区免费视频| 久久综合综合久久综合| 夜夜嗨av一区二区三区四区| 一区二区日韩伦理片| 国产欧美日韩另类视频免费观看| 久久精品国产第一区二区三区最新章节 | 欧美在线亚洲在线| 亚洲国产欧美日韩精品| 亚洲毛片一区| 国内外成人在线| 亚洲精品视频在线看| 国产欧美69| 亚洲精品激情| 激情综合色丁香一区二区| 亚洲日本在线视频观看| 国产自产女人91一区在线观看| 亚洲国产三级在线| 韩国三级电影一区二区| 一区二区激情小说| 亚洲啪啪91| 久久久999精品| 欧美一区二区三区视频| 欧美高清视频一二三区| 久久久久久高潮国产精品视| 欧美日韩1区2区| 欧美大片91| 激情另类综合| 午夜精品久久久久久久久久久| 99国产精品久久久久久久久久| 欧美在线观看你懂的| 亚洲欧美日本国产专区一区| 久热国产精品视频| 久久久久一区二区三区四区| 国产精品国产三级国产aⅴ无密码 国产精品国产三级国产aⅴ入口 | 亚洲欧美日韩国产中文| 一区二区三区av| 免费不卡在线视频| 麻豆av福利av久久av| 国产日韩精品视频一区| 亚洲主播在线观看| 亚洲欧美日韩精品久久| 欧美日韩免费| 日韩亚洲国产欧美| 在线亚洲自拍| 欧美日韩在线电影| 一本色道久久综合狠狠躁的推荐| 一区二区欧美国产| 欧美激情一区二区三区在线视频| 欧美国产一区二区| 91久久极品少妇xxxxⅹ软件| 美女黄毛**国产精品啪啪| 欧美成人午夜| 亚洲精品一区二区三区樱花| 美女精品在线观看| 欧美激情亚洲| 99re6热只有精品免费观看| 欧美电影免费观看高清完整版| 亚洲国产福利在线| 亚洲一区二区伦理| 国产精品一区二区你懂的| 午夜精品亚洲一区二区三区嫩草| 欧美在线观看视频一区二区| 国产精品一区二区男女羞羞无遮挡| 亚洲午夜一区二区| 久久久91精品国产一区二区三区| 韩日成人在线| 美女视频黄 久久| 亚洲乱亚洲高清| 午夜视黄欧洲亚洲| 久久综合免费视频影院| 欧美激情在线观看| 亚洲视频免费| 国产一区二区高清| 男人的天堂成人在线| 亚洲精品在线视频观看| 性色av香蕉一区二区| 在线播放一区| 欧美三区在线视频| 久久精品国产一区二区三区| 亚洲二区在线| 先锋影音国产精品| 亚洲国产精品99久久久久久久久| 欧美日韩高清在线播放| 欧美一级黄色录像| 亚洲精品美女在线观看| 久久激情五月激情| 一区二区三区av| 极品尤物一区二区三区| 欧美日韩大片| 久久午夜视频| 亚洲欧美日韩另类| 欧美激情免费观看| 亚洲欧美成人在线| 亚洲国产三级在线| 国产精品久久婷婷六月丁香| 久久久青草婷婷精品综合日韩| 亚洲国产精品久久久久婷婷老年| 亚洲欧美怡红院| 亚洲精品中文字幕有码专区| 国产精品激情av在线播放| 久久久精品免费视频| 亚洲视频在线观看| 亚洲国产影院| 免费日韩av| 欧美一区二区国产| 亚洲精品视频中文字幕| 国产精品一卡| 欧美日韩亚洲成人| 欧美高清视频免费观看| 久久国产婷婷国产香蕉| 中文在线一区|