Пример #1
2
static void test_customdraw(void) {
    static struct {
        LRESULT FirstReturnValue;
        int ExpectedCalls;
    } expectedResults[] = {
        /* Valid notification responses */
        {CDRF_DODEFAULT, TEST_CDDS_PREPAINT},
        {CDRF_SKIPDEFAULT, TEST_CDDS_PREPAINT},
        {CDRF_NOTIFYPOSTPAINT, TEST_CDDS_PREPAINT | TEST_CDDS_POSTPAINT},

        /* Invalid notification responses */
        {CDRF_NOTIFYITEMDRAW, TEST_CDDS_PREPAINT},
        {CDRF_NOTIFYPOSTERASE, TEST_CDDS_PREPAINT},
        {CDRF_NEWFONT, TEST_CDDS_PREPAINT}
    };

   DWORD       iterationNumber;
   WNDCLASSA wc;
   LRESULT   lResult;

   /* Create a class to use the custom draw wndproc */
   wc.style = CS_HREDRAW | CS_VREDRAW;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = 0;
   wc.hInstance = GetModuleHandleA(NULL);
   wc.hIcon = NULL;
   wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
   wc.hbrBackground = GetSysColorBrush(COLOR_WINDOW);
   wc.lpszMenuName = NULL;
   wc.lpszClassName = "CustomDrawClass";
   wc.lpfnWndProc = CustomDrawWndProc;
   RegisterClass(&wc);

   for (iterationNumber = 0;
        iterationNumber < sizeof(expectedResults)/sizeof(expectedResults[0]);
        iterationNumber++) {

       HWND parent, hwndTip;
       RECT rect;
       TOOLINFO toolInfo = { 0 };

       /* Create a main window */
       parent = CreateWindowEx(0, "CustomDrawClass", NULL,
                               WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |
                               WS_MAXIMIZEBOX | WS_VISIBLE,
                               50, 50,
                               300, 300,
                               NULL, NULL, NULL, 0);
       ok(parent != NULL, "Creation of main window failed\n");

       /* Make it show */
       ShowWindow(parent, SW_SHOWNORMAL);
       flush_events(100);

       /* Create Tooltip */
       hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS,
                                NULL, TTS_NOPREFIX | TTS_ALWAYSTIP,
                                CW_USEDEFAULT, CW_USEDEFAULT,
                                CW_USEDEFAULT, CW_USEDEFAULT,
                                parent, NULL, GetModuleHandleA(NULL), 0);
       ok(hwndTip != NULL, "Creation of tooltip window failed\n");

       /* Set up parms for the wndproc to handle */
       CD_Stages = 0;
       CD_Result = expectedResults[iterationNumber].FirstReturnValue;
       g_hwnd    = hwndTip;

       /* Make it topmost, as per the MSDN */
       SetWindowPos(hwndTip, HWND_TOPMOST, 0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

       /* Create a tool */
       toolInfo.cbSize = TTTOOLINFO_V1_SIZE;
       toolInfo.hwnd = parent;
       toolInfo.hinst = GetModuleHandleA(NULL);
       toolInfo.uFlags = TTF_SUBCLASS;
       toolInfo.uId = 0x1234ABCD;
       toolInfo.lpszText = (LPSTR)"This is a test tooltip";
       toolInfo.lParam = 0xdeadbeef;
       GetClientRect (parent, &toolInfo.rect);
       lResult = SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
       ok(lResult, "Adding the tool to the tooltip failed\n");

       /* Make tooltip appear quickly */
       SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_INITIAL, MAKELPARAM(1,0));

       /* Put cursor inside window, tooltip will appear immediately */
       GetWindowRect( parent, &rect );
       SetCursorPos( (rect.left + rect.right) / 2, (rect.top + rect.bottom) / 2 );
       flush_events(200);

       if (CD_Stages)
       {
           /* Check CustomDraw results */
           ok(CD_Stages == expectedResults[iterationNumber].ExpectedCalls ||
              broken(CD_Stages == (expectedResults[iterationNumber].ExpectedCalls & ~TEST_CDDS_POSTPAINT)), /* nt4 */
              "CustomDraw run %d stages %x, expected %x\n", iterationNumber, CD_Stages,
              expectedResults[iterationNumber].ExpectedCalls);
       }

       /* Clean up */
       DestroyWindow(hwndTip);
       DestroyWindow(parent);
   }


}
Пример #2
0
static void test_PSM_ADDPAGE(void)
{
    HPROPSHEETPAGE hpsp[5];
    PROPSHEETPAGEA psp;
    PROPSHEETHEADERA psh;
    HWND hdlg, tab;
    BOOL ret;
    DWORD r;

    memset(&psp, 0, sizeof(psp));
    psp.dwSize = sizeof(psp);
    psp.dwFlags = 0;
    psp.hInstance = GetModuleHandleA(NULL);
    U(psp).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_MESSAGE_TEST);
    U2(psp).pszIcon = NULL;
    psp.pfnDlgProc = page_dlg_proc_messages;
    psp.lParam = 0;

    /* two page with the same data */
    hpsp[0] = CreatePropertySheetPageA(&psp);
    hpsp[1] = CreatePropertySheetPageA(&psp);
    hpsp[2] = CreatePropertySheetPageA(&psp);

    U(psp).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_ERROR);
    hpsp[3] = CreatePropertySheetPageA(&psp);

    psp.dwFlags = PSP_PREMATURE;
    hpsp[4] = CreatePropertySheetPageA(&psp);

    memset(&psh, 0, sizeof(psh));
    psh.dwSize = PROPSHEETHEADERA_V1_SIZE;
    psh.dwFlags = PSH_MODELESS;
    psh.pszCaption = "test caption";
    psh.nPages = 1;
    psh.hwndParent = GetDesktopWindow();
    U3(psh).phpage = hpsp;

    hdlg = (HWND)PropertySheetA(&psh);
    ok(hdlg != INVALID_HANDLE_VALUE, "got invalid handle %p\n", hdlg);

    /* add pages one by one */
    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, (LPARAM)hpsp[1]);
    ok(ret == TRUE, "got %d\n", ret);

    /* try with null and invalid value */
    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, 0);
    ok(ret == FALSE, "got %d\n", ret);

