/* 
 * Unit test suite for comdlg32 API functions: printer dialogs
 *
 * Copyright 2006-2007 Detlef Riekenberg
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
#include "objbase.h"

#include "cderr.h"
#include "commdlg.h"

#include "wine/test.h"

/* ########################### */

static HMODULE  hcomdlg32;
static HRESULT (WINAPI * pPrintDlgExW)(LPPRINTDLGEXW);

/* ########################### */

static const CHAR emptyA[] = "";
static const CHAR PrinterPortsA[] = "PrinterPorts";

/* ########################### */

static void test_PageSetupDlgA(void)
{
    LPPAGESETUPDLGA pDlg;
    DWORD res;

    pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PAGESETUPDLGA)) * 2);
    if (!pDlg) return;

    SetLastError(0xdeadbeef);
    res = PageSetupDlgA(NULL);
    ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
        "returned %u with %u and 0x%x (expected '0' and "
        "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());

    ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
    pDlg->lStructSize = sizeof(PAGESETUPDLGA) -1;
    SetLastError(0xdeadbeef);
    res = PageSetupDlgA(pDlg);
    ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
        "returned %u with %u and 0x%x (expected '0' and "
        "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());

    ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
    pDlg->lStructSize = sizeof(PAGESETUPDLGA) +1;
    pDlg->Flags = PSD_RETURNDEFAULT;
    SetLastError(0xdeadbeef);
    res = PageSetupDlgA(pDlg);
    ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
        "returned %u with %u and 0x%x (expected '0' and CDERR_STRUCTSIZE)\n",
        res, GetLastError(), CommDlgExtendedError());


    ZeroMemory(pDlg, sizeof(PAGESETUPDLGA));
    pDlg->lStructSize = sizeof(PAGESETUPDLGA);
    pDlg->Flags = PSD_RETURNDEFAULT | PSD_NOWARNING;
    SetLastError(0xdeadbeef);
    res = PageSetupDlgA(pDlg);
    ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
        "returned %u with %u and 0x%x (expected '!= 0' or '0' and "
        "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());

    if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
        skip("No printer configured.\n");
        HeapFree(GetProcessHeap(), 0, pDlg);
        return;
    }

    ok( pDlg->hDevMode && pDlg->hDevNames,
        "got %p and %p (expected '!= NULL' for both)\n",
        pDlg->hDevMode, pDlg->hDevNames);

    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);

    HeapFree(GetProcessHeap(), 0, pDlg);

}

/* ########################### */

