/************************************************************************* * StartDocW [GDI32.@] * */ INT WINAPI StartDocW(HDC hdc, const DOCINFOW* doc) { DOCINFOA docA; INT ret; docA.cbSize = doc->cbSize; docA.lpszDocName = doc->lpszDocName ? HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDocName ) : NULL; docA.lpszOutput = doc->lpszOutput ? HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszOutput ) : NULL; docA.lpszDatatype = doc->lpszDatatype ? HEAP_strdupWtoA( GetProcessHeap(), 0, doc->lpszDatatype ) : NULL; docA.fwType = doc->fwType; ret = StartDocA(hdc, &docA); if(docA.lpszDocName) HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDocName ); if(docA.lpszOutput) HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszOutput ); if(docA.lpszDatatype) HeapFree( GetProcessHeap(), 0, (LPSTR)docA.lpszDatatype ); return ret; }
/****************************************************************** * StartDoc [GDI.377] * */ INT16 WINAPI StartDoc16( HDC16 hdc, const DOCINFO16 *lpdoc ) { DOCINFOA docA; docA.cbSize = lpdoc->cbSize; docA.lpszDocName = MapSL(lpdoc->lpszDocName); docA.lpszOutput = MapSL(lpdoc->lpszOutput); if(lpdoc->cbSize >= 14) docA.lpszDatatype = MapSL(lpdoc->lpszDatatype); else docA.lpszDatatype = NULL; if(lpdoc->cbSize >= 18) docA.fwType = lpdoc->fwType; else docA.fwType = 0; return StartDocA(hdc, &docA); }
static int winprint_start (struct winprint_data *wd, Tcl_Interp *interp, PRINTDLG *pd, const struct print_text_options *pto, int *cancelled) { DOCINFOA di; *cancelled = 0; wd->aborted = 0; /* We have no way to pass information to the abort function, so we need to use a global variable. */ abort_wd = wd; if (! SetAbortProc (pd->hDC, abort_function)) { windows_error (interp, "SetAbortFunc"); return TCL_ERROR; } di.cbSize = sizeof (DOCINFO); di.lpszDocName = pto->name; di.lpszOutput = NULL; di.lpszDatatype = NULL; di.fwType = 0; if (StartDocA (pd->hDC, &di) <= 0) { if (GetLastError () == ERROR_CANCELLED) *cancelled = 1; else { windows_error (interp, "StartDoc"); return TCL_ERROR; } } return TCL_OK; }
/************************************************************************ * Escape [GDI32.@] */ INT WINAPI Escape( HDC hdc, INT escape, INT in_count, LPCSTR in_data, LPVOID out_data ) { INT ret; POINT *pt; switch (escape) { case ABORTDOC: return AbortDoc( hdc ); case ENDDOC: return EndDoc( hdc ); case GETPHYSPAGESIZE: pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALWIDTH ); pt->y = GetDeviceCaps( hdc, PHYSICALHEIGHT ); return 1; case GETPRINTINGOFFSET: pt = out_data; pt->x = GetDeviceCaps( hdc, PHYSICALOFFSETX ); pt->y = GetDeviceCaps( hdc, PHYSICALOFFSETY ); return 1; case GETSCALINGFACTOR: pt = out_data; pt->x = GetDeviceCaps( hdc, SCALINGFACTORX ); pt->y = GetDeviceCaps( hdc, SCALINGFACTORY ); return 1; case NEWFRAME: return EndPage( hdc ); case SETABORTPROC: return SetAbortProc( hdc, (ABORTPROC)in_data ); case STARTDOC: { DOCINFOA doc; char *name = NULL; /* in_data may not be 0 terminated so we must copy it */ if (in_data) { name = HeapAlloc( GetProcessHeap(), 0, in_count+1 ); memcpy( name, in_data, in_count ); name[in_count] = 0; } /* out_data is actually a pointer to the DocInfo structure and used as * a second input parameter */ if (out_data) doc = *(DOCINFOA *)out_data; else { doc.cbSize = sizeof(doc); doc.lpszOutput = NULL; doc.lpszDatatype = NULL; doc.fwType = 0; } doc.lpszDocName = name; ret = StartDocA( hdc, &doc ); HeapFree( GetProcessHeap(), 0, name ); if (ret > 0) ret = StartPage( hdc ); return ret; } case QUERYESCSUPPORT: { const INT *ptr = (const INT *)in_data; if (in_count < sizeof(INT)) return 0; switch(*ptr) { case ABORTDOC: case ENDDOC: case GETPHYSPAGESIZE: case GETPRINTINGOFFSET: case GETSCALINGFACTOR: case NEWFRAME: case QUERYESCSUPPORT: case SETABORTPROC: case STARTDOC: return TRUE; } break; } } /* if not handled internally, pass it to the driver */ return ExtEscape( hdc, escape, in_count, in_data, 0, out_data ); }
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]; 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"); ok(DeleteFileA(filename), "Failed to delete temporary file\n"); return; } ok(pd.hDC != NULL, "PrintDlg didn't return a DC.\n"); if (!(print_dc = pd.hDC)) { ok(DeleteFileA(filename), "Failed to delete temporary file\n"); return; } 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; ok(StartDocA(print_dc, &doc_info) > 0, "StartDocA failed\n"); ok(abort_proc_called, "AbortProc didn't get called by StartDoc.\n"); 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; ok(FillRect(print_dc, &rect, (HBRUSH)(COLOR_BACKGROUND + 1)), "FillRect failed\n"); ok(!abort_proc_called, "AbortProc got called unexpectedly by StretchBlt.\n"); abort_proc_called = FALSE; ok(EndPage(print_dc) > 0, "EndPage failed\n"); ok(!abort_proc_called, "AbortProc got called unexpectedly by EndPage.\n"); abort_proc_called = FALSE; ok(EndDoc(print_dc) > 0, "EndDoc failed\n"); ok(!abort_proc_called, "AbortProc got called unexpectedly by EndDoc.\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; ok(DeleteFileA(filename), "Failed to delete temporary file\n"); }
/* * @unimplemented */ INT WINAPI Escape( _In_ HDC hdc, _In_ INT nEscape, _In_ INT cbInput, _In_ LPCSTR lpvInData, _Out_ LPVOID lpvOutData) { INT retValue = SP_ERROR; ULONG ulObjType; ulObjType = GDI_HANDLE_GET_TYPE(hdc); if (ulObjType == GDILoObjType_LO_METADC16_TYPE) { return METADC16_Escape(hdc, nEscape, cbInput, lpvInData, lpvOutData); } switch (nEscape) { case ABORTDOC: /* Note: Windows checks if the handle has any user data for the ABORTDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } else { retValue = AbortDoc(hdc); } break; case DRAFTMODE: case FLUSHOUTPUT: case SETCOLORTABLE: /* Note 1: DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE are outdated */ /* Note 2: Windows checks if the handle has any user data for the DRAFTMODE, FLUSHOUTPUT, SETCOLORTABLE commands * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); } retValue = FALSE; break; case SETABORTPROC: /* Note: Windows checks if the handle has any user data for the SETABORTPROC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } retValue = SetAbortProc(hdc, (ABORTPROC)lpvInData); break; case GETCOLORTABLE: retValue = GetSystemPaletteEntries(hdc, (UINT)*lpvInData, 1, (LPPALETTEENTRY)lpvOutData); if (!retValue) { retValue = SP_ERROR; } break; case ENDDOC: /* Note: Windows checks if the handle has any user data for the ENDDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } retValue = EndDoc(hdc); break; case GETSCALINGFACTOR: /* Note GETSCALINGFACTOR is outdated have been replace by GetDeviceCaps */ if (ulObjType == GDI_OBJECT_TYPE_DC) { if (lpvOutData) { PPOINT ptr = (PPOINT)lpvOutData; ptr->x = 0; ptr->y = 0; } } retValue = FALSE; break; case GETEXTENDEDTEXTMETRICS: retValue = GetETM(hdc, (EXTTEXTMETRIC *)lpvOutData) != 0; break; case STARTDOC: { DOCINFOA di; /* Note: Windows checks if the handle has any user data for the STARTDOC command * ReactOS copies this behavior to be compatible with windows 2003 */ if (GdiGetDcAttr(hdc) == NULL) { GdiSetLastError(ERROR_INVALID_HANDLE); retValue = FALSE; } di.cbSize = sizeof(DOCINFOA); di.lpszOutput = 0; di.lpszDatatype = 0; di.fwType = 0; di.lpszDocName = lpvInData; /* NOTE : doc for StartDocA/W at msdn http://msdn2.microsoft.com/en-us/library/ms535793(VS.85).aspx */ retValue = StartDocA(hdc, &di); /* Check if StartDocA failed */ if (retValue < 0) { { retValue = GetLastError(); /* Translate StartDocA error code to STARTDOC error code * see msdn http://msdn2.microsoft.com/en-us/library/ms535472.aspx */ switch(retValue) { case ERROR_NOT_ENOUGH_MEMORY: retValue = SP_OUTOFMEMORY; break; case ERROR_PRINT_CANCELLED: retValue = SP_USERABORT; break; case ERROR_DISK_FULL: retValue = SP_OUTOFDISK; break; default: retValue = SP_ERROR; break; } } } } break; default: UNIMPLEMENTED; SetLastError(ERROR_CALL_NOT_IMPLEMENTED); } return retValue; }
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()); }