if (0)
{
    /* crashes on native */
    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, (LPARAM)INVALID_HANDLE_VALUE);
}
    /* check item count */
    tab = (HWND)SendMessageA(hdlg, PSM_GETTABCONTROL, 0, 0);

    r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
    ok(r == 2, "got %d\n", r);

    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, (LPARAM)hpsp[2]);
    ok(ret == TRUE, "got %d\n", ret);

    r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
    ok(r == 3, "got %d\n", r);

    /* add property sheet page that can't be created */
    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, (LPARAM)hpsp[3]);
    ok(ret == TRUE, "got %d\n", ret);

    r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
    ok(r == 4, "got %d\n", r);

    /* select page that can't be created */
    ret = SendMessageA(hdlg, PSM_SETCURSEL, 3, 1);
    ok(ret == TRUE, "got %d\n", ret);

    r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
    ok(r == 3, "got %d\n", r);

    /* test PSP_PREMATURE flag with incorrect property sheet page */
    ret = SendMessageA(hdlg, PSM_ADDPAGE, 0, (LPARAM)hpsp[4]);
    ok(ret == FALSE, "got %d\n", ret);

    r = SendMessageA(tab, TCM_GETITEMCOUNT, 0, 0);
    ok(r == 3, "got %d\n", r);

    DestroyPropertySheetPage(hpsp[4]);
    DestroyWindow(hdlg);
}
Пример #3
0
static void test_custom_default_button(void)
{
    HWND hdlg, page;
    PROPSHEETPAGEA psp[1];
    PROPSHEETHEADERA psh;
    MSG msg;
    LRESULT result;

    psp[0].dwSize = sizeof (PROPSHEETPAGEA);
    psp[0].dwFlags = PSP_USETITLE;
    psp[0].hInstance = GetModuleHandleA(NULL);
    U(psp[0]).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_WITH_CUSTOM_DEFAULT_BUTTON);
    U2(psp[0]).pszIcon = NULL;
    psp[0].pfnDlgProc = page_with_custom_default_button_dlg_proc;
    psp[0].pszTitle = "Page1";
    psp[0].lParam = 0;

    psh.dwSize = PROPSHEETHEADERA_V1_SIZE;
    psh.dwFlags = PSH_PROPSHEETPAGE | PSH_MODELESS;
    psh.hwndParent = GetDesktopWindow();
    psh.hInstance = GetModuleHandleA(NULL);
    U(psh).pszIcon = NULL;
    psh.pszCaption =  "PropertySheet1";
    psh.nPages = 1;
    U3(psh).ppsp = psp;
    U2(psh).nStartPage = 0;

    /* The goal of the test is to make sure that the Add button is pressed
     * when the ENTER key is pressed and a different control, a combobox,
     * has the keyboard focus. */
    add_button_has_been_pressed = FALSE;

    /* Create the modeless property sheet. */
    hdlg = (HWND)PropertySheetA(&psh);
    ok(hdlg != INVALID_HANDLE_VALUE, "Cannot create the property sheet\n");

    /* Set the Add button as the default button. */
    SendMessageA(hdlg, DM_SETDEFID, (WPARAM)IDC_PS_PUSHBUTTON1, 0);

    /* Make sure the default button is the Add button. */
    result = SendMessageA(hdlg, DM_GETDEFID, 0, 0);
    ok(DC_HASDEFID == HIWORD(result), "The property sheet does not have a default button\n");
    ok(IDC_PS_PUSHBUTTON1 == LOWORD(result), "The default button is not the Add button\n");

    /* At this point, the combobox should have keyboard focus, so we press ENTER.
     * Pull the lever, Kronk! */
    page = (HWND)SendMessageW(hdlg, PSM_GETCURRENTPAGEHWND, 0, 0);
    PostMessageW(GetDlgItem(page, IDC_PS_COMBO1), WM_KEYDOWN, VK_RETURN, 0);

    /* Process all the messages in the queue for this thread. */
    while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
    {
        /* (!PropSheet_IsDialogMessage(hdlg, &msg)) */
        if (!((BOOL)SendMessageA(hdlg, PSM_ISDIALOGMESSAGE, 0, (LPARAM)&msg)))
        {
            TranslateMessage(&msg);
            DispatchMessageA(&msg);
        }
    }

    ok(add_button_has_been_pressed, "The Add button has not been pressed!\n");

    DestroyWindow(hdlg);
}
Пример #4
0
static void test_wiznavigation(void)
{
    HPROPSHEETPAGE hpsp[4];
    PROPSHEETPAGEA psp[4];
    PROPSHEETHEADERA psh;
    HWND hdlg, control;
    LONG_PTR controlID;
    DWORD style;
    LRESULT defidres;
    BOOL hwndtoindex_supported = TRUE;
    const INT nextID = 12324;
    const INT backID = 12323;
    HHOOK hook;

    /* set up a hook proc in order to subclass the main dialog early on */
    hook = SetWindowsHookExW( WH_CBT, hook_proc, NULL, GetCurrentThreadId() );

    /* create the property sheet pages */
    memset(psp, 0, sizeof(PROPSHEETPAGEA) * 4);

    psp[0].dwSize = sizeof(PROPSHEETPAGEA);
    psp[0].hInstance = GetModuleHandleA(NULL);
    U(psp[0]).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_INTRO);
    psp[0].pfnDlgProc = nav_page_proc;
    hpsp[0] = CreatePropertySheetPageA(&psp[0]);

    psp[1].dwSize = sizeof(PROPSHEETPAGEA);
    psp[1].hInstance = GetModuleHandleA(NULL);
    U(psp[1]).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_EDIT);
    psp[1].pfnDlgProc = nav_page_proc;
    hpsp[1] = CreatePropertySheetPageA(&psp[1]);

    psp[2].dwSize = sizeof(PROPSHEETPAGEA);
    psp[2].hInstance = GetModuleHandleA(NULL);
    U(psp[2]).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_RADIO);
    psp[2].pfnDlgProc = nav_page_proc;
    hpsp[2] = CreatePropertySheetPageA(&psp[2]);

    psp[3].dwSize = sizeof(PROPSHEETPAGEA);
    psp[3].hInstance = GetModuleHandleA(NULL);
    U(psp[3]).pszTemplate = (LPCSTR)MAKEINTRESOURCE(IDD_PROP_PAGE_EXIT);
    psp[3].pfnDlgProc = nav_page_proc;
    hpsp[3] = CreatePropertySheetPageA(&psp[3]);

    /* set up the property sheet dialog */
    memset(&psh, 0, sizeof(psh));
    psh.dwSize = PROPSHEETHEADERA_V1_SIZE;
    psh.dwFlags = PSH_MODELESS | PSH_WIZARD;
    psh.pszCaption = "A Wizard";
    psh.nPages = 4;
    psh.hwndParent = GetDesktopWindow();
    U3(psh).phpage = hpsp;
    hdlg = (HWND)PropertySheetA(&psh);
    ok(hdlg != INVALID_HANDLE_VALUE, "got invalid handle %p\n", hdlg);

    ok(active_page == 0, "Active page should be 0. Is: %d\n", active_page);

    style = GetWindowLongA(hdlg, GWL_STYLE) & ~(DS_CONTEXTHELP|WS_SYSMENU);
    ok(style == (WS_POPUP|WS_VISIBLE|WS_CLIPSIBLINGS|WS_CAPTION|
                 DS_MODALFRAME|DS_SETFONT|DS_3DLOOK),
       "got unexpected style: %x\n", style);

    control = GetFocus();
    controlID = GetWindowLongPtrA(control, GWLP_ID);
    ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);

    /* simulate pressing the Next button */
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
    if (!active_page) hwndtoindex_supported = FALSE;
    if (hwndtoindex_supported)
        ok(active_page == 1, "Active page should be 1 after pressing Next. Is: %d\n", active_page);

    control = GetFocus();
    controlID = GetWindowLongPtrA(control, GWLP_ID);
    ok(controlID == IDC_PS_EDIT1, "Focus should be set to the first item on the second page. Expected: %d, Found: %ld\n", IDC_PS_EDIT1, controlID);

    defidres = SendMessageA(hdlg, DM_GETDEFID, 0, 0);
    ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));

    /* set the focus to the second edit box on this page */
    SetFocus(GetNextDlgTabItem(hdlg, control, FALSE));

    /* press next again */
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
    if (hwndtoindex_supported)
        ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);

    control = GetFocus();
    controlID = GetWindowLongPtrA(control, GWLP_ID);
    ok(controlID == IDC_PS_RADIO1, "Focus should have been set to item on third page. Expected: %d, Found %ld\n", IDC_PS_RADIO1, controlID);

    /* back button */
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
    if (hwndtoindex_supported)
        ok(active_page == 1, "Active page should be 1 after pressing Back. Is: %d\n", active_page);

    control = GetFocus();
    controlID = GetWindowLongPtrA(control, GWLP_ID);
    ok(controlID == IDC_PS_EDIT1, "Focus should have been set to the first item on second page. Expected: %d, Found %ld\n", IDC_PS_EDIT1, controlID);

    defidres = SendMessageA(hdlg, DM_GETDEFID, 0, 0);
    ok(defidres == MAKELRESULT(backID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", backID, LOWORD(defidres));

    /* press next twice */
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
    if (hwndtoindex_supported)
        ok(active_page == 2, "Active page should be 2 after pressing Next. Is: %d\n", active_page);
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_NEXT, 0);
    if (hwndtoindex_supported)
        ok(active_page == 3, "Active page should be 3 after pressing Next. Is: %d\n", active_page);
    else
        active_page = 3;

    control = GetFocus();
    controlID = GetWindowLongPtrA(control, GWLP_ID);
    ok(controlID == nextID, "Focus should have been set to the Next button. Expected: %d, Found: %ld\n", nextID, controlID);

    /* try to navigate away, but shouldn't be able to */
    SendMessageA(hdlg, PSM_PRESSBUTTON, PSBTN_BACK, 0);
    ok(active_page == 3, "Active page should still be 3 after pressing Back. Is: %d\n", active_page);

    defidres = SendMessageA(hdlg, DM_GETDEFID, 0, 0);
    ok(defidres == MAKELRESULT(nextID, DC_HASDEFID), "Expected default button ID to be %d, is %d\n", nextID, LOWORD(defidres));

    DestroyWindow(hdlg);
    UnhookWindowsHookEx( hook );
}
Пример #5
0
int Inject(HANDLE hProcess, const char *dll_dir, const char *dll_fn, const char *func_name, const void *param, const size_t param_size)
{
	// String constants
	const char *injectError1Format =
		"Could not inject %s.\n"
		"\n"
		"If you're running Windows Vista or 7, make sure that you have installed the KB2533623 update:\n"
		"\n"
		"\thttp://support.microsoft.com/kb/2533623/";
	const char *injectError2Format = "Could not load the function: %s";

//------------------------------------------//
// Function variables.                      //
//------------------------------------------//

	// Main DLL we will need to load
	HMODULE kernel32 = GetModuleHandleA("kernel32.dll");

	// Main functions we will need to import.
	// If [dll_fn] is absolute, LoadLibraryEx() with the LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR
	// flag is used to guarantee that the injected DLL and its dependencies really
	// are only loaded from the given directory. Otherwise, LoadLibrary() may load
	// a possible other DLL with the same name from the directory of [hProcess].
	FARPROC getcurrentdirectory = GetProcAddress(kernel32, "GetCurrentDirectoryW");
	FARPROC setcurrentdirectory = GetProcAddress(kernel32, "SetCurrentDirectoryW");
	FARPROC loadlibrary = GetProcAddress(kernel32, "LoadLibraryW");
	FARPROC loadlibraryex = GetProcAddress(kernel32, "LoadLibraryExW");
	FARPROC getprocaddress = GetProcAddress(kernel32, "GetProcAddress");
	FARPROC exitthread = GetProcAddress(kernel32, "ExitThread");
	FARPROC freelibraryandexitthread = GetProcAddress(kernel32, "FreeLibraryAndExitThread");
	int have_kb2269637 = GetProcAddress(kernel32, "SetDefaultDllDirectories") != 0;

	// The workspace we will build the codecave on locally.
	// workspaceSize gets incremented with the final length of the error strings.
	size_t workspaceSize = 2048;
	LPBYTE workspace = NULL;
	LPBYTE p = NULL;

	// The memory in the process we write to
	LPBYTE codecaveAddress = NULL;

	// Strings we have to write into the process
	size_t injectError1_len = _scprintf(injectError1Format, dll_fn) + 1;
	size_t injectError2_len = _scprintf(injectError2Format, func_name) + 1;

	char *injectError0 = "Error";
	VLA(char, injectError1, injectError1_len);
	VLA(char, injectError2, injectError2_len);
	char *user32Name = "user32.dll";
	char *msgboxName = "MessageBoxW";

	// Placeholder addresses to use the strings
	LPBYTE user32NameAddr = 0;
	LPBYTE user32Addr = 0;
	LPBYTE msgboxNameAddr = 0;
	LPBYTE msgboxAddr = 0;
	LPBYTE dllAddr = 0;
	LPBYTE dllDirAddr = 0;
	LPBYTE dllNameAddr = 0;
	LPBYTE funcNameAddr = 0;
	LPBYTE funcParamAddr = 0;
	LPBYTE error0Addr = 0;
	LPBYTE error1Addr = 0;
	LPBYTE error2Addr = 0;

	// Where the codecave execution should begin at
	LPTHREAD_START_ROUTINE codecaveExecAddr = 0;

	// Handle to the thread we create in the process
	HANDLE hThread = NULL;

	// Old protection on page we are writing to in the process and the bytes written
	DWORD oldProtect = 0;
	DWORD byte_ret = 0;

	// Return code of injection function
	DWORD injRet;

//------------------------------------------//
// Variable initialization.                 //
//------------------------------------------//

// This section will cause compiler warnings on VS8,
// you can upgrade the functions or ignore them

	// Build error messages
	sprintf(injectError1, injectError1Format, dll_fn);
	sprintf(injectError2, injectError2Format, func_name);

	workspaceSize += (
		strlen(dll_dir) + 1 + strlen(dll_fn) + 1 + strlen(func_name) + 1 +
		param_size + strlen(injectError1) + 1 + strlen(injectError2) + 1
	) * sizeof(wchar_t);

	// Create the workspace
	workspace = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, workspaceSize);
	p = workspace;

	// Allocate space for the codecave in the process
	codecaveAddress = (LPBYTE)VirtualAllocEx(hProcess, 0, workspaceSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

// Note there is no error checking done above for any functions that return a pointer/handle.
// I could have added them, but it'd just add more messiness to the code and not provide any real
// benefit. It's up to you though in your final code if you want it there or not.

//------------------------------------------//
// Data and string writing.                 //
//------------------------------------------//

	// Reserve space for the user32 dll address, the MessageBox address,
	// and the address of the injected DLL's module.
	user32Addr = (p - workspace) + codecaveAddress;
	p += sizeof(LPBYTE);

	msgboxAddr = (p - workspace) + codecaveAddress;
	p += sizeof(LPBYTE);

	dllAddr = (p - workspace) + codecaveAddress;
	p += sizeof(LPBYTE);

	// User32 Dll Name
	user32NameAddr = (p - workspace) + codecaveAddress;
	p = StringToUTF16_advance_dst(p, user32Name);

	// MessageBox name
	msgboxNameAddr = (p - workspace) + codecaveAddress;
	p = memcpy_advance_dst(p, msgboxName, strlen(msgboxName) + 1);

	// Directory name
	if(dll_dir) {
		dllDirAddr = (p - workspace) + codecaveAddress;
		p = StringToUTF16_advance_dst(p, dll_dir);
	}

	// Dll Name
	dllNameAddr = (p - workspace) + codecaveAddress;
	p = StringToUTF16_advance_dst(p, dll_fn);

	// Function Name
	funcNameAddr = (p - workspace) + codecaveAddress;
	p = memcpy_advance_dst(p, func_name, strlen(func_name) + 1);

	// Function Parameter
	funcParamAddr = (p - workspace) + codecaveAddress;
	p = memcpy_advance_dst(p, param, param_size);

	// Error Message 1
	error0Addr = (p - workspace) + codecaveAddress;
	p = StringToUTF16_advance_dst(p, injectError0);

	// Error Message 2
	error1Addr = (p - workspace) + codecaveAddress;
	p = StringToUTF16_advance_dst(p, injectError1);

	// Error Message 3
	error2Addr = (p - workspace) + codecaveAddress;
	p = StringToUTF16_advance_dst(p, injectError2);

	// Pad a few INT3s after string data is written for seperation
	*p++ = 0xCC;
	*p++ = 0xCC;
	*p++ = 0xCC;

	// Store where the codecave execution should begin
	codecaveExecAddr = (LPTHREAD_START_ROUTINE)((p - workspace) + codecaveAddress);

// For debugging - infinite loop, attach onto process and step over
	//*p++ = 0xEB;
	//*p++ = 0xFE;

//------------------------------------------//
// User32.dll loading.                      //
//------------------------------------------//

// User32 DLL Loading
	// PUSH 0x00000000 - Push the address of the DLL name to use in LoadLibrary
	*p++ = 0x68;
	p = ptrcpy_advance_dst(p, user32NameAddr);

	// MOV EAX, ADDRESS - Move the address of LoadLibrary into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, loadlibrary);

	// CALL EAX - Call LoadLibrary
	*p++ = 0xFF;
	*p++ = 0xD0;

// MessageBox Loading
	// PUSH 0x000000 - Push the address of the function name to load
	*p++ = 0x68;
	p = ptrcpy_advance_dst(p, msgboxNameAddr);

	// Push EAX, module to use in GetProcAddress
	*p++ = 0x50;

	// MOV EAX, ADDRESS - Move the address of GetProcAddress into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, getprocaddress);

	// CALL EAX - Call GetProcAddress
	*p++ = 0xFF;
	*p++ = 0xD0;

	// MOV [ADDRESS], EAX - Save the address to our variable
	*p++ = 0xA3;
	p = ptrcpy_advance_dst(p, msgboxAddr);

//------------------------------------------//
// Injected dll loading.                    //
//------------------------------------------//

/*
	// This is the way the following assembly code would look like in C/C++

	// In case the injected DLL depends on other DLLs,
	// we need to change the current directory to the one given as parameter
	if(dll_dir) {
		size_t cur_dir_len = GetCurrentDirectory(0, NULL) + 1;
		VLA(wchar_t, cur_dir, cur_dir_len);
		GetCurrentDirectory(cur_dir, cur_dir_len);
		SetCurrentDirectory(dll_dir);
	}

	// Load the injected DLL into this process
	HMODULE h = LoadLibraryEx(dll_fn, NULL, LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR);
	if(!h) {
		MessageBox(0, injectError1, "Error", MB_ICONERROR);
		ExitThread(1);
	}

	if(dll_dir) {
		SetCurrentDirectory(cur_dir);
	}

	// Get the address of the export function
	FARPROC p = GetProcAddress(h, func_name);
	if(!p) {
		MessageBox(0, injectError2, "Error", MB_ICONERROR);
		FreeLibraryAndExitThread(h, 2);
	}

	// So we do not need a function pointer interface
	__asm call p

	// Exit the thread so the loader continues
	ExitThread(0);
*/

// DLL Loading

	if(dllDirAddr) {
		// Registers:

		// ebp: Base stack frame
		// esi: GetCurrentDirectory / SetCurrentDirectory
		// ebx: Current directory of process (on stack)
		// ecx: byte length of string at ebx

		// mov ebp, esp - Save stack frame
		*p++ = 0x89;
		*p++ = 0xe5;

		// Get length for current directory

		// push 0
		// push 0
		*p++ = 0x6a;
		*p++ = 0x00;
		*p++ = 0x6a;
		*p++ = 0x00;
		// mov esi, GetCurrentDirectory
		*p++ = 0xbe;
		p = ptrcpy_advance_dst(p, getcurrentdirectory);

		// call esi
		*p++ = 0xFF;
		*p++ = 0xD6;

		/// Calculate byte size of directory buffer.
		/// Also do some poor man's DWORD boundary alignment
		/// in order to not fuck up the stack

		// mov ecx, eax
		// shl ecx, 1
		// and ecx, fffffff8
		// add ecx, 4

		*p++ = 0x89;
		*p++ = 0xc1;
		*p++ = 0xd1;
		*p++ = 0xe1;
		*p++ = 0x83;
		*p++ = 0xe1;
		*p++ = 0xf8;
		*p++ = 0x83;
		*p++ = 0xc1;
		*p++ = 0x04;

		/// "Allocate" ecx bytes on stack and store buffer pointer to ebx

		// sub esp, ecx
		// mov ebx, esp

		*p++ = 0x29;
		*p++ = 0xcc;
		*p++ = 0x89;
		*p++ = 0xe3;

		/// Call GetCurrentDirectory
		// push ebx
		// push eax
		// call esi
		*p++ = 0x53;
		*p++ = 0x50;
		*p++ = 0xff;
		*p++ = 0xd6;

		/// PUSH 0x00000000 - Push the address of our directory
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, dllDirAddr);

		// mov esi, SetCurrentDirectory
		*p++ = 0xbe;
		p = ptrcpy_advance_dst(p, setcurrentdirectory);

		// call esi
		*p++ = 0xFF;
		*p++ = 0xD6;
	}

	if(PathIsRelativeA(dll_fn) || !have_kb2269637) {
		// PUSH 0x00 (dwFlags = 0)
		*p++ = 0x6a;
		*p++ = 0x00;
	} else {
		// PUSH 0x00000900 (dwFlags = LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32)
		*p++ = 0x68;
		*p++ = 0x00;
		*p++ = 0x09;
		*p++ = 0x00;
		*p++ = 0x00;
	}

	// PUSH 0x00 (hFile = NULL)
	*p++ = 0x6a;
	*p++ = 0x00;

	// PUSH 0x00000000 - Push the address of the DLL name to use in LoadLibraryEx
	*p++ = 0x68;
	p = ptrcpy_advance_dst(p, dllNameAddr);

	// MOV EAX, ADDRESS - Move the address of LoadLibraryEx into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, loadlibraryex);

	// CALL EAX - Call LoadLibraryEx
	*p++ = 0xFF;
	*p++ = 0xD0;

	// mov edi, eax - Save return value
	*p++ = 0x89;
	*p++ = 0xc7;

	if(dllDirAddr) {
		/// Reset directory to the original one of the process
		// push ebx
		// call esi
		*p++ = 0x53;
		*p++ = 0xFF;
		*p++ = 0xD6;

		/// Reset stack frame
		// mov esp, ebp
		*p++ = 0x89;
		*p++ = 0xec;
	}