static void test_PrintDlgA(void)
{
    DWORD       res;
    LPPRINTDLGA pDlg;
    DEVNAMES    *pDevNames;
    LPCSTR driver;
    LPCSTR device;
    LPCSTR port;
    CHAR   buffer[MAX_PATH];
    LPSTR  ptr;


    pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGA)) * 2);
    if (!pDlg) return;


    /* will crash with unpatched wine */
    SetLastError(0xdeadbeef);
    res = PrintDlgA(NULL);
    ok( !res && (CommDlgExtendedError() == CDERR_INITIALIZATION),
        "returned %d with 0x%x and 0x%x (expected '0' and "
        "CDERR_INITIALIZATION)\n", res, GetLastError(), CommDlgExtendedError());

    ZeroMemory(pDlg, sizeof(PRINTDLGA));
    pDlg->lStructSize = sizeof(PRINTDLGA) - 1;
    SetLastError(0xdeadbeef);
    res = PrintDlgA(pDlg);
    ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
        "returned %d with 0x%x and 0x%x (expected '0' and "
        "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());

    ZeroMemory(pDlg, sizeof(PRINTDLGA));
    pDlg->lStructSize = sizeof(PRINTDLGA) + 1;
    pDlg->Flags = PD_RETURNDEFAULT;
    SetLastError(0xdeadbeef);
    res = PrintDlgA(pDlg);
    ok( !res && (CommDlgExtendedError() == CDERR_STRUCTSIZE),
        "returned %u with %u and 0x%x (expected '0' and "
        "CDERR_STRUCTSIZE)\n", res, GetLastError(), CommDlgExtendedError());


    ZeroMemory(pDlg, sizeof(PRINTDLGA));
    pDlg->lStructSize = sizeof(PRINTDLGA);
    pDlg->Flags = PD_RETURNDEFAULT;
    SetLastError(0xdeadbeef);
    res = PrintDlgA(pDlg);
    ok( res || (CommDlgExtendedError() == PDERR_NODEFAULTPRN),
        "returned %d with 0x%x and 0x%x (expected '!= 0' or '0' and "
        "PDERR_NODEFAULTPRN)\n", res, GetLastError(), CommDlgExtendedError());

    if (!res && (CommDlgExtendedError() == PDERR_NODEFAULTPRN)) {
        skip("No printer configured.\n");
        HeapFree(GetProcessHeap(), 0, pDlg);
        return;
    }

    ok(pDlg->hDevNames != NULL, "(expected '!= NULL')\n");
    pDevNames = GlobalLock(pDlg->hDevNames);
    ok(pDevNames != NULL, "(expected '!= NULL')\n");

    if (pDevNames) {
        ok(pDevNames->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n");
        ok(pDevNames->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n");
        ok(pDevNames->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n");
        ok(pDevNames->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", pDevNames->wDefault);

        driver = (LPCSTR)pDevNames + pDevNames->wDriverOffset;
        device = (LPCSTR)pDevNames + pDevNames->wDeviceOffset;
        port = (LPCSTR)pDevNames + pDevNames->wOutputOffset;
        trace("driver '%s' device '%s' port '%s'\n", driver, device, port);

        /* The Driver Entry does not include a Path */
        ptr = strrchr(driver, '\\');
        ok( ptr == NULL, "got %p for '%s' (expected NULL for a simple name)\n", ptr, driver);

        /* The Driver Entry does not have an extension (fixed to ".drv") */
        ptr = strrchr(driver, '.');
        todo_wine {
        ok( ptr == NULL, "got %p for '%s' (expected NULL for no extension)\n", ptr, driver);
        }


        buffer[0] = '\0';
        SetLastError(0xdeadbeef);
        res = GetProfileStringA(PrinterPortsA, device, emptyA, buffer, sizeof(buffer));
        ptr = strchr(buffer, ',');
        ok( (res > 1) && (ptr != NULL),
            "got %u with %u and %p for '%s' (expected '>1' and '!= NULL')\n",
            res, GetLastError(), ptr, buffer);

        if (ptr) ptr[0] = '\0';
        ok( lstrcmpiA(driver, buffer) == 0,
            "got driver '%s' (expected '%s')\n", driver, buffer);
    }

    GlobalUnlock(pDlg->hDevNames);

    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);
    HeapFree(GetProcessHeap(), 0, pDlg);

}

/* ########################### */

static void test_PrintDlgExW(void)
{
    PRINTPAGERANGE pagerange[2];
    LPPRINTDLGEXW pDlg;
    DEVNAMES *dn;
    HRESULT res;

    /* PrintDlgEx not present before w2k */
    if (!pPrintDlgExW) {
        skip("PrintDlgExW not available\n");
        return;
    }

    /* Set CommDlgExtendedError != 0 */
    PrintDlg(NULL);
    SetLastError(0xdeadbeef);
    res = pPrintDlgExW(NULL);
    ok( (res == E_INVALIDARG),
        "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
        res, GetLastError(), CommDlgExtendedError());


    pDlg = HeapAlloc(GetProcessHeap(), 0, (sizeof(PRINTDLGEXW)) + 8);
    if (!pDlg) return;

    /* lStructSize must be exact */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW) - 1;
    PrintDlg(NULL);
    SetLastError(0xdeadbeef);
    res = pPrintDlgExW(pDlg);
    ok( (res == E_INVALIDARG),
        "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
        res, GetLastError(), CommDlgExtendedError());


    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW) + 1;
    PrintDlg(NULL);
    SetLastError(0xdeadbeef);
    res = pPrintDlgExW(pDlg);
    ok( (res == E_INVALIDARG),
        "got 0x%x with %u and %u (expected 'E_INVALIDARG')\n",
        res, GetLastError(), CommDlgExtendedError());


    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    SetLastError(0xdeadbeef);
    res = pPrintDlgExW(pDlg);
    ok( (res == E_HANDLE),
        "got 0x%x with %u and %u (expected 'E_HANDLE')\n",
        res, GetLastError(), CommDlgExtendedError());

    /* nStartPage must be START_PAGE_GENERAL for the general page or a valid property sheet index */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS;
    res = pPrintDlgExW(pDlg);
    ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res);

    /* Use PD_NOPAGENUMS or set nMaxPageRanges and lpPageRanges */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res);

    /* this is invalid: a valid lpPageRanges with 0 for nMaxPageRanges */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING;
    pDlg->lpPageRanges = pagerange;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res);

    /* this is invalid: NULL for lpPageRanges with a valid nMaxPageRanges */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING;
    pDlg->nMaxPageRanges = 1;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok((res == E_INVALIDARG), "got 0x%x (expected 'E_INVALIDARG')\n", res);

    /* this works: lpPageRanges with a valid nMaxPageRanges */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING;
    pDlg->nMaxPageRanges = 1;
    pDlg->lpPageRanges = pagerange;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    if (res == E_FAIL)
    {
        skip("No printer configured.\n");
        HeapFree(GetProcessHeap(), 0, pDlg);
        return;
    }

    ok(res == S_OK, "got 0x%x (expected S_OK)\n", res);

    dn = GlobalLock(pDlg->hDevNames);
    ok(dn != NULL, "expected '!= NULL' for GlobalLock(%p)\n",pDlg->hDevNames);
    if (dn)
    {
        ok(dn->wDriverOffset, "(expected '!= 0' for wDriverOffset)\n");
        ok(dn->wDeviceOffset, "(expected '!= 0' for wDeviceOffset)\n");
        ok(dn->wOutputOffset, "(expected '!= 0' for wOutputOffset)\n");
        ok(dn->wDefault == DN_DEFAULTPRN, "got 0x%x (expected DN_DEFAULTPRN)\n", dn->wDefault);

        GlobalUnlock(pDlg->hDevNames);
    }
    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);

    /* this works also: PD_NOPAGENUMS */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok(res == S_OK, "got 0x%x (expected S_OK)\n", res);
    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);

    /* this works: PD_RETURNDC with PD_RETURNDEFAULT */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS | PD_RETURNDC;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok(res == S_OK, "got 0x%x (expected S_OK)\n", res);
    ok(pDlg->hDC != NULL, "HDC missing for PD_RETURNDC\n");
    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);
    DeleteDC(pDlg->hDC);

    /* this works: PD_RETURNIC with PD_RETURNDEFAULT */
    ZeroMemory(pDlg, sizeof(PRINTDLGEXW));
    pDlg->lStructSize = sizeof(PRINTDLGEXW);
    pDlg->hwndOwner = GetDesktopWindow();
    pDlg->Flags = PD_RETURNDEFAULT | PD_NOWARNING | PD_NOPAGENUMS | PD_RETURNIC;
    pDlg->nStartPage = START_PAGE_GENERAL;
    res = pPrintDlgExW(pDlg);
    ok(res == S_OK, "got 0x%x (expected S_OK)\n", res);
    ok(pDlg->hDC != NULL, "HDC missing for PD_RETURNIC\n");
    GlobalFree(pDlg->hDevMode);
    GlobalFree(pDlg->hDevNames);
    DeleteDC(pDlg->hDC);

    HeapFree(GetProcessHeap(), 0, pDlg);
    return;

}

