Glenn Linderman wrote:

Pre-canning of messages for common controls would be a good thing. It would require lots of work (maybe not that much actually - some analysis should be required).


Complexity and performance considerations may mean that frequently used operations should still be coded in C. But let's hope not, because a single mechanism would be less code to support. Hopefully pre-canning would remove the complexity part, for frequently used messages.

Mechanisms to simplify the interfaces to remote SendMessage calls would certainly be welcomed by most users, to the extent that they can be invented.


You know, when I was thinking about the implementation of Interprocess SendMessage for Win32::GuiTest I first come to an idea that there should be a separate function called, say, SendIPMessage (Send Interprocess message), which should take as a parameter a window handle, message id, WPARAM, LPARAM. In addition a planned to pass as parameters information like - how much data we send in the buffer pointed by WPARAM/LPARAM, how much data we expect to receive in this buffer. This "flexibility" made the function so complex (mainly due to analysis of several possible combinations of input parameters) that I decided that it would be easier, if the user will be given a chance to allocate external memory him/herself and do all necessary copying and then calling an ordinary SendMessage. Another argument for this solution was, that sometimes (for example for LVITEM for ListView) you had to allocate additional memory, which was then pointed by LVITEM member. So you know what was my reasoning behind making user aware of other process memory space problems. But I would be pretty happy to see a solution, which would transparently and inteligently handle this problem, freeing user from worring about complex windows process's related issues.

As for sending frequently used messages we can go this way: In each Win32::GUI function, which actually does need marshaling, we can check if a window to which we send a message, is in the same process which is calling SendMessage. You can use GetCurrentProcessId and GetWindowThreadProcessId API to check it. If there is interprocess call, we take the path with virtuall memory allocation. If window is owned by a process, which sends a message, that the current code is executed. We could start the implemenation from implementing in all these methods (those which involve marshaling) a check if we do an interprocess SendMessage. If such a call is detected, the function whould die. That way, we would have TESTING application dying before making forbidden SendMessage rather than allowing it to call SendMessage, which would kill the TESTED application. We could then start to systematically add interprocess marshaling in all places where it is required.
Let me give you an example:

Currently, the Win32::GUI function for getting an item from ListView looks like this:

void
GetItem(handle,item, subitem=0)
    HWND handle
    int item
    int subitem
ALIAS:
    Win32::GUI::ListView::ItemInfo = 1
PREINIT:
    LV_ITEM lv_item;
    char pszText[1024];
PPCODE:
    ZeroMemory(&lv_item, sizeof(LV_ITEM));
    lv_item.iItem = item;
    lv_item.mask = LVIF_IMAGE
                 | LVIF_PARAM
                 | LVIF_TEXT | LVIF_STATE;
    lv_item.pszText = pszText;
    lv_item.cchTextMax = 1024;
    lv_item.iSubItem = subitem;
    if(ListView_GetItem(handle, &lv_item)) {
        EXTEND(SP, 6);
        XST_mPV(0, "-text");
        XST_mPV(1, lv_item.pszText);
        XST_mPV(2, "-image");
        XST_mIV(3, lv_item.iImage);
        XST_mPV(4, "-state");
        XST_mIV(5, lv_item.state);
        XSRETURN(6);
    } else {
        XSRETURN_UNDEF;
    }


Initially I would add something like this:


void
GetItem(handle,item, subitem=0)
    HWND handle
    int item
    int subitem
ALIAS:
    Win32::GUI::ListView::ItemInfo = 1
PREINIT:
    LV_ITEM lv_item;
    char pszText[1024];
PPCODE:
->    int thisproc = GetCurrentProcessId();
->    int calledproc = 0;
->    GetWindowThreadProcessId( handle, &calledproc );
->    if( thisproc != calledproc ){
-> die( "You are making interprocess call, which is not allowed for this -> message" );
->    }
    ZeroMemory(&lv_item, sizeof(LV_ITEM));
    lv_item.iItem = item;
    lv_item.mask = LVIF_IMAGE
                 | LVIF_PARAM
                 | LVIF_TEXT | LVIF_STATE;
    lv_item.pszText = pszText;
    lv_item.cchTextMax = 1024;
    lv_item.iSubItem = subitem;
    if(ListView_GetItem(handle, &lv_item)) {
        EXTEND(SP, 6);
        XST_mPV(0, "-text");
        XST_mPV(1, lv_item.pszText);
        XST_mPV(2, "-image");
        XST_mIV(3, lv_item.iImage);
        XST_mPV(4, "-state");
        XST_mIV(5, lv_item.state);
        XSRETURN(6);
    } else {
        XSRETURN_UNDEF;
    }



And finally, to make function work with windows owned by other process:


void
GetItem(handle,item, subitem=0)
    HWND handle
    int item
    int subitem
ALIAS:
    Win32::GUI::ListView::ItemInfo = 1
PREINIT:
    LV_ITEM lv_item;
    char pszText[1024];
PPCODE:
->    int thisproc = GetCurrentProcessId();
->    int calledproc = 0;
->    GetWindowThreadProcessId( handle, &calledproc );
    ZeroMemory(&lv_item, sizeof(LV_ITEM));
    lv_item.iItem = item;
    lv_item.mask = LVIF_IMAGE
                 | LVIF_PARAM
                 | LVIF_TEXT | LVIF_STATE;
    lv_item.pszText = pszText;
    lv_item.cchTextMax = 1024;
    lv_item.iSubItem = subitem;
->    if( thisproc != calledproc ){
->        //Allocate memory in called process address space and copy lv_item 
there
-> ListView_GetItem( handle, pointer to buffer in other process address space);
->          //Copy results back to lvitem
->          //Free memory in called process address space
->    }else{ //Standard way for calling window belonging to this process
->          ListView_GetItem(handle, &lv_item);
->    }
      {
        EXTEND(SP, 6);
        XST_mPV(0, "-text");
        XST_mPV(1, lv_item.pszText);
        XST_mPV(2, "-image");
        XST_mIV(3, lv_item.iImage);
        XST_mPV(4, "-state");
        XST_mIV(5, lv_item.state);
        XSRETURN(6);
    } else {
        XSRETURN_UNDEF;
    }



I am curious what do you think about it.


--
Piotr Kaluski

"It is the commitment of the individuals to excellence,
their mastery of the tools of their crafts, and their
ability to work together that makes the product, not rules."
("Testing Computer Software" by Cem Kaner, Jack Falk, Hung Quoc Nguyen)



Reply via email to