// Error Checking
	// CMP EDI, 0
	*p++ = 0x83;
	*p++ = 0xFF;
	*p++ = 0x00;

// JNZ EIP + 0x1E to skip over eror code
	*p++ = 0x75;
	*p++ = 0x1E;

// Error Code 1
	// MessageBox
		// PUSH 0x10 (MB_ICONHAND)
		*p++ = 0x6A;
		*p++ = 0x10;

		// PUSH 0x000000 - Push the address of the MessageBox title
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, error0Addr);

		// PUSH 0x000000 - Push the address of the MessageBox message
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, error1Addr);

		// Push 0
		*p++ = 0x6A;
		*p++ = 0x00;

		// MOV EAX, [ADDRESS] - Move the address of MessageBox into EAX
		*p++ = 0xA1;
		p = ptrcpy_advance_dst(p, msgboxAddr);

		// CALL EAX - Call MessageBoxW
		*p++ = 0xFF;
		*p++ = 0xD0;

	// ExitThread
		// PUSH 1
		*p++ = 0x6A;
		*p++ = 0x01;

		// MOV EAX, ADDRESS - Move the address of ExitThread into EAX
		*p++ = 0xB8;
		p = ptrcpy_advance_dst(p, exitthread);

		// CALL EAX - Call ExitThread
		*p++ = 0xFF;
		*p++ = 0xD0;