static BOOL abort_proc_called = FALSE;
static BOOL CALLBACK abort_proc(HDC hdc, int error) { return abort_proc_called = TRUE; }
static void test_abort_proc(void)
{
    HDC print_dc;
    RECT rect = {0, 0, 100, 100};
    DOCINFOA doc_info = {0};
    PRINTDLGA pd = {0};
    char filename[MAX_PATH];
    int job_id;

    if (!GetTempFileNameA(".", "prn", 0, filename))
    {
        skip("Failed to create a temporary file name\n");
        return;
    }

    pd.lStructSize = sizeof(pd);
    pd.Flags = PD_RETURNDEFAULT | PD_ALLPAGES | PD_RETURNDC | PD_PRINTTOFILE;
    pd.nFromPage = 1;
    pd.nToPage = 1;
    pd.nCopies = 1;

    if (!PrintDlgA(&pd))
    {
        skip("No default printer available.\n");
        goto end;
    }
    GlobalFree(pd.hDevMode);
    GlobalFree(pd.hDevNames);

    ok(pd.hDC != NULL, "PrintDlg didn't return a DC.\n");
    if (!(print_dc = pd.hDC))
        goto end;

    ok(SetAbortProc(print_dc, abort_proc) > 0, "SetAbortProc failed\n");
    ok(!abort_proc_called, "AbortProc got called unexpectedly by SetAbortProc.\n");
    abort_proc_called = FALSE;

    doc_info.cbSize = sizeof(doc_info);
    doc_info.lpszDocName = "Some document";
    doc_info.lpszOutput = filename;

    job_id = StartDocA(print_dc, &doc_info);

    ok(job_id > 0 ||
       GetLastError() == ERROR_SPL_NO_STARTDOC, /* Vista can fail with this error when using the XPS driver */
       "StartDocA failed ret %d gle %d\n", job_id, GetLastError());

    if(job_id <= 0)
    {
        skip("StartDoc failed\n");
        goto end;
    }

    /* StartDoc may or may not call abort proc */

    abort_proc_called = FALSE;
    ok(StartPage(print_dc) > 0, "StartPage failed\n");
    ok(!abort_proc_called, "AbortProc got called unexpectedly by StartPage.\n");
    abort_proc_called = FALSE;

    /* following functions sometimes call abort proc too */
    ok(FillRect(print_dc, &rect, (HBRUSH)(COLOR_BACKGROUND + 1)), "FillRect failed\n");
    ok(EndPage(print_dc) > 0, "EndPage failed\n");
    ok(EndDoc(print_dc) > 0, "EndDoc failed\n");

    abort_proc_called = FALSE;
    ok(DeleteDC(print_dc), "DeleteDC failed\n");
    ok(!abort_proc_called, "AbortProc got called unexpectedly by DeleteDC.\n");
    abort_proc_called = FALSE;

end:
    SetLastError(0xdeadbeef);
    if(!DeleteFileA(filename))
        trace("Failed to delete temporary file (err = %x)\n", GetLastError());
}

/* ########################### */

START_TEST(printdlg)
{
    hcomdlg32 = GetModuleHandleA("comdlg32.dll");
    pPrintDlgExW = (void *) GetProcAddress(hcomdlg32, "PrintDlgExW");

    test_PageSetupDlgA();
    test_PrintDlgA();
    test_PrintDlgExW();
    test_abort_proc();
}