//	Now we have the address of the injected DLL, so save the handle

	// MOV [ADDRESS], EAX - Save the address to our variable
	*p++ = 0x89;
	*p++ = 0x3D;
	p = ptrcpy_advance_dst(p, dllAddr);

// Load the initilize function from it

	// PUSH 0x000000 - Push the address of the function name to load
	*p++ = 0x68;
	p = ptrcpy_advance_dst(p, funcNameAddr);

	// Push EDI - module to use in GetProcAddress
	*p++ = 0x57;

	// MOV EAX, ADDRESS - Move the address of GetProcAddress into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, getprocaddress);

	// CALL EAX - Call GetProcAddress
	*p++ = 0xFF;
	*p++ = 0xD0;

// Error Checking
	// CMP EAX, 0
	*p++ = 0x83;
	*p++ = 0xF8;
	*p++ = 0x00;

// JNZ EIP + 0x23 to skip eror code
	*p++ = 0x75;
	*p++ = 0x23;

// Error Code 2
	// MessageBox
		// PUSH 0x10 (MB_ICONHAND)
		*p++ = 0x6A;
		*p++ = 0x10;

		// PUSH 0x000000 - Push the address of the MessageBox title
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, error0Addr);

		// PUSH 0x000000 - Push the address of the MessageBox message
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, error2Addr);

		// Push 0
		*p++ = 0x6A;
		*p++ = 0x00;

		// MOV EAX, ADDRESS - Move the address of MessageBox into EAX
		*p++ = 0xA1;
		p = ptrcpy_advance_dst(p, msgboxAddr);

		// CALL EAX - Call MessageBoxA
		*p++ = 0xFF;
		*p++ = 0xD0;

	// FreeLibraryAndExitThread
		// PUSH 2
		*p++ = 0x6A;
		*p++ = 0x02;

		// PUSH 0x000000 - Push the injected DLL's module handle
		*p++ = 0x68;
		p = ptrcpy_advance_dst(p, dllAddr);

		// MOV EAX, ADDRESS - Move the address of FreeLibraryAndExitThread into EAX
		*p++ = 0xB8;
		p = ptrcpy_advance_dst(p, freelibraryandexitthread);

		// CALL EAX - Call ExitThread function
		*p++ = 0xFF;
		*p++ = 0xD0;

	// PUSH 0x000000 - Push the address of the function parameter
	*p++ = 0x68;
	p = ptrcpy_advance_dst(p, funcParamAddr);

	// CALL EAX - Call [func_name]
	*p++ = 0xFF;
	*p++ = 0xD0;

	// If we get here, [func_name] has been called,
	// so it's time to close this thread and optionally unload the DLL.

//------------------------------------------//
// Exiting from the injected dll.           //
//------------------------------------------//

// Call ExitThread to leave the DLL loaded
#if 1
	// PUSH 0 (exit code)
	*p++ = 0x6A;
	*p++ = 0x00;

	// MOV EAX, ADDRESS - Move the address of ExitThread into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, exitthread);

	// CALL EAX - Call ExitThread
	*p++ = 0xFF;
	*p++ = 0xD0;
#endif

// Call FreeLibraryAndExitThread to unload DLL
#if 0
	// Push 0 (exit code)
	*p++ = 0x6A;
	*p++ = 0x00;

	// PUSH [0x000000] - Push the address of the DLL module to unload
	*p++ = 0xFF;
	*p++ = 0x35;
	p = ptrcpy_advance_dst(p, dllAddr);

	// MOV EAX, ADDRESS - Move the address of FreeLibraryAndExitThread into EAX
	*p++ = 0xB8;
	p = ptrcpy_advance_dst(p, freelibraryandexitthread);

	// CALL EAX - Call FreeLibraryAndExitThread
	*p++ = 0xFF;
	*p++ = 0xD0;
#endif

//------------------------------------------//
// Code injection and cleanup.              //
//------------------------------------------//

	// Change page protection so we can write executable code
	VirtualProtectEx(hProcess, codecaveAddress, p - workspace, PAGE_EXECUTE_READWRITE, &oldProtect);

	// Write out the patch
	WriteProcessMemory(hProcess, codecaveAddress, workspace, p - workspace, &byte_ret);

	// Restore page protection
	VirtualProtectEx(hProcess, codecaveAddress, p - workspace, oldProtect, &oldProtect);

	// Make sure our changes are written right away
	FlushInstructionCache(hProcess, codecaveAddress, p - workspace);

	// Free the workspace memory
	HeapFree(GetProcessHeap(), 0, workspace);

	// Execute the thread now and wait for it to exit, note we execute where the code starts, and not the codecave start
	// (since we wrote strings at the start of the codecave)
	hThread = CreateRemoteThread(hProcess, NULL, 0, codecaveExecAddr, 0, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);

	GetExitCodeThread(hThread, &injRet);
	CloseHandle(hThread);

	// Free the memory in the process that we allocated
	VirtualFreeEx(hProcess, codecaveAddress, 0, MEM_RELEASE);

	VLA_FREE(injectError1);
	VLA_FREE(injectError2);
	return injRet;
}
Пример #6
0
inline void *get_module_handle(const char *name)
{  return GetModuleHandleA(name); }
Пример #7
0
HWND myGetConsoleWindow()
{
	HWND hConWnd = NULL;

	// If we are in ConEmuHk than gfGetRealConsoleWindow may be set
	if (gfGetRealConsoleWindow)
	{
		hConWnd = gfGetRealConsoleWindow();
		// If the function pointer was set - it must be proper function
		_ASSERTEX(hConWnd==NULL || isConsoleWindow(hConWnd));
		return hConWnd;
	}

	_ASSERTE(ghWorkingModule != 0);
	HMODULE hOurModule = (HMODULE)(DWORD_PTR)ghWorkingModule;

	if (!hConWnd)
	{
		if (!hkFunc.isConEmuHk())
		{
			// Must be already called, but JIC
			hkFunc.Init(L"Unknown", hOurModule);
		}

		hConWnd = GetConsoleWindow();
		// Current process may be GUI and have no console at all
		if (!hConWnd)
			return NULL;

		// RealConsole handle is stored in the Window DATA
		if (!hkFunc.isConEmuHk())
		{
			#ifdef _DEBUG
			wchar_t sClass[64] = L""; GetClassName(hConWnd, sClass, countof(sClass));
			#endif

			// Regardless of GetClassName result, it may be VirtualConsoleClass
			HWND h = (HWND)GetWindowLongPtr(hConWnd, 0);
			if (h && IsWindow(h) && isConsoleWindow(h))
			{
				hConWnd = h;
			}
		}
	}

	return hConWnd;

#if 0
	// Смысла звать GetProcAddress для "GetConsoleWindow" мало, все равно хукается
	typedef HWND (APIENTRY *FGetConsoleWindow)();
	static FGetConsoleWindow fGetConsoleWindow = NULL;

	if (!fGetConsoleWindow)
	{
		HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");

		if (hKernel32)
		{
			fGetConsoleWindow = (FGetConsoleWindow)GetProcAddress(hKernel32, "GetConsoleWindow");
		}
	}

	if (fGetConsoleWindow)
		hConWnd = fGetConsoleWindow();

	return hConWnd;
#endif
}
Пример #8
0
static void test_ttm_gettoolinfo(void)
{
    TTTOOLINFOA ti;
    TTTOOLINFOW tiW;
    HWND hwnd;
    DWORD r;

    hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
                           10, 10, 300, 100,
                           NULL, NULL, NULL, 0);

    ti.cbSize = TTTOOLINFOA_V2_SIZE;
    ti.hwnd = NULL;
    ti.hinst = GetModuleHandleA(NULL);
    ti.uFlags = 0;
    ti.uId = 0x1234ABCD;
    ti.lpszText = NULL;
    ti.lParam = 0x1abe11ed;
    GetClientRect(hwnd, &ti.rect);
    r = SendMessageA(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
    ok(r, "Adding the tool to the tooltip failed\n");

    ti.cbSize = TTTOOLINFOA_V2_SIZE;
    ti.lParam = 0xaaaaaaaa;
    r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
    ok(r, "Getting tooltip info failed\n");
    ok(0x1abe11ed == ti.lParam ||
       broken(0x1abe11ed != ti.lParam), /* comctl32 < 5.81 */
       "Expected 0x1abe11ed, got %lx\n", ti.lParam);

    tiW.cbSize = TTTOOLINFOW_V2_SIZE;
    tiW.hwnd = NULL;
    tiW.uId = 0x1234ABCD;
    tiW.lParam = 0xaaaaaaaa;
    r = SendMessageA(hwnd, TTM_GETTOOLINFOW, 0, (LPARAM)&tiW);
    ok(r, "Getting tooltip info failed\n");
    ok(0x1abe11ed == tiW.lParam ||
       broken(0x1abe11ed != tiW.lParam), /* comctl32 < 5.81 */
       "Expected 0x1abe11ed, got %lx\n", tiW.lParam);

    ti.cbSize = TTTOOLINFOA_V2_SIZE;
    ti.uId = 0x1234ABCD;
    ti.lParam = 0x55555555;
    SendMessageA(hwnd, TTM_SETTOOLINFOA, 0, (LPARAM)&ti);

    ti.cbSize = TTTOOLINFOA_V2_SIZE;
    ti.lParam = 0xdeadbeef;
    r = SendMessageA(hwnd, TTM_GETTOOLINFOA, 0, (LPARAM)&ti);
    ok(r, "Getting tooltip info failed\n");
    ok(0x55555555 == ti.lParam ||
       broken(0x55555555 != ti.lParam), /* comctl32 < 5.81 */
       "Expected 0x55555555, got %lx\n", ti.lParam);

    DestroyWindow(hwnd);

    /* 1. test size parameter validation rules (ansi messages) */
    hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
                           10, 10, 300, 100,
                           NULL, NULL, NULL, 0);

    ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
    ti.hwnd = NULL;
    ti.hinst = GetModuleHandleA(NULL);
    ti.uFlags = 0;
    ti.uId = 0x1234ABCD;
    ti.lpszText = NULL;
    ti.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &ti.rect);
    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    ti.cbSize = TTTOOLINFOA_V1_SIZE - 1;
    ti.hwnd = NULL;
    ti.uId = 0x1234ABCD;
    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
    ti.hwnd = NULL;
    ti.hinst = GetModuleHandleA(NULL);
    ti.uFlags = 0;
    ti.uId = 0x1234ABCD;
    ti.lpszText = NULL;
    ti.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &ti.rect);
    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    ti.cbSize = TTTOOLINFOA_V2_SIZE - 1;
    ti.hwnd = NULL;
    ti.uId = 0x1234ABCD;
    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
    ti.hwnd = NULL;
    ti.hinst = GetModuleHandleA(NULL);
    ti.uFlags = 0;
    ti.uId = 0x1234ABCD;
    ti.lpszText = NULL;
    ti.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &ti.rect);
    r = SendMessage(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&ti);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    ti.cbSize = TTTOOLINFOA_V2_SIZE + 1;
    ti.hwnd = NULL;
    ti.uId = 0x1234ABCD;
    SendMessage(hwnd, TTM_DELTOOLA, 0, (LPARAM)&ti);
    r = SendMessage(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    DestroyWindow(hwnd);

    /* 2. test size parameter validation rules (w-messages) */
    hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
                           10, 10, 300, 100,
                           NULL, NULL, NULL, 0);
    if(!hwnd)
    {
        win_skip("CreateWindowExW() not supported. Skipping.\n");
        return;
    }

    tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
    tiW.hwnd = NULL;
    tiW.hinst = GetModuleHandleA(NULL);
    tiW.uFlags = 0;
    tiW.uId = 0x1234ABCD;
    tiW.lpszText = NULL;
    tiW.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &tiW.rect);
    r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    tiW.cbSize = TTTOOLINFOW_V1_SIZE - 1;
    tiW.hwnd = NULL;
    tiW.uId = 0x1234ABCD;
    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
    tiW.hwnd = NULL;
    tiW.hinst = GetModuleHandleA(NULL);
    tiW.uFlags = 0;
    tiW.uId = 0x1234ABCD;
    tiW.lpszText = NULL;
    tiW.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &tiW.rect);
    r = SendMessageW(hwnd, TTM_ADDTOOLW, 0, (LPARAM)&tiW);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    tiW.cbSize = TTTOOLINFOW_V2_SIZE - 1;
    tiW.hwnd = NULL;
    tiW.uId = 0x1234ABCD;
    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
    tiW.hwnd = NULL;
    tiW.hinst = GetModuleHandleA(NULL);
    tiW.uFlags = 0;
    tiW.uId = 0x1234ABCD;
    tiW.lpszText = NULL;
    tiW.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &tiW.rect);
    r = SendMessageW(hwnd, TTM_ADDTOOLA, 0, (LPARAM)&tiW);
    ok(r, "Adding the tool to the tooltip failed\n");
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);
    /* looks like TTM_DELTOOLW doesn't work with invalid size */
    tiW.cbSize = TTTOOLINFOW_V2_SIZE + 1;
    tiW.hwnd = NULL;
    tiW.uId = 0x1234ABCD;
    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(1, r);

    tiW.cbSize = TTTOOLINFOW_V2_SIZE;
    tiW.hwnd = NULL;
    tiW.uId = 0x1234ABCD;
    SendMessageW(hwnd, TTM_DELTOOLW, 0, (LPARAM)&tiW);
    r = SendMessageW(hwnd, TTM_GETTOOLCOUNT, 0, 0);
    expect(0, r);

    DestroyWindow(hwnd);
}
Пример #9
0
static void test_gettext(void)
{
    HWND hwnd, notify;
    TTTOOLINFOA toolinfoA;
    TTTOOLINFOW toolinfoW;
    LRESULT r;
    CHAR bufA[10] = "";
    WCHAR bufW[10] = { 0 };
    static const CHAR testtipA[] = "testtip";

    notify = create_parent_window();
    ok(notify != NULL, "Expected notification window to be created\n");

    /* For bug 14790 - lpszText is NULL */
    hwnd = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
                           10, 10, 300, 100,
                           NULL, NULL, NULL, 0);
    assert(hwnd);

    /* use sizeof(TTTOOLINFOA) instead of TTTOOLINFOA_V1_SIZE so that adding it fails on Win9x */
    /* otherwise it crashes on the NULL lpszText */
    toolinfoA.cbSize = sizeof(TTTOOLINFOA);
    toolinfoA.hwnd = NULL;
    toolinfoA.hinst = GetModuleHandleA(NULL);
    toolinfoA.uFlags = 0;
    toolinfoA.uId = 0x1234ABCD;
    toolinfoA.lpszText = NULL;
    toolinfoA.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &toolinfoA.rect);
    r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
    if (r)
    {
        toolinfoA.hwnd = NULL;
        toolinfoA.uId = 0x1234ABCD;
        toolinfoA.lpszText = bufA;
        SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
        ok(strcmp(toolinfoA.lpszText, "") == 0, "lpszText should be an empty string\n");
    }
    else
    {
        win_skip( "Old comctl32, not testing NULL text\n" );
        DestroyWindow( hwnd );
        return;
    }

    /* add another tool with text */
    toolinfoA.cbSize = sizeof(TTTOOLINFOA);
    toolinfoA.hwnd = NULL;
    toolinfoA.hinst = GetModuleHandleA(NULL);
    toolinfoA.uFlags = 0;
    toolinfoA.uId = 0x1235ABCD;
    strcpy(bufA, testtipA);
    toolinfoA.lpszText = bufA;
    toolinfoA.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &toolinfoA.rect);
    r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
    ok(r, "Adding the tool to the tooltip failed\n");
    if (r)
    {
        DWORD length;

        length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
        ok(length == 0, "Expected 0, got %d\n", length);

        toolinfoA.hwnd = NULL;
        toolinfoA.uId = 0x1235ABCD;
        toolinfoA.lpszText = bufA;
        SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
        ok(strcmp(toolinfoA.lpszText, testtipA) == 0, "lpszText should be an empty string\n");

        length = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0);
        ok(length == 0, "Expected 0, got %d\n", length);
    }

    /* add another with callback text */
    toolinfoA.cbSize = sizeof(TTTOOLINFOA);
    toolinfoA.hwnd = notify;
    toolinfoA.hinst = GetModuleHandleA(NULL);
    toolinfoA.uFlags = 0;
    toolinfoA.uId = 0x1236ABCD;
    toolinfoA.lpszText = LPSTR_TEXTCALLBACKA;
    toolinfoA.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &toolinfoA.rect);
    r = SendMessageA(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoA);
    ok(r, "Adding the tool to the tooltip failed\n");
    if (r)
    {
        toolinfoA.hwnd = notify;
        toolinfoA.uId = 0x1236ABCD;
        toolinfoA.lpszText = bufA;
        SendMessageA(hwnd, TTM_GETTEXTA, 0, (LPARAM)&toolinfoA);
        ok(strcmp(toolinfoA.lpszText, testcallbackA) == 0,
           "lpszText should be an (%s) string\n", testcallbackA);
    }

    DestroyWindow(hwnd);
    DestroyWindow(notify);

    SetLastError(0xdeadbeef);
    hwnd = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
                           10, 10, 300, 100,
                           NULL, NULL, NULL, 0);

    if (!hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
        win_skip("CreateWindowExW is not implemented\n");
        return;
    }

    assert(hwnd);

    toolinfoW.cbSize = sizeof(TTTOOLINFOW);
    toolinfoW.hwnd = NULL;
    toolinfoW.hinst = GetModuleHandleA(NULL);
    toolinfoW.uFlags = 0;
    toolinfoW.uId = 0x1234ABCD;
    toolinfoW.lpszText = NULL;
    toolinfoW.lParam = 0xdeadbeef;
    GetClientRect(hwnd, &toolinfoW.rect);
    r = SendMessageW(hwnd, TTM_ADDTOOL, 0, (LPARAM)&toolinfoW);
    ok(r, "Adding the tool to the tooltip failed\n");

    if (0)  /* crashes on NT4 */
    {
        toolinfoW.hwnd = NULL;
        toolinfoW.uId = 0x1234ABCD;
        toolinfoW.lpszText = bufW;
        SendMessageW(hwnd, TTM_GETTEXTW, 0, (LPARAM)&toolinfoW);
        ok(toolinfoW.lpszText[0] == 0, "lpszText should be an empty string\n");
    }

    DestroyWindow(hwnd);
}
Пример #10
0
static void test_updown_create(void)
{
    CHAR text[MAX_PATH];
    HWND updown;
    RECT r;

    flush_sequences(sequences, NUM_MSG_SEQUENCES);

    updown = create_updown_control(UDS_ALIGNRIGHT, g_edit);
    ok(updown != NULL, "Failed to create updown control\n");
    ok_sequence(sequences, PARENT_SEQ_INDEX, add_updown_to_parent_seq, "add updown control to parent", TRUE);
    ok_sequence(sequences, EDIT_SEQ_INDEX, add_updown_with_edit_seq, "add updown control with edit", FALSE);

    flush_sequences(sequences, NUM_MSG_SEQUENCES);

    GetWindowTextA(g_edit, text, MAX_PATH);
    ok(lstrlenA(text) == 0, "Expected empty string\n");
    ok_sequence(sequences, EDIT_SEQ_INDEX, get_edit_text_seq, "get edit text", FALSE);

    DestroyWindow(updown);

    /* create with zero width */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.right = 0;
    GetClientRect(updown, &r);
    ok(r.right > 0, "Expected default width, got %d\n", r.right);
    DestroyWindow(updown);
    /* create with really small width */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 2, 0,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.right = 0;
    GetClientRect(updown, &r);
    ok(r.right != 2 && r.right > 0, "Expected default width, got %d\n", r.right);
    DestroyWindow(updown);
    /* create with width greater than default */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 100, 0,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.right = 0;
    GetClientRect(updown, &r);
    ok(r.right < 100 && r.right > 0, "Expected default width, got %d\n", r.right);
    DestroyWindow(updown);
    /* create with zero height, UDS_HORZ */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 0,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.bottom = 0;
    GetClientRect(updown, &r);
    ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
    DestroyWindow(updown);
    /* create with really small height, UDS_HORZ */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 2,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.bottom = 0;
    GetClientRect(updown, &r);
    ok(r.bottom == 0, "Expected zero height, got %d\n", r.bottom);
    DestroyWindow(updown);
    /* create with height greater than default, UDS_HORZ */
    updown = CreateWindowA (UPDOWN_CLASSA, 0, UDS_HORZ | WS_CHILD | WS_BORDER | WS_VISIBLE, 0, 0, 0, 100,
                   parent_wnd, (HMENU)(DWORD_PTR)1, GetModuleHandleA(NULL), 0);
    ok(updown != NULL, "Failed to create updown control\n");
    r.bottom = 0;
    GetClientRect(updown, &r);
    ok(r.bottom < 100 && r.bottom > 0, "Expected default height, got %d\n", r.bottom);
    DestroyWindow(updown);
}
Пример #11
0
void* getUser32Function (const char* functionName)
{
    HMODULE module = GetModuleHandleA ("user32.dll");
    jassert (module != 0);
    return (void*) GetProcAddress (module, functionName);
}
Пример #12
0
static void test_WM_LBUTTONDOWN(void)
{
    HWND hComboEx, hCombo, hEdit, hList;
    COMBOBOXINFO cbInfo;
    UINT x, y, item_height;
    LRESULT result;
    UINT i;
    int idx;
    RECT rect;
    WCHAR buffer[3];
    static const UINT choices[] = {8,9,10,11,12,14,16,18,20,22,24,26,28,36,48,72};
    static const WCHAR stringFormat[] = {'%','2','d','\0'};
    BOOL (WINAPI *pGetComboBoxInfo)(HWND, PCOMBOBOXINFO);

    pGetComboBoxInfo = (void*)GetProcAddress(GetModuleHandleA("user32.dll"), "GetComboBoxInfo");
    if (!pGetComboBoxInfo){
        win_skip("GetComboBoxInfo is not available\n");
        return;
    }

    hComboEx = CreateWindowExA(0, WC_COMBOBOXEXA, NULL,
            WS_VISIBLE|WS_CHILD|CBS_DROPDOWN, 0, 0, 200, 150,
            hComboExParentWnd, NULL, hMainHinst, NULL);

    for (i = 0; i < sizeof(choices)/sizeof(UINT); i++){
        COMBOBOXEXITEMW cbexItem;
        wsprintfW(buffer, stringFormat, choices[i]);

        memset(&cbexItem, 0x00, sizeof(cbexItem));
        cbexItem.mask = CBEIF_TEXT;
        cbexItem.iItem = i;
        cbexItem.pszText = buffer;
        cbexItem.cchTextMax = 0;
        ok(SendMessageW(hComboEx, CBEM_INSERTITEMW, 0, (LPARAM)&cbexItem) >= 0,
           "Failed to add item %d\n", i);
    }

    hCombo = (HWND)SendMessage(hComboEx, CBEM_GETCOMBOCONTROL, 0, 0);
    hEdit = (HWND)SendMessage(hComboEx, CBEM_GETEDITCONTROL, 0, 0);

    cbInfo.cbSize = sizeof(COMBOBOXINFO);
    result = pGetComboBoxInfo(hCombo, &cbInfo);
    ok(result, "Failed to get combobox info structure. LastError=%d\n",
       GetLastError());
    hList = cbInfo.hwndList;

    trace("hWnd=%p, hComboEx=%p, hCombo=%p, hList=%p, hEdit=%p\n",
         hComboExParentWnd, hComboEx, hCombo, hList, hEdit);
    ok(GetFocus() == hComboExParentWnd,
       "Focus not on Main Window, instead on %p\n", GetFocus());

    /* Click on the button to drop down the list */
    x = cbInfo.rcButton.left + (cbInfo.rcButton.right-cbInfo.rcButton.left)/2;
    y = cbInfo.rcButton.top + (cbInfo.rcButton.bottom-cbInfo.rcButton.top)/2;
    result = SendMessage(hCombo, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
    ok(result, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
       GetLastError());
    ok(GetFocus() == hCombo ||
       broken(GetFocus() != hCombo), /* win98 */
       "Focus not on ComboBoxEx's ComboBox Control, instead on %p\n",
       GetFocus());
    ok(SendMessage(hComboEx, CB_GETDROPPEDSTATE, 0, 0),
       "The dropdown list should have appeared after clicking the button.\n");
    idx = SendMessage(hCombo, CB_GETTOPINDEX, 0, 0);
    ok(idx == 0, "For TopIndex expected %d, got %d\n", 0, idx);

    result = SendMessage(hCombo, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
    ok(result, "WM_LBUTTONUP was not processed. LastError=%d\n",
       GetLastError());
    ok(GetFocus() == hCombo ||
       broken(GetFocus() != hCombo), /* win98 */
       "Focus not on ComboBoxEx's ComboBox Control, instead on %p\n",
       GetFocus());

    /* Click on the 5th item in the list */
    item_height = SendMessage(hCombo, CB_GETITEMHEIGHT, 0, 0);
    ok(GetClientRect(hList, &rect), "Failed to get list's client rect.\n");
    x = rect.left + (rect.right-rect.left)/2;
    y = item_height/2 + item_height*4;
    result = SendMessage(hList, WM_MOUSEMOVE, 0, MAKELPARAM(x, y));
    ok(!result, "WM_MOUSEMOVE was not processed. LastError=%d\n",
       GetLastError());
    ok(GetFocus() == hCombo ||
       broken(GetFocus() != hCombo), /* win98 */
       "Focus not on ComboBoxEx's ComboBox Control, instead on %p\n",
       GetFocus());

    result = SendMessage(hList, WM_LBUTTONDOWN, 0, MAKELPARAM(x, y));
    ok(!result, "WM_LBUTTONDOWN was not processed. LastError=%d\n",
       GetLastError());
    ok(GetFocus() == hCombo ||
       broken(GetFocus() != hCombo), /* win98 */
       "Focus not on ComboBoxEx's ComboBox Control, instead on %p\n",
       GetFocus());
    ok(SendMessage(hComboEx, CB_GETDROPPEDSTATE, 0, 0),
       "The dropdown list should still be visible.\n");

    result = SendMessage(hList, WM_LBUTTONUP, 0, MAKELPARAM(x, y));
    ok(!result, "WM_LBUTTONUP was not processed. LastError=%d\n",
       GetLastError());
    todo_wine ok(GetFocus() == hEdit ||
       broken(GetFocus() == hCombo), /* win98 */
       "Focus not on ComboBoxEx's Edit Control, instead on %p\n",
       GetFocus());

    result = SendMessage(hCombo, CB_GETDROPPEDSTATE, 0, 0);
    ok(!result ||
       broken(result != 0), /* win98 */
       "The dropdown list should have been rolled up.\n");
    idx = SendMessage(hComboEx, CB_GETCURSEL, 0, 0);
    ok(idx == 4 ||
       broken(idx == -1), /* win98 */
       "Current Selection: expected %d, got %d\n", 4, idx);
    ok(received_end_edit, "Expected to receive a CBEN_ENDEDIT message\n");

    SetFocus( hComboExParentWnd );
    ok( GetFocus() == hComboExParentWnd, "got %p\n", GetFocus() );
    SetFocus( hComboEx );
    ok( GetFocus() == hEdit, "got %p\n", GetFocus() );

    DestroyWindow(hComboEx);
}
Пример #13
0
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    lpCmdLine = GetCommandLine() + 1;
    while (*lpCmdLine != '"') ++lpCmdLine;
    ExitProcess(WinMain2(GetModuleHandleA(NULL), 0, ++lpCmdLine, SW_SHOWDEFAULT));
}
Пример #14
0
Файл: sip.c Проект: AndreRH/wine
static void test_SIPLoad(void)
{
    BOOL ret;
    GUID subject;
    static GUID dummySubject = { 0xdeadbeef, 0xdead, 0xbeef, { 0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef }};
    static GUID unknown      = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */
    static GUID unknown2     = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */
    /* The next SIP is available on Windows and on Wine */
    static GUID unknown3     = { 0x000C10F1, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }}; /* MSISIP.DLL */
    SIP_DISPATCH_INFO sdi;
    HMODULE hCrypt;

    /* All NULL */
    SetLastError(0xdeadbeef);
    ret = CryptSIPLoad(NULL, 0, NULL);
    ok ( !ret, "Expected CryptSIPLoad to fail\n");
    ok ( GetLastError() == ERROR_INVALID_PARAMETER,
        "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());

    /* Only pSipDispatch NULL */
    SetLastError(0xdeadbeef);
    ret = CryptSIPLoad(&subject, 0, NULL);
    ok ( !ret, "Expected CryptSIPLoad to fail\n");
    ok ( GetLastError() == ERROR_INVALID_PARAMETER,
        "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());

    /* No NULLs, but nonexistent pgSubject */
    SetLastError(0xdeadbeef);
    memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
    sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
    sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
    ret = CryptSIPLoad(&dummySubject, 0, &sdi);
    ok ( !ret, "Expected CryptSIPLoad to fail\n");
    ok ( GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN,
        "Expected TRUST_E_SUBJECT_FORM_UNKNOWN, got 0x%08x\n", GetLastError());
    ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n");

    hCrypt = GetModuleHandleA("crypt32.dll");
    funcCryptSIPGetSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPGetSignedDataMsg");
    funcCryptSIPPutSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPPutSignedDataMsg");
    funcCryptSIPCreateIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPCreateIndirectData");
    funcCryptSIPVerifyIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPVerifyIndirectData");
    funcCryptSIPRemoveSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPRemoveSignedDataMsg");

    /* All OK */
    SetLastError(0xdeadbeef);
    memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
    sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
    sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
    ret = CryptSIPLoad(&unknown, 0, &sdi);
    ok ( ret, "Expected CryptSIPLoad to succeed\n");
    /* On native the last error will always be ERROR_PROC_NOT_FOUND as native searches for the function DllCanUnloadNow
     * in WINTRUST.DLL (in this case). This function is not available in WINTRUST.DLL.
     * For now there's no need to implement this is Wine as I doubt any program will rely on
     * this last error when the call succeeded.
     */
    ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");

    /* The function addresses returned by CryptSIPLoad are actually the addresses of
     * crypt32's own functions. A function calling these addresses will end up first
     * calling crypt32 functions which in its turn call the equivalent in the SIP
     * as dictated by the given GUID.
     */
    if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData &&
        funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg)
        ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg &&
            sdi.pfPut == funcCryptSIPPutSignedDataMsg &&
            sdi.pfCreate == funcCryptSIPCreateIndirectData &&
            sdi.pfVerify == funcCryptSIPVerifyIndirectData &&
            sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg,
            "Expected function addresses to be from crypt32\n");
    else
        trace("Couldn't load function pointers\n");

    /* All OK, but different GUID (same SIP though) */
    SetLastError(0xdeadbeef);
    memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
    sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
    sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
    ret = CryptSIPLoad(&unknown2, 0, &sdi);
    ok ( ret, "Expected CryptSIPLoad to succeed\n");
    /* This call on its own would have resulted in an ERROR_PROC_NOT_FOUND, but the previous
     * call to CryptSIPLoad already loaded wintrust.dll. As this information is cached,
     * CryptSIPLoad will not try to search for the already mentioned DllCanUnloadNow.
     */
    ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");

    /* All OK, but other SIP */
    SetLastError(0xdeadbeef);
    memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
    sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
    sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
    ret = CryptSIPLoad(&unknown3, 0, &sdi);
    if (ret)
    {
        /* The SIP is known so we can safely assume that the next tests can be done */

        /* As msisip.dll is not checked yet by any of the previous calls, the
         * function DllCanUnloadNow will be checked again in msisip.dll (it's not present)
         */
        ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");

        /* This is another SIP but this test proves the function addresses are the same as
         * in the previous test.
         */
        if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData &&
            funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg)
            ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg &&
                sdi.pfPut == funcCryptSIPPutSignedDataMsg &&
                sdi.pfCreate == funcCryptSIPCreateIndirectData &&
                sdi.pfVerify == funcCryptSIPVerifyIndirectData &&
                sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg,
                "Expected function addresses to be from crypt32\n");
        else
            trace("Couldn't load function pointers\n");
    }

    /* Reserved parameter not 0 */
    SetLastError(0xdeadbeef);
    memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
    sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
    sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
    ret = CryptSIPLoad(&unknown, 1, &sdi);
    ok ( !ret, "Expected CryptSIPLoad to fail\n");
    ok ( GetLastError() == ERROR_INVALID_PARAMETER,
        "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());
    ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n");
}