Index: base/services/CMakeLists.txt =================================================================== --- base/services/CMakeLists.txt (revision 73027) +++ base/services/CMakeLists.txt (working copy) @@ -4,7 +4,6 @@ add_subdirectory(eventlog) add_subdirectory(rpcss) add_subdirectory(schedsvc) -add_subdirectory(spoolsv) add_subdirectory(srvsvc) add_subdirectory(svchost) add_subdirectory(tcpsvcs) Index: base/services/spoolsv/CMakeLists.txt =================================================================== --- base/services/spoolsv/CMakeLists.txt (revision 73027) +++ base/services/spoolsv/CMakeLists.txt (nonexistent) @@ -1,6 +0,0 @@ - -add_executable(spoolsv spoolsv.c spoolsv.rc) -target_link_libraries(spoolsv wine) -set_module_type(spoolsv win32cui UNICODE) -add_importlibs(spoolsv advapi32 msvcrt kernel32 ntdll) -add_cd_file(TARGET spoolsv DESTINATION reactos/system32 FOR all) Index: base/services/spoolsv/spoolsv.c =================================================================== --- base/services/spoolsv/spoolsv.c (revision 73027) +++ base/services/spoolsv/spoolsv.c (nonexistent) @@ -1,129 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: base/services/spoolsv/spoolsv.c - * PURPOSE: Printer spooler - * PROGRAMMER: Eric Kohl - */ - -/* INCLUDES *****************************************************************/ - -#include -#include -#include - -WINE_DEFAULT_DEBUG_CHANNEL(spoolsv); - - -/* GLOBALS ******************************************************************/ - -static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv); -static WCHAR ServiceName[] = L"Spooler"; -static SERVICE_TABLE_ENTRYW ServiceTable[] = -{ - {ServiceName, ServiceMain}, - {NULL, NULL} -}; - -SERVICE_STATUS_HANDLE ServiceStatusHandle; -SERVICE_STATUS ServiceStatus; - - -/* FUNCTIONS *****************************************************************/ - -static VOID -UpdateServiceStatus(DWORD dwState) -{ - ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - ServiceStatus.dwCurrentState = dwState; - - if (dwState == SERVICE_RUNNING) - ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; - else - ServiceStatus.dwControlsAccepted = 0; - - ServiceStatus.dwWin32ExitCode = 0; - ServiceStatus.dwServiceSpecificExitCode = 0; - ServiceStatus.dwCheckPoint = 0; - - if (dwState == SERVICE_START_PENDING || - dwState == SERVICE_STOP_PENDING) - ServiceStatus.dwWaitHint = 10000; - else - ServiceStatus.dwWaitHint = 0; - - SetServiceStatus(ServiceStatusHandle, - &ServiceStatus); -} - - -static DWORD WINAPI -ServiceControlHandler(DWORD dwControl, - DWORD dwEventType, - LPVOID lpEventData, - LPVOID lpContext) -{ - TRACE("ServiceControlHandler() called\n"); - - switch (dwControl) - { - case SERVICE_CONTROL_STOP: - TRACE(" SERVICE_CONTROL_STOP received\n"); - UpdateServiceStatus(SERVICE_STOPPED); - return ERROR_SUCCESS; - - case SERVICE_CONTROL_INTERROGATE: - TRACE(" SERVICE_CONTROL_INTERROGATE received\n"); - SetServiceStatus(ServiceStatusHandle, - &ServiceStatus); - return ERROR_SUCCESS; - - case SERVICE_CONTROL_SHUTDOWN: - TRACE(" SERVICE_CONTROL_SHUTDOWN received\n"); - UpdateServiceStatus(SERVICE_STOPPED); - return ERROR_SUCCESS; - - default : - TRACE(" Control %lu received\n"); - return ERROR_CALL_NOT_IMPLEMENTED; - } -} - - -static VOID CALLBACK -ServiceMain(DWORD argc, LPWSTR *argv) -{ - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - TRACE("ServiceMain() called\n"); - - ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, - ServiceControlHandler, - NULL); - - TRACE("Calling SetServiceStatus()\n"); - UpdateServiceStatus(SERVICE_RUNNING); - TRACE("SetServiceStatus() called\n"); - - - TRACE("ServiceMain() done\n"); -} - - -int -wmain(int argc, WCHAR *argv[]) -{ - UNREFERENCED_PARAMETER(argc); - UNREFERENCED_PARAMETER(argv); - - TRACE("Spoolsv: main() started\n"); - - StartServiceCtrlDispatcher(ServiceTable); - - TRACE("Spoolsv: main() done\n"); - - return 0; -} - -/* EOF */ Index: base/services/spoolsv/spoolsv.rc =================================================================== --- base/services/spoolsv/spoolsv.rc (revision 73027) +++ base/services/spoolsv/spoolsv.rc (nonexistent) @@ -1,4 +0,0 @@ -#define REACTOS_STR_FILE_DESCRIPTION "Spooler-Service" -#define REACTOS_STR_INTERNAL_NAME "Spoolsv" -#define REACTOS_STR_ORIGINAL_FILENAME "Spoolsv.exe" -#include Index: boot/bootdata/hivesys.inf =================================================================== --- boot/bootdata/hivesys.inf (revision 73027) +++ boot/bootdata/hivesys.inf (working copy) @@ -1252,14 +1252,38 @@ HKLM,"SYSTEM\CurrentControlSet\Control\PnP\Pci\CardList","Ali",0x00030003,\ 01,00,00,00,b9,10,21,15,00,00,00,00,00,00,00,00 + +; Printing HKLM,"SYSTEM\CurrentControlSet\Control\Print","MajorVersion",0x00010001,2 -HKLM,"SYSTEM\CurrentControlSet\Control\Print","MinorVersion",0x00010003,0 -HKLM,"SYSTEM\CurrentControlSet\Control\Print","PriorityClass",0x00010003,0 -HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors",,0x00000012 -HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port","Driver",2,"localspl.dll" +HKLM,"SYSTEM\CurrentControlSet\Control\Print","MinorVersion",0x00010001,0 +HKLM,"SYSTEM\CurrentControlSet\Control\Print","PriorityClass",0x00010001,0 + +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments",,0x00000010 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86","Directory",,"W32X86" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Print Processors",,0x00000010 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Print Processors\winprint","Driver",,"winprint.dll" + +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors",,0x00000010 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Monitors\Local Port","Driver",,"localmon.dll" + HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers",,0x00000012 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Attributes",0x00010001,0 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Datatype",,"RAW" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Description",,"" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Default DevMode",1,\ +00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ +00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,dc,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ +00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ +00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,\ +00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Port",,"LPT1:" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Print Processor",,"winprint" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Printer Driver",,"Dummy Printer Driver" +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Printers\Dummy Printer On LPT1","Status",0x00010001,0 +HKLM,"SYSTEM\CurrentControlSet\Control\Print\Providers",,0x00000010 + + HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductType",2,"ServerNT" HKLM,"SYSTEM\CurrentControlSet\Control\ProductOptions","ProductSuite",0x00010002,"Terminal Server" ; ReactOS specific - by default we report ourselves as Server for the user, Index: dll/win32/CMakeLists.txt =================================================================== --- dll/win32/CMakeLists.txt (revision 73027) +++ dll/win32/CMakeLists.txt (working copy) @@ -72,8 +72,6 @@ add_subdirectory(kernel32) add_subdirectory(kernel32_vista) add_subdirectory(loadperf) -add_subdirectory(localspl) -add_subdirectory(localui) add_subdirectory(lpk) add_subdirectory(lsasrv) add_subdirectory(lz32) @@ -139,7 +137,6 @@ add_subdirectory(ntdsapi) add_subdirectory(ntlanman) add_subdirectory(ntmarta) -add_subdirectory(ntprint) add_subdirectory(objsel) add_subdirectory(odbc32) add_subdirectory(odbccp32) @@ -194,7 +191,6 @@ add_subdirectory(sndblst) add_subdirectory(snmpapi) add_subdirectory(softpub) -add_subdirectory(spoolss) add_subdirectory(srclient) add_subdirectory(stdole2.tlb) add_subdirectory(stdole32.tlb) @@ -238,7 +234,6 @@ add_subdirectory(wininet) add_subdirectory(winmm) add_subdirectory(winscard) -add_subdirectory(winspool) add_subdirectory(winsta) add_subdirectory(wintrust) add_subdirectory(wlanapi) Index: dll/win32/localspl/CMakeLists.txt =================================================================== --- dll/win32/localspl/CMakeLists.txt (revision 73027) +++ dll/win32/localspl/CMakeLists.txt (nonexistent) @@ -1,25 +0,0 @@ - -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x600) - -add_definitions(-D__WINESRC__) -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -spec2def(localspl.dll localspl.spec) - -list(APPEND SOURCE - localmon.c - localspl_main.c - provider.c - localspl_private.h) - -add_library(localspl SHARED - ${SOURCE} - localspl.rc - ${CMAKE_CURRENT_BINARY_DIR}/localspl_stubs.c - ${CMAKE_CURRENT_BINARY_DIR}/localspl.def) - -set_module_type(localspl win32dll) -target_link_libraries(localspl wine) -add_importlibs(localspl spoolss user32 advapi32 advapi32_vista msvcrt kernel32 ntdll) -add_pch(localspl localspl_private.h SOURCE) -add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all) Index: dll/win32/localspl/lang/spl_Cy.rc =================================================================== --- dll/win32/localspl/lang/spl_Cy.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Cy.rc (nonexistent) @@ -1,28 +0,0 @@ -/* - * Cefnogaeth iaith Cymraeg - * Welsh language support - * - * Copyright 2010 Ken Sharp - * - * 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 - */ - -LANGUAGE LANG_WELSH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Port Lleol" - IDS_LOCALMONITOR "Monitor Lleol" -} Index: dll/win32/localspl/lang/spl_Da.rc =================================================================== --- dll/win32/localspl/lang/spl_Da.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Da.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Danish resources for localspl - * - * Copyright 2008 Jens Albretsen - * - * 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 - */ - -LANGUAGE LANG_DANISH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Lokal port" - IDS_LOCALMONITOR "Lokal overvåger" -} Index: dll/win32/localspl/lang/spl_De.rc =================================================================== --- dll/win32/localspl/lang/spl_De.rc (revision 73027) +++ dll/win32/localspl/lang/spl_De.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * German resources for localspl - * - * Copyright 2005 Henning Gerhardt - * Copyright 2006 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 - */ - -#pragma code_page(65001) - -LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Lokaler Anschluss" - IDS_LOCALMONITOR "Lokale Anzeige" -} Index: dll/win32/localspl/lang/spl_En.rc =================================================================== --- dll/win32/localspl/lang/spl_En.rc (revision 73027) +++ dll/win32/localspl/lang/spl_En.rc (nonexistent) @@ -1,28 +0,0 @@ -/* - * English resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 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 - */ - -LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Local Port" - IDS_LOCALMONITOR "Local Monitor" -} Index: dll/win32/localspl/lang/spl_Es.rc =================================================================== --- dll/win32/localspl/lang/spl_Es.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Es.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Spanish resources for localspl - * - * Copyright 2010 José Manuel Ferrer Ortiz - * - * 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Puerto local" - IDS_LOCALMONITOR "Monitor local" -} Index: dll/win32/localspl/lang/spl_Fr.rc =================================================================== --- dll/win32/localspl/lang/spl_Fr.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Fr.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * French resources for localspl - * - * Copyright 2007 Jonathan Ernst - * - * 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 - */ - -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Port local" - IDS_LOCALMONITOR "Moniteur local" -} Index: dll/win32/localspl/lang/spl_He.rc =================================================================== --- dll/win32/localspl/lang/spl_He.rc (revision 73027) +++ dll/win32/localspl/lang/spl_He.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Hebrew resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 Detlef Riekenberg - * - * Translated by Baruch Rutman - * - * 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 - */ - -LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "יציאה מקומית" - IDS_LOCALMONITOR "ניטור מקומי" -} Index: dll/win32/localspl/lang/spl_Hu.rc =================================================================== --- dll/win32/localspl/lang/spl_Hu.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Hu.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Hungarian resources for localspl - * - * Copyright 2010 Andras Kovacs - * - * 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Helyi Port" - IDS_LOCALMONITOR "Helyi figyelő" -} Index: dll/win32/localspl/lang/spl_It.rc =================================================================== --- dll/win32/localspl/lang/spl_It.rc (revision 73027) +++ dll/win32/localspl/lang/spl_It.rc (nonexistent) @@ -1,31 +0,0 @@ -/* - * Italian resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Porta locale" - IDS_LOCALMONITOR "Schermo locale" -} Index: dll/win32/localspl/lang/spl_Ja.rc =================================================================== --- dll/win32/localspl/lang/spl_Ja.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Ja.rc (nonexistent) @@ -1,31 +0,0 @@ -/* - * Japanese resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "ローカル ポート" - IDS_LOCALMONITOR "ローカル モニタ" -} Index: dll/win32/localspl/lang/spl_Ko.rc =================================================================== --- dll/win32/localspl/lang/spl_Ko.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Ko.rc (nonexistent) @@ -1,29 +0,0 @@ -/* - * Korean resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 Detlef Riekenberg - * Copyright 2006 YunSong Hwang - * - * 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 - */ - -LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "지역 포트" - IDS_LOCALMONITOR "지역 모니터" -} Index: dll/win32/localspl/lang/spl_Lt.rc =================================================================== --- dll/win32/localspl/lang/spl_Lt.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Lt.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Lithuanian resources for localspl - * - * Copyright 2009 Aurimas Fišeras - * - * 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Vietinis prievadas" - IDS_LOCALMONITOR "Vietinis monitorius" -} Index: dll/win32/localspl/lang/spl_Nl.rc =================================================================== --- dll/win32/localspl/lang/spl_Nl.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Nl.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Dutch resources for localspl - * - * Copyright 2008 Frans Kool - * - * 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 - */ - -LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Lokale Poort" - IDS_LOCALMONITOR "Lokale Monitor" -} Index: dll/win32/localspl/lang/spl_No.rc =================================================================== --- dll/win32/localspl/lang/spl_No.rc (revision 73027) +++ dll/win32/localspl/lang/spl_No.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Norwegian Bokmål resources for localspl - * - * Copyright 2006 Alexander N. Sørnes - * - * 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 - */ - -LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL - -STRINGTABLE -{ - IDS_LOCALPORT "Lokal port" - IDS_LOCALMONITOR "Lokal overvåker" -} Index: dll/win32/localspl/lang/spl_Pl.rc =================================================================== --- dll/win32/localspl/lang/spl_Pl.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Pl.rc (nonexistent) @@ -1,29 +0,0 @@ -/* - * Polish resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 Detlef Riekenberg - * Copyright 2007 Mikolaj Zalewski - * - * 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 - */ - -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Port lokalny" - IDS_LOCALMONITOR "Monitor lokalny" -} Index: dll/win32/localspl/lang/spl_Pt.rc =================================================================== --- dll/win32/localspl/lang/spl_Pt.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Pt.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Portuguese resources for localspl - * - * Copyright 2008 Ricardo Filipe - * - * 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 - */ - -LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Porta local" - IDS_LOCALMONITOR "Monitor Local" -} Index: dll/win32/localspl/lang/spl_Ro.rc =================================================================== --- dll/win32/localspl/lang/spl_Ro.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Ro.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Copyright 2005 Huw Davies - * Copyright 2006 Detlef Riekenberg - * Copyright 2008 Michael Stefaniuc - * 2011 Fulea Ștefan - * - * 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 - */ - -#pragma code_page(65001) - -LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Port local" - IDS_LOCALMONITOR "Ecran local" -} Index: dll/win32/localspl/lang/spl_Ru.rc =================================================================== --- dll/win32/localspl/lang/spl_Ru.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Ru.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Russian resources for localspl - * - * Copyright 2008 Vitaliy Margolen - * - * 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Локальный порт" - IDS_LOCALMONITOR "Локальный монитор" -} Index: dll/win32/localspl/lang/spl_Si.rc =================================================================== --- dll/win32/localspl/lang/spl_Si.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Si.rc (nonexistent) @@ -1,29 +0,0 @@ -/* - * Slovenian resources for localspl - * - * Copyright 2008 Rok Mandeljc - * - * 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 - */ - -#pragma code_page(65001) - -LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Lokalna vrata" - IDS_LOCALMONITOR "Lokalen monitor" -} Index: dll/win32/localspl/lang/spl_Sq.rc =================================================================== --- dll/win32/localspl/lang/spl_Sq.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Sq.rc (nonexistent) @@ -1,29 +0,0 @@ -/* - * English resources for localspl - * - * Copyright 2005 Huw Davies - * Copyright 2006 Detlef Riekenberg - * Translation: Ardit Dani (ALbanian Translation Resource File) - * - * 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 - */ - -LANGUAGE LANG_ALBANIAN, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Porti Vendor" - IDS_LOCALMONITOR "Monitorim Vendor" -} Index: dll/win32/localspl/lang/spl_Sv.rc =================================================================== --- dll/win32/localspl/lang/spl_Sv.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Sv.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Swedish resources for localspl - * - * Copyright 2007 Daniel Nylander - * - * 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 - */ - -LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL - -STRINGTABLE -{ - IDS_LOCALPORT "Lokal port" - IDS_LOCALMONITOR "Lokal skärm" -} Index: dll/win32/localspl/lang/spl_Tr.rc =================================================================== --- dll/win32/localspl/lang/spl_Tr.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Tr.rc (nonexistent) @@ -1,27 +0,0 @@ -/* - * Turkish resources for localspl - * - * Copyright: 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) - * - * 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 - */ - -LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Yerli Giriş" - IDS_LOCALMONITOR "Yerli İzleyici" -} Index: dll/win32/localspl/lang/spl_Uk.rc =================================================================== --- dll/win32/localspl/lang/spl_Uk.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Uk.rc (nonexistent) @@ -1,30 +0,0 @@ -/* - * Ukrainian resources for localspl - * - * Copyright 2010 Igor Paliychuk - * - * 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 - */ - -/* UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -STRINGTABLE -{ - IDS_LOCALPORT "Локальний порт" - IDS_LOCALMONITOR "Локальний монітор" -} Index: dll/win32/localspl/lang/spl_Zh.rc =================================================================== --- dll/win32/localspl/lang/spl_Zh.rc (revision 73027) +++ dll/win32/localspl/lang/spl_Zh.rc (nonexistent) @@ -1,38 +0,0 @@ -/* - * localspl (Simplified and Traditional Chinese Resources) - * - * Copyright 2008 Hongbo Ni - * - * 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 - */ - -/* Chinese text is encoded in UTF-8 */ -#pragma code_page(65001) - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED - -STRINGTABLE -{ - IDS_LOCALPORT "本地端口" - IDS_LOCALMONITOR "本地监视器" -} - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL - -STRINGTABLE -{ - IDS_LOCALPORT "本地端口" - IDS_LOCALMONITOR "本地監視器" -} Index: dll/win32/localspl/localmon.c =================================================================== --- dll/win32/localspl/localmon.c (revision 73027) +++ dll/win32/localspl/localmon.c (nonexistent) @@ -1,793 +0,0 @@ -/* - * Implementation of the Local Printmonitor - * - * Copyright 2006 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 "localspl_private.h" - -#include "resource.h" - -/*****************************************************/ - -static CRITICAL_SECTION port_handles_cs; -static CRITICAL_SECTION_DEBUG port_handles_cs_debug = -{ - 0, 0, &port_handles_cs, - { &port_handles_cs_debug.ProcessLocksList, &port_handles_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": port_handles_cs") } -}; -static CRITICAL_SECTION port_handles_cs = { &port_handles_cs_debug, -1, 0, 0, 0, 0 }; - - -static CRITICAL_SECTION xcv_handles_cs; -static CRITICAL_SECTION_DEBUG xcv_handles_cs_debug = -{ - 0, 0, &xcv_handles_cs, - { &xcv_handles_cs_debug.ProcessLocksList, &xcv_handles_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": xcv_handles_cs") } -}; -static CRITICAL_SECTION xcv_handles_cs = { &xcv_handles_cs_debug, -1, 0, 0, 0, 0 }; - -/* ############################### */ - -typedef struct { - struct list entry; - DWORD type; - WCHAR nameW[1]; -} port_t; - -typedef struct { - struct list entry; - ACCESS_MASK GrantedAccess; - WCHAR nameW[1]; -} xcv_t; - -static struct list port_handles = LIST_INIT( port_handles ); -static struct list xcv_handles = LIST_INIT( xcv_handles ); - -/* ############################### */ - -static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0}; -static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0}; -static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e', - 'L','P','T','P','o','r','t', - 'C','o','m','m','a','n','d','O','K',0}; - -static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t', - 'D','e','f','a','u','l','t', - 'C','o','m','m','C','o','n','f','i','g',0}; - -static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t', - 'T','r','a','n','s','m','i','s','s','i','o','n', - 'R','e','t','r','y','T','i','m','e','o','u','t',0}; - -static const WCHAR cmd_MonitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; -static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0}; -static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t', - 'D','e','f','a','u','l','t', - 'C','o','m','m','C','o','n','f','i','g',0}; - -static const WCHAR dllnameuiW[] = {'l','o','c','a','l','u','i','.','d','l','l',0}; -static const WCHAR emptyW[] = {0}; -static const WCHAR LocalPortW[] = {'L','o','c','a','l',' ','P','o','r','t',0}; - -static const WCHAR portname_LPT[] = {'L','P','T',0}; -static const WCHAR portname_COM[] = {'C','O','M',0}; -static const WCHAR portname_FILE[] = {'F','I','L','E',':',0}; -static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0}; -static const WCHAR portname_LPR[] = {'L','P','R',':',0}; - -static const WCHAR TransmissionRetryTimeoutW[] = {'T','r','a','n','s','m','i','s','s','i','o','n', - 'R','e','t','r','y','T','i','m','e','o','u','t',0}; - -static const WCHAR WinNT_CV_PortsW[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s',' ','N','T','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'P','o','r','t','s',0}; - -static const WCHAR WinNT_CV_WindowsW[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s',' ','N','T','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'W','i','n','d','o','w','s',0}; - - -/****************************************************************** - * does_port_exist (internal) - * - * returns TRUE, when the Port already exists - * - */ -static BOOL does_port_exist(LPCWSTR myname) -{ - - LPPORT_INFO_1W pi; - DWORD needed = 0; - DWORD returned; - DWORD id; - - TRACE("(%s)\n", debugstr_w(myname)); - - id = EnumPortsW(NULL, 1, NULL, 0, &needed, &returned); - pi = heap_alloc(needed); - returned = 0; - if (pi) - id = EnumPortsW(NULL, 1, (LPBYTE) pi, needed, &needed, &returned); - - if (id && returned > 0) { - /* we got a number of valid names. */ - for (id = 0; id < returned; id++) - { - if (lstrcmpiW(myname, pi[id].pName) == 0) { - TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName)); - heap_free(pi); - return TRUE; - } - } - } - - heap_free(pi); - return FALSE; -} - -/****************************************************************** - * enumerate the local Ports from the Registry (internal) - * - * See localmon_EnumPortsW. - * - * NOTES - * returns the needed size (in bytes) for pPorts - * and *lpreturned is set to number of entries returned in pPorts - * - */ - -static DWORD get_ports_from_reg(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned) -{ - HKEY hroot = 0; - LPWSTR ptr; - LPPORT_INFO_2W out; - WCHAR portname[MAX_PATH]; - WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; - WCHAR res_MonitorW[IDS_LOCALMONITOR_MAXLEN]; - INT reslen_PortW; - INT reslen_MonitorW; - DWORD len; - DWORD res; - DWORD needed = 0; - DWORD numentries; - DWORD entrysize; - DWORD id = 0; - - TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); - - entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W); - - numentries = *lpreturned; /* this is 0, when we scan the registry */ - needed = entrysize * numentries; - ptr = (LPWSTR) &pPorts[needed]; - - if (needed > cbBuf) pPorts = NULL; /* No buffer for the structs */ - - numentries = 0; - needed = 0; - - /* we do not check more parameters as done in windows */ - if ((level < 1) || (level > 2)) { - goto getports_cleanup; - } - - /* "+1" for '\0' */ - reslen_MonitorW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALMONITOR, res_MonitorW, IDS_LOCALMONITOR_MAXLEN) + 1; - reslen_PortW = LoadStringW(LOCALSPL_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN) + 1; - - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); - if (res == ERROR_SUCCESS) { - - /* Scan all Port-Names */ - while (res == ERROR_SUCCESS) { - len = MAX_PATH; - portname[0] = '\0'; - res = RegEnumValueW(hroot, id, portname, &len, NULL, NULL, NULL, NULL); - - if ((res == ERROR_SUCCESS) && (portname[0])) { - numentries++; - /* calculate the required size */ - needed += entrysize; - needed += (len + 1) * sizeof(WCHAR); - if (level > 1) { - needed += (reslen_MonitorW + reslen_PortW) * sizeof(WCHAR); - } - - /* Now fill the user-buffer, if available */ - if (pPorts && (cbBuf >= needed)){ - out = (LPPORT_INFO_2W) pPorts; - pPorts += entrysize; - TRACE("%p: writing PORT_INFO_%dW #%d (%s)\n", out, level, numentries, debugstr_w(portname)); - out->pPortName = ptr; - lstrcpyW(ptr, portname); /* Name of the Port */ - ptr += (len + 1); - if (level > 1) { - out->pMonitorName = ptr; - lstrcpyW(ptr, res_MonitorW); /* Name of the Monitor */ - ptr += reslen_MonitorW; - - out->pDescription = ptr; - lstrcpyW(ptr, res_PortW); /* Port Description */ - ptr += reslen_PortW; - - out->fPortType = PORT_TYPE_WRITE; - out->Reserved = 0; - } - } - id++; - } - } - RegCloseKey(hroot); - } - else - { - ERR("failed with %d for %s\n", res, debugstr_w(WinNT_CV_PortsW)); - SetLastError(res); - } - -getports_cleanup: - *lpreturned = numentries; - TRACE("need %d byte for %d entries (%d)\n", needed, numentries, GetLastError()); - return needed; -} - -/***************************************************** - * get_type_from_name (internal) - * - */ - -static DWORD get_type_from_name(LPCWSTR name) -{ - HANDLE hfile; - - if (!strncmpW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1)) - return PORT_IS_LPT; - - if (!strncmpW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1)) - return PORT_IS_COM; - - if (!strcmpW(name, portname_FILE)) - return PORT_IS_FILE; - - if (name[0] == '/') - return PORT_IS_UNIXNAME; - - if (name[0] == '|') - return PORT_IS_PIPE; - - if (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1)) - return PORT_IS_CUPS; - - if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -1)) - return PORT_IS_LPR; - - /* Must be a file or a directory. Does the file exist ? */ - hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name)); - if (hfile == INVALID_HANDLE_VALUE) { - /* Can we create the file? */ - hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); - TRACE("%p for OPEN_ALWAYS\n", hfile); - } - if (hfile != INVALID_HANDLE_VALUE) { - CloseHandle(hfile); - return PORT_IS_FILENAME; - } - /* We can't use the name. use GetLastError() for the reason */ - return PORT_IS_UNKNOWN; -} - -/***************************************************** - * get_type_from_local_name (internal) - * - */ - -static DWORD get_type_from_local_name(LPCWSTR nameW) -{ - LPPORT_INFO_1W pi; - LPWSTR myname = NULL; - DWORD needed = 0; - DWORD numentries = 0; - DWORD id = 0; - - TRACE("(%s)\n", debugstr_w(myname)); - - needed = get_ports_from_reg(1, NULL, 0, &numentries); - pi = heap_alloc(needed); - if (pi) - needed = get_ports_from_reg(1, (LPBYTE) pi, needed, &numentries); - - if (pi && needed && numentries > 0) { - /* we got a number of valid ports. */ - - while ((myname == NULL) && (id < numentries)) - { - if (lstrcmpiW(nameW, pi[id].pName) == 0) { - TRACE("(%u) found %s\n", id, debugstr_w(pi[id].pName)); - myname = pi[id].pName; - } - id++; - } - } - - id = (myname) ? get_type_from_name(myname) : PORT_IS_UNKNOWN; - - heap_free(pi); - return id; - -} -/****************************************************************************** - * localmon_AddPortExW [exported through MONITOREX] - * - * Add a Port, without presenting a user interface - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * level [I] Structure-Level (1) for pBuffer - * pBuffer [I] PTR to the Input-Data (PORT_INFO_1) - * pMonitorName [I] Name of the Monitor that manage the Port - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Level 2 is documented on MSDN for Portmonitors, but not supported by the - * "Local Port" Portmonitor (localspl.dll / localmon.dll) - */ -static BOOL WINAPI localmon_AddPortExW(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName) -{ - PORT_INFO_1W * pi; - HKEY hroot; - DWORD res; - - pi = (PORT_INFO_1W *) pBuffer; - TRACE("(%s, %d, %p, %s) => %s\n", debugstr_w(pName), level, pBuffer, - debugstr_w(pMonitorName), debugstr_w(pi ? pi->pName : NULL)); - - - if ((pMonitorName == NULL) || (lstrcmpiW(pMonitorName, LocalPortW) != 0 ) || - (pi == NULL) || (pi->pName == NULL) || (pi->pName[0] == '\0') ) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (level != 1) { - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); - if (res == ERROR_SUCCESS) { - if (does_port_exist(pi->pName)) { - RegCloseKey(hroot); - TRACE("=> FALSE with %u\n", ERROR_INVALID_PARAMETER); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - res = RegSetValueExW(hroot, pi->pName, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW)); - RegCloseKey(hroot); - } - if (res != ERROR_SUCCESS) SetLastError(ERROR_INVALID_PARAMETER); - TRACE("=> %u with %u\n", (res == ERROR_SUCCESS), GetLastError()); - return (res == ERROR_SUCCESS); -} - -/***************************************************** - * localmon_ClosePort [exported through MONITOREX] - * - * Close a - * - * PARAMS - * hPort [i] The Handle to close - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI localmon_ClosePort(HANDLE hPort) -{ - port_t * port = hPort; - - TRACE("(%p)\n", port); - EnterCriticalSection(&port_handles_cs); - list_remove(&port->entry); - LeaveCriticalSection(&port_handles_cs); - heap_free(port); - return TRUE; -} - -/***************************************************** - * localmon_EnumPortsW [exported through MONITOREX] - * - * Enumerate all local Ports - * - * PARAMS - * pName [I] Servername (ignored) - * level [I] Structure-Level (1 or 2) - * pPorts [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pPorts - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts - * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small - * - * NOTES - *| Windows ignores pName - *| Windows crash the app, when pPorts, pcbNeeded or pcReturned are NULL - *| Windows >NT4.0 does not check for illegal levels (TRUE is returned) - * - * ToDo - * "HCU\Software\Wine\Spooler\" - redirection - * - */ -static BOOL WINAPI localmon_EnumPortsW(LPWSTR pName, DWORD level, LPBYTE pPorts, - DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - BOOL res = FALSE; - DWORD needed; - DWORD numentries; - - TRACE("(%s, %d, %p, %d, %p, %p)\n", - debugstr_w(pName), level, pPorts, cbBuf, pcbNeeded, pcReturned); - - numentries = 0; - needed = get_ports_from_reg(level, NULL, 0, &numentries); - /* we calculated the needed buffersize. now do the error-checks */ - if (cbBuf < needed) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto cleanup; - } - - /* fill the buffer with the Port-Names */ - needed = get_ports_from_reg(level, pPorts, cbBuf, &numentries); - res = TRUE; - - if (pcReturned) *pcReturned = numentries; - -cleanup: - if (pcbNeeded) *pcbNeeded = needed; - - TRACE("returning %d with %d (%d byte for %d entries)\n", - res, GetLastError(), needed, numentries); - - return (res); -} - -/***************************************************** - * localmon_OpenPort [exported through MONITOREX] - * - * Open a Data-Channel for a Port - * - * PARAMS - * pName [i] Name of selected Object - * phPort [o] The resulting Handle is stored here - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI localmon_OpenPortW(LPWSTR pName, PHANDLE phPort) -{ - port_t * port; - DWORD type; - - TRACE("%s, %p)\n", debugstr_w(pName), phPort); - - /* an empty name is invalid */ - if (!pName[0]) return FALSE; - - /* does the port exist? */ - type = get_type_from_local_name(pName); - if (!type) return FALSE; - - port = heap_alloc(FIELD_OFFSET(port_t, nameW[lstrlenW(pName) + 1])); - if (!port) return FALSE; - - port->type = type; - lstrcpyW(port->nameW, pName); - *phPort = port; - - EnterCriticalSection(&port_handles_cs); - list_add_tail(&port_handles, &port->entry); - LeaveCriticalSection(&port_handles_cs); - - TRACE("=> %p\n", port); - return TRUE; -} - -/***************************************************** - * localmon_XcvClosePort [exported through MONITOREX] - * - * Close a Communication-Channel - * - * PARAMS - * hXcv [i] The Handle to close - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI localmon_XcvClosePort(HANDLE hXcv) -{ - xcv_t * xcv = hXcv; - - TRACE("(%p)\n", xcv); - /* No checks are done in Windows */ - EnterCriticalSection(&xcv_handles_cs); - list_remove(&xcv->entry); - LeaveCriticalSection(&xcv_handles_cs); - heap_free(xcv); - return TRUE; -} - -/***************************************************** - * localmon_XcvDataPort [exported through MONITOREX] - * - * Execute command through a Communication-Channel - * - * PARAMS - * hXcv [i] The Handle to work with - * pszDataName [i] Name of the command to execute - * pInputData [i] Buffer for extra Input Data (needed only for some commands) - * cbInputData [i] Size in Bytes of Buffer at pInputData - * pOutputData [o] Buffer to receive additional Data (needed only for some commands) - * cbOutputData [i] Size in Bytes of Buffer at pOutputData - * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData - * - * RETURNS - * Success: ERROR_SUCCESS - * Failure: win32 error code - * - * NOTES - * - * Minimal List of commands, that every Printmonitor DLL should support: - * - *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData - *| "AddPort" : Add a Port (Name as WSTR in pInputData) - *| "DeletePort": Delete a Port (Name as WSTR in pInputData) - * - * - */ -static DWORD WINAPI localmon_XcvDataPort(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, - PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) -{ - WCHAR buffer[16]; /* buffer for a decimal number */ - LPWSTR ptr; - DWORD res; - DWORD needed; - HKEY hroot; - - TRACE("(%p, %s, %p, %d, %p, %d, %p)\n", hXcv, debugstr_w(pszDataName), - pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); - - if (!lstrcmpW(pszDataName, cmd_AddPortW)) { - TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); - if (res == ERROR_SUCCESS) { - if (does_port_exist((LPWSTR) pInputData)) { - RegCloseKey(hroot); - TRACE("=> %u\n", ERROR_ALREADY_EXISTS); - return ERROR_ALREADY_EXISTS; - } - res = RegSetValueExW(hroot, (LPWSTR) pInputData, 0, REG_SZ, (const BYTE *) emptyW, sizeof(emptyW)); - RegCloseKey(hroot); - } - TRACE("=> %u\n", res); - return res; - } - - - if (!lstrcmpW(pszDataName, cmd_ConfigureLPTPortCommandOKW)) { - TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); - res = RegCreateKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot); - if (res == ERROR_SUCCESS) { - res = RegSetValueExW(hroot, TransmissionRetryTimeoutW, 0, REG_SZ, pInputData, cbInputData); - RegCloseKey(hroot); - } - return res; - } - - if (!lstrcmpW(pszDataName, cmd_DeletePortW)) { - TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_PortsW, &hroot); - if (res == ERROR_SUCCESS) { - res = RegDeleteValueW(hroot, (LPWSTR) pInputData); - RegCloseKey(hroot); - TRACE("=> %u with %u\n", res, GetLastError() ); - return res; - } - return ERROR_FILE_NOT_FOUND; - } - - if (!lstrcmpW(pszDataName, cmd_GetDefaultCommConfigW)) { - TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); - *pcbOutputNeeded = cbOutputData; - res = GetDefaultCommConfigW((LPWSTR) pInputData, (LPCOMMCONFIG) pOutputData, pcbOutputNeeded); - TRACE("got %u with %u\n", res, GetLastError() ); - return res ? ERROR_SUCCESS : GetLastError(); - } - - if (!lstrcmpW(pszDataName, cmd_GetTransmissionRetryTimeoutW)) { - * pcbOutputNeeded = sizeof(DWORD); - if (cbOutputData >= sizeof(DWORD)) { - /* the w2k resource kit documented a default of 90, but that's wrong */ - *((LPDWORD) pOutputData) = 45; - - res = RegOpenKeyW(HKEY_LOCAL_MACHINE, WinNT_CV_WindowsW, &hroot); - if (res == ERROR_SUCCESS) { - needed = sizeof(buffer) - sizeof(WCHAR); - res = RegQueryValueExW(hroot, TransmissionRetryTimeoutW, NULL, NULL, (LPBYTE) buffer, &needed); - if ((res == ERROR_SUCCESS) && (buffer[0])) { - *((LPDWORD) pOutputData) = strtoulW(buffer, NULL, 0); - } - RegCloseKey(hroot); - } - return ERROR_SUCCESS; - } - return ERROR_INSUFFICIENT_BUFFER; - } - - - if (!lstrcmpW(pszDataName, cmd_MonitorUIW)) { - * pcbOutputNeeded = sizeof(dllnameuiW); - if (cbOutputData >= sizeof(dllnameuiW)) { - memcpy(pOutputData, dllnameuiW, sizeof(dllnameuiW)); - return ERROR_SUCCESS; - } - return ERROR_INSUFFICIENT_BUFFER; - } - - if (!lstrcmpW(pszDataName, cmd_PortIsValidW)) { - TRACE("InputData (%d): %s\n", cbInputData, debugstr_w( (LPWSTR) pInputData)); - res = get_type_from_name((LPCWSTR) pInputData); - TRACE("detected as %u\n", res); - /* names, that we have recognized, are valid */ - if (res) return ERROR_SUCCESS; - - /* ERROR_ACCESS_DENIED, ERROR_PATH_NOT_FOUND or something else */ - TRACE("=> %u\n", GetLastError()); - return GetLastError(); - } - - if (!lstrcmpW(pszDataName, cmd_SetDefaultCommConfigW)) { - /* get the portname from the Handle */ - ptr = strchrW(((xcv_t *)hXcv)->nameW, ' '); - if (ptr) { - ptr++; /* skip the space */ - } - else - { - ptr = ((xcv_t *)hXcv)->nameW; - } - lstrcpynW(buffer, ptr, sizeof(buffer)/sizeof(WCHAR)); - if (buffer[0]) buffer[lstrlenW(buffer)-1] = '\0'; /* remove the ':' */ - res = SetDefaultCommConfigW(buffer, (LPCOMMCONFIG) pInputData, cbInputData); - TRACE("got %u with %u\n", res, GetLastError() ); - return res ? ERROR_SUCCESS : GetLastError(); - } - - FIXME("command not supported: %s\n", debugstr_w(pszDataName)); - return ERROR_INVALID_PARAMETER; -} - -/***************************************************** - * localmon_XcvOpenPort [exported through MONITOREX] - * - * Open a Communication-Channel - * - * PARAMS - * pName [i] Name of selected Object - * GrantedAccess [i] Access-Rights to use - * phXcv [o] The resulting Handle is stored here - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI localmon_XcvOpenPort(LPCWSTR pName, ACCESS_MASK GrantedAccess, PHANDLE phXcv) -{ - xcv_t * xcv; - - TRACE("%s, 0x%x, %p)\n", debugstr_w(pName), GrantedAccess, phXcv); - /* No checks for any field is done in Windows */ - xcv = heap_alloc(FIELD_OFFSET(xcv_t, nameW[lstrlenW(pName) + 1])); - if (xcv) { - xcv->GrantedAccess = GrantedAccess; - lstrcpyW(xcv->nameW, pName); - *phXcv = xcv; - EnterCriticalSection(&xcv_handles_cs); - list_add_tail(&xcv_handles, &xcv->entry); - LeaveCriticalSection(&xcv_handles_cs); - TRACE("=> %p\n", xcv); - return TRUE; - } - else - { - *phXcv = NULL; - return FALSE; - } -} - -/***************************************************** - * InitializePrintMonitor (LOCALSPL.@) - * - * Initialize the Monitor for the Local Ports - * - * PARAMS - * regroot [I] Registry-Path, where the settings are stored - * - * RETURNS - * Success: Pointer to a MONITOREX Structure - * Failure: NULL - * - * NOTES - * The fixed location "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Ports" - * is used to store the Ports (IniFileMapping from "win.ini", Section "Ports"). - * Native localspl.dll fails, when no valid Port-Entry is present. - * - */ - -LPMONITOREX WINAPI InitializePrintMonitor(LPWSTR regroot) -{ - static MONITOREX mymonitorex = - { - sizeof(MONITOREX) - sizeof(DWORD), - { - localmon_EnumPortsW, - localmon_OpenPortW, - NULL, /* localmon_OpenPortExW */ - NULL, /* localmon_StartDocPortW */ - NULL, /* localmon_WritePortW */ - NULL, /* localmon_ReadPortW */ - NULL, /* localmon_EndDocPortW */ - localmon_ClosePort, - NULL, /* Use AddPortUI in localui.dll */ - localmon_AddPortExW, - NULL, /* Use ConfigurePortUI in localui.dll */ - NULL, /* Use DeletePortUI in localui.dll */ - NULL, /* localmon_GetPrinterDataFromPort */ - NULL, /* localmon_SetPortTimeOuts */ - localmon_XcvOpenPort, - localmon_XcvDataPort, - localmon_XcvClosePort - } - }; - - TRACE("(%s)\n", debugstr_w(regroot)); - /* Parameter "regroot" is ignored on NT4.0 (localmon.dll) */ - if (!regroot || !regroot[0]) { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - TRACE("=> %p\n", &mymonitorex); - /* Native windows returns always the same pointer on success */ - return &mymonitorex; -} Index: dll/win32/localspl/localspl.rc =================================================================== --- dll/win32/localspl/localspl.rc (revision 73027) +++ dll/win32/localspl/localspl.rc (nonexistent) @@ -1,107 +0,0 @@ -/* - * Top level resource file for localspl - * - * Copyright 2006 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 "resource.h" - -#define WINE_FILENAME_STR "localspl.dll" -#define WINE_FILEDESCRIPTION_STR "Wine Printer spooler component" - -/* Same Version as WinXP_sp2 */ -#define WINE_FILEVERSION 5,1,2600,2180 -#define WINE_FILEVERSION_STR "5.1.2600.2180" - -#define WINE_PRODUCTVERSION 5,1,2600,2180 -#define WINE_PRODUCTVERSION_STR "5.1.2600.2180" - -#include - -/* UTF-8 */ -#pragma code_page(65001) - -#ifdef LANGUAGE_DA_DK - #include "lang/spl_Da.rc" -#endif -#ifdef LANGUAGE_DE_DE - #include "lang/spl_De.rc" -#endif -#ifdef LANGUAGE_EN_US - #include "lang/spl_En.rc" -#endif -#ifdef LANGUAGE_ES_ES - #include "lang/spl_Es.rc" -#endif -#ifdef LANGUAGE_FR_FR - #include "lang/spl_Fr.rc" -#endif -#ifdef LANGUAGE_HE_IL - #include "lang/spl_He.rc" -#endif -#ifdef LANGUAGE_HU_HU - #include "lang/spl_Hu.rc" -#endif -#ifdef LANGUAGE_IT_IT - #include "lang/spl_It.rc" -#endif -#ifdef LANGUAGE_JA_JP - #include "lang/spl_Ja.rc" -#endif -#ifdef LANGUAGE_KO_KR - #include "lang/spl_Ko.rc" -#endif -#ifdef LANGUAGE_LT_LT - #include "lang/spl_Lt.rc" -#endif -#ifdef LANGUAGE_NL_NL - #include "lang/spl_Nl.rc" -#endif -#ifdef LANGUAGE_NO_NO - #include "lang/spl_No.rc" -#endif -#ifdef LANGUAGE_PL_PL - #include "lang/spl_Pl.rc" -#endif -#ifdef LANGUAGE_PT_PT - #include "lang/spl_Pt.rc" -#endif -#ifdef LANGUAGE_RO_RO - #include "lang/spl_Ro.rc" -#endif -#ifdef LANGUAGE_RU_RU - #include "lang/spl_Ru.rc" -#endif -#ifdef LANGUAGE_SL_SI - #include "lang/spl_Si.rc" -#endif -#ifdef LANGUAGE_SQ_AL - #include "lang/spl_Sq.rc" -#endif -#ifdef LANGUAGE_SV_SE - #include "lang/spl_Sv.rc" -#endif -#ifdef LANGUAGE_TR_TR - #include "lang/spl_Tr.rc" -#endif -#ifdef LANGUAGE_UK_UA - #include "lang/spl_Uk.rc" -#endif -#ifdef LANGUAGE_ZH_CN - #include "lang/spl_Zh.rc" -#endif Index: dll/win32/localspl/localspl.spec =================================================================== --- dll/win32/localspl/localspl.spec (revision 73027) +++ dll/win32/localspl/localspl.spec (nonexistent) @@ -1,64 +0,0 @@ -@ stub ClosePrintProcessor -@ stub ControlPrintProcessor -@ stub EnumPrintProcessorDatatypesW -@ stub GetPrintProcessorCapabilities -@ stdcall InitializePrintMonitor(wstr) -# "Providor" is no typo here -@ stdcall InitializePrintProvidor(ptr long wstr) -@ stub OpenPrintProcessor -@ stub PrintDocumentOnPrintProcessor -@ stub PrintProcLogEvent -@ stub SplAddForm -@ stub SplAddMonitor -@ stub SplAddPort -@ stub SplAddPortEx -@ stub SplAddPrinter -@ stub SplAddPrinterDriverEx -@ stub SplAddPrintProcessor -@ stub SplBroadcastChange -@ stub SplClosePrinter -@ stub SplCloseSpooler -@ stub SplConfigChange -@ stub SplCopyFileEvent -@ stub SplCopyNumberOfFiles -@ stub SplCreateSpooler -@ stub SplDeleteForm -@ stub SplDeleteMonitor -@ stub SplDeletePort -@ stub SplDeletePrinter -@ stub SplDeletePrinterDriverEx -@ stub SplDeletePrinterKey -@ stub SplDeletePrintProcessor -@ stub SplDeleteSpooler -@ stub SplDriverEvent -@ stub SplEnumForms -@ stub SplEnumMonitors -@ stub SplEnumPorts -@ stub SplEnumPrinterDataEx -@ stub SplEnumPrinterKey -@ stub SplEnumPrinters -@ stub SplEnumPrintProcessorDatatypes -@ stub SplEnumPrintProcessors -@ stub SplGetDriverDir -@ stub SplGetForm -@ stub SplGetPrinter -@ stub SplGetPrinterData -@ stub SplGetPrinterDataEx -@ stub SplGetPrinterDriver -@ stub SplGetPrinterDriverDirectory -@ stub SplGetPrinterDriverEx -@ stub SplGetPrinterExtra -@ stub SplGetPrinterExtraEx -@ stub SplGetPrintProcessorDirectory -@ stub SplLoadLibraryTheCopyFileModule -@ stub SplMonitorIsInstalled -@ stub SplOpenPrinter -@ stub SplReenumeratePorts -@ stub SplResetPrinter -@ stub SplSetForm -@ stub SplSetPrinter -@ stub SplSetPrinterData -@ stub SplSetPrinterDataEx -@ stub SplSetPrinterExtra -@ stub SplSetPrinterExtraEx -@ stub SplXcvData Index: dll/win32/localspl/localspl_main.c =================================================================== --- dll/win32/localspl/localspl_main.c (revision 73027) +++ dll/win32/localspl/localspl_main.c (nonexistent) @@ -1,44 +0,0 @@ -/* - * Implementation of the Local Printprovider/ Printmonitor/ Prontprocessor - * - * Copyright 2006-2009 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 "localspl_private.h" - -HINSTANCE LOCALSPL_hInstance = NULL; - -/***************************************************** - * DllMain - */ -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); - - switch(fdwReason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls( hinstDLL ); - LOCALSPL_hInstance = hinstDLL; - setup_provider(); - break; - } - return TRUE; -} Index: dll/win32/localspl/localspl_private.h =================================================================== --- dll/win32/localspl/localspl_private.h (revision 73027) +++ dll/win32/localspl/localspl_private.h (nonexistent) @@ -1,89 +0,0 @@ -/* - * Implementation of the Local Printmonitor: internal include file - * - * Copyright 2006 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 - */ - -#ifndef __WINE_LOCALSPL_PRIVATE__ -#define __WINE_LOCALSPL_PRIVATE__ - -#include - -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -#define COBJMACROS -#define NONAMELESSUNION - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -WINE_DEFAULT_DEBUG_CHANNEL(localspl); - -/* ## DLL-wide Globals ## */ -extern HINSTANCE LOCALSPL_hInstance DECLSPEC_HIDDEN; -void setup_provider(void) DECLSPEC_HIDDEN; - -/* ## Type of Ports ## */ -/* windows types */ -#define PORT_IS_UNKNOWN 0 -#define PORT_IS_LPT 1 -#define PORT_IS_COM 2 -#define PORT_IS_FILE 3 -#define PORT_IS_FILENAME 4 - -/* wine extensions */ -#define PORT_IS_WINE 5 -#define PORT_IS_UNIXNAME 5 -#define PORT_IS_PIPE 6 -#define PORT_IS_CUPS 7 -#define PORT_IS_LPR 8 - - -/* ## Memory allocation functions ## */ - -static inline void * __WINE_ALLOC_SIZE(1) heap_alloc( size_t len ) -{ - return HeapAlloc( GetProcessHeap(), 0, len ); -} - -static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero( size_t len ) -{ - return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ); -} - -static inline void * __WINE_ALLOC_SIZE(2) heap_realloc_zero( void * mem, size_t len ) -{ - return HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mem, len ); -} - -static inline BOOL heap_free( void *mem ) -{ - return HeapFree( GetProcessHeap(), 0, mem ); -} - -#endif /* __WINE_LOCALSPL_PRIVATE__ */ Index: dll/win32/localspl/provider.c =================================================================== --- dll/win32/localspl/provider.c (revision 73027) +++ dll/win32/localspl/provider.c (nonexistent) @@ -1,2456 +0,0 @@ -/* - * Implementation of the Local Printprovider - * - * Copyright 2006-2009 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 "localspl_private.h" - -#include -#include - -/* ############################### */ - -static CRITICAL_SECTION monitor_handles_cs; -static CRITICAL_SECTION_DEBUG monitor_handles_cs_debug = -{ - 0, 0, &monitor_handles_cs, - { &monitor_handles_cs_debug.ProcessLocksList, &monitor_handles_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": monitor_handles_cs") } -}; -static CRITICAL_SECTION monitor_handles_cs = { &monitor_handles_cs_debug, -1, 0, 0, 0, 0 }; - -/* ############################### */ - -typedef struct { - WCHAR src[MAX_PATH+MAX_PATH]; - WCHAR dst[MAX_PATH+MAX_PATH]; - DWORD srclen; - DWORD dstlen; - DWORD copyflags; - BOOL lazy; -} apd_data_t; - -typedef struct { - struct list entry; - LPWSTR name; - LPWSTR dllname; - PMONITORUI monitorUI; - LPMONITOR monitor; - HMODULE hdll; - DWORD refcount; - DWORD dwMonitorSize; -} monitor_t; - -typedef struct { - LPCWSTR envname; - LPCWSTR subdir; - DWORD driverversion; - LPCWSTR versionregpath; - LPCWSTR versionsubdir; -} printenv_t; - -typedef struct { - LPWSTR name; - LPWSTR printername; - monitor_t * pm; - HANDLE hXcv; -} printer_t; - -/* ############################### */ - -static struct list monitor_handles = LIST_INIT( monitor_handles ); -static monitor_t * pm_localport; - -static const PRINTPROVIDOR * pprovider = NULL; - -static const WCHAR backslashW[] = {'\\',0}; -static const WCHAR bs_ports_bsW[] = {'\\','P','o','r','t','s','\\',0}; -static const WCHAR configuration_fileW[] = {'C','o','n','f','i','g','u','r','a','t','i','o','n',' ','F','i','l','e',0}; -static const WCHAR datatypeW[] = {'D','a','t','a','t','y','p','e',0}; -static const WCHAR data_fileW[] = {'D','a','t','a',' ','F','i','l','e',0}; -static const WCHAR dependent_filesW[] = {'D','e','p','e','n','d','e','n','t',' ','F','i','l','e','s',0}; -static const WCHAR driverW[] = {'D','r','i','v','e','r',0}; -static const WCHAR emptyW[] = {0}; -static const WCHAR fmt_driversW[] = { 'S','y','s','t','e','m','\\', - 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'c','o','n','t','r','o','l','\\', - 'P','r','i','n','t','\\', - 'E','n','v','i','r','o','n','m','e','n','t','s','\\', - '%','s','\\','D','r','i','v','e','r','s','%','s',0 }; -static const WCHAR fmt_printprocessorsW[] = { 'S','y','s','t','e','m','\\', - 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'P','r','i','n','t','\\', - 'E','n','v','i','r','o','n','m','e','n','t','s','\\','%','s','\\', - 'P','r','i','n','t',' ','P','r','o','c','e','s','s','o','r','s',0 }; -static const WCHAR help_fileW[] = {'H','e','l','p',' ','F','i','l','e',0}; -static const WCHAR ia64_envnameW[] = {'W','i','n','d','o','w','s',' ','I','A','6','4',0}; -static const WCHAR ia64_subdirW[] = {'i','a','6','4',0}; -static const WCHAR localportW[] = {'L','o','c','a','l',' ','P','o','r','t',0}; -static const WCHAR monitorW[] = {'M','o','n','i','t','o','r',0}; -static const WCHAR monitorsW[] = {'S','y','s','t','e','m','\\', - 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'P','r','i','n','t','\\', - 'M','o','n','i','t','o','r','s','\\',0}; -static const WCHAR monitorUIW[] = {'M','o','n','i','t','o','r','U','I',0}; -static const WCHAR previous_namesW[] = {'P','r','e','v','i','o','u','s',' ','N','a','m','e','s',0}; -static const WCHAR printersW[] = {'S','y','s','t','e','m','\\', - 'C','u', 'r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', - 'C','o','n','t','r','o','l','\\', - 'P','r','i','n','t','\\', - 'P','r','i','n','t','e','r','s',0}; -static const WCHAR spoolW[] = {'\\','s','p','o','o','l',0}; -static const WCHAR driversW[] = {'\\','d','r','i','v','e','r','s','\\',0}; -static const WCHAR spoolprtprocsW[] = {'\\','s','p','o','o','l','\\','p','r','t','p','r','o','c','s','\\',0}; -static const WCHAR version0_regpathW[] = {'\\','V','e','r','s','i','o','n','-','0',0}; -static const WCHAR version0_subdirW[] = {'\\','0',0}; -static const WCHAR version3_regpathW[] = {'\\','V','e','r','s','i','o','n','-','3',0}; -static const WCHAR version3_subdirW[] = {'\\','3',0}; -static const WCHAR versionW[] = {'V','e','r','s','i','o','n',0}; -static const WCHAR win40_envnameW[] = {'W','i','n','d','o','w','s',' ','4','.','0',0}; -static const WCHAR win40_subdirW[] = {'w','i','n','4','0',0}; -static const WCHAR winnt_cv_portsW[] = {'S','o','f','t','w','a','r','e','\\', - 'M','i','c','r','o','s','o','f','t','\\', - 'W','i','n','d','o','w','s',' ','N','T','\\', - 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', - 'P','o','r','t','s',0}; -static const WCHAR winprintW[] = {'w','i','n','p','r','i','n','t',0}; -static const WCHAR x64_envnameW[] = {'W','i','n','d','o','w','s',' ','x','6','4',0}; -static const WCHAR x64_subdirW[] = {'x','6','4',0}; -static const WCHAR x86_envnameW[] = {'W','i','n','d','o','w','s',' ','N','T',' ','x','8','6',0}; -static const WCHAR x86_subdirW[] = {'w','3','2','x','8','6',0}; -static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; -static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; - - -static const printenv_t env_ia64 = {ia64_envnameW, ia64_subdirW, 3, - version3_regpathW, version3_subdirW}; - -static const printenv_t env_x86 = {x86_envnameW, x86_subdirW, 3, - version3_regpathW, version3_subdirW}; - -static const printenv_t env_x64 = {x64_envnameW, x64_subdirW, 3, - version3_regpathW, version3_subdirW}; - -static const printenv_t env_win40 = {win40_envnameW, win40_subdirW, 0, - version0_regpathW, version0_subdirW}; - -static const printenv_t * const all_printenv[] = {&env_x86, &env_x64, &env_ia64, &env_win40}; - - -static const DWORD di_sizeof[] = {0, sizeof(DRIVER_INFO_1W), sizeof(DRIVER_INFO_2W), - sizeof(DRIVER_INFO_3W), sizeof(DRIVER_INFO_4W), - sizeof(DRIVER_INFO_5W), sizeof(DRIVER_INFO_6W), - 0, sizeof(DRIVER_INFO_8W)}; - - -/****************************************************************** - * strdupW [internal] - * - * create a copy of a unicode-string - * - */ -static LPWSTR strdupW(LPCWSTR p) -{ - LPWSTR ret; - DWORD len; - - if(!p) return NULL; - len = (lstrlenW(p) + 1) * sizeof(WCHAR); - ret = heap_alloc(len); - if (ret) memcpy(ret, p, len); - return ret; -} - -/****************************************************************** - * apd_copyfile [internal] - * - * Copy a file from the driverdirectory to the versioned directory - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL apd_copyfile( WCHAR *pathname, WCHAR *file_part, apd_data_t *apd ) -{ - WCHAR *srcname; - BOOL res; - - apd->src[apd->srclen] = '\0'; - apd->dst[apd->dstlen] = '\0'; - - if (!pathname || !pathname[0]) { - /* nothing to copy */ - return TRUE; - } - - if (apd->copyflags & APD_COPY_FROM_DIRECTORY) - srcname = pathname; - else - { - srcname = apd->src; - strcatW( srcname, file_part ); - } - strcatW( apd->dst, file_part ); - - TRACE("%s => %s\n", debugstr_w(srcname), debugstr_w(apd->dst)); - - /* FIXME: handle APD_COPY_NEW_FILES */ - res = CopyFileW(srcname, apd->dst, FALSE); - TRACE("got %d with %u\n", res, GetLastError()); - - return apd->lazy || res; -} - -/****************************************************************** - * copy_servername_from_name (internal) - * - * for an external server, the serverpart from the name is copied. - * - * RETURNS - * the length (in WCHAR) of the serverpart (0 for the local computer) - * (-length), when the name is too long - * - */ -static LONG copy_servername_from_name(LPCWSTR name, LPWSTR target) -{ - LPCWSTR server; - LPWSTR ptr; - WCHAR buffer[MAX_COMPUTERNAME_LENGTH +1]; - DWORD len; - DWORD serverlen; - - if (target) *target = '\0'; - - if (name == NULL) return 0; - if ((name[0] != '\\') || (name[1] != '\\')) return 0; - - server = &name[2]; - /* skip over both backslash, find separator '\' */ - ptr = strchrW(server, '\\'); - serverlen = (ptr) ? ptr - server : lstrlenW(server); - - /* servername is empty */ - if (serverlen == 0) return 0; - - TRACE("found %s\n", debugstr_wn(server, serverlen)); - - if (serverlen > MAX_COMPUTERNAME_LENGTH) return -serverlen; - - if (target) { - memcpy(target, server, serverlen * sizeof(WCHAR)); - target[serverlen] = '\0'; - } - - len = sizeof(buffer) / sizeof(buffer[0]); - if (GetComputerNameW(buffer, &len)) { - if ((serverlen == len) && (strncmpiW(server, buffer, len) == 0)) { - /* The requested Servername is our computername */ - return 0; - } - } - return serverlen; -} - -/****************************************************************** - * get_basename_from_name (internal) - * - * skip over the serverpart from the full name - * - */ -static LPCWSTR get_basename_from_name(LPCWSTR name) -{ - if (name == NULL) return NULL; - if ((name[0] == '\\') && (name[1] == '\\')) { - /* skip over the servername and search for the following '\' */ - name = strchrW(&name[2], '\\'); - if ((name) && (name[1])) { - /* found a separator ('\') followed by a name: - skip over the separator and return the rest */ - name++; - } - else - { - /* no basename present (we found only a servername) */ - return NULL; - } - } - return name; -} - -/****************************************************************** - * monitor_unload [internal] - * - * release a printmonitor and unload it from memory, when needed - * - */ -static void monitor_unload(monitor_t * pm) -{ - if (pm == NULL) return; - TRACE("%p (refcount: %d) %s\n", pm, pm->refcount, debugstr_w(pm->name)); - - EnterCriticalSection(&monitor_handles_cs); - - if (pm->refcount) pm->refcount--; - - if (pm->refcount == 0) { - list_remove(&pm->entry); - FreeLibrary(pm->hdll); - heap_free(pm->name); - heap_free(pm->dllname); - heap_free(pm); - } - LeaveCriticalSection(&monitor_handles_cs); -} - -/****************************************************************** - * monitor_unloadall [internal] - * - * release all registered printmonitors and unload them from memory, when needed - * - */ - -static void monitor_unloadall(void) -{ - monitor_t * pm; - monitor_t * next; - - EnterCriticalSection(&monitor_handles_cs); - /* iterate through the list, with safety against removal */ - LIST_FOR_EACH_ENTRY_SAFE(pm, next, &monitor_handles, monitor_t, entry) - { - /* skip monitorui dlls */ - if (pm->monitor) monitor_unload(pm); - } - LeaveCriticalSection(&monitor_handles_cs); -} - -/****************************************************************** - * monitor_load [internal] - * - * load a printmonitor, get the dllname from the registry, when needed - * initialize the monitor and dump found function-pointers - * - * On failure, SetLastError() is called and NULL is returned - */ - -static monitor_t * monitor_load(LPCWSTR name, LPWSTR dllname) -{ - LPMONITOR2 (WINAPI *pInitializePrintMonitor2) (PMONITORINIT, LPHANDLE); - PMONITORUI (WINAPI *pInitializePrintMonitorUI)(VOID); - LPMONITOREX (WINAPI *pInitializePrintMonitor) (LPWSTR); - DWORD (WINAPI *pInitializeMonitorEx)(LPWSTR, LPMONITOR); - DWORD (WINAPI *pInitializeMonitor) (LPWSTR); - - monitor_t * pm = NULL; - monitor_t * cursor; - LPWSTR regroot = NULL; - LPWSTR driver = dllname; - - TRACE("(%s, %s)\n", debugstr_w(name), debugstr_w(dllname)); - /* Is the Monitor already loaded? */ - EnterCriticalSection(&monitor_handles_cs); - - if (name) { - LIST_FOR_EACH_ENTRY(cursor, &monitor_handles, monitor_t, entry) - { - if (cursor->name && (lstrcmpW(name, cursor->name) == 0)) { - pm = cursor; - break; - } - } - } - - if (pm == NULL) { - pm = heap_alloc_zero(sizeof(monitor_t)); - if (pm == NULL) goto cleanup; - list_add_tail(&monitor_handles, &pm->entry); - } - pm->refcount++; - - if (pm->name == NULL) { - /* Load the monitor */ - LPMONITOREX pmonitorEx; - DWORD len; - - if (name) { - len = lstrlenW(monitorsW) + lstrlenW(name) + 2; - regroot = heap_alloc(len * sizeof(WCHAR)); - } - - if (regroot) { - lstrcpyW(regroot, monitorsW); - lstrcatW(regroot, name); - /* Get the Driver from the Registry */ - if (driver == NULL) { - HKEY hroot; - DWORD namesize; - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regroot, &hroot) == ERROR_SUCCESS) { - if (RegQueryValueExW(hroot, driverW, NULL, NULL, NULL, - &namesize) == ERROR_SUCCESS) { - driver = heap_alloc(namesize); - RegQueryValueExW(hroot, driverW, NULL, NULL, (LPBYTE) driver, &namesize) ; - } - RegCloseKey(hroot); - } - } - } - - pm->name = strdupW(name); - pm->dllname = strdupW(driver); - - if ((name && (!regroot || !pm->name)) || !pm->dllname) { - monitor_unload(pm); - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - pm = NULL; - goto cleanup; - } - - pm->hdll = LoadLibraryW(driver); - TRACE("%p: LoadLibrary(%s) => %d\n", pm->hdll, debugstr_w(driver), GetLastError()); - - if (pm->hdll == NULL) { - monitor_unload(pm); - SetLastError(ERROR_MOD_NOT_FOUND); - pm = NULL; - goto cleanup; - } - - pInitializePrintMonitor2 = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor2"); - pInitializePrintMonitorUI = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitorUI"); - pInitializePrintMonitor = (void *)GetProcAddress(pm->hdll, "InitializePrintMonitor"); - pInitializeMonitorEx = (void *)GetProcAddress(pm->hdll, "InitializeMonitorEx"); - pInitializeMonitor = (void *)GetProcAddress(pm->hdll, "InitializeMonitor"); - - - TRACE("%p: %s,pInitializePrintMonitor2\n", pInitializePrintMonitor2, debugstr_w(driver)); - TRACE("%p: %s,pInitializePrintMonitorUI\n", pInitializePrintMonitorUI, debugstr_w(driver)); - TRACE("%p: %s,pInitializePrintMonitor\n", pInitializePrintMonitor, debugstr_w(driver)); - TRACE("%p: %s,pInitializeMonitorEx\n", pInitializeMonitorEx, debugstr_w(driver)); - TRACE("%p: %s,pInitializeMonitor\n", pInitializeMonitor, debugstr_w(driver)); - - if (pInitializePrintMonitorUI != NULL) { - pm->monitorUI = pInitializePrintMonitorUI(); - TRACE("%p: MONITORUI from %s,InitializePrintMonitorUI()\n", pm->monitorUI, debugstr_w(driver)); - if (pm->monitorUI) { - TRACE("0x%08x: dwMonitorSize (%d)\n", - pm->monitorUI->dwMonitorUISize, pm->monitorUI->dwMonitorUISize); - - } - } - - if (pInitializePrintMonitor && regroot) { - pmonitorEx = pInitializePrintMonitor(regroot); - TRACE("%p: LPMONITOREX from %s,InitializePrintMonitor(%s)\n", - pmonitorEx, debugstr_w(driver), debugstr_w(regroot)); - - if (pmonitorEx) { - pm->dwMonitorSize = pmonitorEx->dwMonitorSize; - pm->monitor = &(pmonitorEx->Monitor); - } - } - - if (pm->monitor) { - TRACE("0x%08x: dwMonitorSize (%d)\n", pm->dwMonitorSize, pm->dwMonitorSize); - - } - - if (!pm->monitor && regroot) { - if (pInitializePrintMonitor2 != NULL) { - FIXME("%s,InitializePrintMonitor2 not implemented\n", debugstr_w(driver)); - } - if (pInitializeMonitorEx != NULL) { - FIXME("%s,InitializeMonitorEx not implemented\n", debugstr_w(driver)); - } - if (pInitializeMonitor != NULL) { - FIXME("%s,InitializeMonitor not implemented\n", debugstr_w(driver)); - } - } - if (!pm->monitor && !pm->monitorUI) { - monitor_unload(pm); - SetLastError(ERROR_PROC_NOT_FOUND); - pm = NULL; - } - } -cleanup: - if ((pm_localport == NULL) && (pm != NULL) && (lstrcmpW(pm->name, localportW) == 0)) { - pm->refcount++; - pm_localport = pm; - } - LeaveCriticalSection(&monitor_handles_cs); - if (driver != dllname) heap_free(driver); - heap_free(regroot); - TRACE("=> %p\n", pm); - return pm; -} - -/****************************************************************** - * monitor_loadall [internal] - * - * Load all registered monitors - * - */ -static DWORD monitor_loadall(void) -{ - monitor_t * pm; - DWORD registered = 0; - DWORD loaded = 0; - HKEY hmonitors; - WCHAR buffer[MAX_PATH]; - DWORD id = 0; - - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hmonitors) == ERROR_SUCCESS) { - RegQueryInfoKeyW(hmonitors, NULL, NULL, NULL, ®istered, NULL, NULL, - NULL, NULL, NULL, NULL, NULL); - - TRACE("%d monitors registered\n", registered); - - while (id < registered) { - buffer[0] = '\0'; - RegEnumKeyW(hmonitors, id, buffer, MAX_PATH); - pm = monitor_load(buffer, NULL); - if (pm) loaded++; - id++; - } - RegCloseKey(hmonitors); - } - TRACE("%d monitors loaded\n", loaded); - return loaded; -} - -/****************************************************************** - * monitor_loadui [internal] - * - * load the userinterface-dll for a given portmonitor - * - * On failure, NULL is returned - */ -static monitor_t * monitor_loadui(monitor_t * pm) -{ - monitor_t * pui = NULL; - WCHAR buffer[MAX_PATH]; - HANDLE hXcv; - DWORD len; - DWORD res; - - if (pm == NULL) return NULL; - TRACE("(%p) => dllname: %s\n", pm, debugstr_w(pm->dllname)); - - /* Try the Portmonitor first; works for many monitors */ - if (pm->monitorUI) { - EnterCriticalSection(&monitor_handles_cs); - pm->refcount++; - LeaveCriticalSection(&monitor_handles_cs); - return pm; - } - - /* query the userinterface-dllname from the Portmonitor */ - if ((pm->monitor) && (pm->monitor->pfnXcvDataPort)) { - /* building (",XcvMonitor %s",pm->name) not needed yet */ - res = pm->monitor->pfnXcvOpenPort(emptyW, SERVER_ACCESS_ADMINISTER, &hXcv); - TRACE("got %u with %p\n", res, hXcv); - if (res) { - res = pm->monitor->pfnXcvDataPort(hXcv, monitorUIW, NULL, 0, (BYTE *) buffer, sizeof(buffer), &len); - TRACE("got %u with %s\n", res, debugstr_w(buffer)); - if (res == ERROR_SUCCESS) pui = monitor_load(NULL, buffer); - pm->monitor->pfnXcvClosePort(hXcv); - } - } - return pui; -} - -/****************************************************************** - * monitor_load_by_port [internal] - * - * load a printmonitor for a given port - * - * On failure, NULL is returned - */ - -static monitor_t * monitor_load_by_port(LPCWSTR portname) -{ - HKEY hroot; - HKEY hport; - LPWSTR buffer; - monitor_t * pm = NULL; - DWORD registered = 0; - DWORD id = 0; - DWORD len; - - TRACE("(%s)\n", debugstr_w(portname)); - - /* Try the Local Monitor first */ - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, winnt_cv_portsW, &hroot) == ERROR_SUCCESS) { - if (RegQueryValueExW(hroot, portname, NULL, NULL, NULL, &len) == ERROR_SUCCESS) { - /* found the portname */ - RegCloseKey(hroot); - return monitor_load(localportW, NULL); - } - RegCloseKey(hroot); - } - - len = MAX_PATH + lstrlenW(bs_ports_bsW) + lstrlenW(portname) + 1; - buffer = heap_alloc(len * sizeof(WCHAR)); - if (buffer == NULL) return NULL; - - if (RegOpenKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { - EnterCriticalSection(&monitor_handles_cs); - RegQueryInfoKeyW(hroot, NULL, NULL, NULL, ®istered, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - - while ((pm == NULL) && (id < registered)) { - buffer[0] = '\0'; - RegEnumKeyW(hroot, id, buffer, MAX_PATH); - TRACE("testing %s\n", debugstr_w(buffer)); - len = lstrlenW(buffer); - lstrcatW(buffer, bs_ports_bsW); - lstrcatW(buffer, portname); - if (RegOpenKeyW(hroot, buffer, &hport) == ERROR_SUCCESS) { - RegCloseKey(hport); - buffer[len] = '\0'; /* use only the Monitor-Name */ - pm = monitor_load(buffer, NULL); - } - id++; - } - LeaveCriticalSection(&monitor_handles_cs); - RegCloseKey(hroot); - } - heap_free(buffer); - return pm; -} - -/****************************************************************** - * Return the number of bytes for an multi_sz string. - * The result includes all \0s - * (specifically the extra \0, that is needed as multi_sz terminator). - */ -static int multi_sz_lenW(const WCHAR *str) -{ - const WCHAR *ptr = str; - if (!str) return 0; - do - { - ptr += lstrlenW(ptr) + 1; - } while (*ptr); - - return (ptr - str + 1) * sizeof(WCHAR); -} - -/****************************************************************** - * validate_envW [internal] - * - * validate the user-supplied printing-environment - * - * PARAMS - * env [I] PTR to Environment-String or NULL - * - * RETURNS - * Success: PTR to printenv_t - * Failure: NULL and ERROR_INVALID_ENVIRONMENT - * - * NOTES - * An empty string is handled the same way as NULL. - * - */ - -static const printenv_t * validate_envW(LPCWSTR env) -{ - const printenv_t *result = NULL; - unsigned int i; - - TRACE("(%s)\n", debugstr_w(env)); - if (env && env[0]) - { - for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++) - { - if (lstrcmpiW(env, all_printenv[i]->envname) == 0) - { - result = all_printenv[i]; - break; - } - } - if (result == NULL) { - FIXME("unsupported Environment: %s\n", debugstr_w(env)); - SetLastError(ERROR_INVALID_ENVIRONMENT); - } - /* on win9x, only "Windows 4.0" is allowed, but we ignore this */ - } - else - { - result = (GetVersion() & 0x80000000) ? &env_win40 : &env_x86; - } - - TRACE("=> using %p: %s\n", result, debugstr_w(result ? result->envname : NULL)); - return result; -} - -/***************************************************************************** - * enumerate the local monitors (INTERNAL) - * - * returns the needed size (in bytes) for pMonitors - * and *lpreturned is set to number of entries returned in pMonitors - * - * Language-Monitors are also installed in the same Registry-Location but - * they are filtered in Windows (not returned by EnumMonitors). - * We do no filtering to simplify our Code. - * - */ -static DWORD get_local_monitors(DWORD level, LPBYTE pMonitors, DWORD cbBuf, LPDWORD lpreturned) -{ - HKEY hroot = NULL; - HKEY hentry = NULL; - LPWSTR ptr; - LPMONITOR_INFO_2W mi; - WCHAR buffer[MAX_PATH]; - WCHAR dllname[MAX_PATH]; - DWORD dllsize; - DWORD len; - DWORD index = 0; - DWORD needed = 0; - DWORD numentries; - DWORD entrysize; - - entrysize = (level == 1) ? sizeof(MONITOR_INFO_1W) : sizeof(MONITOR_INFO_2W); - - numentries = *lpreturned; /* this is 0, when we scan the registry */ - len = entrysize * numentries; - ptr = (LPWSTR) &pMonitors[len]; - - numentries = 0; - len = sizeof(buffer)/sizeof(buffer[0]); - buffer[0] = '\0'; - - /* Windows creates the "Monitors"-Key on reboot / start "spooler" */ - if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) == ERROR_SUCCESS) { - /* Scan all Monitor-Registry-Keys */ - while (RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { - TRACE("Monitor_%d: %s\n", numentries, debugstr_w(buffer)); - dllsize = sizeof(dllname); - dllname[0] = '\0'; - - /* The Monitor must have a Driver-DLL */ - if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { - if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { - /* We found a valid DLL for this Monitor. */ - TRACE("using Driver: %s\n", debugstr_w(dllname)); - } - RegCloseKey(hentry); - } - - /* Windows returns only Port-Monitors here, but to simplify our code, - we do no filtering for Language-Monitors */ - if (dllname[0]) { - numentries++; - needed += entrysize; - needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(monitorname) */ - if (level > 1) { - /* we install and return only monitors for "Windows NT x86" */ - needed += (lstrlenW(x86_envnameW) +1) * sizeof(WCHAR); - needed += dllsize; - } - - /* required size is calculated. Now fill the user-buffer */ - if (pMonitors && (cbBuf >= needed)){ - mi = (LPMONITOR_INFO_2W) pMonitors; - pMonitors += entrysize; - - TRACE("%p: writing MONITOR_INFO_%dW #%d\n", mi, level, numentries); - mi->pName = ptr; - lstrcpyW(ptr, buffer); /* Name of the Monitor */ - ptr += (len+1); /* len is lstrlenW(monitorname) */ - if (level > 1) { - mi->pEnvironment = ptr; - lstrcpyW(ptr, x86_envnameW); /* fixed to "Windows NT x86" */ - ptr += (lstrlenW(x86_envnameW)+1); - - mi->pDLLName = ptr; - lstrcpyW(ptr, dllname); /* Name of the Driver-DLL */ - ptr += (dllsize / sizeof(WCHAR)); - } - } - } - index++; - len = sizeof(buffer)/sizeof(buffer[0]); - buffer[0] = '\0'; - } - RegCloseKey(hroot); - } - *lpreturned = numentries; - TRACE("need %d byte for %d entries\n", needed, numentries); - return needed; -} - -/***************************************************************************** - * enumerate the local print processors (INTERNAL) - * - * returns the needed size (in bytes) for pPPInfo - * and *lpreturned is set to number of entries returned in pPPInfo - * - */ -static DWORD get_local_printprocessors(LPWSTR regpathW, LPBYTE pPPInfo, DWORD cbBuf, LPDWORD lpreturned) -{ - HKEY hroot = NULL; - HKEY hentry = NULL; - LPWSTR ptr; - PPRINTPROCESSOR_INFO_1W ppi; - WCHAR buffer[MAX_PATH]; - WCHAR dllname[MAX_PATH]; - DWORD dllsize; - DWORD len; - DWORD index = 0; - DWORD needed = 0; - DWORD numentries; - - numentries = *lpreturned; /* this is 0, when we scan the registry */ - len = numentries * sizeof(PRINTPROCESSOR_INFO_1W); - ptr = (LPWSTR) &pPPInfo[len]; - - numentries = 0; - len = sizeof(buffer)/sizeof(buffer[0]); - buffer[0] = '\0'; - - if (RegCreateKeyW(HKEY_LOCAL_MACHINE, regpathW, &hroot) == ERROR_SUCCESS) { - /* add "winprint" first */ - numentries++; - needed = sizeof(PRINTPROCESSOR_INFO_1W) + sizeof(winprintW); - if (pPPInfo && (cbBuf >= needed)){ - ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; - pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); - - TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); - ppi->pName = ptr; - lstrcpyW(ptr, winprintW); /* Name of the Print Processor */ - ptr += sizeof(winprintW) / sizeof(WCHAR); - } - - /* Scan all Printprocessor Keys */ - while ((RegEnumKeyExW(hroot, index, buffer, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) && - (lstrcmpiW(buffer, winprintW) != 0)) { - TRACE("PrintProcessor_%d: %s\n", numentries, debugstr_w(buffer)); - dllsize = sizeof(dllname); - dllname[0] = '\0'; - - /* The Print Processor must have a Driver-DLL */ - if (RegOpenKeyExW(hroot, buffer, 0, KEY_READ, &hentry) == ERROR_SUCCESS) { - if (RegQueryValueExW(hentry, driverW, NULL, NULL, (LPBYTE) dllname, &dllsize) == ERROR_SUCCESS) { - /* We found a valid DLL for this Print Processor */ - TRACE("using Driver: %s\n", debugstr_w(dllname)); - } - RegCloseKey(hentry); - } - - if (dllname[0]) { - numentries++; - needed += sizeof(PRINTPROCESSOR_INFO_1W); - needed += (len+1) * sizeof(WCHAR); /* len is lstrlenW(printprocessor name) */ - - /* required size is calculated. Now fill the user-buffer */ - if (pPPInfo && (cbBuf >= needed)){ - ppi = (PPRINTPROCESSOR_INFO_1W) pPPInfo; - pPPInfo += sizeof(PRINTPROCESSOR_INFO_1W); - - TRACE("%p: writing PRINTPROCESSOR_INFO_1W #%d\n", ppi, numentries); - ppi->pName = ptr; - lstrcpyW(ptr, buffer); /* Name of the Print Processor */ - ptr += (len+1); /* len is lstrlenW(printprosessor name) */ - } - } - index++; - len = sizeof(buffer)/sizeof(buffer[0]); - buffer[0] = '\0'; - } - RegCloseKey(hroot); - } - *lpreturned = numentries; - TRACE("need %d byte for %d entries\n", needed, numentries); - return needed; -} - -/****************************************************************** - * enumerate the local Ports from all loaded monitors (internal) - * - * returns the needed size (in bytes) for pPorts - * and *lpreturned is set to number of entries returned in pPorts - * - */ -static DWORD get_ports_from_all_monitors(DWORD level, LPBYTE pPorts, DWORD cbBuf, LPDWORD lpreturned) -{ - monitor_t * pm; - LPWSTR ptr; - LPPORT_INFO_2W cache; - LPPORT_INFO_2W out; - LPBYTE pi_buffer = NULL; - DWORD pi_allocated = 0; - DWORD pi_needed; - DWORD pi_index; - DWORD pi_returned; - DWORD res; - DWORD outindex = 0; - DWORD needed; - DWORD numentries; - DWORD entrysize; - - - TRACE("(%d, %p, %d, %p)\n", level, pPorts, cbBuf, lpreturned); - entrysize = (level == 1) ? sizeof(PORT_INFO_1W) : sizeof(PORT_INFO_2W); - - numentries = *lpreturned; /* this is 0, when we scan the registry */ - needed = entrysize * numentries; - ptr = (LPWSTR) &pPorts[needed]; - - numentries = 0; - needed = 0; - - LIST_FOR_EACH_ENTRY(pm, &monitor_handles, monitor_t, entry) - { - if ((pm->monitor) && (pm->monitor->pfnEnumPorts)) { - pi_needed = 0; - pi_returned = 0; - res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); - if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { - /* Do not use heap_realloc (we do not need the old data in the buffer) */ - heap_free(pi_buffer); - pi_buffer = heap_alloc(pi_needed); - pi_allocated = (pi_buffer) ? pi_needed : 0; - res = pm->monitor->pfnEnumPorts(NULL, level, pi_buffer, pi_allocated, &pi_needed, &pi_returned); - } - TRACE("(%s) got %d with %d (need %d byte for %d entries)\n", - debugstr_w(pm->name), res, GetLastError(), pi_needed, pi_returned); - - numentries += pi_returned; - needed += pi_needed; - - /* fill the output-buffer (pPorts), if we have one */ - if (pPorts && (cbBuf >= needed ) && pi_buffer) { - pi_index = 0; - while (pi_returned > pi_index) { - cache = (LPPORT_INFO_2W) &pi_buffer[pi_index * entrysize]; - out = (LPPORT_INFO_2W) &pPorts[outindex * entrysize]; - out->pPortName = ptr; - lstrcpyW(ptr, cache->pPortName); - ptr += (lstrlenW(ptr)+1); - if (level > 1) { - out->pMonitorName = ptr; - lstrcpyW(ptr, cache->pMonitorName); - ptr += (lstrlenW(ptr)+1); - - out->pDescription = ptr; - lstrcpyW(ptr, cache->pDescription); - ptr += (lstrlenW(ptr)+1); - out->fPortType = cache->fPortType; - out->Reserved = cache->Reserved; - } - pi_index++; - outindex++; - } - } - } - } - /* the temporary portinfo-buffer is no longer needed */ - heap_free(pi_buffer); - - *lpreturned = numentries; - TRACE("need %d byte for %d entries\n", needed, numentries); - return needed; -} - - -/***************************************************************************** - * open_driver_reg [internal] - * - * opens the registry for the printer drivers depending on the given input - * variable pEnvironment - * - * RETURNS: - * Success: the opened hkey - * Failure: NULL - */ -static HKEY open_driver_reg(LPCWSTR pEnvironment) -{ - HKEY retval = NULL; - LPWSTR buffer; - const printenv_t * env; - - TRACE("(%s)\n", debugstr_w(pEnvironment)); - - env = validate_envW(pEnvironment); - if (!env) return NULL; - - buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(fmt_driversW) + - (lstrlenW(env->envname) + lstrlenW(env->versionregpath)) * sizeof(WCHAR)); - - if (buffer) { - wsprintfW(buffer, fmt_driversW, env->envname, env->versionregpath); - RegCreateKeyW(HKEY_LOCAL_MACHINE, buffer, &retval); - HeapFree(GetProcessHeap(), 0, buffer); - } - return retval; -} - -/***************************************************************************** - * fpGetPrinterDriverDirectory [exported through PRINTPROVIDOR] - * - * Return the PATH for the Printer-Drivers - * - * PARAMS - * pName [I] Servername (NT only) or NULL (local Computer) - * pEnvironment [I] Printing-Environment (see below) or NULL (Default) - * Level [I] Structure-Level (must be 1) - * pDriverDirectory [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pDriverDirectory - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / - * required for pDriverDirectory - * - * RETURNS - * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory - * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory, - * if cbBuf is too small - * - * Native Values returned in pDriverDirectory on Success: - *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86" - *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40" - *| win9x(Windows 4.0): "%winsysdir%" - * - * "%winsysdir%" is the Value from GetSystemDirectoryW() - * - */ -static BOOL WINAPI fpGetPrinterDriverDirectory(LPWSTR pName, LPWSTR pEnvironment, - DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded) -{ - DWORD needed; - const printenv_t * env; - WCHAR * const dir = (WCHAR *)pDriverDirectory; - - TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), - debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); - - if (pName != NULL && pName[0]) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - env = validate_envW(pEnvironment); - if (!env) return FALSE; /* pEnvironment invalid or unsupported */ - - - /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ - needed = GetSystemDirectoryW(NULL, 0); - /* add the Size for the Subdirectories */ - needed += lstrlenW(spoolW); - needed += lstrlenW(driversW); - needed += lstrlenW(env->subdir); - needed *= sizeof(WCHAR); /* return-value is size in Bytes */ - - *pcbNeeded = needed; - - if (needed > cbBuf) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - if (dir == NULL) { - /* ERROR_INVALID_USER_BUFFER is NT, ERROR_INVALID_PARAMETER is win9x */ - SetLastError(ERROR_INVALID_USER_BUFFER); - return FALSE; - } - - GetSystemDirectoryW( dir, cbBuf / sizeof(WCHAR) ); - /* add the Subdirectories */ - lstrcatW( dir, spoolW ); - CreateDirectoryW( dir, NULL ); - lstrcatW( dir, driversW ); - CreateDirectoryW( dir, NULL ); - lstrcatW( dir, env->subdir ); - CreateDirectoryW( dir, NULL ); - - TRACE( "=> %s\n", debugstr_w( dir ) ); - return TRUE; -} - -/****************************************************************** - * driver_load [internal] - * - * load a driver user interface dll - * - * On failure, NULL is returned - * - */ - -static HMODULE driver_load(const printenv_t * env, LPWSTR dllname) -{ - WCHAR fullname[MAX_PATH]; - HMODULE hui; - DWORD len; - - TRACE("(%p, %s)\n", env, debugstr_w(dllname)); - - /* build the driverdir */ - len = sizeof(fullname) - - (lstrlenW(env->versionsubdir) + 1 + lstrlenW(dllname) + 1) * sizeof(WCHAR); - - if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, - (LPBYTE) fullname, len, &len)) { - /* Should never fail */ - SetLastError(ERROR_BUFFER_OVERFLOW); - return NULL; - } - - lstrcatW(fullname, env->versionsubdir); - lstrcatW(fullname, backslashW); - lstrcatW(fullname, dllname); - - hui = LoadLibraryW(fullname); - TRACE("%p: LoadLibrary(%s) %d\n", hui, debugstr_w(fullname), GetLastError()); - - return hui; -} - -/****************************************************************** - * printer_free - * free the data pointer of an opened printer - */ -static VOID printer_free(printer_t * printer) -{ - if (printer->hXcv) - printer->pm->monitor->pfnXcvClosePort(printer->hXcv); - - monitor_unload(printer->pm); - - heap_free(printer->printername); - heap_free(printer->name); - heap_free(printer); -} - -/****************************************************************** - * printer_alloc_handle - * alloc a printer handle and remember the data pointer in the printer handle table - * - */ -static HANDLE printer_alloc_handle(LPCWSTR name, LPPRINTER_DEFAULTSW pDefault) -{ - WCHAR servername[MAX_COMPUTERNAME_LENGTH + 1]; - printer_t *printer = NULL; - LPCWSTR printername; - HKEY hkeyPrinters; - HKEY hkeyPrinter; - DWORD len; - - if (copy_servername_from_name(name, servername)) { - FIXME("server %s not supported\n", debugstr_w(servername)); - SetLastError(ERROR_INVALID_PRINTER_NAME); - return NULL; - } - - printername = get_basename_from_name(name); - if (name != printername) TRACE("converted %s to %s\n", debugstr_w(name), debugstr_w(printername)); - - /* an empty printername is invalid */ - if (printername && (!printername[0])) { - SetLastError(ERROR_INVALID_PARAMETER); - return NULL; - } - - printer = heap_alloc_zero(sizeof(printer_t)); - if (!printer) goto end; - - /* clone the base name. This is NULL for the printserver */ - printer->printername = strdupW(printername); - - /* clone the full name */ - printer->name = strdupW(name); - if (name && (!printer->name)) { - printer_free(printer); - printer = NULL; - } - if (printername) { - len = sizeof(XcvMonitorW)/sizeof(WCHAR) - 1; - if (strncmpW(printername, XcvMonitorW, len) == 0) { - /* OpenPrinter(",XcvMonitor ", ...) detected */ - TRACE(",XcvMonitor: %s\n", debugstr_w(&printername[len])); - printer->pm = monitor_load(&printername[len], NULL); - if (printer->pm == NULL) { - printer_free(printer); - SetLastError(ERROR_UNKNOWN_PORT); - printer = NULL; - goto end; - } - } - else - { - len = sizeof(XcvPortW)/sizeof(WCHAR) - 1; - if (strncmpW( printername, XcvPortW, len) == 0) { - /* OpenPrinter(",XcvPort ", ...) detected */ - TRACE(",XcvPort: %s\n", debugstr_w(&printername[len])); - printer->pm = monitor_load_by_port(&printername[len]); - if (printer->pm == NULL) { - printer_free(printer); - SetLastError(ERROR_UNKNOWN_PORT); - printer = NULL; - goto end; - } - } - } - - if (printer->pm) { - if ((printer->pm->monitor) && (printer->pm->monitor->pfnXcvOpenPort)) { - printer->pm->monitor->pfnXcvOpenPort(&printername[len], - pDefault ? pDefault->DesiredAccess : 0, - &printer->hXcv); - } - if (printer->hXcv == NULL) { - printer_free(printer); - SetLastError(ERROR_INVALID_PARAMETER); - printer = NULL; - goto end; - } - } - else - { - /* Does the Printer exist? */ - if (RegCreateKeyW(HKEY_LOCAL_MACHINE, printersW, &hkeyPrinters) != ERROR_SUCCESS) { - ERR("Can't create Printers key\n"); - printer_free(printer); - SetLastError(ERROR_INVALID_PRINTER_NAME); - printer = NULL; - goto end; - } - if (RegOpenKeyW(hkeyPrinters, printername, &hkeyPrinter) != ERROR_SUCCESS) { - WARN("Printer not found in Registry: %s\n", debugstr_w(printername)); - RegCloseKey(hkeyPrinters); - printer_free(printer); - SetLastError(ERROR_INVALID_PRINTER_NAME); - printer = NULL; - goto end; - } - RegCloseKey(hkeyPrinter); - RegCloseKey(hkeyPrinters); - } - } - else - { - TRACE("using the local printserver\n"); - } - -end: - - TRACE("==> %p\n", printer); - return (HANDLE)printer; -} - -static inline WCHAR *get_file_part( WCHAR *name ) -{ - WCHAR *ptr = strrchrW( name, '\\' ); - if (ptr) return ptr + 1; - return name; -} - -/****************************************************************************** - * myAddPrinterDriverEx [internal] - * - * Install a Printer Driver with the Option to upgrade / downgrade the Files - * and a special mode with lazy error checking. - * - */ -static BOOL myAddPrinterDriverEx(DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags, BOOL lazy) -{ - const printenv_t *env; - apd_data_t apd; - DRIVER_INFO_8W di; - BOOL (WINAPI *pDrvDriverEvent)(DWORD, DWORD, LPBYTE, LPARAM); - HMODULE hui; - WCHAR *file; - HKEY hroot; - HKEY hdrv; - DWORD disposition; - DWORD len; - LONG lres; - BOOL res; - - /* we need to set all entries in the Registry, independent from the Level of - DRIVER_INFO, that the caller supplied */ - - ZeroMemory(&di, sizeof(di)); - if (pDriverInfo && (level < (sizeof(di_sizeof) / sizeof(di_sizeof[0])))) { - memcpy(&di, pDriverInfo, di_sizeof[level]); - } - - /* dump the most used infos */ - TRACE("%p: .cVersion : 0x%x/%d\n", pDriverInfo, di.cVersion, di.cVersion); - TRACE("%p: .pName : %s\n", di.pName, debugstr_w(di.pName)); - TRACE("%p: .pEnvironment: %s\n", di.pEnvironment, debugstr_w(di.pEnvironment)); - TRACE("%p: .pDriverPath : %s\n", di.pDriverPath, debugstr_w(di.pDriverPath)); - TRACE("%p: .pDataFile : %s\n", di.pDataFile, debugstr_w(di.pDataFile)); - TRACE("%p: .pConfigFile : %s\n", di.pConfigFile, debugstr_w(di.pConfigFile)); - TRACE("%p: .pHelpFile : %s\n", di.pHelpFile, debugstr_w(di.pHelpFile)); - /* dump only the first of the additional Files */ - TRACE("%p: .pDependentFiles: %s\n", di.pDependentFiles, debugstr_w(di.pDependentFiles)); - - - /* check environment */ - env = validate_envW(di.pEnvironment); - if (env == NULL) return FALSE; /* ERROR_INVALID_ENVIRONMENT */ - - /* fill the copy-data / get the driverdir */ - len = sizeof(apd.src) - sizeof(version3_subdirW) - sizeof(WCHAR); - if (!fpGetPrinterDriverDirectory(NULL, (LPWSTR) env->envname, 1, - (LPBYTE) apd.src, len, &len)) { - /* Should never fail */ - return FALSE; - } - memcpy(apd.dst, apd.src, len); - lstrcatW(apd.src, backslashW); - apd.srclen = lstrlenW(apd.src); - lstrcatW(apd.dst, env->versionsubdir); - lstrcatW(apd.dst, backslashW); - apd.dstlen = lstrlenW(apd.dst); - apd.copyflags = dwFileCopyFlags; - apd.lazy = lazy; - CreateDirectoryW(apd.src, NULL); - CreateDirectoryW(apd.dst, NULL); - - hroot = open_driver_reg(env->envname); - if (!hroot) { - ERR("Can't create Drivers key\n"); - return FALSE; - } - - /* Fill the Registry for the Driver */ - if ((lres = RegCreateKeyExW(hroot, di.pName, 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE | KEY_QUERY_VALUE, NULL, - &hdrv, &disposition)) != ERROR_SUCCESS) { - - ERR("can't create driver %s: %u\n", debugstr_w(di.pName), lres); - RegCloseKey(hroot); - SetLastError(lres); - return FALSE; - } - RegCloseKey(hroot); - - /* Verified with the Adobe PS Driver, that w2k does not use di.Version */ - RegSetValueExW(hdrv, versionW, 0, REG_DWORD, (const BYTE*) &env->driverversion, - sizeof(DWORD)); - - file = get_file_part( di.pDriverPath ); - RegSetValueExW( hdrv, driverW, 0, REG_SZ, (LPBYTE)file, (strlenW( file ) + 1) * sizeof(WCHAR) ); - apd_copyfile( di.pDriverPath, file, &apd ); - - file = get_file_part( di.pDataFile ); - RegSetValueExW( hdrv, data_fileW, 0, REG_SZ, (LPBYTE)file, (strlenW( file ) + 1) * sizeof(WCHAR) ); - apd_copyfile( di.pDataFile, file, &apd ); - - file = get_file_part( di.pConfigFile ); - RegSetValueExW( hdrv, configuration_fileW, 0, REG_SZ, (LPBYTE)file, (strlenW( file ) + 1) * sizeof(WCHAR) ); - apd_copyfile( di.pConfigFile, file, &apd ); - - /* settings for level 3 */ - if (di.pHelpFile) - { - file = get_file_part( di.pHelpFile ); - RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (LPBYTE)file, (strlenW( file ) + 1) * sizeof(WCHAR) ); - apd_copyfile( di.pHelpFile, file, &apd ); - } - else - RegSetValueExW( hdrv, help_fileW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW) ); - - if (di.pDependentFiles && *di.pDependentFiles) - { - WCHAR *reg, *reg_ptr, *in_ptr; - reg = reg_ptr = HeapAlloc( GetProcessHeap(), 0, multi_sz_lenW( di.pDependentFiles ) ); - - for (in_ptr = di.pDependentFiles; *in_ptr; in_ptr += strlenW( in_ptr ) + 1) - { - file = get_file_part( in_ptr ); - len = strlenW( file ) + 1; - memcpy( reg_ptr, file, len * sizeof(WCHAR) ); - reg_ptr += len; - apd_copyfile( in_ptr, file, &apd ); - } - *reg_ptr = 0; - - RegSetValueExW( hdrv, dependent_filesW, 0, REG_MULTI_SZ, (LPBYTE)reg, (reg_ptr - reg + 1) * sizeof(WCHAR) ); - HeapFree( GetProcessHeap(), 0, reg ); - } - else - RegSetValueExW(hdrv, dependent_filesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); - - /* The language-Monitor was already copied by the caller to "%SystemRoot%\system32" */ - if (di.pMonitorName) - RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (LPBYTE) di.pMonitorName, - (lstrlenW(di.pMonitorName)+1)* sizeof(WCHAR)); - else - RegSetValueExW(hdrv, monitorW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); - - if (di.pDefaultDataType) - RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (LPBYTE) di.pDefaultDataType, - (lstrlenW(di.pDefaultDataType)+1)* sizeof(WCHAR)); - else - RegSetValueExW(hdrv, datatypeW, 0, REG_SZ, (const BYTE*)emptyW, sizeof(emptyW)); - - /* settings for level 4 */ - if (di.pszzPreviousNames) - RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (LPBYTE) di.pszzPreviousNames, - multi_sz_lenW(di.pszzPreviousNames)); - else - RegSetValueExW(hdrv, previous_namesW, 0, REG_MULTI_SZ, (const BYTE*)emptyW, sizeof(emptyW)); - - if (level > 5) TRACE("level %u for Driver %s is incomplete\n", level, debugstr_w(di.pName)); - - RegCloseKey(hdrv); - hui = driver_load(env, di.pConfigFile); - pDrvDriverEvent = (void *)GetProcAddress(hui, "DrvDriverEvent"); - if (hui && pDrvDriverEvent) { - - /* Support for DrvDriverEvent is optional */ - TRACE("DRIVER_EVENT_INITIALIZE for %s (%s)\n", debugstr_w(di.pName), debugstr_w(di.pConfigFile)); - /* MSDN: level for DRIVER_INFO is 1 to 3 */ - res = pDrvDriverEvent(DRIVER_EVENT_INITIALIZE, 3, (LPBYTE) &di, 0); - TRACE("got %d from DRIVER_EVENT_INITIALIZE\n", res); - } - FreeLibrary(hui); - - TRACE("=> TRUE with %u\n", GetLastError()); - return TRUE; - -} - -/****************************************************************************** - * fpAddMonitor [exported through PRINTPROVIDOR] - * - * Install a Printmonitor - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level (Must be 2) - * pMonitors [I] PTR to MONITOR_INFO_2 - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32") - * - */ -static BOOL WINAPI fpAddMonitor(LPWSTR pName, DWORD Level, LPBYTE pMonitors) -{ - monitor_t * pm = NULL; - LPMONITOR_INFO_2W mi2w; - HKEY hroot = NULL; - HKEY hentry = NULL; - DWORD disposition; - BOOL res = FALSE; - - mi2w = (LPMONITOR_INFO_2W) pMonitors; - TRACE("(%s, %d, %p): %s %s %s\n", debugstr_w(pName), Level, pMonitors, - debugstr_w(mi2w ? mi2w->pName : NULL), - debugstr_w(mi2w ? mi2w->pEnvironment : NULL), - debugstr_w(mi2w ? mi2w->pDLLName : NULL)); - - if (copy_servername_from_name(pName, NULL)) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - - if (!mi2w->pName || (! mi2w->pName[0])) { - WARN("pName not valid : %s\n", debugstr_w(mi2w->pName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (!mi2w->pEnvironment || lstrcmpW(mi2w->pEnvironment, x86_envnameW)) { - WARN("Environment %s requested (we support only %s)\n", - debugstr_w(mi2w->pEnvironment), debugstr_w(x86_envnameW)); - SetLastError(ERROR_INVALID_ENVIRONMENT); - return FALSE; - } - - if (!mi2w->pDLLName || (! mi2w->pDLLName[0])) { - WARN("pDLLName not valid : %s\n", debugstr_w(mi2w->pDLLName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* Load and initialize the monitor. SetLastError() is called on failure */ - if ((pm = monitor_load(mi2w->pName, mi2w->pDLLName)) == NULL) { - return FALSE; - } - monitor_unload(pm); - - if (RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) { - ERR("unable to create key %s\n", debugstr_w(monitorsW)); - return FALSE; - } - - if (RegCreateKeyExW(hroot, mi2w->pName, 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_WRITE | KEY_QUERY_VALUE, NULL, &hentry, - &disposition) == ERROR_SUCCESS) { - - /* Some installers set options for the port before calling AddMonitor. - We query the "Driver" entry to verify that the monitor is installed, - before we return an error. - When a user installs two print monitors at the same time with the - same name, a race condition is possible but silently ignored. */ - - DWORD namesize = 0; - - if ((disposition == REG_OPENED_EXISTING_KEY) && - (RegQueryValueExW(hentry, driverW, NULL, NULL, NULL, - &namesize) == ERROR_SUCCESS)) { - TRACE("monitor %s already exists\n", debugstr_w(mi2w->pName)); - /* 9x use ERROR_ALREADY_EXISTS */ - SetLastError(ERROR_PRINT_MONITOR_ALREADY_INSTALLED); - } - else - { - INT len; - len = (lstrlenW(mi2w->pDLLName) +1) * sizeof(WCHAR); - res = (RegSetValueExW(hentry, driverW, 0, REG_SZ, - (LPBYTE) mi2w->pDLLName, len) == ERROR_SUCCESS); - } - RegCloseKey(hentry); - } - - RegCloseKey(hroot); - return (res); -} - -/****************************************************************************** - * fpAddPort [exported through PRINTPROVIDOR] - * - * Add a Port for a specific Monitor - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * hWnd [I] Handle to parent Window for the Dialog-Box - * pMonitorName [I] Name of the Monitor that manage the Port - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName) -{ - monitor_t * pm; - monitor_t * pui; - LONG lres; - DWORD res; - - TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pMonitorName)); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* an empty Monitorname is Invalid */ - if (!pMonitorName[0]) { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - pm = monitor_load(pMonitorName, NULL); - if (pm && pm->monitor && pm->monitor->pfnAddPort) { - res = pm->monitor->pfnAddPort(pName, hWnd, pMonitorName); - TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); - } - else - { - pui = monitor_loadui(pm); - if (pui && pui->monitorUI && pui->monitorUI->pfnAddPortUI) { - res = pui->monitorUI->pfnAddPortUI(pName, hWnd, pMonitorName, NULL); - TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pui->dllname)); - } - else - { - FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", - debugstr_w(pMonitorName), pm, debugstr_w(pm ? pm->dllname : NULL), - pui, debugstr_w(pui ? pui->dllname : NULL)); - - SetLastError(ERROR_NOT_SUPPORTED); - res = FALSE; - } - monitor_unload(pui); - } - monitor_unload(pm); - - TRACE("returning %d with %u\n", res, GetLastError()); - return res; -} - -/****************************************************************************** - * fpAddPortEx [exported through PRINTPROVIDOR] - * - * Add a Port for a specific Monitor, without presenting a user interface - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * level [I] Structure-Level (1 or 2) for pBuffer - * pBuffer [I] PTR to: PORT_INFO_1 or PORT_INFO_2 - * pMonitorName [I] Name of the Monitor that manage the Port - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpAddPortEx(LPWSTR pName, DWORD level, LPBYTE pBuffer, LPWSTR pMonitorName) -{ - PORT_INFO_2W * pi2; - monitor_t * pm; - DWORD lres; - DWORD res; - - pi2 = (PORT_INFO_2W *) pBuffer; - - TRACE("(%s, %d, %p, %s): %s %s %s\n", debugstr_w(pName), level, pBuffer, - debugstr_w(pMonitorName), debugstr_w(pi2 ? pi2->pPortName : NULL), - debugstr_w(((level > 1) && pi2) ? pi2->pMonitorName : NULL), - debugstr_w(((level > 1) && pi2) ? pi2->pDescription : NULL)); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if ((level < 1) || (level > 2)) { - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - if ((!pi2) || (!pMonitorName) || (!pMonitorName[0])) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - /* load the Monitor */ - pm = monitor_load(pMonitorName, NULL); - if (pm && pm->monitor && pm->monitor->pfnAddPortEx) { - res = pm->monitor->pfnAddPortEx(pName, level, pBuffer, pMonitorName); - TRACE("got %d with %u (%s)\n", res, GetLastError(), debugstr_w(pm->dllname)); - } - else - { - FIXME("not implemented for %s (monitor %p: %s)\n", - debugstr_w(pMonitorName), pm, pm ? debugstr_w(pm->dllname) : "(null)"); - SetLastError(ERROR_INVALID_PARAMETER); - res = FALSE; - } - monitor_unload(pm); - return res; -} - -/****************************************************************************** - * fpAddPrinterDriverEx [exported through PRINTPROVIDOR] - * - * Install a Printer Driver with the Option to upgrade / downgrade the Files - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * level [I] Level for the supplied DRIVER_INFO_*W struct - * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter - * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files - * - * RESULTS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpAddPrinterDriverEx(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) -{ - LONG lres; - - TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - - if ((dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY) != APD_COPY_ALL_FILES) { - TRACE("Flags 0x%x ignored (using APD_COPY_ALL_FILES)\n", dwFileCopyFlags & ~APD_COPY_FROM_DIRECTORY); - } - - return myAddPrinterDriverEx(level, pDriverInfo, dwFileCopyFlags, TRUE); -} - -/****************************************************************************** - * fpClosePrinter [exported through PRINTPROVIDOR] - * - * Close a printer handle and free associated resources - * - * PARAMS - * hPrinter [I] Printerhandle to close - * - * RESULTS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpClosePrinter(HANDLE hPrinter) -{ - printer_t *printer = (printer_t *) hPrinter; - - TRACE("(%p)\n", hPrinter); - - if (printer) { - printer_free(printer); - return TRUE; - } - return FALSE; -} - -/****************************************************************************** - * fpConfigurePort [exported through PRINTPROVIDOR] - * - * Display the Configuration-Dialog for a specific Port - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * hWnd [I] Handle to parent Window for the Dialog-Box - * pPortName [I] Name of the Port, that should be configured - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpConfigurePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) -{ - monitor_t * pm; - monitor_t * pui; - LONG lres; - DWORD res; - - TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - return FALSE; - } - - /* an empty Portname is Invalid, but can popup a Dialog */ - if (!pPortName[0]) { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - pm = monitor_load_by_port(pPortName); - if (pm && pm->monitor && pm->monitor->pfnConfigurePort) { - TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), - debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); - res = pm->monitor->pfnConfigurePort(pName, hWnd, pPortName); - TRACE("got %d with %u\n", res, GetLastError()); - } - else - { - pui = monitor_loadui(pm); - if (pui && pui->monitorUI && pui->monitorUI->pfnConfigurePortUI) { - TRACE("use %s for %s (monitorui %p: %s)\n", debugstr_w(pui->name), - debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); - res = pui->monitorUI->pfnConfigurePortUI(pName, hWnd, pPortName); - TRACE("got %d with %u\n", res, GetLastError()); - } - else - { - FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", - debugstr_w(pPortName), pm, debugstr_w(pm ? pm->dllname : NULL), - pui, debugstr_w(pui ? pui->dllname : NULL)); - - SetLastError(ERROR_NOT_SUPPORTED); - res = FALSE; - } - monitor_unload(pui); - } - monitor_unload(pm); - - TRACE("returning %d with %u\n", res, GetLastError()); - return res; -} - -/****************************************************************** - * fpDeleteMonitor [exported through PRINTPROVIDOR] - * - * Delete a specific Printmonitor from a Printing-Environment - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default) - * pMonitorName [I] Name of the Monitor, that should be deleted - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * pEnvironment is ignored in Windows for the local Computer. - * - */ - -static BOOL WINAPI fpDeleteMonitor(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName) -{ - HKEY hroot = NULL; - LONG lres; - - TRACE("(%s, %s, %s)\n",debugstr_w(pName),debugstr_w(pEnvironment), - debugstr_w(pMonitorName)); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - return FALSE; - } - - /* pEnvironment is ignored in Windows for the local Computer */ - if (!pMonitorName || !pMonitorName[0]) { - TRACE("pMonitorName %s is invalid\n", debugstr_w(pMonitorName)); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if(RegCreateKeyW(HKEY_LOCAL_MACHINE, monitorsW, &hroot) != ERROR_SUCCESS) { - ERR("unable to create key %s\n", debugstr_w(monitorsW)); - return FALSE; - } - - if(RegDeleteTreeW(hroot, pMonitorName) == ERROR_SUCCESS) { - TRACE("%s deleted\n", debugstr_w(pMonitorName)); - RegCloseKey(hroot); - return TRUE; - } - - TRACE("%s does not exist\n", debugstr_w(pMonitorName)); - RegCloseKey(hroot); - - /* NT: ERROR_UNKNOWN_PRINT_MONITOR (3000), 9x: ERROR_INVALID_PARAMETER (87) */ - SetLastError(ERROR_UNKNOWN_PRINT_MONITOR); - return FALSE; -} - -/***************************************************************************** - * fpDeletePort [exported through PRINTPROVIDOR] - * - * Delete a specific Port - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * hWnd [I] Handle to parent Window for the Dialog-Box - * pPortName [I] Name of the Port, that should be deleted - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -static BOOL WINAPI fpDeletePort(LPWSTR pName, HWND hWnd, LPWSTR pPortName) -{ - monitor_t * pm; - monitor_t * pui; - LONG lres; - DWORD res; - - TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - return FALSE; - } - - /* an empty Portname is Invalid */ - if (!pPortName[0]) { - SetLastError(ERROR_NOT_SUPPORTED); - return FALSE; - } - - pm = monitor_load_by_port(pPortName); - if (pm && pm->monitor && pm->monitor->pfnDeletePort) { - TRACE("use %s for %s (monitor %p: %s)\n", debugstr_w(pm->name), - debugstr_w(pPortName), pm, debugstr_w(pm->dllname)); - res = pm->monitor->pfnDeletePort(pName, hWnd, pPortName); - TRACE("got %d with %u\n", res, GetLastError()); - } - else - { - pui = monitor_loadui(pm); - if (pui && pui->monitorUI && pui->monitorUI->pfnDeletePortUI) { - TRACE("use %s for %s (monitorui %p: %s)\n", debugstr_w(pui->name), - debugstr_w(pPortName), pui, debugstr_w(pui->dllname)); - res = pui->monitorUI->pfnDeletePortUI(pName, hWnd, pPortName); - TRACE("got %d with %u\n", res, GetLastError()); - } - else - { - FIXME("not implemented for %s (monitor %p: %s / monitorui %p: %s)\n", - debugstr_w(pPortName), pm, debugstr_w(pm ? pm->dllname : NULL), - pui, debugstr_w(pui ? pui->dllname : NULL)); - - SetLastError(ERROR_NOT_SUPPORTED); - res = FALSE; - } - monitor_unload(pui); - } - monitor_unload(pm); - - TRACE("returning %d with %u\n", res, GetLastError()); - return res; -} - -/***************************************************************************** - * fpEnumMonitors [exported through PRINTPROVIDOR] - * - * Enumerate available Port-Monitors - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level (1:Win9x+NT or 2:NT only) - * pMonitors [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pMonitors - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors - * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small - * - * NOTES - * Windows reads the Registry once and cache the Results. - * - */ -static BOOL WINAPI fpEnumMonitors(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf, - LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - DWORD numentries = 0; - DWORD needed = 0; - LONG lres; - BOOL res = FALSE; - - TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors, - cbBuf, pcbNeeded, pcReturned); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - goto em_cleanup; - } - - if (!Level || (Level > 2)) { - WARN("level (%d) is ignored in win9x\n", Level); - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - /* Scan all Monitor-Keys */ - numentries = 0; - needed = get_local_monitors(Level, NULL, 0, &numentries); - - /* we calculated the needed buffersize. now do more error-checks */ - if (cbBuf < needed) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto em_cleanup; - } - - /* fill the Buffer with the Monitor-Keys */ - needed = get_local_monitors(Level, pMonitors, cbBuf, &numentries); - res = TRUE; - -em_cleanup: - if (pcbNeeded) *pcbNeeded = needed; - if (pcReturned) *pcReturned = numentries; - - TRACE("returning %d with %d (%d byte for %d entries)\n", - res, GetLastError(), needed, numentries); - - return (res); -} - -/****************************************************************************** - * fpEnumPorts [exported through PRINTPROVIDOR] - * - * Enumerate available Ports - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level (1 or 2) - * pPorts [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pPorts - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts - * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small - * - */ -static BOOL WINAPI fpEnumPorts(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf, - LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - DWORD needed = 0; - DWORD numentries = 0; - LONG lres; - BOOL res = FALSE; - - TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, - cbBuf, pcbNeeded, pcReturned); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - goto emP_cleanup; - } - - if (!Level || (Level > 2)) { - SetLastError(ERROR_INVALID_LEVEL); - goto emP_cleanup; - } - - if (!pcbNeeded || (!pPorts && (cbBuf > 0))) { - SetLastError(RPC_X_NULL_REF_POINTER); - goto emP_cleanup; - } - - EnterCriticalSection(&monitor_handles_cs); - monitor_loadall(); - - /* Scan all local Ports */ - numentries = 0; - needed = get_ports_from_all_monitors(Level, NULL, 0, &numentries); - - /* we calculated the needed buffersize. now do the error-checks */ - if (cbBuf < needed) { - monitor_unloadall(); - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto emP_cleanup_cs; - } - else if (!pPorts || !pcReturned) { - monitor_unloadall(); - SetLastError(RPC_X_NULL_REF_POINTER); - goto emP_cleanup_cs; - } - - /* Fill the Buffer */ - needed = get_ports_from_all_monitors(Level, pPorts, cbBuf, &numentries); - res = TRUE; - monitor_unloadall(); - -emP_cleanup_cs: - LeaveCriticalSection(&monitor_handles_cs); - -emP_cleanup: - if (pcbNeeded) *pcbNeeded = needed; - if (pcReturned) *pcReturned = (res) ? numentries : 0; - - TRACE("returning %d with %d (%d byte for %d of %d entries)\n", - (res), GetLastError(), needed, (res) ? numentries : 0, numentries); - - return (res); -} - -/***************************************************************************** - * fpEnumPrintProcessors [exported through PRINTPROVIDOR] - * - * Enumerate available Print Processors - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * pEnvironment [I] Printing-Environment or NULL (Default) - * Level [I] Structure-Level (Only 1 is allowed) - * pPPInfo [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pMonitors - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo - * pcReturned [O] PTR to DWORD that receives the number of Print Processors in pPPInfo - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small - * - */ -static BOOL WINAPI fpEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, - LPBYTE pPPInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - const printenv_t * env; - LPWSTR regpathW = NULL; - DWORD numentries = 0; - DWORD needed = 0; - LONG lres; - BOOL res = FALSE; - - TRACE("(%s, %s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), - Level, pPPInfo, cbBuf, pcbNeeded, pcReturned); - - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(ERROR_INVALID_NAME); - goto epp_cleanup; - } - - if (Level != 1) { - SetLastError(ERROR_INVALID_LEVEL); - goto epp_cleanup; - } - - env = validate_envW(pEnvironment); - if (!env) - goto epp_cleanup; /* ERROR_INVALID_ENVIRONMENT */ - - regpathW = heap_alloc(sizeof(fmt_printprocessorsW) + - (lstrlenW(env->envname) * sizeof(WCHAR))); - - if (!regpathW) - goto epp_cleanup; - - wsprintfW(regpathW, fmt_printprocessorsW, env->envname); - - /* Scan all Printprocessor-Keys */ - numentries = 0; - needed = get_local_printprocessors(regpathW, NULL, 0, &numentries); - - /* we calculated the needed buffersize. now do more error-checks */ - if (cbBuf < needed) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - goto epp_cleanup; - } - - /* fill the Buffer with the Printprocessor Infos */ - needed = get_local_printprocessors(regpathW, pPPInfo, cbBuf, &numentries); - res = TRUE; - -epp_cleanup: - heap_free(regpathW); - if (pcbNeeded) *pcbNeeded = needed; - if (pcReturned) *pcReturned = numentries; - - TRACE("returning %d with %d (%d byte for %d entries)\n", - res, GetLastError(), needed, numentries); - - return (res); -} - -/****************************************************************************** - * fpGetPrintProcessorDirectory [exported through PRINTPROVIDOR] - * - * Return the PATH for the Print-Processors - * - * PARAMS - * pName [I] Servername or NULL (this computer) - * pEnvironment [I] Printing-Environment or NULL (Default) - * level [I] Structure-Level (must be 1) - * pPPInfo [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pPPInfo - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPPInfo - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pPPInfo, if cbBuf is too small - * - * Native Values returned in pPPInfo on Success for this computer: - *| NT(Windows x64): "%winsysdir%\\spool\\PRTPROCS\\x64" - *| NT(Windows NT x86): "%winsysdir%\\spool\\PRTPROCS\\w32x86" - *| NT(Windows 4.0): "%winsysdir%\\spool\\PRTPROCS\\win40" - * - * "%winsysdir%" is the Value from GetSystemDirectoryW() - * - */ -static BOOL WINAPI fpGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD level, - LPBYTE pPPInfo, DWORD cbBuf, LPDWORD pcbNeeded) -{ - const printenv_t * env; - DWORD needed; - LONG lres; - - TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), debugstr_w(pEnvironment), - level, pPPInfo, cbBuf, pcbNeeded); - - *pcbNeeded = 0; - lres = copy_servername_from_name(pName, NULL); - if (lres) { - FIXME("server %s not supported\n", debugstr_w(pName)); - SetLastError(RPC_S_SERVER_UNAVAILABLE); - return FALSE; - } - - env = validate_envW(pEnvironment); - if (!env) - return FALSE; /* ERROR_INVALID_ENVIRONMENT */ - - /* GetSystemDirectoryW returns number of WCHAR including the '\0' */ - needed = GetSystemDirectoryW(NULL, 0); - /* add the Size for the Subdirectories */ - needed += lstrlenW(spoolprtprocsW); - needed += lstrlenW(env->subdir); - needed *= sizeof(WCHAR); /* return-value is size in Bytes */ - - *pcbNeeded = needed; - - if (needed > cbBuf) { - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - GetSystemDirectoryW((LPWSTR) pPPInfo, cbBuf/sizeof(WCHAR)); - /* add the Subdirectories */ - lstrcatW((LPWSTR) pPPInfo, spoolprtprocsW); - lstrcatW((LPWSTR) pPPInfo, env->subdir); - TRACE("==> %s\n", debugstr_w((LPWSTR) pPPInfo)); - return TRUE; -} - -/****************************************************************************** - * fpOpenPrinter [exported through PRINTPROVIDOR] - * - * Open a Printer / Printserver or a Printer-Object - * - * PARAMS - * lpPrinterName [I] Name of Printserver, Printer, or Printer-Object - * pPrinter [O] The resulting Handle is stored here - * pDefaults [I] PTR to Default Printer Settings or NULL - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * lpPrinterName is one of: - *| Printserver (NT only): "Servername" or NULL for the local Printserver - *| Printer: "PrinterName" - *| Printer-Object: "PrinterName,Job xxx" - *| XcvMonitor: "Servername,XcvMonitor MonitorName" - *| XcvPort: "Servername,XcvPort PortName" - * - * - */ -static BOOL WINAPI fpOpenPrinter(LPWSTR lpPrinterName, HANDLE *pPrinter, - LPPRINTER_DEFAULTSW pDefaults) -{ - - TRACE("(%s, %p, %p)\n", debugstr_w(lpPrinterName), pPrinter, pDefaults); - - *pPrinter = printer_alloc_handle(lpPrinterName, pDefaults); - - return (*pPrinter != 0); -} - -/****************************************************************************** - * fpXcvData [exported through PRINTPROVIDOR] - * - * Execute commands in the Printmonitor DLL - * - * PARAMS - * hXcv [i] Handle from fpOpenPrinter (with XcvMonitor or XcvPort) - * pszDataName [i] Name of the command to execute - * pInputData [i] Buffer for extra Input Data (needed only for some commands) - * cbInputData [i] Size in Bytes of Buffer at pInputData - * pOutputData [o] Buffer to receive additional Data (needed only for some commands) - * cbOutputData [i] Size in Bytes of Buffer at pOutputData - * pcbOutputNeeded [o] PTR to receive the minimal Size in Bytes of the Buffer at pOutputData - * pdwStatus [o] PTR to receive the win32 error code from the Printmonitor DLL - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Returning "TRUE" does mean, that the Printmonitor DLL was called successful. - * The execution of the command can still fail (check pdwStatus for ERROR_SUCCESS). - * - * Minimal List of commands, that a Printmonitor DLL should support: - * - *| "MonitorUI" : Return the Name of the Userinterface-DLL as WSTR in pOutputData - *| "AddPort" : Add a Port - *| "DeletePort": Delete a Port - * - * Many Printmonitors support additional commands. Examples for localspl.dll: - * "GetDefaultCommConfig", "SetDefaultCommConfig", - * "GetTransmissionRetryTimeout", "ConfigureLPTPortCommandOK" - * - */ -static BOOL WINAPI fpXcvData(HANDLE hXcv, LPCWSTR pszDataName, PBYTE pInputData, - DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, - PDWORD pcbOutputNeeded, PDWORD pdwStatus) -{ - printer_t *printer = (printer_t * ) hXcv; - - TRACE("(%p, %s, %p, %d, %p, %d, %p, %p)\n", hXcv, debugstr_w(pszDataName), - pInputData, cbInputData, pOutputData, - cbOutputData, pcbOutputNeeded, pdwStatus); - - if (!printer || (!printer->hXcv)) { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (!pcbOutputNeeded) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (!pszDataName || !pdwStatus || (!pOutputData && (cbOutputData > 0))) { - SetLastError(RPC_X_NULL_REF_POINTER); - return FALSE; - } - - *pcbOutputNeeded = 0; - - *pdwStatus = printer->pm->monitor->pfnXcvDataPort(printer->hXcv, pszDataName, - pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); - - return TRUE; -} - -/***************************************************** - * setup_provider [internal] - */ -void setup_provider(void) -{ - static const PRINTPROVIDOR backend = { - fpOpenPrinter, - NULL, /* fpSetJob */ - NULL, /* fpGetJob */ - NULL, /* fpEnumJobs */ - NULL, /* fpAddPrinter */ - NULL, /* fpDeletePrinter */ - NULL, /* fpSetPrinter */ - NULL, /* fpGetPrinter */ - NULL, /* fpEnumPrinters */ - NULL, /* fpAddPrinterDriver */ - NULL, /* fpEnumPrinterDrivers */ - NULL, /* fpGetPrinterDriver */ - fpGetPrinterDriverDirectory, - NULL, /* fpDeletePrinterDriver */ - NULL, /* fpAddPrintProcessor */ - fpEnumPrintProcessors, - fpGetPrintProcessorDirectory, - NULL, /* fpDeletePrintProcessor */ - NULL, /* fpEnumPrintProcessorDatatypes */ - NULL, /* fpStartDocPrinter */ - NULL, /* fpStartPagePrinter */ - NULL, /* fpWritePrinter */ - NULL, /* fpEndPagePrinter */ - NULL, /* fpAbortPrinter */ - NULL, /* fpReadPrinter */ - NULL, /* fpEndDocPrinter */ - NULL, /* fpAddJob */ - NULL, /* fpScheduleJob */ - NULL, /* fpGetPrinterData */ - NULL, /* fpSetPrinterData */ - NULL, /* fpWaitForPrinterChange */ - fpClosePrinter, - NULL, /* fpAddForm */ - NULL, /* fpDeleteForm */ - NULL, /* fpGetForm */ - NULL, /* fpSetForm */ - NULL, /* fpEnumForms */ - fpEnumMonitors, - fpEnumPorts, - fpAddPort, - fpConfigurePort, - fpDeletePort, - NULL, /* fpCreatePrinterIC */ - NULL, /* fpPlayGdiScriptOnPrinterIC */ - NULL, /* fpDeletePrinterIC */ - NULL, /* fpAddPrinterConnection */ - NULL, /* fpDeletePrinterConnection */ - NULL, /* fpPrinterMessageBox */ - fpAddMonitor, - fpDeleteMonitor, - NULL, /* fpResetPrinter */ - NULL, /* fpGetPrinterDriverEx */ - NULL, /* fpFindFirstPrinterChangeNotification */ - NULL, /* fpFindClosePrinterChangeNotification */ - fpAddPortEx, - NULL, /* fpShutDown */ - NULL, /* fpRefreshPrinterChangeNotification */ - NULL, /* fpOpenPrinterEx */ - NULL, /* fpAddPrinterEx */ - NULL, /* fpSetPort */ - NULL, /* fpEnumPrinterData */ - NULL, /* fpDeletePrinterData */ - NULL, /* fpClusterSplOpen */ - NULL, /* fpClusterSplClose */ - NULL, /* fpClusterSplIsAlive */ - NULL, /* fpSetPrinterDataEx */ - NULL, /* fpGetPrinterDataEx */ - NULL, /* fpEnumPrinterDataEx */ - NULL, /* fpEnumPrinterKey */ - NULL, /* fpDeletePrinterDataEx */ - NULL, /* fpDeletePrinterKey */ - NULL, /* fpSeekPrinter */ - NULL, /* fpDeletePrinterDriverEx */ - NULL, /* fpAddPerMachineConnection */ - NULL, /* fpDeletePerMachineConnection */ - NULL, /* fpEnumPerMachineConnections */ - fpXcvData, - fpAddPrinterDriverEx, - NULL, /* fpSplReadPrinter */ - NULL, /* fpDriverUnloadComplete */ - NULL, /* fpGetSpoolFileInfo */ - NULL, /* fpCommitSpoolData */ - NULL, /* fpCloseSpoolFileHandle */ - NULL, /* fpFlushPrinter */ - NULL, /* fpSendRecvBidiData */ - NULL /* fpAddDriverCatalog */ - }; - pprovider = &backend; - -} - -/***************************************************** - * InitializePrintProvidor (localspl.@) - * - * Initialize the Printprovider - * - * PARAMS - * pPrintProvidor [I] Buffer to fill with a struct PRINTPROVIDOR - * cbPrintProvidor [I] Size of Buffer in Bytes - * pFullRegistryPath [I] Registry-Path for the Printprovidor - * - * RETURNS - * Success: TRUE and pPrintProvidor filled - * Failure: FALSE - * - * NOTES - * The RegistryPath should be: - * "System\CurrentControlSet\Control\Print\Providers\", - * but this Parameter is ignored in "localspl.dll". - * - */ - -BOOL WINAPI InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, - DWORD cbPrintProvidor, LPWSTR pFullRegistryPath) -{ - - TRACE("(%p, %u, %s)\n", pPrintProvidor, cbPrintProvidor, debugstr_w(pFullRegistryPath)); - memcpy(pPrintProvidor, pprovider, - (cbPrintProvidor < sizeof(PRINTPROVIDOR)) ? cbPrintProvidor : sizeof(PRINTPROVIDOR)); - - return TRUE; -} Index: dll/win32/localspl/resource.h =================================================================== --- dll/win32/localspl/resource.h (revision 73027) +++ dll/win32/localspl/resource.h (nonexistent) @@ -1,9 +0,0 @@ -#pragma once - -/* ## Resource-ID ## */ -#define IDS_LOCALPORT 500 -#define IDS_LOCALMONITOR 507 - -/* ## Reserved memorysize for the strings (in WCHAR) ## */ -#define IDS_LOCALMONITOR_MAXLEN 64 -#define IDS_LOCALPORT_MAXLEN 32 Index: dll/win32/ntprint/CMakeLists.txt =================================================================== --- dll/win32/ntprint/CMakeLists.txt (revision 73027) +++ dll/win32/ntprint/CMakeLists.txt (nonexistent) @@ -1,16 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -add_definitions(-D__WINESRC__) -spec2def(ntprint.dll ntprint.spec) - -list(APPEND SOURCE - ntprint.c - ntprint.rc - ${CMAKE_CURRENT_BINARY_DIR}/ntprint_stubs.c - ${CMAKE_CURRENT_BINARY_DIR}/ntprint.def) - -add_library(ntprint SHARED ${SOURCE}) -set_module_type(ntprint win32dll) -target_link_libraries(ntprint wine) -add_importlibs(ntprint winspool msvcrt kernel32 ntdll) -add_cd_file(TARGET ntprint DESTINATION reactos/system32 FOR all) Index: dll/win32/ntprint/ntprint.c =================================================================== --- dll/win32/ntprint/ntprint.c (revision 73027) +++ dll/win32/ntprint/ntprint.c (nonexistent) @@ -1,166 +0,0 @@ -/* - * Implementation of the Spooler Setup API (Printing) - * - * Copyright 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 - */ - -#define WIN32_NO_STATUS - -#include - -#define COBJMACROS -#define NONAMELESSUNION - -#include -#include -//#include "winerror.h" -#include -//#include "winnls.h" -//#include "winver.h" -#include - -//#include "wine/unicode.h" -#include - -WINE_DEFAULT_DEBUG_CHANNEL(ntprint); - -typedef struct { - LPMONITOR_INFO_2W mi2; /* Buffer for installed Monitors */ - DWORD installed; /* Number of installed Monitors */ -} monitorinfo_t; - -/***************************************************** - * DllMain - */ -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); - - switch(fdwReason) - { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls( hinstDLL ); - break; - } - return TRUE; -} - -/***************************************************** - * PSetupCreateMonitorInfo [NTPRINT.@] - * - * - */ - -HANDLE WINAPI PSetupCreateMonitorInfo(LPVOID unknown1, LPVOID unknown2,LPVOID unknown3) -{ - monitorinfo_t * mi=NULL; - DWORD needed; - DWORD res; - - TRACE("(%p, %p, %p)\n", unknown1, unknown2, unknown3); - - if ((unknown2 != NULL) || (unknown3 != NULL)) { - FIXME("got unknown parameter: (%p, %p, %p)\n", unknown1, unknown2, unknown3); - return NULL; - } - - mi = HeapAlloc(GetProcessHeap(), 0, sizeof(monitorinfo_t)); - if (!mi) { - /* FIXME: SetLastError() needed? */ - return NULL; - } - - /* Get the needed size for all Monitors */ - res = EnumMonitorsW(NULL, 2, NULL, 0, &needed, &mi->installed); - if (!res && (GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { - mi->mi2 = HeapAlloc(GetProcessHeap(), 0, needed); - res = EnumMonitorsW(NULL, 2, (LPBYTE) mi->mi2, needed, &needed, &mi->installed); - } - - if (!res) { - HeapFree(GetProcessHeap(), 0, mi); - /* FIXME: SetLastError() needed? */ - return NULL; - } - - TRACE("=> %p (%u monitors installed)\n", mi, mi->installed); - return mi; -} - -/***************************************************** - * PSetupDestroyMonitorInfo [NTPRINT.@] - * - */ - -VOID WINAPI PSetupDestroyMonitorInfo(HANDLE monitorinfo) -{ - monitorinfo_t * mi = monitorinfo; - - TRACE("(%p)\n", mi); - if (mi) { - if (mi->installed) HeapFree(GetProcessHeap(), 0, mi->mi2); - HeapFree(GetProcessHeap(), 0, mi); - } -} - -/***************************************************** - * PSetupEnumMonitor [NTPRINT.@] - * - * Copy the selected Monitorname to a buffer - * - * PARAMS - * monitorinfo [I] HANDLE from PSetupCreateMonitorInfo - * index [I] Nr. of the Monitorname to copy - * buffer [I] Target, that receive the Monitorname - * psize [IO] PTR to a DWORD that hold the size of the buffer and receive - * the needed size, when the buffer is too small - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * size is in Bytes on w2k and WCHAR on XP - * - */ - -BOOL WINAPI PSetupEnumMonitor(HANDLE monitorinfo, DWORD index, LPWSTR buffer, LPDWORD psize) -{ - monitorinfo_t * mi = monitorinfo; - LPWSTR nameW; - DWORD len; - - TRACE("(%p, %u, %p, %p) => %d\n", mi, index, buffer, psize, psize ? *psize : 0); - - if (index < mi->installed) { - nameW = mi->mi2[index].pName; - len = lstrlenW(nameW) + 1; - if (len <= *psize) { - memcpy(buffer, nameW, len * sizeof(WCHAR)); - TRACE("#%u: %s\n", index, debugstr_w(buffer)); - return TRUE; - } - *psize = len; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - SetLastError(ERROR_NO_MORE_ITEMS); - return FALSE; -} Index: dll/win32/ntprint/ntprint.rc =================================================================== --- dll/win32/ntprint/ntprint.rc (revision 73027) +++ dll/win32/ntprint/ntprint.rc (nonexistent) @@ -1,34 +0,0 @@ -/* - * Top level resource file for ntprint.dll - * - * Copyright 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 "winver.h" - -#define WINE_FILENAME_STR "ntprint.dll" -#define WINE_FILEDESCRIPTION_STR "Spooler Setup API (Printing)" - -/* Same Version as WinXP_sp2 */ -#define WINE_FILEVERSION 5,1,2600,2180 -#define WINE_FILEVERSION_STR "5.1.2600.2180" - -#define WINE_PRODUCTVERSION 5,1,2600,2180 -#define WINE_PRODUCTVERSION_STR "5.1.2600.2180" - -#include Index: dll/win32/ntprint/ntprint.spec =================================================================== --- dll/win32/ntprint/ntprint.spec (revision 73027) +++ dll/win32/ntprint/ntprint.spec (nonexistent) @@ -1,35 +0,0 @@ -@ stub ClassInstall32 -@ stub PSetupAssociateICMProfiles -@ stub PSetupBuildDriversFromPath -@ stub PSetupCreateDrvSetupPage -@ stdcall PSetupCreateMonitorInfo(long ptr ptr) -@ stub PSetupCreatePrinterDeviceInfoList -@ stub PSetupDestroyDriverInfo3 -@ stdcall PSetupDestroyMonitorInfo(long) -@ stub PSetupDestroyPrinterDeviceInfoList -@ stub PSetupDestroySelectedDriverInfo -@ stub PSetupDriverInfoFromName -@ stdcall PSetupEnumMonitor(long long ptr ptr) -@ stub PSetupFreeDrvField -@ stub PSetupGetDriverInfForPrinter -@ stub PSetupGetDriverInfo3 -@ stub PSetupGetLocalDataField -@ stub PSetupGetPathToSearch -@ stub PSetupGetSelectedDriverInfo -@ stub PSetupInstallICMProfiles -@ stub PSetupInstallMonitor -@ stub PSetupInstallPrinterDriver -@ stub PSetupInstallPrinterDriverFromTheWeb -@ stub PSetupIsCompatibleDriver -@ stub PSetupIsDriverInstalled -@ stub PSetupIsMonitorInstalled -@ stub PSetupIsOemDriver -@ stub PSetupIsTheDriverFoundInInfInstalled -@ stub PSetupKillBadUserConnections -@ stub PSetupPreSelectDriver -@ stub PSetupProcessPrinterAdded -@ stub PSetupRefreshDriverList -@ stub PSetupSelectDeviceButtons -@ stub PSetupSelectDriver -@ stub PSetupSetSelectDevTitleAndInstructions -@ stub PSetupThisPlatform Index: dll/win32/spoolss/CMakeLists.txt =================================================================== --- dll/win32/spoolss/CMakeLists.txt (revision 73027) +++ dll/win32/spoolss/CMakeLists.txt (nonexistent) @@ -1,20 +0,0 @@ - -add_definitions(-D__WINESRC__) -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB) - -list(APPEND SOURCE - spoolss_main.c - router.c - spoolss.h - ${CMAKE_CURRENT_BINARY_DIR}/spoolss_stubs.c) - -add_library(spoolss SHARED - ${SOURCE} - ${CMAKE_CURRENT_BINARY_DIR}/spoolss.def) - -set_module_type(spoolss win32dll) -target_link_libraries(spoolss wine) -add_importlibs(spoolss msvcrt kernel32 ntdll) -add_pch(spoolss spoolss.h SOURCE) -add_cd_file(TARGET spoolss DESTINATION reactos/system32 FOR all) Index: dll/win32/spoolss/router.c =================================================================== --- dll/win32/spoolss/router.c (revision 73027) +++ dll/win32/spoolss/router.c (nonexistent) @@ -1,563 +0,0 @@ -/* - * Routing for Spooler-Service helper DLL - * - * Copyright 2006-2009 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 "spoolss.h" - -#include -#include -#include - -#include - -/* ################################ */ - -#define MAX_BACKEND 3 - -typedef struct { - /* PRINTPROVIDOR functions */ - DWORD (WINAPI *fpOpenPrinter)(LPWSTR, HANDLE *, LPPRINTER_DEFAULTSW); - DWORD (WINAPI *fpSetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD); - DWORD (WINAPI *fpGetJob)(HANDLE, DWORD, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpEnumJobs)(HANDLE, DWORD, DWORD, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - HANDLE (WINAPI *fpAddPrinter)(LPWSTR, DWORD, LPBYTE); - DWORD (WINAPI *fpDeletePrinter)(HANDLE); - DWORD (WINAPI *fpSetPrinter)(HANDLE, DWORD, LPBYTE, DWORD); - DWORD (WINAPI *fpGetPrinter)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpEnumPrinters)(DWORD, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpAddPrinterDriver)(LPWSTR, DWORD, LPBYTE); - DWORD (WINAPI *fpEnumPrinterDrivers)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpGetPrinterDriver)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpGetPrinterDriverDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpDeletePrinterDriver)(LPWSTR, LPWSTR, LPWSTR); - DWORD (WINAPI *fpAddPrintProcessor)(LPWSTR, LPWSTR, LPWSTR, LPWSTR); - DWORD (WINAPI *fpEnumPrintProcessors)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpGetPrintProcessorDirectory)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpDeletePrintProcessor)(LPWSTR, LPWSTR, LPWSTR); - DWORD (WINAPI *fpEnumPrintProcessorDatatypes)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpStartDocPrinter)(HANDLE, DWORD, LPBYTE); - DWORD (WINAPI *fpStartPagePrinter)(HANDLE); - DWORD (WINAPI *fpWritePrinter)(HANDLE, LPVOID, DWORD, LPDWORD); - DWORD (WINAPI *fpEndPagePrinter)(HANDLE); - DWORD (WINAPI *fpAbortPrinter)(HANDLE); - DWORD (WINAPI *fpReadPrinter)(HANDLE, LPVOID, DWORD, LPDWORD); - DWORD (WINAPI *fpEndDocPrinter)(HANDLE); - DWORD (WINAPI *fpAddJob)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpScheduleJob)(HANDLE, DWORD); - DWORD (WINAPI *fpGetPrinterData)(HANDLE, LPWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpSetPrinterData)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD); - DWORD (WINAPI *fpWaitForPrinterChange)(HANDLE, DWORD); - DWORD (WINAPI *fpClosePrinter)(HANDLE); - DWORD (WINAPI *fpAddForm)(HANDLE, DWORD, LPBYTE); - DWORD (WINAPI *fpDeleteForm)(HANDLE, LPWSTR); - DWORD (WINAPI *fpGetForm)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpSetForm)(HANDLE, LPWSTR, DWORD, LPBYTE); - DWORD (WINAPI *fpEnumForms)(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpEnumMonitors)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpEnumPorts)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpAddPort)(LPWSTR, HWND, LPWSTR); - DWORD (WINAPI *fpConfigurePort)(LPWSTR, HWND, LPWSTR); - DWORD (WINAPI *fpDeletePort)(LPWSTR, HWND, LPWSTR); - HANDLE (WINAPI *fpCreatePrinterIC)(HANDLE, LPDEVMODEW); - DWORD (WINAPI *fpPlayGdiScriptOnPrinterIC)(HANDLE, LPBYTE, DWORD, LPBYTE, DWORD, DWORD); - DWORD (WINAPI *fpDeletePrinterIC)(HANDLE); - DWORD (WINAPI *fpAddPrinterConnection)(LPWSTR); - DWORD (WINAPI *fpDeletePrinterConnection)(LPWSTR); - DWORD (WINAPI *fpPrinterMessageBox)(HANDLE, DWORD, HWND, LPWSTR, LPWSTR, DWORD); - DWORD (WINAPI *fpAddMonitor)(LPWSTR, DWORD, LPBYTE); - DWORD (WINAPI *fpDeleteMonitor)(LPWSTR, LPWSTR, LPWSTR); - DWORD (WINAPI *fpResetPrinter)(HANDLE, LPPRINTER_DEFAULTSW); - DWORD (WINAPI *fpGetPrinterDriverEx)(HANDLE, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, DWORD, DWORD, PDWORD, PDWORD); - HANDLE (WINAPI *fpFindFirstPrinterChangeNotification)(HANDLE, DWORD, DWORD, LPVOID); - DWORD (WINAPI *fpFindClosePrinterChangeNotification)(HANDLE); - DWORD (WINAPI *fpAddPortEx)(HANDLE, LPWSTR, DWORD, LPBYTE, LPWSTR); - DWORD (WINAPI *fpShutDown)(LPVOID); - DWORD (WINAPI *fpRefreshPrinterChangeNotification)(HANDLE, DWORD, PVOID, PVOID); - DWORD (WINAPI *fpOpenPrinterEx)(LPWSTR, LPHANDLE, LPPRINTER_DEFAULTSW, LPBYTE, DWORD); - HANDLE (WINAPI *fpAddPrinterEx)(LPWSTR, DWORD, LPBYTE, LPBYTE, DWORD); - DWORD (WINAPI *fpSetPort)(LPWSTR, LPWSTR, DWORD, LPBYTE); - DWORD (WINAPI *fpEnumPrinterData)(HANDLE, DWORD, LPWSTR, DWORD, LPDWORD, LPDWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpDeletePrinterData)(HANDLE, LPWSTR); - DWORD (WINAPI *fpClusterSplOpen)(LPCWSTR, LPCWSTR, PHANDLE, LPCWSTR, LPCWSTR); - DWORD (WINAPI *fpClusterSplClose)(HANDLE); - DWORD (WINAPI *fpClusterSplIsAlive)(HANDLE); - DWORD (WINAPI *fpSetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, DWORD, LPBYTE, DWORD); - DWORD (WINAPI *fpGetPrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR, LPDWORD, LPBYTE, DWORD, LPDWORD); - DWORD (WINAPI *fpEnumPrinterDataEx)(HANDLE, LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpEnumPrinterKey)(HANDLE, LPCWSTR, LPWSTR, DWORD, LPDWORD); - DWORD (WINAPI *fpDeletePrinterDataEx)(HANDLE, LPCWSTR, LPCWSTR); - DWORD (WINAPI *fpDeletePrinterKey)(HANDLE hPrinter, LPCWSTR pKeyName); - DWORD (WINAPI *fpSeekPrinter)(HANDLE, LARGE_INTEGER, PLARGE_INTEGER, DWORD, BOOL); - DWORD (WINAPI *fpDeletePrinterDriverEx)(LPWSTR, LPWSTR, LPWSTR, DWORD, DWORD); - DWORD (WINAPI *fpAddPerMachineConnection)(LPCWSTR, LPCWSTR, LPCWSTR, LPCWSTR); - DWORD (WINAPI *fpDeletePerMachineConnection)(LPCWSTR, LPCWSTR); - DWORD (WINAPI *fpEnumPerMachineConnections)(LPCWSTR, LPBYTE, DWORD, LPDWORD, LPDWORD); - DWORD (WINAPI *fpXcvData)(HANDLE, LPCWSTR, PBYTE, DWORD, PBYTE, DWORD, PDWORD, PDWORD); - DWORD (WINAPI *fpAddPrinterDriverEx)(LPWSTR, DWORD, LPBYTE, DWORD); - DWORD (WINAPI *fpSplReadPrinter)(HANDLE, LPBYTE *, DWORD); - DWORD (WINAPI *fpDriverUnloadComplete)(LPWSTR); - DWORD (WINAPI *fpGetSpoolFileInfo)(HANDLE, LPWSTR *, LPHANDLE, HANDLE, HANDLE); - DWORD (WINAPI *fpCommitSpoolData)(HANDLE, DWORD); - DWORD (WINAPI *fpCloseSpoolFileHandle)(HANDLE); - DWORD (WINAPI *fpFlushPrinter)(HANDLE, LPBYTE, DWORD, LPDWORD, DWORD); - DWORD (WINAPI *fpSendRecvBidiData)(HANDLE, LPCWSTR, LPBIDI_REQUEST_CONTAINER, LPBIDI_RESPONSE_CONTAINER *); - DWORD (WINAPI *fpAddDriverCatalog)(HANDLE, DWORD, VOID *, DWORD); - /* Private Data */ - HMODULE dll; - LPWSTR dllname; - LPWSTR name; - LPWSTR regroot; - DWORD index; -} backend_t; - -/* ################################ */ - -static backend_t *backend[MAX_BACKEND]; -static DWORD used_backends = 0; - -static CRITICAL_SECTION backend_cs; -static CRITICAL_SECTION_DEBUG backend_cs_debug = -{ - 0, 0, &backend_cs, - { &backend_cs_debug.ProcessLocksList, &backend_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": backend_cs") } -}; -static CRITICAL_SECTION backend_cs = { &backend_cs_debug, -1, 0, 0, 0, 0 }; - -/* ################################ */ - -static WCHAR localsplW[] = {'l','o','c','a','l','s','p','l','.','d','l','l',0}; - -/****************************************************************** - * strdupW [internal] - * - * create a copy of a unicode-string - * - */ - -static LPWSTR strdupW(LPCWSTR p) -{ - LPWSTR ret; - DWORD len; - - if(!p) return NULL; - len = (lstrlenW(p) + 1) * sizeof(WCHAR); - ret = heap_alloc(len); - memcpy(ret, p, len); - return ret; -} - -/****************************************************************** - * backend_unload_all [internal] - * - * unload all backends - */ -void backend_unload_all(void) -{ - EnterCriticalSection(&backend_cs); - while (used_backends > 0) { - used_backends--; - FreeLibrary(backend[used_backends]->dll); - heap_free(backend[used_backends]->dllname); - heap_free(backend[used_backends]->name); - heap_free(backend[used_backends]->regroot); - heap_free(backend[used_backends]); - backend[used_backends] = NULL; - } - LeaveCriticalSection(&backend_cs); -} - -/****************************************************************************** - * backend_load [internal] - * - * load and init a backend - * - * PARAMS - * name [I] Printprovider to use for the backend. NULL for the local print provider - * - * RETURNS - * Success: PTR to the backend - * Failure: NULL - * - */ -static backend_t * backend_load(LPWSTR dllname, LPWSTR name, LPWSTR regroot) -{ - - BOOL (WINAPI *pInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR); - DWORD id; - DWORD res; - - TRACE("(%s, %s, %s)\n", debugstr_w(dllname), debugstr_w(name), debugstr_w(regroot)); - - EnterCriticalSection(&backend_cs); - id = used_backends; - - backend[id] = heap_alloc_zero(sizeof(backend_t)); - if (!backend[id]) { - LeaveCriticalSection(&backend_cs); - return NULL; - } - - backend[id]->dllname = strdupW(dllname); - backend[id]->name = strdupW(name); - backend[id]->regroot = strdupW(regroot); - - backend[id]->dll = LoadLibraryW(dllname); - if (backend[id]->dll) { - pInitializePrintProvidor = (void *) GetProcAddress(backend[id]->dll, "InitializePrintProvidor"); - if (pInitializePrintProvidor) { - - /* native localspl does not clear unused entries */ - res = pInitializePrintProvidor((PRINTPROVIDOR *) backend[id], sizeof(PRINTPROVIDOR), regroot); - if (res) { - used_backends++; - backend[id]->index = used_backends; - LeaveCriticalSection(&backend_cs); - TRACE("--> backend #%d: %p (%s)\n", id, backend[id], debugstr_w(dllname)); - return backend[id]; - } - } - FreeLibrary(backend[id]->dll); - } - heap_free(backend[id]->dllname); - heap_free(backend[id]->name); - heap_free(backend[id]->regroot); - heap_free(backend[id]); - backend[id] = NULL; - LeaveCriticalSection(&backend_cs); - WARN("failed to init %s: %u\n", debugstr_w(dllname), GetLastError()); - return NULL; -} - -/****************************************************************************** - * backend_load_all [internal] - * - * load and init all backends - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -BOOL backend_load_all(void) -{ - static BOOL failed = FALSE; - - EnterCriticalSection(&backend_cs); - - /* if we failed before, don't try again */ - if (!failed && (used_backends == 0)) { - backend_load(localsplW, NULL, NULL); - - /* ToDo: parse the registry and load all other backends */ - - failed = (used_backends == 0); - } - LeaveCriticalSection(&backend_cs); - TRACE("-> %d\n", !failed); - return (!failed); -} - -/****************************************************************************** - * backend_first [internal] - * - * find the first usable backend - * - * RETURNS - * Success: PTR to the backend - * Failure: NULL - * - */ -static backend_t * backend_first(LPWSTR name) -{ - - EnterCriticalSection(&backend_cs); - /* Load all backends, when not done yet */ - if (used_backends || backend_load_all()) { - - /* test for the local system first */ - if (!name || !name[0]) { - LeaveCriticalSection(&backend_cs); - return backend[0]; - } - } - - FIXME("server %s not supported in %d backends\n", debugstr_w(name), used_backends); - LeaveCriticalSection(&backend_cs); - return NULL; -} - -/****************************************************************** - * AddMonitorW (spoolss.@) - * - * Install a Printmonitor - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level (Must be 2) - * pMonitors [I] PTR to MONITOR_INFO_2 - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * All Files for the Monitor must already be copied to %winsysdir% ("%SystemRoot%\system32") - * - */ -BOOL WINAPI AddMonitorW(LPWSTR pName, DWORD Level, LPBYTE pMonitors) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %d, %p)\n", debugstr_w(pName), Level, pMonitors); - - if (Level != 2) { - SetLastError(ERROR_INVALID_LEVEL); - return FALSE; - } - - pb = backend_first(pName); - if (pb && pb->fpAddMonitor) - res = pb->fpAddMonitor(pName, Level, pMonitors); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u\n", res, GetLastError()); - return (res == ROUTER_SUCCESS); -} - -/****************************************************************** - * AddPrinterDriverExW (spoolss.@) - * - * Install a Printer Driver with the Option to upgrade / downgrade the Files - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * level [I] Level for the supplied DRIVER_INFO_*W struct - * pDriverInfo [I] PTR to DRIVER_INFO_*W struct with the Driver Parameter - * dwFileCopyFlags [I] How to Copy / Upgrade / Downgrade the needed Files - * - * RESULTS - * Success: TRUE - * Failure: FALSE - * - */ -BOOL WINAPI AddPrinterDriverExW(LPWSTR pName, DWORD level, LPBYTE pDriverInfo, DWORD dwFileCopyFlags) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %d, %p, 0x%x)\n", debugstr_w(pName), level, pDriverInfo, dwFileCopyFlags); - - if (!pDriverInfo) { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - pb = backend_first(pName); - if (pb && pb->fpAddPrinterDriverEx) - res = pb->fpAddPrinterDriverEx(pName, level, pDriverInfo, dwFileCopyFlags); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u\n", res, GetLastError()); - return (res == ROUTER_SUCCESS); -} - -/****************************************************************** - * DeleteMonitorW (spoolss.@) - * - * Delete a specific Printmonitor from a Printing-Environment - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * pEnvironment [I] Printing-Environment of the Monitor or NULL (Default) - * pMonitorName [I] Name of the Monitor, that should be deleted - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - */ -BOOL WINAPI DeleteMonitorW(LPWSTR pName, LPWSTR pEnvironment, LPWSTR pMonitorName) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %s, %s)\n", debugstr_w(pName), debugstr_w(pEnvironment), debugstr_w(pMonitorName)); - - pb = backend_first(pName); - if (pb && pb->fpDeleteMonitor) - res = pb->fpDeleteMonitor(pName, pEnvironment, pMonitorName); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u\n", res, GetLastError()); - return (res == ROUTER_SUCCESS); -} - -/****************************************************************** - * EnumMonitorsW (spoolss.@) - * - * Enumerate available Port-Monitors - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level - * pMonitors [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pMonitors - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pMonitors - * pcReturned [O] PTR to DWORD that receives the number of Monitors in pMonitors - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pMonitors, if cbBuf is too small - * - */ -BOOL WINAPI EnumMonitorsW(LPWSTR pName, DWORD Level, LPBYTE pMonitors, DWORD cbBuf, - LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pMonitors, - cbBuf, pcbNeeded, pcReturned); - - if (pcbNeeded) *pcbNeeded = 0; - if (pcReturned) *pcReturned = 0; - - pb = backend_first(pName); - if (pb && pb->fpEnumMonitors) - res = pb->fpEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u (%u byte for %u entries)\n\n", res, GetLastError(), - pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0); - - return (res == ROUTER_SUCCESS); -} - -/****************************************************************** - * EnumPortsW (spoolss.@) - * - * Enumerate available Ports - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * Level [I] Structure-Level (1 or 2) - * pPorts [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pPorts - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / required for pPorts - * pcReturned [O] PTR to DWORD that receives the number of Ports in pPorts - * - * RETURNS - * Success: TRUE - * Failure: FALSE and in pcbNeeded the Bytes required for pPorts, if cbBuf is too small - * - */ -BOOL WINAPI EnumPortsW(LPWSTR pName, DWORD Level, LPBYTE pPorts, DWORD cbBuf, - LPDWORD pcbNeeded, LPDWORD pcReturned) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %d, %p, %d, %p, %p)\n", debugstr_w(pName), Level, pPorts, cbBuf, - pcbNeeded, pcReturned); - - if (pcbNeeded) *pcbNeeded = 0; - if (pcReturned) *pcReturned = 0; - - pb = backend_first(pName); - if (pb && pb->fpEnumPorts) - res = pb->fpEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u (%u byte for %u entries)\n", res, GetLastError(), - pcbNeeded ? *pcbNeeded : 0, pcReturned ? *pcReturned : 0); - - return (res == ROUTER_SUCCESS); -} - -/****************************************************************** - * GetPrinterDriverDirectoryW (spoolss.@) - * - * Return the PATH for the Printer-Drivers - * - * PARAMS - * pName [I] Servername or NULL (local Computer) - * pEnvironment [I] Printing-Environment or NULL (Default) - * Level [I] Structure-Level (must be 1) - * pDriverDirectory [O] PTR to Buffer that receives the Result - * cbBuf [I] Size of Buffer at pDriverDirectory - * pcbNeeded [O] PTR to DWORD that receives the size in Bytes used / - * required for pDriverDirectory - * - * RETURNS - * Success: TRUE and in pcbNeeded the Bytes used in pDriverDirectory - * Failure: FALSE and in pcbNeeded the Bytes required for pDriverDirectory, - * if cbBuf is too small - * - * Native Values returned in pDriverDirectory on Success: - *| NT(Windows NT x86): "%winsysdir%\\spool\\DRIVERS\\w32x86" - *| NT(Windows x64): "%winsysdir%\\spool\\DRIVERS\\x64" - *| NT(Windows 4.0): "%winsysdir%\\spool\\DRIVERS\\win40" - *| win9x(Windows 4.0): "%winsysdir%" - * - * "%winsysdir%" is the Value from GetSystemDirectoryW() - * - */ -BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment, - DWORD Level, LPBYTE pDriverDirectory, DWORD cbBuf, LPDWORD pcbNeeded) -{ - backend_t * pb; - DWORD res = ROUTER_UNKNOWN; - - TRACE("(%s, %s, %d, %p, %d, %p)\n", debugstr_w(pName), - debugstr_w(pEnvironment), Level, pDriverDirectory, cbBuf, pcbNeeded); - - if (pcbNeeded) *pcbNeeded = 0; - - pb = backend_first(pName); - if (pb && pb->fpGetPrinterDriverDirectory) - res = pb->fpGetPrinterDriverDirectory(pName, pEnvironment, Level, - pDriverDirectory, cbBuf, pcbNeeded); - else - { - SetLastError(ERROR_PROC_NOT_FOUND); - } - - TRACE("got %u with %u (%u byte)\n", - res, GetLastError(), pcbNeeded ? *pcbNeeded : 0); - - return (res == ROUTER_SUCCESS); - -} Index: dll/win32/spoolss/spoolss.h =================================================================== --- dll/win32/spoolss/spoolss.h (revision 73027) +++ dll/win32/spoolss/spoolss.h (nonexistent) @@ -1,53 +0,0 @@ -/* - * Copyright 2006-2009 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 - */ - -#ifndef _SPOOLSS_H_ -#define _SPOOLSS_H_ - -#include - -#define WIN32_NO_STATUS -#include -#include - -#include -WINE_DEFAULT_DEBUG_CHANNEL(spoolss); - -/* ################################ */ - -BOOL backend_load_all(void) DECLSPEC_HIDDEN; -void backend_unload_all(void) DECLSPEC_HIDDEN; - -/* ## Memory allocation functions ## */ - -static inline void * __WINE_ALLOC_SIZE(1) heap_alloc( size_t len ) -{ - return HeapAlloc( GetProcessHeap(), 0, len ); -} - -static inline void * __WINE_ALLOC_SIZE(1) heap_alloc_zero( size_t len ) -{ - return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ); -} - -static inline BOOL heap_free( void *mem ) -{ - return HeapFree( GetProcessHeap(), 0, mem ); -} - -#endif /* _SPOOLSS_H_ */ Index: dll/win32/spoolss/spoolss.spec =================================================================== --- dll/win32/spoolss/spoolss.spec (revision 73027) +++ dll/win32/spoolss/spoolss.spec (nonexistent) @@ -1,151 +0,0 @@ -@ stub AbortPrinter -@ stub AddFormW -@ stub AddJobW -@ stdcall AddMonitorW(wstr long ptr) -@ stub AddPerMachineConnectionW -@ stub AddPortExW -@ stub AddPortW -@ stub AddPrintProcessorW -@ stub AddPrintProvidorW -@ stub AddPrinterConnectionW -@ stdcall AddPrinterDriverExW(wstr long ptr long) -@ stub AddPrinterDriverW -@ stub AddPrinterExW -@ stub AddPrinterW -@ stdcall AllocSplStr(wstr) -@ stub AppendPrinterNotifyInfoData -@ stdcall BuildOtherNamesFromMachineName(ptr ptr) -@ stub CallDrvDevModeConversion -@ stub CallRouterFindFirstPrinterChangeNotification -@ stub ClosePrinter -@ stub ClusterSplClose -@ stub ClusterSplIsAlive -@ stub ClusterSplOpen -@ stub ConfigurePortW -@ stub CreatePrinterIC -@ stub DbgGetPointers -@ stub DeleteFormW -@ stdcall DeleteMonitorW(wstr wstr wstr) -@ stub DeletePerMachineConnectionW -@ stub DeletePortW -@ stub DeletePrintProcessorW -@ stub DeletePrintProvidorW -@ stub DeletePrinter -@ stub DeletePrinterConnectionW -@ stub DeletePrinterDataExW -@ stub DeletePrinterDataW -@ stub DeletePrinterDriverExW -@ stub DeletePrinterDriverW -@ stub DeletePrinterIC -@ stub DeletePrinterKeyW -@ stdcall DllAllocSplMem(long) -@ stdcall DllFreeSplMem(ptr) -@ stdcall DllFreeSplStr(wstr) -@ stub EndDocPrinter -@ stub EndPagePrinter -@ stub EnumFormsW -@ stub EnumJobsW -@ stdcall EnumMonitorsW(wstr long ptr long ptr ptr) -@ stub EnumPerMachineConnectionsW -@ stdcall EnumPortsW(wstr long ptr long ptr ptr) -@ stub EnumPrintProcessorDatatypesW -@ stub EnumPrintProcessorsW -@ stub EnumPrinterDataExW -@ stub EnumPrinterDataW -@ stub EnumPrinterDriversW -@ stub EnumPrinterKeyW -@ stub EnumPrintersW -@ stub FindClosePrinterChangeNotification -@ stub FlushPrinter -@ stub FormatPrinterForRegistryKey -@ stub FormatRegistryKeyForPrinter -@ stub FreeOtherNames -@ stub GetClientUserHandle -@ stub GetFormW -@ stub GetJobAttributes -@ stub GetJobW -@ stub GetNetworkId -@ stub GetPrintProcessorDirectoryW -@ stub GetPrinterDataExW -@ stub GetPrinterDataW -@ stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr) -@ stub GetPrinterDriverExW -@ stub GetPrinterDriverW -@ stub GetPrinterW -@ stdcall ImpersonatePrinterClient(long) -@ stdcall InitializeRouter() -@ stdcall IsLocalCall() -@ stub IsNamedPipeRpcCall -@ stub LoadDriver -@ stub LoadDriverFiletoConvertDevmode -@ stub MIDL_user_allocate1 -@ stub MIDL_user_free1 -@ stub MarshallDownStructure -@ stub MarshallUpStructure -@ stub OldGetPrinterDriverW -@ stub OpenPrinterExW -@ stub OpenPrinterPortW -@ stub OpenPrinterW -@ stub PackStrings -@ stub PartialReplyPrinterChangeNotification -@ stub PlayGdiScriptOnPrinterIC -@ stub PrinterHandleRundown -@ stub PrinterMessageBoxW -@ stub ProvidorFindClosePrinterChangeNotification -@ stub ProvidorFindFirstPrinterChangeNotification -@ stub ReadPrinter -@ stub ReallocSplMem -@ stub ReallocSplStr -@ stub RemoteFindFirstPrinterChangeNotification -@ stub ReplyClosePrinter -@ stub ReplyOpenPrinter -@ stub ReplyPrinterChangeNotification -@ stub ResetPrinterW -@ stdcall RevertToPrinterSelf() -@ stub RouterAllocPrinterNotifyInfo -@ stub RouterFindFirstPrinterChangeNotification -@ stub RouterFindNextPrinterChangeNotification -@ stub RouterFreePrinterNotifyInfo -@ stub RouterRefreshPrinterChangeNotification -@ stub RouterReplyPrinter -@ stub ScheduleJob -@ stub SeekPrinter -@ stub SetAllocFailCount -@ stub SetFormW -@ stub SetJobW -@ stub SetPortW -@ stub SetPrinterDataExW -@ stub SetPrinterDataW -@ stub SetPrinterW -@ stub SplCloseSpoolFileHandle -@ stub SplCommitSpoolData -@ stub SplDriverUnloadComplete -@ stub SplGetSpoolFileInfo -@ stdcall SplInitializeWinSpoolDrv(ptr) -@ stdcall SplIsUpgrade() -@ stub SplProcessPnPEvent -@ stub SplReadPrinter -@ stub SplRegisterForDeviceEvents -@ stub SplStartPhase2Init -@ stub SplUnregisterForDeviceEvents -@ stub SpoolerFindClosePrinterChangeNotification -@ stub SpoolerFindFirstPrinterChangeNotification -@ stub SpoolerFindNextPrinterChangeNotification -@ stub SpoolerFreePrinterNotifyInfo -@ stdcall SpoolerHasInitialized() -@ stdcall SpoolerInit() -@ stub StartDocPrinterW -@ stub StartPagePrinter -@ stub UnloadDriver -@ stub UnloadDriverFile -@ stub UpdateBufferSize -@ stub UpdatePrinterRegAll -@ stub UpdatePrinterRegUser -@ stub WaitForPrinterChange -@ stdcall WaitForSpoolerInitialization() -@ stub WritePrinter -@ stub XcvDataW -@ stub bGetDevModePerUser -@ stub bSetDevModePerUser -@ stub pszDbgAllocMsgA -@ stub vDbgLogError Index: dll/win32/spoolss/spoolss_main.c =================================================================== --- dll/win32/spoolss/spoolss_main.c (revision 73027) +++ dll/win32/spoolss/spoolss_main.c (nonexistent) @@ -1,276 +0,0 @@ -/* - * Implementation of the Spooler-Service helper DLL - * - * Copyright 2006 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 "spoolss.h" - -/* ################################ */ - -static HMODULE hwinspool; - -static const WCHAR winspooldrvW[] = {'w','i','n','s','p','o','o','l','.','d','r','v',0}; - -/****************************************************************************** - * - */ -BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) -{ - TRACE("(%p, %d, %p)\n", hinstDLL, fdwReason, lpvReserved); - - switch (fdwReason) { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ - case DLL_PROCESS_ATTACH: { - DisableThreadLibraryCalls(hinstDLL); - break; - - case DLL_PROCESS_DETACH: - if (lpvReserved) break; - backend_unload_all(); - break; - } - } - return TRUE; -} - -/****************************************************************** - * AllocSplStr [SPOOLSS.@] - * - * Create a copy from the String on the Spooler-Heap - * - * PARAMS - * pwstr [I] PTR to the String to copy - * - * RETURNS - * Failure: NULL - * Success: PTR to the copied String - * - */ -LPWSTR WINAPI AllocSplStr(LPCWSTR pwstr) -{ - LPWSTR res = NULL; - DWORD len; - - TRACE("(%s)\n", debugstr_w(pwstr)); - if (!pwstr) return NULL; - - len = (lstrlenW(pwstr) + 1) * sizeof(WCHAR); - res = HeapAlloc(GetProcessHeap(), 0, len); - if (res) lstrcpyW(res, pwstr); - - TRACE("returning %p\n", res); - return res; -} - -/****************************************************************** - * BuildOtherNamesFromMachineName [SPOOLSS.@] - */ -BOOL WINAPI BuildOtherNamesFromMachineName(LPVOID * ptr1, LPVOID * ptr2) -{ - FIXME("(%p, %p) stub\n", ptr1, ptr2); - - *ptr1 = NULL; - *ptr2 = NULL; - return FALSE; -} - -/****************************************************************** - * DllAllocSplMem [SPOOLSS.@] - * - * Allocate cleared memory from the spooler heap - * - * PARAMS - * size [I] Number of bytes to allocate - * - * RETURNS - * Failure: NULL - * Success: PTR to the allocated memory - * - * NOTES - * We use the process heap (Windows use a separate spooler heap) - * - */ -LPVOID WINAPI DllAllocSplMem(DWORD size) -{ - LPVOID res; - - res = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); - TRACE("(%d) => %p\n", size, res); - return res; -} - -/****************************************************************** - * DllFreeSplMem [SPOOLSS.@] - * - * Free the allocated spooler memory - * - * PARAMS - * memory [I] PTR to the memory allocated by DllAllocSplMem - * - * RETURNS - * Failure: FALSE - * Success: TRUE - * - * NOTES - * We use the process heap (Windows use a separate spooler heap) - * - */ - -BOOL WINAPI DllFreeSplMem(LPBYTE memory) -{ - TRACE("(%p)\n", memory); - return HeapFree(GetProcessHeap(), 0, memory); -} - -/****************************************************************** - * DllFreeSplStr [SPOOLSS.@] - * - * Free the allocated Spooler-String - * - * PARAMS - * pwstr [I] PTR to the WSTR, allocated by AllocSplStr - * - * RETURNS - * Failure: FALSE - * Success: TRUE - * - */ - -BOOL WINAPI DllFreeSplStr(LPWSTR pwstr) -{ - TRACE("(%s) PTR: %p\n", debugstr_w(pwstr), pwstr); - return HeapFree(GetProcessHeap(), 0, pwstr); -} - - -/****************************************************************** - * ImpersonatePrinterClient [SPOOLSS.@] - */ -BOOL WINAPI ImpersonatePrinterClient(HANDLE hToken) -{ - FIXME("(%p) stub\n", hToken); - return TRUE; -} - -/****************************************************************** - * InitializeRouter [SPOOLSS.@] - */ -BOOL WINAPI InitializeRouter(void) -{ - TRACE("()\n"); - return backend_load_all(); -} - -/****************************************************************** - * IsLocalCall [SPOOLSS.@] - */ -BOOL WINAPI IsLocalCall(void) -{ - FIXME("() stub\n"); - return TRUE; -} - -/****************************************************************** - * RevertToPrinterSelf [SPOOLSS.@] - */ -HANDLE WINAPI RevertToPrinterSelf(void) -{ - FIXME("() stub\n"); - return (HANDLE) 0xdead0947; -} - -/****************************************************************** - * SplInitializeWinSpoolDrv [SPOOLSS.@] - * - * Dynamic load "winspool.drv" and fill an array with some function-pointer - * - * PARAMS - * table [I] array of function-pointer to fill - * - * RETURNS - * Success: TRUE - * Failure: FALSE - * - * NOTES - * Native "spoolss.dll" from w2k fill the table with 11 Function-Pointer. - * We implement the XP-Version (The table has only 9 Pointer) - * - */ -BOOL WINAPI SplInitializeWinSpoolDrv(LPVOID * table) -{ - DWORD res; - - TRACE("(%p)\n", table); - - hwinspool = LoadLibraryW(winspooldrvW); - if (!hwinspool) return FALSE; - - table[0] = (void *) GetProcAddress(hwinspool, "OpenPrinterW"); - table[1] = (void *) GetProcAddress(hwinspool, "ClosePrinter"); - table[2] = (void *) GetProcAddress(hwinspool, "SpoolerDevQueryPrintW"); - table[3] = (void *) GetProcAddress(hwinspool, "SpoolerPrinterEvent"); - table[4] = (void *) GetProcAddress(hwinspool, "DocumentPropertiesW"); - table[5] = (void *) GetProcAddress(hwinspool, (LPSTR) 212); /* LoadPrinterDriver */ - table[6] = (void *) GetProcAddress(hwinspool, (LPSTR) 213); /* RefCntLoadDriver */ - table[7] = (void *) GetProcAddress(hwinspool, (LPSTR) 214); /* RefCntUnloadDriver */ - table[8] = (void *) GetProcAddress(hwinspool, (LPSTR) 215); /* ForceUnloadDriver */ - - for (res = 0; res < 9; res++) { - if (table[res] == NULL) return FALSE; - } - - return TRUE; - -} - -/****************************************************************** - * SplIsUpgrade [SPOOLSS.@] - */ -BOOL WINAPI SplIsUpgrade(void) -{ - FIXME("() stub\n"); - return FALSE; -} - -/****************************************************************** - * SpoolerHasInitialized [SPOOLSS.@] - */ -BOOL WINAPI SpoolerHasInitialized(void) -{ - FIXME("() stub\n"); - return TRUE; -} - -/****************************************************************** - * SpoolerInit [SPOOLSS.@] - */ -BOOL WINAPI SpoolerInit(void) -{ - FIXME("() stub\n"); - return TRUE; -} - -/****************************************************************** - * WaitForSpoolerInitialization [SPOOLSS.@] - */ -BOOL WINAPI WaitForSpoolerInitialization(void) -{ - FIXME("() stub\n"); - return TRUE; -} Index: dll/win32/winspool/CMakeLists.txt =================================================================== --- dll/win32/winspool/CMakeLists.txt (revision 73027) +++ dll/win32/winspool/CMakeLists.txt (nonexistent) @@ -1,21 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) -spec2def(winspool.drv winspool.spec ADD_IMPORTLIB) - -list(APPEND SOURCE - info.c - stubs.c - precomp.h) - -add_library(winspool.drv SHARED - ${SOURCE} - winspool.rc - ${CMAKE_CURRENT_BINARY_DIR}/winspool_stubs.c - ${CMAKE_CURRENT_BINARY_DIR}/winspool.def) - -set_target_properties(winspool.drv PROPERTIES SUFFIX "") -set_module_type(winspool.drv win32dll UNICODE) -target_link_libraries(winspool.drv wine) -add_importlibs(winspool.drv advapi32 shlwapi msvcrt kernel32 ntdll) -add_pch(winspool.drv precomp.h SOURCE) -add_cd_file(TARGET winspool.drv DESTINATION reactos/system32 FOR all) Index: dll/win32/winspool/info.c =================================================================== --- dll/win32/winspool/info.c (revision 73027) +++ dll/win32/winspool/info.c (nonexistent) @@ -1,555 +0,0 @@ -/* - * WINSPOOL functions - * - * Copyright 1996 John Harvey - * Copyright 1998 Andreas Mohr - * Copyright 1999 Klaas van Gend - * Copyright 1999, 2000 Huw D M Davies - * Copyright 2001 Marcus Meissner - * - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "precomp.h" - -#include -#include -#include - -/****************************************************************************** - * GetDefaultPrinterA (WINSPOOL.@) - */ -BOOL WINAPI GetDefaultPrinterA(LPSTR name, LPDWORD namesize) -{ - char *ptr; - - if (*namesize < 1) - { - SetLastError (ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - if (!GetProfileStringA ("windows", "device", "", name, *namesize)) - { - SetLastError (ERROR_FILE_NOT_FOUND); - return FALSE; - } - - if ((ptr = strchr (name, ',')) == NULL) - { - SetLastError (ERROR_FILE_NOT_FOUND); - return FALSE; - } - - *ptr = '\0'; - *namesize = strlen (name) + 1; - return TRUE; -} - - -/****************************************************************************** - * GetDefaultPrinterW (WINSPOOL.@) - */ -BOOL WINAPI GetDefaultPrinterW(LPWSTR name, LPDWORD namesize) -{ - char *buf; - BOOL ret; - - if (*namesize < 1) - { - SetLastError (ERROR_INSUFFICIENT_BUFFER); - return FALSE; - } - - buf = HeapAlloc (GetProcessHeap (), 0, *namesize); - ret = GetDefaultPrinterA (buf, namesize); - if (ret) - { - DWORD len = MultiByteToWideChar (CP_ACP, 0, buf, -1, name, *namesize); - if (!len) - { - SetLastError (ERROR_INSUFFICIENT_BUFFER); - ret = FALSE; - } - else *namesize = len; - } - - HeapFree (GetProcessHeap (), 0, buf); - return ret; -} - -/****************************************************************************** - * AddPrintProvidorA (WINSPOOL.@) - */ -BOOL -WINAPI -AddPrintProvidorA(LPSTR Name, DWORD Level, PBYTE Buffer) -{ - if (Name || Level > 2 || Buffer == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (Level == 1) - { - BOOL bRet; - PROVIDOR_INFO_1W Provider; - PROVIDOR_INFO_1A *Prov = (PROVIDOR_INFO_1A*)Buffer; - - if (Prov->pName == NULL || Prov->pDLLName == NULL || Prov->pEnvironment == NULL) - { - return FALSE; - } - - Provider.pDLLName = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pDLLName)+1) * sizeof(WCHAR)); - if (Provider.pDLLName) - { - MultiByteToWideChar(CP_ACP, 0, Prov->pDLLName, -1, Provider.pDLLName, strlen(Prov->pDLLName)+1); - Provider.pDLLName[strlen(Prov->pDLLName)] = L'\0'; - } - - Provider.pEnvironment = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pEnvironment)+1) * sizeof(WCHAR)); - if (Provider.pEnvironment) - { - MultiByteToWideChar(CP_ACP, 0, Prov->pEnvironment, -1, Provider.pEnvironment, strlen(Prov->pEnvironment)+1); - Provider.pEnvironment[strlen(Prov->pEnvironment)] = L'\0'; - } - - Provider.pName = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pName)+1) * sizeof(WCHAR)); - if (Provider.pName) - { - MultiByteToWideChar(CP_ACP, 0, Prov->pName, -1, Provider.pName, strlen(Prov->pName)+1); - Provider.pName[strlen(Prov->pName)] = L'\0'; - } - - bRet = AddPrintProvidorW(NULL, Level, (LPBYTE)&Provider); - - if (Provider.pDLLName) - HeapFree(GetProcessHeap(), 0, Provider.pDLLName); - - if (Provider.pEnvironment) - HeapFree(GetProcessHeap(), 0, Provider.pEnvironment); - - if (Provider.pName) - HeapFree(GetProcessHeap(), 0, Provider.pName); - - return bRet; - } - else - { - PROVIDOR_INFO_2W Provider; - PROVIDOR_INFO_2A *Prov = (PROVIDOR_INFO_2A*)Buffer; - - Provider.pOrder = HeapAlloc(GetProcessHeap(), 0, (strlen(Prov->pOrder)+1) * sizeof(WCHAR)); - if (Provider.pOrder) - { - BOOL bRet; - MultiByteToWideChar(CP_ACP, 0, Prov->pOrder, -1, Provider.pOrder, strlen(Prov->pOrder)+1); - Provider.pOrder[strlen(Prov->pOrder)] = L'\0'; - - bRet = AddPrintProvidorW(NULL, Level, (LPBYTE)&Provider); - HeapFree(GetProcessHeap(), 0, Provider.pOrder); - return bRet; - } - } - - return FALSE; -} - - -/****************************************************************************** - * AddPrintProvidorW (WINSPOOL.@) - */ -BOOL -WINAPI -AddPrintProvidorW(LPWSTR Name, DWORD Level, PBYTE Buffer) -{ - HKEY hKey; - LPWSTR pOrder; - DWORD dwSize, dwType; - BOOL bRet = FALSE; - - if (Name || Level > 2 || Buffer == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) - { - return FALSE; - } - - if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ) - { - RegCloseKey(hKey); - return FALSE; - } - - pOrder = HeapAlloc(GetProcessHeap(), 0, dwSize); - if (!pOrder) - { - RegCloseKey(hKey); - return FALSE; - } - - if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, (LPBYTE)pOrder, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ) - { - RegCloseKey(hKey); - return FALSE; - } - - if (Level == 1) - { - LPWSTR pBuffer; - BOOL bFound = FALSE; - PROVIDOR_INFO_1W * Prov = (PROVIDOR_INFO_1W*)Buffer; - - if (Prov->pName == NULL || Prov->pDLLName == NULL || Prov->pEnvironment == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - RegCloseKey(hKey); - return FALSE; - } - - pBuffer = pOrder; - - while(pBuffer[0]) - { - if (!wcsicmp(pBuffer, Prov->pName)) - { - bFound = TRUE; - break; - } - pBuffer += wcslen(pBuffer) + 1; - } - - if (!bFound) - { - HKEY hSubKey; - DWORD dwFullSize = dwSize + (wcslen(Prov->pName)+1) * sizeof(WCHAR); - - if (RegCreateKeyExW(hKey, Prov->pName, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS) - { - RegSetValueExW(hSubKey, L"Name", 0, REG_SZ, (LPBYTE)Prov->pDLLName, (wcslen(Prov->pDLLName)+1) * sizeof(WCHAR)); - RegCloseKey(hSubKey); - } - - pBuffer = HeapAlloc(GetProcessHeap(), 0, dwFullSize); - if (pBuffer) - { - CopyMemory(pBuffer, pOrder, dwSize); - wcscpy(&pBuffer[(dwSize/sizeof(WCHAR))-1], Prov->pName); - pBuffer[(dwSize/sizeof(WCHAR)) + wcslen(Prov->pName)] = L'\0'; - RegSetValueExW(hKey, L"Order", 0, REG_MULTI_SZ, (LPBYTE)pBuffer, dwFullSize); - HeapFree(GetProcessHeap(), 0, pBuffer); - } - bRet = TRUE; - } - - } - - RegCloseKey(hKey); - HeapFree(GetProcessHeap(), 0, pOrder); - - return bRet; -} - -/****************************************************************************** - * DeletePrintProvidorA (WINSPOOL.@) - */ -BOOL -WINAPI -DeletePrintProvidorA(LPSTR Name, LPSTR Environment, LPSTR PrintProvidor) -{ - BOOL bRet; - LPWSTR Env, Prov; - - if (Name || !Environment || !PrintProvidor) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - Env = HeapAlloc(GetProcessHeap(), 0, (strlen(Environment)+1) * sizeof(WCHAR)); - if (!Env) - { - return FALSE; - } - - MultiByteToWideChar(CP_ACP, 0, Environment, -1, Env, strlen(Environment)+1); - Env[strlen(Environment)] = L'\0'; - - Prov = HeapAlloc(GetProcessHeap(), 0, (strlen(PrintProvidor)+1) * sizeof(WCHAR)); - if (!Prov) - { - HeapFree(GetProcessHeap(), 0, Env); - return FALSE; - } - - MultiByteToWideChar(CP_ACP, 0, PrintProvidor, -1, Prov, strlen(PrintProvidor)+1); - Prov[strlen(PrintProvidor)] = L'\0'; - - bRet = DeletePrintProvidorW(NULL, Env, Prov); - HeapFree(GetProcessHeap(), 0, Env); - HeapFree(GetProcessHeap(), 0, Prov); - - return bRet; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrintProvidorW(LPWSTR Name, LPWSTR Environment, LPWSTR PrintProvidor) -{ - HKEY hKey; - BOOL bFound; - DWORD dwType, dwSize, dwOffset, dwLength; - LPWSTR pOrder, pBuffer, pNew; - - if (Name || !Environment || !PrintProvidor) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ | KEY_WRITE, &hKey) != ERROR_SUCCESS) - { - return FALSE; - } - - if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, NULL, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ) - { - RegCloseKey(hKey); - return FALSE; - } - - pOrder = HeapAlloc(GetProcessHeap(), 0, dwSize); - if (!pOrder) - { - RegCloseKey(hKey); - return FALSE; - } - - if (RegQueryValueExW(hKey, L"Order", NULL, &dwType, (LPBYTE)pOrder, &dwSize) != ERROR_SUCCESS || dwType != REG_MULTI_SZ) - { - RegCloseKey(hKey); - return FALSE; - } - - - pBuffer = pOrder; - bFound = FALSE; - while(pBuffer[0]) - { - if (!wcsicmp(pBuffer, PrintProvidor)) - { - bFound = TRUE; - break; - } - pBuffer += wcslen(pBuffer) + 1; - } - - if (!bFound) - { - RegCloseKey(hKey); - HeapFree(GetProcessHeap(), 0, pOrder); - return FALSE; - } - - pNew = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize); - if (!pNew) - { - RegCloseKey(hKey); - HeapFree(GetProcessHeap(), 0, pOrder); - return FALSE; - } - - dwOffset = pBuffer - pOrder; - dwLength = (dwSize / sizeof(WCHAR)) - (dwOffset + wcslen(pBuffer) + 1); - CopyMemory(pNew, pOrder, dwOffset * sizeof(WCHAR)); - CopyMemory(&pNew[dwOffset], pBuffer + wcslen(pBuffer) + 1, dwLength); - - RegSetValueExW(hKey, L"Order", 0, REG_MULTI_SZ, (LPBYTE)pNew, (dwOffset + dwLength) * sizeof(WCHAR)); - RegDeleteKey(hKey, PrintProvidor); - - HeapFree(GetProcessHeap(), 0, pOrder); - HeapFree(GetProcessHeap(), 0, pNew); - RegCloseKey(hKey); - - return TRUE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -AddMonitorA(LPSTR Name, DWORD Level, PBYTE Monitors) -{ - LPWSTR szName = NULL; - MONITOR_INFO_2W Monitor; - MONITOR_INFO_2A *pMonitor; - BOOL bRet = FALSE; - - if (Level != 2 || !Monitors) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - pMonitor = (MONITOR_INFO_2A*)Monitors; - if (pMonitor->pDLLName == NULL || pMonitor->pName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - ZeroMemory(&Monitor, sizeof(Monitor)); - - if (Name) - { - szName = HeapAlloc(GetProcessHeap(), 0, (strlen(Name) + 1) * sizeof(WCHAR)); - if (!szName) - { - return FALSE; - } - MultiByteToWideChar(CP_ACP, 0, Name, -1, szName, strlen(Name)+1); - szName[strlen(Name)] = L'\0'; - } - - Monitor.pDLLName = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pDLLName)+1) * sizeof(WCHAR)); - if (!Monitor.pDLLName) - { - goto cleanup; - } - MultiByteToWideChar(CP_ACP, 0, pMonitor->pDLLName, -1, Monitor.pDLLName, strlen(pMonitor->pDLLName)+1); - pMonitor->pDLLName[strlen(pMonitor->pDLLName)] = L'\0'; - - Monitor.pName = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pName)+1) * sizeof(WCHAR)); - if (!Monitor.pName) - { - goto cleanup; - } - MultiByteToWideChar(CP_ACP, 0, pMonitor->pName, -1, Monitor.pName, strlen(pMonitor->pName)+1); - pMonitor->pName[strlen(pMonitor->pName)] = L'\0'; - - - if (pMonitor->pEnvironment) - { - Monitor.pEnvironment = HeapAlloc(GetProcessHeap(), 0, (strlen(pMonitor->pEnvironment)+1) * sizeof(WCHAR)); - if (!Monitor.pEnvironment) - { - goto cleanup; - } - MultiByteToWideChar(CP_ACP, 0, pMonitor->pEnvironment, -1, Monitor.pEnvironment, strlen(pMonitor->pEnvironment)+1); - pMonitor->pEnvironment[strlen(pMonitor->pEnvironment)] = L'\0'; - } - - bRet = AddMonitorW(szName, Level, (LPBYTE)&Monitor); - -cleanup: - - if (szName) - HeapFree(GetProcessHeap(), 0, szName); - - if (Monitor.pDLLName) - HeapFree(GetProcessHeap(), 0, Monitor.pDLLName); - - if (Monitor.pEnvironment) - HeapFree(GetProcessHeap(), 0, Monitor.pEnvironment); - - if (Monitor.pName) - HeapFree(GetProcessHeap(), 0, Monitor.pName); - - return bRet; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddMonitorW(LPWSTR Name, DWORD Level, PBYTE Monitors) -{ - WCHAR szPath[MAX_PATH]; - HMODULE hLibrary = NULL; - FARPROC InitProc; - HKEY hKey, hSubKey; - MONITOR_INFO_2W * pMonitor; - - - if (Level != 2 || !Monitors) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - pMonitor = (MONITOR_INFO_2W*)Monitors; - - if (pMonitor->pDLLName == NULL || pMonitor->pName == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (wcschr(pMonitor->pDLLName, L'\\')) - { - hLibrary = LoadLibraryExW(pMonitor->pDLLName, NULL, 0); - } - else if (GetSystemDirectoryW(szPath, MAX_PATH) && PathAddBackslashW(szPath)) - { - wcscat(szPath, pMonitor->pDLLName); - hLibrary = LoadLibraryExW(szPath, NULL, 0); - } - - if (!hLibrary) - { - return FALSE; - } - - InitProc = GetProcAddress(hLibrary, "InitializePrintMonitor"); - if (!InitProc) - { - InitProc = GetProcAddress(hLibrary, "InitializePrintMonitor2"); - if (!InitProc) - { - FreeLibrary(hLibrary); - SetLastError(ERROR_PROC_NOT_FOUND); - return FALSE; - } - } - - // FIXME - // Initialize monitor - FreeLibrary(hLibrary); - - if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors", 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) - { - if (RegCreateKeyExW(hKey, pMonitor->pName, 0, NULL, 0, KEY_WRITE, NULL, &hSubKey, NULL) == ERROR_SUCCESS) - { - RegSetValueExW(hSubKey, L"Driver", 0, REG_SZ, (LPBYTE)pMonitor->pDLLName, (wcslen(pMonitor->pDLLName)+1)*sizeof(WCHAR)); - RegCloseKey(hSubKey); - } - RegCloseKey(hKey); - } - return TRUE; -} - Index: dll/win32/winspool/precomp.h =================================================================== --- dll/win32/winspool/precomp.h (revision 73027) +++ dll/win32/winspool/precomp.h (nonexistent) @@ -1,17 +0,0 @@ -#ifndef _WINSPOOL_DRV_PCH_ -#define _WINSPOOL_DRV_PCH_ - -#include - -#include - -#define WIN32_NO_STATUS -#define _INC_WINDOWS -#define COM_NO_WINDOWS_H - -#include -#include -#include -#include - -#endif /* _WINSPOOL_DRV_PCH_ */ Index: dll/win32/winspool/stubs.c =================================================================== --- dll/win32/winspool/stubs.c (revision 73027) +++ dll/win32/winspool/stubs.c (nonexistent) @@ -1,1773 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS winspool DRV - * FILE: stubs.c - * PURPOSE: Stub functions - * PROGRAMMERS: Ge van Geldorp (ge@gse.nl) - * REVISIONS: - */ - -#include "precomp.h" - -#include - -/* - * @unimplemented - */ -BOOL -WINAPI -DllMain(HINSTANCE InstDLL, - DWORD Reason, - LPVOID Reserved) -{ - return TRUE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AbortPrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool AbortPrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddFormA(HANDLE Printer, DWORD Level, PBYTE Form) -{ - OutputDebugStringW(L"winspool AddFormA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddFormW(HANDLE Printer, DWORD Level, PBYTE Form) -{ - OutputDebugStringW(L"winspool AddFormW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddJobA(HANDLE Printer, DWORD Level, PBYTE Data, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool AddJobA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddJobW(HANDLE Printer, DWORD Level, PBYTE Data, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool AddJobW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPortA(LPSTR Name, HWND Wnd, LPSTR MonitorName) -{ - OutputDebugStringW(L"winspool stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPortW(LPWSTR Name, HWND Wnd, LPWSTR MonitorName) -{ - OutputDebugStringW(L"winspool AddPortW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -HANDLE -WINAPI -AddPrinterA(LPSTR Name, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool AddPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return NULL; -} - - -/* - * @unimplemented - */ -HANDLE -WINAPI -AddPrinterW(LPWSTR Name, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool AddPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return NULL; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterConnectionA(LPSTR Name) -{ - OutputDebugStringW(L"winspool AddPrinterConnectionA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterConnectionW(LPWSTR Name) -{ - OutputDebugStringW(L"winspool AddPrinterConnectionW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterDriverA(LPSTR Name, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool AddPrinterDriverA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterDriverW(LPWSTR Name, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool AddPrinterDriverW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrintProcessorA(LPSTR Name, LPSTR Environment, LPSTR PathName, LPSTR PrintProcessorName) -{ - OutputDebugStringW(L"winspool AddPrintProcessorA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrintProcessorW(LPWSTR Name, LPWSTR Environment, LPWSTR PathName, LPWSTR PrintProcessorName) -{ - OutputDebugStringW(L"winspool AddPrintProcessorW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - -/* - * @unimplemented - */ -LONG -WINAPI -AdvancedDocumentPropertiesA(HWND Wnd, HANDLE Printer, LPSTR DeviceName, PDEVMODEA DevModeOut, PDEVMODEA DevModeIn) -{ - OutputDebugStringW(L"winspool AdvancedDocumentPropertiesA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -LONG -WINAPI -AdvancedDocumentPropertiesW(HWND Wnd, HANDLE Printer, LPWSTR DeviceName, PDEVMODEW DevModeOut, PDEVMODEW DevModeIn) -{ - OutputDebugStringW(L"winspool AdvancedDocumentPropertiesW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ClosePrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool ClosePrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ConfigurePortA(LPSTR Name, HWND Wnd, LPSTR PortName) -{ - OutputDebugStringW(L"winspool ConfigurePortA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ConfigurePortW(LPWSTR Name, HWND Wnd, LPWSTR PortName) -{ - OutputDebugStringW(L"winspool ConfigurePortW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -HANDLE -WINAPI -ConnectToPrinterDlg(HWND Wnd, DWORD Flags) -{ - OutputDebugStringW(L"winspool ConnectToPrinterDlg stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return NULL; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteFormA(HANDLE Printer, LPSTR Name) -{ - OutputDebugStringW(L"winspool DeleteFormA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteFormW(HANDLE Printer, LPWSTR Name) -{ - OutputDebugStringW(L"winspool DeleteFormW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteMonitorA(LPSTR Name, LPSTR Environment, LPSTR MonitorName) -{ - OutputDebugStringW(L"winspool DeleteMonitorA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteMonitorW(LPWSTR Name, LPWSTR Environment, LPWSTR MonitorName) -{ - OutputDebugStringW(L"winspool DeleteMonitorW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePortA(LPSTR Name, HWND Wnd, LPSTR PortName) -{ - OutputDebugStringW(L"winspool DeletePortA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePortW(LPWSTR Name, HWND Wnd, LPWSTR PortName) -{ - OutputDebugStringW(L"winspool DeletePortW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool DeletePrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterConnectionA(LPSTR Name) -{ - OutputDebugStringW(L"winspool DeletePrinterConnectionA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterConnectionW(LPWSTR Name) -{ - OutputDebugStringW(L"winspool DeletePrinterConnectionW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -DeletePrinterDataA(HANDLE Printer, LPSTR Name) -{ - OutputDebugStringW(L"winspool DeletePrinterDataA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -DeletePrinterDataW(HANDLE Printer, LPWSTR Name) -{ - OutputDebugStringW(L"winspool DeletePrinterDataW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterDriverA(LPSTR Name, LPSTR Environment, LPSTR Driver) -{ - OutputDebugStringW(L"winspool DeletePrinterDriverA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterDriverW(LPWSTR Name, LPWSTR Environment, LPWSTR Driver) -{ - OutputDebugStringW(L"winspool DeletePrinterDriverW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrintProcessorA(LPSTR Name, LPSTR Environment, LPSTR PrintProcessor) -{ - OutputDebugStringW(L"winspool DeletePrintProcessorA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrintProcessorW(LPWSTR Name, LPWSTR Environment, LPWSTR PrintProcessor) -{ - OutputDebugStringW(L"winspool DeletePrintProcessorW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -DeviceCapabilitiesA(LPCSTR Device, LPCSTR Port, WORD Capability, LPSTR Buffer, CONST DEVMODEA *DevMode) -{ - OutputDebugStringW(L"winspool DeviceCapabilitiesA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return -1; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -DeviceCapabilitiesW(LPCWSTR Device, LPCWSTR Port, WORD Capability, LPWSTR Buffer, CONST DEVMODEW *DevMode) -{ - OutputDebugStringW(L"winspool DeviceCapabilitiesW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return -1; -} - - -/* - * @unimplemented - */ -LONG -WINAPI -DocumentPropertiesA(HWND Wnd, HANDLE Printer, LPSTR Device, PDEVMODEA DevModeOut, PDEVMODEA DevModeIn, DWORD Mode) -{ - OutputDebugStringW(L"winspool DocumentPropertiesA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return -1L; -} - - -/* - * @unimplemented - */ -LONG -WINAPI -DocumentPropertiesW(HWND Wnd, HANDLE Printer, LPWSTR Device, PDEVMODEW DevModeOut, PDEVMODEW DevModeIn, DWORD Mode) -{ - OutputDebugStringW(L"winspool DocumentPropertiesW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EndDocPrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool EndDocPrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EndPagePrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool EndPagePrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumFormsA(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumFormsA stub called\n"); - *Needed = 0; - *Returned = 0; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumFormsW(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumFormsW stub called\n"); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumJobsA(HANDLE Printer, DWORD First, DWORD NoJobs, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumJobsA stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumJobsW(HANDLE Printer, DWORD First, DWORD NoJobs, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumJobsW stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumMonitorsA(LPSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumMonitorsA stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumMonitorsW(LPWSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumMonitorsW stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPortsA(LPSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPortsA stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPortsW(LPWSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPortsW stub called\n"); - *Needed = 0; - *Returned = 0; - - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterDataA(HANDLE Printer, DWORD Index, LPSTR Name, DWORD NameSize, PDWORD NameReturned, PDWORD Type, PBYTE Buffer, DWORD BufSize, PDWORD BufReturned) -{ - OutputDebugStringW(L"winspool EnumPrinterDataA stub called\n"); - - return ERROR_CALL_NOT_IMPLEMENTED; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterDataW(HANDLE Printer, DWORD Index, LPWSTR Name, DWORD NameSize, PDWORD NameReturned, PDWORD Type, PBYTE Buffer, DWORD BufSize, PDWORD BufReturned) -{ - OutputDebugStringW(L"winspool EnumPrinterDataW stub called\n"); - - return ERROR_CALL_NOT_IMPLEMENTED; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrinterDriversA(LPSTR Name, LPSTR Environment, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrinterDriversA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrinterDriversW(LPWSTR Name, LPWSTR Environment, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrinterDriversW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterKeyA(HANDLE Printer, LPSTR KeyName, LPTSTR Subkey, DWORD SubkeySize, PDWORD SubkeyReturned) -{ - OutputDebugStringW(L"winspool EnumPrinterKeyA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - *SubkeyReturned = 0; - - return ERROR_FILE_NOT_FOUND; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterKeyW(HANDLE Printer, LPWSTR KeyName, LPTSTR Subkey, DWORD SubkeySize, PDWORD SubkeyReturned) -{ - OutputDebugStringW(L"winspool EnumPrinterKeyW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - *SubkeyReturned = 0; - - return ERROR_FILE_NOT_FOUND; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintersA(DWORD Flags, LPSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintersA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintersW(DWORD Flags, LPWSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintersW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintProcessorDatatypesA(LPSTR Name, LPSTR PrintProcessor, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintProcessorDatatypesA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintProcessorDatatypesW(LPWSTR Name, LPWSTR PrintProcessor, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintProcessorDatatypesW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintProcessorsA(LPSTR Name, LPSTR Environment, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintProcessorsA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumPrintProcessorsW(LPWSTR Name, LPWSTR Environment, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed, PDWORD Returned) -{ - OutputDebugStringW(L"winspool EnumPrintProcessorsW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - *Needed = 0; - *Returned = 0; - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -FindClosePrinterChangeNotification(HANDLE Printer) -{ - OutputDebugStringW(L"winspool FindClosePrinterChangeNotification stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -HANDLE -WINAPI -FindFirstPrinterChangeNotification(HANDLE Printer, DWORD Flags, DWORD Options, PVOID NotifyOptions) -{ - OutputDebugStringW(L"winspool FindFirstPrinterChangeNotification stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return INVALID_HANDLE_VALUE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -FindNextPrinterChangeNotification(HANDLE Printer, PDWORD Change, LPVOID NotifyOptions, LPVOID* NotifyInfo) -{ - OutputDebugStringW(L"winspool FindNextPrinterChangeNotification stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -FreePrinterNotifyInfo(PPRINTER_NOTIFY_INFO NotifyInfo) -{ - OutputDebugStringW(L"winspool FreePrinterNotifyInfo stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetFormA(HANDLE Printer, LPSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetFormA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetFormW(HANDLE Printer, LPWSTR Name, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetFormW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetJobA(HANDLE Printer, DWORD Job, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetJobA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetJobW(HANDLE Printer, DWORD Job, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetJobW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterA(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterW(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -GetPrinterDataA(HANDLE Printer, LPSTR Name, PDWORD Type, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDataA stub called\n"); - - return ERROR_CALL_NOT_IMPLEMENTED; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -GetPrinterDataW(HANDLE Printer, LPWSTR Name, PDWORD Type, PBYTE Buffer, DWORD BufSize, PDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDataW stub called\n"); - - return ERROR_CALL_NOT_IMPLEMENTED; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterDriverA(HANDLE Printer, LPSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDriverA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterDriverW(HANDLE Printer, LPWSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDriverW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterDriverDirectoryA(LPSTR Name, LPSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDriverDirectoryA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrinterDriverDirectoryW(LPWSTR Name, LPWSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrinterDriverDirectoryW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrintProcessorDirectoryA(LPSTR Name, LPSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrintProcessorDirectoryA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -GetPrintProcessorDirectoryW(LPWSTR Name, LPWSTR Environment, DWORD Level, LPBYTE Buffer, DWORD BufSize, LPDWORD Needed) -{ - OutputDebugStringW(L"winspool GetPrintProcessorDirectoryW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -OpenPrinterA(LPSTR Name, PHANDLE Printer, LPPRINTER_DEFAULTSA Defaults) -{ - OutputDebugStringW(L"winspool OpenPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -OpenPrinterW(LPWSTR Name, PHANDLE Printer, LPPRINTER_DEFAULTSW Defaults) -{ - OutputDebugStringW(L"winspool OpenPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -PrinterMessageBoxA(HANDLE Printer, DWORD Error, HWND Wnd, LPSTR Text, LPSTR Caption, DWORD Type) -{ - OutputDebugStringW(L"winspool PrinterMessageBoxA stub called\n"); - - return IDCANCEL; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -PrinterMessageBoxW(HANDLE Printer, DWORD Error, HWND Wnd, LPWSTR Text, LPWSTR Caption, DWORD Type) -{ - OutputDebugStringW(L"winspool PrinterMessageBoxW stub called\n"); - - return IDCANCEL; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -PrinterProperties(HWND Wnd, HANDLE Printer) -{ - OutputDebugStringW(L"winspool PrinterProperties stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ReadPrinter(HANDLE Printer, PVOID Buffer, DWORD BufSize, PDWORD Received) -{ - OutputDebugStringW(L"winspool ReadPrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ResetPrinterA(HANDLE Printer, LPPRINTER_DEFAULTSA Defaults) -{ - OutputDebugStringW(L"winspool ResetPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ResetPrinterW(HANDLE Printer, LPPRINTER_DEFAULTSW Defaults) -{ - OutputDebugStringW(L"winspool ResetPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -ScheduleJob(HANDLE Printer, DWORD Job) -{ - OutputDebugStringW(L"winspool ScheduleJob stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetFormA(HANDLE Printer, LPSTR Form, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool SetFormA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetFormW(HANDLE Printer, LPWSTR Form, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool SetFormW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetJobA(HANDLE Printer, DWORD Job, DWORD Level, PBYTE Buffer, DWORD Command) -{ - OutputDebugStringW(L"winspool SetJobA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetJobW(HANDLE Printer, DWORD Job, DWORD Level, PBYTE Buffer, DWORD Command) -{ - OutputDebugStringW(L"winspool SetJobW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetPrinterA(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD Command) -{ - OutputDebugStringW(L"winspool SetPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetPrinterW(HANDLE Printer, DWORD Level, PBYTE Buffer, DWORD Command) -{ - OutputDebugStringW(L"winspool SetPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetPrinterDataA(HANDLE Printer, LPSTR Name, DWORD Type, PBYTE Buffer, DWORD BufSize) -{ - OutputDebugStringW(L"winspool SetPrinterDataA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -SetPrinterDataW(HANDLE Printer, LPWSTR Name, DWORD Type, PBYTE Buffer, DWORD BufSize) -{ - OutputDebugStringW(L"winspool SetPrinterDataW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -StartDocPrinterA(HANDLE Printer, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool StartDocPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -StartDocPrinterW(HANDLE Printer, DWORD Level, PBYTE Buffer) -{ - OutputDebugStringW(L"winspool StartDocPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -StartPagePrinter(HANDLE Printer) -{ - OutputDebugStringW(L"winspool StartPagePrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -DWORD -WINAPI -WaitForPrinterChange(HANDLE Printer, DWORD Flags) -{ - OutputDebugStringW(L"winspool WaitForPrinterChange stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return 0; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -WritePrinter(HANDLE Printer, PVOID Buffer, DWORD BufSize, PDWORD Written) -{ - OutputDebugStringW(L"winspool WritePrinter stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -XcvDataW(HANDLE hXcv, - LPCWSTR pszDataName, - PBYTE pInputData, - DWORD cbInputData, - PBYTE pOutputData, - DWORD cbOutputData, - PDWORD pcbOutputNeeded, - PDWORD pdwStatus) -{ - OutputDebugStringW(L"winspool XcvDataW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -SetDefaultPrinterA(LPCSTR pszPrinter) -{ - OutputDebugStringW(L"winspool SetDefaultPrinterA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -SetDefaultPrinterW(LPCWSTR pszPrinter) -{ - OutputDebugStringW(L"winspool SetDefaultPrinterW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPortExA(LPSTR pName, - DWORD dwLevel, - LPBYTE pBuffer, - LPSTR pMonitorName) -{ - OutputDebugStringW(L"winspool AddPortExA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPortExW(LPWSTR pName, - DWORD dwLevel, - LPBYTE pBuffer, - LPWSTR pMonitorName) -{ - OutputDebugStringW(L"winspool AddPortExW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterDriverExA(LPSTR pName, - DWORD dwLevel, - LPBYTE pDriverInfo, - DWORD dwFileCopyFlags) -{ - OutputDebugStringW(L"winspool AddPrinterDriverExA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -AddPrinterDriverExW(LPWSTR pName, - DWORD dwLevel, - LPBYTE pDriverInfo, - DWORD dwFileCopyFlags) -{ - OutputDebugStringW(L"winspool AddPrinterDriverExW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -DeletePrinterDataExA(HANDLE hPrinter, - LPCSTR pKeyName, - LPCSTR pValueName) -{ - OutputDebugStringW(L"winspool DeletePrinterDataExA stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -DeletePrinterDataExW(HANDLE hPrinter, - LPCWSTR pKeyName, - LPCWSTR pValueName) -{ - OutputDebugStringW(L"winspool DeletePrinterDataExW stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterDriverExA(LPSTR pName, - LPSTR pEnvironment, - LPSTR pDriverName, - DWORD dwDeleteFlag, - DWORD dwVersionFlag) -{ - OutputDebugStringW(L"winspool DeletePrinterDriverExA stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -DeletePrinterDriverExW(LPWSTR pName, - LPWSTR pEnvironment, - LPWSTR pDriverName, - DWORD dwDeleteFlag, - DWORD dwVersionFlag) -{ - OutputDebugStringW(L"winspool DeletePrinterDriverExW stub called\n"); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterDataExA(HANDLE hPrinter, - LPCSTR pKeyName, - LPBYTE pEnumValues, - DWORD cbEnumValues, - LPDWORD pcbEnumValues, - LPDWORD pnEnumValues) -{ - OutputDebugStringW(L"winspool EnumPrinterDataExA stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -EnumPrinterDataExW(HANDLE hPrinter, - LPCWSTR pKeyName, - LPBYTE pEnumValues, - DWORD cbEnumValues, - LPDWORD pcbEnumValues, - LPDWORD pnEnumValues) -{ - OutputDebugStringW(L"winspool EnumPrinterDataExW stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -LONG -WINAPI -ExtDeviceMode(HWND hWnd, - HANDLE hInst, - LPDEVMODEA pDevModeOutput, - LPSTR pDeviceName, - LPSTR pPort, - LPDEVMODEA pDevModeInput, - LPSTR pProfile, - DWORD fMode) -{ - OutputDebugStringW(L"winspool ExtDeviceMode stub called\n"); - return -1; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -GetPrinterDataExA(HANDLE hPrinter, - LPCSTR pKeyName, - LPCSTR pValueName, - LPDWORD pType, - LPBYTE pData, - DWORD nSize, - LPDWORD pcbNeeded) -{ - OutputDebugStringW(L"winspool GetPrinterDataExA stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -GetPrinterDataExW(HANDLE hPrinter, - LPCWSTR pKeyName, - LPCWSTR pValueName, - LPDWORD pType, - LPBYTE pData, - DWORD nSize, - LPDWORD pcbNeeded) -{ - OutputDebugStringW(L"winspool GetPrinterDataExW stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -SetPrinterDataExA(HANDLE hPrinter, - LPCSTR pKeyName, - LPCSTR pValueName, - DWORD dwType, - LPBYTE pData, - DWORD cbData) -{ - OutputDebugStringW(L"winspool SetPrinterDataExA stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -DWORD -WINAPI -SetPrinterDataExW(HANDLE hPrinter, - LPCWSTR pKeyName, - LPCWSTR pValueName, - DWORD dwType, - LPBYTE pData, - DWORD cbData) -{ - OutputDebugStringW(L"winspool SetPrinterDataExW stub called\n"); - return ERROR_CALL_NOT_IMPLEMENTED; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -SpoolerInit(VOID) -{ - OutputDebugStringW(L"winspool SpoolerInit stub called\n"); - return FALSE; -} Index: dll/win32/winspool/winspool.rc =================================================================== --- dll/win32/winspool/winspool.rc (revision 73027) +++ dll/win32/winspool/winspool.rc (nonexistent) @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "Windows printer spooler" -#define REACTOS_STR_INTERNAL_NAME "winspool" -#define REACTOS_STR_ORIGINAL_FILENAME "winspool.drv" -#include Index: dll/win32/winspool/winspool.spec =================================================================== --- dll/win32/winspool/winspool.spec (revision 73027) +++ dll/win32/winspool/winspool.spec (nonexistent) @@ -1,193 +0,0 @@ -100 stub -noname EnumPrinterPropertySheets -101 stub -noname ClusterSplOpen -102 stub -noname ClusterSplClose -103 stub -noname ClusterSplIsAlive -104 stub PerfClose -105 stub PerfCollect -106 stub PerfOpen -201 stdcall GetDefaultPrinterA(ptr ptr) -202 stdcall SetDefaultPrinterA(str) -203 stdcall GetDefaultPrinterW(ptr ptr) -204 stdcall SetDefaultPrinterW(wstr) -205 stub -noname SplReadPrinter -206 stub -noname AddPerMachineConnectionA -207 stub -noname AddPerMachineConnectionW -208 stub -noname DeletePerMachineConnectionA -209 stub -noname DeletePerMachineConnectionW -210 stub -noname EnumPerMachineConnectionsA -211 stub -noname EnumPerMachineConnectionsW -212 stub -noname LoadPrinterDriver -213 stub -noname RefCntLoadDriver -214 stub -noname RefCntUnloadDriver -215 stub -noname ForceUnloadDriver -216 stub -noname PublishPrinterA -217 stub -noname PublishPrinterW -218 stub -noname CallCommonPropertySheetUI -219 stub -noname PrintUIQueueCreate -220 stub -noname PrintUIPrinterPropPages -221 stub -noname PrintUIDocumentDefaults -222 stub -noname SendRecvBidiData -223 stub -noname RouterFreeBidiResponseContainer -224 stub -noname ExternalConnectToLd64In32Server -226 stub -noname PrintUIWebPnpEntry -227 stub -noname PrintUIWebPnpPostEntry -228 stub -noname PrintUICreateInstance -229 stub -noname PrintUIDocumentPropertiesWrap -230 stub -noname PrintUIPrinterSetup -231 stub -noname PrintUIServerPropPages -232 stub -noname AddDriverCatalog - -@ stub ADVANCEDSETUPDIALOG -@ stdcall AbortPrinter(long) -@ stdcall AddFormA(long long ptr) -@ stdcall AddFormW(long long ptr) -@ stdcall AddJobA(long long ptr long ptr) -@ stdcall AddJobW(long long ptr long ptr) -@ stdcall AddMonitorA(str long ptr) -@ stdcall AddMonitorW(wstr long ptr) -@ stdcall AddPortA(str ptr str) -@ stdcall AddPortExA(str long ptr str) -@ stdcall AddPortExW(wstr long ptr wstr) -@ stdcall AddPortW(wstr long wstr) -@ stdcall AddPrinterA(str long ptr) -@ stdcall AddPrinterConnectionA(str) -@ stdcall AddPrinterConnectionW(wstr) -@ stdcall AddPrinterDriverA(str long ptr) -@ stdcall AddPrinterDriverExA(str long ptr long) -@ stdcall AddPrinterDriverExW(wstr long ptr long) -@ stdcall AddPrinterDriverW(wstr long ptr) -@ stdcall AddPrinterW(wstr long ptr) -@ stdcall AddPrintProcessorA(str str str str) -@ stdcall AddPrintProcessorW(wstr wstr wstr wstr) -@ stdcall AddPrintProvidorA(str long ptr) -@ stdcall AddPrintProvidorW(wstr long ptr) -@ stdcall AdvancedDocumentPropertiesA(long long str ptr ptr) -@ stdcall AdvancedDocumentPropertiesW(long long wstr ptr ptr) -@ stub AdvancedSetupDialog -@ stdcall ClosePrinter(long) -@ stub CloseSpoolFileHandle -@ stdcall ConfigurePortA(str long str) -@ stdcall ConfigurePortW(wstr long wstr) -@ stdcall ConnectToPrinterDlg(long long) -@ stub ConvertAnsiDevModeToUnicodeDevMode -@ stub ConvertUnicodeDevModeToAnsiDevMode -@ stub CommitSpoolData -@ stub CreatePrinterIC -@ stub DEVICECAPABILITIES -@ stub DEVICEMODE -@ stdcall DeleteFormA(long str) -@ stdcall DeleteFormW(long wstr) -@ stdcall DeleteMonitorA(str str str) -@ stdcall DeleteMonitorW(wstr wstr wstr) -@ stdcall DeletePortA(str long str) -@ stdcall DeletePortW(wstr long wstr) -@ stdcall DeletePrinter(long) -@ stdcall DeletePrinterConnectionA(str) -@ stdcall DeletePrinterConnectionW(wstr) -@ stdcall DeletePrinterDataExA(long str str) -@ stdcall DeletePrinterDataExW(long wstr wstr) -@ stdcall DeletePrinterDataA(ptr str) -@ stdcall DeletePrinterDataW(ptr wstr) -@ stdcall DeletePrinterDriverA(str str str) -@ stdcall DeletePrinterDriverExA(str str str long long) -@ stdcall DeletePrinterDriverExW(wstr wstr wstr long long) -@ stdcall DeletePrinterDriverW(wstr wstr wstr) -@ stub DeletePrinterIC -@ stub DevQueryPrint -@ stdcall DeletePrintProcessorA(str str str) -@ stdcall DeletePrintProcessorW(wstr wstr wstr) -@ stdcall DeletePrintProvidorA(str str str) -@ stdcall DeletePrintProvidorW(wstr wstr wstr) -@ stdcall DeviceCapabilitiesA(str str long ptr ptr) -@ stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr) -@ stub DeviceMode -@ stub DocumentEvent -@ stdcall DllMain(ptr long ptr) -@ stdcall DocumentPropertiesA(long long ptr ptr ptr long) -@ stdcall DocumentPropertiesW(long long ptr ptr ptr long) -@ stub EXTDEVICEMODE -@ stdcall EndDocPrinter(long) -@ stdcall EndPagePrinter(long) -@ stdcall EnumFormsA(long long ptr long ptr ptr) -@ stdcall EnumFormsW(long long ptr long ptr ptr) -@ stdcall EnumJobsA(long long long long ptr long ptr ptr) -@ stdcall EnumJobsW(long long long long ptr long ptr ptr) -@ stdcall EnumMonitorsA(str long ptr long long long) -@ stdcall EnumMonitorsW(wstr long ptr long long long) -@ stdcall EnumPortsA(str long ptr ptr ptr ptr) -@ stdcall EnumPortsW(wstr long ptr ptr ptr ptr) -@ stdcall EnumPrinterDataA(long long ptr long ptr ptr ptr long ptr) -@ stdcall EnumPrinterDataExA(long str ptr long ptr ptr) -@ stdcall EnumPrinterDataExW(long wstr ptr long ptr ptr) -@ stdcall EnumPrinterDataW(long long ptr long ptr ptr ptr long ptr) -@ stdcall EnumPrinterDriversA(str str long ptr long ptr ptr) -@ stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr) -@ stdcall EnumPrintersA(long ptr long ptr long ptr ptr) -@ stdcall EnumPrintersW(long ptr long ptr long ptr ptr) -@ stdcall EnumPrinterKeyA(long str str long ptr) -@ stdcall EnumPrinterKeyW(long wstr wstr long ptr) -@ stdcall ExtDeviceMode(long long ptr str str ptr str long) -@ stdcall EnumPrintProcessorDatatypesA(str str long ptr long ptr ptr) -@ stdcall EnumPrintProcessorDatatypesW(wstr wstr long ptr long ptr ptr) -@ stdcall EnumPrintProcessorsA(str str long ptr long ptr ptr) -@ stdcall EnumPrintProcessorsW(wstr wstr long ptr long ptr ptr) -@ stdcall FindClosePrinterChangeNotification(long) -@ stdcall FindFirstPrinterChangeNotification(long long long ptr) -@ stdcall FindNextPrinterChangeNotification(long ptr ptr ptr) -@ stdcall FreePrinterNotifyInfo(ptr) -@ stdcall GetFormA(long str long ptr long ptr) -@ stdcall GetFormW(long wstr long ptr long ptr) -@ stdcall GetJobA(long long long ptr long ptr) -@ stdcall GetJobW(long long long ptr long ptr) -@ stdcall GetPrinterA(long long ptr long ptr) -@ stdcall GetPrinterDataA(long str ptr ptr long ptr) -@ stdcall GetPrinterDataExA(long str str ptr ptr long ptr) -@ stdcall GetPrinterDataExW(long wstr wstr ptr ptr long ptr) -@ stdcall GetPrinterDataW(long wstr ptr ptr long ptr) -@ stdcall GetPrinterDriverA(long str long ptr long ptr) -@ stdcall GetPrinterDriverDirectoryA(str str long ptr long ptr) -@ stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr) -@ stdcall GetPrinterDriverW(long str long ptr long ptr) -@ stdcall GetPrinterW(long long ptr long ptr) -@ stdcall GetPrintProcessorDirectoryA(str str long ptr long ptr) -@ stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr) -@ stub GetSpoolFileHandle -@ stub IsValidDevmodeA -@ stdcall -stub IsValidDevmodeW(ptr long) -@ stdcall OpenPrinterA(str ptr ptr) -@ stdcall OpenPrinterW(wstr ptr ptr) -@ stub PlayGdiScriptOnPrinterIC -@ stdcall PrinterMessageBoxA(ptr long ptr str str long) -@ stdcall PrinterMessageBoxW(ptr long ptr wstr wstr long) -@ stdcall PrinterProperties(long long) -@ stub QueryColorProfile -@ stub QuerySpoolMode -@ stub QueryRemoteFonts -@ stdcall ReadPrinter(long ptr long ptr) -@ stdcall ResetPrinterA(long ptr) -@ stdcall ResetPrinterW(long ptr) -@ stdcall ScheduleJob(long long) -@ stub SeekPrinter -@ stub SetAllocFailCount -@ stdcall SetFormA(long str long ptr) -@ stdcall SetFormW(long wstr long ptr) -@ stdcall SetJobA(long long long ptr long) -@ stdcall SetJobW(long long long ptr long) -@ stdcall SetPrinterA(long long ptr long) -@ stdcall SetPrinterDataA(long str long ptr long) -@ stdcall SetPrinterDataExA(long str str long ptr long) -@ stdcall SetPrinterDataExW(long wstr wstr long ptr long) -@ stdcall SetPrinterDataW(long wstr long ptr long) -@ stdcall SetPrinterW(long long ptr long) -@ stub SplDriverUnloadComplete -@ stub SpoolerDevQueryPrintW -@ stdcall SpoolerInit() -@ stub SpoolerPrinterEvent -@ stub StartDocDlgA -@ stub StartDocDlgW -@ stdcall StartDocPrinterA(long long ptr) -@ stdcall StartDocPrinterW(long long ptr) -@ stdcall StartPagePrinter(long) -@ stdcall WaitForPrinterChange(ptr long) -@ stdcall WritePrinter(long ptr long ptr) -@ stdcall XcvDataW(long wstr ptr long ptr long ptr ptr) Index: sdk/include/psdk/winspool.h =================================================================== --- sdk/include/psdk/winspool.h (revision 73027) +++ sdk/include/psdk/winspool.h (working copy) @@ -1,1981 +1,1675 @@ -#ifndef _WINSPOOL_ -#define _WINSPOOL_ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4820) -#endif - -#define DI_CHANNEL 1 -#define DI_CHANNEL_WRITE 2 -#define DI_READ_SPOOL_JOB 3 - -#define FORM_BUILTIN 1 - -#define JOB_CONTROL_PAUSE 1 -#define JOB_CONTROL_RESUME 2 -#define JOB_CONTROL_CANCEL 3 -#define JOB_CONTROL_RESTART 4 -#define JOB_CONTROL_DELETE 5 - -#define JOB_STATUS_PAUSED 1 -#define JOB_STATUS_ERROR 2 -#define JOB_STATUS_DELETING 4 -#define JOB_STATUS_SPOOLING 8 -#define JOB_STATUS_PRINTING 16 -#define JOB_STATUS_OFFLINE 32 -#define JOB_STATUS_PAPEROUT 0x40 -#define JOB_STATUS_PRINTED 0x80 -#define JOB_STATUS_DELETED 0x100 -#define JOB_STATUS_BLOCKED_DEVQ 0x200 -#define JOB_STATUS_USER_INTERVENTION 0x400 - -#define JOB_POSITION_UNSPECIFIED 0 - -#define JOB_NOTIFY_TYPE 1 - -#define JOB_NOTIFY_FIELD_PRINTER_NAME 0 -#define JOB_NOTIFY_FIELD_MACHINE_NAME 1 -#define JOB_NOTIFY_FIELD_PORT_NAME 2 -#define JOB_NOTIFY_FIELD_USER_NAME 3 -#define JOB_NOTIFY_FIELD_NOTIFY_NAME 4 -#define JOB_NOTIFY_FIELD_DATATYPE 5 -#define JOB_NOTIFY_FIELD_PRINT_PROCESSOR 6 -#define JOB_NOTIFY_FIELD_PARAMETERS 7 -#define JOB_NOTIFY_FIELD_DRIVER_NAME 8 -#define JOB_NOTIFY_FIELD_DEVMODE 9 -#define JOB_NOTIFY_FIELD_STATUS 10 -#define JOB_NOTIFY_FIELD_STATUS_STRING 11 -#define JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR 12 -#define JOB_NOTIFY_FIELD_DOCUMENT 13 -#define JOB_NOTIFY_FIELD_PRIORITY 14 -#define JOB_NOTIFY_FIELD_POSITION 15 -#define JOB_NOTIFY_FIELD_SUBMITTED 16 -#define JOB_NOTIFY_FIELD_START_TIME 17 -#define JOB_NOTIFY_FIELD_UNTIL_TIME 18 -#define JOB_NOTIFY_FIELD_TIME 19 -#define JOB_NOTIFY_FIELD_TOTAL_PAGES 20 -#define JOB_NOTIFY_FIELD_PAGES_PRINTED 21 -#define JOB_NOTIFY_FIELD_TOTAL_BYTES 22 -#define JOB_NOTIFY_FIELD_BYTES_PRINTED 23 - -#define JOB_ACCESS_ADMINISTER 16 -#define JOB_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|JOB_ACCESS_ADMINISTER) -#define JOB_READ (STANDARD_RIGHTS_READ|JOB_ACCESS_ADMINISTER) -#define JOB_WRITE (STANDARD_RIGHTS_WRITE|JOB_ACCESS_ADMINISTER) -#define JOB_EXECUTE (STANDARD_RIGHTS_EXECUTE|JOB_ACCESS_ADMINISTER) - -#define PRINTER_NOTIFY_OPTIONS_REFRESH 1 -#define PRINTER_ACCESS_ADMINISTER 4 -#define PRINTER_ACCESS_USE 8 - -#define PRINTER_ERROR_INFORMATION 0x80000000 -#define PRINTER_ERROR_WARNING 0x40000000 -#define PRINTER_ERROR_SEVERE 0x20000000 -#define PRINTER_ERROR_OUTOFPAPER 1 -#define PRINTER_ERROR_JAM 2 -#define PRINTER_ERROR_OUTOFTONER 4 - -#define PRINTER_CONTROL_PAUSE 1 -#define PRINTER_CONTROL_RESUME 2 -#define PRINTER_CONTROL_PURGE 3 -#define PRINTER_CONTROL_SET_STATUS 4 - -#define PRINTER_STATUS_PAUSED 1 -#define PRINTER_STATUS_ERROR 2 -#define PRINTER_STATUS_PENDING_DELETION 4 -#define PRINTER_STATUS_PAPER_JAM 8 -#define PRINTER_STATUS_PAPER_OUT 0x10 -#define PRINTER_STATUS_MANUAL_FEED 0x20 -#define PRINTER_STATUS_PAPER_PROBLEM 0x40 -#define PRINTER_STATUS_OFFLINE 0x80 -#define PRINTER_STATUS_IO_ACTIVE 0x100 -#define PRINTER_STATUS_BUSY 0x200 -#define PRINTER_STATUS_PRINTING 0x400 -#define PRINTER_STATUS_OUTPUT_BIN_FULL 0x800 -#define PRINTER_STATUS_NOT_AVAILABLE 0x1000 -#define PRINTER_STATUS_WAITING 0x2000 -#define PRINTER_STATUS_PROCESSING 0x4000 -#define PRINTER_STATUS_INITIALIZING 0x8000 -#define PRINTER_STATUS_WARMING_UP 0x10000 -#define PRINTER_STATUS_TONER_LOW 0x20000 -#define PRINTER_STATUS_NO_TONER 0x40000 -#define PRINTER_STATUS_PAGE_PUNT 0x80000 -#define PRINTER_STATUS_USER_INTERVENTION 0x100000 -#define PRINTER_STATUS_OUT_OF_MEMORY 0x200000 -#define PRINTER_STATUS_DOOR_OPEN 0x400000 -#define PRINTER_STATUS_SERVER_UNKNOWN 0x800000 -#define PRINTER_STATUS_POWER_SAVE 0x1000000 - -#define PRINTER_ATTRIBUTE_QUEUED 1 -#define PRINTER_ATTRIBUTE_DIRECT 2 -#define PRINTER_ATTRIBUTE_DEFAULT 4 -#define PRINTER_ATTRIBUTE_SHARED 8 -#define PRINTER_ATTRIBUTE_NETWORK 0x10 -#define PRINTER_ATTRIBUTE_HIDDEN 0x20 -#define PRINTER_ATTRIBUTE_LOCAL 0x40 -#define PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x80 -#define PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x100 -#define PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x200 -#define PRINTER_ATTRIBUTE_WORK_OFFLINE 0x400 -#define PRINTER_ATTRIBUTE_ENABLE_BIDI 0x800 -#define PRINTER_ATTRIBUTE_RAW_ONLY 0x1000 -#define PRINTER_ATTRIBUTE_PUBLISHED 0x2000 - -#define PRINTER_ENUM_DEFAULT 1 -#define PRINTER_ENUM_LOCAL 2 -#define PRINTER_ENUM_CONNECTIONS 4 -#define PRINTER_ENUM_FAVORITE 4 -#define PRINTER_ENUM_NAME 8 -#define PRINTER_ENUM_REMOTE 16 -#define PRINTER_ENUM_SHARED 32 -#define PRINTER_ENUM_NETWORK 0x40 -#define PRINTER_ENUM_EXPAND 0x4000 -#define PRINTER_ENUM_CONTAINER 0x8000 -#define PRINTER_ENUM_ICONMASK 0xff0000 -#define PRINTER_ENUM_ICON1 0x10000 -#define PRINTER_ENUM_ICON2 0x20000 -#define PRINTER_ENUM_ICON3 0x40000 -#define PRINTER_ENUM_ICON4 0x80000 -#define PRINTER_ENUM_ICON5 0x100000 -#define PRINTER_ENUM_ICON6 0x200000 -#define PRINTER_ENUM_ICON7 0x400000 -#define PRINTER_ENUM_ICON8 0x800000 - -#define PRINTER_NOTIFY_TYPE 0 -#define PRINTER_NOTIFY_FIELD_SERVER_NAME 0 -#define PRINTER_NOTIFY_FIELD_PRINTER_NAME 1 -#define PRINTER_NOTIFY_FIELD_SHARE_NAME 2 -#define PRINTER_NOTIFY_FIELD_PORT_NAME 3 -#define PRINTER_NOTIFY_FIELD_DRIVER_NAME 4 -#define PRINTER_NOTIFY_FIELD_COMMENT 5 -#define PRINTER_NOTIFY_FIELD_LOCATION 6 -#define PRINTER_NOTIFY_FIELD_DEVMODE 7 -#define PRINTER_NOTIFY_FIELD_SEPFILE 8 -#define PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR 9 -#define PRINTER_NOTIFY_FIELD_PARAMETERS 10 -#define PRINTER_NOTIFY_FIELD_DATATYPE 11 -#define PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR 12 -#define PRINTER_NOTIFY_FIELD_ATTRIBUTES 13 -#define PRINTER_NOTIFY_FIELD_PRIORITY 14 -#define PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY 15 -#define PRINTER_NOTIFY_FIELD_START_TIME 16 -#define PRINTER_NOTIFY_FIELD_UNTIL_TIME 17 -#define PRINTER_NOTIFY_FIELD_STATUS 18 -#define PRINTER_NOTIFY_FIELD_STATUS_STRING 19 -#define PRINTER_NOTIFY_FIELD_CJOBS 20 -#define PRINTER_NOTIFY_FIELD_AVERAGE_PPM 21 -#define PRINTER_NOTIFY_FIELD_TOTAL_PAGES 22 -#define PRINTER_NOTIFY_FIELD_PAGES_PRINTED 23 -#define PRINTER_NOTIFY_FIELD_TOTAL_BYTES 24 -#define PRINTER_NOTIFY_FIELD_BYTES_PRINTED 25 - -#define PRINTER_CHANGE_ADD_PRINTER 1 -#define PRINTER_CHANGE_SET_PRINTER 2 -#define PRINTER_CHANGE_DELETE_PRINTER 4 -#define PRINTER_CHANGE_FAILED_CONNECTION_PRINTER 8 -#define PRINTER_CHANGE_PRINTER 0xFF -#define PRINTER_CHANGE_ADD_JOB 0x100 -#define PRINTER_CHANGE_SET_JOB 0x200 -#define PRINTER_CHANGE_DELETE_JOB 0x400 -#define PRINTER_CHANGE_WRITE_JOB 0x800 -#define PRINTER_CHANGE_JOB 0xFF00 -#define PRINTER_CHANGE_ADD_FORM 0x10000 -#define PRINTER_CHANGE_SET_FORM 0x20000 -#define PRINTER_CHANGE_DELETE_FORM 0x40000 -#define PRINTER_CHANGE_FORM 0x70000 -#define PRINTER_CHANGE_ADD_PORT 0x100000 -#define PRINTER_CHANGE_CONFIGURE_PORT 0x200000 -#define PRINTER_CHANGE_DELETE_PORT 0x400000 -#define PRINTER_CHANGE_PORT 0x700000 -#define PRINTER_CHANGE_ADD_PRINT_PROCESSOR 0x1000000 -#define PRINTER_CHANGE_DELETE_PRINT_PROCESSOR 0x4000000 -#define PRINTER_CHANGE_PRINT_PROCESSOR 0x7000000 -#define PRINTER_CHANGE_ADD_PRINTER_DRIVER 0x10000000 -#define PRINTER_CHANGE_SET_PRINTER_DRIVER 0x20000000 -#define PRINTER_CHANGE_DELETE_PRINTER_DRIVER 0x40000000 -#define PRINTER_CHANGE_PRINTER_DRIVER 0x70000000 -#define PRINTER_CHANGE_TIMEOUT 0x80000000 -#define PRINTER_CHANGE_ALL 0x7777FFFF - -#define PRINTER_NOTIFY_INFO_DISCARDED 1 -#define PRINTER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE) -#define PRINTER_READ (STANDARD_RIGHTS_READ|PRINTER_ACCESS_USE) -#define PRINTER_WRITE (STANDARD_RIGHTS_WRITE|PRINTER_ACCESS_USE) -#define PRINTER_EXECUTE (STANDARD_RIGHTS_EXECUTE|PRINTER_ACCESS_USE) - -#define NO_PRIORITY 0 -#define MAX_PRIORITY 99 -#define MIN_PRIORITY 1 -#define DEF_PRIORITY 1 - -#define PORT_TYPE_WRITE 1 -#define PORT_TYPE_READ 2 -#define PORT_TYPE_REDIRECTED 4 -#define PORT_TYPE_NET_ATTACHED 8 - -#define SERVER_ACCESS_ADMINISTER 1 -#define SERVER_ACCESS_ENUMERATE 2 -#define SERVER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE) -#define SERVER_READ (STANDARD_RIGHTS_READ|SERVER_ACCESS_ENUMERATE) -#define SERVER_WRITE (STANDARD_RIGHTS_WRITE|SERVER_ACCESS_ADMINISTER|SERVER_ACCESS_ENUMERATE) -#define SERVER_EXECUTE (STANDARD_RIGHTS_EXECUTE|SERVER_ACCESS_ENUMERATE) - -#define PORT_STATUS_TYPE_ERROR 1 -#define PORT_STATUS_TYPE_WARNING 2 -#define PORT_STATUS_TYPE_INFO 3 -#define PORT_STATUS_OFFLINE 1 -#define PORT_STATUS_PAPER_JAM 2 -#define PORT_STATUS_PAPER_OUT 3 -#define PORT_STATUS_OUTPUT_BIN_FULL 4 -#define PORT_STATUS_PAPER_PROBLEM 5 -#define PORT_STATUS_NO_TONER 6 -#define PORT_STATUS_DOOR_OPEN 7 -#define PORT_STATUS_USER_INTERVENTION 8 -#define PORT_STATUS_OUT_OF_MEMORY 9 -#define PORT_STATUS_TONER_LOW 10 -#define PORT_STATUS_WARMING_UP 11 -#define PORT_STATUS_POWER_SAVE 12 - -typedef struct _PRINTER_NOTIFY_OPTIONS_TYPE { - WORD Type; - WORD Reserved0; - DWORD Reserved1; - DWORD Reserved2; - DWORD Count; - PWORD pFields; -} PRINTER_NOTIFY_OPTIONS_TYPE, *PPRINTER_NOTIFY_OPTIONS_TYPE, *LPPRINTER_NOTIFY_OPTIONS_TYPE; - -typedef struct _PRINTER_NOTIFY_OPTIONS { - DWORD Version; - DWORD Flags; - DWORD Count; - PPRINTER_NOTIFY_OPTIONS_TYPE pTypes; -} PRINTER_NOTIFY_OPTIONS, *PPRINTER_NOTIFY_OPTIONS, *LPPRINTER_NOTIFY_OPTIONS; - -#ifndef RC_INVOKED - -typedef struct _ADDJOB_INFO_1A { - LPSTR Path; - DWORD JobId; -} ADDJOB_INFO_1A, *PADDJOB_INFO_1A, *LPADDJOB_INFO_1A; - -typedef struct _ADDJOB_INFO_1W { - LPWSTR Path; - DWORD JobId; -} ADDJOB_INFO_1W, *PADDJOB_INFO_1W, *LPADDJOB_INFO_1W; - -typedef struct _DATATYPES_INFO_1A { - LPSTR pName; -} DATATYPES_INFO_1A, *PDATATYPES_INFO_1A, *LPDATATYPES_INFO_1A; - -typedef struct _DATATYPES_INFO_1W { - LPWSTR pName; -} DATATYPES_INFO_1W, *PDATATYPES_INFO_1W, *LPDATATYPES_INFO_1W; - -typedef struct _JOB_INFO_1A { - DWORD JobId; - LPSTR pPrinterName; - LPSTR pMachineName; - LPSTR pUserName; - LPSTR pDocument; - LPSTR pDatatype; - LPSTR pStatus; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD TotalPages; - DWORD PagesPrinted; - SYSTEMTIME Submitted; -} JOB_INFO_1A, *PJOB_INFO_1A, *LPJOB_INFO_1A; - -typedef struct _JOB_INFO_1W { - DWORD JobId; - LPWSTR pPrinterName; - LPWSTR pMachineName; - LPWSTR pUserName; - LPWSTR pDocument; - LPWSTR pDatatype; - LPWSTR pStatus; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD TotalPages; - DWORD PagesPrinted; - SYSTEMTIME Submitted; -} JOB_INFO_1W, *PJOB_INFO_1W, *LPJOB_INFO_1W; - -typedef struct _JOB_INFO_2A { - DWORD JobId; - LPSTR pPrinterName; - LPSTR pMachineName; - LPSTR pUserName; - LPSTR pDocument; - LPSTR pNotifyName; - LPSTR pDatatype; - LPSTR pPrintProcessor; - LPSTR pParameters; - LPSTR pDriverName; - LPDEVMODEA pDevMode; - LPSTR pStatus; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD StartTime; - DWORD UntilTime; - DWORD TotalPages; - DWORD Size; - SYSTEMTIME Submitted; - DWORD Time; - DWORD PagesPrinted; -} JOB_INFO_2A, *PJOB_INFO_2A, *LPJOB_INFO_2A; - -typedef struct _JOB_INFO_2W { - DWORD JobId; - LPWSTR pPrinterName; - LPWSTR pMachineName; - LPWSTR pUserName; - LPWSTR pDocument; - LPWSTR pNotifyName; - LPWSTR pDatatype; - LPWSTR pPrintProcessor; - LPWSTR pParameters; - LPWSTR pDriverName; - LPDEVMODEW pDevMode; - LPWSTR pStatus; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD StartTime; - DWORD UntilTime; - DWORD TotalPages; - DWORD Size; - SYSTEMTIME Submitted; - DWORD Time; - DWORD PagesPrinted; -} JOB_INFO_2W, *PJOB_INFO_2W, *LPJOB_INFO_2W; - -typedef struct _JOB_INFO_3 { - DWORD JobId; - DWORD NextJobId; - DWORD Reserved; -} JOB_INFO_3, *PJOB_INFO_3, *LPJOB_INFO_3; - -typedef struct _JOB_INFO_4A { - DWORD JobId; - LPSTR pPrinterName; - LPSTR pMachineName; - LPSTR pUserName; - LPSTR pDocument; - LPSTR pNotifyName; - LPSTR pDatatype; - LPSTR pPrintProcessor; - LPSTR pParameters; - LPSTR pDriverName; - LPDEVMODEA pDevMode; - LPSTR pStatus; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD StartTime; - DWORD UntilTime; - DWORD TotalPages; - DWORD Size; - SYSTEMTIME Submitted; - DWORD Time; - DWORD PagesPrinted; - LONG SizeHigh; -} JOB_INFO_4A, *PJOB_INFO_4A, *LPJOB_INFO_4A; - -typedef struct _JOB_INFO_4W { - DWORD JobId; - LPWSTR pPrinterName; - LPWSTR pMachineName; - LPWSTR pUserName; - LPWSTR pDocument; - LPWSTR pNotifyName; - LPWSTR pDatatype; - LPWSTR pPrintProcessor; - LPWSTR pParameters; - LPWSTR pDriverName; - LPDEVMODEW pDevMode; - LPWSTR pStatus; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Status; - DWORD Priority; - DWORD Position; - DWORD StartTime; - DWORD UntilTime; - DWORD TotalPages; - DWORD Size; - SYSTEMTIME Submitted; - DWORD Time; - DWORD PagesPrinted; - LONG SizeHigh; -} JOB_INFO_4W, *PJOB_INFO_4W, *LPJOB_INFO_4W; - -typedef struct _DOC_INFO_1A { - LPSTR pDocName; - LPSTR pOutputFile; - LPSTR pDatatype; -} DOC_INFO_1A, *PDOC_INFO_1A, *LPDOC_INFO_1A; - -typedef struct _DOC_INFO_1W { - LPWSTR pDocName; - LPWSTR pOutputFile; - LPWSTR pDatatype; -} DOC_INFO_1W, *PDOC_INFO_1W, *LPDOC_INFO_1W; - -typedef struct _DOC_INFO_2A { - LPSTR pDocName; - LPSTR pOutputFile; - LPSTR pDatatype; - DWORD dwMode; - DWORD JobId; -} DOC_INFO_2A, *PDOC_INFO_2A, *LPDOC_INFO_2A; - -typedef struct _DOC_INFO_2W { - LPWSTR pDocName; - LPWSTR pOutputFile; - LPWSTR pDatatype; - DWORD dwMode; - DWORD JobId; -} DOC_INFO_2W, *PDOC_INFO_2W, *LPDOC_INFO_2W; - -typedef struct _DRIVER_INFO_1A { - LPSTR pName; -} DRIVER_INFO_1A, *PDRIVER_INFO_1A, *LPDRIVER_INFO_1A; - -typedef struct _DRIVER_INFO_1W { - LPWSTR pName; -} DRIVER_INFO_1W, *PDRIVER_INFO_1W, *LPDRIVER_INFO_1W; - -typedef struct _DRIVER_INFO_2A { - DWORD cVersion; - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDriverPath; - LPSTR pDataFile; - LPSTR pConfigFile; -} DRIVER_INFO_2A, *PDRIVER_INFO_2A, *LPDRIVER_INFO_2A; - -typedef struct _DRIVER_INFO_2W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; -} DRIVER_INFO_2W, *PDRIVER_INFO_2W, *LPDRIVER_INFO_2W; - -typedef struct _DRIVER_INFO_3A { - DWORD cVersion; - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDriverPath; - LPSTR pDataFile; - LPSTR pConfigFile; - LPSTR pHelpFile; - LPSTR pDependentFiles; - LPSTR pMonitorName; - LPSTR pDefaultDataType; -} DRIVER_INFO_3A, *PDRIVER_INFO_3A, *LPDRIVER_INFO_3A; - -typedef struct _DRIVER_INFO_3W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; - LPWSTR pHelpFile; - LPWSTR pDependentFiles; - LPWSTR pMonitorName; - LPWSTR pDefaultDataType; -} DRIVER_INFO_3W, *PDRIVER_INFO_3W, *LPDRIVER_INFO_3W; - -typedef struct _DRIVER_INFO_4A { - DWORD cVersion; // SDK examples: - LPSTR pName; // QMS 810 - LPSTR pEnvironment; // Win32 x86 - LPSTR pDriverPath; // c:\drivers\pscript.dll - LPSTR pDataFile; // c:\drivers\QMS810.PPD - LPSTR pConfigFile; // c:\drivers\PSCRPTUI.DLL - LPSTR pHelpFile; // c:\drivers\PSCRPTUI.HLP - LPSTR pDependentFiles; // PSCRIPT.DLL\0QMS810.PPD\0PSCRIPTUI.DLL\0PSCRIPTUI.HLP\0PSTEST.TXT\0\0 - LPSTR pMonitorName; // "PJL monitor" - LPSTR pDefaultDataType; // "EMF" - LPSTR pszzPreviousNames; // "OldName1\0OldName2\0\0 -} DRIVER_INFO_4A, *PDRIVER_INFO_4A, *LPDRIVER_INFO_4A; - -typedef struct _DRIVER_INFO_4W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; - LPWSTR pHelpFile; - LPWSTR pDependentFiles; - LPWSTR pMonitorName; - LPWSTR pDefaultDataType; - LPWSTR pszzPreviousNames; -} DRIVER_INFO_4W, *PDRIVER_INFO_4W, *LPDRIVER_INFO_4W; - -typedef struct _DRIVER_INFO_5A { - DWORD cVersion; // SDK examples: - LPSTR pName; // QMS 810 - LPSTR pEnvironment; // Win32 x86 - LPSTR pDriverPath; // c:\drivers\pscript.dll - LPSTR pDataFile; // c:\drivers\QMS810.PPD - LPSTR pConfigFile; // c:\drivers\PSCRPTUI.DLL - DWORD dwDriverAttributes; // driver attributes (like UMPD/KMPD) - DWORD dwConfigVersion; // version number of the config file since reboot - DWORD dwDriverVersion; // version number of the driver file since reboot -} DRIVER_INFO_5A, *PDRIVER_INFO_5A, *LPDRIVER_INFO_5A; - -typedef struct _DRIVER_INFO_5W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; - DWORD dwDriverAttributes; - DWORD dwConfigVersion; - DWORD dwDriverVersion; -} DRIVER_INFO_5W, *PDRIVER_INFO_5W, *LPDRIVER_INFO_5W; - -typedef struct _DRIVER_INFO_6A { - DWORD cVersion; - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDriverPath; - LPSTR pDataFile; - LPSTR pConfigFile; - LPSTR pHelpFile; - LPSTR pDependentFiles; - LPSTR pMonitorName; - LPSTR pDefaultDataType; - LPSTR pszzPreviousNames; - FILETIME ftDriverDate; - DWORDLONG dwlDriverVersion; - LPSTR pszMfgName; - LPSTR pszOEMUrl; - LPSTR pszHardwareID; - LPSTR pszProvider; -} DRIVER_INFO_6A, *PDRIVER_INFO_6A, *LPDRIVER_INFO_6A; - -typedef struct _DRIVER_INFO_6W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; - LPWSTR pHelpFile; - LPWSTR pDependentFiles; - LPWSTR pMonitorName; - LPWSTR pDefaultDataType; - LPWSTR pszzPreviousNames; - FILETIME ftDriverDate; - DWORDLONG dwlDriverVersion; - LPWSTR pszMfgName; - LPWSTR pszOEMUrl; - LPWSTR pszHardwareID; - LPWSTR pszProvider; -} DRIVER_INFO_6W, *PDRIVER_INFO_6W, *LPDRIVER_INFO_6W; - -#define PRINTER_DRIVER_PACKAGE_AWARE 0x00000001 - -typedef struct _DRIVER_INFO_8A { - DWORD cVersion; - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDriverPath; - LPSTR pDataFile; - LPSTR pConfigFile; - LPSTR pHelpFile; - LPSTR pDependentFiles; - LPSTR pMonitorName; - LPSTR pDefaultDataType; - LPSTR pszzPreviousNames; - FILETIME ftDriverDate; - DWORDLONG dwlDriverVersion; - LPSTR pszMfgName; - LPSTR pszOEMUrl; - LPSTR pszHardwareID; - LPSTR pszProvider; - LPSTR pszPrintProcessor; - LPSTR pszVendorSetup; - LPSTR pszzColorProfiles; - LPSTR pszInfPath; - DWORD dwPrinterDriverAttributes; - LPSTR pszzCoreDriverDependencies; - FILETIME ftMinInboxDriverVerDate; - DWORDLONG dwlMinInboxDriverVerVersion; -} DRIVER_INFO_8A, *PDRIVER_INFO_8A, *LPDRIVER_INFO_8A; - -typedef struct _DRIVER_INFO_8W { - DWORD cVersion; - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDriverPath; - LPWSTR pDataFile; - LPWSTR pConfigFile; - LPWSTR pHelpFile; - LPWSTR pDependentFiles; - LPWSTR pMonitorName; - LPWSTR pDefaultDataType; - LPWSTR pszzPreviousNames; - FILETIME ftDriverDate; - DWORDLONG dwlDriverVersion; - LPWSTR pszMfgName; - LPWSTR pszOEMUrl; - LPWSTR pszHardwareID; - LPWSTR pszProvider; - LPWSTR pszPrintProcessor; - LPWSTR pszVendorSetup; - LPWSTR pszzColorProfiles; - LPWSTR pszInfPath; - DWORD dwPrinterDriverAttributes; - LPWSTR pszzCoreDriverDependencies; - FILETIME ftMinInboxDriverVerDate; - DWORDLONG dwlMinInboxDriverVerVersion; -} DRIVER_INFO_8W, *PDRIVER_INFO_8W, *LPDRIVER_INFO_8W; - -// FLAGS for dwDriverAttributes -#define DRIVER_KERNELMODE 0x00000001 -#define DRIVER_USERMODE 0x00000002 - -// FLAGS for DeletePrinterDriverEx. -#define DPD_DELETE_UNUSED_FILES 0x00000001 -#define DPD_DELETE_SPECIFIC_VERSION 0x00000002 -#define DPD_DELETE_ALL_FILES 0x00000004 - -// FLAGS for AddPrinterDriverEx. -#define APD_STRICT_UPGRADE 0x00000001 -#define APD_STRICT_DOWNGRADE 0x00000002 -#define APD_COPY_ALL_FILES 0x00000004 -#define APD_COPY_NEW_FILES 0x00000008 -#if(_WIN32_WINNT >= 0x0501) -#define APD_COPY_FROM_DIRECTORY 0x00000010 -#endif - -typedef struct _MONITOR_INFO_1A { - LPSTR pName; -} MONITOR_INFO_1A, *PMONITOR_INFO_1A, *LPMONITOR_INFO_1A; - -typedef struct _MONITOR_INFO_1W { - LPWSTR pName; -} MONITOR_INFO_1W, *PMONITOR_INFO_1W, *LPMONITOR_INFO_1W; - -typedef struct _PORT_INFO_1A { - LPSTR pName; -} PORT_INFO_1A, *PPORT_INFO_1A, *LPPORT_INFO_1A; - -typedef struct _PORT_INFO_1W { - LPWSTR pName; -} PORT_INFO_1W, *PPORT_INFO_1W, *LPPORT_INFO_1W; - -typedef struct _MONITOR_INFO_2A { - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDLLName; -} MONITOR_INFO_2A, *PMONITOR_INFO_2A, *LPMONITOR_INFO_2A; - -typedef struct _MONITOR_INFO_2W { - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDLLName; -} MONITOR_INFO_2W, *PMONITOR_INFO_2W, *LPMONITOR_INFO_2W; - -typedef struct _PORT_INFO_2A { - LPSTR pPortName; - LPSTR pMonitorName; - LPSTR pDescription; - DWORD fPortType; - DWORD Reserved; -} PORT_INFO_2A, *PPORT_INFO_2A, *LPPORT_INFO_2A; - -typedef struct _PORT_INFO_2W { - LPWSTR pPortName; - LPWSTR pMonitorName; - LPWSTR pDescription; - DWORD fPortType; - DWORD Reserved; -} PORT_INFO_2W, *PPORT_INFO_2W, *LPPORT_INFO_2W; - -typedef struct _PORT_INFO_3A { - DWORD dwStatus; - LPSTR pszStatus; - DWORD dwSeverity; -} PORT_INFO_3A, *PPORT_INFO_3A, *LPPORT_INFO_3A; - -typedef struct _PORT_INFO_3W { - DWORD dwStatus; - LPWSTR pszStatus; - DWORD dwSeverity; -} PORT_INFO_3W, *PPORT_INFO_3W, *LPPORT_INFO_3W; - -typedef struct _PRINTER_INFO_1A { - DWORD Flags; - LPSTR pDescription; - LPSTR pName; - LPSTR pComment; -} PRINTER_INFO_1A, *PPRINTER_INFO_1A, *LPPRINTER_INFO_1A; - -typedef struct _PRINTER_INFO_1W { - DWORD Flags; - LPWSTR pDescription; - LPWSTR pName; - LPWSTR pComment; -} PRINTER_INFO_1W, *PPRINTER_INFO_1W, *LPPRINTER_INFO_1W; - -typedef struct _PRINTER_INFO_2A { - LPSTR pServerName; - LPSTR pPrinterName; - LPSTR pShareName; - LPSTR pPortName; - LPSTR pDriverName; - LPSTR pComment; - LPSTR pLocation; - LPDEVMODEA pDevMode; - LPSTR pSepFile; - LPSTR pPrintProcessor; - LPSTR pDatatype; - LPSTR pParameters; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Attributes; - DWORD Priority; - DWORD DefaultPriority; - DWORD StartTime; - DWORD UntilTime; - DWORD Status; - DWORD cJobs; - DWORD AveragePPM; -} PRINTER_INFO_2A, *PPRINTER_INFO_2A, *LPPRINTER_INFO_2A; - -typedef struct _PRINTER_INFO_2W { - LPWSTR pServerName; - LPWSTR pPrinterName; - LPWSTR pShareName; - LPWSTR pPortName; - LPWSTR pDriverName; - LPWSTR pComment; - LPWSTR pLocation; - LPDEVMODEW pDevMode; - LPWSTR pSepFile; - LPWSTR pPrintProcessor; - LPWSTR pDatatype; - LPWSTR pParameters; - PSECURITY_DESCRIPTOR pSecurityDescriptor; - DWORD Attributes; - DWORD Priority; - DWORD DefaultPriority; - DWORD StartTime; - DWORD UntilTime; - DWORD Status; - DWORD cJobs; - DWORD AveragePPM; -} PRINTER_INFO_2W, *PPRINTER_INFO_2W, *LPPRINTER_INFO_2W; - -typedef struct _PRINTER_INFO_3 { - PSECURITY_DESCRIPTOR pSecurityDescriptor; -} PRINTER_INFO_3, *PPRINTER_INFO_3, *LPPRINTER_INFO_3; - -typedef struct _PRINTER_INFO_4A { - LPSTR pPrinterName; - LPSTR pServerName; - DWORD Attributes; -} PRINTER_INFO_4A, *PPRINTER_INFO_4A, *LPPRINTER_INFO_4A; - -typedef struct _PRINTER_INFO_4W { - LPWSTR pPrinterName; - LPWSTR pServerName; - DWORD Attributes; -} PRINTER_INFO_4W, *PPRINTER_INFO_4W, *LPPRINTER_INFO_4W; - -typedef struct _PRINTER_INFO_5A { - LPSTR pPrinterName; - LPSTR pPortName; - DWORD Attributes; - DWORD DeviceNotSelectedTimeout; - DWORD TransmissionRetryTimeout; -} PRINTER_INFO_5A, *PPRINTER_INFO_5A, *LPPRINTER_INFO_5A; - -typedef struct _PRINTER_INFO_5W { - LPWSTR pPrinterName; - LPWSTR pPortName; - DWORD Attributes; - DWORD DeviceNotSelectedTimeout; - DWORD TransmissionRetryTimeout; -} PRINTER_INFO_5W, *PPRINTER_INFO_5W, *LPPRINTER_INFO_5W; - -typedef struct _PRINTER_INFO_6 { - DWORD dwStatus; -} PRINTER_INFO_6, *PPRINTER_INFO_6, *LPPRINTER_INFO_6; - -typedef struct _PRINTER_INFO_7A { - LPSTR pszObjectGUID; - DWORD dwAction; -} PRINTER_INFO_7A, *PPRINTER_INFO_7A, *LPPRINTER_INFO_7A; - -typedef struct _PRINTER_INFO_7W { - LPWSTR pszObjectGUID; - DWORD dwAction; -} PRINTER_INFO_7W, *PPRINTER_INFO_7W, *LPPRINTER_INFO_7W; - -typedef struct _PRINTER_INFO_8A { - LPDEVMODEA pDevMode; -} PRINTER_INFO_8A, *PPRINTER_INFO_8A, *LPPRINTER_INFO_8A; - -typedef struct _PRINTER_INFO_8W { - LPDEVMODEW pDevMode; -} PRINTER_INFO_8W, *PPRINTER_INFO_8W, *LPPRINTER_INFO_8W; - -typedef struct _PRINTER_INFO_9A { - LPDEVMODEA pDevMode; -} PRINTER_INFO_9A, *PPRINTER_INFO_9A, *LPPRINTER_INFO_9A; - -typedef struct _PRINTER_INFO_9W { - LPDEVMODEW pDevMode; -} PRINTER_INFO_9W, *PPRINTER_INFO_9W, *LPPRINTER_INFO_9W; - -typedef struct _PRINTPROCESSOR_INFO_1A { - LPSTR pName; -} PRINTPROCESSOR_INFO_1A, *PPRINTPROCESSOR_INFO_1A, *LPPRINTPROCESSOR_INFO_1A; - -typedef struct _PRINTPROCESSOR_INFO_1W { - LPWSTR pName; -} PRINTPROCESSOR_INFO_1W, *PPRINTPROCESSOR_INFO_1W, *LPPRINTPROCESSOR_INFO_1W; - -typedef struct _PRINTER_NOTIFY_INFO_DATA { - WORD Type; - WORD Field; - DWORD Reserved; - DWORD Id; - union { - DWORD adwData[2]; - struct { - DWORD cbBuf; - PVOID pBuf; - } Data; - } NotifyData; -} PRINTER_NOTIFY_INFO_DATA, *PPRINTER_NOTIFY_INFO_DATA, *LPPRINTER_NOTIFY_INFO_DATA; - -typedef struct _PRINTER_NOTIFY_INFO { - DWORD Version; - DWORD Flags; - DWORD Count; - PRINTER_NOTIFY_INFO_DATA aData[1]; -} PRINTER_NOTIFY_INFO, *PPRINTER_NOTIFY_INFO, *LPPRINTER_NOTIFY_INFO; - -typedef struct _FORM_INFO_1A { - DWORD Flags; - LPSTR pName; - SIZEL Size; - RECTL ImageableArea; -} FORM_INFO_1A, *PFORM_INFO_1A, *LPFORM_INFO_1A; - -typedef struct _FORM_INFO_1W { - DWORD Flags; - LPWSTR pName; - SIZEL Size; - RECTL ImageableArea; -} FORM_INFO_1W, *PFORM_INFO_1W, *LPFORM_INFO_1W; - -#if (NTDDI_VERSION >= NTDDI_VISTA) - -typedef struct _FORM_INFO_2A { - DWORD Flags; - LPCSTR pName; - SIZEL Size; - RECTL ImageableArea; - LPCSTR pKeyword; - DWORD StringType; - LPCSTR pMuiDll; - DWORD dwResourceId; - LPCSTR pDisplayName; - LANGID wLangId; -} FORM_INFO_2A, *PFORM_INFO_2A, *LPFORM_INFO_2A; - -typedef struct _FORM_INFO_2W { - DWORD Flags; - LPCWSTR pName; - SIZEL Size; - RECTL ImageableArea; - LPCSTR pKeyword; - DWORD StringType; - LPCWSTR pMuiDll; - DWORD dwResourceId; - LPCWSTR pDisplayName; - LANGID wLangId; -} FORM_INFO_2W, *PFORM_INFO_2W, *LPFORM_INFO_2W; - -#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ - -typedef struct _PRINTER_DEFAULTSA { - LPSTR pDatatype; - LPDEVMODE pDevMode; - ACCESS_MASK DesiredAccess; -} PRINTER_DEFAULTSA, *PPRINTER_DEFAULTSA, *LPPRINTER_DEFAULTSA; - -typedef struct _PRINTER_DEFAULTSW { - LPWSTR pDatatype; - LPDEVMODE pDevMode; - ACCESS_MASK DesiredAccess; -} PRINTER_DEFAULTSW, *PPRINTER_DEFAULTSW, *LPPRINTER_DEFAULTSW; - -typedef struct _PROVIDOR_INFO_1A { - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDLLName; -} PROVIDOR_INFO_1A, *PPROVIDOR_INFO_1A, *LPPROVIDOR_INFO_1A; - -typedef struct _PROVIDOR_INFO_1W { - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDLLName; -} PROVIDOR_INFO_1W, *LPPROVIDOR_INFO_1W; - -typedef struct _PROVIDOR_INFO_2A { - LPSTR pOrder; -} PROVIDOR_INFO_2A, *PPROVIDOR_INFO_2A, *LPPROVIDOR_INFO_2A; - -typedef struct _PROVIDOR_INFO_2W { - LPWSTR pOrder; -} PROVIDOR_INFO_2W, *LPPROVIDOR_INFO_2W; - -typedef struct _BINARY_CONTAINER { - DWORD cbBuf; - LPBYTE pData; -} BINARY_CONTAINER, *PBINARY_CONTAINER; - -typedef struct _BIDI_DATA { - DWORD dwBidiType; - union { - BOOL bData; - INT iData; - LPWSTR sData; - FLOAT fData; - BINARY_CONTAINER biData; - } u; -} BIDI_DATA, *LPBIDI_DATA, *PBIDI_DATA; - -typedef struct _BIDI_REQUEST_DATA { - DWORD dwReqNumber; - LPWSTR pSchema; - BIDI_DATA data; -} BIDI_REQUEST_DATA, *LPBIDI_REQUEST_DATA, *PBIDI_REQUEST_DATA; - -typedef struct _BIDI_REQUEST_CONTAINER { - DWORD Version; - DWORD Flags; - DWORD Count; - BIDI_REQUEST_DATA aData[1]; -} BIDI_REQUEST_CONTAINER, *LPBIDI_REQUEST_CONTAINER, *PBIDI_REQUEST_CONTAINER; - -typedef struct _BIDI_RESPONSE_DATA { - DWORD dwResult; - DWORD dwReqNumber; - LPWSTR pSchema; - BIDI_DATA data; -} BIDI_RESPONSE_DATA, *LPBIDI_RESPONSE_DATA, *PBIDI_RESPONSE_DATA; - -typedef struct _BIDI_RESPONSE_CONTAINER { - DWORD Version; - DWORD Flags; - DWORD Count; - BIDI_RESPONSE_DATA aData[1]; -} BIDI_RESPONSE_CONTAINER, *LPBIDI_RESPONSE_CONTAINER, *PBIDI_RESPONSE_CONTAINER; - -#ifdef UNICODE - -typedef JOB_INFO_1W JOB_INFO_1, *PJOB_INFO_1, *LPJOB_INFO_1; -typedef JOB_INFO_2W JOB_INFO_2, *PJOB_INFO_2, *LPJOB_INFO_2; -typedef JOB_INFO_4W JOB_INFO_4, *PJOB_INFO_4, *LPJOB_INFO_4; -typedef ADDJOB_INFO_1W ADDJOB_INFO_1, *PADDJOB_INFO_1, *LPADDJOB_INFO_1; -typedef DATATYPES_INFO_1W DATATYPES_INFO_1, *PDATATYPES_INFO_1, *LPDATATYPES_INFO_1; -typedef MONITOR_INFO_1W MONITOR_INFO_1, *PMONITOR_INFO_1, *LPMONITOR_INFO_1; -typedef MONITOR_INFO_2W MONITOR_INFO_2, *PMONITOR_INFO_2, *LPMONITOR_INFO_2; -typedef DOC_INFO_1W DOC_INFO_1, *PDOC_INFO_1, *LPDOC_INFO_1; -typedef DOC_INFO_2W DOC_INFO_2, *PDOC_INFO_2, *LPDOC_INFO_2; -typedef PORT_INFO_1W PORT_INFO_1, *PPORT_INFO_1, *LPPORT_INFO_1; -typedef PORT_INFO_2W PORT_INFO_2, *PPORT_INFO_2, *LPPORT_INFO_2; -typedef PORT_INFO_3W PORT_INFO_3, *PPORT_INFO_3, *LPPORT_INFO_3; -typedef DRIVER_INFO_2W DRIVER_INFO_2, *PDRIVER_INFO_2, *LPDRIVER_INFO_2; -typedef DRIVER_INFO_4W DRIVER_INFO_4, *PDRIVER_INFO_4, *LPDRIVER_INFO_4; -typedef DRIVER_INFO_5W DRIVER_INFO_5, *PDRIVER_INFO_5, *LPDRIVER_INFO_5; -typedef DRIVER_INFO_6W DRIVER_INFO_6, *PDRIVER_INFO_6, *LPDRIVER_INFO_6; -typedef DRIVER_INFO_8W DRIVER_INFO_8, *PDRIVER_INFO_8, *LPDRIVER_INFO_8; -typedef PRINTER_INFO_1W PRINTER_INFO_1, *PPRINTER_INFO_1, *LPPRINTER_INFO_1; -typedef PRINTER_INFO_2W PRINTER_INFO_2, *PPRINTER_INFO_2, *LPPRINTER_INFO_2; -typedef PRINTER_INFO_4W PRINTER_INFO_4, *PPRINTER_INFO_4, *LPPRINTER_INFO_4; -typedef PRINTER_INFO_5W PRINTER_INFO_5, *PPRINTER_INFO_5, *LPPRINTER_INFO_5; -typedef PRINTER_INFO_7W PRINTER_INFO_7, *PPRINTER_INFO_7, *LPPRINTER_INFO_7; -typedef PRINTER_INFO_8W PRINTER_INFO_8, *PPRINTER_INFO_8, *LPPRINTER_INFO_8; -typedef PRINTER_INFO_9W PRINTER_INFO_9, *PPRINTER_INFO_9, *LPPRINTER_INFO_9; -typedef PRINTPROCESSOR_INFO_1W PRINTPROCESSOR_INFO_1, *PPRINTPROCESSOR_INFO_1, *LPPRINTPROCESSOR_INFO_1; -typedef FORM_INFO_1W FORM_INFO_1, *PFORM_INFO_1, *LPFORM_INFO_1; -#if (NTDDI_VERSION >= NTDDI_VISTA) -typedef FORM_INFO_2W FORM_INFO_2, *PFORM_INFO_2, *LPFORM_INFO_2; -#endif -typedef PRINTER_DEFAULTSW PRINTER_DEFAULTS, *PPRINTER_DEFAULTS, *LPPRINTER_DEFAULTS; -typedef PROVIDOR_INFO_1W PROVIDOR_INFO_1, *PPROVIDOR_INFO_1, *LPPROVIDOR_INFO_1; -typedef PROVIDOR_INFO_2W PROVIDOR_INFO_2, *PPROVIDOR_INFO_2, *LPPROVIDOR_INFO_2; - -#else /* UNICODE */ - -typedef JOB_INFO_1A JOB_INFO_1, *PJOB_INFO_1, *LPJOB_INFO_1; -typedef JOB_INFO_2A JOB_INFO_2, *PJOB_INFO_2, *LPJOB_INFO_2; -typedef JOB_INFO_4A JOB_INFO_4, *PJOB_INFO_4, *LPJOB_INFO_4; -typedef ADDJOB_INFO_1A ADDJOB_INFO_1, *PADDJOB_INFO_1, *LPADDJOB_INFO_1; -typedef DATATYPES_INFO_1A DATATYPES_INFO_1, *PDATATYPES_INFO_1, *LPDATATYPES_INFO_1; -typedef MONITOR_INFO_1A MONITOR_INFO_1, *PMONITOR_INFO_1, *LPMONITOR_INFO_1; -typedef MONITOR_INFO_2A MONITOR_INFO_2, *PMONITOR_INFO_2, *LPMONITOR_INFO_2; -typedef DOC_INFO_1A DOC_INFO_1, *PDOC_INFO_1, *LPDOC_INFO_1; -typedef DOC_INFO_2A DOC_INFO_2, *PDOC_INFO_2, *LPDOC_INFO_2; -typedef PORT_INFO_1A PORT_INFO_1, *PPORT_INFO_1, *LPPORT_INFO_1; -typedef PORT_INFO_2A PORT_INFO_2, *PPORT_INFO_2, *LPPORT_INFO_2; -typedef PORT_INFO_3A PORT_INFO_3, *PPORT_INFO_3, *LPPORT_INFO_3; -typedef DRIVER_INFO_2A DRIVER_INFO_2, *PDRIVER_INFO_2, *LPDRIVER_INFO_2; -typedef DRIVER_INFO_4A DRIVER_INFO_4, *PDRIVER_INFO_4, *LPDRIVER_INFO_4; -typedef DRIVER_INFO_5A DRIVER_INFO_5, *PDRIVER_INFO_5, *LPDRIVER_INFO_5; -typedef DRIVER_INFO_6A DRIVER_INFO_6, *PDRIVER_INFO_6, *LPDRIVER_INFO_6; -typedef DRIVER_INFO_8A DRIVER_INFO_8, *PDRIVER_INFO_8, *LPDRIVER_INFO_8; -typedef PRINTER_INFO_1A PRINTER_INFO_1, *PPRINTER_INFO_1, *LPPRINTER_INFO_1; -typedef PRINTER_INFO_2A PRINTER_INFO_2, *PPRINTER_INFO_2, *LPPRINTER_INFO_2; -typedef PRINTER_INFO_4A PRINTER_INFO_4, *PPRINTER_INFO_4, *LPPRINTER_INFO_4; -typedef PRINTER_INFO_5A PRINTER_INFO_5, *PPRINTER_INFO_5, *LPPRINTER_INFO_5; -typedef PRINTER_INFO_7A PRINTER_INFO_7, *PPRINTER_INFO_7, *LPPRINTER_INFO_7; -typedef PRINTER_INFO_8A PRINTER_INFO_8, *PPRINTER_INFO_8, *LPPRINTER_INFO_8; -typedef PRINTER_INFO_9A PRINTER_INFO_9, *PPRINTER_INFO_9, *LPPRINTER_INFO_9; -typedef PRINTPROCESSOR_INFO_1A PRINTPROCESSOR_INFO_1, *PPRINTPROCESSOR_INFO_1, *LPPRINTPROCESSOR_INFO_1; -typedef FORM_INFO_1A FORM_INFO_1, *PFORM_INFO_1, *LPFORM_INFO_1; -#if (NTDDI_VERSION >= NTDDI_VISTA) -typedef FORM_INFO_2A FORM_INFO_2, *PFORM_INFO_2, *LPFORM_INFO_2; -#endif -typedef PRINTER_DEFAULTSA PRINTER_DEFAULTS, *PPRINTER_DEFAULTS, *LPPRINTER_DEFAULTS; -typedef PROVIDOR_INFO_1A PROVIDOR_INFO_1, *PPROVIDOR_INFO_1, *LPPROVIDOR_INFO_1; -typedef PROVIDOR_INFO_2A PROVIDOR_INFO_2, *PPROVIDOR_INFO_2, *LPPROVIDOR_INFO_2; - -#endif /* UNICODE */ - -BOOL WINAPI AbortPrinter(_In_ HANDLE); - -BOOL -WINAPI -AddFormA( - _In_ HANDLE hPrinter, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(FORM_INFO_1A))) -#if (NTDDI_VERSION >= NTDDI_VISTA) - _When_(Level == 2, _In_reads_bytes_(sizeof(FORM_INFO_2A))) -#endif - LPBYTE pForm); - -BOOL -WINAPI -AddFormW( - _In_ HANDLE hPrinter, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(FORM_INFO_1W))) -#if (NTDDI_VERSION >= NTDDI_VISTA) - _When_(Level == 2, _In_reads_bytes_(sizeof(FORM_INFO_2W))) -#endif - LPBYTE pForm); - -BOOL -WINAPI -AddJobA( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pData, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -AddJobW( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pData, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -AddMonitorA( - _In_opt_ LPSTR pName, - _In_ DWORD Level, - _In_reads_bytes_opt_(sizeof(MONITOR_INFO_2)) LPBYTE pMonitors); - -BOOL -WINAPI -AddMonitorW( - _In_opt_ LPWSTR pName, - _In_ DWORD Level, - _In_reads_bytes_opt_(sizeof(MONITOR_INFO_2)) LPBYTE pMonitors); - -BOOL WINAPI AddPortA(_In_opt_ LPSTR, _In_ HWND, _In_ LPSTR); -BOOL WINAPI AddPortW(_In_opt_ LPWSTR, _In_ HWND, _In_ LPWSTR); - -HANDLE -WINAPI -AddPrinterA( - _In_opt_ LPSTR pName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(PRINTER_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PRINTER_INFO_2))) - LPBYTE pPrinter); - -HANDLE -WINAPI -AddPrinterW( - _In_opt_ LPWSTR pName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(PRINTER_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PRINTER_INFO_2))) - LPBYTE pPrinter); - -BOOL WINAPI AddPrinterConnectionA(_In_ LPSTR); -BOOL WINAPI AddPrinterConnectionW(_In_ LPWSTR); -BOOL WINAPI AddPrinterDriverA(_In_opt_ LPSTR, _In_ DWORD, _In_ PBYTE); -BOOL WINAPI AddPrinterDriverW(_In_opt_ LPWSTR, _In_ DWORD, _In_ PBYTE); - -BOOL -WINAPI -AddPrintProcessorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPathName, - _In_ LPSTR pPrintProcessorName); - -BOOL -WINAPI -AddPrintProcessorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPathName, - _In_ LPWSTR pPrintProcessorName); - -BOOL -WINAPI -AddPrintProvidorA( - _In_opt_ LPSTR pName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(PROVIDOR_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PROVIDOR_INFO_2))) - LPBYTE pProvidorInfo); - -BOOL -WINAPI -AddPrintProvidorW( - _In_opt_ LPWSTR pName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(PROVIDOR_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PROVIDOR_INFO_2))) - LPBYTE pProvidorInfo); - -LONG -WINAPI -AdvancedDocumentPropertiesA( - _In_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPSTR pDeviceName, - _Inout_opt_ PDEVMODEA pDevModeOutput, - _In_opt_ PDEVMODEA pDevModeInput); - -LONG -WINAPI -AdvancedDocumentPropertiesW( - _In_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPWSTR pDeviceName, - _Inout_opt_ PDEVMODEW pDevModeOutput, - _In_opt_ PDEVMODEW pDevModeInput); - -BOOL WINAPI ClosePrinter(_In_ HANDLE); -BOOL WINAPI ConfigurePortA(_In_opt_ LPSTR, _In_ HWND, _In_ LPSTR); -BOOL WINAPI ConfigurePortW(_In_opt_ LPWSTR, _In_ HWND, _In_ LPWSTR); -HANDLE WINAPI ConnectToPrinterDlg(_In_ HWND, _In_ DWORD); -BOOL WINAPI DeleteFormA(_In_ HANDLE, _In_ LPSTR); -BOOL WINAPI DeleteFormW(_In_ HANDLE, _In_ LPWSTR); -BOOL WINAPI DeleteMonitorA(_In_opt_ LPSTR, _In_opt_ LPSTR, _In_ LPSTR); -BOOL WINAPI DeleteMonitorW(_In_opt_ LPWSTR, _In_opt_ LPWSTR, _In_ LPWSTR); -BOOL WINAPI DeletePortA(_In_opt_ LPSTR, _In_ HWND, _In_ LPSTR); -BOOL WINAPI DeletePortW(_In_opt_ LPWSTR, _In_ HWND, _In_ LPWSTR); -BOOL WINAPI DeletePrinter(_Inout_ HANDLE); -BOOL WINAPI DeletePrinterConnectionA(_In_ LPSTR); -BOOL WINAPI DeletePrinterConnectionW(_In_ LPWSTR); -DWORD WINAPI DeletePrinterDataA(_In_ HANDLE, _In_ LPSTR); -DWORD WINAPI DeletePrinterDataW(_In_ HANDLE, _In_ LPWSTR); - -BOOL -WINAPI -DeletePrinterDriverA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pDriverName); - -BOOL -WINAPI -DeletePrinterDriverW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pDriverName); - -BOOL -WINAPI -DeletePrintProcessorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPrintProcessorName); - -BOOL -WINAPI -DeletePrintProcessorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPrintProcessorName); - -BOOL -WINAPI -DeletePrintProvidorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPrintProvidorName); - -BOOL -WINAPI -DeletePrintProvidorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPrintProvidorName); - -LONG -WINAPI -DocumentPropertiesA( - _In_opt_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPSTR pDeviceName, - _Out_opt_ PDEVMODEA pDevModeOutput, - _In_opt_ PDEVMODEA pDevModeInput, - _In_ DWORD fMode); - -LONG -WINAPI -DocumentPropertiesW( - _In_opt_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPWSTR pDeviceName, - _Out_opt_ PDEVMODEW pDevModeOutput, - _In_opt_ PDEVMODEW pDevModeInput, - _In_ DWORD fMode); - -BOOL WINAPI EndDocPrinter(_In_ HANDLE); -BOOL WINAPI EndPagePrinter(_In_ HANDLE); - -BOOL -WINAPI -EnumFormsA( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pForm, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumFormsW( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pForm, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumJobsA( - _In_ HANDLE hPrinter, - _In_ DWORD FirstJob, - _In_ DWORD NoJobs, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pJob, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumJobsW( - _In_ HANDLE hPrinter, - _In_ DWORD FirstJob, - _In_ DWORD NoJobs, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pJob, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumMonitorsA( - _In_opt_ LPSTR pName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pMonitor, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumMonitorsW( - _In_opt_ LPWSTR pName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pMonitor, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumPortsA( - _In_opt_ LPSTR pName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPort, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumPortsW( - _In_opt_ LPWSTR pName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPort, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -DWORD -WINAPI -EnumPrinterDataA( - _In_ HANDLE hPrinter, - _In_ DWORD dwIndex, - _Out_writes_bytes_(cbValueName) LPSTR pValueName, - _In_ DWORD cbValueName, - _Out_ LPDWORD pcbValueName, - _Out_opt_ LPDWORD pType, - _Out_writes_to_opt_(cbData, *pcbData) LPBYTE pData, - _In_ DWORD cbData, - _When_(pData != NULL, _Pre_notnull_) _Out_opt_ LPDWORD pcbData); - -DWORD -WINAPI -EnumPrinterDataW( - _In_ HANDLE hPrinter, - _In_ DWORD dwIndex, - _Out_writes_bytes_(cbValueName) LPWSTR pValueName, - _In_ DWORD cbValueName, - _Out_ LPDWORD pcbValueName, - _Out_opt_ LPDWORD pType, - _Out_writes_to_opt_(cbData, *pcbData) LPBYTE pData, - _In_ DWORD cbData, - _When_(pData != NULL, _Pre_notnull_) _Out_opt_ LPDWORD pcbData); - -BOOL -WINAPI -EnumPrinterDriversA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumPrinterDriversW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -_Success_(return != 0) -BOOL -WINAPI -EnumPrintersA( - _In_ DWORD Flags, - _In_opt_ LPSTR Name, - _In_ DWORD Level, - _Out_writes_bytes_to_opt_(cbBuf, *pcbNeeded) LPBYTE pPrinterEnum, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -_Success_(return != 0) -BOOL -WINAPI -EnumPrintersW( - _In_ DWORD Flags, - _In_opt_ LPWSTR Name, - _In_ DWORD Level, - _Out_writes_bytes_to_opt_(cbBuf, *pcbNeeded) LPBYTE pPrinterEnum, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -_Success_(return != 0) -BOOL -WINAPI -EnumPrintProcessorDatatypesA( - _In_opt_ LPSTR pName, - _In_ LPSTR pPrintProcessorName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDatatypes, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -_Success_(return != 0) -BOOL -WINAPI -EnumPrintProcessorDatatypesW( - _In_opt_ LPWSTR pName, - _In_ LPWSTR pPrintProcessorName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDatatypes, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumPrintProcessorsA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrintProcessorInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -BOOL -WINAPI -EnumPrintProcessorsW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrintProcessorInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded, - _Out_ LPDWORD pcReturned); - -LONG -WINAPI -ExtDeviceMode( - _In_opt_ HWND hWnd, - _In_opt_ HANDLE hInst, - _Inout_opt_ LPDEVMODEA pDevModeOutput, - _In_opt_ LPSTR pDeviceName, - _In_opt_ LPSTR pPort, - _In_opt_ LPDEVMODEA pDevModeInput, - _In_opt_ LPSTR pProfile, - _In_ DWORD fMode); - -BOOL WINAPI FindClosePrinterChangeNotification(_In_ HANDLE); - -HANDLE -WINAPI -FindFirstPrinterChangeNotification( - _In_ HANDLE hPrinter, - DWORD fdwFilter, - DWORD fdwOptions, - _In_opt_ PVOID pPrinterNotifyOptions); - -BOOL -WINAPI -FindNextPrinterChangeNotification( - _In_ HANDLE hChange, - _Out_opt_ PDWORD pdwChange, - _In_opt_ LPVOID pvReserved, - _Out_opt_ LPVOID *ppPrinterNotifyInfo); - -BOOL WINAPI FreePrinterNotifyInfo(_In_ PPRINTER_NOTIFY_INFO); - -#if _WIN32_WINNT >= 0x0500 - -BOOL -WINAPI -GetDefaultPrinterA( - _Out_writes_opt_(*pcchBuffer) LPSTR pszBuffer, - _Inout_ LPDWORD pcchBuffer); - -BOOL -WINAPI -GetDefaultPrinterW( - _Out_writes_opt_(*pcchBuffer) LPWSTR pszBuffer, - _Inout_ LPDWORD pcchBuffer); - -#endif - -BOOL -WINAPI -GetFormA( - _In_ HANDLE hPrinter, - _In_ LPSTR pFormName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pForm, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetFormW( - _In_ HANDLE hPrinter, - _In_ LPWSTR pFormName, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pForm, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetJobA( - _In_ HANDLE hPrinter, - _In_ DWORD JobId, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pJob, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetJobW( - _In_ HANDLE hPrinter, - _In_ DWORD JobId, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pJob, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterA( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrinter, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterW( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrinter, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -DWORD -WINAPI -GetPrinterDataA( - _In_ HANDLE hPrinter, - _In_ LPSTR pValueName, - _Out_opt_ LPDWORD pType, - _Out_writes_bytes_opt_(nSize) LPBYTE pData, - _In_ DWORD nSize, - _Out_ LPDWORD pcbNeeded); - -DWORD -WINAPI -GetPrinterDataW( - _In_ HANDLE hPrinter, - _In_ LPWSTR pValueName, - _Out_opt_ LPDWORD pType, - _Out_writes_bytes_opt_(nSize) LPBYTE pData, - _In_ DWORD nSize, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterDriverA( - _In_ HANDLE hPrinter, - _In_opt_ LPSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterDriverW( - _In_ HANDLE hPrinter, - _In_opt_ LPWSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterDriverDirectoryA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverDirectory, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrinterDriverDirectoryW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pDriverDirectory, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrintProcessorDirectoryA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrintProcessorInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -BOOL -WINAPI -GetPrintProcessorDirectoryW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrintProcessorInfo, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); - -#if NTDDI_VERSION >= NTDDI_WINXPSP2 -BOOL WINAPI IsValidDevmodeA(_In_opt_ PDEVMODEA, size_t); -BOOL WINAPI IsValidDevmodeW(_In_opt_ PDEVMODEW, size_t); -#endif - -BOOL -WINAPI -OpenPrinterA( - _In_opt_ LPSTR pPrinterName, - _Out_ LPHANDLE phPrinter, - _In_opt_ LPPRINTER_DEFAULTSA pDefault); - -BOOL -WINAPI -OpenPrinterW( - _In_opt_ LPWSTR pPrinterName, - _Out_ LPHANDLE phPrinter, - _In_opt_ LPPRINTER_DEFAULTSW pDefault); - -DWORD -WINAPI -PrinterMessageBoxA( - _In_ HANDLE hPrinter, - DWORD Error, - _In_ HWND hWnd, - _In_ LPSTR pText, - _In_ LPSTR pCaption, - DWORD dwType); - -DWORD -WINAPI -PrinterMessageBoxW( - _In_ HANDLE hPrinter, - DWORD Error, - _In_ HWND hWnd, - _In_ LPWSTR pText, - _In_ LPWSTR pCaption, - DWORD dwType); - -BOOL WINAPI PrinterProperties(_In_ HWND, _In_ HANDLE); - -BOOL -WINAPI -ReadPrinter( - _In_ HANDLE hPrinter, - _Out_writes_bytes_(cbBuf) LPVOID pBuf, - _In_ DWORD cbBuf, - _Out_ LPDWORD pNoBytesRead); - -BOOL WINAPI ResetPrinterA(_In_ HANDLE, _In_opt_ LPPRINTER_DEFAULTSA); -BOOL WINAPI ResetPrinterW(_In_ HANDLE, _In_opt_ LPPRINTER_DEFAULTSW); -BOOL WINAPI ScheduleJob(_In_ HANDLE, _In_ DWORD); - -BOOL -WINAPI -SetFormA( - _In_ HANDLE hPrinter, - _In_ LPSTR pFormName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(FORM_INFO_1A))) LPBYTE pForm); - -BOOL -WINAPI -SetFormW( - _In_ HANDLE hPrinter, - _In_ LPWSTR pFormName, - _In_range_(1, 2) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(FORM_INFO_1W))) LPBYTE pForm); - -BOOL -WINAPI -SetJobA( - _In_ HANDLE hPrinter, - _In_ DWORD JobId, - _In_range_(0, 4) DWORD Level, - _When_(Level == 0, _Reserved_) - _When_(Level == 1, _In_reads_bytes_opt_(sizeof(JOB_INFO_1))) - _When_(Level == 2, _In_reads_bytes_opt_(sizeof(JOB_INFO_2))) - _When_(Level == 3, _In_reads_bytes_opt_(sizeof(JOB_INFO_3))) - _When_(Level == 4, _In_reads_bytes_opt_(sizeof(JOB_INFO_4))) - LPBYTE pJob, - _In_ DWORD Command); - -BOOL -WINAPI -SetJobW( - _In_ HANDLE hPrinter, - _In_ DWORD JobId, - _In_range_(0, 4) DWORD Level, - _When_(Level == 0, _Reserved_) - _When_(Level == 1, _In_reads_bytes_opt_(sizeof(JOB_INFO_1))) - _When_(Level == 2, _In_reads_bytes_opt_(sizeof(JOB_INFO_2))) - _When_(Level == 3, _In_reads_bytes_opt_(sizeof(JOB_INFO_3))) - _When_(Level == 4, _In_reads_bytes_opt_(sizeof(JOB_INFO_4))) - LPBYTE pJob, - _In_ DWORD Command); - -BOOL -WINAPI -SetPrinterA( - _In_ HANDLE hPrinter, - _In_range_(0, 9) DWORD Level, - _When_(Level == 0 && Command == PRINTER_CONTROL_SET_STATUS, _In_reads_bytes_(sizeof(DWORD))) - _When_(Level == 0 && Command != PRINTER_CONTROL_SET_STATUS, _In_opt_) - _When_(Level == 1, _In_reads_bytes_(sizeof(PRINTER_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PRINTER_INFO_2))) - _When_(Level == 3, _In_reads_bytes_(sizeof(PRINTER_INFO_3))) - _When_(Level == 4, _In_reads_bytes_(sizeof(PRINTER_INFO_4))) - _When_(Level == 5, _In_reads_bytes_(sizeof(PRINTER_INFO_5))) - _When_(Level == 6, _In_reads_bytes_(sizeof(PRINTER_INFO_6))) - _When_(Level == 7, _In_reads_bytes_(sizeof(PRINTER_INFO_7))) - _When_(Level == 8, _In_reads_bytes_(sizeof(PRINTER_INFO_8))) - _When_(Level == 9, _In_reads_bytes_(sizeof(PRINTER_INFO_9))) - LPBYTE pPrinter, - _In_ DWORD Command); - -BOOL -WINAPI -SetPrinterW( - _In_ HANDLE hPrinter, - _In_range_(0, 9) DWORD Level, - _When_(Level == 0 && Command == PRINTER_CONTROL_SET_STATUS, _In_reads_bytes_(sizeof(DWORD))) - _When_(Level == 0 && Command != PRINTER_CONTROL_SET_STATUS, _In_opt_) - _When_(Level == 1, _In_reads_bytes_(sizeof(PRINTER_INFO_1))) - _When_(Level == 2, _In_reads_bytes_(sizeof(PRINTER_INFO_2))) - _When_(Level == 3, _In_reads_bytes_(sizeof(PRINTER_INFO_3))) - _When_(Level == 4, _In_reads_bytes_(sizeof(PRINTER_INFO_4))) - _When_(Level == 5, _In_reads_bytes_(sizeof(PRINTER_INFO_5))) - _When_(Level == 6, _In_reads_bytes_(sizeof(PRINTER_INFO_6))) - _When_(Level == 7, _In_reads_bytes_(sizeof(PRINTER_INFO_7))) - _When_(Level == 8, _In_reads_bytes_(sizeof(PRINTER_INFO_8))) - _When_(Level == 9, _In_reads_bytes_(sizeof(PRINTER_INFO_9))) - LPBYTE pPrinter, - _In_ DWORD Command); - -BOOL -WINAPI -SetPrinterDataA( - _In_ HANDLE hPrinter, - _In_ LPSTR pValueName, - _In_ DWORD Type, - _In_reads_bytes_(cbData) LPBYTE pData, - _In_ DWORD cbData); - -BOOL -WINAPI -SetPrinterDataW( - _In_ HANDLE hPrinter, - _In_ LPWSTR pValueName, - _In_ DWORD Type, - _In_reads_bytes_(cbData) LPBYTE pData, - _In_ DWORD cbData); - -#ifdef _WINE -LPSTR WINAPI StartDocDlgA(HANDLE hPrinter, DOCINFOA *doc); -LPWSTR WINAPI StartDocDlgW(HANDLE hPrinter, DOCINFOW *doc); -#define StartDocDlg WINELIB_NAME_AW(StartDocDlg) -#endif - -DWORD -WINAPI -StartDocPrinterA( - _In_ HANDLE hPrinter, - _In_range_(1, 3) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(DOC_INFO_1))) LPBYTE pDocInfo); - -DWORD -WINAPI -StartDocPrinterW( - _In_ HANDLE hPrinter, - _In_range_(1, 3) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(DOC_INFO_1))) LPBYTE pDocInfo); - -BOOL WINAPI StartPagePrinter(_In_ HANDLE); -DWORD WINAPI WaitForPrinterChange(_In_ HANDLE, _In_ DWORD); - -BOOL -WINAPI -WritePrinter( - _In_ HANDLE hPrinter, - _In_reads_bytes_(cbBuf) LPVOID pBuf, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcWritten); - -BOOL -WINAPI -XcvDataW( - _In_ HANDLE hXcv, - _In_ PCWSTR pszDataName, - _In_reads_bytes_opt_(cbInputData) PBYTE pInputData, - DWORD cbInputData, - _Out_writes_bytes_opt_(cbOutputData) PBYTE pOutputData, - DWORD cbOutputData, - _Out_ PDWORD pcbOutputNeeded, - _Out_opt_ PDWORD pdwStatus); - -#ifdef UNICODE - -#define AddForm AddFormW -#define AddJob AddJobW -#define AddMonitor AddMonitorW -#define AddPort AddPortW -#define AddPrinter AddPrinterW -#define AddPrinterConnection AddPrinterConnectionW -#define AddPrinterDriver AddPrinterDriverW -#define AddPrintProcessor AddPrintProcessorW -#define AddPrintProvidor AddPrintProvidorW -#define AdvancedDocumentProperties AdvancedDocumentPropertiesW -#define ConfigurePort ConfigurePortW -#define DeleteForm DeleteFormW -#define DeleteMonitor DeleteMonitorW -#define DeletePort DeletePortW -#define DeletePrinterConnection DeletePrinterConnectionW -#define DeletePrinterData DeletePrinterDataW -#define DeletePrinterDriver DeletePrinterDriverW -#define DeletePrintProcessor DeletePrinterProcessorW -#define DeletePrintProvidor DeletePrinterProvidorW -#define DocumentProperties DocumentPropertiesW -#define EnumForms EnumFormsW -#define EnumJobs EnumJobsW -#define EnumMonitors EnumMonitorsW -#define EnumPorts EnumPortsW -#define EnumPrinterData EnumPrinterDataW -#define EnumPrinterDrivers EnumPrinterDriversW -#define EnumPrinters EnumPrintersW -#define EnumPrintProcessorDatatypes EnumPrintProcessorDatatypesW -#define EnumPrintProcessors EnumPrintProcessorsW -#define GetDefaultPrinter GetDefaultPrinterW -#define GetForm GetFormW -#define GetJob GetJobW -#define GetPrinter GetPrinterW -#define GetPrinterData GetPrinterDataW -#define GetPrinterDriver GetPrinterDriverW -#define GetPrinterDriverDirectory GetPrinterDriverDirectoryW -#define GetPrintProcessorDirectory GetPrintProcessorDirectoryW -#define IsValidDevmode IsValidDevmodeW -#define OpenPrinter OpenPrinterW -#define PrinterMessageBox PrinterMessageBoxW -#define ResetPrinter ResetPrinterW -#define SetForm SetFormW -#define SetJob SetJobW -#define SetPrinter SetPrinterW -#define SetPrinterData SetPrinterDataW -#define StartDocPrinter StartDocPrinterW - -#else /* UNICODE */ - -#define AddForm AddFormA -#define AddJob AddJobA -#define AddMonitor AddMonitorA -#define AddPort AddPortA -#define AddPrinter AddPrinterA -#define AddPrinterConnection AddPrinterConnectionA -#define AddPrinterDriver AddPrinterDriverA -#define AddPrintProcessor AddPrintProcessorA -#define AddPrintProvidor AddPrintProvidorA -#define AdvancedDocumentProperties AdvancedDocumentPropertiesA -#define ConfigurePort ConfigurePortA -#define DeleteForm DeleteFormA -#define DeleteMonitor DeleteMonitorA -#define DeletePort DeletePortA -#define DeletePrinterConnection DeletePrinterConnectionA -#define DeletePrinterData DeletePrinterDataA -#define DeletePrinterDriver DeletePrinterDriverA -#define DeletePrintProcessor DeletePrinterProcessorA -#define DeletePrintProvidor DeletePrinterProvidorA -#define DocumentProperties DocumentPropertiesA -#define EnumForms EnumFormsA -#define EnumJobs EnumJobsA -#define EnumMonitors EnumMonitorsA -#define EnumPorts EnumPortsA -#define EnumPrinterData EnumPrinterDataA -#define EnumPrinterDrivers EnumPrinterDriversA -#define EnumPrinters EnumPrintersA -#define EnumPrintProcessorDatatypes EnumPrintProcessorDatatypesA -#define EnumPrintProcessors EnumPrintProcessorsA -#define GetDefaultPrinter GetDefaultPrinterA -#define GetForm GetFormA -#define GetJob GetJobA -#define GetPrinter GetPrinterA -#define GetPrinterData GetPrinterDataA -#define GetPrinterDriver GetPrinterDriverA -#define GetPrinterDriverDirectory GetPrinterDriverDirectoryA -#define GetPrintProcessorDirectory GetPrintProcessorDirectoryA -#define IsValidDevmode IsValidDevmodeA -#define OpenPrinter OpenPrinterA -#define PrinterMessageBox PrinterMessageBoxA -#define ResetPrinter ResetPrinterA -#define SetForm SetFormA -#define SetJob SetJobA -#define SetPrinter SetPrinterA -#define SetPrinterData SetPrinterDataA -#define StartDocPrinter StartDocPrinterA - -#endif /* UNICODE */ - -#endif /* !RC_INVOKED */ - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _WINSPOOL_ */ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _WINSPOOL_ +#define _WINSPOOL_ + +#include <_mingw_unicode.h> + +#ifdef _WINUSER_ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + typedef struct _PRINTER_INFO_1A { + DWORD Flags; + LPSTR pDescription; + LPSTR pName; + LPSTR pComment; + } PRINTER_INFO_1A,*PPRINTER_INFO_1A,*LPPRINTER_INFO_1A; + + typedef struct _PRINTER_INFO_1W { + DWORD Flags; + LPWSTR pDescription; + LPWSTR pName; + LPWSTR pComment; + } PRINTER_INFO_1W,*PPRINTER_INFO_1W,*LPPRINTER_INFO_1W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_1) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_1) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_1) + + typedef struct _PRINTER_INFO_2A { + LPSTR pServerName; + LPSTR pPrinterName; + LPSTR pShareName; + LPSTR pPortName; + LPSTR pDriverName; + LPSTR pComment; + LPSTR pLocation; + LPDEVMODEA pDevMode; + LPSTR pSepFile; + LPSTR pPrintProcessor; + LPSTR pDatatype; + LPSTR pParameters; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Attributes; + DWORD Priority; + DWORD DefaultPriority; + DWORD StartTime; + DWORD UntilTime; + DWORD Status; + DWORD cJobs; + DWORD AveragePPM; + } PRINTER_INFO_2A,*PPRINTER_INFO_2A,*LPPRINTER_INFO_2A; + + typedef struct _PRINTER_INFO_2W { + LPWSTR pServerName; + LPWSTR pPrinterName; + LPWSTR pShareName; + LPWSTR pPortName; + LPWSTR pDriverName; + LPWSTR pComment; + LPWSTR pLocation; + LPDEVMODEW pDevMode; + LPWSTR pSepFile; + LPWSTR pPrintProcessor; + LPWSTR pDatatype; + LPWSTR pParameters; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Attributes; + DWORD Priority; + DWORD DefaultPriority; + DWORD StartTime; + DWORD UntilTime; + DWORD Status; + DWORD cJobs; + DWORD AveragePPM; + } PRINTER_INFO_2W,*PPRINTER_INFO_2W,*LPPRINTER_INFO_2W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_2) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_2) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_2) + + typedef struct _PRINTER_INFO_3 { + PSECURITY_DESCRIPTOR pSecurityDescriptor; + } PRINTER_INFO_3,*PPRINTER_INFO_3,*LPPRINTER_INFO_3; + + typedef struct _PRINTER_INFO_4A { + LPSTR pPrinterName; + LPSTR pServerName; + DWORD Attributes; + } PRINTER_INFO_4A,*PPRINTER_INFO_4A,*LPPRINTER_INFO_4A; + + typedef struct _PRINTER_INFO_4W { + LPWSTR pPrinterName; + LPWSTR pServerName; + DWORD Attributes; + } PRINTER_INFO_4W,*PPRINTER_INFO_4W,*LPPRINTER_INFO_4W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_4) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_4) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_4) + + typedef struct _PRINTER_INFO_5A { + LPSTR pPrinterName; + LPSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; + } PRINTER_INFO_5A,*PPRINTER_INFO_5A,*LPPRINTER_INFO_5A; + + typedef struct _PRINTER_INFO_5W { + LPWSTR pPrinterName; + LPWSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; + } PRINTER_INFO_5W,*PPRINTER_INFO_5W,*LPPRINTER_INFO_5W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_5) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_5) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_5) + + typedef struct _PRINTER_INFO_6 { + DWORD dwStatus; + } PRINTER_INFO_6,*PPRINTER_INFO_6,*LPPRINTER_INFO_6; + + typedef struct _PRINTER_INFO_7A { + LPSTR pszObjectGUID; + DWORD dwAction; + } PRINTER_INFO_7A,*PPRINTER_INFO_7A,*LPPRINTER_INFO_7A; + + typedef struct _PRINTER_INFO_7W { + LPWSTR pszObjectGUID; + DWORD dwAction; + } PRINTER_INFO_7W,*PPRINTER_INFO_7W,*LPPRINTER_INFO_7W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_7) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_7) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_7) + +#define DSPRINT_PUBLISH 0x00000001 +#define DSPRINT_UPDATE 0x00000002 +#define DSPRINT_UNPUBLISH 0x00000004 +#define DSPRINT_REPUBLISH 0x00000008 +#define DSPRINT_PENDING 0x80000000 + + typedef struct _PRINTER_INFO_8A { + LPDEVMODEA pDevMode; + } PRINTER_INFO_8A,*PPRINTER_INFO_8A,*LPPRINTER_INFO_8A; + + typedef struct _PRINTER_INFO_8W { + LPDEVMODEW pDevMode; + } PRINTER_INFO_8W,*PPRINTER_INFO_8W,*LPPRINTER_INFO_8W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_8) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_8) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_8) + + typedef struct _PRINTER_INFO_9A { + LPDEVMODEA pDevMode; + } PRINTER_INFO_9A,*PPRINTER_INFO_9A,*LPPRINTER_INFO_9A; + + typedef struct _PRINTER_INFO_9W { + LPDEVMODEW pDevMode; + } PRINTER_INFO_9W,*PPRINTER_INFO_9W,*LPPRINTER_INFO_9W; + + __MINGW_TYPEDEF_AW(PRINTER_INFO_9) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_9) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_9) + +#define PRINTER_CONTROL_PAUSE 1 +#define PRINTER_CONTROL_RESUME 2 +#define PRINTER_CONTROL_PURGE 3 +#define PRINTER_CONTROL_SET_STATUS 4 + +#define PRINTER_STATUS_PAUSED 0x00000001 +#define PRINTER_STATUS_ERROR 0x00000002 +#define PRINTER_STATUS_PENDING_DELETION 0x00000004 +#define PRINTER_STATUS_PAPER_JAM 0x00000008 +#define PRINTER_STATUS_PAPER_OUT 0x00000010 +#define PRINTER_STATUS_MANUAL_FEED 0x00000020 +#define PRINTER_STATUS_PAPER_PROBLEM 0x00000040 +#define PRINTER_STATUS_OFFLINE 0x00000080 +#define PRINTER_STATUS_IO_ACTIVE 0x00000100 +#define PRINTER_STATUS_BUSY 0x00000200 +#define PRINTER_STATUS_PRINTING 0x00000400 +#define PRINTER_STATUS_OUTPUT_BIN_FULL 0x00000800 +#define PRINTER_STATUS_NOT_AVAILABLE 0x00001000 +#define PRINTER_STATUS_WAITING 0x00002000 +#define PRINTER_STATUS_PROCESSING 0x00004000 +#define PRINTER_STATUS_INITIALIZING 0x00008000 +#define PRINTER_STATUS_WARMING_UP 0x00010000 +#define PRINTER_STATUS_TONER_LOW 0x00020000 +#define PRINTER_STATUS_NO_TONER 0x00040000 +#define PRINTER_STATUS_PAGE_PUNT 0x00080000 +#define PRINTER_STATUS_USER_INTERVENTION 0x00100000 +#define PRINTER_STATUS_OUT_OF_MEMORY 0x00200000 +#define PRINTER_STATUS_DOOR_OPEN 0x00400000 +#define PRINTER_STATUS_SERVER_UNKNOWN 0x00800000 +#define PRINTER_STATUS_POWER_SAVE 0x01000000 + +#define PRINTER_ATTRIBUTE_QUEUED 0x00000001 +#define PRINTER_ATTRIBUTE_DIRECT 0x00000002 +#define PRINTER_ATTRIBUTE_DEFAULT 0x00000004 +#define PRINTER_ATTRIBUTE_SHARED 0x00000008 +#define PRINTER_ATTRIBUTE_NETWORK 0x00000010 +#define PRINTER_ATTRIBUTE_HIDDEN 0x00000020 +#define PRINTER_ATTRIBUTE_LOCAL 0x00000040 + +#define PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x00000080 +#define PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x00000100 +#define PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x00000200 + +#define PRINTER_ATTRIBUTE_WORK_OFFLINE 0x00000400 +#define PRINTER_ATTRIBUTE_ENABLE_BIDI 0x00000800 +#define PRINTER_ATTRIBUTE_RAW_ONLY 0x00001000 +#define PRINTER_ATTRIBUTE_PUBLISHED 0x00002000 +#define PRINTER_ATTRIBUTE_FAX 0x00004000 +#define PRINTER_ATTRIBUTE_TS 0x00008000 + +#define NO_PRIORITY 0 +#define MAX_PRIORITY 99 +#define MIN_PRIORITY 1 +#define DEF_PRIORITY 1 + + typedef struct _JOB_INFO_1A { + DWORD JobId; + LPSTR pPrinterName; + LPSTR pMachineName; + LPSTR pUserName; + LPSTR pDocument; + LPSTR pDatatype; + LPSTR pStatus; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD TotalPages; + DWORD PagesPrinted; + SYSTEMTIME Submitted; + } JOB_INFO_1A,*PJOB_INFO_1A,*LPJOB_INFO_1A; + + typedef struct _JOB_INFO_1W { + DWORD JobId; + LPWSTR pPrinterName; + LPWSTR pMachineName; + LPWSTR pUserName; + LPWSTR pDocument; + LPWSTR pDatatype; + LPWSTR pStatus; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD TotalPages; + DWORD PagesPrinted; + SYSTEMTIME Submitted; + } JOB_INFO_1W,*PJOB_INFO_1W,*LPJOB_INFO_1W; + + __MINGW_TYPEDEF_AW(JOB_INFO_1) + __MINGW_TYPEDEF_AW(PJOB_INFO_1) + __MINGW_TYPEDEF_AW(LPJOB_INFO_1) + + typedef struct _JOB_INFO_2A { + DWORD JobId; + LPSTR pPrinterName; + LPSTR pMachineName; + LPSTR pUserName; + LPSTR pDocument; + LPSTR pNotifyName; + LPSTR pDatatype; + LPSTR pPrintProcessor; + LPSTR pParameters; + LPSTR pDriverName; + LPDEVMODEA pDevMode; + LPSTR pStatus; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD StartTime; + DWORD UntilTime; + DWORD TotalPages; + DWORD Size; + SYSTEMTIME Submitted; + DWORD Time; + DWORD PagesPrinted; + } JOB_INFO_2A,*PJOB_INFO_2A,*LPJOB_INFO_2A; + + typedef struct _JOB_INFO_2W { + DWORD JobId; + LPWSTR pPrinterName; + LPWSTR pMachineName; + LPWSTR pUserName; + LPWSTR pDocument; + LPWSTR pNotifyName; + LPWSTR pDatatype; + LPWSTR pPrintProcessor; + LPWSTR pParameters; + LPWSTR pDriverName; + LPDEVMODEW pDevMode; + LPWSTR pStatus; + PSECURITY_DESCRIPTOR pSecurityDescriptor; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD StartTime; + DWORD UntilTime; + DWORD TotalPages; + DWORD Size; + SYSTEMTIME Submitted; + DWORD Time; + DWORD PagesPrinted; + } JOB_INFO_2W,*PJOB_INFO_2W,*LPJOB_INFO_2W; + + __MINGW_TYPEDEF_AW(JOB_INFO_2) + __MINGW_TYPEDEF_AW(PJOB_INFO_2) + __MINGW_TYPEDEF_AW(LPJOB_INFO_2) + + typedef struct _JOB_INFO_3 { + DWORD JobId; + DWORD NextJobId; + DWORD Reserved; + } JOB_INFO_3,*PJOB_INFO_3,*LPJOB_INFO_3; + +#define JOB_CONTROL_PAUSE 1 +#define JOB_CONTROL_RESUME 2 +#define JOB_CONTROL_CANCEL 3 +#define JOB_CONTROL_RESTART 4 +#define JOB_CONTROL_DELETE 5 +#define JOB_CONTROL_SENT_TO_PRINTER 6 +#define JOB_CONTROL_LAST_PAGE_EJECTED 7 + +#define JOB_STATUS_PAUSED 0x00000001 +#define JOB_STATUS_ERROR 0x00000002 +#define JOB_STATUS_DELETING 0x00000004 +#define JOB_STATUS_SPOOLING 0x00000008 +#define JOB_STATUS_PRINTING 0x00000010 +#define JOB_STATUS_OFFLINE 0x00000020 +#define JOB_STATUS_PAPEROUT 0x00000040 +#define JOB_STATUS_PRINTED 0x00000080 +#define JOB_STATUS_DELETED 0x00000100 +#define JOB_STATUS_BLOCKED_DEVQ 0x00000200 +#define JOB_STATUS_USER_INTERVENTION 0x00000400 +#define JOB_STATUS_RESTART 0x00000800 +#define JOB_STATUS_COMPLETE 0x00001000 + +#define JOB_POSITION_UNSPECIFIED 0 + + typedef struct _ADDJOB_INFO_1A { + LPSTR Path; + DWORD JobId; + } ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A; + + typedef struct _ADDJOB_INFO_1W { + LPWSTR Path; + DWORD JobId; + } ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_INFO_1W; + + __MINGW_TYPEDEF_AW(ADDJOB_INFO_1) + __MINGW_TYPEDEF_AW(PADDJOB_INFO_1) + __MINGW_TYPEDEF_AW(LPADDJOB_INFO_1) + + typedef struct _DRIVER_INFO_1A { + LPSTR pName; + } DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A; + + typedef struct _DRIVER_INFO_1W { + LPWSTR pName; + } DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_1) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_1) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_1) + + typedef struct _DRIVER_INFO_2A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + } DRIVER_INFO_2A,*PDRIVER_INFO_2A,*LPDRIVER_INFO_2A; + + typedef struct _DRIVER_INFO_2W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + } DRIVER_INFO_2W,*PDRIVER_INFO_2W,*LPDRIVER_INFO_2W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_2) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_2) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_2) + + typedef struct _DRIVER_INFO_3A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + LPSTR pHelpFile; + LPSTR pDependentFiles; + LPSTR pMonitorName; + LPSTR pDefaultDataType; + } DRIVER_INFO_3A,*PDRIVER_INFO_3A,*LPDRIVER_INFO_3A; + + typedef struct _DRIVER_INFO_3W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + LPWSTR pHelpFile; + LPWSTR pDependentFiles; + LPWSTR pMonitorName; + LPWSTR pDefaultDataType; + } DRIVER_INFO_3W,*PDRIVER_INFO_3W,*LPDRIVER_INFO_3W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_3) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_3) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_3) + + typedef struct _DRIVER_INFO_4A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + LPSTR pHelpFile; + LPSTR pDependentFiles; + LPSTR pMonitorName; + LPSTR pDefaultDataType; + LPSTR pszzPreviousNames; + } DRIVER_INFO_4A,*PDRIVER_INFO_4A,*LPDRIVER_INFO_4A; + + typedef struct _DRIVER_INFO_4W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + LPWSTR pHelpFile; + LPWSTR pDependentFiles; + LPWSTR pMonitorName; + LPWSTR pDefaultDataType; + LPWSTR pszzPreviousNames; + } DRIVER_INFO_4W,*PDRIVER_INFO_4W,*LPDRIVER_INFO_4W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_4) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_4) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_4) + + typedef struct _DRIVER_INFO_5A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + DWORD dwDriverAttributes; + DWORD dwConfigVersion; + DWORD dwDriverVersion; + } DRIVER_INFO_5A,*PDRIVER_INFO_5A,*LPDRIVER_INFO_5A; + + typedef struct _DRIVER_INFO_5W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + DWORD dwDriverAttributes; + DWORD dwConfigVersion; + DWORD dwDriverVersion; + } DRIVER_INFO_5W,*PDRIVER_INFO_5W,*LPDRIVER_INFO_5W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_5) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_5) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_5) + + typedef struct _DRIVER_INFO_6A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + LPSTR pHelpFile; + LPSTR pDependentFiles; + LPSTR pMonitorName; + LPSTR pDefaultDataType; + LPSTR pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + LPSTR pszMfgName; + LPSTR pszOEMUrl; + LPSTR pszHardwareID; + LPSTR pszProvider; + } DRIVER_INFO_6A,*PDRIVER_INFO_6A,*LPDRIVER_INFO_6A; + + typedef struct _DRIVER_INFO_6W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + LPWSTR pHelpFile; + LPWSTR pDependentFiles; + LPWSTR pMonitorName; + LPWSTR pDefaultDataType; + LPWSTR pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + LPWSTR pszMfgName; + LPWSTR pszOEMUrl; + LPWSTR pszHardwareID; + LPWSTR pszProvider; + } DRIVER_INFO_6W,*PDRIVER_INFO_6W,*LPDRIVER_INFO_6W; + + __MINGW_TYPEDEF_AW(DRIVER_INFO_6) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_6) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_6) + +#define DRIVER_KERNELMODE 0x00000001 +#define DRIVER_USERMODE 0x00000002 + +#define DPD_DELETE_UNUSED_FILES 0x00000001 +#define DPD_DELETE_SPECIFIC_VERSION 0x00000002 +#define DPD_DELETE_ALL_FILES 0x00000004 + +#define APD_STRICT_UPGRADE 0x00000001 +#define APD_STRICT_DOWNGRADE 0x00000002 +#define APD_COPY_ALL_FILES 0x00000004 +#define APD_COPY_NEW_FILES 0x00000008 +#define APD_COPY_FROM_DIRECTORY 0x00000010 + + typedef struct _DOC_INFO_1A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + } DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A; + + typedef struct _DOC_INFO_1W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + } DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W; + + __MINGW_TYPEDEF_AW(DOC_INFO_1) + __MINGW_TYPEDEF_AW(PDOC_INFO_1) + __MINGW_TYPEDEF_AW(LPDOC_INFO_1) + + typedef struct _FORM_INFO_1A { + DWORD Flags; + LPSTR pName; + SIZEL Size; + RECTL ImageableArea; + } FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A; + + typedef struct _FORM_INFO_1W { + DWORD Flags; + LPWSTR pName; + SIZEL Size; + RECTL ImageableArea; + } FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W; + + __MINGW_TYPEDEF_AW(FORM_INFO_1) + __MINGW_TYPEDEF_AW(PFORM_INFO_1) + __MINGW_TYPEDEF_AW(LPFORM_INFO_1) + + typedef struct _DOC_INFO_2A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + DWORD dwMode; + DWORD JobId; + } DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_INFO_2A; + + typedef struct _DOC_INFO_2W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + DWORD dwMode; + DWORD JobId; + } DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W; + + __MINGW_TYPEDEF_AW(DOC_INFO_2) + __MINGW_TYPEDEF_AW(PDOC_INFO_2) + __MINGW_TYPEDEF_AW(LPDOC_INFO_2) + +#define DI_CHANNEL 1 +#define DI_READ_SPOOL_JOB 3 + + typedef struct _DOC_INFO_3A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + DWORD dwFlags; + } DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A; + + typedef struct _DOC_INFO_3W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + DWORD dwFlags; + } DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W; + + __MINGW_TYPEDEF_AW(DOC_INFO_3) + __MINGW_TYPEDEF_AW(PDOC_INFO_3) + __MINGW_TYPEDEF_AW(LPDOC_INFO_3) + +#define DI_MEMORYMAP_WRITE 0x00000001 + +#define FORM_USER 0x00000000 +#define FORM_BUILTIN 0x00000001 +#define FORM_PRINTER 0x00000002 + + typedef struct _PRINTPROCESSOR_INFO_1A { + LPSTR pName; + } PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A; + + typedef struct _PRINTPROCESSOR_INFO_1W { + LPWSTR pName; + } PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W; + + __MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1) + __MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1) + __MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1) + + typedef struct _PRINTPROCESSOR_CAPS_1 { + DWORD dwLevel; + DWORD dwNupOptions; + DWORD dwPageOrderFlags; + DWORD dwNumberOfCopies; + } PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1; + +#define NORMAL_PRINT 0x00000000 +#define REVERSE_PRINT 0x00000001 + + typedef struct _PORT_INFO_1A { + LPSTR pName; + } PORT_INFO_1A,*PPORT_INFO_1A,*LPPORT_INFO_1A; + typedef struct _PORT_INFO_1W { + LPWSTR pName; + } PORT_INFO_1W,*PPORT_INFO_1W,*LPPORT_INFO_1W; + + __MINGW_TYPEDEF_AW(PORT_INFO_1) + __MINGW_TYPEDEF_AW(PPORT_INFO_1) + __MINGW_TYPEDEF_AW(LPPORT_INFO_1) + + typedef struct _PORT_INFO_2A { + LPSTR pPortName; + LPSTR pMonitorName; + LPSTR pDescription; + DWORD fPortType; + DWORD Reserved; + } PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A; + + typedef struct _PORT_INFO_2W { + LPWSTR pPortName; + LPWSTR pMonitorName; + LPWSTR pDescription; + DWORD fPortType; + DWORD Reserved; + } PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W; + + __MINGW_TYPEDEF_AW(PORT_INFO_2) + __MINGW_TYPEDEF_AW(PPORT_INFO_2) + __MINGW_TYPEDEF_AW(LPPORT_INFO_2) + +#define PORT_TYPE_WRITE 0x0001 +#define PORT_TYPE_READ 0x0002 +#define PORT_TYPE_REDIRECTED 0x0004 +#define PORT_TYPE_NET_ATTACHED 0x0008 + + typedef struct _PORT_INFO_3A { + DWORD dwStatus; + LPSTR pszStatus; + DWORD dwSeverity; + } PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A; + + typedef struct _PORT_INFO_3W { + DWORD dwStatus; + LPWSTR pszStatus; + DWORD dwSeverity; + } PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W; + + __MINGW_TYPEDEF_AW(PORT_INFO_3) + __MINGW_TYPEDEF_AW(PPORT_INFO_3) + __MINGW_TYPEDEF_AW(LPPORT_INFO_3) + +#define PORT_STATUS_TYPE_ERROR 1 +#define PORT_STATUS_TYPE_WARNING 2 +#define PORT_STATUS_TYPE_INFO 3 + +#define PORT_STATUS_OFFLINE 1 +#define PORT_STATUS_PAPER_JAM 2 +#define PORT_STATUS_PAPER_OUT 3 +#define PORT_STATUS_OUTPUT_BIN_FULL 4 +#define PORT_STATUS_PAPER_PROBLEM 5 +#define PORT_STATUS_NO_TONER 6 +#define PORT_STATUS_DOOR_OPEN 7 +#define PORT_STATUS_USER_INTERVENTION 8 +#define PORT_STATUS_OUT_OF_MEMORY 9 +#define PORT_STATUS_TONER_LOW 10 +#define PORT_STATUS_WARMING_UP 11 +#define PORT_STATUS_POWER_SAVE 12 + + typedef struct _MONITOR_INFO_1A{ + LPSTR pName; + } MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A; + + typedef struct _MONITOR_INFO_1W{ + LPWSTR pName; + } MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W; + + __MINGW_TYPEDEF_AW(MONITOR_INFO_1) + __MINGW_TYPEDEF_AW(PMONITOR_INFO_1) + __MINGW_TYPEDEF_AW(LPMONITOR_INFO_1) + + typedef struct _MONITOR_INFO_2A { + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDLLName; + } MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A; + + typedef struct _MONITOR_INFO_2W { + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDLLName; + } MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W; + + __MINGW_TYPEDEF_AW(MONITOR_INFO_2) + __MINGW_TYPEDEF_AW(PMONITOR_INFO_2) + __MINGW_TYPEDEF_AW(LPMONITOR_INFO_2) + + typedef struct _DATATYPES_INFO_1A { + LPSTR pName; + } DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A; + + typedef struct _DATATYPES_INFO_1W { + LPWSTR pName; + } DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W; + + __MINGW_TYPEDEF_AW(DATATYPES_INFO_1) + __MINGW_TYPEDEF_AW(PDATATYPES_INFO_1) + __MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1) + + typedef struct _PRINTER_DEFAULTSA { + LPSTR pDatatype; + LPDEVMODEA pDevMode; + ACCESS_MASK DesiredAccess; + } PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA; + + typedef struct _PRINTER_DEFAULTSW { + LPWSTR pDatatype; + LPDEVMODEW pDevMode; + ACCESS_MASK DesiredAccess; + } PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW; + + __MINGW_TYPEDEF_AW(PRINTER_DEFAULTS) + __MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS) + __MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS) + + typedef struct _PRINTER_ENUM_VALUESA { + LPSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; + } PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA; + + typedef struct _PRINTER_ENUM_VALUESW { + LPWSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; + } PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW; + + __MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES) + __MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES) + __MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES) + +#define EnumPrinters __MINGW_NAME_AW(EnumPrinters) + + WINBOOL WINAPI EnumPrintersA(DWORD Flags,LPSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumPrintersW(DWORD Flags,LPWSTR Name,DWORD Level,LPBYTE pPrinterEnum,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + +#define PRINTER_ENUM_DEFAULT 0x00000001 +#define PRINTER_ENUM_LOCAL 0x00000002 +#define PRINTER_ENUM_CONNECTIONS 0x00000004 +#define PRINTER_ENUM_FAVORITE 0x00000004 +#define PRINTER_ENUM_NAME 0x00000008 +#define PRINTER_ENUM_REMOTE 0x00000010 +#define PRINTER_ENUM_SHARED 0x00000020 +#define PRINTER_ENUM_NETWORK 0x00000040 + +#define PRINTER_ENUM_EXPAND 0x00004000 +#define PRINTER_ENUM_CONTAINER 0x00008000 + +#define PRINTER_ENUM_ICONMASK 0x00ff0000 +#define PRINTER_ENUM_ICON1 0x00010000 +#define PRINTER_ENUM_ICON2 0x00020000 +#define PRINTER_ENUM_ICON3 0x00040000 +#define PRINTER_ENUM_ICON4 0x00080000 +#define PRINTER_ENUM_ICON5 0x00100000 +#define PRINTER_ENUM_ICON6 0x00200000 +#define PRINTER_ENUM_ICON7 0x00400000 +#define PRINTER_ENUM_ICON8 0x00800000 +#define PRINTER_ENUM_HIDE 0x01000000 + +#define SPOOL_FILE_PERSISTENT 0x00000001 +#define SPOOL_FILE_TEMPORARY 0x00000002 + +#define OpenPrinter __MINGW_NAME_AW(OpenPrinter) +#define ResetPrinter __MINGW_NAME_AW(ResetPrinter) +#define SetJob __MINGW_NAME_AW(SetJob) +#define GetJob __MINGW_NAME_AW(GetJob) +#define EnumJobs __MINGW_NAME_AW(EnumJobs) +#define AddPrinter __MINGW_NAME_AW(AddPrinter) +#define SetPrinter __MINGW_NAME_AW(SetPrinter) +#define GetPrinter __MINGW_NAME_AW(GetPrinter) +#define AddPrinterDriver __MINGW_NAME_AW(AddPrinterDriver) +#define AddPrinterDriverEx __MINGW_NAME_AW(AddPrinterDriverEx) +#define EnumPrinterDrivers __MINGW_NAME_AW(EnumPrinterDrivers) +#define GetPrinterDriver __MINGW_NAME_AW(GetPrinterDriver) +#define GetPrinterDriverDirectory __MINGW_NAME_AW(GetPrinterDriverDirectory) +#define DeletePrinterDriver __MINGW_NAME_AW(DeletePrinterDriver) +#define DeletePrinterDriverEx __MINGW_NAME_AW(DeletePrinterDriverEx) +#define AddPrintProcessor __MINGW_NAME_AW(AddPrintProcessor) +#define EnumPrintProcessors __MINGW_NAME_AW(EnumPrintProcessors) +#define GetPrintProcessorDirectory __MINGW_NAME_AW(GetPrintProcessorDirectory) +#define EnumPrintProcessorDatatypes __MINGW_NAME_AW(EnumPrintProcessorDatatypes) +#define DeletePrintProcessor __MINGW_NAME_AW(DeletePrintProcessor) +#define StartDocPrinter __MINGW_NAME_AW(StartDocPrinter) +#define AddJob __MINGW_NAME_AW(AddJob) +#define DocumentProperties __MINGW_NAME_AW(DocumentProperties) +#define AdvancedDocumentProperties __MINGW_NAME_AW(AdvancedDocumentProperties) +#define GetPrinterData __MINGW_NAME_AW(GetPrinterData) +#define GetPrinterDataEx __MINGW_NAME_AW(GetPrinterDataEx) +#define EnumPrinterData __MINGW_NAME_AW(EnumPrinterData) +#define EnumPrinterDataEx __MINGW_NAME_AW(EnumPrinterDataEx) +#define EnumPrinterKey __MINGW_NAME_AW(EnumPrinterKey) +#define SetPrinterData __MINGW_NAME_AW(SetPrinterData) +#define SetPrinterDataEx __MINGW_NAME_AW(SetPrinterDataEx) +#define DeletePrinterData __MINGW_NAME_AW(DeletePrinterData) +#define DeletePrinterDataEx __MINGW_NAME_AW(DeletePrinterDataEx) +#define DeletePrinterKey __MINGW_NAME_AW(DeletePrinterKey) + + WINBOOL WINAPI OpenPrinterA(LPSTR pPrinterName,LPHANDLE phPrinter,LPPRINTER_DEFAULTSA pDefault); + WINBOOL WINAPI OpenPrinterW(LPWSTR pPrinterName,LPHANDLE phPrinter,LPPRINTER_DEFAULTSW pDefault); + WINBOOL WINAPI ResetPrinterA(HANDLE hPrinter,LPPRINTER_DEFAULTSA pDefault); + WINBOOL WINAPI ResetPrinterW(HANDLE hPrinter,LPPRINTER_DEFAULTSW pDefault); + WINBOOL WINAPI SetJobA(HANDLE hPrinter,DWORD JobId,DWORD Level,LPBYTE pJob,DWORD Command); + WINBOOL WINAPI SetJobW(HANDLE hPrinter,DWORD JobId,DWORD Level,LPBYTE pJob,DWORD Command); + WINBOOL WINAPI GetJobA(HANDLE hPrinter,DWORD JobId,DWORD Level,LPBYTE pJob,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetJobW(HANDLE hPrinter,DWORD JobId,DWORD Level,LPBYTE pJob,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI EnumJobsA(HANDLE hPrinter,DWORD FirstJob,DWORD NoJobs,DWORD Level,LPBYTE pJob,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumJobsW(HANDLE hPrinter,DWORD FirstJob,DWORD NoJobs,DWORD Level,LPBYTE pJob,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + HANDLE WINAPI AddPrinterA(LPSTR pName,DWORD Level,LPBYTE pPrinter); + HANDLE WINAPI AddPrinterW(LPWSTR pName,DWORD Level,LPBYTE pPrinter); + WINBOOL WINAPI DeletePrinter(HANDLE hPrinter); + WINBOOL WINAPI SetPrinterA(HANDLE hPrinter,DWORD Level,LPBYTE pPrinter,DWORD Command); + WINBOOL WINAPI SetPrinterW(HANDLE hPrinter,DWORD Level,LPBYTE pPrinter,DWORD Command); + WINBOOL WINAPI GetPrinterA(HANDLE hPrinter,DWORD Level,LPBYTE pPrinter,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetPrinterW(HANDLE hPrinter,DWORD Level,LPBYTE pPrinter,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI AddPrinterDriverA(LPSTR pName,DWORD Level,LPBYTE pDriverInfo); + WINBOOL WINAPI AddPrinterDriverW(LPWSTR pName,DWORD Level,LPBYTE pDriverInfo); + WINBOOL WINAPI AddPrinterDriverExA(LPSTR pName,DWORD Level,LPBYTE pDriverInfo,DWORD dwFileCopyFlags); + WINBOOL WINAPI AddPrinterDriverExW(LPWSTR pName,DWORD Level,LPBYTE pDriverInfo,DWORD dwFileCopyFlags); + WINBOOL WINAPI EnumPrinterDriversA(LPSTR pName,LPSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumPrinterDriversW(LPWSTR pName,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI GetPrinterDriverA(HANDLE hPrinter,LPSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetPrinterDriverW(HANDLE hPrinter,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverInfo,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName,LPSTR pEnvironment,DWORD Level,LPBYTE pDriverDirectory,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName,LPWSTR pEnvironment,DWORD Level,LPBYTE pDriverDirectory,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI DeletePrinterDriverA(LPSTR pName,LPSTR pEnvironment,LPSTR pDriverName); + WINBOOL WINAPI DeletePrinterDriverW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pDriverName); + WINBOOL WINAPI DeletePrinterDriverExA(LPSTR pName,LPSTR pEnvironment,LPSTR pDriverName,DWORD dwDeleteFlag,DWORD dwVersionFlag); + WINBOOL WINAPI DeletePrinterDriverExW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pDriverName,DWORD dwDeleteFlag,DWORD dwVersionFlag); + WINBOOL WINAPI AddPrintProcessorA(LPSTR pName,LPSTR pEnvironment,LPSTR pPathName,LPSTR pPrintProcessorName); + WINBOOL WINAPI AddPrintProcessorW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pPathName,LPWSTR pPrintProcessorName); + WINBOOL WINAPI EnumPrintProcessorsA(LPSTR pName,LPSTR pEnvironment,DWORD Level,LPBYTE pPrintProcessorInfo,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumPrintProcessorsW(LPWSTR pName,LPWSTR pEnvironment,DWORD Level,LPBYTE pPrintProcessorInfo,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI GetPrintProcessorDirectoryA(LPSTR pName,LPSTR pEnvironment,DWORD Level,LPBYTE pPrintProcessorInfo,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetPrintProcessorDirectoryW(LPWSTR pName,LPWSTR pEnvironment,DWORD Level,LPBYTE pPrintProcessorInfo,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI EnumPrintProcessorDatatypesA(LPSTR pName,LPSTR pPrintProcessorName,DWORD Level,LPBYTE pDatatypes,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumPrintProcessorDatatypesW(LPWSTR pName,LPWSTR pPrintProcessorName,DWORD Level,LPBYTE pDatatypes,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI DeletePrintProcessorA(LPSTR pName,LPSTR pEnvironment,LPSTR pPrintProcessorName); + WINBOOL WINAPI DeletePrintProcessorW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pPrintProcessorName); + DWORD WINAPI StartDocPrinterA(HANDLE hPrinter,DWORD Level,LPBYTE pDocInfo); + DWORD WINAPI StartDocPrinterW(HANDLE hPrinter,DWORD Level,LPBYTE pDocInfo); + WINBOOL WINAPI StartPagePrinter(HANDLE hPrinter); + WINBOOL WINAPI WritePrinter(HANDLE hPrinter,LPVOID pBuf,DWORD cbBuf,LPDWORD pcWritten); + WINBOOL WINAPI FlushPrinter(HANDLE hPrinter,LPVOID pBuf,DWORD cbBuf,LPDWORD pcWritten,DWORD cSleep); + WINBOOL WINAPI EndPagePrinter(HANDLE hPrinter); + WINBOOL WINAPI AbortPrinter(HANDLE hPrinter); + WINBOOL WINAPI ReadPrinter(HANDLE hPrinter,LPVOID pBuf,DWORD cbBuf,LPDWORD pNoBytesRead); + WINBOOL WINAPI EndDocPrinter(HANDLE hPrinter); + WINBOOL WINAPI AddJobA(HANDLE hPrinter,DWORD Level,LPBYTE pData,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI AddJobW(HANDLE hPrinter,DWORD Level,LPBYTE pData,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI ScheduleJob(HANDLE hPrinter,DWORD JobId); + WINBOOL WINAPI PrinterProperties(HWND hWnd,HANDLE hPrinter); + LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,LPSTR pDeviceName,PDEVMODEA pDevModeOutput,PDEVMODEA pDevModeInput,DWORD fMode); + LONG WINAPI DocumentPropertiesW(HWND hWnd,HANDLE hPrinter,LPWSTR pDeviceName,PDEVMODEW pDevModeOutput,PDEVMODEW pDevModeInput,DWORD fMode); + LONG WINAPI AdvancedDocumentPropertiesA(HWND hWnd,HANDLE hPrinter,LPSTR pDeviceName,PDEVMODEA pDevModeOutput,PDEVMODEA pDevModeInput); + LONG WINAPI AdvancedDocumentPropertiesW(HWND hWnd,HANDLE hPrinter,LPWSTR pDeviceName,PDEVMODEW pDevModeOutput,PDEVMODEW pDevModeInput); + LONG ExtDeviceMode(HWND hWnd,HANDLE hInst,LPDEVMODEA pDevModeOutput,LPSTR pDeviceName,LPSTR pPort,LPDEVMODEA pDevModeInput,LPSTR pProfile,DWORD fMode); + DWORD WINAPI GetPrinterDataA(HANDLE hPrinter,LPSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded); + DWORD WINAPI GetPrinterDataW(HANDLE hPrinter,LPWSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded); + DWORD WINAPI GetPrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPCSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded); + DWORD WINAPI GetPrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPCWSTR pValueName,LPDWORD pType,LPBYTE pData,DWORD nSize,LPDWORD pcbNeeded); + DWORD WINAPI EnumPrinterDataA(HANDLE hPrinter,DWORD dwIndex,LPSTR pValueName,DWORD cbValueName,LPDWORD pcbValueName,LPDWORD pType,LPBYTE pData,DWORD cbData,LPDWORD pcbData); + DWORD WINAPI EnumPrinterDataW(HANDLE hPrinter,DWORD dwIndex,LPWSTR pValueName,DWORD cbValueName,LPDWORD pcbValueName,LPDWORD pType,LPBYTE pData,DWORD cbData,LPDWORD pcbData); + DWORD WINAPI EnumPrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPBYTE pEnumValues,DWORD cbEnumValues,LPDWORD pcbEnumValues,LPDWORD pnEnumValues); + DWORD WINAPI EnumPrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPBYTE pEnumValues,DWORD cbEnumValues,LPDWORD pcbEnumValues,LPDWORD pnEnumValues); + DWORD WINAPI EnumPrinterKeyA(HANDLE hPrinter,LPCSTR pKeyName,LPSTR pSubkey,DWORD cbSubkey,LPDWORD pcbSubkey); + DWORD WINAPI EnumPrinterKeyW(HANDLE hPrinter,LPCWSTR pKeyName,LPWSTR pSubkey,DWORD cbSubkey,LPDWORD pcbSubkey); + DWORD WINAPI SetPrinterDataA(HANDLE hPrinter,LPSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData); + DWORD WINAPI SetPrinterDataW(HANDLE hPrinter,LPWSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData); + DWORD WINAPI SetPrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPCSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData); + DWORD WINAPI SetPrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPCWSTR pValueName,DWORD Type,LPBYTE pData,DWORD cbData); + DWORD WINAPI DeletePrinterDataA(HANDLE hPrinter,LPSTR pValueName); + DWORD WINAPI DeletePrinterDataW(HANDLE hPrinter,LPWSTR pValueName); + DWORD WINAPI DeletePrinterDataExA(HANDLE hPrinter,LPCSTR pKeyName,LPCSTR pValueName); + DWORD WINAPI DeletePrinterDataExW(HANDLE hPrinter,LPCWSTR pKeyName,LPCWSTR pValueName); + DWORD WINAPI DeletePrinterKeyA(HANDLE hPrinter,LPCSTR pKeyName); + DWORD WINAPI DeletePrinterKeyW(HANDLE hPrinter,LPCWSTR pKeyName); + +#define PRINTER_NOTIFY_TYPE 0x00 +#define JOB_NOTIFY_TYPE 0x01 + +#define PRINTER_NOTIFY_FIELD_SERVER_NAME 0x00 +#define PRINTER_NOTIFY_FIELD_PRINTER_NAME 0x01 +#define PRINTER_NOTIFY_FIELD_SHARE_NAME 0x02 +#define PRINTER_NOTIFY_FIELD_PORT_NAME 0x03 +#define PRINTER_NOTIFY_FIELD_DRIVER_NAME 0x04 +#define PRINTER_NOTIFY_FIELD_COMMENT 0x05 +#define PRINTER_NOTIFY_FIELD_LOCATION 0x06 +#define PRINTER_NOTIFY_FIELD_DEVMODE 0x07 +#define PRINTER_NOTIFY_FIELD_SEPFILE 0x08 +#define PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR 0x09 +#define PRINTER_NOTIFY_FIELD_PARAMETERS 0x0A +#define PRINTER_NOTIFY_FIELD_DATATYPE 0x0B +#define PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR 0x0C +#define PRINTER_NOTIFY_FIELD_ATTRIBUTES 0x0D +#define PRINTER_NOTIFY_FIELD_PRIORITY 0x0E +#define PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY 0x0F +#define PRINTER_NOTIFY_FIELD_START_TIME 0x10 +#define PRINTER_NOTIFY_FIELD_UNTIL_TIME 0x11 +#define PRINTER_NOTIFY_FIELD_STATUS 0x12 +#define PRINTER_NOTIFY_FIELD_STATUS_STRING 0x13 +#define PRINTER_NOTIFY_FIELD_CJOBS 0x14 +#define PRINTER_NOTIFY_FIELD_AVERAGE_PPM 0x15 +#define PRINTER_NOTIFY_FIELD_TOTAL_PAGES 0x16 +#define PRINTER_NOTIFY_FIELD_PAGES_PRINTED 0x17 +#define PRINTER_NOTIFY_FIELD_TOTAL_BYTES 0x18 +#define PRINTER_NOTIFY_FIELD_BYTES_PRINTED 0x19 +#define PRINTER_NOTIFY_FIELD_OBJECT_GUID 0x1A + +#define JOB_NOTIFY_FIELD_PRINTER_NAME 0x00 +#define JOB_NOTIFY_FIELD_MACHINE_NAME 0x01 +#define JOB_NOTIFY_FIELD_PORT_NAME 0x02 +#define JOB_NOTIFY_FIELD_USER_NAME 0x03 +#define JOB_NOTIFY_FIELD_NOTIFY_NAME 0x04 +#define JOB_NOTIFY_FIELD_DATATYPE 0x05 +#define JOB_NOTIFY_FIELD_PRINT_PROCESSOR 0x06 +#define JOB_NOTIFY_FIELD_PARAMETERS 0x07 +#define JOB_NOTIFY_FIELD_DRIVER_NAME 0x08 +#define JOB_NOTIFY_FIELD_DEVMODE 0x09 +#define JOB_NOTIFY_FIELD_STATUS 0x0A +#define JOB_NOTIFY_FIELD_STATUS_STRING 0x0B +#define JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR 0x0C +#define JOB_NOTIFY_FIELD_DOCUMENT 0x0D +#define JOB_NOTIFY_FIELD_PRIORITY 0x0E +#define JOB_NOTIFY_FIELD_POSITION 0x0F +#define JOB_NOTIFY_FIELD_SUBMITTED 0x10 +#define JOB_NOTIFY_FIELD_START_TIME 0x11 +#define JOB_NOTIFY_FIELD_UNTIL_TIME 0x12 +#define JOB_NOTIFY_FIELD_TIME 0x13 +#define JOB_NOTIFY_FIELD_TOTAL_PAGES 0x14 +#define JOB_NOTIFY_FIELD_PAGES_PRINTED 0x15 +#define JOB_NOTIFY_FIELD_TOTAL_BYTES 0x16 +#define JOB_NOTIFY_FIELD_BYTES_PRINTED 0x17 + + typedef struct _PRINTER_NOTIFY_OPTIONS_TYPE { + WORD Type; + WORD Reserved0; + DWORD Reserved1; + DWORD Reserved2; + DWORD Count; + PWORD pFields; + } PRINTER_NOTIFY_OPTIONS_TYPE,*PPRINTER_NOTIFY_OPTIONS_TYPE,*LPPRINTER_NOTIFY_OPTIONS_TYPE; + +#define PRINTER_NOTIFY_OPTIONS_REFRESH 0x01 + + typedef struct _PRINTER_NOTIFY_OPTIONS { + DWORD Version; + DWORD Flags; + DWORD Count; + PPRINTER_NOTIFY_OPTIONS_TYPE pTypes; + } PRINTER_NOTIFY_OPTIONS,*PPRINTER_NOTIFY_OPTIONS,*LPPRINTER_NOTIFY_OPTIONS; + +#define PRINTER_NOTIFY_INFO_DISCARDED 0x01 + + typedef struct _PRINTER_NOTIFY_INFO_DATA { + WORD Type; + WORD Field; + DWORD Reserved; + DWORD Id; + union { + DWORD adwData[2]; + struct { + DWORD cbBuf; + LPVOID pBuf; + } Data; + } NotifyData; + } PRINTER_NOTIFY_INFO_DATA,*PPRINTER_NOTIFY_INFO_DATA,*LPPRINTER_NOTIFY_INFO_DATA; + + typedef struct _PRINTER_NOTIFY_INFO { + DWORD Version; + DWORD Flags; + DWORD Count; + PRINTER_NOTIFY_INFO_DATA aData[1]; + } PRINTER_NOTIFY_INFO,*PPRINTER_NOTIFY_INFO,*LPPRINTER_NOTIFY_INFO; + + typedef struct _BINARY_CONTAINER{ + DWORD cbBuf; + LPBYTE pData; + } BINARY_CONTAINER,*PBINARY_CONTAINER; + + typedef struct _BIDI_DATA{ + DWORD dwBidiType; + union { + WINBOOL bData; + LONG iData; + LPWSTR sData; + FLOAT fData; + BINARY_CONTAINER biData; + } u; + } BIDI_DATA,*PBIDI_DATA,*LPBIDI_DATA; + + typedef struct _BIDI_REQUEST_DATA{ + DWORD dwReqNumber; + LPWSTR pSchema; + BIDI_DATA data; + } BIDI_REQUEST_DATA ,*PBIDI_REQUEST_DATA ,*LPBIDI_REQUEST_DATA; + + typedef struct _BIDI_REQUEST_CONTAINER{ + DWORD Version; + DWORD Flags; + DWORD Count; + BIDI_REQUEST_DATA aData[1 ]; + }BIDI_REQUEST_CONTAINER,*PBIDI_REQUEST_CONTAINER,*LPBIDI_REQUEST_CONTAINER; + + typedef struct _BIDI_RESPONSE_DATA{ + DWORD dwResult; + DWORD dwReqNumber; + LPWSTR pSchema; + BIDI_DATA data; + } BIDI_RESPONSE_DATA,*PBIDI_RESPONSE_DATA,*LPBIDI_RESPONSE_DATA; + + typedef struct _BIDI_RESPONSE_CONTAINER{ + DWORD Version; + DWORD Flags; + DWORD Count; + BIDI_RESPONSE_DATA aData[1 ]; + } BIDI_RESPONSE_CONTAINER,*PBIDI_RESPONSE_CONTAINER,*LPBIDI_RESPONSE_CONTAINER; + +#define BIDI_ACTION_ENUM_SCHEMA L"EnumSchema" +#define BIDI_ACTION_GET L"Get" +#define BIDI_ACTION_SET L"Set" +#define BIDI_ACTION_GET_ALL L"GetAll" + + typedef enum { + BIDI_NULL = 0,BIDI_INT = 1,BIDI_FLOAT = 2,BIDI_BOOL = 3,BIDI_STRING = 4,BIDI_TEXT = 5,BIDI_ENUM = 6,BIDI_BLOB = 7 + } BIDI_TYPE; + +#define BIDI_ACCESS_ADMINISTRATOR 0x1 +#define BIDI_ACCESS_USER 0x2 + +#define ERROR_BIDI_STATUS_OK 0 +#define ERROR_BIDI_NOT_SUPPORTED ERROR_NOT_SUPPORTED + +#define ERROR_BIDI_ERROR_BASE 13000 +#define ERROR_BIDI_STATUS_WARNING (ERROR_BIDI_ERROR_BASE + 1) +#define ERROR_BIDI_SCHEMA_READ_ONLY (ERROR_BIDI_ERROR_BASE + 2) +#define ERROR_BIDI_SERVER_OFFLINE (ERROR_BIDI_ERROR_BASE + 3) +#define ERROR_BIDI_DEVICE_OFFLINE (ERROR_BIDI_ERROR_BASE + 4) +#define ERROR_BIDI_SCHEMA_NOT_SUPPORTED (ERROR_BIDI_ERROR_BASE + 5) + + DWORD WINAPI WaitForPrinterChange(HANDLE hPrinter,DWORD Flags); + HANDLE WINAPI FindFirstPrinterChangeNotification(HANDLE hPrinter,DWORD fdwFlags,DWORD fdwOptions,LPVOID pPrinterNotifyOptions); + WINBOOL WINAPI FindNextPrinterChangeNotification(HANDLE hChange,PDWORD pdwChange,LPVOID pPrinterNotifyOptions,LPVOID *ppPrinterNotifyInfo); + WINBOOL WINAPI FreePrinterNotifyInfo (PPRINTER_NOTIFY_INFO pPrinterNotifyInfo); + WINBOOL WINAPI FindClosePrinterChangeNotification(HANDLE hChange); + +#define PRINTER_CHANGE_ADD_PRINTER 0x00000001 +#define PRINTER_CHANGE_SET_PRINTER 0x00000002 +#define PRINTER_CHANGE_DELETE_PRINTER 0x00000004 +#define PRINTER_CHANGE_FAILED_CONNECTION_PRINTER 0x00000008 +#define PRINTER_CHANGE_PRINTER 0x000000FF +#define PRINTER_CHANGE_ADD_JOB 0x00000100 +#define PRINTER_CHANGE_SET_JOB 0x00000200 +#define PRINTER_CHANGE_DELETE_JOB 0x00000400 +#define PRINTER_CHANGE_WRITE_JOB 0x00000800 +#define PRINTER_CHANGE_JOB 0x0000FF00 +#define PRINTER_CHANGE_ADD_FORM 0x00010000 +#define PRINTER_CHANGE_SET_FORM 0x00020000 +#define PRINTER_CHANGE_DELETE_FORM 0x00040000 +#define PRINTER_CHANGE_FORM 0x00070000 +#define PRINTER_CHANGE_ADD_PORT 0x00100000 +#define PRINTER_CHANGE_CONFIGURE_PORT 0x00200000 +#define PRINTER_CHANGE_DELETE_PORT 0x00400000 +#define PRINTER_CHANGE_PORT 0x00700000 +#define PRINTER_CHANGE_ADD_PRINT_PROCESSOR 0x01000000 +#define PRINTER_CHANGE_DELETE_PRINT_PROCESSOR 0x04000000 +#define PRINTER_CHANGE_PRINT_PROCESSOR 0x07000000 +#define PRINTER_CHANGE_ADD_PRINTER_DRIVER 0x10000000 +#define PRINTER_CHANGE_SET_PRINTER_DRIVER 0x20000000 +#define PRINTER_CHANGE_DELETE_PRINTER_DRIVER 0x40000000 +#define PRINTER_CHANGE_PRINTER_DRIVER 0x70000000 +#define PRINTER_CHANGE_TIMEOUT 0x80000000 +#define PRINTER_CHANGE_ALL 0x7777FFFF + +#define PrinterMessageBox __MINGW_NAME_AW(PrinterMessageBox) +#define AddForm __MINGW_NAME_AW(AddForm) +#define DeleteForm __MINGW_NAME_AW(DeleteForm) +#define GetForm __MINGW_NAME_AW(GetForm) +#define SetForm __MINGW_NAME_AW(SetForm) +#define EnumForms __MINGW_NAME_AW(EnumForms) +#define EnumMonitors __MINGW_NAME_AW(EnumMonitors) +#define AddMonitor __MINGW_NAME_AW(AddMonitor) +#define DeleteMonitor __MINGW_NAME_AW(DeleteMonitor) +#define EnumPorts __MINGW_NAME_AW(EnumPorts) +#define AddPort __MINGW_NAME_AW(AddPort) +#define ConfigurePort __MINGW_NAME_AW(ConfigurePort) +#define DeletePort __MINGW_NAME_AW(DeletePort) +#define GetDefaultPrinter __MINGW_NAME_AW(GetDefaultPrinter) +#define SetDefaultPrinter __MINGW_NAME_AW(SetDefaultPrinter) +#define SetPort __MINGW_NAME_AW(SetPort) +#define AddPrinterConnection __MINGW_NAME_AW(AddPrinterConnection) +#define DeletePrinterConnection __MINGW_NAME_AW(DeletePrinterConnection) + + DWORD WINAPI PrinterMessageBoxA(HANDLE hPrinter,DWORD Error,HWND hWnd,LPSTR pText,LPSTR pCaption,DWORD dwType); + DWORD WINAPI PrinterMessageBoxW(HANDLE hPrinter,DWORD Error,HWND hWnd,LPWSTR pText,LPWSTR pCaption,DWORD dwType); + +#define PRINTER_ERROR_INFORMATION 0x80000000 +#define PRINTER_ERROR_WARNING 0x40000000 +#define PRINTER_ERROR_SEVERE 0x20000000 + +#define PRINTER_ERROR_OUTOFPAPER 0x00000001 +#define PRINTER_ERROR_JAM 0x00000002 +#define PRINTER_ERROR_OUTOFTONER 0x00000004 + + WINBOOL WINAPI ClosePrinter(HANDLE hPrinter); + WINBOOL WINAPI AddFormA(HANDLE hPrinter,DWORD Level,LPBYTE pForm); + WINBOOL WINAPI AddFormW(HANDLE hPrinter,DWORD Level,LPBYTE pForm); + WINBOOL WINAPI DeleteFormA(HANDLE hPrinter,LPSTR pFormName); + WINBOOL WINAPI DeleteFormW(HANDLE hPrinter,LPWSTR pFormName); + WINBOOL WINAPI GetFormA(HANDLE hPrinter,LPSTR pFormName,DWORD Level,LPBYTE pForm,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI GetFormW(HANDLE hPrinter,LPWSTR pFormName,DWORD Level,LPBYTE pForm,DWORD cbBuf,LPDWORD pcbNeeded); + WINBOOL WINAPI SetFormA(HANDLE hPrinter,LPSTR pFormName,DWORD Level,LPBYTE pForm); + WINBOOL WINAPI SetFormW(HANDLE hPrinter,LPWSTR pFormName,DWORD Level,LPBYTE pForm); + WINBOOL WINAPI EnumFormsA(HANDLE hPrinter,DWORD Level,LPBYTE pForm,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumFormsW(HANDLE hPrinter,DWORD Level,LPBYTE pForm,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumMonitorsA(LPSTR pName,DWORD Level,LPBYTE pMonitor,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumMonitorsW(LPWSTR pName,DWORD Level,LPBYTE pMonitor,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI AddMonitorA(LPSTR pName,DWORD Level,LPBYTE pMonitorInfo); + WINBOOL WINAPI AddMonitorW(LPWSTR pName,DWORD Level,LPBYTE pMonitorInfo); + WINBOOL WINAPI DeleteMonitorA(LPSTR pName,LPSTR pEnvironment,LPSTR pMonitorName); + WINBOOL WINAPI DeleteMonitorW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pMonitorName); + WINBOOL WINAPI EnumPortsA(LPSTR pName,DWORD Level,LPBYTE pPorts,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI EnumPortsW(LPWSTR pName,DWORD Level,LPBYTE pPorts,DWORD cbBuf,LPDWORD pcbNeeded,LPDWORD pcReturned); + WINBOOL WINAPI AddPortA(LPSTR pName,HWND hWnd,LPSTR pMonitorName); + WINBOOL WINAPI AddPortW(LPWSTR pName,HWND hWnd,LPWSTR pMonitorName); + WINBOOL WINAPI ConfigurePortA(LPSTR pName,HWND hWnd,LPSTR pPortName); + WINBOOL WINAPI ConfigurePortW(LPWSTR pName,HWND hWnd,LPWSTR pPortName); + WINBOOL WINAPI DeletePortA(LPSTR pName,HWND hWnd,LPSTR pPortName); + WINBOOL WINAPI DeletePortW(LPWSTR pName,HWND hWnd,LPWSTR pPortName); + WINBOOL WINAPI XcvDataW(HANDLE hXcv,PCWSTR pszDataName,PBYTE pInputData,DWORD cbInputData,PBYTE pOutputData,DWORD cbOutputData,PDWORD pcbOutputNeeded,PDWORD pdwStatus); + +#define XcvData XcvDataW + + WINBOOL WINAPI GetDefaultPrinterA(LPSTR pszBuffer,LPDWORD pcchBuffer); + WINBOOL WINAPI GetDefaultPrinterW(LPWSTR pszBuffer,LPDWORD pcchBuffer); + WINBOOL WINAPI SetDefaultPrinterA(LPCSTR pszPrinter); + WINBOOL WINAPI SetDefaultPrinterW(LPCWSTR pszPrinter); + WINBOOL WINAPI SetPortA(LPSTR pName,LPSTR pPortName,DWORD dwLevel,LPBYTE pPortInfo); + WINBOOL WINAPI SetPortW(LPWSTR pName,LPWSTR pPortName,DWORD dwLevel,LPBYTE pPortInfo); + WINBOOL WINAPI AddPrinterConnectionA(LPSTR pName); + WINBOOL WINAPI AddPrinterConnectionW(LPWSTR pName); + WINBOOL WINAPI DeletePrinterConnectionA(LPSTR pName); + WINBOOL WINAPI DeletePrinterConnectionW(LPWSTR pName); + HANDLE WINAPI ConnectToPrinterDlg(HWND hwnd,DWORD Flags); + + typedef struct _PROVIDOR_INFO_1A{ + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDLLName; + } PROVIDOR_INFO_1A,*PPROVIDOR_INFO_1A,*LPPROVIDOR_INFO_1A; + + typedef struct _PROVIDOR_INFO_1W{ + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDLLName; + } PROVIDOR_INFO_1W,*PPROVIDOR_INFO_1W,*LPPROVIDOR_INFO_1W; + + __MINGW_TYPEDEF_AW(PROVIDOR_INFO_1) + __MINGW_TYPEDEF_AW(PPROVIDOR_INFO_1) + __MINGW_TYPEDEF_AW(LPPROVIDOR_INFO_1) + + typedef struct _PROVIDOR_INFO_2A{ + LPSTR pOrder; + } PROVIDOR_INFO_2A,*PPROVIDOR_INFO_2A,*LPPROVIDOR_INFO_2A; + + typedef struct _PROVIDOR_INFO_2W{ + LPWSTR pOrder; + } PROVIDOR_INFO_2W,*PPROVIDOR_INFO_2W,*LPPROVIDOR_INFO_2W; + + __MINGW_TYPEDEF_AW(PROVIDOR_INFO_2) + __MINGW_TYPEDEF_AW(PPROVIDOR_INFO_2) + __MINGW_TYPEDEF_AW(LPPROVIDOR_INFO_2) + +#define AddPrintProvidor __MINGW_NAME_AW(AddPrintProvidor) +#define DeletePrintProvidor __MINGW_NAME_AW(DeletePrintProvidor) +#define IsValidDevmode __MINGW_NAME_AW(IsValidDevmode) + + WINBOOL WINAPI AddPrintProvidorA(LPSTR pName,DWORD level,LPBYTE pProvidorInfo); + WINBOOL WINAPI AddPrintProvidorW(LPWSTR pName,DWORD level,LPBYTE pProvidorInfo); + WINBOOL WINAPI DeletePrintProvidorA(LPSTR pName,LPSTR pEnvironment,LPSTR pPrintProvidorName); + WINBOOL WINAPI DeletePrintProvidorW(LPWSTR pName,LPWSTR pEnvironment,LPWSTR pPrintProvidorName); + WINBOOL WINAPI IsValidDevmodeA (PDEVMODEA pDevmode,size_t DevmodeSize); + WINBOOL WINAPI IsValidDevmodeW (PDEVMODEW pDevmode,size_t DevmodeSize); + +#define SPLREG_DEFAULT_SPOOL_DIRECTORY TEXT("DefaultSpoolDirectory") +#define SPLREG_PORT_THREAD_PRIORITY_DEFAULT TEXT("PortThreadPriorityDefault") +#define SPLREG_PORT_THREAD_PRIORITY TEXT("PortThreadPriority") +#define SPLREG_SCHEDULER_THREAD_PRIORITY_DEFAULT TEXT("SchedulerThreadPriorityDefault") +#define SPLREG_SCHEDULER_THREAD_PRIORITY TEXT("SchedulerThreadPriority") +#define SPLREG_BEEP_ENABLED TEXT("BeepEnabled") +#define SPLREG_NET_POPUP TEXT("NetPopup") +#define SPLREG_RETRY_POPUP TEXT("RetryPopup") +#define SPLREG_NET_POPUP_TO_COMPUTER TEXT("NetPopupToComputer") +#define SPLREG_EVENT_LOG TEXT("EventLog") +#define SPLREG_MAJOR_VERSION TEXT("MajorVersion") +#define SPLREG_MINOR_VERSION TEXT("MinorVersion") +#define SPLREG_ARCHITECTURE TEXT("Architecture") +#define SPLREG_OS_VERSION TEXT("OSVersion") +#define SPLREG_OS_VERSIONEX TEXT("OSVersionEx") +#define SPLREG_DS_PRESENT TEXT("DsPresent") +#define SPLREG_DS_PRESENT_FOR_USER TEXT("DsPresentForUser") +#define SPLREG_REMOTE_FAX TEXT("RemoteFax") +#define SPLREG_RESTART_JOB_ON_POOL_ERROR TEXT("RestartJobOnPoolError") +#define SPLREG_RESTART_JOB_ON_POOL_ENABLED TEXT("RestartJobOnPoolEnabled") +#define SPLREG_DNS_MACHINE_NAME TEXT("DNSMachineName") +#define SPLREG_ALLOW_USER_MANAGEFORMS TEXT("AllowUserManageForms") +#define SPLREG_WEBSHAREMGMT TEXT("WebShareMgmt") + +#define SERVER_ACCESS_ADMINISTER 0x00000001 +#define SERVER_ACCESS_ENUMERATE 0x00000002 + +#define PRINTER_ACCESS_ADMINISTER 0x00000004 +#define PRINTER_ACCESS_USE 0x00000008 + +#define JOB_ACCESS_ADMINISTER 0x00000010 +#define JOB_ACCESS_READ 0x00000020 + +#define SERVER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE) +#define SERVER_READ (STANDARD_RIGHTS_READ | SERVER_ACCESS_ENUMERATE) +#define SERVER_WRITE (STANDARD_RIGHTS_WRITE | SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE) +#define SERVER_EXECUTE (STANDARD_RIGHTS_EXECUTE | SERVER_ACCESS_ENUMERATE) +#define PRINTER_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE) +#define PRINTER_READ (STANDARD_RIGHTS_READ | PRINTER_ACCESS_USE) +#define PRINTER_WRITE (STANDARD_RIGHTS_WRITE | PRINTER_ACCESS_USE) +#define PRINTER_EXECUTE (STANDARD_RIGHTS_EXECUTE | PRINTER_ACCESS_USE) +#define JOB_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | JOB_ACCESS_ADMINISTER | JOB_ACCESS_READ) +#define JOB_READ (STANDARD_RIGHTS_READ | JOB_ACCESS_READ) +#define JOB_WRITE (STANDARD_RIGHTS_WRITE | JOB_ACCESS_ADMINISTER) +#define JOB_EXECUTE (STANDARD_RIGHTS_EXECUTE | JOB_ACCESS_ADMINISTER) + +#define SPLDS_SPOOLER_KEY TEXT("DsSpooler") +#define SPLDS_DRIVER_KEY TEXT("DsDriver") +#define SPLDS_USER_KEY TEXT("DsUser") + +#define SPLDS_ASSET_NUMBER TEXT("assetNumber") +#define SPLDS_BYTES_PER_MINUTE TEXT("bytesPerMinute") +#define SPLDS_DESCRIPTION TEXT("description") +#define SPLDS_DRIVER_NAME TEXT("driverName") +#define SPLDS_DRIVER_VERSION TEXT("driverVersion") +#define SPLDS_LOCATION TEXT("location") +#define SPLDS_PORT_NAME TEXT("portName") +#define SPLDS_PRINT_ATTRIBUTES TEXT("printAttributes") +#define SPLDS_PRINT_BIN_NAMES TEXT("printBinNames") +#define SPLDS_PRINT_COLLATE TEXT("printCollate") +#define SPLDS_PRINT_COLOR TEXT("printColor") +#define SPLDS_PRINT_DUPLEX_SUPPORTED TEXT("printDuplexSupported") +#define SPLDS_PRINT_END_TIME TEXT("printEndTime") +#define SPLDS_PRINTER_CLASS TEXT("printQueue") +#define SPLDS_PRINTER_NAME TEXT("printerName") +#define SPLDS_PRINT_KEEP_PRINTED_JOBS TEXT("printKeepPrintedJobs") +#define SPLDS_PRINT_LANGUAGE TEXT("printLanguage") +#define SPLDS_PRINT_MAC_ADDRESS TEXT("printMACAddress") +#define SPLDS_PRINT_MAX_X_EXTENT TEXT("printMaxXExtent") +#define SPLDS_PRINT_MAX_Y_EXTENT TEXT("printMaxYExtent") +#define SPLDS_PRINT_MAX_RESOLUTION_SUPPORTED TEXT("printMaxResolutionSupported") +#define SPLDS_PRINT_MEDIA_READY TEXT("printMediaReady") +#define SPLDS_PRINT_MEDIA_SUPPORTED TEXT("printMediaSupported") +#define SPLDS_PRINT_MEMORY TEXT("printMemory") +#define SPLDS_PRINT_MIN_X_EXTENT TEXT("printMinXExtent") +#define SPLDS_PRINT_MIN_Y_EXTENT TEXT("printMinYExtent") +#define SPLDS_PRINT_NETWORK_ADDRESS TEXT("printNetworkAddress") +#define SPLDS_PRINT_NOTIFY TEXT("printNotify") +#define SPLDS_PRINT_NUMBER_UP TEXT("printNumberUp") +#define SPLDS_PRINT_ORIENTATIONS_SUPPORTED TEXT("printOrientationsSupported") +#define SPLDS_PRINT_OWNER TEXT("printOwner") +#define SPLDS_PRINT_PAGES_PER_MINUTE TEXT("printPagesPerMinute") +#define SPLDS_PRINT_RATE TEXT("printRate") +#define SPLDS_PRINT_RATE_UNIT TEXT("printRateUnit") +#define SPLDS_PRINT_SEPARATOR_FILE TEXT("printSeparatorFile") +#define SPLDS_PRINT_SHARE_NAME TEXT("printShareName") +#define SPLDS_PRINT_SPOOLING TEXT("printSpooling") +#define SPLDS_PRINT_STAPLING_SUPPORTED TEXT("printStaplingSupported") +#define SPLDS_PRINT_START_TIME TEXT("printStartTime") +#define SPLDS_PRINT_STATUS TEXT("printStatus") +#define SPLDS_PRIORITY TEXT("priority") +#define SPLDS_SERVER_NAME TEXT("serverName") +#define SPLDS_SHORT_SERVER_NAME TEXT("shortServerName") +#define SPLDS_UNC_NAME TEXT("uNCName") +#define SPLDS_URL TEXT("url") +#define SPLDS_FLAGS TEXT("flags") +#define SPLDS_VERSION_NUMBER TEXT("versionNumber") + +#define SPLDS_PRINTER_NAME_ALIASES TEXT("printerNameAliases") +#define SPLDS_PRINTER_LOCATIONS TEXT("printerLocations") +#define SPLDS_PRINTER_MODEL TEXT("printerModel") + +#if (_WIN32_WINNT >= 0x0600) +#define AddPrinterConnection2 __MINGW_NAME_AW(AddPrinterConnection2) +#define DeletePrinterDriverPackage __MINGW_NAME_AW(DeletePrinterDriverPackage) +#define DocumentEvent __MINGW_NAME_AW(DocumentEvent) + +#define PRINTER_CONNECTION_MISMATCH 0x00000020 +#define PRINTER_CONNECTION_NO_UI 0x00000040 + +typedef enum tagPRINTER_OPTION_FLAGS { + PRINTER_OPTION_NO_CACHE, + PRINTER_OPTION_CACHE, + PRINTER_OPTION_CLIENT_CHANGE +} PRINTER_OPTION_FLAGS; + +typedef enum tagEPrintXPSJobOperation { + kJobProduction, + kJobConsumption +} EPrintXPSJobOperation; + +typedef enum tagEPrintXPSJobProgress { + kAddingDocumentSequence, + kDocumentSequenceAdded, + kAddingFixedDocument, + kFixedDocumentAdded, + kAddingFixedPage, + kFixedPageAdded, + kResourceAdded, + kFontAdded, + kImageAdded, + kXpsDocumentCommitted +} EPrintXPSJobProgress; + +typedef struct _PRINTER_CONNECTION_INFO_1 { + DWORD dwFlags; + LPTSTR pszDriverName; +} PRINTER_CONNECTION_INFO_1, *PPRINTER_CONNECTION_INFO_1; + + WINBOOL AddPrinterConnection2W(HWND hWnd,LPCWSTR pszName,DWORD dwLevel,PVOID pConnectionInfo); + WINBOOL AddPrinterConnection2A(HWND hWnd,LPCSTR pszName,DWORD dwLevel,PVOID pConnectionInfo); /*Not supported and returns ERROR_NOT_SUPPORTED.*/ + +HRESULT WINAPI DeletePrinterDriverPackageA( + LPCSTR pszServer, + LPCSTR pszInfPath, + LPCSTR pszEnvironment +); + +HRESULT WINAPI DeletePrinterDriverPackageW( + LPCWSTR pszServer, + LPCWSTR pszInfPath, + LPCWSTR pszEnvironment +); + +HRESULT DocumentEventA( + HANDLE hPrinter, + HDC hdc, + INT iEsc, + ULONG cbIn, + PVOID pvIn, + ULONG cbOut, + PVOID pvOut +); + +HRESULT DocumentEventW( + HANDLE hPrinter, + HDC hdc, + INT iEsc, + ULONG cbIn, + PVOID pvIn, + ULONG cbOut, + PVOID pvOut +); + +typedef struct _DRIVER_INFO_8W { + DWORD cVersion; + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDriverPath; + LPWSTR pDataFile; + LPWSTR pConfigFile; + LPWSTR pHelpFile; + LPWSTR pDependentFiles; + LPWSTR pMonitorName; + LPWSTR pDefaultDataType; + LPWSTR pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + LPWSTR pszMfgName; + LPWSTR pszOEMUrl; + LPWSTR pszHardwareID; + LPWSTR pszProvider; + LPWSTR pszPrintProcessor; + LPWSTR pszVendorSetup; + LPWSTR pszzColorProfiles; + LPWSTR pszInfPath; + DWORD dwPrinterDriverAttributes; + LPWSTR pszzCoreDriverDependencies; + FILETIME ftMinInboxDriverVerDate; + DWORDLONG dwlMinInboxDriverVerVersion; +} DRIVER_INFO_8W, *PDRIVER_INFO_8W, *LPDRIVER_INFO_8W; + +typedef struct _DRIVER_INFO_8A { + DWORD cVersion; + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDriverPath; + LPSTR pDataFile; + LPSTR pConfigFile; + LPSTR pHelpFile; + LPSTR pDependentFiles; + LPSTR pMonitorName; + LPSTR pDefaultDataType; + LPSTR pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + LPSTR pszMfgName; + LPSTR pszOEMUrl; + LPSTR pszHardwareID; + LPSTR pszProvider; + LPSTR pszPrintProcessor; + LPSTR pszVendorSetup; + LPSTR pszzColorProfiles; + LPSTR pszInfPath; + DWORD dwPrinterDriverAttributes; + LPSTR pszzCoreDriverDependencies; + FILETIME ftMinInboxDriverVerDate; + DWORDLONG dwlMinInboxDriverVerVersion; +} DRIVER_INFO_8A, *PDRIVER_INFO_8A, *LPDRIVER_INFO_8A; + +typedef struct _FORM_INFO_2A { + DWORD Flags; + LPSTR pName; + SIZEL Size; + RECTL ImageableArea; + LPCSTR pKeyword; + DWORD StringType; + LPCSTR pMuiDll; + DWORD dwResourceId; + LPCSTR pDisplayName; + LANGID wLangId; +} FORM_INFO_2A, *PFORM_INFO_2A; + +typedef struct _FORM_INFO_2W { + DWORD Flags; + LPWSTR pName; + SIZEL Size; + RECTL ImageableArea; + LPCSTR pKeyword; + DWORD StringType; + LPCWSTR pMuiDll; + DWORD dwResourceId; + LPCWSTR pDisplayName; + LANGID wLangId; +} FORM_INFO_2W, *PFORM_INFO_2W; + +__MINGW_TYPEDEF_AW(DRIVER_INFO_8) +__MINGW_TYPEDEF_AW(PDRIVER_INFO_8) +__MINGW_TYPEDEF_AW(LPDRIVER_INFO_8) +__MINGW_TYPEDEF_AW(FORM_INFO_2) +__MINGW_TYPEDEF_AW(PFORM_INFO_2) + +typedef struct _PRINTPROCESSOR_CAPS_2 { + DWORD dwLevel; + DWORD dwNupOptions; + DWORD dwPageOrderFlags; + DWORD dwNumberOfCopies; + DWORD dwNupDirectionCaps; + DWORD dwNupBorderCaps; + DWORD dwBookletHandlingCaps; + DWORD dwDuplexHandlingCaps; + DWORD dwScalingCaps; +} PRINTPROCESSOR_CAPS_2, *PPRINTPROCESSOR_CAPS_2; + +HRESULT ReportJobProcessingProgress( + HANDLE printerHandle, + ULONG jobId, + EPrintXPSJobOperation jobOperation, + EPrintXPSJobProgress jobProgress +); + +typedef struct _CORE_PRINTER_DRIVERA { + GUID CoreDriverGUID; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + CHAR szPackageID[MAX_PATH]; +} CORE_PRINTER_DRIVERA, *PCORE_PRINTER_DRIVERA; + +typedef struct _CORE_PRINTER_DRIVERW { + GUID CoreDriverGUID; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + WCHAR szPackageID[MAX_PATH]; +} CORE_PRINTER_DRIVERW, *PCORE_PRINTER_DRIVERW; + +typedef struct _PRINTER_OPTIONS { + UINT cbSize; + DWORD dwFlags; +} PRINTER_OPTIONS, *PPRINTER_OPTIONS; + +__MINGW_TYPEDEF_AW(CORE_PRINTER_DRIVER) +__MINGW_TYPEDEF_AW(PCORE_PRINTER_DRIVER) +#define GetCorePrinterDrivers __MINGW_NAME_AW(GetCorePrinterDrivers) +#define GetPrinterDriver2 __MINGW_NAME_AW(GetPrinterDriver2) +#define GetPrinterDriverPackagePath __MINGW_NAME_AW(GetPrinterDriverPackagePath) +#define GetSpoolFileHandle __MINGW_NAME_AW(GetSpoolFileHandle) + +HRESULT WINAPI GetCorePrinterDriversA( + LPCSTR pszServer, + LPCSTR pszEnvironment, + LPCSTR pszzCoreDriverDependencies, + DWORD cCorePrinterDrivers, + PCORE_PRINTER_DRIVERA pCorePrinterDrivers +); + +HRESULT WINAPI GetCorePrinterDriversW( + LPCWSTR pszServer, + LPCWSTR pszEnvironment, + LPCWSTR pszzCoreDriverDependencies, + DWORD cCorePrinterDrivers, + PCORE_PRINTER_DRIVERW pCorePrinterDrivers +); + +/*Unsupported*/ +WINBOOL WINAPI GetPrinterDriver2A( + HWND hWnd, + HANDLE hPrinter, + LPSTR pEnvironment, + DWORD Level, + LPBYTE pDriverInfo, + DWORD cbBuf, + LPDWORD pcbNeeded +); + +WINBOOL WINAPI GetPrinterDriver2W( + HWND hWnd, + HANDLE hPrinter, + LPWSTR pEnvironment, + DWORD Level, + LPBYTE pDriverInfo, + DWORD cbBuf, + LPDWORD pcbNeeded +); + +HRESULT WINAPI GetPrinterDriverPackagePathA( + LPCSTR pszServer, + LPCSTR pszEnvironment, + LPCSTR pszLanguage, + LPCSTR pszPackageID, + LPSTR pszDriverPackageCab, + DWORD cchDriverPackageCab, + LPDWORD pcchRequiredSize +); + +HRESULT WINAPI GetPrinterDriverPackagePathW( + LPCWSTR pszServer, + LPCWSTR pszEnvironment, + LPCWSTR pszLanguage, + LPCWSTR pszPackageID, + LPWSTR pszDriverPackageCab, + DWORD cchDriverPackageCab, + LPDWORD pcchRequiredSize +); + +HANDLE WINAPI GetSpoolFileHandleA( + HANDLE hPrinter +); + +HANDLE WINAPI GetSpoolFileHandleW( + HANDLE hPrinter +); + +HANDLE WINAPI CommitSpoolData( + HANDLE hPrinter, + HANDLE hSpoolFile, + DWORD cbCommit +); + +WINBOOL WINAPI CloseSpoolFileHandle( + HANDLE hPrinter, + HANDLE hSpoolFile +); + +WINBOOL WINAPI OpenPrinter2A( + LPCSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTS pDefault, + PPRINTER_OPTIONS pOptions +); + +WINBOOL WINAPI OpenPrinter2W( + LPCWSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTS pDefault, + PPRINTER_OPTIONS pOptions +); + +#define OpenPrinter2 __MINGW_NAME_AW(OpenPrinter2) + +HRESULT WINAPI UploadPrinterDriverPackageA( + LPCSTR pszServer, + LPCSTR pszInfPath, + LPCSTR pszEnvironment, + DWORD dwFlags, + HWND hwnd, + LPSTR pszDestInfPath, + PULONG pcchDestInfPath +); + +HRESULT WINAPI UploadPrinterDriverPackageW( + LPCWSTR pszServer, + LPCWSTR pszInfPath, + LPCWSTR pszEnvironment, + DWORD dwFlags, + HWND hwnd, + LPWSTR pszDestInfPath, + PULONG pcchDestInfPath +); + +#define UploadPrinterDriverPackage __MINGW_NAME_AW(UploadPrinterDriverPackage) + +#endif /*(_WIN32_WINNT >= 0x0600)*/ + +#ifdef __cplusplus +} +#endif +#endif Index: sdk/include/reactos/idl/winspool.idl =================================================================== --- sdk/include/reactos/idl/winspool.idl (nonexistent) +++ sdk/include/reactos/idl/winspool.idl (working copy) @@ -0,0 +1,1594 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: This file is in the public domain + * PURPOSE: WIDL-compatible interface definition for the Spooler API + * AUTHORS: Colin Finck + */ + +#include + +/* + * Handle definitions + */ +typedef [context_handle] void* WINSPOOL_GDI_HANDLE; +typedef [context_handle] void* WINSPOOL_PRINTER_HANDLE; +typedef [handle, string] WCHAR* WINSPOOL_HANDLE; + + +/* + * Type definitions and enumerations + */ +typedef WORD WINSPOOL_LANGID; + +typedef enum +{ + WINSPOOL_BIDI_NULL = 0, + WINSPOOL_BIDI_INT = 1, + WINSPOOL_BIDI_FLOAT = 2, + WINSPOOL_BIDI_BOOL = 3, + WINSPOOL_BIDI_STRING = 4, + WINSPOOL_BIDI_TEXT = 5, + WINSPOOL_BIDI_ENUM = 6, + WINSPOOL_BIDI_BLOB = 7 +} +WINSPOOL_BIDI_TYPE; + +typedef enum +{ + WINSPOOL_TABLE_DWORD = 1, + WINSPOOL_TABLE_STRING = 2, + WINSPOOL_TABLE_DEVMODE = 3, + WINSPOOL_TABLE_TIME = 4, + WINSPOOL_TABLE_SECURITYDESCRIPTOR = 5 +} +WINSPOOL_TABLE_TYPE; + + +/* + * Various definitions + */ +typedef struct _WINSPOOL_RECTL +{ + LONG left; + LONG top; + LONG right; + LONG bottom; +} +WINSPOOL_RECTL; + +typedef struct _WINSPOOL_SIZEL +{ + LONG cx; + LONG cy; +} +WINSPOOL_SIZEL; + + +/* + * INFO structures + */ +typedef struct _WINSPOOL_DOC_INFO_1 { + [string] WCHAR* pDocName; + [string] WCHAR* pOutputFile; + [string] WCHAR* pDatatype; +} +WINSPOOL_DOC_INFO_1; + +typedef struct _WINSPOOL_DRIVER_INFO_1 +{ + [string] WCHAR* pName; +} +WINSPOOL_DRIVER_INFO_1; + +typedef struct _WINSPOOL_DRIVER_INFO_2 +{ + DWORD cVersion; + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDriverPath; + [string] WCHAR* pDataFile; + [string] WCHAR* pConfigFile; +} +WINSPOOL_DRIVER_INFO_2; + +typedef struct _WINSPOOL_DRIVER_INFO_3 +{ + DWORD cVersion; + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDriverPath; + [string] WCHAR* pDataFile; + [string] WCHAR* pConfigFile; + [string] WCHAR* pHelpFile; + [string] WCHAR* pMonitorName; + [string] WCHAR* pDefaultDataType; + DWORD cchDependentFiles; + [size_is(cchDependentFiles), unique] WCHAR* pDependentFiles; +} +WINSPOOL_DRIVER_INFO_3; + +typedef struct _WINSPOOL_DRIVER_INFO_4 +{ + DWORD cVersion; + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDriverPath; + [string] WCHAR* pDataFile; + [string] WCHAR* pConfigFile; + [string] WCHAR* pHelpFile; + [string] WCHAR* pMonitorName; + [string] WCHAR* pDefaultDataType; + DWORD cchDependentFiles; + [size_is(cchDependentFiles), unique] WCHAR* pDependentFiles; + DWORD cchPreviousNames; + [size_is(cchPreviousNames), unique] WCHAR* pszzPreviousNames; +} +WINSPOOL_DRIVER_INFO_4; + +typedef struct _WINSPOOL_DRIVER_INFO_6 +{ + DWORD cVersion; + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDriverPath; + [string] WCHAR* pDataFile; + [string] WCHAR* pConfigFile; + [string] WCHAR* pHelpFile; + [string] WCHAR* pMonitorName; + [string] WCHAR* pDefaultDataType; + DWORD cchDependentFiles; + [size_is(cchDependentFiles), unique] WCHAR* pDependentFiles; + DWORD cchPreviousNames; + [size_is(cchPreviousNames), unique] WCHAR* pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + [string] WCHAR* pMfgName; + [string] WCHAR* pOEMUrl; + [string] WCHAR* pHardwareID; + [string] WCHAR* pProvider; +} +WINSPOOL_DRIVER_INFO_6; + +typedef struct _WINSPOOL_DRIVER_INFO_8 +{ + DWORD cVersion; + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDriverPath; + [string] WCHAR* pDataFile; + [string] WCHAR* pConfigFile; + [string] WCHAR* pHelpFile; + [string] WCHAR* pMonitorName; + [string] WCHAR* pDefaultDataType; + DWORD cchDependentFiles; + [size_is(cchDependentFiles), unique] WCHAR* pDependentFiles; + DWORD cchPreviousNames; + [size_is(cchPreviousNames), unique] WCHAR* pszzPreviousNames; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + [string] WCHAR* pMfgName; + [string] WCHAR* pOEMUrl; + [string] WCHAR* pHardwareID; + [string] WCHAR* pProvider; + [string] WCHAR* pPrintProcessor; + [string] WCHAR* pVendorSetup; + DWORD cchColorProfiles; + [size_is(cchColorProfiles), unique] WCHAR* pszzColorProfiles; + [string] WCHAR* pInfPath; + DWORD dwPrinterDriverAttributes; + DWORD cchCoreDependencies; + [size_is(cchCoreDependencies), unique] WCHAR* pszzCoreDriverDependencies; + FILETIME ftMinInboxDriverVerDate; + DWORDLONG dwlMinInboxDriverVerVersion; +} +WINSPOOL_DRIVER_INFO_8; + +typedef struct _WINSPOOL_FORM_INFO_1 +{ + DWORD Flags; + [string] WCHAR* pName; + WINSPOOL_SIZEL Size; + WINSPOOL_RECTL ImageableArea; +} +WINSPOOL_FORM_INFO_1; + +typedef struct _WINSPOOL_FORM_INFO_2 +{ + DWORD Flags; + [string, unique] const WCHAR* pName; + WINSPOOL_SIZEL Size; + WINSPOOL_RECTL ImageableArea; + [string, unique] const WCHAR* pKeyword; + DWORD StringType; + [string, unique] const WCHAR* pMuiDll; + DWORD dwResourceId; + [string, unique] const WCHAR* pDisplayName; + WINSPOOL_LANGID wLangID; +} +WINSPOOL_FORM_INFO_2; + +typedef struct _WINSPOOL_JOB_INFO_1 +{ + DWORD JobId; + [string] WCHAR* pPrinterName; + [string] WCHAR* pMachineName; + [string] WCHAR* pUserName; + [string] WCHAR* pDocument; + [string] WCHAR* pDatatype; + [string] WCHAR* pStatus; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD TotalPages; + DWORD PagesPrinted; + SYSTEMTIME Submitted; +} +WINSPOOL_JOB_INFO_1; + +typedef struct _WINSPOOL_JOB_INFO_2 +{ + DWORD JobId; + [string] WCHAR* pPrinterName; + [string] WCHAR* pMachineName; + [string] WCHAR* pUserName; + [string] WCHAR* pDocument; + [string] WCHAR* pNotifyName; + [string] WCHAR* pDatatype; + [string] WCHAR* pPrintProcessor; + [string] WCHAR* pParameters; + [string] WCHAR* pDriverName; + ULONG_PTR pDevMode; + [string] WCHAR* pStatus; + ULONG_PTR pSecurityDescriptor; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD StartTime; + DWORD UntilTime; + DWORD TotalPages; + DWORD Size; + SYSTEMTIME Submitted; + DWORD Time; + DWORD PagesPrinted; +} +WINSPOOL_JOB_INFO_2; + +typedef struct _WINSPOOL_JOB_INFO_3 +{ + DWORD JobId; + DWORD NextJobId; + DWORD Reserved; +} +WINSPOOL_JOB_INFO_3; + +typedef struct _WINSPOOL_JOB_INFO_4 +{ + DWORD JobId; + [string] WCHAR* pPrinterName; + [string] WCHAR* pMachineName; + [string] WCHAR* pUserName; + [string] WCHAR* pDocument; + [string] WCHAR* pNotifyName; + [string] WCHAR* pDatatype; + [string] WCHAR* pPrintProcessor; + [string] WCHAR* pParameters; + [string] WCHAR* pDriverName; + ULONG_PTR pDevMode; + [string] WCHAR* pStatus; + ULONG_PTR pSecurityDescriptor; + DWORD Status; + DWORD Priority; + DWORD Position; + DWORD StartTime; + DWORD UntilTime; + DWORD TotalPages; + DWORD Size; + SYSTEMTIME Submitted; + DWORD Time; + DWORD PagesPrinted; + LONG SizeHigh; +} +WINSPOOL_JOB_INFO_4; + +typedef struct _WINSPOOL_MONITOR_INFO_1 +{ + [string] WCHAR* pName; +} +WINSPOOL_MONITOR_INFO_1; + +typedef struct _WINSPOOL_MONITOR_INFO_2 +{ + [string] WCHAR* pName; + [string] WCHAR* pEnvironment; + [string] WCHAR* pDLLName; +} +WINSPOOL_MONITOR_INFO_2; + +typedef struct _WINSPOOL_PORT_INFO_1 +{ + [string] WCHAR* pPortName; +} +WINSPOOL_PORT_INFO_1; + +typedef struct _WINSPOOL_PORT_INFO_2 +{ + [string] WCHAR* pPortName; + [string] WCHAR* pMonitorName; + [string] WCHAR* pDescription; + DWORD fPortType; + DWORD Reserved; +} +WINSPOOL_PORT_INFO_2; + +typedef struct _WINSPOOL_PORT_INFO_3 +{ + DWORD dwStatus; + [string] WCHAR* pszStatus; + DWORD dwSeverity; +} +WINSPOOL_PORT_INFO_3; + +typedef struct _WINSPOOL_PORT_INFO_FF +{ + [string] WCHAR* pPortName; + DWORD cbMonitorData; + BYTE* pMonitorData; +} +WINSPOOL_PORT_INFO_FF; + +typedef struct _WINSPOOL_PRINTER_INFO_STRESS { + [string] WCHAR* pPrinterName; + [string] WCHAR* pServerName; + DWORD cJobs; + DWORD cTotalJobs; + DWORD cTotalBytes; + SYSTEMTIME stUpTime; + DWORD MaxcRef; + DWORD cTotalPagesPrinted; + DWORD dwGetVersion; + DWORD fFreeBuild; + DWORD cSpooling; + DWORD cMaxSpooling; + DWORD cRef; + DWORD cErrorOutOfPaper; + DWORD cErrorNotReady; + DWORD cJobError; + DWORD dwNumberOfProcessors; + DWORD dwProcessorType; + DWORD dwHighPartTotalBytes; + DWORD cChangeID; + DWORD dwLastError; + DWORD Status; + DWORD cEnumerateNetworkPrinters; + DWORD cAddNetPrinters; + USHORT wProcessorArchitecture; + USHORT wProcessorLevel; + DWORD cRefIC; + DWORD dwReserved2; + DWORD dwReserved3; +} +WINSPOOL_PRINTER_INFO_STRESS; + +typedef struct _WINSPOOL_PRINTER_INFO_1 +{ + DWORD Flags; + [string] WCHAR* pDescription; + [string] WCHAR* pName; + [string] WCHAR* pComment; +} +WINSPOOL_PRINTER_INFO_1; + +typedef struct _WINSPOOL_PRINTER_INFO_2 +{ + [string] WCHAR* pServerName; + [string] WCHAR* pPrinterName; + [string] WCHAR* pShareName; + [string] WCHAR* pPortName; + [string] WCHAR* pDriverName; + [string] WCHAR* pComment; + [string] WCHAR* pLocation; + ULONG_PTR pDevMode; + [string] WCHAR* pSepFile; + [string] WCHAR* pPrintProcessor; + [string] WCHAR* pDatatype; + [string] WCHAR* pParameters; + ULONG_PTR pSecurityDescriptor; + DWORD Attributes; + DWORD Priority; + DWORD DefaultPriority; + DWORD StartTime; + DWORD UntilTime; + DWORD Status; + DWORD cJobs; + DWORD AveragePPM; +} +WINSPOOL_PRINTER_INFO_2; + +typedef struct _WINSPOOL_PRINTER_INFO_3 +{ + ULONG_PTR pSecurityDescriptor; +} +WINSPOOL_PRINTER_INFO_3; + +typedef struct _WINSPOOL_PRINTER_INFO_4 +{ + [string] WCHAR* pPrinterName; + [string] WCHAR* pServerName; + DWORD Attributes; +} +WINSPOOL_PRINTER_INFO_4; + +typedef struct _WINSPOOL_PRINTER_INFO_5 +{ + [string] WCHAR* pPrinterName; + [string] WCHAR* pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; +} +WINSPOOL_PRINTER_INFO_5; + +typedef struct _WINSPOOL_PRINTER_INFO_6 +{ + DWORD dwStatus; +} +WINSPOOL_PRINTER_INFO_6; + +typedef struct _WINSPOOL_PRINTER_INFO_7 +{ + [string] WCHAR* pszObjectGUID; + DWORD dwAction; +} +WINSPOOL_PRINTER_INFO_7; + +typedef struct _WINSPOOL_PRINTER_INFO_8 +{ + ULONG_PTR pDevMode; +} +WINSPOOL_PRINTER_INFO_8; + +typedef struct _WINSPOOL_PRINTER_INFO_9 +{ + ULONG_PTR pDevMode; +} +WINSPOOL_PRINTER_INFO_9; + +typedef struct _WINSPOOL_PROVIDOR_INFO_1 +{ + WCHAR* pName; + WCHAR* pEnvironment; + WCHAR* pDLLName; +} +WINSPOOL_PROVIDOR_INFO_1; + +typedef struct _WINSPOOL_PROVIDOR_INFO_2 +{ + WCHAR* pOrder; +} +WINSPOOL_PROVIDOR_INFO_2; + +typedef struct _WINSPOOL_SPLCLIENT_INFO_1 +{ + DWORD dwSize; + [string] WCHAR* pMachineName; + [string] WCHAR* pUserName; + DWORD dwBuildNum; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + USHORT wProcessorArchitecture; +} +WINSPOOL_SPLCLIENT_INFO_1; + +typedef struct _WINSPOOL_SPLCLIENT_INFO_2 +{ + LONG_PTR notUsed; +} +WINSPOOL_SPLCLIENT_INFO_2; + +typedef struct _WINSPOOL_SPLCLIENT_INFO_3 +{ + UINT cbSize; + DWORD dwFlags; + DWORD dwSize; + [string] WCHAR* pMachineName; + [string] WCHAR* pUserName; + DWORD dwBuildNum; + DWORD dwMajorVersion; + DWORD dwMinorVersion; + USHORT wProcessorArchitecture; + UINT64 hSplPrinter; +} +WINSPOOL_SPLCLIENT_INFO_3; + + +/* + * CONTAINER structures + */ +typedef struct _WINSPOOL_BINARY_CONTAINER +{ + DWORD cbBuf; + [size_is(cbBuf), unique] BYTE* pszString; +} +WINSPOOL_BINARY_CONTAINER; + +typedef struct _WINSPOOL_BIDI_DATA +{ + DWORD dwBidiType; + + [switch_is(dwBidiType)] union + { + [case(WINSPOOL_BIDI_NULL, WINSPOOL_BIDI_BOOL)] + INT bData; + [case(WINSPOOL_BIDI_INT)] + LONG iData; + [case(WINSPOOL_BIDI_STRING, WINSPOOL_BIDI_TEXT, WINSPOOL_BIDI_ENUM)] + [string, unique] WCHAR* sData; + [case(WINSPOOL_BIDI_FLOAT)] + FLOAT fData; + [case(WINSPOOL_BIDI_BLOB)] + WINSPOOL_BINARY_CONTAINER biData; + } + u; +} +WINSPOOL_BIDI_DATA; + +typedef struct _WINSPOOL_BIDI_REQUEST_DATA +{ + DWORD dwReqNumber; + [string, unique] WCHAR* pSchema; + WINSPOOL_BIDI_DATA data; +} +WINSPOOL_BIDI_REQUEST_DATA; + +typedef struct _WINSPOOL_BIDI_RESPONSE_DATA +{ + DWORD dwResult; + DWORD dwReqNumber; + [string, unique] WCHAR* pSchema; + WINSPOOL_BIDI_DATA data; +} +WINSPOOL_BIDI_RESPONSE_DATA; + +typedef struct _WINSPOOL_BIDI_REQUEST_CONTAINER +{ + DWORD Version; + DWORD Flags; + DWORD Count; + [size_is(Count), unique] WINSPOOL_BIDI_REQUEST_DATA aData[]; +} +WINSPOOL_BIDI_REQUEST_CONTAINER; + +typedef struct _WINSPOOL_BIDI_RESPONSE_CONTAINER +{ + DWORD Version; + DWORD Flags; + DWORD Count; + [size_is(Count), unique] WINSPOOL_BIDI_RESPONSE_DATA aData[]; +} +WINSPOOL_BIDI_RESPONSE_CONTAINER; + +typedef struct _WINSPOOL_DOC_INFO_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_DOC_INFO_1* pDocInfo1; + } + DocInfo; +} +WINSPOOL_DOC_INFO_CONTAINER; + +typedef struct _WINSPOOL_DEVMODE_CONTAINER +{ + DWORD cbBuf; + [size_is(cbBuf), unique] BYTE* pDevMode; +} +WINSPOOL_DEVMODE_CONTAINER; + +typedef struct _WINSPOOL_DRIVER_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_DRIVER_INFO_1* pNotUsed; + [case(2)] + WINSPOOL_DRIVER_INFO_2* Level2; + [case(3)] + WINSPOOL_DRIVER_INFO_3* Level3; + [case(4)] + WINSPOOL_DRIVER_INFO_4* Level4; + [case(6)] + WINSPOOL_DRIVER_INFO_6* Level6; + [case(8)] + WINSPOOL_DRIVER_INFO_8* Level8; + } + DriverInfo; +} +WINSPOOL_DRIVER_CONTAINER; + +typedef struct _WINSPOOL_FORM_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_FORM_INFO_1* pFormInfo1; + [case(2)] + WINSPOOL_FORM_INFO_2* pFormInfo2; + } + FormInfo; +} +WINSPOOL_FORM_CONTAINER; + +typedef struct _WINSPOOL_JOB_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_JOB_INFO_1* Level1; + [case(2)] + WINSPOOL_JOB_INFO_2* Level2; + [case(3)] + WINSPOOL_JOB_INFO_3* Level3; + [case(4)] + WINSPOOL_JOB_INFO_4* Level4; + } + JobInfo; +} +WINSPOOL_JOB_CONTAINER; + +typedef struct _WINSPOOL_MONITOR_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_MONITOR_INFO_1* pMonitorInfo1; + [case(2)] + WINSPOOL_MONITOR_INFO_2* pMonitorInfo2; + } + MonitorInfo; +} +WINSPOOL_MONITOR_CONTAINER; + +typedef struct _WINSPOOL_PORT_CONTAINER +{ + DWORD Level; + + [switch_is(0x00FFFFFF & Level)] + union + { + [case(1)] + WINSPOOL_PORT_INFO_1* pPortInfo1; + [case(2)] + WINSPOOL_PORT_INFO_2* pPortInfo2; + [case(3)] + WINSPOOL_PORT_INFO_3* pPortInfo3; + [case(0x00FFFFFF)] + WINSPOOL_PORT_INFO_FF* pPortInfoFF; + } + PortInfo; +} +WINSPOOL_PORT_CONTAINER; + +typedef struct _WINSPOOL_PORT_VAR_CONTAINER +{ + DWORD cbMonitorData; + [size_is(cbMonitorData), unique] BYTE* pMonitorData; +} +WINSPOOL_PORT_VAR_CONTAINER; + +typedef struct _WINSPOOL_PRINTER_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(0)] + WINSPOOL_PRINTER_INFO_STRESS* pPrinterInfoStress; + [case(1)] + WINSPOOL_PRINTER_INFO_1* pPrinterInfo1; + [case(2)] + WINSPOOL_PRINTER_INFO_2* pPrinterInfo2; + [case(3)] + WINSPOOL_PRINTER_INFO_3* pPrinterInfo3; + [case(4)] + WINSPOOL_PRINTER_INFO_4* pPrinterInfo4; + [case(5)] + WINSPOOL_PRINTER_INFO_5* pPrinterInfo5; + [case(6)] + WINSPOOL_PRINTER_INFO_6* pPrinterInfo6; + [case(7)] + WINSPOOL_PRINTER_INFO_7* pPrinterInfo7; + [case(8)] + WINSPOOL_PRINTER_INFO_8* pPrinterInfo8; + [case(9)] + WINSPOOL_PRINTER_INFO_9* pPrinterInfo9; + } + PrinterInfo; +} +WINSPOOL_PRINTER_CONTAINER; + +typedef struct _WINSPOOL_PROVIDOR_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_PROVIDOR_INFO_1* pProvidorInfo1; + [case(2)] + WINSPOOL_PROVIDOR_INFO_2* pProvidorInfo2; + } + ProvidorInfo; +} +WINSPOOL_PROVIDOR_CONTAINER; + +typedef struct _WINSPOOL_SECURITY_CONTAINER +{ + DWORD cbBuf; + [size_is(cbBuf), unique] BYTE* pSecurity; +} +WINSPOOL_SECURITY_CONTAINER; + +typedef struct _WINSPOOL_SPLCLIENT_CONTAINER +{ + DWORD Level; + + [switch_is(Level)] union + { + [case(1)] + WINSPOOL_SPLCLIENT_INFO_1* pClientInfo1; + [case(2)] + WINSPOOL_SPLCLIENT_INFO_2* pNotUsed1; + [case(3)] + WINSPOOL_SPLCLIENT_INFO_3* pNotUsed2; + } + ClientInfo; +} +WINSPOOL_SPLCLIENT_CONTAINER; + +typedef struct _WINSPOOL_STRING_CONTAINER +{ + DWORD cbBuf; + [size_is(cbBuf / 2), unique] WCHAR* pszString; +} +WINSPOOL_STRING_CONTAINER; + +typedef struct _WINSPOOL_SYSTEMTIME_CONTAINER { + DWORD cbBuf; + SYSTEMTIME* pSystemTime; +} +WINSPOOL_SYSTEMTIME_CONTAINER; + + +/* + * Various definitions + */ +typedef struct _WINSPOOL_V2_NOTIFY_OPTIONS_TYPE +{ + USHORT Type; + USHORT Reserved0; + DWORD Reserved1; + DWORD Reserved2; + DWORD Count; + [size_is(Count), unique] USHORT* pFields; +} +WINSPOOL_V2_NOTIFY_OPTIONS_TYPE; + +typedef struct _WINSPOOL_V2_NOTIFY_OPTIONS +{ + DWORD Version; + DWORD Reserved; + DWORD Count; + [size_is(Count), unique] WINSPOOL_V2_NOTIFY_OPTIONS_TYPE* pTypes; +} +WINSPOOL_V2_NOTIFY_OPTIONS; + +typedef [switch_type(DWORD)] union _WINSPOOL_V2_NOTIFY_INFO_DATA_DATA +{ + [case(WINSPOOL_TABLE_STRING)] + WINSPOOL_STRING_CONTAINER String; + [case(WINSPOOL_TABLE_DWORD)] + DWORD dwData[2]; + [case(WINSPOOL_TABLE_TIME)] + WINSPOOL_SYSTEMTIME_CONTAINER SystemTime; + [case(WINSPOOL_TABLE_DEVMODE)] + WINSPOOL_DEVMODE_CONTAINER DevMode; + [case(WINSPOOL_TABLE_SECURITYDESCRIPTOR)] + WINSPOOL_SECURITY_CONTAINER SecurityDescriptor; +} +WINSPOOL_V2_NOTIFY_INFO_DATA_DATA; + +typedef struct _WINSPOOL_V2_NOTIFY_INFO_DATA +{ + USHORT Type; + USHORT Field; + DWORD Reserved; + DWORD Id; + [switch_is(Reserved & 0xffff)] WINSPOOL_V2_NOTIFY_INFO_DATA_DATA Data; +} +WINSPOOL_V2_NOTIFY_INFO_DATA; + +typedef struct _WINSPOOL_V2_NOTIFY_INFO +{ + DWORD Version; + DWORD Flags; + DWORD Count; + [size_is(Count), unique] WINSPOOL_V2_NOTIFY_INFO_DATA aData[]; +} +WINSPOOL_V2_NOTIFY_INFO; + +typedef [switch_type(DWORD)] union _WINSPOOL_V2_UREPLY_PRINTER +{ + [case(0)] + WINSPOOL_V2_NOTIFY_INFO* pInfo; +} +WINSPOOL_V2_UREPLY_PRINTER; + + +/* + * The actual interface + */ +[ + uuid(12345678-1234-ABCD-EF00-0123456789AB), + version(1.0), + endpoint("ncalrpc:[spoolss]", "ncacn_np:[\\pipe\\spoolss]"), + pointer_default(unique) +] + +interface winspool { + /* Function 0x00 */ + DWORD _RpcEnumPrinters( + [in] DWORD Flags, + [in, unique] WINSPOOL_HANDLE Name, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPrinterEnum, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x01 */ + DWORD _RpcOpenPrinter( + [in, unique] WINSPOOL_HANDLE pPrinterName, + [out] WINSPOOL_PRINTER_HANDLE* phPrinter, + [in, string, unique] WCHAR* pDatatype, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, + [in] DWORD AccessRequired + ); + + /* Function 0x02 */ + DWORD _RpcSetJob( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD JobId, + [in, unique] WINSPOOL_JOB_CONTAINER* pJobContainer, + [in] DWORD Command + ); + + /* Function 0x03 */ + DWORD _RpcGetJob( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD JobId, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pJob, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x04 */ + DWORD _RpcEnumJobs( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD FirstJob, + [in] DWORD NoJobs, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pJob, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x05 */ + DWORD _RpcAddPrinter( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, + [in] WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, + [out] WINSPOOL_PRINTER_HANDLE* pHandle + ); + + /* Function 0x06 */ + DWORD _RpcDeletePrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter + ); + + /* Function 0x07 */ + DWORD _RpcSetPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, + [in] WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, + [in] DWORD Command + ); + + /* Function 0x08 */ + DWORD _RpcGetPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPrinter, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x09 */ + DWORD _RpcAddPrinterDriver( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_DRIVER_CONTAINER* pDriverContainer + ); + + /* Function 0x0A */ + DWORD _RpcEnumPrinterDrivers( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pDrivers, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x0B */ + DWORD _RpcGetPrinterDriver( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pDriver, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x0C */ + DWORD _RpcGetPrinterDriverDirectory( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pDriverDirectory, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x0D */ + DWORD _RpcDeletePrinterDriver( + [in, unique] WINSPOOL_HANDLE pName, + [in, string] WCHAR* pEnvironment, + [in, string] WCHAR* pDriverName + ); + + /* Function 0x0E */ + DWORD _RpcAddPrintProcessor( + [in, unique] WINSPOOL_HANDLE pName, + [in, string] WCHAR* pEnvironment, + [in, string] WCHAR* pPathName, + [in, string] WCHAR* pPrintProcessorName + ); + + /* Function 0x0F */ + DWORD _RpcEnumPrintProcessors( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPrintProcessorInfo, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x10 */ + DWORD _RpcGetPrintProcessorDirectory( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPrintProcessorDirectory, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x11 */ + DWORD _RpcStartDocPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] WINSPOOL_DOC_INFO_CONTAINER* pDocInfoContainer, + [out] DWORD* pJobId + ); + + /* Function 0x12 */ + DWORD _RpcStartPagePrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter + ); + + /* Function 0x13 */ + DWORD _RpcWritePrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, size_is(cbBuf)] BYTE* pBuf, + [in] DWORD cbBuf, + [out] DWORD* pcWritten + ); + + /* Function 0x14 */ + DWORD _RpcEndPagePrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter + ); + + /* Function 0x15 */ + DWORD _RpcAbortPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter + ); + + /* Function 0x16 */ + DWORD _RpcReadPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [out, size_is(cbBuf)] BYTE* pBuf, + [in] DWORD cbBuf, + [out] DWORD* pcNoBytesRead + ); + + /* Function 0x17 */ + DWORD _RpcEndDocPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter + ); + + /* Function 0x18 */ + DWORD _RpcAddJob( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pAddJob, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x19 */ + DWORD _RpcScheduleJob( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD JobId + ); + + /* Function 0x1A */ + DWORD _RpcGetPrinterData( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pValueName, + [out] DWORD* pType, + [out, size_is(nSize)] BYTE* pData, + [in] DWORD nSize, + [out] DWORD* pcbNeeded + ); + + /* Function 0x1B */ + DWORD _RpcSetPrinterData( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pValueName, + [in] DWORD Type, + [in, size_is(cbData)] BYTE* pData, + [in] DWORD cbData + ); + + /* Function 0x1C */ + DWORD _RpcWaitForPrinterChange( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD Flags, + [out] DWORD* pFlags + ); + + /* Function 0x1D */ + DWORD _RpcClosePrinter( + [in, out] WINSPOOL_PRINTER_HANDLE* phPrinter + ); + + /* Function 0x1E */ + DWORD _RpcAddForm( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] WINSPOOL_FORM_CONTAINER* pFormInfoContainer + ); + + /* Function 0x1F */ + DWORD _RpcDeleteForm( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pFormName + ); + + /* Function 0x20 */ + DWORD _RpcGetForm( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pFormName, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pForm, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded + ); + + /* Function 0x21 */ + DWORD _RpcSetForm( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pFormName, + [in] WINSPOOL_FORM_CONTAINER* pFormInfoContainer + ); + + /* Function 0x22 */ + DWORD _RpcEnumForms( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pForm, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x23 */ + DWORD _RpcEnumPorts( + [in, unique] WINSPOOL_HANDLE pName, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPort, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x24 */ + DWORD _RpcEnumMonitors( + [in, unique] WINSPOOL_HANDLE pName, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pMonitor, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x25 */ + DWORD _RpcAddPort( + [in, unique] WINSPOOL_HANDLE pName, + [in] ULONG_PTR hWnd, + [in] WCHAR* pMonitorName + ); + + /* Function 0x26 */ + DWORD _RpcConfigurePort( + [in, unique] WINSPOOL_HANDLE pName, + [in] ULONG_PTR hWnd, + [in] WCHAR* pPortName + ); + + /* Function 0x27 */ + DWORD _RpcDeletePort( + [in, unique] WINSPOOL_HANDLE pName, + [in] ULONG_PTR hWnd, + [in, string] WCHAR* pPortName + ); + + /* Function 0x28 */ + DWORD _RpcCreatePrinterIC( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [out] WINSPOOL_GDI_HANDLE* pHandle, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer + ); + + /* Function 0x29 */ + DWORD _RpcPlayGdiScriptOnPrinterIC( + [in] WINSPOOL_GDI_HANDLE hPrinterIC, + [in, size_is(cIn)] BYTE* pIn, + [in] DWORD cIn, + [out, size_is(cOut)] BYTE* pOut, + [in] DWORD cOut, + [in] DWORD ul + ); + + /* Function 0x2A */ + DWORD _RpcDeletePrinterIC( + [in, out] WINSPOOL_GDI_HANDLE* phPrinterIC + ); + + /* Function 0x2B */ + DWORD _RpcAddPrinterConnection( + [in, unique] WINSPOOL_HANDLE pName + ); + + /* Function 0x2C */ + DWORD _RpcDeletePrinterConnection( + [in, unique] WINSPOOL_HANDLE pName + ); + + /* Function 0x2D */ + DWORD _RpcPrinterMessageBox( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD Error, + [in] ULONG_PTR hWnd, + [in, string] WCHAR* pText, + [in, string] WCHAR* pCaption, + [in] DWORD dwType + ); + + /* Function 0x2E */ + DWORD _RpcAddMonitor( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_MONITOR_CONTAINER* pMonitorContainer + ); + + /* Function 0x2F */ + DWORD _RpcDeleteMonitor( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in, string] WCHAR* pMonitorName + ); + + /* Function 0x30 */ + DWORD _RpcDeletePrintProcessor( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in, string] WCHAR* pPrintProcessorName + ); + + /* Function 0x31 */ + DWORD _RpcAddPrintProvidor( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_PROVIDOR_CONTAINER* pProvidorContainer + ); + + /* Function 0x32 */ + DWORD _RpcDeletePrintProvidor( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pEnvironment, + [in, string] WCHAR* pPrintProviderName + ); + + /* Function 0x33 */ + DWORD _RpcEnumPrintProcessorDatatypes( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pPrintProcessorName, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pDatatypes, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x34 */ + DWORD _RpcResetPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string, unique] WCHAR* pDatatype, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer + ); + + /* Function 0x35 */ + DWORD _RpcGetPrinterDriver2( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string, unique] WCHAR* pEnvironment, + [in] DWORD Level, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pDriver, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [in] DWORD dwClientMajorVersion, + [in] DWORD dwClientMinorVersion, + [out] DWORD* pdwServerMaxVersion, + [out] DWORD* pdwServerMinVersion + ); + + /* Function 0x36 (TODO) */ + DWORD _RpcClientFindFirstPrinterChangeNotification( + /* TODO */ + ); + + /* Function 0x37 (TODO) */ + DWORD _RpcFindNextPrinterChangeNotification( + /* TODO */ + ); + + /* Function 0x38 (TODO) */ + DWORD _RpcFindClosePrinterChangeNotification( + /* TODO */ + ); + + /* Function 0x39 (TODO) */ + DWORD _RpcRouterFindFirstPrinterChangeNotificationOld( + /* TODO */ + ); + + /* Function 0x3A */ + DWORD _RpcReplyOpenPrinter( + [in] WINSPOOL_HANDLE pMachine, + [out] WINSPOOL_PRINTER_HANDLE* phPrinterNotify, + [in] DWORD dwPrinterRemote, + [in] DWORD dwType, + [in, range(0, 512)] DWORD cbBuffer, + [in, unique, size_is(cbBuffer), disable_consistency_check] BYTE* pBuffer + ); + + /* Function 0x3B */ + DWORD _RpcRouterReplyPrinter( + [in] WINSPOOL_PRINTER_HANDLE hNotify, + [in] DWORD fdwFlags, + [in, range(0, 512)] DWORD cbBuffer, + [in, unique, size_is(cbBuffer), disable_consistency_check] BYTE* pBuffer + ); + + /* Function 0x3C */ + DWORD _RpcReplyClosePrinter( + [in, out] WINSPOOL_PRINTER_HANDLE* phNotify + ); + + /* Function 0x3D */ + DWORD _RpcAddPortEx( + [in] WINSPOOL_HANDLE pName, + [in] WINSPOOL_PORT_CONTAINER* pPortContainer, + [in] WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer, + [in, string] WCHAR* pMonitorName + ); + + /* Function 0x3E */ + DWORD _RpcRemoteFindFirstPrinterChangeNotification( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD fdwFlags, + [in] DWORD fdwOptions, + [in, string, unique] WCHAR* pszLocalMachine, + [in] DWORD dwPrinterLocal, + [in, range(0, 512)] DWORD cbBuffer, + [in, out, unique, size_is(cbBuffer), disable_consistency_check] BYTE* pBuffer + ); + + /* Function 0x3F */ + DWORD _RpcSpoolerInit(); + + /* Function 0x40 (TODO) */ + DWORD _RpcResetPrinterEx( + /* TODO */ + ); + + /* Function 0x41 */ + DWORD _RpcRemoteFindFirstPrinterChangeNotificationEx( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD fdwFlags, + [in] DWORD fdwOptions, + [in, string, unique] WCHAR* pszLocalMachine, + [in] DWORD dwPrinterLocal, + [in, unique] WINSPOOL_V2_NOTIFY_OPTIONS* pOptions + ); + + /* Function 0x42 */ + DWORD _RpcRouterReplyPrinterEx( + [in] WINSPOOL_PRINTER_HANDLE hNotify, + [in] DWORD dwColor, + [in] DWORD fdwFlags, + [out] DWORD* pdwResult, + [in] DWORD dwReplyType, + [in, switch_is(dwReplyType)] WINSPOOL_V2_UREPLY_PRINTER Reply + ); + + /* Function 0x43 */ + DWORD _RpcRouterRefreshPrinterChangeNotification( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD dwColor, + [in, unique] WINSPOOL_V2_NOTIFY_OPTIONS* pOptions, + [out] WINSPOOL_V2_NOTIFY_INFO** ppInfo + ); + + /* Function 0x44 (TODO) */ + DWORD _RpcSetAllocFailCount( + /* TODO */ + ); + + /* Function 0x45 */ + DWORD _RpcOpenPrinterEx( + [in, unique] WINSPOOL_HANDLE pPrinterName, + [out] WINSPOOL_PRINTER_HANDLE* pHandle, + [in, string, unique] WCHAR* pDatatype, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, + [in] DWORD AccessRequired, + [in] WINSPOOL_SPLCLIENT_CONTAINER* pClientInfo + ); + + /* Function 0x46 */ + DWORD _RpcAddPrinterEx( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, + [in] WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, + [in] WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, + [in] WINSPOOL_SPLCLIENT_CONTAINER* pClientInfo, + [out] WINSPOOL_PRINTER_HANDLE* pHandle + ); + + /* Function 0x47 */ + DWORD _RpcSetPort( + [in, unique] WINSPOOL_HANDLE pName, + [in, string, unique] WCHAR* pPortName, + [in] WINSPOOL_PORT_CONTAINER* pPortContainer + ); + + /* Function 0x48 */ + DWORD _RpcEnumPrinterData( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in] DWORD dwIndex, + [out, size_is(cbValueName / sizeof(WCHAR))] WCHAR* pValueName, + [in] DWORD cbValueName, + [out] DWORD* pcbValueName, + [out] DWORD* pType, + [out, size_is(cbData)] BYTE* pData, + [in] DWORD cbData, + [out] DWORD* pcbData + ); + + /* Function 0x49 */ + DWORD _RpcDeletePrinterData( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] WCHAR* pValueName + ); + + /* Function 0x4A (TODO) */ + DWORD _RpcClusterSplOpen( + /* TODO */ + ); + + /* Function 0x4B (TODO) */ + DWORD _RpcClusterSplClose( + /* TODO */ + ); + + /* Function 0x4C (TODO) */ + DWORD _RpcClusterSplIsAlive( + /* TODO */ + ); + + /* Function 0x4D */ + DWORD _RpcSetPrinterDataEx( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName, + [in, string] const WCHAR* pValueName, + [in] DWORD Type, + [in, size_is(cbData)] BYTE* pData, + [in] DWORD cbData + ); + + /* Function 0x4E */ + DWORD _RpcGetPrinterDataEx( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName, + [in, string] const WCHAR* pValueName, + [out] DWORD* pType, + [out, size_is(nSize)] BYTE* pData, + [in] DWORD nSize, + [out] DWORD* pcbNeeded + ); + + /* Function 0x4F */ + DWORD _RpcEnumPrinterDataEx( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName, + [out, size_is(cbEnumValues)] BYTE* pEnumValues, + [in] DWORD cbEnumValues, + [out] DWORD* pcbEnumValues, + [out] DWORD* pnEnumValues + ); + + /* Function 0x50 */ + DWORD _RpcEnumPrinterKey( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName, + [out, size_is(cbSubkey / sizeof(WCHAR))] WCHAR* pSubkey, + [in] DWORD cbSubkey, + [out] DWORD* pcbSubkey + ); + + /* Function 0x51 */ + DWORD _RpcDeletePrinterDataEx( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName, + [in, string] const WCHAR* pValueName + ); + + /* Function 0x52 */ + DWORD _RpcDeletePrinterKey( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string] const WCHAR* pKeyName + ); + + /* Function 0x53 (TODO) */ + DWORD _RpcSeekPrinter( + /* TODO */ + ); + + /* Function 0x54 */ + DWORD _RpcDeletePrinterDriverEx( + [in, unique] WINSPOOL_HANDLE pName, + [in, string] WCHAR* pEnvironment, + [in, string] WCHAR* pDriverName, + [in] DWORD dwDeleteFlag, + [in] DWORD dwVersionNum + ); + + /* Function 0x55 */ + DWORD _RpcAddPerMachineConnection( + [in, unique] WINSPOOL_HANDLE pServer, + [in, string] const WCHAR* pPrinterName, + [in, string] const WCHAR* pPrintServer, + [in, string] const WCHAR* pProvider + ); + + /* Function 0x56 */ + DWORD _RpcDeletePerMachineConnection( + [in, unique] WINSPOOL_HANDLE pServer, + [in, string] const WCHAR* pPrinterName + ); + + /* Function 0x57 */ + DWORD _RpcEnumPerMachineConnections( + [in, unique] WINSPOOL_HANDLE pServer, + [in, out, unique, size_is(cbBuf), disable_consistency_check] BYTE* pPrinterEnum, + [in] DWORD cbBuf, + [out] DWORD* pcbNeeded, + [out] DWORD* pcReturned + ); + + /* Function 0x58 */ + DWORD _RpcXcvData( + [in] WINSPOOL_PRINTER_HANDLE hXcv, + [in, string] const WCHAR* pszDataName, + [in, size_is(cbInputData)] BYTE* pInputData, + [in] DWORD cbInputData, + [out, size_is(cbOutputData)] BYTE* pOutputData, + [in] DWORD cbOutputData, + [out] DWORD* pcbOutputNeeded, + [in, out] DWORD* pdwStatus + ); + + /* Function 0x59 */ + DWORD _RpcAddPrinterDriverEx( + [in, unique] WINSPOOL_HANDLE pName, + [in] WINSPOOL_DRIVER_CONTAINER* pDriverContainer, + [in] DWORD dwFileCopyFlags + ); + + /* Function 0x5A (TODO) */ + DWORD _RpcSplOpenPrinter( + /* TODO */ + ); + + /* Function 0x5B (TODO) */ + DWORD _RpcGetSpoolFileInfo( + /* TODO */ + ); + + /* Function 0x5C (TODO) */ + DWORD _RpcCommitSpoolData( + /* TODO */ + ); + + /* Function 0x5D (TODO) */ + DWORD _RpcCloseSpoolFileHandle( + /* TODO */ + ); + + /* Function 0x5E */ + DWORD _RpcFlushPrinter( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, size_is(cbBuf)] BYTE* pBuf, + [in] DWORD cbBuf, + [out] DWORD* pcWritten, + [in] DWORD cSleep + ); + + /* Function 0x5F */ + DWORD _RpcSendRecvBidiData( + [in] WINSPOOL_PRINTER_HANDLE hPrinter, + [in, string, unique] const WCHAR* pAction, + [in] WINSPOOL_BIDI_REQUEST_CONTAINER* pReqData, + [out] WINSPOOL_BIDI_RESPONSE_CONTAINER** ppRespData + ); + + /* Function 0x60 (TODO) */ + DWORD _RpcAddDriverCatalog( + /* TODO */ + ); +} Index: sdk/lib/CMakeLists.txt =================================================================== --- sdk/lib/CMakeLists.txt (revision 73027) +++ sdk/lib/CMakeLists.txt (working copy) @@ -41,6 +41,7 @@ add_subdirectory(rtl) add_subdirectory(scrnsave) +add_subdirectory(skiplist) add_subdirectory(strmiids) add_subdirectory(smlib) add_subdirectory(tdilib) Index: sdk/lib/skiplist/CMakeLists.txt =================================================================== --- sdk/lib/skiplist/CMakeLists.txt (nonexistent) +++ sdk/lib/skiplist/CMakeLists.txt (working copy) @@ -0,0 +1,11 @@ + +# The library +add_definitions(-DSKIPLIST_LEVELS=16) +add_library(skiplist16 skiplist.c) +add_dependencies(skiplist16 psdk) + +# The Test program +add_executable(skiplist_test skiplist_test.c) +target_link_libraries(skiplist_test skiplist16) +set_module_type(skiplist_test win32cui) +add_importlibs(skiplist_test msvcrt kernel32 ntdll) Index: sdk/lib/skiplist/skiplist.c =================================================================== --- sdk/lib/skiplist/skiplist.c (nonexistent) +++ sdk/lib/skiplist/skiplist.c (working copy) @@ -0,0 +1,440 @@ +/* + * PROJECT: Skiplist implementation for the ReactOS Project + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: All implemented functions operating on the Skiplist + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include +#include +#include +#include "skiplist.h" + +/** + * @name _GetRandomLevel + * + * Returns a random level for the next element to be inserted. + * This level is geometrically distributed for p = 0.5, so perfectly suitable for an efficient Skiplist implementation. + * + * @return + * A value between 0 and SKIPLIST_LEVELS - 1. + */ +static __inline CHAR +_GetRandomLevel() +{ + // Using a simple fixed seed and the Park-Miller Lehmer Minimal Standard Random Number Generator gives an acceptable distribution for our "random" levels. + static DWORD dwRandom = 1; + + DWORD dwLevel = 0; + DWORD dwShifted; + + // Generate 31 uniformly distributed pseudo-random bits using the Park-Miller Lehmer Minimal Standard Random Number Generator. + dwRandom = (DWORD)(((ULONGLONG)dwRandom * 48271UL) % 2147483647UL); + + // Shift out (31 - SKIPLIST_LEVELS) bits to the right to have no more than SKIPLIST_LEVELS bits set. + dwShifted = dwRandom >> (31 - SKIPLIST_LEVELS); + + // BitScanForward doesn't operate on a zero input value. + if (dwShifted) + { + // BitScanForward sets dwLevel to the zero-based position of the first set bit (from LSB to MSB). + // This makes dwLevel a geometrically distributed value between 0 and SKIPLIST_LEVELS - 1 for p = 0.5. + BitScanForward(&dwLevel, dwShifted); + } + + // dwLevel can't have a value higher than 30 this way, so a CHAR is more than enough. + return (CHAR)dwLevel; +} + +/** + * @name _InsertElementSkiplistWithInformation + * + * Determines a level for the new element and inserts it at the given position in the Skiplist. + * This function is internally used by the Skiplist insertion functions. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param Element + * The element to insert. + * + * @param pUpdate + * Array containing the last nodes before our new node on each level. + * + * @param dwDistance + * Array containing the distance to the last node before our new node on each level. + * + * @return + * TRUE if the node was successfully inserted, FALSE if no memory could be allocated for it. + */ +static BOOL +_InsertElementSkiplistWithInformation(PSKIPLIST Skiplist, PVOID Element, PSKIPLIST_NODE* pUpdate, DWORD* dwDistance) +{ + CHAR chNewLevel; + CHAR i; + PSKIPLIST_NODE pNode; + + // Get the highest level, on which the node shall be inserted. + chNewLevel = _GetRandomLevel(); + + // Check if the new level is higher than the maximum level we currently have in the Skiplist. + if (chNewLevel > Skiplist->MaximumLevel) + { + // It is, so we also need to insert the new node right after the Head node on some levels. + // These are the levels higher than the current maximum level up to the new level. + // We also need to set the distance of these elements to the new node count to account for the calculations below. + for (i = Skiplist->MaximumLevel + 1; i <= chNewLevel; i++) + { + pUpdate[i] = &Skiplist->Head; + pUpdate[i]->Distance[i] = Skiplist->NodeCount + 1; + } + + // The new level is the new maximum level of the entire Skiplist. + Skiplist->MaximumLevel = chNewLevel; + } + + // Finally create our new Skiplist node. + pNode = Skiplist->AllocateRoutine(sizeof(SKIPLIST_NODE)); + if (!pNode) + return FALSE; + + pNode->Element = Element; + + // For each used level, insert us between the saved node for this level and its current next node. + for (i = 0; i <= chNewLevel; i++) + { + pNode->Next[i] = pUpdate[i]->Next[i]; + pUpdate[i]->Next[i] = pNode; + + // We know the walked distance in this level: dwDistance[i] + // We also know the element index of the new node: dwDistance[0] + // The new node's distance is now the walked distance in this level plus the difference between the saved node's distance and the element index. + pNode->Distance[i] = dwDistance[i] + (pUpdate[i]->Distance[i] - dwDistance[0]); + + // The saved node's distance is now the element index plus one (to account for the added node) minus the walked distance in this level. + pUpdate[i]->Distance[i] = dwDistance[0] + 1 - dwDistance[i]; + } + + // For all levels above the new node's level, we need to increment the distance, because we've just added our new node. + for (i = chNewLevel + 1; i <= Skiplist->MaximumLevel; i++) + ++pUpdate[i]->Distance[i]; + + // We've successfully added a node :) + ++Skiplist->NodeCount; + return TRUE; +} + +/** + * @name DeleteElementSkiplist + * + * Deletes an element from the Skiplist. The efficiency of this operation is O(log N) on average. + * + * Instead of the result of a LookupElementSkiplist call, it's sufficient to provide a dummy element with just enough information for your CompareRoutine. + * A lookup for the element to be deleted needs to be performed in any case. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param Element + * Information about the element to be deleted. + * + * @return + * Returns the deleted element or NULL if no such element was found. + * You can then free memory for the deleted element if necessary. + */ +PVOID +DeleteElementSkiplist(PSKIPLIST Skiplist, PVOID Element) +{ + CHAR i; + PSKIPLIST_NODE pLastComparedNode = NULL; + PSKIPLIST_NODE pNode = &Skiplist->Head; + PSKIPLIST_NODE pUpdate[SKIPLIST_LEVELS]; + PVOID pReturnValue; + + // Find the node on every currently used level, after which the node to be deleted must follow. + // This can be done efficiently by starting from the maximum level and going down a level each time a position has been found. + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + while (pNode->Next[i] && pNode->Next[i] != pLastComparedNode && Skiplist->CompareRoutine(pNode->Next[i]->Element, Element) < 0) + pNode = pNode->Next[i]; + + // Reduce the number of comparisons by not comparing the same node on different levels twice. + pLastComparedNode = pNode->Next[i]; + pUpdate[i] = pNode; + } + + // Check if the node we're looking for has been found. + pNode = pNode->Next[0]; + if (!pNode || Skiplist->CompareRoutine(pNode->Element, Element) != 0) + { + // It hasn't been found, so there's nothing to delete. + return NULL; + } + + // Beginning at the lowest level, remove the node from each level of the list and merge distances. + // We can stop as soon as we found the first level that doesn't contain the node. + for (i = 0; i <= Skiplist->MaximumLevel && pUpdate[i]->Next[i] == pNode; i++) + { + pUpdate[i]->Distance[i] += pNode->Distance[i] - 1; + pUpdate[i]->Next[i] = pNode->Next[i]; + } + + // Now decrement the distance of the corresponding node in levels higher than the deleted node's level to account for the deleted node. + while (i <= Skiplist->MaximumLevel) + { + --pUpdate[i]->Distance[i]; + i++; + } + + // Return the deleted element (so the caller can free it if necessary) and free the memory for the node itself (allocated by us). + pReturnValue = pNode->Element; + Skiplist->FreeRoutine(pNode); + + // Find all levels which now contain no more nodes and reduce the maximum level of the entire Skiplist accordingly. + while (Skiplist->MaximumLevel > 0 && !Skiplist->Head.Next[Skiplist->MaximumLevel]) + --Skiplist->MaximumLevel; + + // We've successfully deleted the node :) + --Skiplist->NodeCount; + return pReturnValue; +} + +/** + * @name InitializeSkiplist + * + * Initializes a new Skiplist structure. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param AllocateRoutine + * Pointer to a SKIPLIST_ALLOCATE_ROUTINE for allocating memory for new Skiplist nodes. + * + * @param CompareRoutine + * Pointer to a SKIPLIST_COMPARE_ROUTINE for comparing two elements of the Skiplist. + * + * @param FreeRoutine + * Pointer to a SKIPLIST_FREE_ROUTINE for freeing memory allocated with AllocateRoutine. + */ +void +InitializeSkiplist(PSKIPLIST Skiplist, PSKIPLIST_ALLOCATE_ROUTINE AllocateRoutine, PSKIPLIST_COMPARE_ROUTINE CompareRoutine, PSKIPLIST_FREE_ROUTINE FreeRoutine) +{ + // Store the routines. + Skiplist->AllocateRoutine = AllocateRoutine; + Skiplist->CompareRoutine = CompareRoutine; + Skiplist->FreeRoutine = FreeRoutine; + + // Initialize the members and pointers. + // The Distance array is only used when a node is non-NULL, so it doesn't need initialization. + Skiplist->MaximumLevel = 0; + Skiplist->NodeCount = 0; + ZeroMemory(Skiplist->Head.Next, sizeof(Skiplist->Head.Next)); +} + +/** + * @name InsertElementSkiplist + * + * Inserts a new element into the Skiplist. The efficiency of this operation is O(log N) on average. + * Uses CompareRoutine to find the right position for the insertion. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param Element + * The element to insert. + * + * @return + * TRUE if the node was successfully inserted, FALSE if it already exists or no memory could be allocated for it. + */ +BOOL +InsertElementSkiplist(PSKIPLIST Skiplist, PVOID Element) +{ + CHAR i; + DWORD dwDistance[SKIPLIST_LEVELS + 1] = { 0 }; + PSKIPLIST_NODE pLastComparedNode = NULL; + PSKIPLIST_NODE pNode = &Skiplist->Head; + PSKIPLIST_NODE pUpdate[SKIPLIST_LEVELS]; + + // Find the node on every currently used level, after which the new node needs to be inserted. + // This can be done efficiently by starting from the maximum level and going down a level each time a position has been found. + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + // When entering this level, we begin at the distance of the last level we walked through. + dwDistance[i] = dwDistance[i + 1]; + + while (pNode->Next[i] && pNode->Next[i] != pLastComparedNode && Skiplist->CompareRoutine(pNode->Next[i]->Element, Element) < 0) + { + // Save our position in every level when walking through the nodes. + dwDistance[i] += pNode->Distance[i]; + + // Advance to the next node. + pNode = pNode->Next[i]; + } + + // Reduce the number of comparisons by not comparing the same node on different levels twice. + pLastComparedNode = pNode->Next[i]; + pUpdate[i] = pNode; + } + + // Check if the node already exists in the Skiplist. + pNode = pNode->Next[0]; + if (pNode && Skiplist->CompareRoutine(pNode->Element, Element) == 0) + { + // All elements to be inserted mustn't exist in the list, so we see this as a failure. + return FALSE; + } + + // The rest of the procedure is the same for both insertion functions. + return _InsertElementSkiplistWithInformation(Skiplist, Element, pUpdate, dwDistance); +} + +/** + * @name InsertTailElementSkiplist + * + * Inserts a new element at the end of the Skiplist. The efficiency of this operation is O(log N) on average. + * In contrast to InsertElementSkiplist, this function is more efficient by not calling CompareRoutine at all and always inserting the element at the end. + * You're responsible for calling this function only when you can guarantee that InsertElementSkiplist would also insert the element at the end. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param Element + * The element to insert. + * + * @return + * TRUE if the node was successfully inserted, FALSE if it already exists or no memory could be allocated for it. + */ +BOOL +InsertTailElementSkiplist(PSKIPLIST Skiplist, PVOID Element) +{ + CHAR i; + DWORD dwDistance[SKIPLIST_LEVELS + 1] = { 0 }; + PSKIPLIST_NODE pNode = &Skiplist->Head; + PSKIPLIST_NODE pUpdate[SKIPLIST_LEVELS]; + + // Find the last node on every currently used level, after which the new node needs to be inserted. + // This can be done efficiently by starting from the maximum level and going down a level each time a position has been found. + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + // When entering this level, we begin at the distance of the last level we walked through. + dwDistance[i] = dwDistance[i + 1]; + + while (pNode->Next[i]) + { + // Save our position in every level when walking through the nodes. + dwDistance[i] += pNode->Distance[i]; + + // Advance to the next node. + pNode = pNode->Next[i]; + } + + pUpdate[i] = pNode; + } + + // The rest of the procedure is the same for both insertion functions. + return _InsertElementSkiplistWithInformation(Skiplist, Element, pUpdate, dwDistance); +} + +/** + * @name LookupElementSkiplist + * + * Looks up an element in the Skiplist. The efficiency of this operation is O(log N) on average. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param Element + * Information about the element to look for. + * + * @param ElementIndex + * Pointer to a DWORD that will contain the zero-based index of the element in the Skiplist. + * If you're not interested in the index, you can set this parameter to NULL. + * + * @return + * Returns the found element or NULL if no such element was found. + */ +PVOID +LookupElementSkiplist(PSKIPLIST Skiplist, PVOID Element, PDWORD ElementIndex) +{ + CHAR i; + DWORD dwIndex = 0; + PSKIPLIST_NODE pLastComparedNode = NULL; + PSKIPLIST_NODE pNode = &Skiplist->Head; + + // Do the efficient lookup in Skiplists: + // * Start from the maximum level. + // * Walk through all nodes on this level that come before the node we're looking for. + // * When we have reached such a node, go down a level and continue there. + // * Repeat these steps till we're in level 0, right in front of the node we're looking for. + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + while (pNode->Next[i] && pNode->Next[i] != pLastComparedNode && Skiplist->CompareRoutine(pNode->Next[i]->Element, Element) < 0) + { + dwIndex += pNode->Distance[i]; + pNode = pNode->Next[i]; + } + + // Reduce the number of comparisons by not comparing the same node on different levels twice. + pLastComparedNode = pNode->Next[i]; + } + + // We must be right in front of the node we're looking for now, otherwise it doesn't exist in the Skiplist at all. + pNode = pNode->Next[0]; + if (!pNode || Skiplist->CompareRoutine(pNode->Element, Element) != 0) + { + // It hasn't been found, so there's nothing to return. + return NULL; + } + + // Return the index of the element if the caller is interested. + if (ElementIndex) + *ElementIndex = dwIndex; + + // Return the stored element of the found node. + return pNode->Element; +} + +/** + * @name LookupNodeByIndexSkiplist + * + * Looks up a node in the Skiplist at the given position. The efficiency of this operation is O(log N) on average. + * + * @param Skiplist + * Pointer to the SKIPLIST structure to operate on. + * + * @param ElementIndex + * Zero-based position of the node in the Skiplist. + * + * @return + * Returns the found node or NULL if the position is invalid. + */ +PSKIPLIST_NODE +LookupNodeByIndexSkiplist(PSKIPLIST Skiplist, DWORD ElementIndex) +{ + CHAR i; + DWORD dwIndex = 0; + PSKIPLIST_NODE pNode = &Skiplist->Head; + + // The only way the node can't be found is when the index is out of range. + if (ElementIndex >= Skiplist->NodeCount) + return NULL; + + // Do the efficient lookup in Skiplists: + // * Start from the maximum level. + // * Walk through all nodes on this level that come before the node we're looking for. + // * When we have reached such a node, go down a level and continue there. + // * Repeat these steps till we're in level 0, right in front of the node we're looking for. + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + // We compare with <= instead of < here, because the added distances make up a 1-based index while ElementIndex is zero-based, + // so we have to jump one node further. + while (pNode->Next[i] && dwIndex + pNode->Distance[i] <= ElementIndex) + { + dwIndex += pNode->Distance[i]; + pNode = pNode->Next[i]; + } + } + + // We are right in front of the node we're looking for now. + return pNode->Next[0]; +} Index: sdk/lib/skiplist/skiplist.h =================================================================== --- sdk/lib/skiplist/skiplist.h (nonexistent) +++ sdk/lib/skiplist/skiplist.h (working copy) @@ -0,0 +1,54 @@ +/* + * PROJECT: Skiplist implementation for the ReactOS Project + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Interfaces for the Skiplist + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _REACTOS_SKIPLIST_H +#define _REACTOS_SKIPLIST_H + +// Define SKIPLIST_LEVELS to a value between 1 and 31 before including this header. +// This specifies the maximum number of levels you want your Skiplist to have. +// A value of X is recommended for handling up to 2^X elements. +#ifndef SKIPLIST_LEVELS +#error Please define SKIPLIST_LEVELS to a value between 1 and 31. +#endif + +C_ASSERT(SKIPLIST_LEVELS >= 1); +C_ASSERT(SKIPLIST_LEVELS <= 31); + +// Function pointer definitions +typedef PVOID (WINAPI *PSKIPLIST_ALLOCATE_ROUTINE)(DWORD); +typedef int (WINAPI *PSKIPLIST_COMPARE_ROUTINE)(PVOID, PVOID); +typedef void (WINAPI *PSKIPLIST_FREE_ROUTINE)(PVOID); + +// Structure definitions +typedef struct _SKIPLIST_NODE +{ + DWORD Distance[SKIPLIST_LEVELS]; + struct _SKIPLIST_NODE* Next[SKIPLIST_LEVELS]; + PVOID Element; +} +SKIPLIST_NODE, *PSKIPLIST_NODE; + +typedef struct _SKIPLIST +{ + SKIPLIST_NODE Head; + CHAR MaximumLevel; + DWORD NodeCount; + PSKIPLIST_ALLOCATE_ROUTINE AllocateRoutine; + PSKIPLIST_COMPARE_ROUTINE CompareRoutine; + PSKIPLIST_FREE_ROUTINE FreeRoutine; +} +SKIPLIST, *PSKIPLIST; + +// Function prototypes +void InitializeSkiplist(PSKIPLIST Skiplist, PSKIPLIST_ALLOCATE_ROUTINE AllocateRoutine, PSKIPLIST_COMPARE_ROUTINE CompareRoutine, PSKIPLIST_FREE_ROUTINE FreeRoutine); +BOOL InsertElementSkiplist(PSKIPLIST Skiplist, PVOID Element); +BOOL InsertTailElementSkiplist(PSKIPLIST Skiplist, PVOID Element); +PVOID DeleteElementSkiplist(PSKIPLIST Skiplist, PVOID Element); +PVOID LookupElementSkiplist(PSKIPLIST Skiplist, PVOID Element, PDWORD ElementIndex); +PSKIPLIST_NODE LookupNodeByIndexSkiplist(PSKIPLIST Skiplist, DWORD ElementIndex); + +#endif Index: sdk/lib/skiplist/skiplist_test.c =================================================================== --- sdk/lib/skiplist/skiplist_test.c (nonexistent) +++ sdk/lib/skiplist/skiplist_test.c (working copy) @@ -0,0 +1,98 @@ +/* + * PROJECT: Skiplist implementation for the ReactOS Project + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: A simple program for testing the Skiplist implementation + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include +#include +#include "skiplist.h" + +void +DumpSkiplist(PSKIPLIST Skiplist) +{ + CHAR i; + DWORD j; + PSKIPLIST_NODE pNode; + + printf("======= DUMPING SKIPLIST =======\n"); + + for (i = Skiplist->MaximumLevel + 1; --i >= 0;) + { + pNode = &Skiplist->Head; + printf("H"); + + while (pNode->Next[i]) + { + printf("-"); + + // By using the Distance array for painting the lines, we verify both the links and the distances for correctness. + for (j = 1; j < pNode->Distance[i]; j++) + printf("---"); + + printf("%02lu", (DWORD)pNode->Next[i]->Element); + + pNode = pNode->Next[i]; + } + + printf("\n"); + } + + printf("================================\n\n"); +} + +PVOID WINAPI +MyAlloc(DWORD Size) +{ + return HeapAlloc(GetProcessHeap(), 0, Size); +} + +int WINAPI +MyCompare(PVOID A, PVOID B) +{ + return (DWORD)A - (DWORD)B; +} + +void WINAPI +MyFree(PVOID Ptr) +{ + HeapFree(GetProcessHeap(), 0, Ptr); +} + +int +main() +{ + DWORD Element; + DWORD ElementIndex; + DWORD i; + SKIPLIST Skiplist; + PSKIPLIST_NODE pNode; + + system("mode con cols=300"); + InitializeSkiplist(&Skiplist, MyAlloc, MyCompare, MyFree); + + // Insert some random elements with random numbers. + for (i = 0; i < 40; i++) + InsertElementSkiplist(&Skiplist, (PVOID)(rand() % 100)); + + // Delete all with index 0 to 29. + for (i = 0; i < 30; i++) + DeleteElementSkiplist(&Skiplist, (PVOID)i); + + // Insert some more random elements. + for (i = 0; i < 40; i++) + InsertElementSkiplist(&Skiplist, (PVOID)(rand() % 100)); + + // Output the third element (with zero-based index 2). + pNode = LookupNodeByIndexSkiplist(&Skiplist, 2); + printf("Element = %lu for index 2\n", (DWORD)pNode->Element); + + // Check if an element with number 44 is in the list and output its index. + Element = (DWORD)LookupElementSkiplist(&Skiplist, (PVOID)44, &ElementIndex); + printf("Element = %lu, ElementIndex = %lu\n\n", Element, ElementIndex); + + DumpSkiplist(&Skiplist); + + return 0; +} Index: win32ss/CMakeLists.txt =================================================================== --- win32ss/CMakeLists.txt (revision 73027) +++ win32ss/CMakeLists.txt (working copy) @@ -16,6 +16,7 @@ endif() add_subdirectory(gdi/gdi32) +add_subdirectory(printing) add_subdirectory(reactx) add_subdirectory(user/user32) add_subdirectory(user/winsrv) Index: win32ss/printing/CMakeLists.txt =================================================================== --- win32ss/printing/CMakeLists.txt (nonexistent) +++ win32ss/printing/CMakeLists.txt (working copy) @@ -0,0 +1,7 @@ +include_directories(include) + +add_subdirectory(base) +#add_subdirectory(drivers) +add_subdirectory(monitors) +add_subdirectory(processors) +add_subdirectory(providers) Index: win32ss/printing/base/CMakeLists.txt =================================================================== --- win32ss/printing/base/CMakeLists.txt (nonexistent) +++ win32ss/printing/base/CMakeLists.txt (working copy) @@ -0,0 +1,4 @@ +#add_subdirectory(printui) +add_subdirectory(spoolss) +add_subdirectory(spoolsv) +add_subdirectory(winspool) Index: win32ss/printing/base/spoolss/CMakeLists.txt =================================================================== --- win32ss/printing/base/spoolss/CMakeLists.txt (nonexistent) +++ win32ss/printing/base/spoolss/CMakeLists.txt (working copy) @@ -0,0 +1,26 @@ + +spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + context.c + jobs.c + main.c + memory.c + monitors.c + ports.c + precomp.h + printers.c + printprocessors.c + tools.c) + +add_library(spoolss SHARED + ${SOURCE} + spoolss.rc + ${CMAKE_CURRENT_BINARY_DIR}/spoolss_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/spoolss.def) + +set_module_type(spoolss win32dll UNICODE) +target_link_libraries(spoolss wine) +add_importlibs(spoolss advapi32 msvcrt kernel32 ntdll) +add_pch(spoolss precomp.h SOURCE) +add_cd_file(TARGET spoolss DESTINATION reactos/system32 FOR all) Index: win32ss/printing/base/spoolss/context.c =================================================================== --- win32ss/printing/base/spoolss/context.c (nonexistent) +++ win32ss/printing/base/spoolss/context.c (working copy) @@ -0,0 +1,104 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to switching between security contexts + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +/** + * @see RevertToPrinterSelf + */ +BOOL WINAPI +ImpersonatePrinterClient(HANDLE hToken) +{ + DWORD cbReturned; + DWORD dwErrorCode; + TOKEN_TYPE Type; + + // Sanity check + if (!hToken) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Get the type of the supplied token. + if (!GetTokenInformation(hToken, TokenType, &Type, sizeof(TOKEN_TYPE), &cbReturned)) + { + dwErrorCode = GetLastError(); + ERR("GetTokenInformation failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Check if this is an impersonation token and only set it as the thread token in this case. + // This is not always an impersonation token, see RevertToPrinterSelf. + if (Type == TokenImpersonation) + { + if (!SetThreadToken(NULL, hToken)) + { + dwErrorCode = GetLastError(); + ERR("SetThreadToken failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + } + +Cleanup: + if (hToken) + CloseHandle(hToken); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/** + * RevertToPrinterSelf reverts the security context from the current user's context back to the process context. + * As spoolss.dll is used by spoolsv.exe, this is usually the SYSTEM security context. + * + * Unlike the traditional ImpersonateClient and then RevertToSelf approach, we do it the other way round here, + * because spoolss.dll is delay-loaded by spoolsv.exe in the current user's context. Use RevertToPrinterSelf then to + * return to the SYSTEM context for specific tasks. + */ +HANDLE WINAPI +RevertToPrinterSelf() +{ + DWORD dwErrorCode; + HANDLE hReturnValue = NULL; + HANDLE hToken = NULL; + + // All spoolss code is usually called after impersonating the client. In this case, we can retrieve our current thread impersonation token using OpenThreadToken. + // But in rare occasions, spoolss code is also called from a higher-privileged thread that doesn't impersonate the client. Then we don't get an impersonation token. + // Anyway, we can't just return nothing in this case, because this is being treated as failure by the caller. So we return the token of the current process. + // This behaviour is verified with Windows! + if (OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hToken)) + { + // Tell the thread to stop impersonating. + if (!SetThreadToken(NULL, NULL)) + { + dwErrorCode = GetLastError(); + ERR("SetThreadToken failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + } + else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + dwErrorCode = GetLastError(); + ERR("OpenProcessToken failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We were successful, return a token! + dwErrorCode = ERROR_SUCCESS; + hReturnValue = hToken; + + // Don't let the cleanup routine close this. + hToken = NULL; + +Cleanup: + if (hToken) + CloseHandle(hToken); + + SetLastError(dwErrorCode); + return hReturnValue; +} Index: win32ss/printing/base/spoolss/jobs.c =================================================================== --- win32ss/printing/base/spoolss/jobs.c (nonexistent) +++ win32ss/printing/base/spoolss/jobs.c (working copy) @@ -0,0 +1,83 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions for managing print jobs + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded); +} + +BOOL WINAPI +EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); +} + +BOOL WINAPI +GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); +} + +BOOL WINAPI +ScheduleJob(HANDLE hPrinter, DWORD dwJobID) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpScheduleJob(pHandle->hPrinter, dwJobID); +} + +BOOL WINAPI +SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpSetJob(pHandle->hPrinter, JobId, Level, pJobInfo, Command); +} Index: win32ss/printing/base/spoolss/main.c =================================================================== --- win32ss/printing/base/spoolss/main.c (nonexistent) +++ win32ss/printing/base/spoolss/main.c (working copy) @@ -0,0 +1,248 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +HANDLE hProcessHeap; +LIST_ENTRY PrintProviderList; + + +static DWORD +_AddPrintProviderToList(PCWSTR pwszFileName) +{ + DWORD dwErrorCode; + HINSTANCE hinstPrintProvider; + PInitializePrintProvidor pfnInitializePrintProvidor; + PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL; + + // Try to load it. + hinstPrintProvider = LoadLibraryW(pwszFileName); + if (!hinstPrintProvider) + { + dwErrorCode = GetLastError(); + ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Get the initialization routine. + pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstPrintProvider, "InitializePrintProvidor"); + if (!pfnInitializePrintProvidor) + { + dwErrorCode = GetLastError(); + ERR("GetProcAddress failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Create a new SPOOLSS_PRINT_PROVIDER structure for it. + pPrintProvider = DllAllocSplMem(sizeof(SPOOLSS_PRINT_PROVIDER)); + if (!pPrintProvider) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Call the Print Provider initialization function. + if (!pfnInitializePrintProvidor(&pPrintProvider->PrintProvider, sizeof(PRINTPROVIDOR), NULL)) + { + dwErrorCode = GetLastError(); + ERR("InitializePrintProvidor failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode); + goto Cleanup; + } + + // Add this Print Provider to the list. + InsertTailList(&PrintProviderList, &pPrintProvider->Entry); + + // Don't let the cleanup routine free this. + pPrintProvider = NULL; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pPrintProvider) + DllFreeSplMem(pPrintProvider); + + return dwErrorCode; +} + +static BOOL +_InitializePrintProviderList() +{ + DWORD cbFileName; + DWORD cchMaxSubKey; + DWORD cchPrintProviderName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + PWSTR pwszPrintProviderName = NULL; + WCHAR wszFileName[MAX_PATH]; + + // Initialize an empty list for our Print Providers. + InitializeListHead(&PrintProviderList); + + // First add the Local Spooler. + // This one must exist and must be the first one in the list. + dwErrorCode = _AddPrintProviderToList(L"localspl"); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("The Local Spooler could not be loaded!\n"); + goto Cleanup; + } + + // Now add additional Print Providers from the registry. + // First of all, open the key containing print providers. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Providers and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Allocate a temporary buffer for the Print Provider names. + pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pwszPrintProviderName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Loop through all available Print Providers. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubKey) + { + RegCloseKey(hSubKey); + hSubKey = NULL; + } + + // Get the name of this Print Provider. + cchPrintProviderName = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pwszPrintProviderName, &cchPrintProviderName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); + continue; + } + + // Open this Print Provider's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pwszPrintProviderName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Provider \"%S\" with status %lu!\n", pwszPrintProviderName, dwErrorCode); + continue; + } + + // Get the file name of the Print Provider. + cbFileName = MAX_PATH * sizeof(WCHAR); + dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode); + continue; + } + + // Load and add it to the list. + dwErrorCode = _AddPrintProviderToList(wszFileName); + if (dwErrorCode != ERROR_SUCCESS) + continue; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + // Outside the loop + if (pwszPrintProviderName) + DllFreeSplMem(pwszPrintProviderName); + + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + hProcessHeap = GetProcessHeap(); + break; + } + + return TRUE; +} + +BOOL WINAPI +InitializeRouter(HANDLE SpoolerStatusHandle) +{ + return _InitializePrintProviderList(); +} + +BOOL WINAPI +SplInitializeWinSpoolDrv(PVOID* pTable) +{ + HINSTANCE hWinspool; + int i; + + hWinspool = LoadLibraryW(L"winspool.drv"); + if (!hWinspool) + { + ERR("Could not load winspool.drv, last error is %lu!\n", GetLastError()); + return FALSE; + } + + // Get the function pointers which are meant to be returned by this function. + pTable[0] = GetProcAddress(hWinspool, "OpenPrinterW"); + pTable[1] = GetProcAddress(hWinspool, "ClosePrinter"); + pTable[2] = GetProcAddress(hWinspool, "SpoolerDevQueryPrintW"); + pTable[3] = GetProcAddress(hWinspool, "SpoolerPrinterEvent"); + pTable[4] = GetProcAddress(hWinspool, "DocumentPropertiesW"); + pTable[5] = GetProcAddress(hWinspool, (LPSTR)212); + pTable[6] = GetProcAddress(hWinspool, (LPSTR)213); + pTable[7] = GetProcAddress(hWinspool, (LPSTR)214); + pTable[8] = GetProcAddress(hWinspool, (LPSTR)215); + + // Verify that all calls succeeded. + for (i = 0; i < 9; i++) + if (!pTable[i]) + return FALSE; + + return TRUE; +} + +BOOL WINAPI +SplIsUpgrade() +{ + return FALSE; +} + +BOOL WINAPI +SpoolerInit() +{ + // Nothing to do here yet + SetLastError(ERROR_SUCCESS); + return TRUE; +} Index: win32ss/printing/base/spoolss/memory.c =================================================================== --- win32ss/printing/base/spoolss/memory.c (nonexistent) +++ win32ss/printing/base/spoolss/memory.c (working copy) @@ -0,0 +1,168 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions for allocating and freeing memory + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + + +/** + * @name AllocSplStr + * + * Allocates memory for a Unicode string and copies the input string into it. + * Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr. + * + * @param pwszInput + * The input string to copy + * + * @return + * Pointer to the copied string or NULL if no memory could be allocated. + */ +PWSTR WINAPI +AllocSplStr(PCWSTR pwszInput) +{ + DWORD cbInput; + PWSTR pwszOutput; + + // Sanity check + if (!pwszInput) + return NULL; + + // Get the length of the input string. + cbInput = (wcslen(pwszInput) + 1) * sizeof(WCHAR); + + // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory. + pwszOutput = HeapAlloc(hProcessHeap, 0, cbInput); + if (!pwszOutput) + { + ERR("HeapAlloc failed with error %lu!\n", GetLastError()); + return NULL; + } + + // Copy the string and return it. + CopyMemory(pwszOutput, pwszInput, cbInput); + return pwszOutput; +} + +/** + * @name DllAllocSplMem + * + * Allocate a block of zeroed memory. + * Windows allocates from a separate spooler heap here while we just use the process heap. + * + * @param dwBytes + * Number of bytes to allocate. + * + * @return + * A pointer to the allocated memory or NULL in case of an error. + * You have to free this memory using DllFreeSplMem. + */ +PVOID WINAPI +DllAllocSplMem(DWORD dwBytes) +{ + return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes); +} + +/** + * @name DllFreeSplMem + * + * Frees the memory allocated with DllAllocSplMem. + * + * @param pMem + * Pointer to the allocated memory. + * + * @return + * TRUE in case of success, FALSE otherwise. + */ +BOOL WINAPI +DllFreeSplMem(PVOID pMem) +{ + return HeapFree(hProcessHeap, 0, pMem); +} + +/** + * @name DllFreeSplStr + * + * Frees the string allocated with AllocSplStr. + * + * @param pwszString + * Pointer to the allocated string. + * + * @return + * TRUE in case of success, FALSE otherwise. + */ +BOOL WINAPI +DllFreeSplStr(PWSTR pwszString) +{ + return HeapFree(hProcessHeap, 0, pwszString); +} + +/** + * @name ReallocSplMem + * + * Allocates a new block of memory and copies the contents of the old block into the new one. + * + * @param pOldMem + * Pointer to the old block of memory. + * If this parameter is NULL, ReallocSplMem behaves exactly like DllAllocSplMem. + * + * @param cbOld + * Number of bytes to copy from the old block into the new one. + * + * @param cbNew + * Number of bytes to allocate for the new block. + * + * @return + * A pointer to the allocated new block or NULL in case of an error. + * You have to free this memory using DllFreeSplMem. + */ +PVOID WINAPI +ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew) +{ + PVOID pNewMem; + + // Always allocate the new block of memory. + pNewMem = DllAllocSplMem(cbNew); + if (!pNewMem) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return NULL; + } + + // Copy the old memory into the new block and free it. + if (pOldMem) + { + CopyMemory(pNewMem, pOldMem, min(cbOld, cbNew)); + DllFreeSplMem(pOldMem); + } + + return pNewMem; +} + +/** + * @name ReallocSplStr + * + * Frees a string allocated by AllocSplStr and copies the given Unicode string into a newly allocated block of memory. + * + * @param ppwszString + * Pointer to the string pointer allocated by AllocSplStr. + * When the function returns, the variable receives the pointer to the copied string. + * + * @param pwszInput + * The Unicode string to copy into the new block of memory. + * + * @return + * Returns TRUE in any case. +*/ +BOOL WINAPI +ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput) +{ + if (*ppwszString) + DllFreeSplStr(*ppwszString); + + *ppwszString = AllocSplStr(pwszInput); + + return TRUE; +} Index: win32ss/printing/base/spoolss/monitors.c =================================================================== --- win32ss/printing/base/spoolss/monitors.c (nonexistent) +++ win32ss/printing/base/spoolss/monitors.c (working copy) @@ -0,0 +1,68 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pMonitors; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Check if this Print Provider provides an EnumMonitors function. + if (!pPrintProvider->PrintProvider.fpEnumMonitors) + continue; + + // Call the EnumMonitors function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + + // Check if we shall not ask other Print Providers. + if (bReturnValue == ROUTER_STOP_ROUTING) + break; + } + + return bReturnValue; +} Index: win32ss/printing/base/spoolss/ports.c =================================================================== --- win32ss/printing/base/spoolss/ports.c (nonexistent) +++ win32ss/printing/base/spoolss/ports.c (working copy) @@ -0,0 +1,64 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Ports of the Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPorts; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Call the EnumPorts function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + + // Check if we shall not ask other Print Providers. + if (bReturnValue == ROUTER_STOP_ROUTING) + break; + } + + return bReturnValue; +} Index: win32ss/printing/base/spoolss/precomp.h =================================================================== --- win32ss/printing/base/spoolss/precomp.h (nonexistent) +++ win32ss/printing/base/spoolss/precomp.h (working copy) @@ -0,0 +1,54 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(spoolss); + +// Function pointers +typedef BOOL (WINAPI *PInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR); + +// Structures +/** + * Describes a Print Provider. + */ +typedef struct _SPOOLSS_PRINT_PROVIDER +{ + LIST_ENTRY Entry; + PRINTPROVIDOR PrintProvider; +} +SPOOLSS_PRINT_PROVIDER, *PSPOOLSS_PRINT_PROVIDER; + +/* + * Describes a handle returned by OpenPrinterW. + * We can't just pass the handle returned by the Print Provider, because spoolss has to remember which Print Provider opened this handle. + */ +typedef struct _SPOOLSS_PRINTER_HANDLE +{ + PSPOOLSS_PRINT_PROVIDER pPrintProvider; /** Pointer to the Print Provider that opened this printer. */ + HANDLE hPrinter; /** The handle returned by fpOpenPrinter of the Print Provider and passed to subsequent Print Provider functions. */ +} +SPOOLSS_PRINTER_HANDLE, *PSPOOLSS_PRINTER_HANDLE; + +// main.c +extern HANDLE hProcessHeap; +extern LIST_ENTRY PrintProviderList; + +#endif Index: win32ss/printing/base/spoolss/printers.c =================================================================== --- win32ss/printing/base/spoolss/printers.c (nonexistent) +++ win32ss/printing/base/spoolss/printers.c (working copy) @@ -0,0 +1,272 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printers and printing + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + + +BOOL WINAPI +ClosePrinter(HANDLE hPrinter) +{ + BOOL bReturnValue; + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // FIXME: Call FindClosePrinterChangeNotification for all created change notifications (according to MSDN). + + // Call CloseHandle of the Print Provider. + bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter); + + // Free our handle information. + DllFreeSplMem(pHandle); + + return bReturnValue; +} + +BOOL WINAPI +EndDocPrinter(HANDLE hPrinter) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter); +} + +BOOL WINAPI +EndPagePrinter(HANDLE hPrinter) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter); +} + +BOOL WINAPI +EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pPrinterEnum) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPrinterEnum; + + // Loop through all Print Provider. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + // Call the EnumPrinters function of this Print Provider. + bReturnValue = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + } + + return bReturnValue; +} + +BOOL WINAPI +GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded); +} + +BOOL WINAPI +GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded); +} + +BOOL WINAPI +OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault) +{ + BOOL bReturnValue; + HANDLE hPrinter; + PLIST_ENTRY pEntry; + PSPOOLSS_PRINTER_HANDLE pHandle; + PSPOOLSS_PRINT_PROVIDER pPrintProvider; + + // Sanity checks. + if (!pPrinterName || !phPrinter) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Loop through all Print Providers to find one able to open this Printer. + for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink) + { + pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry); + + bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault); + if (bReturnValue == ROUTER_SUCCESS) + { + // This Print Provider has opened this Printer. + // Store this information and return a handle. + pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE)); + if (!pHandle) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return FALSE; + } + + pHandle->pPrintProvider = pPrintProvider; + pHandle->hPrinter = hPrinter; + *phPrinter = (HANDLE)pHandle; + + SetLastError(ERROR_SUCCESS); + return TRUE; + } + else if (bReturnValue == ROUTER_STOP_ROUTING) + { + ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName); + return FALSE; + } + } + + // We found no Print Provider able to open this Printer. + return FALSE; +} + +BOOL WINAPI +ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead); +} + +DWORD WINAPI +StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo); +} + +BOOL WINAPI +StartPagePrinter(HANDLE hPrinter) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter); +} + +BOOL WINAPI +WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten); +} + +BOOL WINAPI +XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus) +{ + PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv; + + // Sanity checks. + if (!pHandle) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus); +} Index: win32ss/printing/base/spoolss/printprocessors.c =================================================================== --- win32ss/printing/base/spoolss/printprocessors.c (nonexistent) +++ win32ss/printing/base/spoolss/printprocessors.c (working copy) @@ -0,0 +1,32 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Processors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); +} + +BOOL WINAPI +EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned); +} + +BOOL WINAPI +GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded) +{ + // Always call this function on the Local Spooler. + PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(&PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry); + return pPrintProvider->PrintProvider.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded); +} Index: win32ss/printing/base/spoolss/spoolss.rc =================================================================== --- win32ss/printing/base/spoolss/spoolss.rc (nonexistent) +++ win32ss/printing/base/spoolss/spoolss.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Spooler Router" +#define REACTOS_STR_INTERNAL_NAME "spoolss" +#define REACTOS_STR_ORIGINAL_FILENAME "spoolss.dll" +#include Index: win32ss/printing/base/spoolss/spoolss.spec =================================================================== --- win32ss/printing/base/spoolss/spoolss.spec (nonexistent) +++ win32ss/printing/base/spoolss/spoolss.spec (working copy) @@ -0,0 +1,178 @@ +@ stub AbortPrinter +@ stub AddDriverCatalog +@ stub AddFormW +@ stdcall AddJobW(long long ptr long ptr) +@ stub AddMonitorW +@ stub AddPerMachineConnectionW +@ stub AddPortExW +@ stub AddPortW +@ stub AddPrinterConnectionW +@ stub AddPrinterDriverExW +@ stub AddPrinterDriverW +@ stub AddPrinterExW +@ stub AddPrinterW +@ stub AddPrintProcessorW +@ stub AddPrintProvidorW +@ stub AdjustPointers +@ stub AdjustPointersInStructuresArray +@ stub AlignKMPtr +@ stub AlignRpcPtr +@ stdcall AllocSplStr(ptr) +@ stub AllowRemoteCalls +@ stub AppendPrinterNotifyInfoData +@ stub bGetDevModePerUser +@ stub bSetDevModePerUser +@ stub BuildOtherNamesFromMachineName +@ stub CacheAddName +@ stub CacheCreateAndAddNode +@ stub CacheCreateAndAddNodeWithIPAddresses +@ stub CacheDeleteNode +@ stub CacheIsNameCluster +@ stub CacheIsNameInNodeList +@ stub CallDrvDevModeConversion +@ stub CallRouterFindFirstPrinterChangeNotification +@ stub CheckLocalCall +@ stdcall ClosePrinter(long) +@ stub ClusterSplClose +@ stub ClusterSplIsAlive +@ stub ClusterSplOpen +@ stub ConfigurePortW +@ stub CreatePrinterIC +@ stub DbgGetPointers +@ stub DeleteFormW +@ stub DeleteMonitorW +@ stub DeletePerMachineConnectionW +@ stub DeletePortW +@ stub DeletePrinter +@ stub DeletePrinterConnectionW +@ stub DeletePrinterDataExW +@ stub DeletePrinterDataW +@ stub DeletePrinterDriverExW +@ stub DeletePrinterDriverW +@ stub DeletePrinterIC +@ stub DeletePrinterKeyW +@ stub DeletePrintProcessorW +@ stub DeletePrintProvidorW +@ stdcall DllAllocSplMem(long) +@ stdcall DllFreeSplMem(ptr) +@ stdcall DllFreeSplStr(ptr) +@ stdcall EndDocPrinter(long) +@ stdcall EndPagePrinter(long) +@ stub EnumFormsW +@ stdcall EnumJobsW(long long long long ptr long ptr ptr) +@ stdcall EnumMonitorsW(wstr long ptr long ptr ptr) +@ stub EnumPerMachineConnectionsW +@ stdcall EnumPortsW(wstr long ptr long ptr ptr) +@ stub EnumPrinterDataExW +@ stub EnumPrinterDataW +@ stub EnumPrinterDriversW +@ stub EnumPrinterKeyW +@ stdcall EnumPrintersW(long wstr long ptr long ptr ptr) +@ stdcall EnumPrintProcessorDatatypesW(wstr wstr long ptr long ptr ptr) +@ stdcall EnumPrintProcessorsW(wstr wstr long ptr long ptr ptr) +@ stub FindClosePrinterChangeNotification +@ stub FlushPrinter +@ stub FormatPrinterForRegistryKey +@ stub FormatRegistryKeyForPrinter +@ stub FreeOtherNames +@ stub GetClientUserHandle +@ stub GetFormW +@ stub GetJobAttributes +@ stdcall GetJobW(long long long ptr long ptr) +@ stub GetNetworkId +@ stub GetPrinterDataExW +@ stub GetPrinterDataW +@ stub GetPrinterDriverDirectoryW +@ stub GetPrinterDriverExW +@ stdcall GetPrinterDriverW(long wstr long ptr long ptr) +@ stdcall GetPrinterW(long long ptr long ptr) +@ stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr) +@ stub GetServerPolicy +@ stub GetShrinkedSize +@ stdcall ImpersonatePrinterClient(long) +@ stdcall InitializeRouter(long) +@ stub IsNamedPipeRpcCall +@ stub LoadDriver +@ stub LoadDriverFiletoConvertDevmode +@ stub LoadDriverWithVersion +@ stub LogWmiTraceEvent +@ stdcall MarshallDownStructure(ptr ptr long long) +@ stub MarshallDownStructuresArray +@ stub MarshallUpStructure +@ stub MarshallUpStructuresArray +@ stub MIDL_user_allocate1 +@ stub MIDL_user_free1 +@ stub OldGetPrinterDriverW +@ stub OpenPrinterExW +@ stub OpenPrinterPortW +@ stdcall OpenPrinterW(wstr ptr ptr) +@ stdcall PackStrings(ptr ptr ptr ptr) +@ stub PartialReplyPrinterChangeNotification +@ stub PlayGdiScriptOnPrinterIC +@ stub PrinterHandleRundown +@ stub PrinterMessageBoxW +@ stub ProvidorFindClosePrinterChangeNotification +@ stub ProvidorFindFirstPrinterChangeNotification +@ stub pszDbgAllocMsgA +@ stdcall ReadPrinter(long ptr long ptr) +@ stdcall ReallocSplMem(ptr long long) +@ stdcall ReallocSplStr(ptr ptr) +@ stub RemoteFindFirstPrinterChangeNotification +@ stub ReplyClosePrinter +@ stub ReplyOpenPrinter +@ stub ReplyPrinterChangeNotification +@ stub ResetPrinterW +@ stdcall RevertToPrinterSelf() +@ stub RouterAllocBidiMem +@ stub RouterAllocBidiResponseContainer +@ stub RouterAllocPrinterNotifyInfo +@ stub RouterFindFirstPrinterChangeNotification +@ stub RouterFindNextPrinterChangeNotification +@ stub RouterFreeBidiMem +@ stub RouterFreePrinterNotifyInfo +@ stub RouterRefreshPrinterChangeNotification +@ stub RouterReplyPrinter +@ stdcall ScheduleJob(long long) +@ stub SeekPrinter +@ stub SendRecvBidiData +@ stub SetAllocFailCount +@ stub SetFormW +@ stdcall SetJobW(long long long ptr long) +@ stub SetPortW +@ stub SetPrinterDataExW +@ stub SetPrinterDataW +@ stub SetPrinterW +@ stub SplCloseSpoolFileHandle +@ stub SplCommitSpoolData +@ stub SplDriverUnloadComplete +@ stub SplGetSpoolFileInfo +@ stdcall SplInitializeWinSpoolDrv(ptr) +@ stub SplIsSessionZero +@ stdcall SplIsUpgrade() +@ stub SplPowerEvent +@ stub SplProcessPnPEvent +@ stub SplPromptUIInUsersSession +@ stub SplReadPrinter +@ stub SplRegisterForDeviceEvents +@ stub SplShutDownRouter +@ stub SplUnregisterForDeviceEvents +@ stub SpoolerFindClosePrinterChangeNotification +@ stub SpoolerFindFirstPrinterChangeNotification +@ stub SpoolerFindNextPrinterChangeNotification +@ stub SpoolerFreePrinterNotifyInfo +@ stub SpoolerHasInitialized +@ stdcall SpoolerInit() +@ stdcall StartDocPrinterW(long long ptr) +@ stdcall StartPagePrinter(long) +@ stub UndoAlignKMPtr +@ stub UndoAlignRpcPtr +@ stub UnloadDriver +@ stub UnloadDriverFile +@ stub UpdateBufferSize +@ stub UpdatePrinterRegAll +@ stub UpdatePrinterRegUser +@ stub vDbgLogError +@ stub WaitForPrinterChange +@ stub WaitForSpoolerInitialization +@ stdcall WritePrinter(long ptr long ptr) +@ stdcall XcvDataW(long wstr ptr long ptr long ptr ptr) Index: win32ss/printing/base/spoolss/tools.c =================================================================== --- win32ss/printing/base/spoolss/tools.c (nonexistent) +++ win32ss/printing/base/spoolss/tools.c (working copy) @@ -0,0 +1,120 @@ +/* + * PROJECT: ReactOS Spooler Router + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Miscellaneous tool functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + + +/** + * @name MarshallDownStructure + * + * Prepare a structure for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets. + * + * @param pStructure + * Pointer to the structure to operate on. + * + * @param pParameters + * Array of MARSHALL_DOWN_INFO elements containing information about the fields of the structure as well as how to modify them. + * See the documentation on MARSHALL_DOWN_INFO for more information. + * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD. + * + * @param cbStructureSize + * Apparently, this is the size in bytes of the structure given through pStructure under Windows. + * This parameter is unused in my implementation. + * + * @param bSomeBoolean + * Unknown boolean value + * + * @return + * TRUE if the structure was successfully adjusted, FALSE otherwise. + */ +BOOL WINAPI +MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean) +{ + // Sanity checks + if (!pStructure || !pParameters) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Loop until we reach an element with offset set to MAXDWORD. + while (pParameters->dwOffset != MAXDWORD) + { + if (pParameters->bAdjustAddress) + { + // Apply the byte offset on pStructure. There must be a pointer at this position, whose address we're adjusting + // by subtracting the address of pStructure from it. + *((PULONG_PTR)((PBYTE)pStructure + pParameters->dwOffset)) -= (ULONG_PTR)pStructure; + } + + // Advance to the next element description. + pParameters++; + } + + return TRUE; +} + +/** + * @name PackStrings + * + * Takes an array of Unicode strings and fills an output buffer with these strings at the end and pointers to each string at specific offsets. + * Useful helper for functions that copy an information structure including strings into a given buffer (like PRINTER_INFO_1). + * + * @param pSource + * The array of Unicode strings to copy. Needs to have at least as many elements as the DestOffsets array. + * + * @param pDest + * Pointer to the beginning of the output buffer. + * The caller is responsible for verifying that this buffer is large enough to hold all strings and pointers. + * + * @param DestOffsets + * Array of byte offsets in the output buffer. For each element of DestOffsets, the function will copy the address of the corresponding copied + * string of pSource to this location in the output buffer. If a string in pSource is NULL, the function will set the pointer address to NULL + * in the output buffer. + * Use macros like FIELD_OFFSET to calculate the offsets for this array. + * The last element of the array must have the value MAXDWORD to let the function detect the end of the array. + * + * @param pEnd + * Pointer to the end of the output buffer. That means the first element outside of the buffer given in pDest. + * + * @return + * Returns a pointer to the beginning of the strings in pDest. + * The strings are copied in reverse order, so this pointer will point to the last copied string of pSource. + */ +PBYTE WINAPI +PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd) +{ + DWORD cbString; + ULONG_PTR StringAddress; + + // Loop until we reach an element with offset set to MAXDWORD. + while (*DestOffsets != MAXDWORD) + { + StringAddress = 0; + + if (*pSource) + { + // Determine the length of the source string. + cbString = (wcslen(*pSource) + 1) * sizeof(WCHAR); + + // Copy it before the last string. + pEnd -= cbString; + StringAddress = (ULONG_PTR)pEnd; + CopyMemory(pEnd, *pSource, cbString); + } + + // Copy the address of the copied string to the location given by the offset. + CopyMemory(&pDest[*DestOffsets], &StringAddress, sizeof(ULONG_PTR)); + + // Advance to the next source string and destination offset. + pSource++; + DestOffsets++; + } + + // pEnd is now at the last string we copied. Return this value as a pointer to the beginning of all strings in the output buffer. + return pEnd; +} Index: win32ss/printing/base/spoolsv/CMakeLists.txt =================================================================== --- win32ss/printing/base/spoolsv/CMakeLists.txt (nonexistent) +++ win32ss/printing/base/spoolsv/CMakeLists.txt (working copy) @@ -0,0 +1,30 @@ + +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl) +add_rpc_files(server ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/winspool.idl) + +list(APPEND SOURCE + forms.c + init.c + jobs.c + main.c + monitors.c + notifications.c + ports.c + precomp.h + printerdata.c + printerdrivers.c + printers.c + printprocessors.c + printproviders.c + rpcserver.c + rpcstubs.c + xcv.c + ${CMAKE_CURRENT_BINARY_DIR}/winspool_s.c) + +add_executable(spoolsv ${SOURCE} spoolsv.rc) +set_module_type(spoolsv win32cui UNICODE) +target_link_libraries(spoolsv wine) +add_delay_importlibs(spoolsv spoolss) +add_importlibs(spoolsv advapi32 rpcrt4 msvcrt kernel32 ntdll) +add_pch(spoolsv precomp.h SOURCE) +add_cd_file(TARGET spoolsv DESTINATION reactos/system32 FOR all) Index: win32ss/printing/base/spoolsv/forms.c =================================================================== --- win32ss/printing/base/spoolsv/forms.c (nonexistent) +++ win32ss/printing/base/spoolsv/forms.c (working copy) @@ -0,0 +1,43 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Forms + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcAddForm(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_FORM_CONTAINER* pFormInfoContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeleteForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumForms(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pForm, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName, DWORD Level, BYTE* pForm, DWORD cbBuf, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSetForm(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pFormName, WINSPOOL_FORM_CONTAINER* pFormInfoContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/init.c =================================================================== --- win32ss/printing/base/spoolsv/init.c (nonexistent) +++ win32ss/printing/base/spoolsv/init.c (working copy) @@ -0,0 +1,29 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Various initialization functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcSpoolerInit() +{ + DWORD dwErrorCode; + + // Call SpoolerInit in the security context of the client. + // This delay-loads spoolss.dll in the user context and all further calls to functions in spoolss.dll will be done in the user context as well. + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + SpoolerInit(); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} Index: win32ss/printing/base/spoolsv/jobs.c =================================================================== --- win32ss/printing/base/spoolsv/jobs.c (nonexistent) +++ win32ss/printing/base/spoolsv/jobs.c (working copy) @@ -0,0 +1,178 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions for managing print jobs + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallDownAddJobInfo(PADDJOB_INFO_1W pAddJobInfo1) +{ + // Replace absolute pointer addresses in the output by relative offsets. + pAddJobInfo1->Path = (PWSTR)((ULONG_PTR)pAddJobInfo1->Path - (ULONG_PTR)pAddJobInfo1); +} + +static void +_MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level) +{ + PJOB_INFO_1W pJobInfo1; + PJOB_INFO_2W pJobInfo2; + + // Replace absolute pointer addresses in the output by relative offsets. + if (Level == 1) + { + pJobInfo1 = (PJOB_INFO_1W)pJobInfo; + pJobInfo1->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo1->pDatatype - (ULONG_PTR)pJobInfo1); + pJobInfo1->pDocument = (PWSTR)((ULONG_PTR)pJobInfo1->pDocument - (ULONG_PTR)pJobInfo1); + pJobInfo1->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo1->pMachineName - (ULONG_PTR)pJobInfo1); + pJobInfo1->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo1->pPrinterName - (ULONG_PTR)pJobInfo1); + + if (pJobInfo1->pStatus) + pJobInfo1->pStatus = (PWSTR)((ULONG_PTR)pJobInfo1->pStatus - (ULONG_PTR)pJobInfo1); + + pJobInfo1->pUserName = (PWSTR)((ULONG_PTR)pJobInfo1->pUserName - (ULONG_PTR)pJobInfo1); + } + else if (Level == 2) + { + pJobInfo2 = (PJOB_INFO_2W)pJobInfo; + pJobInfo2->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo2->pDatatype - (ULONG_PTR)pJobInfo2); + pJobInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pJobInfo2->pDevMode - (ULONG_PTR)pJobInfo2); + pJobInfo2->pDocument = (PWSTR)((ULONG_PTR)pJobInfo2->pDocument - (ULONG_PTR)pJobInfo2); + pJobInfo2->pDriverName = (PWSTR)((ULONG_PTR)pJobInfo2->pDriverName - (ULONG_PTR)pJobInfo2); + pJobInfo2->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo2->pMachineName - (ULONG_PTR)pJobInfo2); + pJobInfo2->pNotifyName = (PWSTR)((ULONG_PTR)pJobInfo2->pNotifyName - (ULONG_PTR)pJobInfo2); + pJobInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo2->pPrinterName - (ULONG_PTR)pJobInfo2); + pJobInfo2->pPrintProcessor = (PWSTR)((ULONG_PTR)pJobInfo2->pPrintProcessor - (ULONG_PTR)pJobInfo2); + + if (pJobInfo2->pParameters) + pJobInfo2->pParameters = (PWSTR)((ULONG_PTR)pJobInfo2->pParameters - (ULONG_PTR)pJobInfo2); + + if (pJobInfo2->pStatus) + pJobInfo2->pStatus = (PWSTR)((ULONG_PTR)pJobInfo2->pStatus - (ULONG_PTR)pJobInfo2); + + pJobInfo2->pUserName = (PWSTR)((ULONG_PTR)pJobInfo2->pUserName - (ULONG_PTR)pJobInfo2); + } +} + +DWORD +_RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD cbBuf, DWORD* pcbNeeded) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + _MarshallDownAddJobInfo((PADDJOB_INFO_1W)pAddJob); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcEnumJobs(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pJob; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownJobInfo(p, Level); + + if (Level == 1) + p += sizeof(JOB_INFO_1W); + else if (Level == 2) + p += sizeof(JOB_INFO_2W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + _MarshallDownJobInfo(pJob, Level); + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + ScheduleJob(hPrinter, JobId); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcSetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, WINSPOOL_JOB_CONTAINER* pJobContainer, DWORD Command) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + // pJobContainer->JobInfo is a union of pointers, so we can just convert any element to our BYTE pointer. + SetJobW(hPrinter, JobId, pJobContainer->Level, (PBYTE)pJobContainer->JobInfo.Level1, Command); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} Index: win32ss/printing/base/spoolsv/main.c =================================================================== --- win32ss/printing/base/spoolsv/main.c (nonexistent) +++ win32ss/printing/base/spoolsv/main.c (working copy) @@ -0,0 +1,100 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +SERVICE_STATUS_HANDLE hServiceStatus; +SERVICE_STATUS ServiceStatus; +WCHAR wszServiceName[] = L"Spooler"; + +static void +_UpdateServiceStatus(DWORD dwNewStatus, DWORD dwCheckPoint) +{ + ServiceStatus.dwCheckPoint = dwCheckPoint; + ServiceStatus.dwCurrentState = dwNewStatus; + SetServiceStatus(hServiceStatus, &ServiceStatus); +} + +static DWORD WINAPI +_ServiceControlHandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) +{ + switch (dwControl) + { + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + _UpdateServiceStatus(SERVICE_STOP_PENDING, 1); + RpcMgmtStopServerListening(NULL); + _UpdateServiceStatus(SERVICE_STOPPED, 0); + return NO_ERROR; + + case SERVICE_CONTROL_INTERROGATE: + return NO_ERROR; + + default: + return ERROR_CALL_NOT_IMPLEMENTED; + } +} + +static VOID WINAPI +_ServiceMain(DWORD dwArgc, LPWSTR* lpszArgv) +{ + HANDLE hThread; + + UNREFERENCED_PARAMETER(dwArgc); + UNREFERENCED_PARAMETER(lpszArgv); + + // Register our service for control + hServiceStatus = RegisterServiceCtrlHandlerExW(wszServiceName, _ServiceControlHandlerEx, NULL); + + // Report initial SERVICE_START_PENDING status + ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; + ServiceStatus.dwServiceSpecificExitCode = 0; + ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ServiceStatus.dwWaitHint = 4000; + ServiceStatus.dwWin32ExitCode = NO_ERROR; + _UpdateServiceStatus(SERVICE_START_PENDING, 0); + + // Create a thread for serving RPC requests + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)LrpcThreadProc, NULL, 0, NULL); + if (!hThread) + { + ERR("CreateThread failed with error %u!\n", GetLastError()); + _UpdateServiceStatus(SERVICE_STOPPED, 0); + return; + } + + // We don't need the thread handle. Keeping it open blocks the thread from terminating. + CloseHandle(hThread); + + // Initialize the routing layer in spoolss.dll + if (!InitializeRouter(hServiceStatus)) + { + ERR("InitializeRouter failed with error %lu!\n", GetLastError()); + _UpdateServiceStatus(SERVICE_STOPPED, 0); + return; + } + + // We're alive! + _UpdateServiceStatus(SERVICE_RUNNING, 0); +} + +int +wmain(int argc, WCHAR* argv[]) +{ + SERVICE_TABLE_ENTRYW ServiceTable[] = + { + {wszServiceName, _ServiceMain}, + {NULL, NULL} + }; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + StartServiceCtrlDispatcherW(ServiceTable); + + return 0; +} Index: win32ss/printing/base/spoolsv/monitors.c =================================================================== --- win32ss/printing/base/spoolsv/monitors.c (nonexistent) +++ win32ss/printing/base/spoolsv/monitors.c (working copy) @@ -0,0 +1,72 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallDownMonitorInfo(PBYTE pMonitorInfo, DWORD Level) +{ + PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)pMonitorInfo; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W + + // Replace absolute pointer addresses in the output by relative offsets. + pMonitorInfo2->pName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pName - (ULONG_PTR)pMonitorInfo2); + + if (Level == 2) + { + pMonitorInfo2->pDLLName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pDLLName - (ULONG_PTR)pMonitorInfo2); + pMonitorInfo2->pEnvironment = (PWSTR)((ULONG_PTR)pMonitorInfo2->pEnvironment - (ULONG_PTR)pMonitorInfo2); + } +} + +DWORD +_RpcAddMonitor(WINSPOOL_HANDLE pName, WINSPOOL_MONITOR_CONTAINER* pMonitorContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeleteMonitor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pMonitorName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pMonitor, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pMonitor; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumMonitorsW(pName, Level, pMonitor, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownMonitorInfo(p, Level); + + if (Level == 1) + p += sizeof(MONITOR_INFO_1W); + else if (Level == 2) + p += sizeof(MONITOR_INFO_2W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} Index: win32ss/printing/base/spoolsv/notifications.c =================================================================== --- win32ss/printing/base/spoolsv/notifications.c (nonexistent) +++ win32ss/printing/base/spoolsv/notifications.c (working copy) @@ -0,0 +1,92 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printer Configuration Data + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcClientFindFirstPrinterChangeNotification() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcFindClosePrinterChangeNotification() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcFindNextPrinterChangeNotification() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRemoteFindFirstPrinterChangeNotification(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD fdwFlags, DWORD fdwOptions, WCHAR* pszLocalMachine, DWORD dwPrinterLocal, DWORD cbBuffer, BYTE* pBuffer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRemoteFindFirstPrinterChangeNotificationEx(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD fdwFlags, DWORD fdwOptions, WCHAR* pszLocalMachine, DWORD dwPrinterLocal, WINSPOOL_V2_NOTIFY_OPTIONS* pOptions) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcReplyClosePrinter(WINSPOOL_PRINTER_HANDLE* phNotify) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcReplyOpenPrinter(WINSPOOL_HANDLE pMachine, WINSPOOL_PRINTER_HANDLE* phPrinterNotify, DWORD dwPrinterRemote, DWORD dwType, DWORD cbBuffer, BYTE* pBuffer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRouterFindFirstPrinterChangeNotificationOld() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRouterRefreshPrinterChangeNotification(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD dwColor, WINSPOOL_V2_NOTIFY_OPTIONS* pOptions, WINSPOOL_V2_NOTIFY_INFO** ppInfo) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRouterReplyPrinter(WINSPOOL_PRINTER_HANDLE hNotify, DWORD fdwFlags, DWORD cbBuffer, BYTE* pBuffer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcRouterReplyPrinterEx(WINSPOOL_PRINTER_HANDLE hNotify, DWORD dwColor, DWORD fdwFlags, DWORD* pdwResult, DWORD dwReplyType, WINSPOOL_V2_UREPLY_PRINTER Reply) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcWaitForPrinterChange(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Flags, DWORD* pFlags) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/ports.c =================================================================== --- win32ss/printing/base/spoolsv/ports.c (nonexistent) +++ win32ss/printing/base/spoolsv/ports.c (working copy) @@ -0,0 +1,93 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Ports + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallDownPortInfo(PBYTE pPortInfo, DWORD Level) +{ + PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)pPortInfo; // PORT_INFO_1W is a subset of PORT_INFO_2W + + // Replace absolute pointer addresses in the output by relative offsets. + pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName - (ULONG_PTR)pPortInfo2); + + if (Level == 2) + { + pPortInfo2->pDescription = (PWSTR)((ULONG_PTR)pPortInfo2->pDescription - (ULONG_PTR)pPortInfo2); + pPortInfo2->pMonitorName = (PWSTR)((ULONG_PTR)pPortInfo2->pMonitorName - (ULONG_PTR)pPortInfo2); + } +} + +DWORD +_RpcAddPort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pMonitorName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPortEx(WINSPOOL_HANDLE pName, WINSPOOL_PORT_CONTAINER* pPortContainer, WINSPOOL_PORT_VAR_CONTAINER* pPortVarContainer, WCHAR* pMonitorName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcConfigurePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePort(WINSPOOL_HANDLE pName, ULONG_PTR hWnd, WCHAR* pPortName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPort; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumPortsW(pName, Level, pPort, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownPortInfo(p, Level); + + if (Level == 1) + p += sizeof(PORT_INFO_1W); + else if (Level == 2) + p += sizeof(PORT_INFO_2W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcSetPort(WINSPOOL_HANDLE pName, WCHAR* pPortName, WINSPOOL_PORT_CONTAINER* pPortContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/precomp.h =================================================================== --- win32ss/printing/base/spoolsv/precomp.h (nonexistent) +++ win32ss/printing/base/spoolsv/precomp.h (working copy) @@ -0,0 +1,31 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include +#include +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(spoolsv); + +// rpcserver.c +DWORD WINAPI LrpcThreadProc(LPVOID lpParameter); + +// Undocumented spoolss +BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle); +DWORD WINAPI SpoolerInit(); + +#endif Index: win32ss/printing/base/spoolsv/printerdata.c =================================================================== --- win32ss/printing/base/spoolsv/printerdata.c (nonexistent) +++ win32ss/printing/base/spoolsv/printerdata.c (working copy) @@ -0,0 +1,78 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printer Configuration Data + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcDeletePrinterData(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pValueName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterDataEx(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName, const WCHAR* pValueName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterKey(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPrinterData(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD dwIndex, WCHAR* pValueName, DWORD cbValueName, DWORD* pcbValueName, DWORD* pType, BYTE* pData, DWORD cbData, DWORD* pcbData) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPrinterKey(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName, WCHAR* pSubkey, DWORD cbSubkey, DWORD* pcbSubkey) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPrinterDataEx(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName, BYTE* pEnumValues, DWORD cbEnumValues, DWORD* pcbEnumValues, DWORD* pnEnumValues) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinterData(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pValueName, DWORD* pType, BYTE* pData, DWORD nSize, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinterDataEx(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName, const WCHAR* pValueName, DWORD* pType, BYTE* pData, DWORD nSize, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSetPrinterData(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pValueName, DWORD Type, BYTE* pData, DWORD cbData) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSetPrinterDataEx(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pKeyName, const WCHAR* pValueName, DWORD Type, BYTE* pData, DWORD cbData) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/printerdrivers.c =================================================================== --- win32ss/printing/base/spoolsv/printerdrivers.c (nonexistent) +++ win32ss/printing/base/spoolsv/printerdrivers.c (working copy) @@ -0,0 +1,64 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printer Drivers + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcAddPrinterDriver(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPrinterDriverEx(WINSPOOL_HANDLE pName, WINSPOOL_DRIVER_CONTAINER* pDriverContainer, DWORD dwFileCopyFlags) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterDriver(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterDriverEx(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pDriverName, DWORD dwDeleteFlag, DWORD dwVersionNum) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPrinterDrivers(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDrivers, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinterDriver2(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pEnvironment, DWORD Level, BYTE* pDriver, DWORD cbBuf, DWORD* pcbNeeded, DWORD dwClientMajorVersion, DWORD dwClientMinorVersion, DWORD* pdwServerMaxVersion, DWORD* pdwServerMinVersion) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinterDriverDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pDriverDirectory, DWORD cbBuf, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/printers.c =================================================================== --- win32ss/printing/base/spoolsv/printers.c (nonexistent) +++ win32ss/printing/base/spoolsv/printers.c (working copy) @@ -0,0 +1,318 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printers and printing + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallDownPrinterInfo(PBYTE pPrinterInfo, DWORD Level) +{ + PPRINTER_INFO_1W pPrinterInfo1; + PPRINTER_INFO_2W pPrinterInfo2; + + // Replace absolute pointer addresses in the output by relative offsets. + if (Level == 1) + { + pPrinterInfo1 = (PPRINTER_INFO_1W)pPrinterInfo; + + pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName - (ULONG_PTR)pPrinterInfo1); + pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription - (ULONG_PTR)pPrinterInfo1); + pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment - (ULONG_PTR)pPrinterInfo1); + } + else if (Level == 2) + { + pPrinterInfo2 = (PPRINTER_INFO_2W)pPrinterInfo; + + pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pPortName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPortName - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDriverName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pDriverName - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo2->pComment - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pLocation = (PWSTR)((ULONG_PTR)pPrinterInfo2->pLocation - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo2->pDevMode - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pSepFile = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSepFile - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pPrintProcessor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrintProcessor - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDatatype = (PWSTR)((ULONG_PTR)pPrinterInfo2->pDatatype - (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pParameters = (PWSTR)((ULONG_PTR)pPrinterInfo2->pParameters - (ULONG_PTR)pPrinterInfo2); + + if (pPrinterInfo2->pServerName) + pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName - (ULONG_PTR)pPrinterInfo2); + + if (pPrinterInfo2->pSecurityDescriptor) + pPrinterInfo2->pSecurityDescriptor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor - (ULONG_PTR)pPrinterInfo2); + } +} + +DWORD +_RpcAbortPrinter(WINSPOOL_PRINTER_HANDLE hPrinter) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPrinter(WINSPOOL_HANDLE pName, WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, WINSPOOL_PRINTER_HANDLE* pHandle) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPrinterEx(WINSPOOL_HANDLE pName, WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, WINSPOOL_SPLCLIENT_CONTAINER* pClientInfo, WINSPOOL_PRINTER_HANDLE* pHandle) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcClosePrinter(WINSPOOL_PRINTER_HANDLE* phPrinter) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + if (ClosePrinter(*phPrinter)) + *phPrinter = NULL; + + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcDeletePrinter(WINSPOOL_PRINTER_HANDLE hPrinter) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EndDocPrinter(hPrinter); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcEndPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EndPagePrinter(hPrinter); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterEnum, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPrinterEnum; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownPrinterInfo(p, Level); + + if (Level == 1) + p += sizeof(PRINTER_INFO_1W); + else if (Level == 2) + p += sizeof(PRINTER_INFO_2W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcFlushPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWORD* pcWritten, DWORD cSleep) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pPrinter, DWORD cbBuf, DWORD* pcbNeeded) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* phPrinter, WCHAR* pDatatype, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, DWORD AccessRequired) +{ + DWORD dwErrorCode; + PRINTER_DEFAULTSW Default; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + Default.DesiredAccess = AccessRequired; + Default.pDatatype = pDatatype; + Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode; + + OpenPrinterW(pPrinterName, phPrinter, &Default); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcOpenPrinterEx(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* pHandle, WCHAR* pDatatype, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, DWORD AccessRequired, WINSPOOL_SPLCLIENT_CONTAINER* pClientInfo) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWORD* pcNoBytesRead) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + ReadPrinter(hPrinter, pBuf, cbBuf, pcNoBytesRead); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcResetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR* pDatatype, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcResetPrinterEx() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSeekPrinter() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_PRINTER_CONTAINER* pPrinterContainer, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer, WINSPOOL_SECURITY_CONTAINER* pSecurityContainer, DWORD Command) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcStartDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_DOC_INFO_CONTAINER* pDocInfoContainer, DWORD* pJobId) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + *pJobId = StartDocPrinterW(hPrinter, pDocInfoContainer->Level, (PBYTE)pDocInfoContainer->DocInfo.pDocInfo1); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + StartPagePrinter(hPrinter); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWORD* pcWritten) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + WritePrinter(hPrinter, pBuf, cbBuf, pcWritten); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} Index: win32ss/printing/base/spoolsv/printprocessors.c =================================================================== --- win32ss/printing/base/spoolsv/printprocessors.c (nonexistent) +++ win32ss/printing/base/spoolsv/printprocessors.c (working copy) @@ -0,0 +1,117 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Processors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallDownDatatypesInfo(PDATATYPES_INFO_1W pDatatypesInfo1) +{ + // Replace absolute pointer addresses in the output by relative offsets. + pDatatypesInfo1->pName = (PWSTR)((ULONG_PTR)pDatatypesInfo1->pName - (ULONG_PTR)pDatatypesInfo1); +} + +static void +_MarshallDownPrintProcessorInfo(PPRINTPROCESSOR_INFO_1W pPrintProcessorInfo1) +{ + // Replace absolute pointer addresses in the output by relative offsets. + pPrintProcessorInfo1->pName = (PWSTR)((ULONG_PTR)pPrintProcessorInfo1->pName - (ULONG_PTR)pPrintProcessorInfo1); +} + +DWORD +_RpcAddPrintProcessor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPathName, WCHAR* pPrintProcessorName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrintProcessor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPrintProcessorName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPrintProcessorDatatypes(WINSPOOL_HANDLE pName, WCHAR* pPrintProcessorName, DWORD Level, BYTE* pDatatypes, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pDatatypes; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownDatatypesInfo((PDATATYPES_INFO_1W)p); + p += sizeof(DATATYPES_INFO_1W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pPrintProcessorInfo, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPrintProcessorInfo; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned); + dwErrorCode = GetLastError(); + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace absolute pointer addresses in the output by relative offsets. + for (i = 0; i < *pcReturned; i++) + { + _MarshallDownPrintProcessorInfo((PPRINTPROCESSOR_INFO_1W)p); + p += sizeof(PRINTPROCESSOR_INFO_1W); + } + } + + RpcRevertToSelf(); + return dwErrorCode; +} + +DWORD +_RpcGetPrintProcessorDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pPrintProcessorDirectory, DWORD cbBuf, DWORD* pcbNeeded) +{ + DWORD dwErrorCode; + + dwErrorCode = RpcImpersonateClient(NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RpcImpersonateClient failed with error %lu!\n", dwErrorCode); + return dwErrorCode; + } + + GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded); + dwErrorCode = GetLastError(); + + RpcRevertToSelf(); + return dwErrorCode; +} Index: win32ss/printing/base/spoolsv/printproviders.c =================================================================== --- win32ss/printing/base/spoolsv/printproviders.c (nonexistent) +++ win32ss/printing/base/spoolsv/printproviders.c (working copy) @@ -0,0 +1,22 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Providers + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcAddPrintProvidor(WINSPOOL_HANDLE pName, WINSPOOL_PROVIDOR_CONTAINER* pProvidorContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrintProvidor(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, WCHAR* pPrintProviderName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/rpcserver.c =================================================================== --- win32ss/printing/base/spoolsv/rpcserver.c (nonexistent) +++ win32ss/printing/base/spoolsv/rpcserver.c (working copy) @@ -0,0 +1,58 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: RPC Server Thread + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD WINAPI +LrpcThreadProc(LPVOID lpParameter) +{ + RPC_STATUS Status; + + Status = RpcServerUseProtseqEpW(L"ncalrpc", 20, L"spoolss", NULL); + if (Status != RPC_S_OK) + { + ERR("RpcServerUseProtseqEpW failed with status %ld!\n", Status); + return 0; + } + + Status = RpcServerRegisterIf(winspool_v1_0_s_ifspec, NULL, NULL); + if (Status != RPC_S_OK) + { + ERR("RpcServerRegisterIf failed with status %ld!\n", Status); + return 0; + } + + Status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, 0); + if (Status != RPC_S_OK) + { + ERR("RpcServerListen() failed with status %ld!\n", Status); + } + + return 0; +} + +void __RPC_FAR* __RPC_USER +midl_user_allocate(SIZE_T len) +{ + return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); +} + +void __RPC_USER +midl_user_free(void __RPC_FAR* ptr) +{ + HeapFree(GetProcessHeap(), 0, ptr); +} + +void __RPC_USER +WINSPOOL_GDI_HANDLE_rundown(WINSPOOL_GDI_HANDLE hGdiHandle) +{ +} + +void __RPC_USER +WINSPOOL_PRINTER_HANDLE_rundown(WINSPOOL_PRINTER_HANDLE hPrinter) +{ +} Index: win32ss/printing/base/spoolsv/rpcstubs.c =================================================================== --- win32ss/printing/base/spoolsv/rpcstubs.c (nonexistent) +++ win32ss/printing/base/spoolsv/rpcstubs.c (working copy) @@ -0,0 +1,141 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Unimplemented RPC calls + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcCreatePrinterIC(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_GDI_HANDLE* pHandle, WINSPOOL_DEVMODE_CONTAINER* pDevModeContainer) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcPlayGdiScriptOnPrinterIC(WINSPOOL_GDI_HANDLE hPrinterIC, BYTE* pIn, DWORD cIn, BYTE* pOut, DWORD cOut, DWORD ul) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterIC(WINSPOOL_GDI_HANDLE* phPrinterIC) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPrinterConnection(WINSPOOL_HANDLE pName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePrinterConnection(WINSPOOL_HANDLE pName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcPrinterMessageBox(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Error, ULONG_PTR hWnd, WCHAR* pText, WCHAR* pCaption, DWORD dwType) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSetAllocFailCount() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcClusterSplOpen() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcClusterSplClose() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcClusterSplIsAlive() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddPerMachineConnection(WINSPOOL_HANDLE pServer, const WCHAR* pPrinterName, const WCHAR* pPrintServer, const WCHAR* pProvider) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcDeletePerMachineConnection(WINSPOOL_HANDLE pServer, const WCHAR* pPrinterName) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcEnumPerMachineConnections(WINSPOOL_HANDLE pServer, BYTE* pPrinterEnum, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSplOpenPrinter() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcGetSpoolFileInfo() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcCommitSpoolData() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcCloseSpoolFileHandle() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcSendRecvBidiData(WINSPOOL_PRINTER_HANDLE hPrinter, const WCHAR* pAction, WINSPOOL_BIDI_REQUEST_CONTAINER* pReqData, WINSPOOL_BIDI_RESPONSE_CONTAINER** ppRespData) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} + +DWORD +_RpcAddDriverCatalog() +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/spoolsv/spoolsv.rc =================================================================== --- win32ss/printing/base/spoolsv/spoolsv.rc (nonexistent) +++ win32ss/printing/base/spoolsv/spoolsv.rc (working copy) @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Print Spooler Service" +#define REACTOS_STR_INTERNAL_NAME "spoolsv" +#define REACTOS_STR_ORIGINAL_FILENAME "spoolsv.exe" +#include Index: win32ss/printing/base/spoolsv/xcv.c =================================================================== --- win32ss/printing/base/spoolsv/xcv.c (nonexistent) +++ win32ss/printing/base/spoolsv/xcv.c (working copy) @@ -0,0 +1,15 @@ +/* + * PROJECT: ReactOS Print Spooler Service + * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Xcv* functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD +_RpcXcvData(WINSPOOL_PRINTER_HANDLE hXcv, const WCHAR* pszDataName, BYTE* pInputData, DWORD cbInputData, BYTE* pOutputData, DWORD cbOutputData, DWORD* pcbOutputNeeded, DWORD* pdwStatus) +{ + UNIMPLEMENTED; + return ERROR_INVALID_FUNCTION; +} Index: win32ss/printing/base/winspool/CMakeLists.txt =================================================================== --- win32ss/printing/base/winspool/CMakeLists.txt (nonexistent) +++ win32ss/printing/base/winspool/CMakeLists.txt (working copy) @@ -0,0 +1,31 @@ + +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl) +add_rpc_files(client ${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/winspool.idl) +spec2def(winspool.drv winspool.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + devmode.c + jobs.c + main.c + monitors.c + ports.c + precomp.h + printerdata.c + printerdrivers.c + printers.c + printprocessors.c + printproviders.c + ${CMAKE_CURRENT_BINARY_DIR}/winspool_c.c) + +add_library(winspool SHARED + ${SOURCE} + winspool.rc + ${CMAKE_CURRENT_BINARY_DIR}/winspool_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/winspool.def) + +set_target_properties(winspool PROPERTIES SUFFIX ".drv") +set_module_type(winspool win32dll UNICODE) +target_link_libraries(winspool wine ${PSEH_LIB}) +add_importlibs(winspool gdi32 rpcrt4 msvcrt kernel32 ntdll) +add_pch(winspool precomp.h SOURCE) +add_cd_file(TARGET winspool DESTINATION reactos/system32 FOR all) Index: win32ss/printing/base/winspool/devmode.c =================================================================== --- win32ss/printing/base/winspool/devmode.c (nonexistent) +++ win32ss/printing/base/winspool/devmode.c (working copy) @@ -0,0 +1,231 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions giving information about DEVMODE structures + * COPYRIGHT: Copyright 2016 Colin Finck + */ + +#include "precomp.h" + +typedef struct _MINIMUM_SIZE_TABLE +{ + DWORD dwField; + WORD wSize; +} +MINIMUM_SIZE_TABLE, *PMINIMUM_SIZE_TABLE; + +/** + * Minimum required DEVMODEA structure size based on the used fields. Must be in descending order! + */ +static MINIMUM_SIZE_TABLE MinimumSizeA[] = { + { DM_PANNINGHEIGHT, FIELD_OFFSET(DEVMODEA, dmPanningHeight) + RTL_FIELD_SIZE(DEVMODEA, dmPanningHeight) }, + { DM_PANNINGWIDTH, FIELD_OFFSET(DEVMODEA, dmPanningWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPanningWidth) }, + { DM_DITHERTYPE, FIELD_OFFSET(DEVMODEA, dmDitherType) + RTL_FIELD_SIZE(DEVMODEA, dmDitherType) }, + { DM_MEDIATYPE, FIELD_OFFSET(DEVMODEA, dmMediaType) + RTL_FIELD_SIZE(DEVMODEA, dmMediaType) }, + { DM_ICMINTENT, FIELD_OFFSET(DEVMODEA, dmICMIntent) + RTL_FIELD_SIZE(DEVMODEA, dmICMIntent) }, + { DM_ICMMETHOD, FIELD_OFFSET(DEVMODEA, dmICMMethod) + RTL_FIELD_SIZE(DEVMODEA, dmICMMethod) }, + { DM_DISPLAYFREQUENCY, FIELD_OFFSET(DEVMODEA, dmDisplayFrequency) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFrequency) }, + { DM_NUP, FIELD_OFFSET(DEVMODEA, dmNup) + RTL_FIELD_SIZE(DEVMODEA, dmNup) }, + { DM_DISPLAYFLAGS, FIELD_OFFSET(DEVMODEA, dmDisplayFlags) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFlags) }, + { DM_PELSHEIGHT, FIELD_OFFSET(DEVMODEA, dmPelsHeight) + RTL_FIELD_SIZE(DEVMODEA, dmPelsHeight) }, + { DM_PELSWIDTH, FIELD_OFFSET(DEVMODEA, dmPelsWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPelsWidth) }, + { DM_BITSPERPEL, FIELD_OFFSET(DEVMODEA, dmBitsPerPel) + RTL_FIELD_SIZE(DEVMODEA, dmBitsPerPel) }, + { DM_LOGPIXELS, FIELD_OFFSET(DEVMODEA, dmLogPixels) + RTL_FIELD_SIZE(DEVMODEA, dmLogPixels) }, + { DM_FORMNAME, FIELD_OFFSET(DEVMODEA, dmFormName) + RTL_FIELD_SIZE(DEVMODEA, dmFormName) }, + { DM_COLLATE, FIELD_OFFSET(DEVMODEA, dmCollate) + RTL_FIELD_SIZE(DEVMODEA, dmCollate) }, + { DM_TTOPTION, FIELD_OFFSET(DEVMODEA, dmTTOption) + RTL_FIELD_SIZE(DEVMODEA, dmTTOption) }, + { DM_YRESOLUTION, FIELD_OFFSET(DEVMODEA, dmYResolution) + RTL_FIELD_SIZE(DEVMODEA, dmYResolution) }, + { DM_DUPLEX, FIELD_OFFSET(DEVMODEA, dmDuplex) + RTL_FIELD_SIZE(DEVMODEA, dmDuplex) }, + { DM_COLOR, FIELD_OFFSET(DEVMODEA, dmColor) + RTL_FIELD_SIZE(DEVMODEA, dmColor) }, + { DM_DISPLAYFIXEDOUTPUT, FIELD_OFFSET(DEVMODEA, dmDisplayFixedOutput) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFixedOutput) }, + { DM_DISPLAYORIENTATION, FIELD_OFFSET(DEVMODEA, dmDisplayOrientation) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayOrientation) }, + { DM_POSITION, FIELD_OFFSET(DEVMODEA, dmPosition) + RTL_FIELD_SIZE(DEVMODEA, dmPosition) }, + { DM_PRINTQUALITY, FIELD_OFFSET(DEVMODEA, dmPrintQuality) + RTL_FIELD_SIZE(DEVMODEA, dmPrintQuality) }, + { DM_DEFAULTSOURCE, FIELD_OFFSET(DEVMODEA, dmDefaultSource) + RTL_FIELD_SIZE(DEVMODEA, dmDefaultSource) }, + { DM_COPIES, FIELD_OFFSET(DEVMODEA, dmCopies) + RTL_FIELD_SIZE(DEVMODEA, dmCopies) }, + { DM_SCALE, FIELD_OFFSET(DEVMODEA, dmScale) + RTL_FIELD_SIZE(DEVMODEA, dmScale) }, + { DM_PAPERWIDTH, FIELD_OFFSET(DEVMODEA, dmPaperWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPaperWidth) }, + { DM_PAPERLENGTH, FIELD_OFFSET(DEVMODEA, dmPaperLength) + RTL_FIELD_SIZE(DEVMODEA, dmPaperLength) }, + { DM_PAPERSIZE, FIELD_OFFSET(DEVMODEA, dmPaperSize) + RTL_FIELD_SIZE(DEVMODEA, dmPaperSize) }, + { DM_ORIENTATION, FIELD_OFFSET(DEVMODEA, dmOrientation) + RTL_FIELD_SIZE(DEVMODEA, dmOrientation) }, + { 0, 0 } +}; + +/** + * Minimum required DEVMODEW structure size based on the used fields. Must be in descending order! + */ +static MINIMUM_SIZE_TABLE MinimumSizeW[] = { + { DM_PANNINGHEIGHT, FIELD_OFFSET(DEVMODEW, dmPanningHeight) + RTL_FIELD_SIZE(DEVMODEW, dmPanningHeight) }, + { DM_PANNINGWIDTH, FIELD_OFFSET(DEVMODEW, dmPanningWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPanningWidth) }, + { DM_DITHERTYPE, FIELD_OFFSET(DEVMODEW, dmDitherType) + RTL_FIELD_SIZE(DEVMODEW, dmDitherType) }, + { DM_MEDIATYPE, FIELD_OFFSET(DEVMODEW, dmMediaType) + RTL_FIELD_SIZE(DEVMODEW, dmMediaType) }, + { DM_ICMINTENT, FIELD_OFFSET(DEVMODEW, dmICMIntent) + RTL_FIELD_SIZE(DEVMODEW, dmICMIntent) }, + { DM_ICMMETHOD, FIELD_OFFSET(DEVMODEW, dmICMMethod) + RTL_FIELD_SIZE(DEVMODEW, dmICMMethod) }, + { DM_DISPLAYFREQUENCY, FIELD_OFFSET(DEVMODEW, dmDisplayFrequency) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFrequency) }, + { DM_NUP, FIELD_OFFSET(DEVMODEW, dmNup) + RTL_FIELD_SIZE(DEVMODEW, dmNup) }, + { DM_DISPLAYFLAGS, FIELD_OFFSET(DEVMODEW, dmDisplayFlags) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFlags) }, + { DM_PELSHEIGHT, FIELD_OFFSET(DEVMODEW, dmPelsHeight) + RTL_FIELD_SIZE(DEVMODEW, dmPelsHeight) }, + { DM_PELSWIDTH, FIELD_OFFSET(DEVMODEW, dmPelsWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPelsWidth) }, + { DM_BITSPERPEL, FIELD_OFFSET(DEVMODEW, dmBitsPerPel) + RTL_FIELD_SIZE(DEVMODEW, dmBitsPerPel) }, + { DM_LOGPIXELS, FIELD_OFFSET(DEVMODEW, dmLogPixels) + RTL_FIELD_SIZE(DEVMODEW, dmLogPixels) }, + { DM_FORMNAME, FIELD_OFFSET(DEVMODEW, dmFormName) + RTL_FIELD_SIZE(DEVMODEW, dmFormName) }, + { DM_COLLATE, FIELD_OFFSET(DEVMODEW, dmCollate) + RTL_FIELD_SIZE(DEVMODEW, dmCollate) }, + { DM_TTOPTION, FIELD_OFFSET(DEVMODEW, dmTTOption) + RTL_FIELD_SIZE(DEVMODEW, dmTTOption) }, + { DM_YRESOLUTION, FIELD_OFFSET(DEVMODEW, dmYResolution) + RTL_FIELD_SIZE(DEVMODEW, dmYResolution) }, + { DM_DUPLEX, FIELD_OFFSET(DEVMODEW, dmDuplex) + RTL_FIELD_SIZE(DEVMODEW, dmDuplex) }, + { DM_COLOR, FIELD_OFFSET(DEVMODEW, dmColor) + RTL_FIELD_SIZE(DEVMODEW, dmColor) }, + { DM_DISPLAYFIXEDOUTPUT, FIELD_OFFSET(DEVMODEW, dmDisplayFixedOutput) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFixedOutput) }, + { DM_DISPLAYORIENTATION, FIELD_OFFSET(DEVMODEW, dmDisplayOrientation) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayOrientation) }, + { DM_POSITION, FIELD_OFFSET(DEVMODEW, dmPosition) + RTL_FIELD_SIZE(DEVMODEW, dmPosition) }, + { DM_PRINTQUALITY, FIELD_OFFSET(DEVMODEW, dmPrintQuality) + RTL_FIELD_SIZE(DEVMODEW, dmPrintQuality) }, + { DM_DEFAULTSOURCE, FIELD_OFFSET(DEVMODEW, dmDefaultSource) + RTL_FIELD_SIZE(DEVMODEW, dmDefaultSource) }, + { DM_COPIES, FIELD_OFFSET(DEVMODEW, dmCopies) + RTL_FIELD_SIZE(DEVMODEW, dmCopies) }, + { DM_SCALE, FIELD_OFFSET(DEVMODEW, dmScale) + RTL_FIELD_SIZE(DEVMODEW, dmScale) }, + { DM_PAPERWIDTH, FIELD_OFFSET(DEVMODEW, dmPaperWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPaperWidth) }, + { DM_PAPERLENGTH, FIELD_OFFSET(DEVMODEW, dmPaperLength) + RTL_FIELD_SIZE(DEVMODEW, dmPaperLength) }, + { DM_PAPERSIZE, FIELD_OFFSET(DEVMODEW, dmPaperSize) + RTL_FIELD_SIZE(DEVMODEW, dmPaperSize) }, + { DM_ORIENTATION, FIELD_OFFSET(DEVMODEW, dmOrientation) + RTL_FIELD_SIZE(DEVMODEW, dmOrientation) }, + { 0, 0 } +}; + +/** + * Replace the last character by a null terminator if the given ANSI string is not null-terminated. + */ +static __inline void +_FixStringA(PBYTE String, DWORD cbString) +{ + const PBYTE pLastCharacter = &String[cbString / sizeof(BYTE) - 1]; + PBYTE p = String; + + while (*p) + { + if (p == pLastCharacter) + { + *p = 0; + break; + } + + p++; + } +} + +/** + * Replace the last character by a null terminator if the given Unicode string is not null-terminated. + */ +static __inline void +_FixStringW(PWSTR String, DWORD cbString) +{ + const PWSTR pLastCharacter = &String[cbString / sizeof(WCHAR) - 1]; + PWSTR p = String; + + while (*p) + { + if (p == pLastCharacter) + { + *p = 0; + break; + } + + p++; + } +} + +BOOL WINAPI +IsValidDevmodeA(PDEVMODEA pDevmode, size_t DevmodeSize) +{ + PMINIMUM_SIZE_TABLE pTable = MinimumSizeA; + WORD wRequiredSize; + + // Check if a Devmode was given at all. + if (!pDevmode) + goto Failure; + + // Verify that DevmodeSize is large enough to hold the public and private members of the structure. + if (DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra) + goto Failure; + + // If the structure has private members, the public structure must be 32-bit packed. + if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4) + goto Failure; + + // Now determine the minimum possible dmSize based on the given fields in dmFields. + wRequiredSize = FIELD_OFFSET(DEVMODEA, dmFields) + RTL_FIELD_SIZE(DEVMODEA, dmFields); + + while (pTable->dwField) + { + if (pDevmode->dmFields & pTable->dwField) + { + wRequiredSize = pTable->wSize; + break; + } + + pTable++; + } + + // Verify that the value in dmSize is big enough for the used fields. + if (pDevmode->dmSize < wRequiredSize) + goto Failure; + + // Check if dmDeviceName and (if used) dmFormName are null-terminated. + // Fix this if they aren't. + _FixStringA(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName)); + if (pDevmode->dmFields & DM_FORMNAME) + _FixStringA(pDevmode->dmFormName, sizeof(pDevmode->dmFormName)); + + // Return success without setting the error code. + return TRUE; + +Failure: + SetLastError(ERROR_INVALID_DATA); + return FALSE; +} + +BOOL WINAPI +IsValidDevmodeW(PDEVMODEW pDevmode, size_t DevmodeSize) +{ + PMINIMUM_SIZE_TABLE pTable = MinimumSizeW; + WORD wRequiredSize; + + // Check if a Devmode was given at all. + if (!pDevmode) + goto Failure; + + // Verify that DevmodeSize is large enough to hold the public and private members of the structure. + if (DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra) + goto Failure; + + // If the structure has private members, the public structure must be 32-bit packed. + if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4) + goto Failure; + + // Now determine the minimum possible dmSize based on the given fields in dmFields. + wRequiredSize = FIELD_OFFSET(DEVMODEW, dmFields) + RTL_FIELD_SIZE(DEVMODEW, dmFields); + + while (pTable->dwField) + { + if (pDevmode->dmFields & pTable->dwField) + { + wRequiredSize = pTable->wSize; + break; + } + + pTable++; + } + + // Verify that the value in dmSize is big enough for the used fields. + if (pDevmode->dmSize < wRequiredSize) + goto Failure; + + // Check if dmDeviceName and (if used) dmFormName are null-terminated. + // Fix this if they aren't. + _FixStringW(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName)); + if (pDevmode->dmFields & DM_FORMNAME) + _FixStringW(pDevmode->dmFormName, sizeof(pDevmode->dmFormName)); + + // Return success without setting the error code. + return TRUE; + +Failure: + SetLastError(ERROR_INVALID_DATA); + return FALSE; +} Index: win32ss/printing/base/winspool/jobs.c =================================================================== --- win32ss/printing/base/winspool/jobs.c (nonexistent) +++ win32ss/printing/base/winspool/jobs.c (working copy) @@ -0,0 +1,260 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions for managing print jobs + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallUpAddJobInfo(PADDJOB_INFO_1W pAddJobInfo1) +{ + // Replace relative offset addresses in the output by absolute pointers. + pAddJobInfo1->Path = (PWSTR)((ULONG_PTR)pAddJobInfo1->Path + (ULONG_PTR)pAddJobInfo1); +} + +static void +_MarshallUpJobInfo(PBYTE pJobInfo, DWORD Level) +{ + PJOB_INFO_1W pJobInfo1; + PJOB_INFO_2W pJobInfo2; + + // Replace relative offset addresses in the output by absolute pointers. + if (Level == 1) + { + pJobInfo1 = (PJOB_INFO_1W)pJobInfo; + pJobInfo1->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo1->pDatatype + (ULONG_PTR)pJobInfo1); + pJobInfo1->pDocument = (PWSTR)((ULONG_PTR)pJobInfo1->pDocument + (ULONG_PTR)pJobInfo1); + pJobInfo1->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo1->pMachineName + (ULONG_PTR)pJobInfo1); + pJobInfo1->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo1->pPrinterName + (ULONG_PTR)pJobInfo1); + + if (pJobInfo1->pStatus) + pJobInfo1->pStatus = (PWSTR)((ULONG_PTR)pJobInfo1->pStatus + (ULONG_PTR)pJobInfo1); + + pJobInfo1->pUserName = (PWSTR)((ULONG_PTR)pJobInfo1->pUserName + (ULONG_PTR)pJobInfo1); + } + else if (Level == 2) + { + pJobInfo2 = (PJOB_INFO_2W)pJobInfo; + pJobInfo2->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo2->pDatatype + (ULONG_PTR)pJobInfo2); + pJobInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pJobInfo2->pDevMode + (ULONG_PTR)pJobInfo2); + pJobInfo2->pDocument = (PWSTR)((ULONG_PTR)pJobInfo2->pDocument + (ULONG_PTR)pJobInfo2); + pJobInfo2->pDriverName = (PWSTR)((ULONG_PTR)pJobInfo2->pDriverName + (ULONG_PTR)pJobInfo2); + pJobInfo2->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo2->pMachineName + (ULONG_PTR)pJobInfo2); + pJobInfo2->pNotifyName = (PWSTR)((ULONG_PTR)pJobInfo2->pNotifyName + (ULONG_PTR)pJobInfo2); + pJobInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pJobInfo2->pPrinterName + (ULONG_PTR)pJobInfo2); + pJobInfo2->pPrintProcessor = (PWSTR)((ULONG_PTR)pJobInfo2->pPrintProcessor + (ULONG_PTR)pJobInfo2); + + if (pJobInfo2->pParameters) + pJobInfo2->pParameters = (PWSTR)((ULONG_PTR)pJobInfo2->pParameters + (ULONG_PTR)pJobInfo2); + + if (pJobInfo2->pStatus) + pJobInfo2->pStatus = (PWSTR)((ULONG_PTR)pJobInfo2->pStatus + (ULONG_PTR)pJobInfo2); + + pJobInfo2->pUserName = (PWSTR)((ULONG_PTR)pJobInfo2->pUserName + (ULONG_PTR)pJobInfo2); + } +} + +BOOL WINAPI +AddJobA(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcAddJob failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + _MarshallUpAddJobInfo((PADDJOB_INFO_1W)pData); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pJob; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumJobs failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpJobInfo(p, Level); + + if (Level == 1) + p += sizeof(JOB_INFO_1W); + else if (Level == 2) + p += sizeof(JOB_INFO_2W); + } + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +GetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcGetJob failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + _MarshallUpJobInfo(pJob, Level); + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +ScheduleJob(HANDLE hPrinter, DWORD dwJobID) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, dwJobID); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + WINSPOOL_JOB_CONTAINER JobContainer; + + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // pJobContainer->JobInfo is a union of pointers, so we can just set any element to our BYTE pointer. + JobContainer.Level = Level; + JobContainer.JobInfo.Level1 = (WINSPOOL_JOB_INFO_1*)pJobInfo; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcSetJob(pHandle->hPrinter, JobId, &JobContainer, Command); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcSetJob failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/base/winspool/main.c =================================================================== --- win32ss/printing/base/winspool/main.c (nonexistent) +++ win32ss/printing/base/winspool/main.c (working copy) @@ -0,0 +1,106 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +HANDLE hProcessHeap; + + +handle_t __RPC_USER +WINSPOOL_HANDLE_bind(WINSPOOL_HANDLE wszName) +{ + handle_t hBinding; + PWSTR wszStringBinding; + RPC_STATUS Status; + + // Get us a string binding handle from the supplied connection information + Status = RpcStringBindingComposeW(NULL, L"ncalrpc", NULL, L"spoolss", NULL, &wszStringBinding); + if (Status != RPC_S_OK) + { + ERR("RpcStringBindingComposeW failed with status %ld!\n", Status); + return NULL; + } + + // Get a handle_t binding handle from the string binding handle + Status = RpcBindingFromStringBindingW(wszStringBinding, &hBinding); + if (Status != RPC_S_OK) + { + ERR("RpcBindingFromStringBindingW failed with status %ld!\n", Status); + return NULL; + } + + // Free the string binding handle + Status = RpcStringFreeW(&wszStringBinding); + if (Status != RPC_S_OK) + { + ERR("RpcStringFreeW failed with status %ld!\n", Status); + return NULL; + } + + return hBinding; +} + +void __RPC_USER +WINSPOOL_HANDLE_unbind(WINSPOOL_HANDLE wszName, handle_t hBinding) +{ + RPC_STATUS Status; + + Status = RpcBindingFree(&hBinding); + if (Status != RPC_S_OK) + { + ERR("RpcBindingFree failed with status %ld!\n", Status); + } +} + +void __RPC_FAR* __RPC_USER +midl_user_allocate(SIZE_T len) +{ + return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, len); +} + +void __RPC_USER +midl_user_free(void __RPC_FAR* ptr) +{ + HeapFree(hProcessHeap, 0, ptr); +} + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + hProcessHeap = GetProcessHeap(); + break; + } + + return TRUE; +} + +BOOL WINAPI +SpoolerInit() +{ + BOOL bReturnValue = FALSE; + DWORD dwErrorCode; + + // Nothing to initialize here yet, but pass this call to the Spool Service as well. + RpcTryExcept + { + dwErrorCode = _RpcSpoolerInit(); + SetLastError(dwErrorCode); + bReturnValue = (dwErrorCode == ERROR_SUCCESS); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + ERR("_RpcSpoolerInit failed with exception code %lu!\n", RpcExceptionCode()); + } + RpcEndExcept; + + return bReturnValue; +} Index: win32ss/printing/base/winspool/monitors.c =================================================================== --- win32ss/printing/base/winspool/monitors.c (nonexistent) +++ win32ss/printing/base/winspool/monitors.c (working copy) @@ -0,0 +1,74 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallUpMonitorInfo(PBYTE pMonitorInfo, DWORD Level) +{ + PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)pMonitorInfo; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W + + // Replace relative offset addresses in the output by absolute pointers. + pMonitorInfo2->pName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pName + (ULONG_PTR)pMonitorInfo2); + + if (Level == 2) + { + pMonitorInfo2->pDLLName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pDLLName + (ULONG_PTR)pMonitorInfo2); + pMonitorInfo2->pEnvironment = (PWSTR)((ULONG_PTR)pMonitorInfo2->pEnvironment + (ULONG_PTR)pMonitorInfo2); + } +} + +BOOL WINAPI +AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pMonitors; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumMonitors(pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpMonitorInfo(p, Level); + + if (Level == 1) + p += sizeof(MONITOR_INFO_1W); + else if (Level == 2) + p += sizeof(MONITOR_INFO_2W); + } + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/base/winspool/ports.c =================================================================== --- win32ss/printing/base/winspool/ports.c (nonexistent) +++ win32ss/printing/base/winspool/ports.c (working copy) @@ -0,0 +1,81 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Ports + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallUpPortInfo(PBYTE pPortInfo, DWORD Level) +{ + PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)pPortInfo; // PORT_INFO_1W is a subset of PORT_INFO_2W + + // Replace relative offset addresses in the output by absolute pointers. + pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName + (ULONG_PTR)pPortInfo2); + + if (Level == 2) + { + pPortInfo2->pDescription = (PWSTR)((ULONG_PTR)pPortInfo2->pDescription + (ULONG_PTR)pPortInfo2); + pPortInfo2->pMonitorName = (PWSTR)((ULONG_PTR)pPortInfo2->pMonitorName + (ULONG_PTR)pPortInfo2); + } +} + +BOOL WINAPI +AddPortW(PWSTR pName, HWND hWnd, PWSTR pMonitorName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +ConfigurePortW(PWSTR pName, HWND hWnd, PWSTR pPortName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +DeletePortW(PWSTR pName, HWND hWnd, PWSTR pPortName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPorts; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumPorts(pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPorts failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpPortInfo(p, Level); + + if (Level == 1) + p += sizeof(PORT_INFO_1W); + else if (Level == 2) + p += sizeof(PORT_INFO_2W); + } + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/base/winspool/precomp.h =================================================================== --- win32ss/printing/base/winspool/precomp.h (nonexistent) +++ win32ss/printing/base/winspool/precomp.h (working copy) @@ -0,0 +1,38 @@ +/* + * PROJECT: ReactOS Print Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(winspool); + +// Structures +/* + * Describes a handle returned by OpenPrinterW. + */ +typedef struct _SPOOLER_HANDLE +{ + BOOL bStartedDoc : 1; + DWORD dwJobID; + HANDLE hPrinter; + HANDLE hSPLFile; +} +SPOOLER_HANDLE, *PSPOOLER_HANDLE; + +// main.c +extern HANDLE hProcessHeap; + +#endif Index: win32ss/printing/base/winspool/printerdata.c =================================================================== --- win32ss/printing/base/winspool/printerdata.c (nonexistent) +++ win32ss/printing/base/winspool/printerdata.c (working copy) @@ -0,0 +1,29 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printer Configuration Data + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +LONG WINAPI +AdvancedDocumentPropertiesW(HWND hWnd, HANDLE hPrinter, PWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput) +{ + UNIMPLEMENTED; + return FALSE; +} + +DWORD WINAPI +GetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded) +{ + UNIMPLEMENTED; + return FALSE; +} + +DWORD WINAPI +SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData) +{ + UNIMPLEMENTED; + return FALSE; +} Index: win32ss/printing/base/winspool/printerdrivers.c =================================================================== --- win32ss/printing/base/winspool/printerdrivers.c (nonexistent) +++ win32ss/printing/base/winspool/printerdrivers.c (working copy) @@ -0,0 +1,36 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printer Drivers + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +AddPrinterDriverW(PWSTR pName, DWORD Level, PBYTE pDriverInfo) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +DeletePrinterDriverW(PWSTR pName, PWSTR pEnvironment, PWSTR pDriverName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumPrinterDriversW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +GetPrinterDriverDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pDriverDirectory, DWORD cbBuf, PDWORD pcbNeeded) +{ + UNIMPLEMENTED; + return FALSE; +} Index: win32ss/printing/base/winspool/printers.c =================================================================== --- win32ss/printing/base/winspool/printers.c (nonexistent) +++ win32ss/printing/base/winspool/printers.c (working copy) @@ -0,0 +1,799 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printers and printing + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallUpPrinterInfo(PBYTE pPrinterInfo, DWORD Level) +{ + PPRINTER_INFO_1W pPrinterInfo1; + PPRINTER_INFO_2W pPrinterInfo2; + + // Replace relative offset addresses in the output by absolute pointers. + if (Level == 1) + { + pPrinterInfo1 = (PPRINTER_INFO_1W)pPrinterInfo; + + pPrinterInfo1->pName = (PWSTR)((ULONG_PTR)pPrinterInfo1->pName + (ULONG_PTR)pPrinterInfo1); + pPrinterInfo1->pDescription = (PWSTR)((ULONG_PTR)pPrinterInfo1->pDescription + (ULONG_PTR)pPrinterInfo1); + pPrinterInfo1->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo1->pComment + (ULONG_PTR)pPrinterInfo1); + } + else if (Level == 2) + { + pPrinterInfo2 = (PPRINTER_INFO_2W)pPrinterInfo; + + pPrinterInfo2->pPrinterName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrinterName + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pShareName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pShareName + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pPortName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPortName + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDriverName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pDriverName + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pComment = (PWSTR)((ULONG_PTR)pPrinterInfo2->pComment + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pLocation = (PWSTR)((ULONG_PTR)pPrinterInfo2->pLocation + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pPrinterInfo2->pDevMode + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pSepFile = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSepFile + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pPrintProcessor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pPrintProcessor + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pDatatype = (PWSTR)((ULONG_PTR)pPrinterInfo2->pDatatype + (ULONG_PTR)pPrinterInfo2); + pPrinterInfo2->pParameters = (PWSTR)((ULONG_PTR)pPrinterInfo2->pParameters + (ULONG_PTR)pPrinterInfo2); + + if (pPrinterInfo2->pServerName) + pPrinterInfo2->pServerName = (PWSTR)((ULONG_PTR)pPrinterInfo2->pServerName + (ULONG_PTR)pPrinterInfo2); + + if (pPrinterInfo2->pSecurityDescriptor) + pPrinterInfo2->pSecurityDescriptor = (PWSTR)((ULONG_PTR)pPrinterInfo2->pSecurityDescriptor + (ULONG_PTR)pPrinterInfo2); + } +} + +static DWORD +_StartDocPrinterSpooled(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1, PADDJOB_INFO_1W pAddJobInfo1) +{ + DWORD cbNeeded; + DWORD dwErrorCode; + PJOB_INFO_1W pJobInfo1 = NULL; + + // Create the spool file. + pHandle->hSPLFile = CreateFileW(pAddJobInfo1->Path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + if (pHandle->hSPLFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = GetLastError(); + ERR("CreateFileW failed for \"%S\" with error %lu!\n", pAddJobInfo1->Path, dwErrorCode); + goto Cleanup; + } + + // Get the size of the job information. + GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, NULL, 0, &cbNeeded); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + dwErrorCode = GetLastError(); + ERR("GetJobW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Allocate enough memory for the returned job information. + pJobInfo1 = HeapAlloc(hProcessHeap, 0, cbNeeded); + if (!pJobInfo1) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("HeapAlloc failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the job information. + if (!GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, cbNeeded, &cbNeeded)) + { + dwErrorCode = GetLastError(); + ERR("GetJobW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Add our document information. + if (pDocInfo1->pDatatype) + pJobInfo1->pDatatype = pDocInfo1->pDatatype; + + pJobInfo1->pDocument = pDocInfo1->pDocName; + + // Set the new job information. + if (!SetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, 0)) + { + dwErrorCode = GetLastError(); + ERR("SetJobW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We were successful! + pHandle->dwJobID = pAddJobInfo1->JobId; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pJobInfo1) + HeapFree(hProcessHeap, 0, pJobInfo1); + + return dwErrorCode; +} + +static DWORD +_StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1) +{ + DWORD dwErrorCode; + WINSPOOL_DOC_INFO_CONTAINER DocInfoContainer; + + DocInfoContainer.Level = 1; + DocInfoContainer.DocInfo.pDocInfo1 = (WINSPOOL_DOC_INFO_1*)pDocInfo1; + + RpcTryExcept + { + dwErrorCode = _RpcStartDocPrinter(pHandle->hPrinter, &DocInfoContainer, &pHandle->dwJobID); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcStartDocPrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + return dwErrorCode; +} + +HANDLE WINAPI +AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter) +{ + UNIMPLEMENTED; + return NULL; +} + +BOOL WINAPI +ClosePrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call. + RpcTryExcept + { + dwErrorCode = _RpcClosePrinter(pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcClosePrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + // Close any open file handle. + if (pHandle->hSPLFile != INVALID_HANDLE_VALUE) + CloseHandle(pHandle->hSPLFile); + + // Free the memory for the handle. + HeapFree(hProcessHeap, 0, pHandle); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); + +} + +DWORD WINAPI +DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode) +{ + return 0; +} + +DWORD WINAPI +DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode) +{ + return 0; +} + +LONG WINAPI +DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode) +{ + return 0; +} + +LONG WINAPI +DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode) +{ + return 0; +} + +BOOL WINAPI +EndDocPrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if (pHandle->hSPLFile != INVALID_HANDLE_VALUE) + { + // For spooled jobs, the document is finished by calling _RpcScheduleJob. + RpcTryExcept + { + dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + // Close the spool file handle. + CloseHandle(pHandle->hSPLFile); + } + else + { + // In all other cases, just call _RpcEndDocPrinter. + RpcTryExcept + { + dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + } + + // A new document can now be started again. + pHandle->bStartedDoc = FALSE; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +EndPagePrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if (pHandle->hSPLFile != INVALID_HANDLE_VALUE) + { + // For spooled jobs, we don't need to do anything. + dwErrorCode = ERROR_SUCCESS; + } + else + { + // In all other cases, just call _RpcEndPagePrinter. + RpcTryExcept + { + dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + return FALSE; +} + +BOOL WINAPI +EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPrinterEnum; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpPrinterInfo(p, Level); + + if (Level == 1) + p += sizeof(PRINTER_INFO_1W); + else if (Level == 2) + p += sizeof(PRINTER_INFO_2W); + } + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer) +{ + return FALSE; +} + +BOOL WINAPI +GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer) +{ + return FALSE; +} + +BOOL WINAPI +GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded) +{ + return FALSE; +} + +BOOL WINAPI +GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) +{ + return FALSE; +} + +BOOL WINAPI +GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded) +{ + return FALSE; +} + +BOOL WINAPI +GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded) +{ + return FALSE; +} + +BOOL WINAPI +OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault) +{ + BOOL bReturnValue = FALSE; + DWORD cch; + PWSTR pwszPrinterName = NULL; + PRINTER_DEFAULTSW wDefault = { 0 }; + + if (pPrinterName) + { + // Convert pPrinterName to a Unicode string pwszPrinterName + cch = strlen(pPrinterName); + + pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!pwszPrinterName) + { + ERR("HeapAlloc failed for pwszPrinterName with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1); + } + + if (pDefault) + { + wDefault.DesiredAccess = pDefault->DesiredAccess; + + if (pDefault->pDatatype) + { + // Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype + cch = strlen(pDefault->pDatatype); + + wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!wDefault.pDatatype) + { + ERR("HeapAlloc failed for wDefault.pDatatype with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1); + } + + if (pDefault->pDevMode) + wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode); + } + + bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault); + +Cleanup: + if (wDefault.pDatatype) + HeapFree(hProcessHeap, 0, wDefault.pDatatype); + + if (wDefault.pDevMode) + HeapFree(hProcessHeap, 0, wDefault.pDevMode); + + if (pwszPrinterName) + HeapFree(hProcessHeap, 0, pwszPrinterName); + + return bReturnValue; +} + +BOOL WINAPI +OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault) +{ + DWORD dwErrorCode; + HANDLE hPrinter; + PSPOOLER_HANDLE pHandle; + PWSTR pDatatype = NULL; + WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 }; + ACCESS_MASK AccessRequired = 0; + + // Prepare the additional parameters in the format required by _RpcOpenPrinter + if (pDefault) + { + pDatatype = pDefault->pDatatype; + DevModeContainer.cbBuf = sizeof(DEVMODEW); + DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode; + AccessRequired = pDefault->DesiredAccess; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Create a new SPOOLER_HANDLE structure. + pHandle = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(SPOOLER_HANDLE)); + if (!pHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("HeapAlloc failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pHandle->hPrinter = hPrinter; + pHandle->hSPLFile = INVALID_HANDLE_VALUE; + + // Return it as phPrinter. + *phPrinter = (HANDLE)pHandle; + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command) +{ + UNIMPLEMENTED; + return FALSE; +} + +DWORD WINAPI +StartDocPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + DOC_INFO_1W wDocInfo1 = { 0 }; + DWORD cch; + DWORD dwErrorCode; + DWORD dwReturnValue = 0; + PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo; + + // Only check the minimum required for accessing pDocInfo. + // Additional sanity checks are done in StartDocPrinterW. + if (!pDocInfo1) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (pDocInfo1->pDatatype) + { + // Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype + cch = strlen(pDocInfo1->pDatatype); + + wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!wDocInfo1.pDatatype) + { + ERR("HeapAlloc failed for wDocInfo1.pDatatype with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1); + } + + if (pDocInfo1->pDocName) + { + // Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName + cch = strlen(pDocInfo1->pDocName); + + wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!wDocInfo1.pDocName) + { + ERR("HeapAlloc failed for wDocInfo1.pDocName with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1); + } + + if (pDocInfo1->pOutputFile) + { + // Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile + cch = strlen(pDocInfo1->pOutputFile); + + wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR)); + if (!wDocInfo1.pOutputFile) + { + ERR("HeapAlloc failed for wDocInfo1.pOutputFile with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1); + } + + dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1); + dwErrorCode = GetLastError(); + +Cleanup: + if (wDocInfo1.pDatatype) + HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype); + + if (wDocInfo1.pDocName) + HeapFree(hProcessHeap, 0, wDocInfo1.pDocName); + + if (wDocInfo1.pOutputFile) + HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile); + + SetLastError(dwErrorCode); + return dwReturnValue; +} + +DWORD WINAPI +StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + DWORD cbAddJobInfo1; + DWORD cbNeeded; + DWORD dwErrorCode; + DWORD dwReturnValue = 0; + PADDJOB_INFO_1W pAddJobInfo1 = NULL; + PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if (!pDocInfo1) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (pHandle->bStartedDoc) + { + dwErrorCode = ERROR_INVALID_PRINTER_STATE; + goto Cleanup; + } + + // Check if we want to redirect output into a file. + if (pDocInfo1->pOutputFile) + { + // Do a StartDocPrinter RPC call in this case. + dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1); + } + else + { + // Allocate memory for the ADDJOB_INFO_1W structure and a path. + cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR); + pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1); + if (!pAddJobInfo1) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("HeapAlloc failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Try to add a new job. + // This only succeeds if the printer is set to do spooled printing. + if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded)) + { + // Do spooled printing. + dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1); + } + else if (GetLastError() == ERROR_INVALID_ACCESS) + { + // ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing. + // In this case, we do a StartDocPrinter RPC call. + dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1); + } + else + { + dwErrorCode = GetLastError(); + ERR("AddJobW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + } + + if (dwErrorCode == ERROR_SUCCESS) + { + pHandle->bStartedDoc = TRUE; + dwReturnValue = pHandle->dwJobID; + } + +Cleanup: + if (pAddJobInfo1) + HeapFree(hProcessHeap, 0, pAddJobInfo1); + + SetLastError(dwErrorCode); + return dwReturnValue; +} + +BOOL WINAPI +StartPagePrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten) +{ + DWORD dwErrorCode; + PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if (!pHandle->bStartedDoc) + { + dwErrorCode = ERROR_SPL_NO_STARTDOC; + goto Cleanup; + } + + if (pHandle->hSPLFile != INVALID_HANDLE_VALUE) + { + // Write to the spool file. This doesn't need an RPC request. + if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL)) + { + dwErrorCode = GetLastError(); + ERR("WriteFile failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = ERROR_SUCCESS; + } + else + { + // TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed. + // We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full. + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus) +{ + return FALSE; +} Index: win32ss/printing/base/winspool/printprocessors.c =================================================================== --- win32ss/printing/base/winspool/printprocessors.c (nonexistent) +++ win32ss/printing/base/winspool/printprocessors.c (working copy) @@ -0,0 +1,131 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Processors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static void +_MarshallUpDatatypesInfo(PDATATYPES_INFO_1W pDatatypesInfo1) +{ + // Replace relative offset addresses in the output by absolute pointers. + pDatatypesInfo1->pName = (PWSTR)((ULONG_PTR)pDatatypesInfo1->pName + (ULONG_PTR)pDatatypesInfo1); +} + +static void +_MarshallUpPrintProcessorInfo(PPRINTPROCESSOR_INFO_1W pPrintProcessorInfo1) +{ + // Replace relative offset addresses in the output by absolute pointers. + pPrintProcessorInfo1->pName = (PWSTR)((ULONG_PTR)pPrintProcessorInfo1->pName + (ULONG_PTR)pPrintProcessorInfo1); +} + +BOOL WINAPI +AddPrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPathName, PWSTR pPrintProcessorName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +DeletePrintProcessorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProcessorName) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumPrintProcessorDatatypesA(PSTR pName, LPSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +EnumPrintProcessorDatatypesW(PWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pDatatypes; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPrintProcessorDatatypes failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpDatatypesInfo((PDATATYPES_INFO_1W)p); + p += sizeof(DATATYPES_INFO_1W); + } + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE p = pPrintProcessorInfo; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + dwErrorCode = RpcExceptionCode(); + ERR("_RpcEnumPrintProcessors failed with exception code %lu!\n", dwErrorCode); + } + RpcEndExcept; + + if (dwErrorCode == ERROR_SUCCESS) + { + // Replace relative offset addresses in the output by absolute pointers. + for (i = 0; i < *pcReturned; i++) + { + _MarshallUpPrintProcessorInfo((PPRINTPROCESSOR_INFO_1W)p); + p += sizeof(PRINTPROCESSOR_INFO_1W); + } + } + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded) +{ + BOOL bReturnValue = FALSE; + DWORD dwErrorCode; + + // Do the RPC call + RpcTryExcept + { + dwErrorCode = _RpcGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded); + SetLastError(dwErrorCode); + bReturnValue = (dwErrorCode == ERROR_SUCCESS); + } + RpcExcept(EXCEPTION_EXECUTE_HANDLER) + { + ERR("_RpcGetPrintProcessorDirectory failed with exception code %lu!\n", RpcExceptionCode()); + } + RpcEndExcept; + + return bReturnValue; +} Index: win32ss/printing/base/winspool/printproviders.c =================================================================== --- win32ss/printing/base/winspool/printproviders.c (nonexistent) +++ win32ss/printing/base/winspool/printproviders.c (working copy) @@ -0,0 +1,22 @@ +/* + * PROJECT: ReactOS Spooler API + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Providers + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +BOOL WINAPI +AddPrintProvidorW(PWSTR pName, DWORD Level, PBYTE pProviderInfo) +{ + UNIMPLEMENTED; + return FALSE; +} + +BOOL WINAPI +DeletePrintProvidorW(PWSTR pName, PWSTR pEnvironment, PWSTR pPrintProviderName) +{ + UNIMPLEMENTED; + return FALSE; +} Index: win32ss/printing/base/winspool/winspool.rc =================================================================== --- win32ss/printing/base/winspool/winspool.rc (nonexistent) +++ win32ss/printing/base/winspool/winspool.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Spooler API" +#define REACTOS_STR_INTERNAL_NAME "winspool" +#define REACTOS_STR_ORIGINAL_FILENAME "winspool.drv" +#include Index: win32ss/printing/base/winspool/winspool.spec =================================================================== --- win32ss/printing/base/winspool/winspool.spec (nonexistent) +++ win32ss/printing/base/winspool/winspool.spec (working copy) @@ -0,0 +1,200 @@ +100 stub -noname EnumPrinterPropertySheets +101 stub -noname ClusterSplOpen +102 stub -noname ClusterSplClose +103 stub -noname ClusterSplIsAlive +104 stub PerfClose +105 stub PerfCollect +106 stub PerfOpen +107 stub ADVANCEDSETUPDIALOG +108 stub AbortPrinter +109 stub AddFormA +110 stub AddFormW +111 stdcall AddJobA(long long ptr long ptr) +112 stdcall AddJobW(long long ptr long ptr) +113 stub AddMonitorA +114 stdcall AddMonitorW(wstr long ptr) +115 stub AddPortA +116 stub AddPortExA +117 stub AddPortExW +118 stdcall AddPortW(wstr long wstr) +119 stub AddPrintProcessorA +120 stdcall AddPrintProcessorW(wstr wstr wstr wstr) +121 stub AddPrintProvidorA +122 stdcall AddPrintProvidorW(wstr long ptr) +123 stub AddPrinterA +124 stub AddPrinterConnectionA +125 stub AddPrinterConnectionW +126 stub AddPrinterDriverA +127 stub AddPrinterDriverExA +128 stub AddPrinterDriverExW +129 stdcall AddPrinterDriverW(wstr long ptr) +130 stdcall AddPrinterW(wstr long ptr) +131 stub AdvancedDocumentPropertiesA +132 stdcall AdvancedDocumentPropertiesW(long long wstr ptr ptr) +133 stub AdvancedSetupDialog +134 stdcall ClosePrinter(long) +135 stub CloseSpoolFileHandle +136 stub CommitSpoolData +137 stub ConfigurePortA +138 stdcall ConfigurePortW(wstr long wstr) +139 stub ConnectToPrinterDlg +140 stub ConvertAnsiDevModeToUnicodeDevmode +141 stub ConvertUnicodeDevModeToAnsiDevmode +142 stub CreatePrinterIC +143 stub DEVICECAPABILITIES +144 stub DEVICEMODE +145 stub DeleteFormA +146 stub DeleteFormW +147 stub DeleteMonitorA +148 stdcall DeleteMonitorW(wstr wstr wstr) +149 stub DeletePortA +150 stdcall DeletePortW(wstr long wstr) +151 stub DeletePrintProcessorA +152 stdcall DeletePrintProcessorW(wstr wstr wstr) +153 stub DeletePrintProvidorA +154 stdcall DeletePrintProvidorW(wstr wstr wstr) +155 stub DeletePrinter +156 stub DeletePrinterConnectionA +157 stub DeletePrinterConnectionW +158 stub DeletePrinterDataA +159 stub DeletePrinterDataExA +160 stub DeletePrinterDataExW +161 stub DeletePrinterDataW +162 stub DeletePrinterDriverA +163 stub DeletePrinterDriverExA +164 stub DeletePrinterDriverExW +165 stdcall DeletePrinterDriverW(wstr wstr wstr) +166 stub DeletePrinterIC +167 stub DeletePrinterKeyA +168 stub DeletePrinterKeyW +169 stub DevQueryPrint +170 stub DevQueryPrintEx +171 stub DeviceCapabilities +172 stdcall DeviceCapabilitiesA(str str long ptr ptr) +173 stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr) +174 stub DeviceMode +175 stub DevicePropertySheets +176 stub DocumentEvent +177 stdcall DocumentPropertiesA(long long ptr ptr ptr long) +178 stdcall DocumentPropertiesW(long long ptr ptr ptr long) +179 stub DocumentPropertySheets +180 stub EXTDEVICEMODE +181 stdcall EndDocPrinter(long) +182 stdcall EndPagePrinter(long) +183 stub EnumFormsA +184 stub EnumFormsW +185 stdcall EnumJobsA(long long long long ptr long ptr ptr) +186 stdcall EnumJobsW(long long long long ptr long ptr ptr) +187 stub EnumMonitorsA +188 stdcall EnumMonitorsW(wstr long ptr long ptr ptr) +189 stub EnumPortsA +190 stdcall EnumPortsW(wstr long ptr long ptr ptr) +191 stdcall EnumPrintProcessorDatatypesA(ptr ptr long ptr long ptr ptr) +192 stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr) +193 stub EnumPrintProcessorsA +194 stdcall EnumPrintProcessorsW(ptr ptr long ptr long ptr ptr) +195 stub EnumPrinterDataA +196 stub EnumPrinterDataExA +197 stub EnumPrinterDataExW +198 stub EnumPrinterDataW +199 stub EnumPrinterDriversA +200 stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr) +201 stdcall GetDefaultPrinterA(ptr ptr) +202 stub SetDefaultPrinterA +203 stdcall GetDefaultPrinterW(ptr ptr) +204 stub SetDefaultPrinterW +205 stub -noname SplReadPrinter +206 stub -noname AddPerMachineConnectionA +207 stub -noname AddPerMachineConnectionW +208 stub -noname DeletePerMachineConnectionA +209 stub -noname DeletePerMachineConnectionW +210 stub -noname EnumPerMachineConnectionsA +211 stub -noname EnumPerMachineConnectionsW +212 stub -noname LoadPrinterDriver +213 stub -noname RefCntLoadDriver +214 stub -noname RefCntUnloadDriver +215 stub -noname ForceUnloadDriver +216 stub -noname PublishPrinterA +217 stub -noname PublishPrinterW +218 stub -noname CallCommonPropertySheetUI +219 stub -noname PrintUIQueueCreate +220 stub -noname PrintUIPrinterPropPages +221 stub -noname PrintUIDocumentDefaults +222 stub -noname SendRecvBidiData +223 stub -noname RouterFreeBidiResponseContainer +224 stub -noname ExternalConnectToLd64In32Server +225 stub EnumPrinterKeyA +226 stub -noname PrintUIWebPnpEntry +227 stub -noname PrintUIWebPnpPostEntry +228 stub -noname PrintUICreateInstance +229 stub -noname PrintUIDocumentPropertiesWrap +230 stub -noname PrintUIPrinterSetup +231 stub -noname PrintUIServerPropPages +232 stub -noname AddDriverCatalog +233 stub EnumPrinterKeyW +234 stdcall EnumPrintersA(long ptr long ptr long ptr ptr) +235 stdcall EnumPrintersW(long ptr long ptr long ptr ptr) +236 stub ExtDeviceMode +237 stub FindClosePrinterChangeNotification +238 stub FindFirstPrinterChangeNotification +239 stub FindNextPrinterChangeNotification +240 stub FlushPrinter +241 stub FreePrinterNotifyInfo +242 stub GetFormA +243 stub GetFormW +244 stdcall GetJobA(long long long ptr long ptr) +245 stdcall GetJobW(long long long ptr long ptr) +246 stub GetPrintProcessorDirectoryA +247 stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr) +248 stdcall GetPrinterA(long long ptr long ptr) +249 stub GetPrinterDataA +250 stub GetPrinterDataExA +251 stub GetPrinterDataExW +252 stdcall GetPrinterDataW(long wstr ptr ptr long ptr) +253 stdcall GetPrinterDriverA(long str long ptr long ptr) +254 stub GetPrinterDriverDirectoryA +255 stdcall GetPrinterDriverDirectoryW(wstr wstr long ptr long ptr) +256 stdcall GetPrinterDriverW(long wstr long ptr long ptr) +257 stdcall GetPrinterW(long long ptr long ptr) +258 stub GetSpoolFileHandle +259 stdcall IsValidDevmodeA(ptr long) +260 stdcall IsValidDevmodeW(ptr long) +261 stdcall OpenPrinterA(str ptr ptr) +262 stdcall OpenPrinterW(wstr ptr ptr) +263 stub PlayGdiScriptOnPrinterIC +264 stub PrinterMessageBoxA +265 stub PrinterMessageBoxW +266 stub PrinterProperties +267 stub QueryColorProfile +268 stub QueryRemoteFonts +269 stub QuerySpoolMode +270 stdcall ReadPrinter(long ptr long ptr) +271 stub ResetPrinterA +272 stdcall ResetPrinterW(long ptr) +273 stdcall ScheduleJob(long long) +274 stub SeekPrinter +275 stub SetAllocFailCount +276 stub SetFormA +277 stub SetFormW +278 stdcall SetJobA(long long long ptr long) +279 stdcall SetJobW(long long long ptr long) +280 stub SetPortA +281 stub SetPortW +282 stub SetPrinterA +283 stub SetPrinterDataA +284 stub SetPrinterDataExA +285 stub SetPrinterDataExW +286 stdcall SetPrinterDataW(long wstr long ptr long) +287 stdcall SetPrinterW(long long ptr long) +288 stub SplDriverUnloadComplete +289 stub SpoolerDevQueryPrintW +290 stdcall SpoolerInit() +291 stub SpoolerPrinterEvent +292 stub StartDocDlgA +293 stub StartDocDlgW +294 stdcall StartDocPrinterA(long long ptr) +295 stdcall StartDocPrinterW(long long ptr) +296 stdcall StartPagePrinter(long) +297 stub WaitForPrinterChange +298 stdcall WritePrinter(long ptr long ptr) +299 stdcall XcvDataW(long wstr ptr long ptr long ptr ptr) Index: win32ss/printing/drivers/CMakeLists.txt =================================================================== --- win32ss/printing/drivers/CMakeLists.txt (nonexistent) +++ win32ss/printing/drivers/CMakeLists.txt (working copy) @@ -0,0 +1,2 @@ +#add_subdirectory(tty) +#add_subdirectory(unidrv) Index: win32ss/printing/include/spoolss.h =================================================================== --- win32ss/printing/include/spoolss.h (nonexistent) +++ win32ss/printing/include/spoolss.h (working copy) @@ -0,0 +1,32 @@ +/* + * PROJECT: ReactOS Printing Include files + * LICENSE: GNU LGPLv2 or any later version as published by the Free Software Foundation + * PURPOSE: Undocumented APIs of the Spooler Router "spoolss.dll" + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _REACTOS_SPOOLSS_H +#define _REACTOS_SPOOLSS_H + +typedef struct _MARSHALL_DOWN_INFO +{ + DWORD dwOffset; /** Byte offset of this element within the structure or MAXDWORD to indicate the end of the array */ + DWORD cbSize; /** Total size of this element in bytes under Windows. Unused here, I don't know what we need this number for. */ + DWORD cbPerElementSize; /** If this element is a structure itself, this field gives the size in bytes of each element of the structure. + Otherwise, this is the same as cbTotalSize. E.g. for SYSTEMTIME, cbSize would be 16 and cbPerElementSize would be 2. + Unused here, I don't know what we need this number for. */ + BOOL bAdjustAddress; /** TRUE if MarshallDownStructure shall adjust the address of this element, FALSE if it shall leave this element untouched. */ +} +MARSHALL_DOWN_INFO, *PMARSHALL_DOWN_INFO; + +PWSTR WINAPI AllocSplStr(PCWSTR pwszInput); +PVOID WINAPI DllAllocSplMem(DWORD dwBytes); +BOOL WINAPI DllFreeSplMem(PVOID pMem); +BOOL WINAPI DllFreeSplStr(PWSTR pwszString); +BOOL WINAPI MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean); +PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd); +PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew); +BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput); +BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable); + +#endif Index: win32ss/printing/monitors/CMakeLists.txt =================================================================== --- win32ss/printing/monitors/CMakeLists.txt (nonexistent) +++ win32ss/printing/monitors/CMakeLists.txt (working copy) @@ -0,0 +1,4 @@ +add_subdirectory(localmon) +#add_subdirectory(pjlmon) +#add_subdirectory(tcpmon) +#add_subdirectory(usbmon) Index: win32ss/printing/monitors/localmon/CMakeLists.txt =================================================================== --- win32ss/printing/monitors/localmon/CMakeLists.txt (nonexistent) +++ win32ss/printing/monitors/localmon/CMakeLists.txt (working copy) @@ -0,0 +1,22 @@ + +add_subdirectory(ui) + +spec2def(localmon.dll localmon.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + main.c + ports.c + precomp.h + tools.c + xcv.c) + +add_library(localmon SHARED + ${SOURCE} + localmon.rc + ${CMAKE_CURRENT_BINARY_DIR}/localmon.def) + +set_module_type(localmon win32dll UNICODE) +target_link_libraries(localmon wine) +add_importlibs(localmon advapi32 spoolss user32 msvcrt kernel32 ntdll) +add_pch(localmon precomp.h SOURCE) +add_cd_file(TARGET localmon DESTINATION reactos/system32 FOR all) Index: win32ss/printing/monitors/localmon/lang/de-DE.rc =================================================================== --- win32ss/printing/monitors/localmon/lang/de-DE.rc (nonexistent) +++ win32ss/printing/monitors/localmon/lang/de-DE.rc (working copy) @@ -0,0 +1,7 @@ +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_LOCAL_PORT "Lokaler Anschluss" + IDS_LOCAL_MONITOR "Lokaler Monitor" +END Index: win32ss/printing/monitors/localmon/lang/en-US.rc =================================================================== --- win32ss/printing/monitors/localmon/lang/en-US.rc (nonexistent) +++ win32ss/printing/monitors/localmon/lang/en-US.rc (working copy) @@ -0,0 +1,7 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_LOCAL_PORT "Local Port" + IDS_LOCAL_MONITOR "Local Monitor" +END Index: win32ss/printing/monitors/localmon/localmon.rc =================================================================== --- win32ss/printing/monitors/localmon/localmon.rc (nonexistent) +++ win32ss/printing/monitors/localmon/localmon.rc (working copy) @@ -0,0 +1,26 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Resource file + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include +#include "resource.h" + +/* Version Information */ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Local Port Monitor" +#define REACTOS_STR_INTERNAL_NAME "localmon" +#define REACTOS_STR_ORIGINAL_FILENAME "localmon.dll" +#include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_DE_DE + #include "lang/de-DE.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif Index: win32ss/printing/monitors/localmon/localmon.spec =================================================================== --- win32ss/printing/monitors/localmon/localmon.spec (nonexistent) +++ win32ss/printing/monitors/localmon/localmon.spec (working copy) @@ -0,0 +1 @@ +@ stdcall InitializePrintMonitor2(ptr ptr) Index: win32ss/printing/monitors/localmon/main.c =================================================================== --- win32ss/printing/monitors/localmon/main.c (nonexistent) +++ win32ss/printing/monitors/localmon/main.c (working copy) @@ -0,0 +1,247 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +DWORD cbLocalMonitor; +DWORD cbLocalPort; +PCWSTR pwszLocalMonitor; +PCWSTR pwszLocalPort; + +// Local Constants +static MONITOR2 _MonitorFunctions = { + sizeof(MONITOR2), // cbSize + LocalmonEnumPorts, // pfnEnumPorts + LocalmonOpenPort, // pfnOpenPort + NULL, // pfnOpenPortEx + LocalmonStartDocPort, // pfnStartDocPort + LocalmonWritePort, // pfnWritePort + LocalmonReadPort, // pfnReadPort + LocalmonEndDocPort, // pfnEndDocPort + LocalmonClosePort, // pfnClosePort + NULL, // pfnAddPort + NULL, // pfnAddPortEx + NULL, // pfnConfigurePort + NULL, // pfnDeletePort + LocalmonGetPrinterDataFromPort, // pfnGetPrinterDataFromPort + LocalmonSetPortTimeOuts, // pfnSetPortTimeOuts + LocalmonXcvOpenPort, // pfnXcvOpenPort + LocalmonXcvDataPort, // pfnXcvDataPort + LocalmonXcvClosePort, // pfnXcvClosePort + LocalmonShutdown, // pfnShutdown + NULL, // pfnSendRecvBidiDataFromPort +}; + + +/** + * @name _IsNEPort + * + * Checks if the given port name is a virtual Ne port. + * A virtual Ne port may appear in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports and can have the formats + * Ne00:, Ne01:, Ne-02:, Ne456: + * This check is extra picky to not cause false positives (like file name ports starting with "Ne"). + * + * @param pwszPortName + * The port name to check. + * + * @return + * TRUE if this is definitely a virtual Ne port, FALSE if not. + */ +static __inline BOOL +_IsNEPort(PCWSTR pwszPortName) +{ + PCWSTR p = pwszPortName; + + // First character needs to be 'N' (uppercase or lowercase) + if (*p != L'N' && *p != L'n') + return FALSE; + + // Next character needs to be 'E' (uppercase or lowercase) + p++; + if (*p != L'E' && *p != L'e') + return FALSE; + + // An optional hyphen may follow now. + p++; + if (*p == L'-') + p++; + + // Now an arbitrary number of digits may follow. + while (*p >= L'0' && *p <= L'9') + p++; + + // Finally, the virtual Ne port must be terminated by a colon. + if (*p != ':') + return FALSE; + + // If this is the end of the string, we have a virtual Ne port. + p++; + return (*p == L'\0'); +} + +static void +_LoadResources(HINSTANCE hinstDLL) +{ + LoadStringW(hinstDLL, IDS_LOCAL_MONITOR, (PWSTR)&pwszLocalMonitor, 0); + cbLocalMonitor = (wcslen(pwszLocalMonitor) + 1) * sizeof(WCHAR); + + LoadStringW(hinstDLL, IDS_LOCAL_PORT, (PWSTR)&pwszLocalPort, 0); + cbLocalPort = (wcslen(pwszLocalPort) + 1) * sizeof(WCHAR); +} + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + _LoadResources(hinstDLL); + break; + } + + return TRUE; +} + +void WINAPI +LocalmonShutdown(HANDLE hMonitor) +{ + PLOCALMON_HANDLE pLocalmon; + PLOCALMON_PORT pPort; + PLOCALMON_XCV pXcv; + + TRACE("LocalmonShutdown(%p)\n", hMonitor); + + pLocalmon = (PLOCALMON_HANDLE)hMonitor; + + // Close all virtual file ports. + while (!IsListEmpty(&pLocalmon->FilePorts)) + { + pPort = CONTAINING_RECORD(&pLocalmon->FilePorts.Flink, LOCALMON_PORT, Entry); + LocalmonClosePort((HANDLE)pPort); + } + + // Do the same for the open Xcv ports. + while (!IsListEmpty(&pLocalmon->XcvHandles)) + { + pXcv = CONTAINING_RECORD(&pLocalmon->XcvHandles.Flink, LOCALMON_XCV, Entry); + LocalmonXcvClosePort((HANDLE)pXcv); + } + + // Now close all registry ports, remove them from the list and free their memory. + while (!IsListEmpty(&pLocalmon->RegistryPorts)) + { + pPort = CONTAINING_RECORD(&pLocalmon->RegistryPorts.Flink, LOCALMON_PORT, Entry); + LocalmonClosePort((HANDLE)pPort); + RemoveEntryList(&pPort->Entry); + DllFreeSplMem(pPort); + } + + // Finally clean the LOCALMON_HANDLE structure itself. + DeleteCriticalSection(&pLocalmon->Section); + DllFreeSplMem(pLocalmon); +} + +PMONITOR2 WINAPI +InitializePrintMonitor2(PMONITORINIT pMonitorInit, PHANDLE phMonitor) +{ + DWORD cchMaxPortName; + DWORD cchPortName; + DWORD dwErrorCode; + DWORD dwPortCount; + DWORD i; + HKEY hKey; + PMONITOR2 pReturnValue = NULL; + PLOCALMON_HANDLE pLocalmon; + PLOCALMON_PORT pPort = NULL; + + TRACE("InitializePrintMonitor2(%p, %p)\n", pMonitorInit, phMonitor); + + // Create a new LOCALMON_HANDLE structure. + pLocalmon = DllAllocSplMem(sizeof(LOCALMON_HANDLE)); + InitializeCriticalSection(&pLocalmon->Section); + InitializeListHead(&pLocalmon->FilePorts); + InitializeListHead(&pLocalmon->RegistryPorts); + InitializeListHead(&pLocalmon->XcvHandles); + + // The Local Spooler Port Monitor doesn't need to care about the given registry key and functions. + // Instead it uses a well-known registry key for getting its information about local ports. Open this one. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Ports", 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of ports and the length of the largest port name. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwPortCount, &cchMaxPortName, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Loop through all ports. + for (i = 0; i < dwPortCount; i++) + { + // Allocate memory for a new LOCALMON_PORT structure and its name. + pPort = DllAllocSplMem(sizeof(LOCALMON_PORT) + (cchMaxPortName + 1) * sizeof(WCHAR)); + if (!pPort) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pPort->pLocalmon = pLocalmon; + pPort->hFile = INVALID_HANDLE_VALUE; + pPort->pwszPortName = (PWSTR)((PBYTE)pPort + sizeof(LOCALMON_PORT)); + + // Get the port name. + cchPortName = cchMaxPortName + 1; + dwErrorCode = (DWORD)RegEnumValueW(hKey, i, pPort->pwszPortName, &cchPortName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumValueW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // pwszPortName can be one of the following to be valid for this Port Monitor: + // COMx: - Physical COM port + // LPTx: - Physical LPT port (or redirected one using "net use LPT1 ...") + // FILE: - Opens a prompt that asks for an output filename + // C:\bla.txt - Redirection into the file "C:\bla.txt" + // \\COMPUTERNAME\PrinterName - Redirection to a shared network printer installed as a local port + // + // We can't detect valid and invalid ones by the name, so we can only exclude empty ports and the virtual "Ne00:", "Ne01:", ... ports. + // Skip the invalid ones here. + if (!cchPortName || _IsNEPort(pPort->pwszPortName)) + { + DllFreeSplMem(pPort); + continue; + } + + // Add it to the list. + InsertTailList(&pLocalmon->RegistryPorts, &pPort->Entry); + + // Don't let the cleanup routine free this. + pPort = NULL; + } + + // Return our handle and the Print Monitor functions. + *phMonitor = (HANDLE)pLocalmon; + pReturnValue = &_MonitorFunctions; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pPort) + DllFreeSplMem(pPort); + + SetLastError(dwErrorCode); + return pReturnValue; +} Index: win32ss/printing/monitors/localmon/ports.c =================================================================== --- win32ss/printing/monitors/localmon/ports.c (nonexistent) +++ win32ss/printing/monitors/localmon/ports.c (working copy) @@ -0,0 +1,1085 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to ports + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + + +// Local Constants +static const WCHAR wszNonspooledPrefix[] = L"NONSPOOLED_"; +static const DWORD cchNonspooledPrefix = _countof(wszNonspooledPrefix) - 1; + + +/** + * @name _GetNonspooledPortName + * + * Prepends "NONSPOOLED_" to a port name without colon. + * + * @param pwszPortNameWithoutColon + * Result of a previous GetPortNameWithoutColon call. + * + * @param ppwszNonspooledPortName + * Pointer to a buffer that will contain the NONSPOOLED port name. + * You have to free this buffer using DllFreeSplMem. + * + * @return + * ERROR_SUCCESS if the NONSPOOLED port name was successfully copied into the buffer. + * ERROR_NOT_ENOUGH_MEMORY if memory allocation failed. + */ +static __inline DWORD +_GetNonspooledPortName(PCWSTR pwszPortNameWithoutColon, PWSTR* ppwszNonspooledPortName) +{ + DWORD cchPortNameWithoutColon; + + cchPortNameWithoutColon = wcslen(pwszPortNameWithoutColon); + + *ppwszNonspooledPortName = DllAllocSplMem((cchNonspooledPrefix + cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + if (!*ppwszNonspooledPortName) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return ERROR_NOT_ENOUGH_MEMORY; + } + + CopyMemory(*ppwszNonspooledPortName, wszNonspooledPrefix, cchNonspooledPrefix * sizeof(WCHAR)); + CopyMemory(&(*ppwszNonspooledPortName)[cchNonspooledPrefix], pwszPortNameWithoutColon, (cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + + return ERROR_SUCCESS; +} + +/** + * @name _IsLegacyPort + * + * Checks if the given port name is a legacy port (COM or LPT). + * This check is extra picky to not cause false positives (like file name ports starting with "COM" or "LPT"). + * + * @param pwszPortName + * The port name to check. + * + * @param pwszPortType + * L"COM" or L"LPT" + * + * @return + * TRUE if this is definitely the asked legacy port, FALSE if not. + */ +static __inline BOOL +_IsLegacyPort(PCWSTR pwszPortName, PCWSTR pwszPortType) +{ + const DWORD cchPortType = 3; + PCWSTR p = pwszPortName; + + // The port name must begin with pwszPortType. + if (_wcsnicmp(p, pwszPortType, cchPortType) != 0) + return FALSE; + + p += cchPortType; + + // Now an arbitrary number of digits may follow. + while (*p >= L'0' && *p <= L'9') + p++; + + // Finally, the legacy port must be terminated by a colon. + if (*p != ':') + return FALSE; + + // If this is the end of the string, we have a legacy port. + p++; + return (*p == L'\0'); +} + +/** + * @name _ClosePortHandles + * + * Closes a port of any type if it's open. + * Removes any saved mapping or existing definition of a NONSPOOLED device mapping. + * + * @param pPort + * The port you want to close. + */ +static void +_ClosePortHandles(PLOCALMON_PORT pPort) +{ + PWSTR pwszNonspooledPortName; + PWSTR pwszPortNameWithoutColon; + + // A port is already fully closed if the file handle is invalid. + if (pPort->hFile == INVALID_HANDLE_VALUE) + return; + + // Close the file handle. + CloseHandle(pPort->hFile); + pPort->hFile = INVALID_HANDLE_VALUE; + + // A NONSPOOLED port was only created if pwszMapping contains the current port mapping. + if (!pPort->pwszMapping) + return; + + // Free the information about the current mapping. + DllFreeSplStr(pPort->pwszMapping); + pPort->pwszMapping = NULL; + + // Finally get the required strings and remove the DOS device definition for the NONSPOOLED port. + if (GetPortNameWithoutColon(pPort->pwszPortName, &pwszPortNameWithoutColon) == ERROR_SUCCESS) + { + if (_GetNonspooledPortName(pwszPortNameWithoutColon, &pwszNonspooledPortName) == ERROR_SUCCESS) + { + DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL); + DllFreeSplMem(pwszNonspooledPortName); + } + + DllFreeSplMem(pwszPortNameWithoutColon); + } +} + +/** + * @name _CreateNonspooledPort + * + * Queries the system-wide device definition of the given port. + * If such a definition exists, it's a legacy port remapped to a named pipe by the spooler. + * In this case, the function creates and opens a NONSPOOLED device definition to the most recent mapping before the current one (usually the physical device). + * + * @param pPort + * Pointer to the LOCALMON_PORT structure of the desired port. + * + * @return + * TRUE if a NONSPOOLED port was successfully created, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + * In particular, if the return value is FALSE and GetLastError returns ERROR_SUCCESS, no NONSPOOLED port is needed for this port. + */ +static BOOL +_CreateNonspooledPort(PLOCALMON_PORT pPort) +{ + const WCHAR wszLocalSlashes[] = L"\\\\.\\"; + const DWORD cchLocalSlashes = _countof(wszLocalSlashes) - 1; + + const WCHAR wszSpoolerNamedPipe[] = L"\\Device\\NamedPipe\\Spooler\\"; + const DWORD cchSpoolerNamedPipe = _countof(wszSpoolerNamedPipe) - 1; + + BOOL bReturnValue = FALSE; + DWORD cchPortNameWithoutColon; + DWORD dwErrorCode; + HANDLE hToken = NULL; + PWSTR p; + PWSTR pwszDeviceMappings = NULL; + PWSTR pwszNonspooledFileName = NULL; + PWSTR pwszNonspooledPortName = NULL; + PWSTR pwszPipeName = NULL; + PWSTR pwszPortNameWithoutColon = NULL; + + // We need the port name without the trailing colon. + dwErrorCode = GetPortNameWithoutColon(pPort->pwszPortName, &pwszPortNameWithoutColon); + if (dwErrorCode == ERROR_INVALID_PARAMETER) + { + // This port has no trailing colon, so we also need no NONSPOOLED mapping for it. + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + else if (dwErrorCode != ERROR_SUCCESS) + { + // Another unexpected failure. + goto Cleanup; + } + + cchPortNameWithoutColon = wcslen(pwszPortNameWithoutColon); + + // The spooler has usually remapped the legacy port to a named pipe of the format in wszSpoolerNamedPipe. + // Construct the device name of this pipe. + pwszPipeName = DllAllocSplMem((cchSpoolerNamedPipe + cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + if (!pwszPipeName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszPipeName, wszSpoolerNamedPipe, cchSpoolerNamedPipe * sizeof(WCHAR)); + CopyMemory(&pwszPipeName[cchSpoolerNamedPipe], pwszPortNameWithoutColon, (cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + + // QueryDosDeviceW is one of the shitty APIs that gives no information about the required buffer size and wants you to know it by pure magic. + // Examples show that a value of MAX_PATH * sizeof(WCHAR) is usually taken here, so we have no other option either. + pwszDeviceMappings = DllAllocSplMem(MAX_PATH * sizeof(WCHAR)); + if (!pwszDeviceMappings) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Switch to the SYSTEM context, because we're only interested in creating NONSPOOLED ports for system-wide ports. + // User-local ports (like _some_ redirected networked ones) aren't remapped by the spooler and can be opened directly. + hToken = RevertToPrinterSelf(); + if (!hToken) + { + dwErrorCode = GetLastError(); + ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // QueryDosDeviceW returns the current mapping and a list of prior mappings of this legacy port, which is managed as a DOS device in the system. + if (!QueryDosDeviceW(pwszPortNameWithoutColon, pwszDeviceMappings, MAX_PATH)) + { + // No system-wide port exists, so we also need no NONSPOOLED mapping. + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + // Check if this port has already been opened by _CreateNonspooledPort previously. + if (pPort->pwszMapping) + { + // In this case, we just need to do something if the mapping has changed. + // Therefore, check if the stored mapping equals the current mapping. + if (wcscmp(pPort->pwszMapping, pwszDeviceMappings) == 0) + { + // We don't need to do anything in this case. + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + else + { + // Close the open file handle and free the memory for pwszMapping before remapping. + CloseHandle(pPort->hFile); + pPort->hFile = INVALID_HANDLE_VALUE; + + DllFreeSplStr(pPort->pwszMapping); + pPort->pwszMapping = NULL; + } + } + + // The port is usually mapped to the named pipe and this is how we received our data for printing. + // What we now need for accessing the actual port is the most recent mapping different from the named pipe. + p = pwszDeviceMappings; + + for (;;) + { + if (!*p) + { + // We reached the end of the list without finding a mapping. + ERR("Can't find a suitable mapping for the port \"%S\"!", pPort->pwszPortName); + goto Cleanup; + } + + if (_wcsicmp(p, pwszPipeName) != 0) + break; + + // Advance to the next mapping in the list. + p += wcslen(p) + 1; + } + + // We now want to create a DOS device "NONSPOOLED_" to this mapping, so that we're able to open it through CreateFileW. + dwErrorCode = _GetNonspooledPortName(pwszPortNameWithoutColon, &pwszNonspooledPortName); + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // Delete a possibly existing NONSPOOLED device before creating the new one, so we don't stack up device definitions. + DefineDosDeviceW(DDD_REMOVE_DEFINITION, pwszNonspooledPortName, NULL); + + if (!DefineDosDeviceW(DDD_RAW_TARGET_PATH, pwszNonspooledPortName, p)) + { + dwErrorCode = GetLastError(); + ERR("DefineDosDeviceW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // This is all we needed to do in SYSTEM context. + ImpersonatePrinterClient(hToken); + hToken = NULL; + + // Construct the file name to our created device for CreateFileW. + pwszNonspooledFileName = DllAllocSplMem((cchLocalSlashes + cchNonspooledPrefix + cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + if (!pwszNonspooledFileName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszNonspooledFileName, wszLocalSlashes, cchLocalSlashes * sizeof(WCHAR)); + CopyMemory(&pwszNonspooledFileName[cchLocalSlashes], wszNonspooledPrefix, cchNonspooledPrefix * sizeof(WCHAR)); + CopyMemory(&pwszNonspooledFileName[cchLocalSlashes + cchNonspooledPrefix], pwszPortNameWithoutColon, (cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + + // Finally open it for reading and writing. + pPort->hFile = CreateFileW(pwszNonspooledFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + if (pPort->hFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = GetLastError(); + ERR("CreateFileW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Store the current mapping of the port, so that we can check if it has changed. + pPort->pwszMapping = AllocSplStr(pwszDeviceMappings); + if (!pPort->pwszMapping) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + bReturnValue = TRUE; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (hToken) + ImpersonatePrinterClient(hToken); + + if (pwszDeviceMappings) + DllFreeSplMem(pwszDeviceMappings); + + if (pwszNonspooledFileName) + DllFreeSplMem(pwszNonspooledFileName); + + if (pwszNonspooledPortName) + DllFreeSplMem(pwszNonspooledPortName); + + if (pwszPipeName) + DllFreeSplMem(pwszPipeName); + + if (pwszPortNameWithoutColon) + DllFreeSplMem(pwszPortNameWithoutColon); + + SetLastError(dwErrorCode); + return bReturnValue; +} + +static PLOCALMON_PORT +_FindPort(PLOCALMON_HANDLE pLocalmon, PCWSTR pwszPortName) +{ + PLIST_ENTRY pEntry; + PLOCALMON_PORT pPort; + + for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry); + + if (wcscmp(pPort->pwszPortName, pwszPortName) == 0) + return pPort; + } + + return NULL; +} + +static DWORD +_LocalmonEnumPortsLevel1(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD cbPortName; + DWORD dwErrorCode; + DWORD dwPortCount = 0; + PBYTE pPortInfo; + PBYTE pPortString; + PLIST_ENTRY pEntry; + PLOCALMON_PORT pPort; + PORT_INFO_1W PortInfo1; + + // Count the required buffer size and the number of datatypes. + for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry); + + cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR); + *pcbNeeded += sizeof(PORT_INFO_1W) + cbPortName; + dwPortCount++; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings right after the last PORT_INFO_1W structure. + pPortInfo = pPorts; + pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_1W); + + // Copy over all ports. + for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry); + + // Copy the port name. + PortInfo1.pName = (PWSTR)pPortString; + cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR); + CopyMemory(pPortString, pPort->pwszPortName, cbPortName); + pPortString += cbPortName; + + // Copy the structure and advance to the next one in the output buffer. + CopyMemory(pPortInfo, &PortInfo1, sizeof(PORT_INFO_1W)); + pPortInfo += sizeof(PORT_INFO_1W); + } + + *pcReturned = dwPortCount; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +static DWORD +_LocalmonEnumPortsLevel2(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD cbPortName; + DWORD dwErrorCode; + DWORD dwPortCount = 0; + PBYTE pPortInfo; + PBYTE pPortString; + PLIST_ENTRY pEntry; + PLOCALMON_PORT pPort; + PORT_INFO_2W PortInfo2; + + // Count the required buffer size and the number of datatypes. + for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry); + + cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR); + *pcbNeeded += sizeof(PORT_INFO_2W) + cbPortName + cbLocalMonitor + cbLocalPort; + dwPortCount++; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings right after the last PORT_INFO_2W structure. + pPortInfo = pPorts; + pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_2W); + + // Copy over all ports. + for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry); + + // All local ports are writable and readable. + PortInfo2.fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ; + PortInfo2.Reserved = 0; + + // Copy the port name. + PortInfo2.pPortName = (PWSTR)pPortString; + cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR); + CopyMemory(pPortString, pPort->pwszPortName, cbPortName); + pPortString += cbPortName; + + // Copy the monitor name. + PortInfo2.pMonitorName = (PWSTR)pPortString; + CopyMemory(pPortString, pwszLocalMonitor, cbLocalMonitor); + pPortString += cbLocalMonitor; + + // Copy the description. + PortInfo2.pDescription = (PWSTR)pPortString; + CopyMemory(pPortString, pwszLocalPort, cbLocalPort); + pPortString += cbLocalPort; + + // Copy the structure and advance to the next one in the output buffer. + CopyMemory(pPortInfo, &PortInfo2, sizeof(PORT_INFO_2W)); + pPortInfo += sizeof(PORT_INFO_2W); + } + + *pcReturned = dwPortCount; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +/** + * @name _SetTransmissionRetryTimeout + * + * Checks if the given port is a physical one and sets the transmission retry timeout in this case using the value from registry. + * + * @param pPort + * The port to operate on. + * + * @return + * TRUE if the given port is a physical one, FALSE otherwise. + */ +static BOOL +_SetTransmissionRetryTimeout(PLOCALMON_PORT pPort) +{ + COMMTIMEOUTS CommTimeouts; + + // Get the timeout from the port. + if (!GetCommTimeouts(pPort->hFile, &CommTimeouts)) + return FALSE; + + // Set the timeout using the value from registry. + CommTimeouts.WriteTotalTimeoutConstant = GetLPTTransmissionRetryTimeout() * 1000; + SetCommTimeouts(pPort->hFile, &CommTimeouts); + + return TRUE; +} + +BOOL WINAPI +LocalmonClosePort(HANDLE hPort) +{ + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonClosePort(%p)\n", hPort); + + // Sanity checks + if (!pPort) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Close the file handle, free memory for pwszMapping and delete any NONSPOOLED port. + _ClosePortHandles(pPort); + + // Close any open printer handle. + if (pPort->hPrinter) + { + ClosePrinter(pPort->hPrinter); + pPort->hPrinter = NULL; + } + + // Free virtual FILE: ports which were created in LocalmonOpenPort. + if (pPort->PortType == PortType_FILE) + { + EnterCriticalSection(&pPort->pLocalmon->Section); + RemoveEntryList(&pPort->Entry); + DllFreeSplMem(pPort); + LeaveCriticalSection(&pPort->pLocalmon->Section); + } + + SetLastError(ERROR_SUCCESS); + return TRUE; +} + +BOOL WINAPI +LocalmonEndDocPort(HANDLE hPort) +{ + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonEndDocPort(%p)\n", hPort); + + // Sanity checks + if (!pPort) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Ending a document requires starting it first :-P + if (pPort->bStartedDoc) + { + // Close all ports opened in StartDocPort. + // That is, all but physical LPT ports (opened in OpenPort). + if (pPort->PortType != PortType_PhysicalLPT) + _ClosePortHandles(pPort); + + // Report our progress. + SetJobW(pPort->hPrinter, pPort->dwJobID, 0, NULL, JOB_CONTROL_SENT_TO_PRINTER); + + // We're done with the printer. + ClosePrinter(pPort->hPrinter); + pPort->hPrinter = NULL; + + // A new document can now be started again. + pPort->bStartedDoc = FALSE; + } + + SetLastError(ERROR_SUCCESS); + return TRUE; +} + +BOOL WINAPI +LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD dwErrorCode; + PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor; + + TRACE("LocalmonEnumPorts(%p, %S, %lu, %p, %lu, %p, %p)\n", hMonitor, pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned); + + // Sanity checks + if (!pLocalmon || (cbBuf && !pPorts) || !pcbNeeded || !pcReturned) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if (Level > 2) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + EnterCriticalSection(&pLocalmon->Section); + + // The function behaves differently for each level. + if (Level == 1) + dwErrorCode = _LocalmonEnumPortsLevel1(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned); + else if (Level == 2) + dwErrorCode = _LocalmonEnumPortsLevel2(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned); + + LeaveCriticalSection(&pLocalmon->Section); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/* + * @name LocalmonGetPrinterDataFromPort + * + * Performs a DeviceIoControl call for the given port. + * + * @param hPort + * The port to operate on. + * + * @param ControlID + * The dwIoControlCode passed to DeviceIoControl. Must not be zero! + * + * @param pValueName + * This parameter is ignored. + * + * @param lpInBuffer + * The lpInBuffer passed to DeviceIoControl. + * + * @param cbInBuffer + * The nInBufferSize passed to DeviceIoControl. + * + * @param lpOutBuffer + * The lpOutBuffer passed to DeviceIoControl. + * + * @param cbOutBuffer + * The nOutBufferSize passed to DeviceIoControl. + * + * @param lpcbReturned + * The lpBytesReturned passed to DeviceIoControl. Must not be zero! + * + * @return + * TRUE if the DeviceIoControl call was successful, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +LocalmonGetPrinterDataFromPort(HANDLE hPort, DWORD ControlID, PWSTR pValueName, PWSTR lpInBuffer, DWORD cbInBuffer, PWSTR lpOutBuffer, DWORD cbOutBuffer, PDWORD lpcbReturned) +{ + BOOL bOpenedPort = FALSE; + DWORD dwErrorCode; + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonGetPrinterDataFromPort(%p, %lu, %p, %p, %lu, %p, %lu, %p)\n", hPort, ControlID, pValueName, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer, lpcbReturned); + + // Sanity checks + if (!pPort || !ControlID || !lpcbReturned) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // If this is a serial port, a temporary file handle may be opened. + if (pPort->PortType == PortType_PhysicalCOM) + { + if (_CreateNonspooledPort(pPort)) + { + bOpenedPort = TRUE; + } + else if (GetLastError() != ERROR_SUCCESS) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else if (pPort->hFile == INVALID_HANDLE_VALUE) + { + // All other port types need to be opened already. + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Pass the parameters to DeviceIoControl. + if (!DeviceIoControl(pPort->hFile, ControlID, lpInBuffer, cbInBuffer, lpOutBuffer, cbOutBuffer, lpcbReturned, NULL)) + { + dwErrorCode = GetLastError(); + ERR("DeviceIoControl failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (bOpenedPort) + _ClosePortHandles(pPort); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle) +{ + DWORD dwErrorCode; + PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor; + PLOCALMON_PORT pPort; + + TRACE("LocalmonOpenPort(%p, %S, %p)\n", hMonitor, pName, pHandle); + + // Sanity checks + if (!pLocalmon || !pName || !pHandle) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Check if this is a FILE: port. + if (_wcsicmp(pName, L"FILE:") == 0) + { + // For FILE:, we create a virtual port for each request. + pPort = DllAllocSplMem(sizeof(LOCALMON_PORT)); + pPort->pLocalmon = pLocalmon; + pPort->PortType = PortType_FILE; + pPort->hFile = INVALID_HANDLE_VALUE; + + // Add it to the list of file ports. + EnterCriticalSection(&pLocalmon->Section); + InsertTailList(&pLocalmon->FilePorts, &pPort->Entry); + } + else + { + EnterCriticalSection(&pLocalmon->Section); + + // Check if the port name is valid. + pPort = _FindPort(pLocalmon, pName); + if (!pPort) + { + LeaveCriticalSection(&pLocalmon->Section); + dwErrorCode = ERROR_UNKNOWN_PORT; + goto Cleanup; + } + + // Even if this API is called OpenPort, port file handles aren't always opened here :-P + // Windows only does this for physical LPT ports here to enable bidirectional communication with the printer outside of jobs (using ReadPort and WritePort). + // The others are only opened per job in StartDocPort. + if (_IsLegacyPort(pName, L"LPT")) + { + // Try to create a NONSPOOLED port and open it. + if (_CreateNonspooledPort(pPort)) + { + // Set the transmission retry timeout for the ReadPort and WritePort calls. + // This also checks if this port is a physical one. + if (_SetTransmissionRetryTimeout(pPort)) + { + // This is definitely a physical LPT port! + pPort->PortType = PortType_PhysicalLPT; + } + else + { + // This is no physical port, so don't keep its handle open. + _ClosePortHandles(pPort); + } + } + else if (GetLastError() != ERROR_SUCCESS) + { + LeaveCriticalSection(&pLocalmon->Section); + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else if (_IsLegacyPort(pName, L"COM")) + { + // COM ports can't be redirected over the network, so this is a physical one. + pPort->PortType = PortType_PhysicalCOM; + } + } + + LeaveCriticalSection(&pLocalmon->Section); + + // Return our fetched LOCALMON_PORT structure in the handle. + *pHandle = (PHANDLE)pPort; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/* + * @name LocalmonSetPortTimeOuts + * + * Performs a SetCommTimeouts call for the given port. + * + * @param hPort + * The port to operate on. + * + * @param lpCTO + * Pointer to a COMMTIMEOUTS structure that is passed to SetCommTimeouts. + * + * @param Reserved + * Reserved parameter, must be 0. + * + * @return + * TRUE if the SetCommTimeouts call was successful, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved) +{ + BOOL bOpenedPort = FALSE; + DWORD dwErrorCode; + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonSetPortTimeOuts(%p, %p, %lu)\n", hPort, lpCTO, Reserved); + + // Sanity checks + if (!pPort || !lpCTO) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // If this is a serial port, a temporary file handle may be opened. + if (pPort->PortType == PortType_PhysicalCOM) + { + if (_CreateNonspooledPort(pPort)) + { + bOpenedPort = TRUE; + } + else if (GetLastError() != ERROR_SUCCESS) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else if (pPort->hFile == INVALID_HANDLE_VALUE) + { + // All other port types need to be opened already. + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Finally pass the parameters to SetCommTimeouts. + if (!SetCommTimeouts(pPort->hFile, lpCTO)) + { + dwErrorCode = GetLastError(); + ERR("SetCommTimeouts failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (bOpenedPort) + _ClosePortHandles(pPort); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD pcbRead) +{ + BOOL bOpenedPort = FALSE; + DWORD dwErrorCode; + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonReadPort(%p, %p, %lu, %p)\n", hPort, pBuffer, cbBuffer, pcbRead); + + // Sanity checks + if (!pPort || (cbBuffer && !pBuffer) || !pcbRead) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Reading is only supported for physical ports. + if (pPort->PortType != PortType_PhysicalCOM && pPort->PortType != PortType_PhysicalLPT) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // If this is a serial port, a temporary file handle may be opened. + if (pPort->PortType == PortType_PhysicalCOM) + { + if (_CreateNonspooledPort(pPort)) + { + bOpenedPort = TRUE; + } + else if (GetLastError() != ERROR_SUCCESS) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + + // Pass the parameters to ReadFile. + if (!ReadFile(pPort->hFile, pBuffer, cbBuffer, pcbRead, NULL)) + { + dwErrorCode = GetLastError(); + ERR("ReadFile failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + +Cleanup: + if (bOpenedPort) + _ClosePortHandles(pPort); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level, PBYTE pDocInfo) +{ + DWORD dwErrorCode; + PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo; // DOC_INFO_1W is the least common denominator for both DOC_INFO levels. + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonStartDocPort(%p, %S, %lu, %lu, %p)\n", hPort, pPrinterName, JobId, Level, pDocInfo); + + // Sanity checks + if (!pPort || !pPrinterName || (pPort->PortType == PortType_FILE && (!pDocInfo1 || !pDocInfo1->pOutputFile || !*pDocInfo1->pOutputFile))) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if (Level > 2) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Calling StartDocPort multiple times isn't considered a failure, but we don't need to do anything then. + if (pPort->bStartedDoc) + { + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + // Open a handle to the given printer for later reporting our progress using SetJobW. + if (!OpenPrinterW(pPrinterName, &pPort->hPrinter, NULL)) + { + dwErrorCode = GetLastError(); + ERR("OpenPrinterW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We need our Job ID for SetJobW as well. + pPort->dwJobID = JobId; + + // Check the port type. + if (pPort->PortType == PortType_PhysicalLPT) + { + // Update the NONSPOOLED mapping if the port mapping has changed since our OpenPort call. + if (!_CreateNonspooledPort(pPort) && GetLastError() != ERROR_SUCCESS) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // Update the transmission retry timeout as well. + _SetTransmissionRetryTimeout(pPort); + } + else if(pPort->PortType == PortType_FILE) + { + // This is a FILE: port. Open the output file given in the Document Info. + pPort->hFile = CreateFileW(pDocInfo1->pOutputFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL); + if (pPort->hFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else + { + // This can be: + // - a physical COM port + // - a non-physical LPT port (e.g. with "net use LPT1 ...") + // - any other port (e.g. a file or a shared printer installed as a local port) + // + // For all these cases, we try to create a NONSPOOLED port per job. + // If _CreateNonspooledPort reports that no NONSPOOLED port is necessary, we can just open the port name. + if (!_CreateNonspooledPort(pPort)) + { + if (GetLastError() == ERROR_SUCCESS) + { + pPort->hFile = CreateFileW(pPort->pwszPortName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + if (pPort->hFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + pPort->bStartedDoc = TRUE; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten) +{ + BOOL bOpenedPort = FALSE; + DWORD dwErrorCode; + PLOCALMON_PORT pPort = (PLOCALMON_PORT)hPort; + + TRACE("LocalmonWritePort(%p, %p, %lu, %p)\n", hPort, pBuffer, cbBuf, pcbWritten); + + // Sanity checks + if (!pPort || (cbBuf && !pBuffer) || !pcbWritten) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // If this is a serial port, a temporary file handle may be opened. + if (pPort->PortType == PortType_PhysicalCOM) + { + if (_CreateNonspooledPort(pPort)) + { + bOpenedPort = TRUE; + } + else if (GetLastError() != ERROR_SUCCESS) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + } + else if (pPort->hFile == INVALID_HANDLE_VALUE) + { + // All other port types need to be opened already. + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Pass the parameters to WriteFile. + if (!WriteFile(pPort->hFile, pBuffer, cbBuf, pcbWritten, NULL)) + { + dwErrorCode = GetLastError(); + ERR("WriteFile failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // If something was written down, we consider that a success, otherwise it's a timeout. + if (*pcbWritten) + dwErrorCode = ERROR_SUCCESS; + else + dwErrorCode = ERROR_TIMEOUT; + +Cleanup: + if (bOpenedPort) + _ClosePortHandles(pPort); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/monitors/localmon/precomp.h =================================================================== --- win32ss/printing/monitors/localmon/precomp.h (nonexistent) +++ win32ss/printing/monitors/localmon/precomp.h (working copy) @@ -0,0 +1,109 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(localmon); + +#include "resource.h" + +// Structures +/** + * Describes the monitor handle returned by InitializePrintMonitor2. + * Manages all available ports in this instance. + */ +typedef struct _LOCALMON_HANDLE +{ + CRITICAL_SECTION Section; /** Critical Section for modifying or reading the ports. */ + LIST_ENTRY FilePorts; /** Ports created when a document is printed on FILE: and the user entered a file name. */ + LIST_ENTRY RegistryPorts; /** Valid ports loaded from the local registry. */ + LIST_ENTRY XcvHandles; /** Xcv handles created with LocalmonXcvOpenPort. */ +} +LOCALMON_HANDLE, *PLOCALMON_HANDLE; + +/** + * Describes the port handle returned by LocalmonOpenPort. + * Manages a legacy port (COM/LPT) or virtual FILE: port for printing as well as its associated printer and job. + */ +typedef struct _LOCALMON_PORT +{ + LIST_ENTRY Entry; + enum { + PortType_Other = 0, /** Any port that doesn't belong into the other categories (default). */ + PortType_FILE, /** A port created when a document is printed on FILE: and the user entered a file name. */ + PortType_PhysicalCOM, /** A physical serial port (COM) */ + PortType_PhysicalLPT /** A physical parallel port (LPT) */ + } + PortType; + BOOL bStartedDoc; /** Whether a document has been started with StartDocPort. */ + DWORD dwJobID; /** ID of the printing job we are processing (for later reporting progress using SetJobW). */ + HANDLE hFile; /** Handle to the opened port or INVALID_HANDLE_VALUE if it isn't currently opened. */ + HANDLE hPrinter; /** Handle to the printer for the job on this port (for using SetJobW). */ + PLOCALMON_HANDLE pLocalmon; /** Pointer to the parent LOCALMON_HANDLE structure. */ + PWSTR pwszMapping; /** The current mapping of the DOS Device corresponding to this port at the time _CreateNonspooledPort has been called. */ + PWSTR pwszPortName; /** The name of this port including the trailing colon. Empty for virtual file ports. */ +} +LOCALMON_PORT, *PLOCALMON_PORT; + +/** + * Describes the Xcv handle returned by LocalmonXcvOpenPort. + * Manages the required data for the Xcv* calls. + */ +typedef struct _LOCALMON_XCV +{ + LIST_ENTRY Entry; + ACCESS_MASK GrantedAccess; + PLOCALMON_HANDLE pLocalmon; + PWSTR pwszObject; +} +LOCALMON_XCV, *PLOCALMON_XCV; + +// main.c +extern DWORD cbLocalMonitor; +extern DWORD cbLocalPort; +extern PCWSTR pwszLocalMonitor; +extern PCWSTR pwszLocalPort; +void WINAPI LocalmonShutdown(HANDLE hMonitor); + +// ports.c +BOOL WINAPI LocalmonClosePort(HANDLE hPort); +BOOL WINAPI LocalmonEndDocPort(HANDLE hPort); +BOOL WINAPI LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned); +BOOL WINAPI LocalmonGetPrinterDataFromPort(HANDLE hPort, DWORD ControlID, PWSTR pValueName, PWSTR lpInBuffer, DWORD cbInBuffer, PWSTR lpOutBuffer, DWORD cbOutBuffer, PDWORD lpcbReturned); +BOOL WINAPI LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle); +BOOL WINAPI LocalmonReadPort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuffer, PDWORD pcbRead); +BOOL WINAPI LocalmonSetPortTimeOuts(HANDLE hPort, LPCOMMTIMEOUTS lpCTO, DWORD Reserved); +BOOL WINAPI LocalmonStartDocPort(HANDLE hPort, PWSTR pPrinterName, DWORD JobId, DWORD Level, PBYTE pDocInfo); +BOOL WINAPI LocalmonWritePort(HANDLE hPort, PBYTE pBuffer, DWORD cbBuf, PDWORD pcbWritten); + +// tools.c +BOOL DoesPortExist(PCWSTR pwszPortName); +DWORD GetLPTTransmissionRetryTimeout(); +DWORD GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon); + +// xcv.c +BOOL WINAPI LocalmonXcvClosePort(HANDLE hXcv); +DWORD WINAPI LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded); +BOOL WINAPI LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv); + +#endif Index: win32ss/printing/monitors/localmon/resource.h =================================================================== --- win32ss/printing/monitors/localmon/resource.h (nonexistent) +++ win32ss/printing/monitors/localmon/resource.h (working copy) @@ -0,0 +1,11 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Resource IDs + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#pragma once + +#define IDS_LOCAL_PORT 500 +#define IDS_LOCAL_MONITOR 507 Index: win32ss/printing/monitors/localmon/tools.c =================================================================== --- win32ss/printing/monitors/localmon/tools.c (nonexistent) +++ win32ss/printing/monitors/localmon/tools.c (working copy) @@ -0,0 +1,166 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Various support functions shared by multiple files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +/** + * @name DoesPortExist + * + * Checks all Port Monitors installed on the local system to find out if a given port already exists. + * + * @param pwszPortName + * The port name to check. + * + * @return + * TRUE if a port with that name already exists on the local system. + * If the return value is FALSE, either the port doesn't exist or an error occurred. + * Use GetLastError in this case to check the error case. + */ +BOOL +DoesPortExist(PCWSTR pwszPortName) +{ + BOOL bReturnValue = FALSE; + DWORD cbNeeded; + DWORD dwErrorCode; + DWORD dwReturned; + DWORD i; + PPORT_INFO_1W p; + PPORT_INFO_1W pPortInfo1 = NULL; + + // Determine the required buffer size. + EnumPortsW(NULL, 1, NULL, 0, &cbNeeded, &dwReturned); + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + dwErrorCode = GetLastError(); + ERR("EnumPortsW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Allocate a buffer large enough. + pPortInfo1 = DllAllocSplMem(cbNeeded); + if (!pPortInfo1) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Now get the actual port information. + if (!EnumPortsW(NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned)) + { + dwErrorCode = GetLastError(); + ERR("EnumPortsW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We were successful! Loop through all returned ports. + dwErrorCode = ERROR_SUCCESS; + p = pPortInfo1; + + for (i = 0; i < dwReturned; i++) + { + // Check if this existing port matches our queried one. + if (wcsicmp(p->pName, pwszPortName) == 0) + { + bReturnValue = TRUE; + goto Cleanup; + } + + p++; + } + +Cleanup: + if (pPortInfo1) + DllFreeSplMem(pPortInfo1); + + SetLastError(dwErrorCode); + return bReturnValue; +} + +DWORD +GetLPTTransmissionRetryTimeout() +{ + DWORD cbBuffer; + DWORD dwReturnValue = 90; // Use 90 seconds as default if we fail to read from registry. + HKEY hKey; + LSTATUS lStatus; + + // Six digits is the most you can enter in Windows' LocalUI.dll. + // Larger values make it crash, so introduce a limit here. + WCHAR wszBuffer[6 + 1]; + + // Open the key where our value is stored. + lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_READ, &hKey); + if (lStatus != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %ld!\n", lStatus); + goto Cleanup; + } + + // Query the value. + cbBuffer = sizeof(wszBuffer); + lStatus = RegQueryValueExW(hKey, L"TransmissionRetryTimeout", NULL, NULL, (PBYTE)wszBuffer, &cbBuffer); + if (lStatus != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %ld!\n", lStatus); + goto Cleanup; + } + + // Return it converted to a DWORD. + dwReturnValue = wcstoul(wszBuffer, NULL, 10); + +Cleanup: + if (hKey) + RegCloseKey(hKey); + + return dwReturnValue; +} + +/** + * @name GetPortNameWithoutColon + * + * Most of the time, we operate on port names with a trailing colon. But some functions require the name without the trailing colon. + * This function checks if the port has a trailing colon and if so, it returns the port name without the colon. + * + * @param pwszPortName + * The port name with colon + * + * @param ppwszPortNameWithoutColon + * Pointer to a PWSTR that will contain the port name without colon. + * You have to free this buffer using DllFreeSplMem. + * + * @return + * ERROR_SUCCESS if the port name without colon was successfully copied into the buffer. + * ERROR_INVALID_PARAMETER if this port name has no trailing colon. + * ERROR_NOT_ENOUGH_MEMORY if memory allocation failed. + */ +DWORD +GetPortNameWithoutColon(PCWSTR pwszPortName, PWSTR* ppwszPortNameWithoutColon) +{ + DWORD cchPortNameWithoutColon; + + // Compute the string length of pwszPortNameWithoutColon. + cchPortNameWithoutColon = wcslen(pwszPortName) - 1; + + // Check if pwszPortName really has a colon as the last character. + if (pwszPortName[cchPortNameWithoutColon] != L':') + return ERROR_INVALID_PARAMETER; + + // Allocate the output buffer. + *ppwszPortNameWithoutColon = DllAllocSplMem((cchPortNameWithoutColon + 1) * sizeof(WCHAR)); + if (!*ppwszPortNameWithoutColon) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return ERROR_NOT_ENOUGH_MEMORY; + } + + // Copy the port name without colon into the buffer. + // The buffer is already zero-initialized, so no additional null-termination is necessary. + CopyMemory(*ppwszPortNameWithoutColon, pwszPortName, cchPortNameWithoutColon * sizeof(WCHAR)); + + return ERROR_SUCCESS; +} Index: win32ss/printing/monitors/localmon/ui/CMakeLists.txt =================================================================== --- win32ss/printing/monitors/localmon/ui/CMakeLists.txt (nonexistent) +++ win32ss/printing/monitors/localmon/ui/CMakeLists.txt (working copy) @@ -0,0 +1,14 @@ + +add_definitions(-D__WINESRC__) +include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) +spec2def(localui.dll localui.spec) + +list(APPEND SOURCE + localui.c + ${CMAKE_CURRENT_BINARY_DIR}/localui.def) + +add_library(localui SHARED ${SOURCE} localui.rc) +set_module_type(localui win32dll) +target_link_libraries(localui wine) +add_importlibs(localui winspool user32 msvcrt kernel32 ntdll) +add_cd_file(TARGET localui DESTINATION reactos/system32 FOR all) Index: win32ss/printing/monitors/localmon/ui/lang/ui_Da.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Da.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Da.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Danish resources for localui + * + * Copyright 2008 Jens Albretsen + * + * 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 + * + */ + +LANGUAGE LANG_DANISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Lokal port" + IDS_INVALIDNAME "'%s' er ikke et gyldigt port navn" + IDS_PORTEXISTS "Porten %s findes allerede" + IDS_NOTHINGTOCONFIG "Denne port har ingen indstillinger" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Opret en lokal port" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Skriv navnet på den nye port:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuller", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Opsæt LPT port" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (sekunder)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Transmission retry:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuller", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_De.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_De.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_De.rc (working copy) @@ -0,0 +1,56 @@ +/* + * German resources for localui + * + * Copyright 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 + * + */ + +#pragma code_page(65001) + +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Lokaler Anschluss" + IDS_INVALIDNAME "'%s' ist kein gültiger Anschlussname" + IDS_PORTEXISTS "Der Anschluss %s existiert bereits" + IDS_NOTHINGTOCONFIG "Dieser Anschluss besitzt keine zu konfigurierenden Optionen" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Lokalen Anschluss hinzufügen" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Lokaler Anschluss, der hinzugefügt werden soll:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Abbrechen", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "LPT-Anschluss konfigurieren" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Zeitüberschreitung (Sekunden)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "Ü&bertragung wiederholen:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Abbrechen", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_En.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_En.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_En.rc (working copy) @@ -0,0 +1,54 @@ +/* + * English resources for localui + * + * Copyright 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 + * + */ + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Local Port" + IDS_INVALIDNAME "'%s' is not a valid port name" + IDS_PORTEXISTS "Port %s already exists" + IDS_NOTHINGTOCONFIG "This port has no options to configure" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Add a Local Port" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Enter the port name to add:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancel", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configure LPT Port" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (seconds)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Transmission Retry:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancel", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Es.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Es.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Es.rc (working copy) @@ -0,0 +1,56 @@ +/* + * Spanish resources for localui + * + * Copyright 2010 José Rostagno + * + * 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 + * + */ + +#pragma code_page(65001) + +LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Puerto local" + IDS_INVALIDNAME "'%s' no es un nombre de puerto válido" + IDS_PORTEXISTS "El puerto %s ya existe" + IDS_NOTHINGTOCONFIG "Este puerto no tiene opciones para configurar" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Agregar un puerto local" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Ingrese el nombre del puerto a agregar:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "Aceptar", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancelar", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configurar puerto LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Tiempo de espera (segundos)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Reintentar transmisión:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "Aceptar", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancelar", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Fr.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Fr.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Fr.rc (working copy) @@ -0,0 +1,56 @@ +/* + * French resources for localui + * + * Copyright 2007 Jonathan Ernst + * + * 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 + * + */ + +#pragma code_page(65001) + +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Port local" + IDS_INVALIDNAME "« %s » n'est pas un nom de port valide" + IDS_PORTEXISTS "Le port %s existe déjà" + IDS_NOTHINGTOCONFIG "Ce port n'a pas d'options de configuration" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Ajouter un port local" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Saisisser le nom du port à ajouter :", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuler", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configurer un port LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Délai (en secondes)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Essais de retransmission :", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuler", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_He.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_He.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_He.rc (working copy) @@ -0,0 +1,56 @@ +/* + * Hebrew resources for localui + * + * Copyright 2007 Detlef Riekenberg + * + * Translated by Baruch Rutman + * + * 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 + * + */ + +LANGUAGE LANG_HEBREW, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "יציאה מקומית" + IDS_INVALIDNAME "'%s' אינו שם יציאה חוקי" + IDS_PORTEXISTS "יציאה %s כבר קיימת" + IDS_NOTHINGTOCONFIG "ליציאה הזו אין אפשרויות להגדיר" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "הוסף יציאה מקומית" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "הזן את שם היציאה כדי להוסיפה:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "אישור", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "ביטול", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "הגדרת יציאת LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "פסק זמן (שניות)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "ניסיון שידור חוזר:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "אישור", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "ביטול", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Hu.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Hu.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Hu.rc (working copy) @@ -0,0 +1,57 @@ +/* + * Hungarian resources for localui + * + * Copyright 2010 Andras Kovacs + * + * 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Helyi port" + IDS_INVALIDNAME "A(z) '%s' nem egy érvényes portnév" + IDS_PORTEXISTS "A port: %s már létezik" + IDS_NOTHINGTOCONFIG "Ennek a portnak nincsenek beállítható tulajdonságai" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Helyi port hozzáadása" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Adja meg a &hozzáadni kívánt port nevét:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Mégse", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "LPT port beállítása" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Időtúllépés (másodperc)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "Á&tviteli újrapróbálkozás:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Mégse", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_It.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_It.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_It.rc (working copy) @@ -0,0 +1,58 @@ +/* + * Italian resources for localui + * + * Copyright 2007 Detlef Riekenberg + * Copyright 2010 Luca Bennati + * + * 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Porta locale" + IDS_INVALIDNAME "'%s' non è un nome di porta valido" + IDS_PORTEXISTS "La porta %s già esiste" + IDS_NOTHINGTOCONFIG "Questa porta non ha opzioni da configurare" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Aggiungi una porta locale" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Inserisci il nome della porta da aggiungere:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annulla", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configura la porta LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (secondi)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Tentativi di trasmissione:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annulla", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Ja.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Ja.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Ja.rc (working copy) @@ -0,0 +1,57 @@ +/* + * Japanese resources for localui + * + * Copyright 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "ローカル ポート" + IDS_INVALIDNAME "'%s' はポート名として正しくありません" + IDS_PORTEXISTS "ポート %s はすでに存在します" + IDS_NOTHINGTOCONFIG "このポートには設定項目がありません" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "ローカル ポートの追加" +FONT 9, "MS UI Gothic" +BEGIN + LTEXT "追加するポートの名前(&E):", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "キャンセル", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "プリンタ ポートの設定" +FONT 9, "MS UI Gothic" +BEGIN + GROUPBOX "タイムアウト (秒)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "再送回数(&T):", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "キャンセル", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Ko.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Ko.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Ko.rc (working copy) @@ -0,0 +1,55 @@ +/* + * Korean resources for localui + * + * Copyright 2007 Detlef Riekenberg + * Copyright 2007 YunSong Hwang(황윤성)(hys545@dreamwiz.com) + * + * 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 + * + */ + +LANGUAGE LANG_KOREAN, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "지역 포트" + IDS_INVALIDNAME "'%s'는 올바른 포트 이름이 아닙니다" + IDS_PORTEXISTS "포트 %s는 이미 존재합니다" + IDS_NOTHINGTOCONFIG "이 포트는 설정할 옵션이 없습니다" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "지역 포트 더하기" +FONT 9, "MS Shell Dlg" +BEGIN + LTEXT "더할 포트 이름 입력(&E):", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "확인", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "취소", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "LPT 포트 설정" +FONT 9, "MS Shell Dlg" +BEGIN + GROUPBOX "시간초과(초)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "재 전송 횟수(&T):", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "확인", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "취소", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Lt.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Lt.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Lt.rc (working copy) @@ -0,0 +1,57 @@ +/* + * Lithuanian resources for localui + * + * Copyright 2009 Aurimas Fišeras + * + * 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_LITHUANIAN, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Vietinis prievadas" + IDS_INVALIDNAME "„%s“ yra netinkamas prievado vardas" + IDS_PORTEXISTS "Prievadas %s jau egzistuoja" + IDS_NOTHINGTOCONFIG "Šis prievadas neturi parinkčių konfigūravimui" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Pridėti vietinį prievadą" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Įveskite pridedamo prievado vardą:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "Gerai", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Atsisakyti", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Konfigūruoti LPT prievadą" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Laukimo laikas (sekundėmis)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Perdavimo pakartojimas:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "Gerai", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Atsisakyti", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Nl.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Nl.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Nl.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Dutch resources for localui + * + * Copyright 2008 Frans Kool + * + * 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 + * + */ + +LANGUAGE LANG_DUTCH, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Lokale Poort" + IDS_INVALIDNAME "'%s' is geen valide poort naam" + IDS_PORTEXISTS "Poort %s bestaat reeds" + IDS_NOTHINGTOCONFIG "Deze poort heeft geen opties om in te stellen" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Voeg een Lokale Poort toe" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Voer de toe te voegen poort naam in:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuleren", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configureer LPT Poort" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (seconden)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Transmissie Herstart:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Annuleren", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_No.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_No.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_No.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Norwegian Bokmål resources for localui + * + * Copyright 2007 Alexander N. Sørnes + * + * 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 + * + */ + +LANGUAGE LANG_NORWEGIAN, SUBLANG_NORWEGIAN_BOKMAL + +STRINGTABLE +{ + IDS_LOCALPORT "Lokal port" + IDS_INVALIDNAME "«%s» er ikke et gyldig portnavn" + IDS_PORTEXISTS "Porten %s finnes allerede" + IDS_NOTHINGTOCONFIG "Denne porten har ingen innstillinger" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Legg til en lokal port" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Skriv inn navn&et på den nye porten:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Avbryt", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Oppsett av LPT-port" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Tidsavbrudd (sekunder)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "Prøv å sende på nyt&t:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Avbryt", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Pl.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Pl.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Pl.rc (working copy) @@ -0,0 +1,55 @@ +/* + * Polish resources for localui + * + * Copyright 2007 Detlef Riekenberg + * Copyright 2007 Mikolaj Zalewski + * + * 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 + * + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Port lokalny" + IDS_INVALIDNAME "'%s' nie jest poprawną nazwą portu" + IDS_PORTEXISTS "Port %s już istnieje" + IDS_NOTHINGTOCONFIG "Ten port nie ma opcji do skonfigurowania" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Dodaj port lokalny" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Nazwa nowego portu:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "&OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "&Anuluj", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Konfiguracja portu LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Czasy oczekiwania (sekundy)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Ponowienie transmisji:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "&OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "&Anuluj", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Pt.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Pt.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Pt.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Portuguese resources for localui + * + * Copyright 2008 Ricardo Filipe + * + * 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 + * + */ + +LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Porta Local" + IDS_INVALIDNAME "'%s' não é um nome de porta válido" + IDS_PORTEXISTS "Porta %s já existe" + IDS_NOTHINGTOCONFIG "Esta porta não possui opções de configuração" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Adicionar uma porta local" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Introduza o nome da porta a adicionar:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancelar", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configurar porta LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Tempo expirado (segundos)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Recomeço da transmissão:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Cancelar", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Ro.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Ro.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Ro.rc (working copy) @@ -0,0 +1,56 @@ +/* + * Copyright 2007 Detlef Riekenberg + * Copyright 2008 Michael Stefaniuc + * 2011 Fulea Ștefan + * + * 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 + * + */ + +#pragma code_page(65001) + +LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Port local" + IDS_INVALIDNAME "„%s” nu este un nume valid de port" + IDS_PORTEXISTS "Portul %s existsă deja" + IDS_NOTHINGTOCONFIG "Acest port nu are opțiuni de configurat" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Adaugare port local" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "N&umele portului adăugat:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "Con&firmă", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "A&nulează", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Configurare port LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Temporizare (secunde)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Reîncearcă transmisia:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "Con&firmă", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "A&nulează", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Ru.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Ru.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Ru.rc (working copy) @@ -0,0 +1,57 @@ +/* + * Russian resources for localui + * + * Copyright 2008 Vitaliy Margolen + * + * 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Локальный порт" + IDS_INVALIDNAME "Неправильное название порта '%s'" + IDS_PORTEXISTS "Порт '%s' уже существует" + IDS_NOTHINGTOCONFIG "Этот порт не имеет настроек" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Добавить локальный порт" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Введите &название локального порта:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Отменить", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Установки параллельного порта" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Тайм-аут (секунд)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Попыток пересылки:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Отмена", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Si.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Si.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Si.rc (working copy) @@ -0,0 +1,56 @@ +/* + * Slovenian resources for localui + * + * Copyright 2008 Rok Mandeljc + * + * 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 + * + */ + +#pragma code_page(65001) + +LANGUAGE LANG_SLOVENIAN, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Lokalna vrata" + IDS_INVALIDNAME "'%s' ni veljavno ime vrat" + IDS_PORTEXISTS "Vrata z imenom %s že obstajajo" + IDS_NOTHINGTOCONFIG "Ta vrata nimajo možnosti nastavitve" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Dodaj lokalna vrata" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Ime vrat:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "V redu", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Prekliči", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Nastavitev LPT vrat" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Časovna omejitev (seconds)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Ponoven poskus prenosa:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "V redu", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Prekliči", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Sq.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Sq.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Sq.rc (working copy) @@ -0,0 +1,55 @@ +/* + * English resources for localui + * + * Copyright 2007 Detlef Riekenberg + * Translation: Ardit Dani (Albanian Translation Resource File) + * + * 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 + * + */ + +LANGUAGE LANG_ALBANIAN, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Porti Vendor" + IDS_INVALIDNAME "'%s' nuk është emer e vlefshem porti" + IDS_PORTEXISTS "Porti %s ekziston" + IDS_NOTHINGTOCONFIG "Ky port ska opsione për të konfiguruar" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Shto një Port Vendor" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Fut emrin e Portit për të shtuar:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Anulo", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Konfiguro Portin LPT" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Timeout (sekonda)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Transmission Riprove:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Anulo", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Sv.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Sv.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Sv.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Swedish resources for localui + * + * Copyright 2007 Daniel Nylander + * + * 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 + * + */ + +LANGUAGE LANG_SWEDISH, SUBLANG_NEUTRAL + +STRINGTABLE +{ + IDS_LOCALPORT "Lokal port" + IDS_INVALIDNAME "'%s' är inte ett giltigt portnamn" + IDS_PORTEXISTS "Porten %s finns redan" + IDS_NOTHINGTOCONFIG "Denna port har inga alternativ att konfigurera" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Lägg till en lokal port" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Ange portnamnet att lägga till:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Avbryt", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Konfigurera LPT-port" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Tidsgräns (sekunder)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "Öve&rföringsförsök:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Avbryt", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Tr.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Tr.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Tr.rc (working copy) @@ -0,0 +1,54 @@ +/* + * Turkish resources for localui + * + * Copyright: 2014 Erdem Ersoy (eersoy93) (erdemersoy@live.com) + * + * 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 + * + */ + +LANGUAGE LANG_TURKISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Yerli Giriş" + IDS_INVALIDNAME """%s"", geçerli bir giriş adı değil." + IDS_PORTEXISTS "%s girişi önceden var." + IDS_NOTHINGTOCONFIG "Bu girişin yapılandırmak için seçeneği yok." +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Bir Yerli Giriş Ekle" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "&Eklemek için giriş adını giriniz:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "Tamam", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "İptal", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "LPT Girişini Yapılandır" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Süre Aşımı (Sâniye)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&İletimi Yeniden Dene:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "Tamam", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "İptal", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Uk.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Uk.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Uk.rc (working copy) @@ -0,0 +1,57 @@ +/* + * Ukrainian resources for localui + * + * Copyright 2010 Igor Paliychuk + * + * 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 + * + */ + +/* UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT + +STRINGTABLE +{ + IDS_LOCALPORT "Локальний порт" + IDS_INVALIDNAME "'%s' не дійсна назва порту" + IDS_PORTEXISTS "Порт '%s' вже існує" + IDS_NOTHINGTOCONFIG "Цей порт не має налаштувань" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Додати локальний порт" +FONT 8, "MS Shell Dlg" +BEGIN + LTEXT "Введіть &назву локального порта:", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "OK", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Скасувати", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "Налаштування LPT порта" +FONT 8, "MS Shell Dlg" +BEGIN + GROUPBOX "Тайм-аут (секунд)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "&Спроб пересилання:", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "OK", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "Скасувати", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/lang/ui_Zh.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/lang/ui_Zh.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/lang/ui_Zh.rc (working copy) @@ -0,0 +1,91 @@ +/* + * localui (Simplified and Traditional Chinese Resources) + * + * Copyright 2008 Hongbo Ni + * + * 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 + * + */ + +/* Chinese text is encoded in UTF-8 */ +#pragma code_page(65001) + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +STRINGTABLE +{ + IDS_LOCALPORT "本地端口" + IDS_INVALIDNAME "'%s' 不是有效的端口名称" + IDS_PORTEXISTS "端口 %s 已经存在" + IDS_NOTHINGTOCONFIG "这个端口没有可设置选项" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "添加本地端口" +FONT 9, "MS Shell Dlg" +BEGIN + LTEXT "添加本地端口名称(&E):", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "确定", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "取消", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "设置打印端口" +FONT 9, "MS Shell Dlg" +BEGIN + GROUPBOX "超时(秒)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "重试通讯(&T):", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "确定", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "取消", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL + +STRINGTABLE +{ + IDS_LOCALPORT "本地端口" + IDS_INVALIDNAME "'%s' 不是有效的端口名稱" + IDS_PORTEXISTS "端口 %s 已經存在" + IDS_NOTHINGTOCONFIG "這個端口沒有可設定選項" +} + +ADDPORT_DIALOG DIALOGEX 6, 18, 245, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "添加本地端口" +FONT 9, "MS Shell Dlg" +BEGIN + LTEXT "添加本地端口名稱(&E):", -1, 7, 13, 194, 13, WS_VISIBLE + EDITTEXT ADDPORT_EDIT, 6, 28, 174, 12, WS_VISIBLE | ES_AUTOHSCROLL + DEFPUSHBUTTON "確定", IDOK, 188, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "取消", IDCANCEL, 188, 27, 50, 14, WS_VISIBLE +END + + +LPTCONFIG_DIALOG DIALOGEX 6, 18, 220, 47 +STYLE DS_SHELLFONT | DS_CONTEXTHELP | DS_MODALFRAME | DS_SETFOREGROUND | WS_POPUPWINDOW | WS_VISIBLE | WS_CAPTION +CAPTION "設定列印端口" +FONT 9, "MS Shell Dlg" +BEGIN + GROUPBOX "超時(秒)", LPTCONFIG_GROUP, 6, 6, 150, 35, BS_GROUPBOX + LTEXT "重試通訊(&T):", -1, 14, 22, 90, 13, WS_VISIBLE + EDITTEXT LPTCONFIG_EDIT, 112, 20, 32, 13, WS_VISIBLE | ES_NUMBER + DEFPUSHBUTTON "確定", IDOK, 164, 10, 50, 14, WS_VISIBLE + PUSHBUTTON "取消", IDCANCEL, 164, 27, 50, 14, WS_VISIBLE +END Index: win32ss/printing/monitors/localmon/ui/localui.c =================================================================== --- win32ss/printing/monitors/localmon/ui/localui.c (nonexistent) +++ win32ss/printing/monitors/localmon/ui/localui.c (working copy) @@ -0,0 +1,696 @@ +/* + * Implementation of the Local Printmonitor User Interface + * + * Copyright 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 + */ + +#define WIN32_NO_STATUS + +#include + +#define NONAMELESSUNION + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "localui.h" + +WINE_DEFAULT_DEBUG_CHANNEL(localui); + +/*****************************************************/ + +static HINSTANCE LOCALUI_hInstance; + +static const WCHAR cmd_AddPortW[] = {'A','d','d','P','o','r','t',0}; +static const WCHAR cmd_ConfigureLPTPortCommandOKW[] = {'C','o','n','f','i','g','u','r','e', + 'L','P','T','P','o','r','t', + 'C','o','m','m','a','n','d','O','K',0}; +static const WCHAR cmd_DeletePortW[] = {'D','e','l','e','t','e','P','o','r','t',0}; +static const WCHAR cmd_GetDefaultCommConfigW[] = {'G','e','t', + 'D','e','f','a','u','l','t', + 'C','o','m','m','C','o','n','f','i','g',0}; +static const WCHAR cmd_GetTransmissionRetryTimeoutW[] = {'G','e','t', + 'T','r','a','n','s','m','i','s','s','i','o','n', + 'R','e','t','r','y','T','i','m','e','o','u','t',0}; +static const WCHAR cmd_PortIsValidW[] = {'P','o','r','t','I','s','V','a','l','i','d',0}; +static const WCHAR cmd_SetDefaultCommConfigW[] = {'S','e','t', + 'D','e','f','a','u','l','t', + 'C','o','m','m','C','o','n','f','i','g',0}; + +static const WCHAR fmt_uW[] = {'%','u',0}; +static const WCHAR portname_LPT[] = {'L','P','T',0}; +static const WCHAR portname_COM[] = {'C','O','M',0}; +static const WCHAR portname_FILE[] = {'F','I','L','E',':',0}; +static const WCHAR portname_CUPS[] = {'C','U','P','S',':',0}; +static const WCHAR portname_LPR[] = {'L','P','R',':',0}; + +static const WCHAR XcvMonitorW[] = {',','X','c','v','M','o','n','i','t','o','r',' ',0}; +static const WCHAR XcvPortW[] = {',','X','c','v','P','o','r','t',' ',0}; + +/*****************************************************/ + +typedef struct tag_addportui_t { + LPWSTR portname; + HANDLE hXcv; +} addportui_t; + +typedef struct tag_lptconfig_t { + HANDLE hXcv; + DWORD value; +} lptconfig_t; + + +static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + +/***************************************************** + * strdupWW [internal] + */ + +static LPWSTR strdupWW(LPCWSTR pPrefix, LPCWSTR pSuffix) +{ + LPWSTR ptr; + DWORD len; + + len = lstrlenW(pPrefix) + (pSuffix ? lstrlenW(pSuffix) : 0) + 1; + ptr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (ptr) { + lstrcpyW(ptr, pPrefix); + if (pSuffix) lstrcatW(ptr, pSuffix); + } + return ptr; +} + +/***************************************************** + * dlg_configure_com [internal] + * + */ + +static BOOL dlg_configure_com(HANDLE hXcv, HWND hWnd, PCWSTR pPortName) +{ + COMMCONFIG cfg; + LPWSTR shortname; + DWORD status; + DWORD dummy; + DWORD len; + BOOL res; + + /* strip the colon (pPortName is never empty here) */ + len = lstrlenW(pPortName); + shortname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (shortname) { + memcpy(shortname, pPortName, (len -1) * sizeof(WCHAR)); + shortname[len-1] = '\0'; + + /* get current settings */ + len = FIELD_OFFSET(COMMCONFIG, wcProviderData[1]); + status = ERROR_SUCCESS; + res = XcvDataW( hXcv, cmd_GetDefaultCommConfigW, + (PBYTE) shortname, + (lstrlenW(shortname) +1) * sizeof(WCHAR), + (PBYTE) &cfg, len, &len, &status); + + if (res && (status == ERROR_SUCCESS)) { + /* display the Dialog */ + res = CommConfigDialogW(pPortName, hWnd, &cfg); + if (res) { + status = ERROR_SUCCESS; + /* set new settings */ + res = XcvDataW(hXcv, cmd_SetDefaultCommConfigW, + (PBYTE) &cfg, len, + (PBYTE) &dummy, 0, &len, &status); + } + } + HeapFree(GetProcessHeap(), 0, shortname); + return res; + } + return FALSE; +} + + +/***************************************************** + * dlg_configure_lpt [internal] + * + */ + +static BOOL dlg_configure_lpt(HANDLE hXcv, HWND hWnd) +{ + lptconfig_t data; + BOOL res; + + + data.hXcv = hXcv; + + res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(LPTCONFIG_DIALOG), hWnd, + dlgproc_lptconfig, (LPARAM) &data); + + TRACE("got %u with %u\n", res, GetLastError()); + + if (!res) SetLastError(ERROR_CANCELLED); + return res; +} + +/****************************************************************** + * dlg_port_already_exists [internal] + */ + +static void dlg_port_already_exists(HWND hWnd, LPCWSTR portname) +{ + WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; + WCHAR res_PortExistsW[IDS_PORTEXISTS_MAXLEN]; + LPWSTR message; + DWORD len; + + res_PortW[0] = '\0'; + res_PortExistsW[0] = '\0'; + LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); + LoadStringW(LOCALUI_hInstance, IDS_PORTEXISTS, res_PortExistsW, IDS_PORTEXISTS_MAXLEN); + + len = lstrlenW(portname) + IDS_PORTEXISTS_MAXLEN + 1; + message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (message) { + message[0] = '\0'; + snprintfW(message, len, res_PortExistsW, portname); + MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); + HeapFree(GetProcessHeap(), 0, message); + } +} + +/****************************************************************** + * dlg_invalid_portname [internal] + */ + +static void dlg_invalid_portname(HWND hWnd, LPCWSTR portname) +{ + WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; + WCHAR res_InvalidNameW[IDS_INVALIDNAME_MAXLEN]; + LPWSTR message; + DWORD len; + + res_PortW[0] = '\0'; + res_InvalidNameW[0] = '\0'; + LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); + LoadStringW(LOCALUI_hInstance, IDS_INVALIDNAME, res_InvalidNameW, IDS_INVALIDNAME_MAXLEN); + + len = lstrlenW(portname) + IDS_INVALIDNAME_MAXLEN; + message = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (message) { + message[0] = '\0'; + snprintfW(message, len, res_InvalidNameW, portname); + MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); + HeapFree(GetProcessHeap(), 0, message); + } +} + +/****************************************************************** + * display the Dialog "Nothing to configure" + * + */ + +static void dlg_nothingtoconfig(HWND hWnd) +{ + WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; + WCHAR res_nothingW[IDS_NOTHINGTOCONFIG_MAXLEN]; + + res_PortW[0] = '\0'; + res_nothingW[0] = '\0'; + LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); + LoadStringW(LOCALUI_hInstance, IDS_NOTHINGTOCONFIG, res_nothingW, IDS_NOTHINGTOCONFIG_MAXLEN); + + MessageBoxW(hWnd, res_nothingW, res_PortW, MB_OK | MB_ICONINFORMATION); +} + +/****************************************************************** + * dlg_win32error [internal] + */ + +static void dlg_win32error(HWND hWnd, DWORD lasterror) +{ + WCHAR res_PortW[IDS_LOCALPORT_MAXLEN]; + LPWSTR message = NULL; + DWORD res; + + res_PortW[0] = '\0'; + LoadStringW(LOCALUI_hInstance, IDS_LOCALPORT, res_PortW, IDS_LOCALPORT_MAXLEN); + + + res = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, lasterror, 0, (LPWSTR) &message, 0, NULL); + + if (res > 0) { + MessageBoxW(hWnd, message, res_PortW, MB_OK | MB_ICONERROR); + LocalFree(message); + } +} + +/***************************************************************************** + * + */ + +static INT_PTR CALLBACK dlgproc_addport(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + addportui_t * data; + DWORD status; + DWORD dummy; + DWORD len; + DWORD res; + + switch(msg) + { + case WM_INITDIALOG: + SetWindowLongPtrW(hwnd, DWLP_USER, lparam); + return TRUE; + + case WM_COMMAND: + if (wparam == MAKEWPARAM(IDOK, BN_CLICKED)) + { + data = (addportui_t *) GetWindowLongPtrW(hwnd, DWLP_USER); + /* length in WCHAR, without the '\0' */ + len = SendDlgItemMessageW(hwnd, ADDPORT_EDIT, WM_GETTEXTLENGTH, 0, 0); + data->portname = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); + + if (!data->portname) { + EndDialog(hwnd, FALSE); + return TRUE; + } + /* length is in WCHAR, including the '\0' */ + GetDlgItemTextW(hwnd, ADDPORT_EDIT, data->portname, len + 1); + status = ERROR_SUCCESS; + res = XcvDataW( data->hXcv, cmd_PortIsValidW, (PBYTE) data->portname, + (lstrlenW(data->portname) + 1) * sizeof(WCHAR), + (PBYTE) &dummy, 0, &len, &status); + + TRACE("got %u with status %u\n", res, status); + if (res && (status == ERROR_SUCCESS)) { + /* The caller must free data->portname */ + EndDialog(hwnd, TRUE); + return TRUE; + } + + if (res && (status == ERROR_INVALID_NAME)) { + dlg_invalid_portname(hwnd, data->portname); + HeapFree(GetProcessHeap(), 0, data->portname); + data->portname = NULL; + return TRUE; + } + + dlg_win32error(hwnd, status); + HeapFree(GetProcessHeap(), 0, data->portname); + data->portname = NULL; + return TRUE; + } + + if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) + { + EndDialog(hwnd, FALSE); + return TRUE; + } + return FALSE; + } + return FALSE; +} + +/***************************************************************************** + * dlgproc_lptconfig [internal] + * + * Our message-proc is simple, as the range-check is done only during the + * command "OK" and the dialog is set to the start-value at "out of range". + * + * Native localui.dll does the check during keyboard-input and set the dialog + * to the previous value. + * + */ + +static INT_PTR CALLBACK dlgproc_lptconfig(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + lptconfig_t * data; + WCHAR bufferW[16]; + DWORD status; + DWORD dummy; + DWORD len; + DWORD res; + + + switch(msg) + { + case WM_INITDIALOG: + SetWindowLongPtrW(hwnd, DWLP_USER, lparam); + data = (lptconfig_t *) lparam; + + /* Get current setting */ + data->value = 45; + status = ERROR_SUCCESS; + res = XcvDataW( data->hXcv, cmd_GetTransmissionRetryTimeoutW, + (PBYTE) &dummy, 0, + (PBYTE) &data->value, sizeof(data->value), &len, &status); + + TRACE("got %u with status %u\n", res, status); + + /* Set current setting as the initial value in the Dialog */ + SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); + return TRUE; + + case WM_COMMAND: + if (wparam == MAKEWPARAM(IDOK, BN_CLICKED)) + { + data = (lptconfig_t *) GetWindowLongPtrW(hwnd, DWLP_USER); + + status = FALSE; + res = GetDlgItemInt(hwnd, LPTCONFIG_EDIT, (BOOL *) &status, FALSE); + /* length is in WCHAR, including the '\0' */ + GetDlgItemTextW(hwnd, LPTCONFIG_EDIT, bufferW, sizeof(bufferW) / sizeof(bufferW[0])); + TRACE("got %s and %u (translated: %u)\n", debugstr_w(bufferW), res, status); + + /* native localui.dll use the same limits */ + if ((res > 0) && (res < 1000000) && status) { + sprintfW(bufferW, fmt_uW, res); + res = XcvDataW( data->hXcv, cmd_ConfigureLPTPortCommandOKW, + (PBYTE) bufferW, + (lstrlenW(bufferW) +1) * sizeof(WCHAR), + (PBYTE) &dummy, 0, &len, &status); + + TRACE("got %u with status %u\n", res, status); + EndDialog(hwnd, TRUE); + return TRUE; + } + + /* Set initial value and rerun the Dialog */ + SetDlgItemInt(hwnd, LPTCONFIG_EDIT, data->value, FALSE); + return TRUE; + } + + if (wparam == MAKEWPARAM(IDCANCEL, BN_CLICKED)) + { + EndDialog(hwnd, FALSE); + return TRUE; + } + return FALSE; + } + return FALSE; +} + + +/***************************************************** + * get_type_from_name (internal) + * + */ + +static DWORD get_type_from_name(LPCWSTR name) +{ + HANDLE hfile; + + if (!strncmpiW(name, portname_LPT, sizeof(portname_LPT) / sizeof(WCHAR) -1)) + return PORT_IS_LPT; + + if (!strncmpiW(name, portname_COM, sizeof(portname_COM) / sizeof(WCHAR) -1)) + return PORT_IS_COM; + + if (!strcmpiW(name, portname_FILE)) + return PORT_IS_FILE; + + if (name[0] == '/') + return PORT_IS_UNIXNAME; + + if (name[0] == '|') + return PORT_IS_PIPE; + + if (!strncmpW(name, portname_CUPS, sizeof(portname_CUPS) / sizeof(WCHAR) -1)) + return PORT_IS_CUPS; + + if (!strncmpW(name, portname_LPR, sizeof(portname_LPR) / sizeof(WCHAR) -1)) + return PORT_IS_LPR; + + /* Must be a file or a directory. Does the file exist ? */ + hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + TRACE("%p for OPEN_EXISTING on %s\n", hfile, debugstr_w(name)); + if (hfile == INVALID_HANDLE_VALUE) { + /* Can we create the file? */ + hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); + TRACE("%p for OPEN_ALWAYS\n", hfile); + } + if (hfile != INVALID_HANDLE_VALUE) { + CloseHandle(hfile); + return PORT_IS_FILENAME; + } + /* We can't use the name. use GetLastError() for the reason */ + return PORT_IS_UNKNOWN; +} + +/***************************************************** + * open_monitor_by_name [internal] + * + */ +static BOOL open_monitor_by_name(LPCWSTR pPrefix, LPCWSTR pPort, HANDLE * phandle) +{ + PRINTER_DEFAULTSW pd; + LPWSTR fullname; + BOOL res; + + * phandle = 0; + TRACE("(%s,%s)\n", debugstr_w(pPrefix),debugstr_w(pPort) ); + + fullname = strdupWW(pPrefix, pPort); + pd.pDatatype = NULL; + pd.pDevMode = NULL; + pd.DesiredAccess = SERVER_ACCESS_ADMINISTER; + + res = OpenPrinterW(fullname, phandle, &pd); + HeapFree(GetProcessHeap(), 0, fullname); + return res; +} + +/***************************************************** + * localui_AddPortUI [exported through MONITORUI] + * + * Display a Dialog to add a local Port + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * hWnd [I] Handle to parent Window for the Dialog-Box or NULL + * pMonitorName[I] Name of the Monitor, that should be used to add a Port or NULL + * ppPortName [O] PTR to PTR of a buffer, that receive the Name of the new Port or NULL + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * The caller must free the buffer (returned in ppPortName) with GlobalFree(). + * Native localui.dll failed with ERROR_INVALID_PARAMETER, when the user tried + * to add a Port, that start with "COM" or "LPT". + * + */ +static BOOL WINAPI localui_AddPortUI(PCWSTR pName, HWND hWnd, PCWSTR pMonitorName, PWSTR *ppPortName) +{ + addportui_t data; + HANDLE hXcv; + DWORD needed; + DWORD dummy; + DWORD status; + DWORD res = FALSE; + + TRACE( "(%s, %p, %s, %p) (*ppPortName: %p)\n", debugstr_w(pName), hWnd, + debugstr_w(pMonitorName), ppPortName, ppPortName ? *ppPortName : NULL); + + if (open_monitor_by_name(XcvMonitorW, pMonitorName, &hXcv)) { + + ZeroMemory(&data, sizeof(addportui_t)); + data.hXcv = hXcv; + res = DialogBoxParamW(LOCALUI_hInstance, MAKEINTRESOURCEW(ADDPORT_DIALOG), hWnd, + dlgproc_addport, (LPARAM) &data); + + TRACE("got %u with %u for %s\n", res, GetLastError(), debugstr_w(data.portname)); + + if (ppPortName) *ppPortName = NULL; + + if (res) { + res = XcvDataW(hXcv, cmd_AddPortW, (PBYTE) data.portname, + (lstrlenW(data.portname)+1) * sizeof(WCHAR), + (PBYTE) &dummy, 0, &needed, &status); + + TRACE("got %u with status %u\n", res, status); + if (res && (status == ERROR_SUCCESS) && ppPortName) { + /* Native localui uses GlobalAlloc also. + The caller must GlobalFree the buffer */ + *ppPortName = GlobalAlloc(GPTR, (lstrlenW(data.portname)+1) * sizeof(WCHAR)); + if (*ppPortName) lstrcpyW(*ppPortName, data.portname); + } + + if (res && (status == ERROR_ALREADY_EXISTS)) { + dlg_port_already_exists(hWnd, data.portname); + /* Native localui also return "TRUE" from AddPortUI in this case */ + } + + HeapFree(GetProcessHeap(), 0, data.portname); + } + else + { + SetLastError(ERROR_CANCELLED); + } + ClosePrinter(hXcv); + } + + TRACE("=> %u with %u\n", res, GetLastError()); + return res; +} + + +/***************************************************** + * localui_ConfigurePortUI [exported through MONITORUI] + * + * Display the Configuration-Dialog for a specific Port + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * hWnd [I] Handle to parent Window for the Dialog-Box or NULL + * pPortName [I] Name of the Port, that should be configured + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + */ +static BOOL WINAPI localui_ConfigurePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName) +{ + HANDLE hXcv; + DWORD res; + + TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); + if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) { + + res = get_type_from_name(pPortName); + switch(res) + { + + case PORT_IS_COM: + res = dlg_configure_com(hXcv, hWnd, pPortName); + break; + + case PORT_IS_LPT: + res = dlg_configure_lpt(hXcv, hWnd); + break; + + default: + dlg_nothingtoconfig(hWnd); + SetLastError(ERROR_CANCELLED); + res = FALSE; + } + + ClosePrinter(hXcv); + return res; + } + return FALSE; + +} + +/***************************************************** + * localui_DeletePortUI [exported through MONITORUI] + * + * Delete a specific Port + * + * PARAMS + * pName [I] Servername or NULL (local Computer) + * hWnd [I] Handle to parent Window + * pPortName [I] Name of the Port, that should be deleted + * + * RETURNS + * Success: TRUE + * Failure: FALSE + * + * NOTES + * Native localui does not allow to delete a COM / LPT - Port (ERROR_NOT_SUPPORTED) + * + */ +static BOOL WINAPI localui_DeletePortUI(PCWSTR pName, HWND hWnd, PCWSTR pPortName) +{ + HANDLE hXcv; + DWORD dummy; + DWORD needed; + DWORD status; + + TRACE("(%s, %p, %s)\n", debugstr_w(pName), hWnd, debugstr_w(pPortName)); + + if ((!pPortName) || (!pPortName[0])) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (open_monitor_by_name(XcvPortW, pPortName, &hXcv)) { + /* native localui tests here for LPT / COM - Ports and failed with + ERROR_NOT_SUPPORTED. */ + if (XcvDataW(hXcv, cmd_DeletePortW, (LPBYTE) pPortName, + (lstrlenW(pPortName)+1) * sizeof(WCHAR), (LPBYTE) &dummy, 0, &needed, &status)) { + + ClosePrinter(hXcv); + if (status != ERROR_SUCCESS) SetLastError(status); + return (status == ERROR_SUCCESS); + } + ClosePrinter(hXcv); + return FALSE; + } + SetLastError(ERROR_UNKNOWN_PORT); + return FALSE; +} + +/***************************************************** + * InitializePrintMonitorUI (LOCALUI.@) + * + * Initialize the User-Interface for the Local Ports + * + * RETURNS + * Success: Pointer to a MONITORUI Structure + * Failure: NULL + * + */ + +PMONITORUI WINAPI InitializePrintMonitorUI(void) +{ + static MONITORUI mymonitorui = + { + sizeof(MONITORUI), + localui_AddPortUI, + localui_ConfigurePortUI, + localui_DeletePortUI + }; + + TRACE("=> %p\n", &mymonitorui); + return &mymonitorui; +} + +/***************************************************** + * DllMain + */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + TRACE("(%p, %d, %p)\n",hinstDLL, fdwReason, lpvReserved); + + switch(fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hinstDLL ); + LOCALUI_hInstance = hinstDLL; + break; + } + return TRUE; +} Index: win32ss/printing/monitors/localmon/ui/localui.h =================================================================== --- win32ss/printing/monitors/localmon/ui/localui.h (nonexistent) +++ win32ss/printing/monitors/localmon/ui/localui.h (working copy) @@ -0,0 +1,62 @@ +/* + * internal include file of the Local Printmonitor User Interface + * + * Copyright 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 + */ + +#ifndef __WINE_LOCALUI__ +#define __WINE_LOCALUI__ + +//#include +//#include + +/* ## Resource-ID ## */ +#define ADDPORT_DIALOG 100 +#define ADDPORT_EDIT 101 + +#define LPTCONFIG_DIALOG 200 +#define LPTCONFIG_GROUP 201 +#define LPTCONFIG_EDIT 202 + +#define IDS_LOCALPORT 300 +#define IDS_INVALIDNAME 301 +#define IDS_PORTEXISTS 302 +#define IDS_NOTHINGTOCONFIG 303 + +/* ## Reserved memorysize for the strings (in WCHAR) ## */ +#define IDS_LOCALPORT_MAXLEN 32 +#define IDS_INVALIDNAME_MAXLEN 48 +#define IDS_PORTEXISTS_MAXLEN 48 +#define IDS_NOTHINGTOCONFIG_MAXLEN 80 + +/* ## Type of Ports ## */ +/* windows types */ +#define PORT_IS_UNKNOWN 0 +#define PORT_IS_LPT 1 +#define PORT_IS_COM 2 +#define PORT_IS_FILE 3 +#define PORT_IS_FILENAME 4 + +/* wine extensions */ +#define PORT_IS_WINE 5 +#define PORT_IS_UNIXNAME 5 +#define PORT_IS_PIPE 6 +#define PORT_IS_CUPS 7 +#define PORT_IS_LPR 8 + + +#endif /* __WINE_LOCALUI__ */ Index: win32ss/printing/monitors/localmon/ui/localui.rc =================================================================== --- win32ss/printing/monitors/localmon/ui/localui.rc (nonexistent) +++ win32ss/printing/monitors/localmon/ui/localui.rc (working copy) @@ -0,0 +1,112 @@ +/* + * Top level resource file for localui + * + * Copyright 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 +#include + +#include "localui.h" + +#define WINE_FILENAME_STR "localui.dll" +#define WINE_FILEDESCRIPTION_STR "User Interface for the Local Monitor" + +/* Same Version as WinXP_sp2 */ +#define WINE_FILEVERSION 5,1,2600,2180 +#define WINE_FILEVERSION_STR "5.1.2600.2180" + +#define WINE_PRODUCTVERSION 5,1,2600,2180 +#define WINE_PRODUCTVERSION_STR "5.1.2600.2180" + +#include "wine/wine_common_ver.rc" + +#include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_DA_DK + #include "lang/ui_Da.rc" +#endif +#ifdef LANGUAGE_DE_DE + #include "lang/ui_De.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/ui_En.rc" +#endif +#ifdef LANGUAGE_ES_ES + #include "lang/ui_Es.rc" +#endif +#ifdef LANGUAGE_FR_FR + #include "lang/ui_Fr.rc" +#endif +#ifdef LANGUAGE_HE_IL + #include "lang/ui_He.rc" +#endif +#ifdef LANGUAGE_HU_HU + #include "lang/ui_Hu.rc" +#endif +#ifdef LANGUAGE_IT_IT + #include "lang/ui_It.rc" +#endif +#ifdef LANGUAGE_JA_JP + #include "lang/ui_Ja.rc" +#endif +#ifdef LANGUAGE_KO_KR + #include "lang/ui_Ko.rc" +#endif +#ifdef LANGUAGE_LT_LT + #include "lang/ui_Lt.rc" +#endif +#ifdef LANGUAGE_NL_NL + #include "lang/ui_Nl.rc" +#endif +#ifdef LANGUAGE_NO_NO + #include "lang/ui_No.rc" +#endif +#ifdef LANGUAGE_PL_PL + #include "lang/ui_Pl.rc" +#endif +#ifdef LANGUAGE_PT_PT + #include "lang/ui_Pt.rc" +#endif +#ifdef LANGUAGE_RO_RO + #include "lang/ui_Ro.rc" +#endif +#ifdef LANGUAGE_RU_RU + #include "lang/ui_Ru.rc" +#endif +#ifdef LANGUAGE_SL_SI + #include "lang/ui_Si.rc" +#endif +#ifdef LANGUAGE_SQ_AL + #include "lang/ui_Sq.rc" +#endif +#ifdef LANGUAGE_SV_SE + #include "lang/ui_Sv.rc" +#endif +#ifdef LANGUAGE_TR_TR + #include "lang/ui_Tr.rc" +#endif +#ifdef LANGUAGE_UK_UA + #include "lang/ui_Uk.rc" +#endif +#ifdef LANGUAGE_ZH_CN + #include "lang/ui_Zh.rc" +#endif Index: win32ss/printing/monitors/localmon/ui/localui.spec =================================================================== --- win32ss/printing/monitors/localmon/ui/localui.spec (nonexistent) +++ win32ss/printing/monitors/localmon/ui/localui.spec (working copy) @@ -0,0 +1 @@ +@ stdcall InitializePrintMonitorUI() Index: win32ss/printing/monitors/localmon/xcv.c =================================================================== --- win32ss/printing/monitors/localmon/xcv.c (nonexistent) +++ win32ss/printing/monitors/localmon/xcv.c (working copy) @@ -0,0 +1,451 @@ +/* + * PROJECT: ReactOS Local Port Monitor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Implementation of Xcv* and support functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +static DWORD +_HandleAddPort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded) +{ + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/** + * @name _HandleConfigureLPTPortCommandOK + * + * Writes the value for "TransmissionRetryTimeout" to the registry. Checks for granted SERVER_ACCESS_ADMINISTER access. + * Actually the opposite of _HandleGetTransmissionRetryTimeout, but name kept for compatibility. + * + * @param pXcv + * Pointer to the LOCALMON_XCV structure of the currently opened Xcv port. + * + * @param pInputData + * Pointer to a Unicode string containing the value to be written to the registry. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that will be zeroed on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandleConfigureLPTPortCommandOK(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded) +{ + DWORD cbBuffer; + DWORD dwErrorCode; + HKEY hKey = NULL; + HKEY hToken = NULL; + + // Sanity checks + if (!pXcv || !pInputData || !pcbOutputNeeded) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + *pcbOutputNeeded = 0; + + // This action can only happen at SERVER_ACCESS_ADMINISTER access level. + if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER)) + { + dwErrorCode = ERROR_ACCESS_DENIED; + goto Cleanup; + } + + // Switch to the SYSTEM context for modifying the registry. + hToken = RevertToPrinterSelf(); + if (!hToken) + { + dwErrorCode = GetLastError(); + ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Open the key where our value is stored. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows", 0, KEY_SET_VALUE, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We don't use cbInputData here, because the buffer pInputData could be bigger than the data it contains. + cbBuffer = (wcslen((PWSTR)pInputData) + 1) * sizeof(WCHAR); + + // Write the value to the registry. + dwErrorCode = (DWORD)RegSetValueExW(hKey, L"TransmissionRetryTimeout", 0, REG_SZ, pInputData, cbBuffer); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + +Cleanup: + if (hKey) + RegCloseKey(hKey); + + if (hToken) + ImpersonatePrinterClient(hToken); + + return dwErrorCode; +} + +static DWORD +_HandleDeletePort(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded) +{ + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/** + * @name _HandleGetDefaultCommConfig + * + * Gets the default configuration of a legacy port. + * The opposite function is _HandleSetDefaultCommConfig. + * + * @param pInputData + * The port name (without colon!) whose default configuration you want to get. + * + * @param pOutputData + * Pointer to a COMMCONFIG structure that will receive the configuration information. + * + * @param cbOutputData + * Size of the variable pointed to by pOutputData. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that contains the required size for pOutputData on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandleGetDefaultCommConfig(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + // Sanity checks + if (!pInputData || !pcbOutputNeeded) + return ERROR_INVALID_PARAMETER; + + *pcbOutputNeeded = sizeof(COMMCONFIG); + + // Check if the supplied buffer is large enough. + if (cbOutputData < *pcbOutputNeeded) + return ERROR_INSUFFICIENT_BUFFER; + + // Finally get the port configuration. + if (!GetDefaultCommConfigW((PCWSTR)pInputData, (LPCOMMCONFIG)pOutputData, pcbOutputNeeded)) + return GetLastError(); + + return ERROR_SUCCESS; +} + +/** + * @name _HandleGetTransmissionRetryTimeout + * + * Reads the value for "TransmissionRetryTimeout" from the registry and converts it to a DWORD. + * The opposite function is _HandleConfigureLPTPortCommandOK. + * + * @param pOutputData + * Pointer to a DWORD that will receive the timeout value. + * + * @param cbOutputData + * Size of the variable pointed to by pOutputData. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that contains the required size for pOutputData on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandleGetTransmissionRetryTimeout(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + DWORD dwTimeout; + + // Sanity checks + if (!pOutputData || !pcbOutputNeeded) + return ERROR_INVALID_PARAMETER; + + *pcbOutputNeeded = sizeof(DWORD); + + // Check if the supplied buffer is large enough. + if (cbOutputData < *pcbOutputNeeded) + return ERROR_INSUFFICIENT_BUFFER; + + // Retrieve and copy the number. + dwTimeout = GetLPTTransmissionRetryTimeout(); + CopyMemory(pOutputData, &dwTimeout, sizeof(DWORD)); + return ERROR_SUCCESS; +} + +/** + * @name _HandleMonitorUI + * + * Returns the filename of the associated UI DLL for this Port Monitor. + * + * @param pOutputData + * Pointer to a Unicode string that will receive the DLL filename. + * + * @param cbOutputData + * Size of the variable pointed to by pOutputData. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that contains the required size for pOutputData on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandleMonitorUI(PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + const WCHAR wszMonitorUI[] = L"LocalUI.dll"; + + // Sanity checks + if (!pOutputData || !pcbOutputNeeded) + return ERROR_INVALID_PARAMETER; + + *pcbOutputNeeded = sizeof(wszMonitorUI); + + // Check if the supplied buffer is large enough. + if (cbOutputData < *pcbOutputNeeded) + return ERROR_INSUFFICIENT_BUFFER; + + // Copy the string. + CopyMemory(pOutputData, wszMonitorUI, sizeof(wszMonitorUI)); + return ERROR_SUCCESS; +} + +/** + * @name _HandlePortExists + * + * Checks all Port Monitors installed on the local system to find out if a given port already exists. + * + * @param pInputData + * Pointer to a Unicode string specifying the port name to check. + * + * @param pOutputData + * Pointer to a BOOL that receives the result of the check. + * + * @param cbOutputData + * Size of the variable pointed to by pOutputData. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that contains the required size for pOutputData on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandlePortExists(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + // Sanity checks + if (!pInputData || !pOutputData || !pcbOutputNeeded) + return ERROR_INVALID_PARAMETER; + + *pcbOutputNeeded = sizeof(BOOL); + + // Check if the supplied buffer is large enough. + if (cbOutputData < *pcbOutputNeeded) + return ERROR_INSUFFICIENT_BUFFER; + + // Return the check result and error code. + *(PBOOL)pOutputData = DoesPortExist((PCWSTR)pInputData); + return GetLastError(); +} + +static DWORD +_HandlePortIsValid(PBYTE pInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + return ERROR_CALL_NOT_IMPLEMENTED; +} + +/** + * @name _HandleSetDefaultCommConfig + * + * Sets the default configuration of a legacy port. Checks for granted SERVER_ACCESS_ADMINISTER access. + * You have to supply the port name (with colon!) in XcvOpenPort. + * The opposite function is _HandleGetDefaultCommConfig. + * + * @param pXcv + * Pointer to the LOCALMON_XCV structure of the currently opened Xcv port. + * + * @param pInputData + * Pointer to the COMMCONFIG structure that shall be passed to SetDefaultCommConfigW. + * + * @param pcbOutputNeeded + * Pointer to a DWORD that will be zeroed on return. + * + * @return + * An error code indicating success or failure. + */ +static DWORD +_HandleSetDefaultCommConfig(PLOCALMON_XCV pXcv, PBYTE pInputData, PDWORD pcbOutputNeeded) +{ + DWORD dwErrorCode; + HANDLE hToken = NULL; + LPCOMMCONFIG pCommConfig; + PWSTR pwszPortNameWithoutColon = NULL; + + // Sanity checks + // pwszObject needs to be at least 2 characters long to be a port name with a trailing colon. + if (!pXcv || !pXcv->pwszObject || !pXcv->pwszObject[0] || !pXcv->pwszObject[1] || !pInputData || !pcbOutputNeeded) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + *pcbOutputNeeded = 0; + + // This action can only happen at SERVER_ACCESS_ADMINISTER access level. + if (!(pXcv->GrantedAccess & SERVER_ACCESS_ADMINISTER)) + { + dwErrorCode = ERROR_ACCESS_DENIED; + goto Cleanup; + } + + // SetDefaultCommConfigW needs the port name without colon. + dwErrorCode = GetPortNameWithoutColon(pXcv->pwszObject, &pwszPortNameWithoutColon); + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // Switch to the SYSTEM context for setting the port configuration. + hToken = RevertToPrinterSelf(); + if (!hToken) + { + dwErrorCode = GetLastError(); + ERR("RevertToPrinterSelf failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Finally pass the parameters to SetDefaultCommConfigW. + pCommConfig = (LPCOMMCONFIG)pInputData; + if (!SetDefaultCommConfigW(pwszPortNameWithoutColon, pCommConfig, pCommConfig->dwSize)) + { + dwErrorCode = GetLastError(); + ERR("SetDefaultCommConfigW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (hToken) + ImpersonatePrinterClient(hToken); + + if (pwszPortNameWithoutColon) + DllFreeSplMem(pwszPortNameWithoutColon); + + return dwErrorCode; +} + +BOOL WINAPI +LocalmonXcvClosePort(HANDLE hXcv) +{ + PLOCALMON_XCV pXcv = (PLOCALMON_XCV)hXcv; + + TRACE("LocalmonXcvClosePort(%p)\n", hXcv); + + // Sanity checks + if (!pXcv) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Remove it from the list and free the memory. + RemoveEntryList(&pXcv->Entry); + DllFreeSplMem(pXcv); + + SetLastError(ERROR_SUCCESS); + return TRUE; +} + +DWORD WINAPI +LocalmonXcvDataPort(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded) +{ + TRACE("LocalmonXcvDataPort(%p, %S, %p, %lu, %p, %lu, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded); + + // Sanity checks + if (!pszDataName) + return ERROR_INVALID_PARAMETER; + + // Call the appropriate handler for the requested data name. + if (wcscmp(pszDataName, L"AddPort") == 0) + return _HandleAddPort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"ConfigureLPTPortCommandOK") == 0) + return _HandleConfigureLPTPortCommandOK((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"DeletePort") == 0) + return _HandleDeletePort((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"GetDefaultCommConfig") == 0) + return _HandleGetDefaultCommConfig(pInputData, pOutputData, cbOutputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"GetTransmissionRetryTimeout") == 0) + return _HandleGetTransmissionRetryTimeout(pOutputData, cbOutputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"MonitorUI") == 0) + return _HandleMonitorUI(pOutputData, cbOutputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"PortExists") == 0) + return _HandlePortExists(pInputData, pOutputData, cbOutputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"PortIsValid") == 0) + return _HandlePortIsValid(pInputData, pOutputData, cbOutputData, pcbOutputNeeded); + + if (wcscmp(pszDataName, L"SetDefaultCommConfig") == 0) + return _HandleSetDefaultCommConfig((PLOCALMON_XCV)hXcv, pInputData, pcbOutputNeeded); + + return ERROR_INVALID_PARAMETER; +} + +BOOL WINAPI +LocalmonXcvOpenPort(HANDLE hMonitor, PCWSTR pwszObject, ACCESS_MASK GrantedAccess, PHANDLE phXcv) +{ + DWORD cbObject = 0; + DWORD dwErrorCode; + PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor; + PLOCALMON_XCV pXcv; + + TRACE("LocalmonXcvOpenPort(%p, %S, %lu, %p)\n", hMonitor, pwszObject, GrantedAccess, phXcv); + + // Sanity checks + if (!pLocalmon || !phXcv) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + if (pwszObject) + cbObject = (wcslen(pwszObject) + 1) * sizeof(WCHAR); + + // Create a new LOCALMON_XCV structure and fill the relevant fields. + pXcv = DllAllocSplMem(sizeof(LOCALMON_XCV) + cbObject); + if (!pXcv) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pXcv->pLocalmon = pLocalmon; + pXcv->GrantedAccess = GrantedAccess; + + if (cbObject) + { + pXcv->pwszObject = (PWSTR)((PBYTE)pXcv + sizeof(LOCALMON_XCV)); + CopyMemory(pXcv->pwszObject, pwszObject, cbObject); + } + + InsertTailList(&pLocalmon->XcvHandles, &pXcv->Entry); + + // Return it as the Xcv handle. + *phXcv = (HANDLE)pXcv; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/monitors/tcpmon/CMakeLists.txt =================================================================== --- win32ss/printing/monitors/tcpmon/CMakeLists.txt (nonexistent) +++ win32ss/printing/monitors/tcpmon/CMakeLists.txt (working copy) @@ -0,0 +1 @@ +#add_subdirectory(ui) Index: win32ss/printing/processors/CMakeLists.txt =================================================================== --- win32ss/printing/processors/CMakeLists.txt (nonexistent) +++ win32ss/printing/processors/CMakeLists.txt (working copy) @@ -0,0 +1 @@ +add_subdirectory(winprint) Index: win32ss/printing/processors/winprint/CMakeLists.txt =================================================================== --- win32ss/printing/processors/winprint/CMakeLists.txt (nonexistent) +++ win32ss/printing/processors/winprint/CMakeLists.txt (working copy) @@ -0,0 +1,18 @@ + +spec2def(winprint.dll winprint.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + main.c + raw.c + precomp.h) + +add_library(winprint SHARED + ${SOURCE} + winprint.rc + ${CMAKE_CURRENT_BINARY_DIR}/winprint.def) + +set_module_type(winprint win32dll UNICODE) +target_link_libraries(winprint wine) +add_importlibs(winprint spoolss msvcrt kernel32 ntdll) +add_pch(winprint precomp.h SOURCE) +add_cd_file(TARGET winprint DESTINATION reactos/system32/spool/prtprocs/w32x86 FOR all) Index: win32ss/printing/processors/winprint/main.c =================================================================== --- win32ss/printing/processors/winprint/main.c (nonexistent) +++ win32ss/printing/processors/winprint/main.c (working copy) @@ -0,0 +1,286 @@ +/* + * PROJECT: ReactOS Standard Print Processor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Local Constants +static PCWSTR _pwszDatatypes[] = { + L"RAW", + 0 +}; + + +/** + * @name ClosePrintProcessor + * + * Closes a Print Processor Handle that has previously been opened through OpenPrintProcessor. + * + * @param hPrintProcessor + * The return value of a previous successful OpenPrintProcessor call. + * + * @return + * TRUE if the Print Processor Handle was successfully closed, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +ClosePrintProcessor(HANDLE hPrintProcessor) +{ + DWORD dwErrorCode; + PWINPRINT_HANDLE pHandle; + + TRACE("ClosePrintProcessor(%p)\n", hPrintProcessor); + + // Sanity checks + if (!hPrintProcessor) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pHandle = (PWINPRINT_HANDLE)hPrintProcessor; + + // Free all structure fields for which memory has been allocated. + if (pHandle->pwszDatatype) + DllFreeSplStr(pHandle->pwszDatatype); + + if (pHandle->pwszDocumentName) + DllFreeSplStr(pHandle->pwszDocumentName); + + if (pHandle->pwszOutputFile) + DllFreeSplStr(pHandle->pwszOutputFile); + + if (pHandle->pwszPrinterPort) + DllFreeSplStr(pHandle->pwszPrinterPort); + + // Finally free the WINSPOOL_HANDLE structure itself. + DllFreeSplMem(pHandle); + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +ControlPrintProcessor(HANDLE hPrintProcessor, DWORD Command) +{ + TRACE("ControlPrintProcessor(%p, %lu)\n", hPrintProcessor, Command); + + UNIMPLEMENTED; + return FALSE; +} + +/** + * @name EnumPrintProcessorDatatypesW + * + * Obtains an array of all datatypes supported by this Print Processor. + * + * @param pName + * Server Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information. + * + * @param pPrintProcessorName + * Print Processor Name. Ignored here, because every caller of EnumPrintProcessorDatatypesW is interested in this Print Processor's information. + * + * @param Level + * The level of the structure supplied through pDatatypes. This must be 1. + * + * @param pDatatypes + * Pointer to the buffer that receives an array of DATATYPES_INFO_1W structures. + * Can be NULL if you just want to know the required size of the buffer. + * + * @param cbBuf + * Size of the buffer you supplied for pDatatypes, in bytes. + * + * @param pcbNeeded + * Pointer to a variable that receives the required size of the buffer for pDatatypes, in bytes. + * This parameter mustn't be NULL! + * + * @param pcReturned + * Pointer to a variable that receives the number of elements of the DATATYPES_INFO_1W array. + * This parameter mustn't be NULL! + * + * @return + * TRUE if we successfully copied the array into pDatatypes, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD cbDatatype; + DWORD dwDatatypeCount = 0; + DWORD dwErrorCode; + DWORD dwOffsets[_countof(_pwszDatatypes)]; + PCWSTR* pCurrentDatatype; + PDWORD pCurrentOffset = dwOffsets; + + TRACE("EnumPrintProcessorDatatypesW(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned); + + // Sanity checks + if (Level != 1 || !pcbNeeded || !pcReturned) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Count the required buffer size and the number of datatypes. + *pcbNeeded = 0; + *pcReturned = 0; + + for (pCurrentDatatype = _pwszDatatypes; *pCurrentDatatype; pCurrentDatatype++) + { + cbDatatype = (wcslen(*pCurrentDatatype) + 1) * sizeof(WCHAR); + *pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype; + + // Also calculate the offset in the output buffer of the pointer to this datatype string. + *pCurrentOffset = dwDatatypeCount * sizeof(DATATYPES_INFO_1W) + FIELD_OFFSET(DATATYPES_INFO_1W, pName); + + dwDatatypeCount++; + pCurrentOffset++; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Check if a buffer was supplied at all. + if (!pDatatypes) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Copy over all datatypes. + *pCurrentOffset = MAXDWORD; + PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]); + + *pcReturned = dwDatatypeCount; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + + +DWORD WINAPI +GetPrintProcessorCapabilities(PWSTR pValueName, DWORD dwAttributes, PBYTE pData, DWORD nSize, PDWORD pcbNeeded) +{ + TRACE("GetPrintProcessorCapabilities(%S, %lu, %p, %lu, %p)\n", pValueName, dwAttributes, pData, nSize, pcbNeeded); + + UNIMPLEMENTED; + return 0; +} + +/** + * @name OpenPrintProcessor + * + * Prepares this Print Processor for processing a document. + * + * @param pPrinterName + * String in the format "\\COMPUTERNAME\Port:, Port" that is passed to OpenPrinterW for writing to the Print Monitor on the specified port. + * + * @param pPrintProcessorOpenData + * Pointer to a PRINTPROCESSOROPENDATA structure containing details about the print job to be processed. + * + * @return + * A Print Processor handle on success or NULL in case of a failure. This handle has to be passed to PrintDocumentOnPrintProcessor to do the actual processing. + * A more specific error code can be obtained through GetLastError. + */ +HANDLE WINAPI +OpenPrintProcessor(PWSTR pPrinterName, PPRINTPROCESSOROPENDATA pPrintProcessorOpenData) +{ + DWORD dwErrorCode; + HANDLE hReturnValue = NULL; + PWINPRINT_HANDLE pHandle = NULL; + + TRACE("OpenPrintProcessor(%S, %p)\n", pPrinterName, pPrintProcessorOpenData); + + // Sanity checks + // This time a datatype needs to be given. We can't fall back to a default here. + if (!pPrintProcessorOpenData || !pPrintProcessorOpenData->pDatatype || !*pPrintProcessorOpenData->pDatatype) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Create a new WINPRINT_HANDLE structure and fill the relevant fields. + pHandle = DllAllocSplMem(sizeof(WINPRINT_HANDLE)); + + // Check what datatype was given. + if (wcsicmp(pPrintProcessorOpenData->pDatatype, L"RAW") == 0) + { + pHandle->Datatype = RAW; + } + else + { + dwErrorCode = ERROR_INVALID_DATATYPE; + goto Cleanup; + } + + // Fill the relevant fields. + pHandle->dwJobID = pPrintProcessorOpenData->JobId; + pHandle->pwszDatatype = AllocSplStr(pPrintProcessorOpenData->pDatatype); + pHandle->pwszDocumentName = AllocSplStr(pPrintProcessorOpenData->pDocumentName); + pHandle->pwszOutputFile = AllocSplStr(pPrintProcessorOpenData->pOutputFile); + pHandle->pwszPrinterPort = AllocSplStr(pPrinterName); + + // We were successful! Return the handle and don't let the cleanup routine free it. + dwErrorCode = ERROR_SUCCESS; + hReturnValue = pHandle; + pHandle = NULL; + +Cleanup: + if (pHandle) + DllFreeSplMem(pHandle); + + SetLastError(dwErrorCode); + return hReturnValue; +} + +/** + * @name PrintDocumentOnPrintProcessor + * + * Prints a document on this Print Processor after a handle for the document has been opened through OpenPrintProcessor. + * + * @param hPrintProcessor + * The return value of a previous successful OpenPrintProcessor call. + * + * @param pDocumentName + * String in the format "Printer, Job N" describing the spooled job that is to be processed. + * + * @return + * TRUE if the document was successfully processed by this Print Processor, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +PrintDocumentOnPrintProcessor(HANDLE hPrintProcessor, PWSTR pDocumentName) +{ + DWORD dwErrorCode; + PWINPRINT_HANDLE pHandle; + + TRACE("PrintDocumentOnPrintProcessor(%p, %S)\n", hPrintProcessor, pDocumentName); + + // Sanity checks + if (!hPrintProcessor) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pHandle = (PWINPRINT_HANDLE)hPrintProcessor; + + // Call the corresponding Print function for the datatype. + if (pHandle->Datatype == RAW) + dwErrorCode = PrintRawJob(pHandle, pDocumentName); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/processors/winprint/precomp.h =================================================================== --- win32ss/printing/processors/winprint/precomp.h (nonexistent) +++ win32ss/printing/processors/winprint/precomp.h (working copy) @@ -0,0 +1,40 @@ +/* + * PROJECT: ReactOS Standard Print Processor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(winprint); + +// Structures +typedef struct _WINPRINT_HANDLE +{ + enum { RAW } Datatype; + DWORD dwJobID; + PWSTR pwszDatatype; + PWSTR pwszDocumentName; + PWSTR pwszOutputFile; + PWSTR pwszPrinterPort; +} +WINPRINT_HANDLE, *PWINPRINT_HANDLE; + +// raw.c +DWORD PrintRawJob(PWINPRINT_HANDLE pHandle, PWSTR pwszPrinterAndJob); + +#endif Index: win32ss/printing/processors/winprint/raw.c =================================================================== --- win32ss/printing/processors/winprint/raw.c (nonexistent) +++ win32ss/printing/processors/winprint/raw.c (working copy) @@ -0,0 +1,100 @@ +/* + * PROJECT: ReactOS Standard Print Processor + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Printing a job with RAW datatype + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +/** + * @name PrintRawJob + * + * @param pHandle + * Pointer to a WINPRINT_HANDLE structure containing information about this job. + * + * @param pwszPrinterAndJob + * String in the format "Printer, Job N" that is passed to OpenPrinterW to read from the spooled print job. + * + * @return + * An error code indicating success or failure. + */ +DWORD +PrintRawJob(PWINPRINT_HANDLE pHandle, PWSTR pwszPrinterAndJob) +{ + // Use a read buffer of 256 KB size like Windows does. + const DWORD cbReadBuffer = 262144; + + BOOL bStartedDoc = FALSE; + DOC_INFO_1W DocInfo1; + DWORD cbRead; + DWORD cbWritten; + DWORD dwErrorCode; + HANDLE hPrintJob; + HANDLE hPrintMonitor; + PBYTE pBuffer = NULL; + + // Open the spooled job to read from it. + if (!OpenPrinterW(pwszPrinterAndJob, &hPrintJob, NULL)) + { + dwErrorCode = GetLastError(); + ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pwszPrinterAndJob, GetLastError()); + goto Cleanup; + } + + // Open a Print Monitor handle to write to it. + if (!OpenPrinterW(pHandle->pwszPrinterPort, &hPrintMonitor, NULL)) + { + dwErrorCode = GetLastError(); + ERR("OpenPrinterW failed for \"%S\" with error %lu!\n", pHandle->pwszPrinterPort, GetLastError()); + goto Cleanup; + } + + // Fill the Document Information. + DocInfo1.pDatatype = pHandle->pwszDatatype; + DocInfo1.pDocName = pHandle->pwszDocumentName; + DocInfo1.pOutputFile = pHandle->pwszOutputFile; + + // Tell the Print Monitor that we're starting a new document. + if (!StartDocPrinterW(hPrintMonitor, 1, (PBYTE)&DocInfo1)) + { + dwErrorCode = GetLastError(); + ERR("StartDocPrinterW failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + bStartedDoc = TRUE; + + // Allocate a read buffer on the heap. This would easily exceed the stack size. + pBuffer = DllAllocSplMem(cbReadBuffer); + if (!pBuffer) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Loop as long as data is available. + while (ReadPrinter(hPrintJob, pBuffer, cbReadBuffer, &cbRead) && cbRead) + { + // Write it to the Print Monitor. + WritePrinter(hPrintMonitor, pBuffer, cbRead, &cbWritten); + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pBuffer) + DllFreeSplMem(pBuffer); + + if (bStartedDoc) + EndDocPrinter(hPrintMonitor); + + if (hPrintMonitor) + ClosePrinter(hPrintMonitor); + + if (hPrintJob) + ClosePrinter(hPrintJob); + + return dwErrorCode; +} Index: win32ss/printing/processors/winprint/winprint.rc =================================================================== --- win32ss/printing/processors/winprint/winprint.rc (nonexistent) +++ win32ss/printing/processors/winprint/winprint.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Standard Print Processor" +#define REACTOS_STR_INTERNAL_NAME "winprint" +#define REACTOS_STR_ORIGINAL_FILENAME "winprint.dll" +#include Index: win32ss/printing/processors/winprint/winprint.spec =================================================================== --- win32ss/printing/processors/winprint/winprint.spec (nonexistent) +++ win32ss/printing/processors/winprint/winprint.spec (working copy) @@ -0,0 +1,6 @@ +@ stdcall ClosePrintProcessor(long) +@ stdcall ControlPrintProcessor(long long) +@ stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr) +@ stdcall GetPrintProcessorCapabilities(wstr long ptr long ptr) +@ stdcall OpenPrintProcessor(wstr ptr) +@ stdcall PrintDocumentOnPrintProcessor(long wstr) Index: win32ss/printing/providers/CMakeLists.txt =================================================================== --- win32ss/printing/providers/CMakeLists.txt (nonexistent) +++ win32ss/printing/providers/CMakeLists.txt (working copy) @@ -0,0 +1,3 @@ +#add_subdirectory(inetpp) +add_subdirectory(localspl) +#add_subdirectory(win32spl) Index: win32ss/printing/providers/localspl/CMakeLists.txt =================================================================== --- win32ss/printing/providers/localspl/CMakeLists.txt (nonexistent) +++ win32ss/printing/providers/localspl/CMakeLists.txt (working copy) @@ -0,0 +1,27 @@ + +spec2def(localspl.dll localspl.spec ADD_IMPORTLIB) + +include_directories(${REACTOS_SOURCE_DIR}/sdk/lib/skiplist) + +list(APPEND SOURCE + jobs.c + main.c + monitors.c + ports.c + precomp.h + printers.c + printingthread.c + printprocessors.c + tools.c) + +add_library(localspl SHARED + ${SOURCE} + localspl.rc + ${CMAKE_CURRENT_BINARY_DIR}/localspl_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/localspl.def) + +set_module_type(localspl win32dll UNICODE) +target_link_libraries(localspl skiplist16 wine) +add_importlibs(localspl advapi32 rpcrt4 spoolss msvcrt kernel32 ntdll) +add_pch(localspl precomp.h SOURCE) +add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all) Index: win32ss/printing/providers/localspl/jobs.c =================================================================== --- win32ss/printing/providers/localspl/jobs.c (nonexistent) +++ win32ss/printing/providers/localspl/jobs.c (working copy) @@ -0,0 +1,1480 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions for managing print jobs + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +SKIPLIST GlobalJobList; + +// Local Variables +static DWORD _dwLastJobID; + + +/** + * @name _EqualStrings + * + * Returns whether two strings are equal. + * Unlike wcscmp, this function also works with NULL strings. + * + * @param pwszA + * First string to compare. + * + * @param pwszB + * Second string to compare. + * + * @return + * TRUE if the strings are equal, FALSE if they differ. + */ +static __inline BOOL +_EqualStrings(PCWSTR pwszA, PCWSTR pwszB) +{ + if (!pwszA && !pwszB) + return TRUE; + + if (pwszA && !pwszB) + return FALSE; + + if (!pwszA && pwszB) + return FALSE; + + return (wcscmp(pwszA, pwszB) == 0); +} + +static BOOL +_GetNextJobID(PDWORD dwJobID) +{ + ++_dwLastJobID; + + while (LookupElementSkiplist(&GlobalJobList, &_dwLastJobID, NULL)) + { + // This ID is already taken. Try the next one. + ++_dwLastJobID; + } + + if (!IS_VALID_JOB_ID(_dwLastJobID)) + { + ERR("Job ID %lu isn't valid!\n", _dwLastJobID); + return FALSE; + } + + *dwJobID = _dwLastJobID; + return TRUE; +} + +/** + * @name _GlobalJobListCompareRoutine + * + * SKIPLIST_COMPARE_ROUTINE for the Global Job List. + * We need the Global Job List to check whether a Job ID is already in use. Consequently, this list is sorted by ID. + */ +static int WINAPI +_GlobalJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct) +{ + PLOCAL_JOB A = (PLOCAL_JOB)FirstStruct; + PLOCAL_JOB B = (PLOCAL_JOB)SecondStruct; + + return A->dwJobID - B->dwJobID; +} + +/** + * @name _PrinterJobListCompareRoutine + * + * SKIPLIST_COMPARE_ROUTINE for the each Printer's Job List. + * Jobs in this list are sorted in the desired order of processing. + */ +static int WINAPI +_PrinterJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct) +{ + PLOCAL_JOB A = (PLOCAL_JOB)FirstStruct; + PLOCAL_JOB B = (PLOCAL_JOB)SecondStruct; + int iComparison; + FILETIME ftSubmittedA; + FILETIME ftSubmittedB; + ULARGE_INTEGER uliSubmittedA; + ULARGE_INTEGER uliSubmittedB; + ULONGLONG ullResult; + + // First compare the priorities to determine the order. + // The job with a higher priority shall come first. + iComparison = A->dwPriority - B->dwPriority; + if (iComparison != 0) + return iComparison; + + // Both have the same priority, so go by creation time. + // Comparison is done using the MSDN-recommended way for comparing SYSTEMTIMEs. + if (!SystemTimeToFileTime(&A->stSubmitted, &ftSubmittedA)) + { + ERR("SystemTimeToFileTime failed for A with error %lu!\n", GetLastError()); + return 0; + } + + if (!SystemTimeToFileTime(&B->stSubmitted, &ftSubmittedB)) + { + ERR("SystemTimeToFileTime failed for B with error %lu!\n", GetLastError()); + return 0; + } + + uliSubmittedA.LowPart = ftSubmittedA.dwLowDateTime; + uliSubmittedA.HighPart = ftSubmittedA.dwHighDateTime; + uliSubmittedB.LowPart = ftSubmittedB.dwLowDateTime; + uliSubmittedB.HighPart = ftSubmittedB.dwHighDateTime; + ullResult = uliSubmittedA.QuadPart - uliSubmittedB.QuadPart; + + if (ullResult < 0) + return -1; + else if (ullResult > 0) + return 1; + + return 0; +} + +DWORD +GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput) +{ + const WCHAR wszPrintersPath[] = L"\\PRINTERS\\"; + const DWORD cchPrintersPath = _countof(wszPrintersPath) - 1; + const DWORD cchSpoolerFile = sizeof("?????.") - 1; + const DWORD cchExtension = sizeof("SPL") - 1; // pwszExtension may be L"SPL" or L"SHD", same length for both! + + if (pwszOutput) + { + CopyMemory(pwszOutput, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR)); + CopyMemory(&pwszOutput[cchSpoolDirectory], wszPrintersPath, cchPrintersPath * sizeof(WCHAR)); + swprintf(&pwszOutput[cchSpoolDirectory + cchPrintersPath], L"%05lu.", dwJobID); + CopyMemory(&pwszOutput[cchSpoolDirectory + cchPrintersPath + cchSpoolerFile], pwszExtension, (cchExtension + 1) * sizeof(WCHAR)); + } + + return (cchSpoolDirectory + cchPrintersPath + cchSpoolerFile + cchExtension + 1) * sizeof(WCHAR); +} + +BOOL +InitializeGlobalJobList() +{ + const WCHAR wszPath[] = L"\\PRINTERS\\?????.SHD"; + const DWORD cchPath = _countof(wszPath) - 1; + + DWORD dwErrorCode; + DWORD dwJobID; + HANDLE hFind; + PLOCAL_JOB pJob = NULL; + PWSTR p; + WCHAR wszFullPath[MAX_PATH]; + WIN32_FIND_DATAW FindData; + + // This one is incremented in _GetNextJobID. + _dwLastJobID = 0; + + // Initialize an empty list for all jobs of all local printers. + // We will search it by Job ID (supply a pointer to a DWORD in LookupElementSkiplist). + InitializeSkiplist(&GlobalJobList, DllAllocSplMem, _GlobalJobListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem); + + // Construct the full path search pattern. + CopyMemory(wszFullPath, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR)); + CopyMemory(&wszFullPath[cchSpoolDirectory], wszPath, (cchPath + 1) * sizeof(WCHAR)); + + // Use the search pattern to look for unfinished jobs serialized in shadow files (.SHD) + hFind = FindFirstFileW(wszFullPath, &FindData); + if (hFind == INVALID_HANDLE_VALUE) + { + // No unfinished jobs found. + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + do + { + // Skip possible subdirectories. + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + continue; + + // Extract the Job ID and verify the file name format at the same time. + // This includes all valid names (like "00005.SHD") and excludes invalid ones (like "10ABC.SHD"). + dwJobID = wcstoul(FindData.cFileName, &p, 10); + if (!IS_VALID_JOB_ID(dwJobID)) + continue; + + if (wcsicmp(p, L".SHD") != 0) + continue; + + // This shadow file has a valid name. Construct the full path and try to load it. + GetJobFilePath(L"SHD", dwJobID, wszFullPath); + pJob = ReadJobShadowFile(wszFullPath); + if (!pJob) + continue; + + // Add it to the Global Job List. + if (!InsertElementSkiplist(&GlobalJobList, pJob)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID); + goto Cleanup; + } + + // Add it to the Printer's Job List. + if (!InsertElementSkiplist(&pJob->pPrinter->JobList, pJob)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("InsertElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID); + goto Cleanup; + } + } + while (FindNextFileW(hFind, &FindData)); + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Outside the loop + if (hFind) + FindClose(hFind); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +void +InitializePrinterJobList(PLOCAL_PRINTER pPrinter) +{ + // Initialize an empty list for this printer's jobs. + // This one is only for sorting the jobs. If you need to lookup a job, search the GlobalJobList by Job ID. + InitializeSkiplist(&pPrinter->JobList, DllAllocSplMem, _PrinterJobListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem); +} + +DWORD WINAPI +CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle) +{ + const WCHAR wszDoubleBackslash[] = L"\\"; + const DWORD cchDoubleBackslash = _countof(wszDoubleBackslash) - 1; + + DWORD cchMachineName; + DWORD cchUserName; + DWORD dwErrorCode; + PLOCAL_JOB pJob; + RPC_BINDING_HANDLE hServerBinding = NULL; + RPC_WSTR pwszBinding = NULL; + RPC_WSTR pwszMachineName = NULL; + + // Create a new job. + pJob = DllAllocSplMem(sizeof(LOCAL_JOB)); + if (!pJob) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Reserve an ID for this job. + if (!_GetNextJobID(&pJob->dwJobID)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + goto Cleanup; + } + + // Copy over defaults to the LOCAL_JOB structure. + pJob->pPrinter = pPrinterHandle->pPrinter; + pJob->pPrintProcessor = pPrinterHandle->pPrinter->pPrintProcessor; + pJob->dwPriority = DEF_PRIORITY; + pJob->dwStatus = JOB_STATUS_SPOOLING; + pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype); + pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName); + pJob->pDevMode = DuplicateDevMode(pPrinterHandle->pDevMode); + GetSystemTime(&pJob->stSubmitted); + + // Get the user name for the Job. + cchUserName = UNLEN + 1; + pJob->pwszUserName = DllAllocSplMem(cchUserName * sizeof(WCHAR)); + if (!GetUserNameW(pJob->pwszUserName, &cchUserName)) + { + dwErrorCode = GetLastError(); + ERR("GetUserNameW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // FIXME: For now, pwszNotifyName equals pwszUserName. + pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName); + + // Get the name of the machine that submitted the Job over RPC. + dwErrorCode = RpcBindingServerFromClient(NULL, &hServerBinding); + if (dwErrorCode != RPC_S_OK) + { + ERR("RpcBindingServerFromClient failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = RpcBindingToStringBindingW(hServerBinding, &pwszBinding); + if (dwErrorCode != RPC_S_OK) + { + ERR("RpcBindingToStringBindingW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL); + if (dwErrorCode != RPC_S_OK) + { + ERR("RpcStringBindingParseW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + cchMachineName = wcslen(pwszMachineName); + pJob->pwszMachineName = DllAllocSplMem((cchMachineName + cchDoubleBackslash + 1) * sizeof(WCHAR)); + CopyMemory(pJob->pwszMachineName, wszDoubleBackslash, cchDoubleBackslash * sizeof(WCHAR)); + CopyMemory(&pJob->pwszMachineName[cchDoubleBackslash], pwszMachineName, (cchMachineName + 1) * sizeof(WCHAR)); + + // Add the job to the Global Job List. + if (!InsertElementSkiplist(&GlobalJobList, pJob)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID); + goto Cleanup; + } + + // Add the job at the end of the Printer's Job List. + // As all new jobs are created with default priority, we can be sure that it would always be inserted at the end. + if (!InsertTailElementSkiplist(&pJob->pPrinter->JobList, pJob)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID); + goto Cleanup; + } + + // We were successful! + pPrinterHandle->bStartedDoc = TRUE; + pPrinterHandle->pJob = pJob; + dwErrorCode = ERROR_SUCCESS; + + // Don't let the cleanup routine free this. + pJob = NULL; + +Cleanup: + if (pJob) + DllFreeSplMem(pJob); + + if (pwszMachineName) + RpcStringFreeW(&pwszMachineName); + + if (pwszBinding) + RpcStringFreeW(&pwszBinding); + + if (hServerBinding) + RpcBindingFree(&hServerBinding); + + return dwErrorCode; +} + +BOOL WINAPI +LocalAddJob(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded) +{ + ADDJOB_INFO_1W AddJobInfo1; + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Check if this is a printer handle. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // This handle must not have started a job yet! + if (pPrinterHandle->pJob) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Check if this is the right structure level. + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Check if the printer is set to do direct printing. + // The Job List isn't used in this case. + if (pPrinterHandle->pPrinter->dwAttributes & PRINTER_ATTRIBUTE_DIRECT) + { + dwErrorCode = ERROR_INVALID_ACCESS; + goto Cleanup; + } + + // Check if the supplied buffer is large enough. + *pcbNeeded = sizeof(ADDJOB_INFO_1W) + GetJobFilePath(L"SPL", 0, NULL); + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // All requirements are met - create a new job. + dwErrorCode = CreateJob(pPrinterHandle); + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // Mark that this job was started with AddJob (so that it can be scheduled for printing with ScheduleJob). + pPrinterHandle->pJob->bAddedJob = TRUE; + + // Return a proper ADDJOB_INFO_1W structure. + AddJobInfo1.JobId = pPrinterHandle->pJob->dwJobID; + AddJobInfo1.Path = (PWSTR)(pData + sizeof(ADDJOB_INFO_1W)); + + CopyMemory(pData, &AddJobInfo1, sizeof(ADDJOB_INFO_1W)); + GetJobFilePath(L"SPL", AddJobInfo1.JobId, AddJobInfo1.Path); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + + +static DWORD +_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded) +{ + DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR); + DWORD cbDocumentName = 0; + DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR); + DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR); + DWORD cbStatus = 0; + DWORD cbUserName = 0; + DWORD dwErrorCode; + JOB_INFO_1W JobInfo1 = { 0 }; + + // Calculate the lengths of the optional values. + if (pJob->pwszDocumentName) + cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR); + + if (pJob->pwszStatus) + cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR); + + if (pJob->pwszUserName) + cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR); + + // Check if the supplied buffer is large enough. + *pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName; + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings at the end of the buffer. + *ppEnd -= cbDatatype; + JobInfo1.pDatatype = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype); + + *ppEnd -= cbMachineName; + JobInfo1.pMachineName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName); + + *ppEnd -= cbPrinterName; + JobInfo1.pPrinterName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName); + + // Copy the optional values. + if (cbDocumentName) + { + *ppEnd -= cbDocumentName; + JobInfo1.pDocument = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName); + } + + if (cbStatus) + { + *ppEnd -= cbStatus; + JobInfo1.pStatus = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus); + } + + if (cbUserName) + { + *ppEnd -= cbUserName; + JobInfo1.pUserName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName); + } + + // Fill the rest of the structure. + JobInfo1.JobId = pJob->dwJobID; + JobInfo1.Priority = pJob->dwPriority; + JobInfo1.Status = pJob->dwStatus; + JobInfo1.TotalPages = pJob->dwTotalPages; + CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME)); + + // Finally copy the structure to the output pointer. + CopyMemory(*ppStart, &JobInfo1, sizeof(JOB_INFO_1W)); + *ppStart += sizeof(JOB_INFO_1W); + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +static DWORD +_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded) +{ + DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR); + DWORD cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra; + DWORD cbDocumentName = 0; + DWORD cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR); + DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR); + DWORD cbNotifyName = 0; + DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR); + DWORD cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR); + DWORD cbPrintProcessorParameters = 0; + DWORD cbStatus = 0; + DWORD cbUserName = 0; + DWORD dwErrorCode; + FILETIME ftNow; + FILETIME ftSubmitted; + JOB_INFO_2W JobInfo2 = { 0 }; + ULARGE_INTEGER uliNow; + ULARGE_INTEGER uliSubmitted; + + // Calculate the lengths of the optional values. + if (pJob->pwszDocumentName) + cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR); + + if (pJob->pwszNotifyName) + cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR); + + if (pJob->pwszPrintProcessorParameters) + cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR); + + if (pJob->pwszStatus) + cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR); + + if (pJob->pwszUserName) + cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR); + + // Check if the supplied buffer is large enough. + *pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + cbDevMode + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbStatus + cbUserName; + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings at the end of the buffer. + *ppEnd -= cbDatatype; + JobInfo2.pDatatype = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype); + + *ppEnd -= cbDevMode; + JobInfo2.pDevMode = (PDEVMODEW)*ppEnd; + CopyMemory(*ppEnd, pJob->pDevMode, cbDevMode); + + *ppEnd -= cbDriverName; + JobInfo2.pDriverName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterDriver, cbDriverName); + + *ppEnd -= cbMachineName; + JobInfo2.pMachineName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName); + + *ppEnd -= cbPrinterName; + JobInfo2.pPrinterName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName); + + *ppEnd -= cbPrintProcessor; + JobInfo2.pPrintProcessor = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pPrintProcessor->pwszName, cbPrintProcessor); + + // Copy the optional values. + if (cbDocumentName) + { + *ppEnd -= cbDocumentName; + JobInfo2.pDocument = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName); + } + + if (cbNotifyName) + { + *ppEnd -= cbNotifyName; + JobInfo2.pNotifyName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszNotifyName, cbNotifyName); + } + + if (cbPrintProcessorParameters) + { + *ppEnd -= cbPrintProcessorParameters; + JobInfo2.pParameters = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszPrintProcessorParameters, cbPrintProcessorParameters); + } + + if (cbStatus) + { + *ppEnd -= cbStatus; + JobInfo2.pStatus = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus); + } + + if (cbUserName) + { + *ppEnd -= cbUserName; + JobInfo2.pUserName = (PWSTR)*ppEnd; + CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName); + } + + // Time in JOB_INFO_2W is the number of milliseconds elapsed since the job was submitted. Calculate this time. + if (!SystemTimeToFileTime(&pJob->stSubmitted, &ftSubmitted)) + { + ERR("SystemTimeToFileTime failed with error %lu!\n", GetLastError()); + return FALSE; + } + + GetSystemTimeAsFileTime(&ftNow); + uliSubmitted.LowPart = ftSubmitted.dwLowDateTime; + uliSubmitted.HighPart = ftSubmitted.dwHighDateTime; + uliNow.LowPart = ftNow.dwLowDateTime; + uliNow.HighPart = ftNow.dwHighDateTime; + JobInfo2.Time = (DWORD)((uliNow.QuadPart - uliSubmitted.QuadPart) / 10000); + + // Position in JOB_INFO_2W is the 1-based index of the job in the processing queue. + // Retrieve this through the element index of the job in the Printer's Job List. + if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &JobInfo2.Position)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("pJob could not be located in the Printer's Job List!\n"); + goto Cleanup; + } + + // Make the index 1-based. + ++JobInfo2.Position; + + // Fill the rest of the structure. + JobInfo2.JobId = pJob->dwJobID; + JobInfo2.PagesPrinted = pJob->dwPagesPrinted; + JobInfo2.Priority = pJob->dwPriority; + JobInfo2.StartTime = pJob->dwStartTime; + JobInfo2.Status = pJob->dwStatus; + JobInfo2.TotalPages = pJob->dwTotalPages; + JobInfo2.UntilTime = pJob->dwUntilTime; + CopyMemory(&JobInfo2.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME)); + + // Finally copy the structure to the output pointer. + CopyMemory(*ppStart, &JobInfo2, sizeof(JOB_INFO_2W)); + *ppStart += sizeof(JOB_INFO_2W); + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +BOOL WINAPI +LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded) +{ + DWORD dwErrorCode; + PBYTE pEnd = &pStart[cbBuf]; + PLOCAL_HANDLE pHandle; + PLOCAL_JOB pJob; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Check if this is a printer handle. + pHandle = (PLOCAL_HANDLE)hPrinter; + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // Get the desired job. + pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL); + if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Begin counting. + *pcbNeeded = 0; + + // The function behaves differently for each level. + if (Level == 1) + dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded); + else if (Level == 2) + dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded); + else + dwErrorCode = ERROR_INVALID_LEVEL; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +static DWORD +_LocalSetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PJOB_INFO_1W pJobInfo) +{ + DWORD dwErrorCode; + + // First check the validity of the input before changing anything. + if (!FindDatatype(pJob->pPrintProcessor, pJobInfo->pDatatype)) + { + dwErrorCode = ERROR_INVALID_DATATYPE; + goto Cleanup; + } + + // Check if the datatype has changed. + if (!_EqualStrings(pJob->pwszDatatype, pJobInfo->pDatatype)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszDatatype, pJobInfo->pDatatype)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the document name has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszDocumentName, pJobInfo->pDocument)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszDocumentName, pJobInfo->pDocument)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the status message has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszStatus, pJobInfo->pStatus)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszStatus, pJobInfo->pStatus)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the user name has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszUserName, pJobInfo->pUserName) != 0) + { + // The new user name doesn't need to exist, so no additional verification is required. + + // Use the new value. + if (!ReallocSplStr(&pJob->pwszUserName, pJobInfo->pUserName)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the priority has changed. + if (pJob->dwPriority != pJobInfo->Priority && IS_VALID_PRIORITY(pJobInfo->Priority)) + { + // Set the new priority. + pJob->dwPriority = pJobInfo->Priority; + + // Remove and reinsert the job in the Printer's Job List. + // The Compare function will be used to find the right position now considering the new priority. + DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob); + InsertElementSkiplist(&pJob->pPrinter->JobList, pJob); + } + + // Check if the status flags have changed. + if (pJob->dwStatus != pJobInfo->Status) + { + // Only add status flags that make sense. + if (pJobInfo->Status & JOB_STATUS_PAUSED) + pJob->dwStatus |= JOB_STATUS_PAUSED; + + if (pJobInfo->Status & JOB_STATUS_ERROR) + pJob->dwStatus |= JOB_STATUS_ERROR; + + if (pJobInfo->Status & JOB_STATUS_OFFLINE) + pJob->dwStatus |= JOB_STATUS_OFFLINE; + + if (pJobInfo->Status & JOB_STATUS_PAPEROUT) + pJob->dwStatus |= JOB_STATUS_PAPEROUT; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +static DWORD +_LocalSetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PJOB_INFO_2W pJobInfo) +{ + DWORD dwErrorCode; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + + // First check the validity of the input before changing anything. + pPrintProcessor = FindPrintProcessor(pJobInfo->pPrintProcessor); + if (!pPrintProcessor) + { + dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR; + goto Cleanup; + } + + if (!FindDatatype(pPrintProcessor, pJobInfo->pDatatype)) + { + dwErrorCode = ERROR_INVALID_DATATYPE; + goto Cleanup; + } + + // Check if the datatype has changed. + if (!_EqualStrings(pJob->pwszDatatype, pJobInfo->pDatatype)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszDatatype, pJobInfo->pDatatype)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the document name has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszDocumentName, pJobInfo->pDocument)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszDocumentName, pJobInfo->pDocument)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the notify name has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszNotifyName, pJobInfo->pNotifyName)) + { + // The new notify name doesn't need to exist, so no additional verification is required. + + // Use the new value. + if (!ReallocSplStr(&pJob->pwszNotifyName, pJobInfo->pNotifyName)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the Print Processor Parameters have changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszPrintProcessorParameters, pJobInfo->pParameters)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszPrintProcessorParameters, pJobInfo->pParameters)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the Status Message has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszStatus, pJobInfo->pStatus)) + { + // Use the new value. + if (!ReallocSplStr(&pJob->pwszStatus, pJobInfo->pStatus)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the user name has changed. An empty string is permitted here! + if (!_EqualStrings(pJob->pwszUserName, pJobInfo->pUserName)) + { + // The new user name doesn't need to exist, so no additional verification is required. + + // Use the new value. + if (!ReallocSplStr(&pJob->pwszUserName, pJobInfo->pUserName)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + } + + // Check if the priority has changed. + if (pJob->dwPriority != pJobInfo->Priority && IS_VALID_PRIORITY(pJobInfo->Priority)) + { + // Set the new priority. + pJob->dwPriority = pJobInfo->Priority; + + // Remove and reinsert the job in the Printer's Job List. + // The Compare function will be used to find the right position now considering the new priority. + DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob); + InsertElementSkiplist(&pJob->pPrinter->JobList, pJob); + } + + // Check if the status flags have changed. + if (pJob->dwStatus != pJobInfo->Status) + { + // Only add status flags that make sense. + if (pJobInfo->Status & JOB_STATUS_PAUSED) + pJob->dwStatus |= JOB_STATUS_PAUSED; + + if (pJobInfo->Status & JOB_STATUS_ERROR) + pJob->dwStatus |= JOB_STATUS_ERROR; + + if (pJobInfo->Status & JOB_STATUS_OFFLINE) + pJob->dwStatus |= JOB_STATUS_OFFLINE; + + if (pJobInfo->Status & JOB_STATUS_PAPEROUT) + pJob->dwStatus |= JOB_STATUS_PAPEROUT; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +BOOL WINAPI +LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command) +{ + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle; + PLOCAL_JOB pJob; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + WCHAR wszFullPath[MAX_PATH]; + + // Check if this is a printer handle. + pHandle = (PLOCAL_HANDLE)hPrinter; + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // Get the desired job. + pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL); + if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Setting job information is handled differently for each level. + if (Level) + { + if (Level == 1) + dwErrorCode = _LocalSetJobLevel1(pPrinterHandle, pJob, (PJOB_INFO_1W)pJobInfo); + else if (Level == 2) + dwErrorCode = _LocalSetJobLevel2(pPrinterHandle, pJob, (PJOB_INFO_2W)pJobInfo); + else + dwErrorCode = ERROR_INVALID_LEVEL; + } + + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // If we do spooled printing, the job information is written down into a shadow file. + if (!(pPrinterHandle->pPrinter->dwAttributes & PRINTER_ATTRIBUTE_DIRECT)) + { + // Write the job data into the shadow file. + GetJobFilePath(L"SHD", JobId, wszFullPath); + WriteJobShadowFile(wszFullPath, pJob); + } + + // Perform an additional command if desired. + if (Command) + { + if (Command == JOB_CONTROL_SENT_TO_PRINTER) + { + // This indicates the end of the Print Job. + + // Cancel the Job at the Print Processor. + if (pJob->hPrintProcessor) + pJob->pPrintProcessor->pfnControlPrintProcessor(pJob->hPrintProcessor, JOB_CONTROL_CANCEL); + + FreeJob(pJob); + + // TODO: All open handles associated with the job need to be invalidated. + // This certainly needs handle tracking... + } + else + { + ERR("Unimplemented SetJob Command: %lu!\n", Command); + } + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + DWORD dwErrorCode; + DWORD i; + PBYTE pEnd = &pStart[cbBuf]; + PLOCAL_HANDLE pHandle; + PLOCAL_JOB pJob; + PSKIPLIST_NODE pFirstJobNode; + PSKIPLIST_NODE pNode; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Check if this is a printer handle. + pHandle = (PLOCAL_HANDLE)hPrinter; + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // Check the level. + if (Level > 2) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // Lookup the node of the first job requested by the caller in the Printer's Job List. + pFirstJobNode = LookupNodeByIndexSkiplist(&pPrinterHandle->pPrinter->JobList, FirstJob); + + // Count the required buffer size and the number of jobs. + i = 0; + pNode = pFirstJobNode; + + while (i < NoJobs && pNode) + { + pJob = (PLOCAL_JOB)pNode->Element; + + // The function behaves differently for each level. + if (Level == 1) + _LocalGetJobLevel1(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded); + else if (Level == 2) + _LocalGetJobLevel2(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded); + + // We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first. + i++; + pNode = pNode->Next[0]; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Begin counting again and also empty the given buffer. + *pcbNeeded = 0; + ZeroMemory(pStart, cbBuf); + + // Now call the same functions again to copy the actual data for each job into the buffer. + i = 0; + pNode = pFirstJobNode; + + while (i < NoJobs && pNode) + { + pJob = (PLOCAL_JOB)pNode->Element; + + // The function behaves differently for each level. + if (Level == 1) + dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded); + else if (Level == 2) + dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded); + + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first. + i++; + pNode = pNode->Next[0]; + } + + *pcReturned = i; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID) +{ + DWORD dwAttributes; + DWORD dwErrorCode; + HANDLE hThread; + PLOCAL_JOB pJob; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + WCHAR wszFullPath[MAX_PATH]; + + // Check if this is a printer handle. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // Check if the Job ID is valid. + pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL); + if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Check if this Job was started with AddJob. + if (!pJob->bAddedJob) + { + dwErrorCode = ERROR_SPL_NO_ADDJOB; + goto Cleanup; + } + + // Construct the full path to the spool file. + GetJobFilePath(L"SPL", dwJobID, wszFullPath); + + // Check if it exists. + dwAttributes = GetFileAttributesW(wszFullPath); + if (dwAttributes == INVALID_FILE_ATTRIBUTES || dwAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + dwErrorCode = ERROR_SPOOL_FILE_NOT_FOUND; + goto Cleanup; + } + + // Spooling is finished at this point. + pJob->dwStatus &= ~JOB_STATUS_SPOOLING; + + // Write the job data into the shadow file. + wcscpy(wcsrchr(wszFullPath, L'.'), L".SHD"); + WriteJobShadowFile(wszFullPath, pJob); + + // Create the thread for performing the printing process. + hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PrintingThreadProc, pJob, 0, NULL); + if (!hThread) + { + dwErrorCode = GetLastError(); + ERR("CreateThread failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We don't need the thread handle. Keeping it open blocks the thread from terminating. + CloseHandle(hThread); + + // ScheduleJob has done its job. The rest happens inside the thread. + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +PLOCAL_JOB +ReadJobShadowFile(PCWSTR pwszFilePath) +{ + DWORD cbFileSize; + DWORD cbRead; + HANDLE hFile = INVALID_HANDLE_VALUE; + PLOCAL_JOB pJob; + PLOCAL_JOB pReturnValue = NULL; + PLOCAL_PRINTER pPrinter; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + PSHD_HEADER pShadowFile = NULL; + PWSTR pwszPrinterName; + PWSTR pwszPrintProcessor; + + // Try to open the file. + hFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + ERR("CreateFileW failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + // Get its file size (small enough for a single DWORD) and allocate memory for all of it. + cbFileSize = GetFileSize(hFile, NULL); + pShadowFile = DllAllocSplMem(cbFileSize); + if (!pShadowFile) + { + ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + // Read the entire file. + if (!ReadFile(hFile, pShadowFile, cbFileSize, &cbRead, NULL)) + { + ERR("ReadFile failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + // Check signature and header size. + if (pShadowFile->dwSignature != SHD_WIN2003_SIGNATURE || pShadowFile->cbHeader != sizeof(SHD_HEADER)) + { + ERR("Signature or Header Size mismatch for file \"%S\"!\n", pwszFilePath); + goto Cleanup; + } + + // Retrieve the associated printer from the list. + pwszPrinterName = (PWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrinterName); + pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL); + if (!pPrinter) + { + ERR("Shadow file \"%S\" references a non-existing printer \"%S\"!\n", pwszFilePath, pwszPrinterName); + goto Cleanup; + } + + // Retrieve the associated Print Processor from the list. + pwszPrintProcessor = (PWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrintProcessor); + pPrintProcessor = FindPrintProcessor(pwszPrintProcessor); + if (!pPrintProcessor) + { + ERR("Shadow file \"%S\" references a non-existing Print Processor \"%S\"!\n", pwszFilePath, pwszPrintProcessor); + goto Cleanup; + } + + // Create a new job structure and copy over the relevant fields. + pJob = DllAllocSplMem(sizeof(LOCAL_JOB)); + if (!pJob) + { + ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + pJob->dwJobID = pShadowFile->dwJobID; + pJob->dwPriority = pShadowFile->dwPriority; + pJob->dwStartTime = pShadowFile->dwStartTime; + pJob->dwTotalPages = pShadowFile->dwTotalPages; + pJob->dwUntilTime = pShadowFile->dwUntilTime; + pJob->pPrinter = pPrinter; + pJob->pPrintProcessor = pPrintProcessor; + pJob->pDevMode = DuplicateDevMode((PDEVMODEW)((ULONG_PTR)pShadowFile + pShadowFile->offDevMode)); + pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype)); + pJob->pwszMachineName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offMachineName)); + CopyMemory(&pJob->stSubmitted, &pShadowFile->stSubmitted, sizeof(SYSTEMTIME)); + + // Copy the optional values. + if (pShadowFile->offDocumentName) + pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName)); + + if (pShadowFile->offNotifyName) + pJob->pwszNotifyName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offNotifyName)); + + if (pShadowFile->offPrintProcessorParameters) + pJob->pwszPrintProcessorParameters = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrintProcessorParameters)); + + if (pShadowFile->offUserName) + pJob->pwszUserName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offUserName)); + + // Jobs read from shadow files were always added using AddJob. + pJob->bAddedJob = TRUE; + + pReturnValue = pJob; + +Cleanup: + if (pShadowFile) + DllFreeSplMem(pShadowFile); + + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + + return pReturnValue; +} + +BOOL +WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob) +{ + BOOL bReturnValue = FALSE; + DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR); + DWORD cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra; + DWORD cbDocumentName = 0; + DWORD cbFileSize; + DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR); + DWORD cbNotifyName = 0; + DWORD cbPrinterDriver = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR); + DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR); + DWORD cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR); + DWORD cbPrintProcessorParameters = 0; + DWORD cbUserName = 0; + DWORD cbWritten; + DWORD dwCurrentOffset; + HANDLE hSHDFile = INVALID_HANDLE_VALUE; + HANDLE hSPLFile = INVALID_HANDLE_VALUE; + PSHD_HEADER pShadowFile = NULL; + + // Try to open the SHD file. + hSHDFile = CreateFileW(pwszFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL); + if (hSHDFile == INVALID_HANDLE_VALUE) + { + ERR("CreateFileW failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + // Calculate the lengths of the optional values and the total size of the shadow file. + if (pJob->pwszDocumentName) + cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR); + + if (pJob->pwszNotifyName) + cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR); + + if (pJob->pwszPrintProcessorParameters) + cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR); + + if (pJob->pwszUserName) + cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR); + + cbFileSize = sizeof(SHD_HEADER) + cbDatatype + cbDocumentName + cbDevMode + cbMachineName + cbNotifyName + cbPrinterDriver + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbUserName; + + // Allocate memory for it. + pShadowFile = DllAllocSplMem(cbFileSize); + if (!pShadowFile) + { + ERR("DllAllocSplMem failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + // Fill out the shadow file header information. + pShadowFile->dwSignature = SHD_WIN2003_SIGNATURE; + pShadowFile->cbHeader = sizeof(SHD_HEADER); + + // Copy the values. + pShadowFile->dwJobID = pJob->dwJobID; + pShadowFile->dwPriority = pJob->dwPriority; + pShadowFile->dwStartTime = pJob->dwStartTime; + pShadowFile->dwTotalPages = pJob->dwTotalPages; + pShadowFile->dwUntilTime = pJob->dwUntilTime; + CopyMemory(&pShadowFile->stSubmitted, &pJob->stSubmitted, sizeof(SYSTEMTIME)); + + // Determine the file size of the .SPL file + wcscpy(wcsrchr(pwszFilePath, L'.'), L".SPL"); + hSPLFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (hSPLFile != INVALID_HANDLE_VALUE) + pShadowFile->dwSPLSize = GetFileSize(hSPLFile, NULL); + + // Add the extra values that are stored as offsets in the shadow file. + // The first value begins right after the shadow file header. + dwCurrentOffset = sizeof(SHD_HEADER); + + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszDatatype, cbDatatype); + pShadowFile->offDatatype = dwCurrentOffset; + dwCurrentOffset += cbDatatype; + + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pDevMode, cbDevMode); + pShadowFile->offDevMode = dwCurrentOffset; + dwCurrentOffset += cbDevMode; + + // offDriverName is only written, but automatically determined through offPrinterName when reading. + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pPrinter->pwszPrinterDriver, cbPrinterDriver); + pShadowFile->offDriverName = dwCurrentOffset; + dwCurrentOffset += cbPrinterDriver; + + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszMachineName, cbMachineName); + pShadowFile->offMachineName = dwCurrentOffset; + dwCurrentOffset += cbMachineName; + + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pPrinter->pwszPrinterName, cbPrinterName); + pShadowFile->offPrinterName = dwCurrentOffset; + dwCurrentOffset += cbPrinterName; + + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pPrintProcessor->pwszName, cbPrintProcessor); + pShadowFile->offPrintProcessor = dwCurrentOffset; + dwCurrentOffset += cbPrintProcessor; + + // Copy the optional values. + if (cbDocumentName) + { + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszDocumentName, cbDocumentName); + pShadowFile->offDocumentName = dwCurrentOffset; + dwCurrentOffset += cbDocumentName; + } + + if (cbNotifyName) + { + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszNotifyName, cbNotifyName); + pShadowFile->offNotifyName = dwCurrentOffset; + dwCurrentOffset += cbNotifyName; + } + + if (cbPrintProcessorParameters) + { + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszPrintProcessorParameters, cbPrintProcessorParameters); + pShadowFile->offPrintProcessorParameters = dwCurrentOffset; + dwCurrentOffset += cbPrintProcessorParameters; + } + + if (cbUserName) + { + CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszUserName, cbUserName); + pShadowFile->offUserName = dwCurrentOffset; + dwCurrentOffset += cbUserName; + } + + // Write the file. + if (!WriteFile(hSHDFile, pShadowFile, cbFileSize, &cbWritten, NULL)) + { + ERR("WriteFile failed with error %lu for file \"%S\"!\n", GetLastError(), pwszFilePath); + goto Cleanup; + } + + bReturnValue = TRUE; + +Cleanup: + if (pShadowFile) + DllFreeSplMem(pShadowFile); + + if (hSHDFile != INVALID_HANDLE_VALUE) + CloseHandle(hSHDFile); + + if (hSPLFile != INVALID_HANDLE_VALUE) + CloseHandle(hSPLFile); + + return bReturnValue; +} + +void +FreeJob(PLOCAL_JOB pJob) +{ + PWSTR pwszSHDFile; + + // Remove the Job from both Job Lists. + DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob); + DeleteElementSkiplist(&GlobalJobList, pJob); + + // Try to delete the corresponding .SHD file. + pwszSHDFile = DllAllocSplMem(GetJobFilePath(L"SHD", 0, NULL)); + if (pwszSHDFile && GetJobFilePath(L"SHD", pJob->dwJobID, pwszSHDFile)) + DeleteFileW(pwszSHDFile); + + // Free memory for the mandatory fields. + DllFreeSplMem(pJob->pDevMode); + DllFreeSplStr(pJob->pwszDatatype); + DllFreeSplStr(pJob->pwszDocumentName); + DllFreeSplStr(pJob->pwszMachineName); + DllFreeSplStr(pJob->pwszNotifyName); + DllFreeSplStr(pJob->pwszUserName); + + // Free memory for the optional fields if they are present. + if (pJob->pwszOutputFile) + DllFreeSplStr(pJob->pwszOutputFile); + + if (pJob->pwszPrintProcessorParameters) + DllFreeSplStr(pJob->pwszPrintProcessorParameters); + + if (pJob->pwszStatus) + DllFreeSplStr(pJob->pwszStatus); + + // Finally free the job structure itself. + DllFreeSplMem(pJob); +} Index: win32ss/printing/providers/localspl/localspl.rc =================================================================== --- win32ss/printing/providers/localspl/localspl.rc (nonexistent) +++ win32ss/printing/providers/localspl/localspl.rc (working copy) @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Local Spooler" +#define REACTOS_STR_INTERNAL_NAME "localspl" +#define REACTOS_STR_ORIGINAL_FILENAME "localspl.dll" +#include Index: win32ss/printing/providers/localspl/localspl.spec =================================================================== --- win32ss/printing/providers/localspl/localspl.spec (nonexistent) +++ win32ss/printing/providers/localspl/localspl.spec (working copy) @@ -0,0 +1 @@ +@ stdcall InitializePrintProvidor(ptr long ptr) Index: win32ss/printing/providers/localspl/main.c =================================================================== --- win32ss/printing/providers/localspl/main.c (nonexistent) +++ win32ss/printing/providers/localspl/main.c (working copy) @@ -0,0 +1,166 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Main functions + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +WCHAR wszSpoolDirectory[MAX_PATH]; +DWORD cchSpoolDirectory; + +// Global Constants +const WCHAR wszCurrentEnvironment[] = +#if defined(_X86_) + L"Windows NT x86"; +#elif defined(_AMD64_) + L"Windows x64"; +#elif defined(_ARM_) + L"Windows ARM"; +#else + #error Unsupported architecture +#endif + +const DWORD cbCurrentEnvironment = sizeof(wszCurrentEnvironment); + +const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document"; + +const WCHAR* wszPrintProviderInfo[3] = { + L"Windows NT Local Print Providor", // Name + L"Windows NT Local Printers", // Description + L"Locally connected Printers" // Comment +}; + +// Local Constants +static const PRINTPROVIDOR _PrintProviderFunctions = { + LocalOpenPrinter, // fpOpenPrinter + LocalSetJob, // fpSetJob + LocalGetJob, // fpGetJob + LocalEnumJobs, // fpEnumJobs + NULL, // fpAddPrinter + NULL, // fpDeletePrinter + NULL, // fpSetPrinter + NULL, // fpGetPrinter + LocalEnumPrinters, // fpEnumPrinters + NULL, // fpAddPrinterDriver + NULL, // fpEnumPrinterDrivers + NULL, // fpGetPrinterDriver + NULL, // fpGetPrinterDriverDirectory + NULL, // fpDeletePrinterDriver + NULL, // fpAddPrintProcessor + LocalEnumPrintProcessors, // fpEnumPrintProcessors + LocalGetPrintProcessorDirectory, // fpGetPrintProcessorDirectory + NULL, // fpDeletePrintProcessor + LocalEnumPrintProcessorDatatypes, // fpEnumPrintProcessorDatatypes + LocalStartDocPrinter, // fpStartDocPrinter + LocalStartPagePrinter, // fpStartPagePrinter + LocalWritePrinter, // fpWritePrinter + LocalEndPagePrinter, // fpEndPagePrinter + NULL, // fpAbortPrinter + LocalReadPrinter, // fpReadPrinter + LocalEndDocPrinter, // fpEndDocPrinter + LocalAddJob, // fpAddJob + LocalScheduleJob, // fpScheduleJob + NULL, // fpGetPrinterData + NULL, // fpSetPrinterData + NULL, // fpWaitForPrinterChange + LocalClosePrinter, // fpClosePrinter + NULL, // fpAddForm + NULL, // fpDeleteForm + NULL, // fpGetForm + NULL, // fpSetForm + NULL, // fpEnumForms + LocalEnumMonitors, // fpEnumMonitors + LocalEnumPorts, // fpEnumPorts + NULL, // fpAddPort + NULL, // fpConfigurePort + NULL, // fpDeletePort + NULL, // fpCreatePrinterIC + NULL, // fpPlayGdiScriptOnPrinterIC + NULL, // fpDeletePrinterIC + NULL, // fpAddPrinterConnection + NULL, // fpDeletePrinterConnection + NULL, // fpPrinterMessageBox + NULL, // fpAddMonitor + NULL, // fpDeleteMonitor + NULL, // fpResetPrinter + NULL, // fpGetPrinterDriverEx + NULL, // fpFindFirstPrinterChangeNotification + NULL, // fpFindClosePrinterChangeNotification + NULL, // fpAddPortEx + NULL, // fpShutDown + NULL, // fpRefreshPrinterChangeNotification + NULL, // fpOpenPrinterEx + NULL, // fpAddPrinterEx + NULL, // fpSetPort + NULL, // fpEnumPrinterData + NULL, // fpDeletePrinterData + NULL, // fpClusterSplOpen + NULL, // fpClusterSplClose + NULL, // fpClusterSplIsAlive + NULL, // fpSetPrinterDataEx + NULL, // fpGetPrinterDataEx + NULL, // fpEnumPrinterDataEx + NULL, // fpEnumPrinterKey + NULL, // fpDeletePrinterDataEx + NULL, // fpDeletePrinterKey + NULL, // fpSeekPrinter + NULL, // fpDeletePrinterDriverEx + NULL, // fpAddPerMachineConnection + NULL, // fpDeletePerMachineConnection + NULL, // fpEnumPerMachineConnections + NULL, // fpXcvData + NULL, // fpAddPrinterDriverEx + NULL, // fpSplReadPrinter + NULL, // fpDriverUnloadComplete + NULL, // fpGetSpoolFileInfo + NULL, // fpCommitSpoolData + NULL, // fpCloseSpoolFileHandle + NULL, // fpFlushPrinter + NULL, // fpSendRecvBidiData + NULL, // fpAddDriverCatalog +}; + +static void +_GetSpoolDirectory() +{ + const WCHAR wszSpoolPath[] = L"\\spool"; + const DWORD cchSpoolPath = _countof(wszSpoolPath) - 1; + + // Get the system directory and append the "spool" subdirectory. + // Forget about length checks here. If this doesn't fit into MAX_PATH, our OS has more serious problems... + cchSpoolDirectory = GetSystemDirectoryW(wszSpoolDirectory, MAX_PATH); + CopyMemory(&wszSpoolDirectory[cchSpoolDirectory], wszSpoolPath, (cchSpoolPath + 1) * sizeof(WCHAR)); + cchSpoolDirectory += cchSpoolPath; +} + +BOOL WINAPI +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + _GetSpoolDirectory(); + + return InitializePrintMonitorList() && + InitializePortList() && + InitializePrintProcessorList() && + InitializePrinterList() && + InitializeGlobalJobList(); + + default: + return TRUE; + } +} + +BOOL WINAPI +InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath) +{ + CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR))); + + SetLastError(ERROR_SUCCESS); + return TRUE; +} Index: win32ss/printing/providers/localspl/monitors.c =================================================================== --- win32ss/printing/providers/localspl/monitors.c (nonexistent) +++ win32ss/printing/providers/localspl/monitors.c (working copy) @@ -0,0 +1,335 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +LIST_ENTRY PrintMonitorList; + + +PLOCAL_PRINT_MONITOR +FindPrintMonitor(PCWSTR pwszName) +{ + PLIST_ENTRY pEntry; + PLOCAL_PRINT_MONITOR pPrintMonitor; + + if (!pwszName) + return NULL; + + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + if (_wcsicmp(pPrintMonitor->pwszName, pwszName) == 0) + return pPrintMonitor; + } + + return NULL; +} + +BOOL +InitializePrintMonitorList() +{ + const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors"; + const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1; + + DWORD cchMaxSubKey; + DWORD cchPrintMonitorName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HINSTANCE hinstPrintMonitor = NULL; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + MONITORINIT MonitorInit; + PInitializePrintMonitor pfnInitializePrintMonitor; + PInitializePrintMonitor2 pfnInitializePrintMonitor2; + PLOCAL_PRINT_MONITOR pPrintMonitor = NULL; + PWSTR pwszRegistryPath = NULL; + + // Initialize an empty list for our Print Monitors. + InitializeListHead(&PrintMonitorList); + + // Open the key containing Print Monitors. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszMonitorsPath, 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Providers and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Loop through all available Print Providers. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubKey) + { + RegCloseKey(hSubKey); + hSubKey = NULL; + } + + if (pwszRegistryPath) + { + DllFreeSplMem(pwszRegistryPath); + pwszRegistryPath = NULL; + } + + if (pPrintMonitor) + { + if (pPrintMonitor->pwszFileName) + DllFreeSplMem(pPrintMonitor->pwszFileName); + + if (pPrintMonitor->pwszName) + DllFreeSplMem(pPrintMonitor->pwszName); + + DllFreeSplMem(pPrintMonitor); + pPrintMonitor = NULL; + } + + // Create a new LOCAL_PRINT_MONITOR structure for it. + pPrintMonitor = DllAllocSplMem(sizeof(LOCAL_PRINT_MONITOR)); + if (!pPrintMonitor) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Allocate memory for the Print Monitor Name. + pPrintMonitor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pPrintMonitor->pwszName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the name of this Print Monitor. + cchPrintMonitorName = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pPrintMonitor->pwszName, &cchPrintMonitorName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); + continue; + } + + // Open this Print Monitor's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pPrintMonitor->pwszName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Provider \"%S\" with status %lu!\n", pPrintMonitor->pwszName, dwErrorCode); + continue; + } + + // Get the file name of the Print Monitor. + pPrintMonitor->pwszFileName = AllocAndRegQueryWSZ(hSubKey, L"Driver"); + if (!pPrintMonitor->pwszFileName) + continue; + + // Try to load it. + hinstPrintMonitor = LoadLibraryW(pPrintMonitor->pwszFileName); + if (!hinstPrintMonitor) + { + ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + + // Try to find a Level 2 initialization routine first. + pfnInitializePrintMonitor2 = (PInitializePrintMonitor2)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor2"); + if (pfnInitializePrintMonitor2) + { + // Prepare a MONITORINIT structure. + MonitorInit.cbSize = sizeof(MONITORINIT); + MonitorInit.bLocal = TRUE; + + // TODO: Fill the other fields. + + // Call the Level 2 initialization routine. + pPrintMonitor->pMonitor = (PMONITOR2)pfnInitializePrintMonitor2(&MonitorInit, &pPrintMonitor->hMonitor); + if (!pPrintMonitor->pMonitor) + { + ERR("InitializePrintMonitor2 failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + + pPrintMonitor->bIsLevel2 = TRUE; + } + else + { + // Try to find a Level 1 initialization routine then. + pfnInitializePrintMonitor = (PInitializePrintMonitor)GetProcAddress(hinstPrintMonitor, "InitializePrintMonitor"); + if (pfnInitializePrintMonitor) + { + // Construct the registry path. + pwszRegistryPath = DllAllocSplMem((cchMonitorsPath + 1 + cchPrintMonitorName + 1) * sizeof(WCHAR)); + if (!pwszRegistryPath) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszRegistryPath, wszMonitorsPath, cchMonitorsPath * sizeof(WCHAR)); + pwszRegistryPath[cchMonitorsPath] = L'\\'; + CopyMemory(&pwszRegistryPath[cchMonitorsPath + 1], pPrintMonitor->pwszName, (cchPrintMonitorName + 1) * sizeof(WCHAR)); + + // Call the Level 1 initialization routine. + pPrintMonitor->pMonitor = (LPMONITOREX)pfnInitializePrintMonitor(pwszRegistryPath); + if (!pPrintMonitor->pMonitor) + { + ERR("InitializePrintMonitor failed for \"%S\" with error %lu!\n", pPrintMonitor->pwszFileName, GetLastError()); + continue; + } + } + else + { + ERR("No initialization routine found for \"%S\"!\n", pPrintMonitor->pwszFileName); + continue; + } + } + + // Add this Print Monitor to the list. + InsertTailList(&PrintMonitorList, &pPrintMonitor->Entry); + + // Don't let the cleanup routine free this. + pPrintMonitor = NULL; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + if (pwszRegistryPath) + DllFreeSplMem(pwszRegistryPath); + + if (pPrintMonitor) + { + if (pPrintMonitor->pwszFileName) + DllFreeSplMem(pPrintMonitor->pwszFileName); + + if (pPrintMonitor->pwszName) + DllFreeSplMem(pPrintMonitor->pwszName); + + DllFreeSplMem(pPrintMonitor); + } + + // Outside the loop + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + DWORD cbFileName; + DWORD cbMonitorName; + DWORD dwErrorCode; + PBYTE pStart; + PBYTE pEnd; + PLIST_ENTRY pEntry; + PLOCAL_PRINT_MONITOR pPrintMonitor; + MONITOR_INFO_2W MonitorInfo2; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W, so we can handle both in one function here. + + // Sanity checks. + if (Level > 2) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // Count the required buffer size and the number of monitors. + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR); + cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR); + + if (Level == 1) + *pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName; + else + *pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings at the end of the buffer. + pStart = pMonitors; + pEnd = &pMonitors[cbBuf]; + + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + // Copy the monitor name. + cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR); + pEnd -= cbMonitorName; + MonitorInfo2.pName = (PWSTR)pEnd; + CopyMemory(pEnd, pPrintMonitor->pwszName, cbMonitorName); + + if (Level == 1) + { + // Finally copy the structure. + CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_1W)); + pStart += sizeof(MONITOR_INFO_1W); + } + else + { + // Copy the environment. + pEnd -= cbCurrentEnvironment; + MonitorInfo2.pEnvironment = (PWSTR)pEnd; + CopyMemory(pEnd, wszCurrentEnvironment, cbCurrentEnvironment); + + // Copy the file name. + cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR); + pEnd -= cbFileName; + MonitorInfo2.pDLLName = (PWSTR)pEnd; + CopyMemory(pEnd, pPrintMonitor->pwszFileName, cbFileName); + + // Finally copy the structure. + CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_2W)); + pStart += sizeof(MONITOR_INFO_2W); + } + + (*pcReturned)++; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/providers/localspl/ports.c =================================================================== --- win32ss/printing/providers/localspl/ports.c (nonexistent) +++ win32ss/printing/providers/localspl/ports.c (working copy) @@ -0,0 +1,189 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Ports of the Print Monitors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Local Variables +static LIST_ENTRY _PortList; + + +PLOCAL_PORT +FindPort(PCWSTR pwszName) +{ + PLIST_ENTRY pEntry; + PLOCAL_PORT pPort; + + if (!pwszName) + return NULL; + + for (pEntry = _PortList.Flink; pEntry != &_PortList; pEntry = pEntry->Flink) + { + pPort = CONTAINING_RECORD(pEntry, LOCAL_PORT, Entry); + + if (_wcsicmp(pPort->pwszName, pwszName) == 0) + return pPort; + } + + return NULL; +} + +BOOL +InitializePortList() +{ + BOOL bReturnValue; + DWORD cbNeeded; + DWORD cbPortName; + DWORD dwErrorCode; + DWORD dwReturned; + DWORD i; + PLOCAL_PORT pPort; + PLOCAL_PRINT_MONITOR pPrintMonitor; + PLIST_ENTRY pEntry; + PPORT_INFO_1W p; + PPORT_INFO_1W pPortInfo1 = NULL; + + // Initialize an empty list for our Ports. + InitializeListHead(&_PortList); + + // Loop through all Print Monitors. + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + // Cleanup from the previous run. + if (pPortInfo1) + { + DllFreeSplMem(pPortInfo1); + pPortInfo1 = NULL; + } + + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + // Determine the required buffer size for EnumPorts. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, NULL, 1, NULL, 0, &cbNeeded, &dwReturned); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(NULL, 1, NULL, 0, &cbNeeded, &dwReturned); + + // Check the returned error code. + if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) + { + ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor->pwszName, GetLastError()); + continue; + } + + // Allocate a buffer large enough. + pPortInfo1 = DllAllocSplMem(cbNeeded); + if (!pPortInfo1) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the ports handled by this monitor. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned); + + // Check the return value. + if (!bReturnValue) + { + ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor->pwszName, GetLastError()); + continue; + } + + // Loop through all returned ports. + p = pPortInfo1; + + for (i = 0; i < dwReturned; i++) + { + cbPortName = (wcslen(p->pName) + 1) * sizeof(WCHAR); + + // Create a new LOCAL_PORT structure for it. + pPort = DllAllocSplMem(sizeof(LOCAL_PORT) + cbPortName); + if (!pPort) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pPort->pPrintMonitor = pPrintMonitor; + pPort->pwszName = (PWSTR)((PBYTE)pPort + sizeof(LOCAL_PORT)); + CopyMemory(pPort->pwszName, p->pName, cbPortName); + + // Insert it into the list and advance to the next port. + InsertTailList(&_PortList, &pPort->Entry); + p++; + } + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (pPortInfo1) + DllFreeSplMem(pPortInfo1); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned) +{ + BOOL bReturnValue; + DWORD cbCallBuffer; + DWORD cbNeeded; + DWORD dwReturned; + PBYTE pCallBuffer; + PLOCAL_PRINT_MONITOR pPrintMonitor; + PLIST_ENTRY pEntry; + + // Sanity checks. + if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // At the beginning, we have the full buffer available. + cbCallBuffer = cbBuf; + pCallBuffer = pPorts; + + // Loop through all Print Monitors. + for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink) + { + pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry); + + // Call the EnumPorts function of this Print Monitor. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned); + + // Add the returned counts to the total values. + *pcbNeeded += cbNeeded; + *pcReturned += dwReturned; + + // Reduce the available buffer size for the next call without risking an underflow. + if (cbNeeded < cbCallBuffer) + cbCallBuffer -= cbNeeded; + else + cbCallBuffer = 0; + + // Advance the buffer if the caller provided it. + if (pCallBuffer) + pCallBuffer += cbNeeded; + } + + return bReturnValue; +} Index: win32ss/printing/providers/localspl/precomp.h =================================================================== --- win32ss/printing/providers/localspl/precomp.h (nonexistent) +++ win32ss/printing/providers/localspl/precomp.h (working copy) @@ -0,0 +1,302 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Precompiled Header for all source files + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +#define WIN32_NO_STATUS +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SKIPLIST_LEVELS 16 +#include +#include + +#include +WINE_DEFAULT_DEBUG_CHANNEL(localspl); + +// Macros +#define IS_VALID_JOB_ID(ID) (ID >= 1 && ID <= 99999) +#define IS_VALID_PRIORITY(P) (P >= MIN_PRIORITY && P <= MAX_PRIORITY) + +// Constants +#define MAX_PRINTER_NAME 220 +#define SHD_WIN2003_SIGNATURE 0x4968 + +// Function pointers +typedef BOOL (WINAPI *PClosePrintProcessor)(HANDLE); +typedef BOOL (WINAPI *PControlPrintProcessor)(HANDLE, DWORD); +typedef BOOL (WINAPI *PEnumPrintProcessorDatatypesW)(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD, LPDWORD); +typedef DWORD (WINAPI *PGetPrintProcessorCapabilities)(LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD); +typedef HANDLE (WINAPI *POpenPrintProcessor)(LPWSTR, PPRINTPROCESSOROPENDATA); +typedef BOOL (WINAPI *PPrintDocumentOnPrintProcessor)(HANDLE, LPWSTR); +typedef LPMONITOREX(WINAPI *PInitializePrintMonitor)(PWSTR); +typedef LPMONITOR2(WINAPI *PInitializePrintMonitor2)(PMONITORINIT, PHANDLE); + +// Forward declarations +typedef struct _LOCAL_HANDLE LOCAL_HANDLE, *PLOCAL_HANDLE; +typedef struct _LOCAL_JOB LOCAL_JOB, *PLOCAL_JOB; +typedef struct _LOCAL_PORT LOCAL_PORT, *PLOCAL_PORT; +typedef struct _LOCAL_PORT_HANDLE LOCAL_PORT_HANDLE, *PLOCAL_PORT_HANDLE; +typedef struct _LOCAL_PRINT_MONITOR LOCAL_PRINT_MONITOR, *PLOCAL_PRINT_MONITOR; +typedef struct _LOCAL_PRINT_PROCESSOR LOCAL_PRINT_PROCESSOR, *PLOCAL_PRINT_PROCESSOR; +typedef struct _LOCAL_PRINTER LOCAL_PRINTER, *PLOCAL_PRINTER; +typedef struct _LOCAL_PRINTER_HANDLE LOCAL_PRINTER_HANDLE, *PLOCAL_PRINTER_HANDLE; +typedef struct _LOCAL_XCV_HANDLE LOCAL_XCV_HANDLE, *PLOCAL_XCV_HANDLE; +typedef struct _SHD_HEADER SHD_HEADER, *PSHD_HEADER; + +// Structures +/** + * Describes a Print Monitor. + */ +struct _LOCAL_PRINT_MONITOR +{ + LIST_ENTRY Entry; + PWSTR pwszName; /** Name of the Print Monitor as read from the registry. */ + PWSTR pwszFileName; /** DLL File Name of the Print Monitor. */ + BOOL bIsLevel2; /** Whether this Print Monitor supplies an InitializePrintMonitor2 API (preferred) instead of InitializePrintMonitor. */ + PVOID pMonitor; /** For bIsLevel2 == TRUE: LPMONITOR2 pointer returned by InitializePrintMonitor2. + For bIsLevel2 == FALSE: LPMONITOREX pointer returned by InitializePrintMonitor. */ + HANDLE hMonitor; /** Only used when bIsLevel2 == TRUE: Handle returned by InitializePrintMonitor2. */ +}; + +/** + * Describes a Port handled by a Print Monitor. + */ +struct _LOCAL_PORT +{ + LIST_ENTRY Entry; + PWSTR pwszName; /** The name of the port (including the trailing colon). */ + PLOCAL_PRINT_MONITOR pPrintMonitor; /** The Print Monitor handling this port. */ + PLOCAL_JOB pNextJobToProcess; /** The Print Job that will be processed by the next created Port handle. */ +}; + +/** + * Describes a Print Processor. + */ +struct _LOCAL_PRINT_PROCESSOR +{ + LIST_ENTRY Entry; + PWSTR pwszName; + PDATATYPES_INFO_1W pDatatypesInfo1; + DWORD dwDatatypeCount; + PClosePrintProcessor pfnClosePrintProcessor; + PControlPrintProcessor pfnControlPrintProcessor; + PEnumPrintProcessorDatatypesW pfnEnumPrintProcessorDatatypesW; + PGetPrintProcessorCapabilities pfnGetPrintProcessorCapabilities; + POpenPrintProcessor pfnOpenPrintProcessor; + PPrintDocumentOnPrintProcessor pfnPrintDocumentOnPrintProcessor; +}; + +/** + * Describes a printer and manages its print jobs. + * Created once for every printer at startup. + */ +struct _LOCAL_PRINTER +{ + // This sort key must be the first element for LookupElementSkiplist to work! + PWSTR pwszPrinterName; + + DWORD dwAttributes; + DWORD dwStatus; + PWSTR pwszPrinterDriver; + PWSTR pwszDescription; + PWSTR pwszDefaultDatatype; + PDEVMODEW pDefaultDevMode; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + PLOCAL_PORT pPort; + SKIPLIST JobList; +}; + +/** + * Describes an entire print job associated to a specific printer through the Printer member. + * Created with every valid call to LocalStartDocPrinter. + */ +struct _LOCAL_JOB +{ + // This sort key must be the first element for LookupElementSkiplist to work! + DWORD dwJobID; /** Internal and external ID of this Job */ + + BOOL bAddedJob : 1; /** Whether AddJob has already been called on this Job. */ + HANDLE hPrintProcessor; /** Handle returned by OpenPrintProcessor while the Job is printing. */ + PLOCAL_PRINTER pPrinter; /** Associated Printer to this Job */ + PLOCAL_PRINT_PROCESSOR pPrintProcessor; /** Associated Print Processor to this Job */ + DWORD dwPriority; /** Priority of this Job from MIN_PRIORITY to MAX_PRIORITY, default being DEF_PRIORITY */ + SYSTEMTIME stSubmitted; /** Time of the submission of this Job */ + PWSTR pwszUserName; /** Optional; User that submitted the Job */ + PWSTR pwszNotifyName; /** Optional; User that shall be notified about the status of the Job */ + PWSTR pwszDocumentName; /** Optional; Name of the Document that is printed */ + PWSTR pwszDatatype; /** Datatype of the Document */ + PWSTR pwszOutputFile; /** Output File to spool the Job to */ + PWSTR pwszPrintProcessorParameters; /** Optional; Parameters for the chosen Print Processor */ + PWSTR pwszStatus; /** Optional; a Status Message for the Job */ + DWORD dwTotalPages; /** Total pages of the Document */ + DWORD dwPagesPrinted; /** Number of pages that have already been printed */ + DWORD dwStartTime; /** Earliest time in minutes since 12:00 AM UTC when this document can be printed */ + DWORD dwUntilTime; /** Latest time in minutes since 12:00 AM UTC when this document can be printed */ + DWORD dwStatus; /** JOB_STATUS_* flags of the Job */ + PWSTR pwszMachineName; /** Name of the machine that submitted the Job (prepended with two backslashes) */ + PDEVMODEW pDevMode; /** Associated Device Mode to this Job */ +}; + +/** + * Specific handle returned by LocalOpenPrinter for every valid call that opens a Printer or Print Job. + */ +struct _LOCAL_PRINTER_HANDLE +{ + BOOL bStartedDoc : 1; /** Whether StartDocPrinter has already been called. */ + HANDLE hSPLFile; /** Handle to an opened SPL file for Printer Job handles. */ + PLOCAL_PRINTER pPrinter; /** Printer associated with this handle. */ + PLOCAL_JOB pJob; /** Print Job associated with this handle. This can be the specified Job if this is a Print Job handle or the started job through LocalStartDocPrinter. */ + PWSTR pwszDatatype; /** Datatype used for newly started jobs. */ + PDEVMODEW pDevMode; /** DevMode used for newly started jobs. */ +}; + +/** + * Specific handle returned by LocalOpenPrinter for every valid call that opens a Port. + */ +struct _LOCAL_PORT_HANDLE +{ + HANDLE hPort; /** Handle returned by pfnOpenPort. */ + PLOCAL_PORT pPort; /** Port associated with this handle. */ +}; + +/** + * Specific handle returned by LocalOpenPrinter for every valid call that opens an XcvMonitor or XcvPort. + */ +struct _LOCAL_XCV_HANDLE +{ + HANDLE hXcv; /** Handle returned by pfnXcvOpenPort. */ + PLOCAL_PRINT_MONITOR pPrintMonitor; /** Print Monitor associated with this handle. */ +}; + +/** + * Describes a handle returned by LocalOpenPrinter. + * Suitable for all things that can be opened through LocalOpenPrinter. + */ +struct _LOCAL_HANDLE +{ + enum { + HandleType_Port, /** pSpecificHandle is a PLOCAL_PORT_HANDLE. */ + HandleType_Printer, /** pSpecificHandle is a PLOCAL_PRINTER_HANDLE. */ + HandleType_Xcv /** pSpecificHandle is a PLOCAL_XCV_HANDLE. */ + } + HandleType; + PVOID pSpecificHandle; +}; + +/** + * Describes the header of a print job serialized into a shadow file (.SHD) + * Documented in http://www.undocprint.org/formats/winspool/shd + * Compatible with Windows Server 2003 + */ +struct _SHD_HEADER +{ + DWORD dwSignature; + DWORD cbHeader; + WORD wStatus; + WORD wUnknown1; + DWORD dwJobID; + DWORD dwPriority; + DWORD offUserName; + DWORD offNotifyName; + DWORD offDocumentName; + DWORD offPort; + DWORD offPrinterName; + DWORD offDriverName; + DWORD offDevMode; + DWORD offPrintProcessor; + DWORD offDatatype; + DWORD offPrintProcessorParameters; + SYSTEMTIME stSubmitted; + DWORD dwStartTime; + DWORD dwUntilTime; + DWORD dwUnknown6; + DWORD dwTotalPages; + DWORD cbSecurityDescriptor; + DWORD offSecurityDescriptor; + DWORD dwUnknown3; + DWORD dwUnknown4; + DWORD dwUnknown5; + DWORD offMachineName; + DWORD dwSPLSize; +}; + +// jobs.c +extern SKIPLIST GlobalJobList; +DWORD WINAPI CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle); +void FreeJob(PLOCAL_JOB pJob); +DWORD GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput); +BOOL InitializeGlobalJobList(); +void InitializePrinterJobList(PLOCAL_PRINTER pPrinter); +BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded); +BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); +BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded); +BOOL WINAPI LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID); +BOOL WINAPI LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command); +PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath); +BOOL WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob); + +// main.c +extern const WCHAR wszCurrentEnvironment[]; +extern const DWORD cbCurrentEnvironment; +extern const WCHAR wszDefaultDocumentName[]; +extern const WCHAR* wszPrintProviderInfo[3]; +extern WCHAR wszSpoolDirectory[MAX_PATH]; +extern DWORD cchSpoolDirectory; + +// monitors.c +extern LIST_ENTRY PrintMonitorList; +PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName); +BOOL InitializePrintMonitorList(); +BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned); + +// ports.c +PLOCAL_PORT FindPort(PCWSTR pwszName); +BOOL InitializePortList(); +BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned); + +// printers.c +extern SKIPLIST PrinterList; +BOOL InitializePrinterList(); +BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); +BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault); +BOOL WINAPI LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead); +DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo); +BOOL WINAPI LocalStartPagePrinter(HANDLE hPrinter); +BOOL WINAPI LocalWritePrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, LPDWORD pcWritten); +BOOL WINAPI LocalEndPagePrinter(HANDLE hPrinter); +BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter); +BOOL WINAPI LocalClosePrinter(HANDLE hPrinter); + +// printingthread.c +DWORD WINAPI PrintingThreadProc(PLOCAL_JOB pJob); + +// printprocessors.c +BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype); +PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName); +BOOL InitializePrintProcessorList(); +BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); +BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned); +BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded); + +// tools.c +PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName); +PDEVMODEW DuplicateDevMode(PDEVMODEW pInput); + +#endif Index: win32ss/printing/providers/localspl/printers.c =================================================================== --- win32ss/printing/providers/localspl/printers.c (nonexistent) +++ win32ss/printing/providers/localspl/printers.c (working copy) @@ -0,0 +1,1303 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Printers and printing + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +// Global Variables +SKIPLIST PrinterList; + + +/** + * @name _PrinterListCompareRoutine + * + * SKIPLIST_COMPARE_ROUTINE for the Printer List. + * Does a case-insensitive comparison, because e.g. LocalOpenPrinter doesn't match the case when looking for Printers. + */ +static int WINAPI +_PrinterListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct) +{ + PLOCAL_PRINTER A = (PLOCAL_PRINTER)FirstStruct; + PLOCAL_PRINTER B = (PLOCAL_PRINTER)SecondStruct; + + return wcsicmp(A->pwszPrinterName, B->pwszPrinterName); +} + +/** + * @name InitializePrinterList + * + * Initializes a list of locally available Printers. + * The list is searchable by name and returns information about the printers, including their job queues. + * During this process, the job queues are also initialized. + */ +BOOL +InitializePrinterList() +{ + const WCHAR wszPrintersKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers"; + + DWORD cbData; + DWORD cchPrinterName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + PLOCAL_PORT pPort; + PLOCAL_PRINTER pPrinter = NULL; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + PWSTR pwszPort = NULL; + PWSTR pwszPrintProcessor = NULL; + WCHAR wszPrinterName[MAX_PRINTER_NAME + 1]; + + // Initialize an empty list for our printers. + InitializeSkiplist(&PrinterList, DllAllocSplMem, _PrinterListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem); + + // Open our printers registry key. Each subkey is a local printer there. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszPrintersKey, 0, KEY_READ, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of subkeys. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Loop through all available local printers. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubKey) + { + RegCloseKey(hSubKey); + hSubKey = NULL; + } + + if (pPrinter) + { + if (pPrinter->pDefaultDevMode) + DllFreeSplMem(pPrinter->pDefaultDevMode); + + if (pPrinter->pwszDefaultDatatype) + DllFreeSplStr(pPrinter->pwszDefaultDatatype); + + if (pPrinter->pwszDescription) + DllFreeSplStr(pPrinter->pwszDescription); + + if (pPrinter->pwszPrinterDriver) + DllFreeSplStr(pPrinter->pwszPrinterDriver); + + if (pPrinter->pwszPrinterName) + DllFreeSplStr(pPrinter->pwszPrinterName); + + DllFreeSplMem(pPrinter); + pPrinter = NULL; + } + + if (pwszPrintProcessor) + { + DllFreeSplStr(pwszPrintProcessor); + pwszPrintProcessor = NULL; + } + + // Get the name of this printer. + cchPrinterName = _countof(wszPrinterName); + dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL); + if (dwErrorCode == ERROR_MORE_DATA) + { + // This printer name exceeds the maximum length and is invalid. + continue; + } + else if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode); + continue; + } + + // Open this Printer's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, wszPrinterName, 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Printer \"%S\" with status %lu!\n", wszPrinterName, dwErrorCode); + continue; + } + + // Get the Print Processor. + pwszPrintProcessor = AllocAndRegQueryWSZ(hSubKey, L"Print Processor"); + if (!pwszPrintProcessor) + continue; + + // Try to find it in the Print Processor List. + pPrintProcessor = FindPrintProcessor(pwszPrintProcessor); + if (!pPrintProcessor) + { + ERR("Invalid Print Processor \"%S\" for Printer \"%S\"!\n", pwszPrintProcessor, wszPrinterName); + continue; + } + + // Get the Port. + pwszPort = AllocAndRegQueryWSZ(hSubKey, L"Port"); + if (!pwszPort) + continue; + + // Try to find it in the Port List. + pPort = FindPort(pwszPort); + if (!pPort) + { + ERR("Invalid Port \"%S\" for Printer \"%S\"!\n", pwszPort, wszPrinterName); + continue; + } + + // Create a new LOCAL_PRINTER structure for it. + pPrinter = DllAllocSplMem(sizeof(LOCAL_PRINTER)); + if (!pPrinter) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pPrinter->pwszPrinterName = AllocSplStr(wszPrinterName); + pPrinter->pPrintProcessor = pPrintProcessor; + pPrinter->pPort = pPort; + InitializePrinterJobList(pPrinter); + + // Get the printer driver. + pPrinter->pwszPrinterDriver = AllocAndRegQueryWSZ(hSubKey, L"Printer Driver"); + if (!pPrinter->pwszPrinterDriver) + continue; + + // Get the description. + pPrinter->pwszDescription = AllocAndRegQueryWSZ(hSubKey, L"Description"); + if (!pPrinter->pwszDescription) + continue; + + // Get the default datatype. + pPrinter->pwszDefaultDatatype = AllocAndRegQueryWSZ(hSubKey, L"Datatype"); + if (!pPrinter->pwszDefaultDatatype) + continue; + + // Verify that it's valid. + if (!FindDatatype(pPrintProcessor, pPrinter->pwszDefaultDatatype)) + { + ERR("Invalid default datatype \"%S\" for Printer \"%S\"!\n", pPrinter->pwszDefaultDatatype, wszPrinterName); + continue; + } + + // Determine the size of the DevMode. + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, NULL, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query the size of the DevMode for Printer \"%S\", status is %lu, cbData is %lu!\n", wszPrinterName, dwErrorCode, cbData); + continue; + } + + // Allocate enough memory for the DevMode. + pPrinter->pDefaultDevMode = DllAllocSplMem(cbData); + if (!pPrinter->pDefaultDevMode) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the default DevMode. + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)pPrinter->pDefaultDevMode, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query a DevMode for Printer \"%S\", status is %lu, cbData is %lu!\n", wszPrinterName, dwErrorCode, cbData); + continue; + } + + // Get the Attributes. + cbData = sizeof(DWORD); + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Attributes", NULL, NULL, (PBYTE)&pPrinter->dwAttributes, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query Attributes for Printer \"%S\", status is %lu!\n", wszPrinterName, dwErrorCode); + continue; + } + + // Get the Status. + cbData = sizeof(DWORD); + dwErrorCode = (DWORD)RegQueryValueExW(hSubKey, L"Status", NULL, NULL, (PBYTE)&pPrinter->dwStatus, &cbData); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("Couldn't query Status for Printer \"%S\", status is %lu!\n", wszPrinterName, dwErrorCode); + continue; + } + + // Add this printer to the printer list. + if (!InsertElementSkiplist(&PrinterList, pPrinter)) + { + ERR("InsertElementSkiplist failed for Printer \"%S\"!\n", pPrinter->pwszPrinterName); + goto Cleanup; + } + + // Don't let the cleanup routines free this. + pPrinter = NULL; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + if (pPrinter) + { + if (pPrinter->pDefaultDevMode) + DllFreeSplMem(pPrinter->pDefaultDevMode); + + if (pPrinter->pwszDefaultDatatype) + DllFreeSplStr(pPrinter->pwszDefaultDatatype); + + if (pPrinter->pwszDescription) + DllFreeSplStr(pPrinter->pwszDescription); + + if (pPrinter->pwszPrinterDriver) + DllFreeSplStr(pPrinter->pwszPrinterDriver); + + if (pPrinter->pwszPrinterName) + DllFreeSplStr(pPrinter->pwszPrinterName); + + DllFreeSplMem(pPrinter); + } + + if (pwszPrintProcessor) + DllFreeSplStr(pwszPrintProcessor); + + // Outside the loop + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + + +DWORD +_LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + const WCHAR wszComma[] = L","; + + DWORD cbName; + DWORD cbComment; + DWORD cbDescription; + DWORD cchComputerName = 0; + DWORD dwErrorCode; + DWORD i; + PBYTE pPrinterInfo; + PBYTE pPrinterString; + PSKIPLIST_NODE pNode; + PLOCAL_PRINTER pPrinter; + PRINTER_INFO_1W PrinterInfo1; + WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1]; + + DWORD dwOffsets[] = { + FIELD_OFFSET(PRINTER_INFO_1W, pName), + FIELD_OFFSET(PRINTER_INFO_1W, pDescription), + FIELD_OFFSET(PRINTER_INFO_1W, pComment), + MAXDWORD + }; + + if (Flags & PRINTER_ENUM_NAME) + { + if (Name) + { + // The user supplied a Computer Name (with leading double backslashes) or Print Provider Name. + // Only process what's directed at us and dismiss every other request with ERROR_INVALID_NAME. + if (Name[0] == L'\\' && Name[1] == L'\\') + { + // Prepend slashes to the computer name. + wszComputerName[0] = L'\\'; + wszComputerName[1] = L'\\'; + + // Get the local computer name for comparison. + cchComputerName = MAX_COMPUTERNAME_LENGTH + 1; + if (!GetComputerNameW(&wszComputerName[2], &cchComputerName)) + { + dwErrorCode = GetLastError(); + ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Add the leading slashes to the total length. + cchComputerName += 2; + + // Now compare this with the local computer name and reject if it doesn't match. + if (wcsicmp(&Name[2], &wszComputerName[2]) != 0) + { + dwErrorCode = ERROR_INVALID_NAME; + goto Cleanup; + } + + // Add a trailing backslash to wszComputerName, which will later be prepended in front of the printer names. + wszComputerName[cchComputerName++] = L'\\'; + wszComputerName[cchComputerName] = 0; + } + else if (wcsicmp(Name, wszPrintProviderInfo[0]) != 0) + { + // The user supplied a name that cannot be processed by the local print provider. + dwErrorCode = ERROR_INVALID_NAME; + goto Cleanup; + } + } + else + { + // The caller wants information about this Print Provider. + // spoolss packs this into an array of information about all Print Providers. + *pcbNeeded = sizeof(PRINTER_INFO_1W); + + for (i = 0; i < 3; i++) + *pcbNeeded += (wcslen(wszPrintProviderInfo[i]) + 1) * sizeof(WCHAR); + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Copy over the print processor information. + ((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0; + PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets, &pPrinterEnum[*pcbNeeded]); + *pcReturned = 1; + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + } + + // Count the required buffer size and the number of printers. + i = 0; + + for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0]) + { + pPrinter = (PLOCAL_PRINTER)pNode->Element; + + // This looks wrong, but is totally right. PRINTER_INFO_1W has three members pName, pComment and pDescription. + // But pComment equals the "Description" registry value while pDescription is concatenated out of pName and pComment. + // On top of this, the computer name is prepended to the printer name if the user supplied the local computer name during the query. + cbName = (wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR); + cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR); + cbDescription = cchComputerName * sizeof(WCHAR) + cbName + cbComment + sizeof(WCHAR); + + *pcbNeeded += sizeof(PRINTER_INFO_1W) + cchComputerName * sizeof(WCHAR) + cbName + cbComment + cbDescription; + i++; + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the strings right after the last PRINTER_INFO_1W structure. + // Due to all the required string processing, we can't just use PackStrings here :( + pPrinterInfo = pPrinterEnum; + pPrinterString = pPrinterEnum + i * sizeof(PRINTER_INFO_1W); + + // Copy over the printer information. + for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0]) + { + pPrinter = (PLOCAL_PRINTER)pNode->Element; + + // FIXME: As for now, the Flags member returns no information. + PrinterInfo1.Flags = 0; + + // Copy the printer name. + PrinterInfo1.pName = (PWSTR)pPrinterString; + CopyMemory(pPrinterString, wszComputerName, cchComputerName * sizeof(WCHAR)); + pPrinterString += cchComputerName * sizeof(WCHAR); + cbName = (wcslen(pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR); + CopyMemory(pPrinterString, pPrinter->pwszPrinterName, cbName); + pPrinterString += cbName; + + // Copy the printer comment (equals the "Description" registry value). + PrinterInfo1.pComment = (PWSTR)pPrinterString; + cbComment = (wcslen(pPrinter->pwszDescription) + 1) * sizeof(WCHAR); + CopyMemory(pPrinterString, pPrinter->pwszDescription, cbComment); + pPrinterString += cbComment; + + // Copy the description, which for PRINTER_INFO_1W has the form "Name,Comment," + PrinterInfo1.pDescription = (PWSTR)pPrinterString; + CopyMemory(pPrinterString, wszComputerName, cchComputerName * sizeof(WCHAR)); + pPrinterString += cchComputerName * sizeof(WCHAR); + CopyMemory(pPrinterString, pPrinter->pwszPrinterName, cbName - sizeof(WCHAR)); + pPrinterString += cbName - sizeof(WCHAR); + CopyMemory(pPrinterString, wszComma, sizeof(WCHAR)); + pPrinterString += sizeof(WCHAR); + CopyMemory(pPrinterString, pPrinter->pwszDescription, cbComment - sizeof(WCHAR)); + pPrinterString += cbComment - sizeof(WCHAR); + CopyMemory(pPrinterString, wszComma, sizeof(wszComma)); + pPrinterString += sizeof(wszComma); + + // Finally copy the structure and advance to the next one in the output buffer. + CopyMemory(pPrinterInfo, &PrinterInfo1, sizeof(PRINTER_INFO_1W)); + pPrinterInfo += sizeof(PRINTER_INFO_1W); + } + + *pcReturned = i; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + return dwErrorCode; +} + +BOOL WINAPI +LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + DWORD dwErrorCode; + + // Do no sanity checks here. This is verified by localspl_apitest! + + // Begin counting. + *pcbNeeded = 0; + *pcReturned = 0; + + // Think positive :) + // Treat it as success if the caller queried no information and we don't need to return any. + dwErrorCode = ERROR_SUCCESS; + + if (Flags & PRINTER_ENUM_LOCAL) + { + // The function behaves quite differently for each level. + if (Level == 1) + { + dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned); + } + else + { + // TODO: Handle other levels. + // The caller supplied an invalid level. + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + } + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault) +{ + BOOL bReturnValue; + DWORD cchComputerName; + DWORD cchFirstParameter; + DWORD dwErrorCode; + DWORD dwJobID; + HANDLE hExternalHandle; + PWSTR p = lpPrinterName; + PWSTR pwszFirstParameter = NULL; + PWSTR pwszSecondParameter = NULL; + PLOCAL_JOB pJob; + PLOCAL_HANDLE pHandle = NULL; + PLOCAL_PORT pPort; + PLOCAL_PORT_HANDLE pPortHandle = NULL; + PLOCAL_PRINT_MONITOR pPrintMonitor; + PLOCAL_PRINTER pPrinter; + PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL; + PLOCAL_XCV_HANDLE pXcvHandle = NULL; + WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1]; + WCHAR wszFullPath[MAX_PATH]; + + // TODO: lpPrinterName == NULL is supported and means access to the local printer server. + // Not sure yet if that is passed down to localspl.dll or processed in advance. + + // Sanity checks + if (!lpPrinterName || !phPrinter) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + *phPrinter = NULL; + + // Skip any server name in the first parameter. + // Does lpPrinterName begin with two backslashes to indicate a server name? + if (lpPrinterName[0] == L'\\' && lpPrinterName[1] == L'\\') + { + // Skip these two backslashes. + lpPrinterName += 2; + + // Look for the closing backslash. + p = wcschr(lpPrinterName, L'\\'); + if (!p) + { + // We didn't get a proper server name. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Get the local computer name for comparison. + cchComputerName = _countof(wszComputerName); + if (!GetComputerNameW(wszComputerName, &cchComputerName)) + { + dwErrorCode = GetLastError(); + ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Now compare this string excerpt with the local computer name. + // The input parameter may not be writable, so we can't null-terminate the input string at this point. + // This print provider only supports local printers, so both strings have to match. + if (p - lpPrinterName != cchComputerName || _wcsnicmp(lpPrinterName, wszComputerName, cchComputerName) != 0) + { + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // We have checked the server name and don't need it anymore. + lpPrinterName = p + 1; + } + + // Look for a comma. If it exists, it indicates the end of the first parameter. + pwszSecondParameter = wcschr(lpPrinterName, L','); + if (pwszSecondParameter) + cchFirstParameter = pwszSecondParameter - p; + else + cchFirstParameter = wcslen(lpPrinterName); + + // We must have at least one parameter. + if (!cchFirstParameter && !pwszSecondParameter) + { + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Do we have a first parameter? + if (cchFirstParameter) + { + // Yes, extract it. + // No null-termination is necessary here, because DllAllocSplMem returns a zero-initialized buffer. + pwszFirstParameter = DllAllocSplMem((cchFirstParameter + 1) * sizeof(WCHAR)); + CopyMemory(pwszFirstParameter, lpPrinterName, cchFirstParameter * sizeof(WCHAR)); + } + + // Do we have a second parameter? + if (pwszSecondParameter) + { + // Yes, skip the comma at the beginning. + ++pwszSecondParameter; + + // Skip whitespace as well. + while (*pwszSecondParameter == L' ') + ++pwszSecondParameter; + } + + // Create a new handle. + pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE)); + if (!pHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Now we can finally check the type of handle actually requested. + if (pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Port", 4) == 0) + { + // The caller wants a port handle and provided a string like: + // "LPT1:, Port" + // "\\COMPUTERNAME\LPT1:, Port" + + // Look for this port in our Print Monitor Port list. + pPort = FindPort(pwszFirstParameter); + if (!pPort) + { + // The supplied port is unknown to all our Print Monitors. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + pPrintMonitor = pPort->pPrintMonitor; + + // Call the monitor's OpenPort function. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnOpenPort(pPrintMonitor->hMonitor, pwszFirstParameter, &hExternalHandle); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnOpenPort(pwszFirstParameter, &hExternalHandle); + + if (!bReturnValue) + { + // The OpenPort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // Create a new LOCAL_PORT_HANDLE. + pPortHandle = DllAllocSplMem(sizeof(LOCAL_PORT_HANDLE)); + if (!pPortHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pPortHandle->hPort = hExternalHandle; + pPortHandle->pPort = pPort; + + // Return the Port handle through our general handle. + pHandle->HandleType = HandleType_Port; + pHandle->pSpecificHandle = pPortHandle; + } + else if (!pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Xcv", 3) == 0) + { + // The caller wants an Xcv handle and provided a string like: + // ", XcvMonitor Local Port" + // "\\COMPUTERNAME\, XcvMonitor Local Port" + // ", XcvPort LPT1:" + // "\\COMPUTERNAME\, XcvPort LPT1:" + + // Skip the "Xcv" string. + pwszSecondParameter += 3; + + // Is XcvMonitor or XcvPort requested? + if (wcsncmp(pwszSecondParameter, L"Monitor ", 8) == 0) + { + // Skip the "Monitor " string. + pwszSecondParameter += 8; + + // Look for this monitor in our Print Monitor list. + pPrintMonitor = FindPrintMonitor(pwszSecondParameter); + if (!pPrintMonitor) + { + // The caller supplied a non-existing Monitor name. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + } + else if (wcsncmp(pwszSecondParameter, L"Port ", 5) == 0) + { + // Skip the "Port " string. + pwszSecondParameter += 5; + + // Look for this port in our Print Monitor Port list. + pPort = FindPort(pwszFirstParameter); + if (!pPort) + { + // The supplied port is unknown to all our Print Monitors. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + pPrintMonitor = pPort->pPrintMonitor; + } + else + { + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Call the monitor's XcvOpenPort function. + if (pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvOpenPort(pPrintMonitor->hMonitor, pwszSecondParameter, SERVER_EXECUTE, &hExternalHandle); + else + bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvOpenPort(pwszSecondParameter, SERVER_EXECUTE, &hExternalHandle); + + if (!bReturnValue) + { + // The XcvOpenPort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // Create a new LOCAL_XCV_HANDLE. + pXcvHandle = DllAllocSplMem(sizeof(LOCAL_XCV_HANDLE)); + if (!pXcvHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pXcvHandle->hXcv = hExternalHandle; + pXcvHandle->pPrintMonitor = pPrintMonitor; + + // Return the Xcv handle through our general handle. + pHandle->HandleType = HandleType_Xcv; + pHandle->pSpecificHandle = pXcvHandle; + } + else + { + // The caller wants a Printer or Printer Job handle and provided a string like: + // "HP DeskJet" + // "\\COMPUTERNAME\HP DeskJet" + // "HP DeskJet, Job 5" + // "\\COMPUTERNAME\HP DeskJet, Job 5" + + // Retrieve the printer from the list. + pPrinter = LookupElementSkiplist(&PrinterList, &pwszFirstParameter, NULL); + if (!pPrinter) + { + // The printer does not exist. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Create a new LOCAL_PRINTER_HANDLE. + pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE)); + if (!pPrinterHandle) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + pPrinterHandle->hSPLFile = INVALID_HANDLE_VALUE; + pPrinterHandle->pPrinter = pPrinter; + + // Check if a datatype was given. + if (pDefault && pDefault->pDatatype) + { + // Use the datatype if it's valid. + if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype)) + { + dwErrorCode = ERROR_INVALID_DATATYPE; + goto Cleanup; + } + + pPrinterHandle->pwszDatatype = AllocSplStr(pDefault->pDatatype); + } + else + { + // Use the default datatype. + pPrinterHandle->pwszDatatype = AllocSplStr(pPrinter->pwszDefaultDatatype); + } + + // Check if a DevMode was given, otherwise use the default. + if (pDefault && pDefault->pDevMode) + pPrinterHandle->pDevMode = DuplicateDevMode(pDefault->pDevMode); + else + pPrinterHandle->pDevMode = DuplicateDevMode(pPrinter->pDefaultDevMode); + + // Check if the caller wants a handle to an existing Print Job. + if (pwszSecondParameter) + { + // The "Job " string has to follow now. + if (wcsncmp(pwszSecondParameter, L"Job ", 4) != 0) + { + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Skip the "Job " string. + pwszSecondParameter += 4; + + // Skip even more whitespace. + while (*pwszSecondParameter == ' ') + ++pwszSecondParameter; + + // Finally extract the desired Job ID. + dwJobID = wcstoul(pwszSecondParameter, NULL, 10); + if (!IS_VALID_JOB_ID(dwJobID)) + { + // The user supplied an invalid Job ID. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Look for this job in the Global Job List. + pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL); + if (!pJob || pJob->pPrinter != pPrinter) + { + // The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name. + dwErrorCode = ERROR_INVALID_PRINTER_NAME; + goto Cleanup; + } + + // Try to open its SPL file. + GetJobFilePath(L"SPL", dwJobID, wszFullPath); + pPrinterHandle->hSPLFile = CreateFileW(wszFullPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); + if (pPrinterHandle->hSPLFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = GetLastError(); + ERR("CreateFileW failed with error %lu for \"%S\"!", dwErrorCode, wszFullPath); + goto Cleanup; + } + + // Associate the job to our Printer Handle, but don't set bStartedDoc. + // This prevents the caller from doing further StartDocPrinter, WritePrinter, etc. calls on it. + pPrinterHandle->pJob = pJob; + } + + // Return the Printer handle through our general handle. + pHandle->HandleType = HandleType_Printer; + pHandle->pSpecificHandle = pPrinterHandle; + } + + // We were successful! Return the handle. + *phPrinter = (HANDLE)pHandle; + dwErrorCode = ERROR_SUCCESS; + + // Don't let the cleanup routines free this. + pHandle = NULL; + pPrinterHandle = NULL; + +Cleanup: + if (pHandle) + DllFreeSplMem(pHandle); + + if (pPrinterHandle) + { + if (pPrinterHandle->pwszDatatype) + DllFreeSplStr(pPrinterHandle->pwszDatatype); + + if (pPrinterHandle->pDevMode) + DllFreeSplMem(pPrinterHandle->pDevMode); + + DllFreeSplMem(pPrinterHandle); + } + + if (pwszFirstParameter) + DllFreeSplMem(pwszFirstParameter); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead) +{ + BOOL bReturnValue; + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PORT_HANDLE pPortHandle; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Port handles are an entirely different thing. + if (pHandle->HandleType == HandleType_Port) + { + pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle; + + // Call the monitor's ReadPort function. + if (pPortHandle->pPort->pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead); + else + bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnReadPort(pPortHandle->hPort, pBuf, cbBuf, pNoBytesRead); + + if (!bReturnValue) + { + // The ReadPort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + // The remaining function deals with Printer handles only. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // ReadPrinter needs an opened SPL file to work. + // This only works if a Printer Job Handle was requested in OpenPrinter. + if (pPrinterHandle->hSPLFile == INVALID_HANDLE_VALUE) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Pass the parameters to ReadFile. + if (!ReadFile(pPrinterHandle->hSPLFile, pBuf, cbBuf, pNoBytesRead, NULL)) + { + dwErrorCode = GetLastError(); + ERR("ReadFile failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +DWORD WINAPI +LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + BOOL bReturnValue; + DWORD dwErrorCode; + DWORD dwReturnValue = 0; + PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo; + PLOCAL_JOB pJob; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PORT_HANDLE pPortHandle; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Port handles are an entirely different thing. + if (pHandle->HandleType == HandleType_Port) + { + pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle; + + // This call should come from a Print Processor and the job this port is going to print was assigned to us before opening the Print Processor. + // Claim it exclusively for this port handle. + pJob = pPortHandle->pPort->pNextJobToProcess; + pPortHandle->pPort->pNextJobToProcess = NULL; + ASSERT(pJob); + + // Call the monitor's StartDocPort function. + if (pPortHandle->pPort->pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo); + else + bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnStartDocPort(pPortHandle->hPort, pJob->pPrinter->pwszPrinterName, pJob->dwJobID, Level, pDocInfo); + + if (!bReturnValue) + { + // The StartDocPort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + dwReturnValue = pJob->dwJobID; + goto Cleanup; + } + + // The remaining function deals with Printer handles only. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + if (!pDocInfo1) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // pJob may already be occupied if this is a Print Job handle. In this case, StartDocPrinter has to fail. + if (pPrinterHandle->pJob) + { + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Check the validity of the datatype if we got one. + if (pDocInfo1->pDatatype && !FindDatatype(pPrinterHandle->pJob->pPrintProcessor, pDocInfo1->pDatatype)) + { + dwErrorCode = ERROR_INVALID_DATATYPE; + goto Cleanup; + } + + // Check if this is the right document information level. + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // All requirements are met - create a new job. + dwErrorCode = CreateJob(pPrinterHandle); + if (dwErrorCode != ERROR_SUCCESS) + goto Cleanup; + + // Use any given datatype. + if (pDocInfo1->pDatatype && !ReallocSplStr(&pPrinterHandle->pJob->pwszDatatype, pDocInfo1->pDatatype)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + // Use any given document name. + if (pDocInfo1->pDocName && !ReallocSplStr(&pPrinterHandle->pJob->pwszDocumentName, pDocInfo1->pDocName)) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + dwReturnValue = pPrinterHandle->pJob->dwJobID; + +Cleanup: + SetLastError(dwErrorCode); + return dwReturnValue; +} + +BOOL WINAPI +LocalStartPagePrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Sanity checks. + if (!pHandle || pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // We require StartDocPrinter or AddJob to be called first. + if (!pPrinterHandle->bStartedDoc) + { + dwErrorCode = ERROR_SPL_NO_STARTDOC; + goto Cleanup; + } + + // Increase the page count. + ++pPrinterHandle->pJob->dwTotalPages; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalWritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten) +{ + BOOL bReturnValue; + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PORT_HANDLE pPortHandle; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Port handles are an entirely different thing. + if (pHandle->HandleType == HandleType_Port) + { + pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle; + + // Call the monitor's WritePort function. + if (pPortHandle->pPort->pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten); + else + bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnWritePort(pPortHandle->hPort, pBuf, cbBuf, pcWritten); + + if (!bReturnValue) + { + // The WritePort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + // The remaining function deals with Printer handles only. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // We require StartDocPrinter or AddJob to be called first. + if (!pPrinterHandle->bStartedDoc) + { + dwErrorCode = ERROR_SPL_NO_STARTDOC; + goto Cleanup; + } + + // TODO: This function is only called when doing non-spooled printing. + // This needs to be investigated further. We can't just use pPrinterHandle->hSPLFile here, because that's currently reserved for Printer Job handles (see LocalReadPrinter). +#if 0 + // Pass the parameters to WriteFile. + if (!WriteFile(SOME_SPOOL_FILE_HANDLE, pBuf, cbBuf, pcWritten, NULL)) + { + dwErrorCode = GetLastError(); + ERR("WriteFile failed with error %lu!\n", GetLastError()); + goto Cleanup; + } +#endif + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEndPagePrinter(HANDLE hPrinter) +{ + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + + // Sanity checks. + if (!pHandle || pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // This function doesn't do anything else for now. + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalEndDocPrinter(HANDLE hPrinter) +{ + BOOL bReturnValue; + DWORD dwErrorCode; + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PORT_HANDLE pPortHandle; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + + // Sanity checks. + if (!pHandle) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + // Port handles are an entirely different thing. + if (pHandle->HandleType == HandleType_Port) + { + pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle; + + // Call the monitor's EndDocPort function. + if (pPortHandle->pPort->pPrintMonitor->bIsLevel2) + bReturnValue = ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnEndDocPort(pPortHandle->hPort); + else + bReturnValue = ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnEndDocPort(pPortHandle->hPort); + + if (!bReturnValue) + { + // The EndDocPort function failed. Return its last error. + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + goto Cleanup; + } + + // The remaining function deals with Printer handles only. + if (pHandle->HandleType != HandleType_Printer) + { + dwErrorCode = ERROR_INVALID_HANDLE; + goto Cleanup; + } + + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // We require StartDocPrinter or AddJob to be called first. + if (!pPrinterHandle->bStartedDoc) + { + dwErrorCode = ERROR_SPL_NO_STARTDOC; + goto Cleanup; + } + + // TODO: Something like ScheduleJob + + // Finish the job. + pPrinterHandle->bStartedDoc = FALSE; + pPrinterHandle->pJob = NULL; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +BOOL WINAPI +LocalClosePrinter(HANDLE hPrinter) +{ + PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter; + PLOCAL_PORT_HANDLE pPortHandle; + PLOCAL_PRINTER_HANDLE pPrinterHandle; + PLOCAL_XCV_HANDLE pXcvHandle; + + if (!pHandle) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + if (pHandle->HandleType == HandleType_Port) + { + pPortHandle = (PLOCAL_PORT_HANDLE)pHandle->pSpecificHandle; + + // Call the monitor's ClosePort function. + if (pPortHandle->pPort->pPrintMonitor->bIsLevel2) + ((PMONITOR2)pPortHandle->pPort->pPrintMonitor->pMonitor)->pfnClosePort(pPortHandle->hPort); + else + ((LPMONITOREX)pPortHandle->pPort->pPrintMonitor->pMonitor)->Monitor.pfnClosePort(pPortHandle->hPort); + } + else if (pHandle->HandleType == HandleType_Printer) + { + pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle; + + // Terminate any started job. + if (pPrinterHandle->pJob) + FreeJob(pPrinterHandle->pJob); + + // Free memory for the fields. + DllFreeSplMem(pPrinterHandle->pDevMode); + DllFreeSplStr(pPrinterHandle->pwszDatatype); + } + else if (pHandle->HandleType == HandleType_Xcv) + { + pXcvHandle = (PLOCAL_XCV_HANDLE)pHandle->pSpecificHandle; + + // Call the monitor's XcvClosePort function. + if (pXcvHandle->pPrintMonitor->bIsLevel2) + ((PMONITOR2)pXcvHandle->pPrintMonitor->pMonitor)->pfnXcvClosePort(pXcvHandle->hXcv); + else + ((LPMONITOREX)pXcvHandle->pPrintMonitor->pMonitor)->Monitor.pfnXcvClosePort(pXcvHandle->hXcv); + } + + // Free memory for the handle and the specific handle. + DllFreeSplMem(pHandle->pSpecificHandle); + DllFreeSplMem(pHandle); + + return TRUE; +} Index: win32ss/printing/providers/localspl/printingthread.c =================================================================== --- win32ss/printing/providers/localspl/printingthread.c (nonexistent) +++ win32ss/printing/providers/localspl/printingthread.c (working copy) @@ -0,0 +1,127 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Implementation of the Thread that actually performs the printing process + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +DWORD WINAPI +PrintingThreadProc(PLOCAL_JOB pJob) +{ + const DWORD cchMaxJobIdDigits = 5; // Job ID is limited to 5 decimal digits, see IS_VALID_JOB_ID + const WCHAR wszJobAppendix[] = L", Job "; + const DWORD cchJobAppendix = _countof(wszJobAppendix) - 1; + const WCHAR wszPortAppendix[] = L", Port"; + + DWORD cchPortName; + DWORD cchPrinterName; + DWORD dwErrorCode; + HANDLE hPrintProcessor = NULL; + PLOCAL_PRINT_PROCESSOR pPrintProcessor = pJob->pPrintProcessor; + PRINTPROCESSOROPENDATA OpenData; + PWSTR pwszPrinterAndJob = NULL; + PWSTR pwszPrinterPort = NULL; + PWSTR pwszSPLFile = NULL; + + // Prepare the pPrinterName parameter. + // This is the string for LocalOpenPrinter to open a port (e.g. "LPT1:, Port"). + cchPortName = wcslen(pJob->pPrinter->pPort->pwszName); + pwszPrinterPort = DllAllocSplMem(cchPortName * sizeof(WCHAR) + sizeof(wszPortAppendix)); + if (!pwszPrinterPort) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszPrinterPort, pJob->pPrinter->pPort->pwszName, cchPortName * sizeof(WCHAR)); + CopyMemory(&pwszPrinterPort[cchPortName], wszPortAppendix, sizeof(wszPortAppendix)); + + // Prepare the pPrintProcessorOpenData parameter. + OpenData.JobId = pJob->dwJobID; + OpenData.pDatatype = pJob->pwszDatatype; + OpenData.pDevMode = pJob->pDevMode; + OpenData.pDocumentName = pJob->pwszDocumentName; + OpenData.pOutputFile = NULL; + OpenData.pParameters = pJob->pwszPrintProcessorParameters; + OpenData.pPrinterName = pJob->pPrinter->pwszPrinterName; + + // Associate our job to the port. The next port handle created through LocalOpenPrinter will pick this up. + // LocalStartDocPrinter needs this information to call StartDocPort of the Print Monitor, but as the parameters + // for LocalOpenPrinter and LocalStartDocPrinter are fixed, we can only pass over the information this way. + pJob->pPrinter->pPort->pNextJobToProcess = pJob; + + // Open a handle to the Print Processor. + hPrintProcessor = pPrintProcessor->pfnOpenPrintProcessor(pwszPrinterPort, &OpenData); + if (!hPrintProcessor) + { + dwErrorCode = GetLastError(); + ERR("OpenPrintProcessor failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Let other functions use the Print Processor as well while it's opened. + pJob->hPrintProcessor = hPrintProcessor; + + // Prepare the pDocumentName parameter. + cchPrinterName = wcslen(OpenData.pPrinterName); + pwszPrinterAndJob = DllAllocSplMem((cchPrinterName + cchJobAppendix + cchMaxJobIdDigits + 1) * sizeof(WCHAR)); + if (!pwszPrinterAndJob) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszPrinterAndJob, OpenData.pPrinterName, cchPrinterName * sizeof(WCHAR)); + CopyMemory(&pwszPrinterAndJob[cchPrinterName], wszJobAppendix, cchJobAppendix * sizeof(WCHAR)); + _ultow(OpenData.JobId, &pwszPrinterAndJob[cchPrinterName + cchJobAppendix], 10); + + // Printing starts here. + pJob->dwStatus |= JOB_STATUS_PRINTING; + + // Print the document. + // Note that pJob is freed after this function, so we may not access it anymore. + if (!pPrintProcessor->pfnPrintDocumentOnPrintProcessor(hPrintProcessor, pwszPrinterAndJob)) + { + dwErrorCode = GetLastError(); + ERR("PrintDocumentOnPrintProcessor failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Close the Print Processor. + pPrintProcessor->pfnClosePrintProcessor(hPrintProcessor); + hPrintProcessor = NULL; + + // Delete the spool file. + pwszSPLFile = DllAllocSplMem(GetJobFilePath(L"SPL", 0, NULL)); + if (!pwszSPLFile) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + GetJobFilePath(L"SPL", OpenData.JobId, pwszSPLFile); + DeleteFileW(pwszSPLFile); + + // We were successful! + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (hPrintProcessor) + pPrintProcessor->pfnClosePrintProcessor(hPrintProcessor); + + if (pwszPrinterPort) + DllFreeSplMem(pwszPrinterPort); + + if (pwszPrinterAndJob) + DllFreeSplMem(pwszPrinterAndJob); + + if (pwszSPLFile) + DllFreeSplMem(pwszSPLFile); + + return dwErrorCode; +} Index: win32ss/printing/providers/localspl/printprocessors.c =================================================================== --- win32ss/printing/providers/localspl/printprocessors.c (nonexistent) +++ win32ss/printing/providers/localspl/printprocessors.c (working copy) @@ -0,0 +1,696 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Functions related to Print Processors + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + + +// Local Variables +static LIST_ENTRY _PrintProcessorList; + +/** + * @name _OpenEnvironment + * + * Checks a supplied pEnvironment variable for validity and opens its registry key. + * + * @param pEnvironment + * The pEnvironment variable to check. Can be NULL to use the current environment. + * + * @param hKey + * On success, this variable will contain a HKEY to the opened registry key of the environment. + * You can use it for further tasks and have to close it with RegCloseKey. + * + * @return + * A Windows Error Code indicating success or failure. + */ +static DWORD +_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey) +{ + const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\"; + const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1; + + DWORD cchEnvironment; + DWORD dwErrorCode; + PWSTR pwszEnvironmentKey = NULL; + + // Use the current environment if none was supplied. + if (!pEnvironment) + pEnvironment = wszCurrentEnvironment; + + // Construct the registry key of the demanded environment. + cchEnvironment = wcslen(pEnvironment); + pwszEnvironmentKey = DllAllocSplMem((cchEnvironmentsKey + cchEnvironment + 1) * sizeof(WCHAR)); + if (!pwszEnvironmentKey) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + CopyMemory(pwszEnvironmentKey, wszEnvironmentsKey, cchEnvironmentsKey * sizeof(WCHAR)); + CopyMemory(&pwszEnvironmentKey[cchEnvironmentsKey], pEnvironment, (cchEnvironment + 1) * sizeof(WCHAR)); + + // Open the registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey); + if (dwErrorCode == ERROR_FILE_NOT_FOUND) + { + dwErrorCode = ERROR_INVALID_ENVIRONMENT; + goto Cleanup; + } + else if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + +Cleanup: + if (pwszEnvironmentKey) + DllFreeSplMem(pwszEnvironmentKey); + + return dwErrorCode; +} + +BOOL +FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype) +{ + DWORD i; + PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1; + + if (!pwszDatatype) + return FALSE; + + for (i = 0; i < pPrintProcessor->dwDatatypeCount; i++) + { + if (wcsicmp(pCurrentDatatype->pName, pwszDatatype) == 0) + return TRUE; + + ++pCurrentDatatype; + } + + return FALSE; +} + +PLOCAL_PRINT_PROCESSOR +FindPrintProcessor(PCWSTR pwszName) +{ + PLIST_ENTRY pEntry; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + + if (!pwszName) + return NULL; + + for (pEntry = _PrintProcessorList.Flink; pEntry != &_PrintProcessorList; pEntry = pEntry->Flink) + { + pPrintProcessor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_PROCESSOR, Entry); + + if (wcsicmp(pPrintProcessor->pwszName, pwszName) == 0) + return pPrintProcessor; + } + + return NULL; +} + +/** + * @name InitializePrintProcessorList + * + * Initializes a singly linked list of locally available Print Processors. + */ +BOOL +InitializePrintProcessorList() +{ + DWORD cbDatatypes; + DWORD cbFileName; + DWORD cchPrintProcessorPath; + DWORD cchMaxSubKey; + DWORD cchPrintProcessorName; + DWORD dwErrorCode; + DWORD dwSubKeys; + DWORD i; + HINSTANCE hinstPrintProcessor; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + HKEY hSubSubKey = NULL; + PLOCAL_PRINT_PROCESSOR pPrintProcessor = NULL; + WCHAR wszFileName[MAX_PATH]; + WCHAR wszPrintProcessorPath[MAX_PATH]; + + // Initialize an empty list for our Print Processors. + InitializeListHead(&_PrintProcessorList); + + // Prepare the path to the Print Processor directory. + if (!LocalGetPrintProcessorDirectory(NULL, NULL, 1, (PBYTE)wszPrintProcessorPath, sizeof(wszPrintProcessorPath), &cchPrintProcessorPath)) + { + dwErrorCode = GetLastError(); + goto Cleanup; + } + + // LocalGetPrintProcessorDirectory returns the number of copied bytes. Convert this into a number of characters without the terminating null-character. + cchPrintProcessorPath /= sizeof(WCHAR); + --cchPrintProcessorPath; + + // Append a trailing backslash. + wszPrintProcessorPath[cchPrintProcessorPath] = L'\\'; + ++cchPrintProcessorPath; + + // Open the environment registry key. + dwErrorCode = _OpenEnvironment(NULL, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Open the "Print Processors" subkey. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Processors and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Loop through all available local Print Processors. + for (i = 0; i < dwSubKeys; i++) + { + // Cleanup tasks from the previous run + if (hSubSubKey) + { + RegCloseKey(hSubSubKey); + hSubSubKey = NULL; + } + + if (pPrintProcessor) + { + if (pPrintProcessor->pwszName) + DllFreeSplStr(pPrintProcessor->pwszName); + + if (pPrintProcessor->pDatatypesInfo1) + DllFreeSplMem(pPrintProcessor->pDatatypesInfo1); + + DllFreeSplMem(pPrintProcessor); + pPrintProcessor = NULL; + } + + // Create a new LOCAL_PRINT_PROCESSOR structure for it. + pPrintProcessor = DllAllocSplMem(sizeof(LOCAL_PRINT_PROCESSOR)); + if (!pPrintProcessor) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Allocate memory for the Print Monitor Name. + pPrintProcessor->pwszName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pPrintProcessor->pwszName) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Get the name of this Print Processor. + cchPrintProcessorName = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pPrintProcessor->pwszName, &cchPrintProcessorName, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed with status %ld!\n", dwErrorCode); + continue; + } + + // Open this Print Processor's registry key. + dwErrorCode = (DWORD)RegOpenKeyExW(hSubKey, pPrintProcessor->pwszName, 0, KEY_READ, &hSubSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed for Print Processor \"%S\" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode); + continue; + } + + // Get the file name of the Print Processor. + cbFileName = sizeof(wszFileName); + dwErrorCode = (DWORD)RegQueryValueExW(hSubSubKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed for Print Processor \"%S\" with status %lu!\n", pPrintProcessor->pwszName, dwErrorCode); + continue; + } + + // Verify that our buffer is large enough. + if (cchPrintProcessorPath + cbFileName / sizeof(WCHAR) > MAX_PATH) + { + ERR("Print Processor directory \"%S\" for Print Processor \"%S\" is too long!\n", wszFileName, pPrintProcessor->pwszName); + continue; + } + + // Construct the full path to the Print Processor. + CopyMemory(&wszPrintProcessorPath[cchPrintProcessorPath], wszFileName, cbFileName); + + // Try to load it. + hinstPrintProcessor = LoadLibraryW(wszPrintProcessorPath); + if (!hinstPrintProcessor) + { + ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", wszPrintProcessorPath, GetLastError()); + continue; + } + + // Get and verify all its function pointers. + pPrintProcessor->pfnClosePrintProcessor = (PClosePrintProcessor)GetProcAddress(hinstPrintProcessor, "ClosePrintProcessor"); + if (!pPrintProcessor->pfnClosePrintProcessor) + { + ERR("Print Processor \"%S\" exports no ClosePrintProcessor!\n", wszPrintProcessorPath); + continue; + } + + pPrintProcessor->pfnControlPrintProcessor = (PControlPrintProcessor)GetProcAddress(hinstPrintProcessor, "ControlPrintProcessor"); + if (!pPrintProcessor->pfnControlPrintProcessor) + { + ERR("Print Processor \"%S\" exports no ControlPrintProcessor!\n", wszPrintProcessorPath); + continue; + } + + pPrintProcessor->pfnEnumPrintProcessorDatatypesW = (PEnumPrintProcessorDatatypesW)GetProcAddress(hinstPrintProcessor, "EnumPrintProcessorDatatypesW"); + if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW) + { + ERR("Print Processor \"%S\" exports no EnumPrintProcessorDatatypesW!\n", wszPrintProcessorPath); + continue; + } + + pPrintProcessor->pfnGetPrintProcessorCapabilities = (PGetPrintProcessorCapabilities)GetProcAddress(hinstPrintProcessor, "GetPrintProcessorCapabilities"); + if (!pPrintProcessor->pfnGetPrintProcessorCapabilities) + { + ERR("Print Processor \"%S\" exports no GetPrintProcessorCapabilities!\n", wszPrintProcessorPath); + continue; + } + + pPrintProcessor->pfnOpenPrintProcessor = (POpenPrintProcessor)GetProcAddress(hinstPrintProcessor, "OpenPrintProcessor"); + if (!pPrintProcessor->pfnOpenPrintProcessor) + { + ERR("Print Processor \"%S\" exports no OpenPrintProcessor!\n", wszPrintProcessorPath); + continue; + } + + pPrintProcessor->pfnPrintDocumentOnPrintProcessor = (PPrintDocumentOnPrintProcessor)GetProcAddress(hinstPrintProcessor, "PrintDocumentOnPrintProcessor"); + if (!pPrintProcessor->pfnPrintDocumentOnPrintProcessor) + { + ERR("Print Processor \"%S\" exports no PrintDocumentOnPrintProcessor!\n", wszPrintProcessorPath); + continue; + } + + // Get all supported datatypes. + pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0, &cbDatatypes, &pPrintProcessor->dwDatatypeCount); + pPrintProcessor->pDatatypesInfo1 = DllAllocSplMem(cbDatatypes); + if (!pPrintProcessor->pDatatypesInfo1) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, (PBYTE)pPrintProcessor->pDatatypesInfo1, cbDatatypes, &cbDatatypes, &pPrintProcessor->dwDatatypeCount)) + { + ERR("EnumPrintProcessorDatatypesW failed for Print Processor \"%S\" with error %lu!\n", wszPrintProcessorPath, GetLastError()); + continue; + } + + // Add the Print Processor to the list. + InsertTailList(&_PrintProcessorList, &pPrintProcessor->Entry); + + // Don't let the cleanup routines free this. + pPrintProcessor = NULL; + } + + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + // Inside the loop + if (hSubSubKey) + RegCloseKey(hSubSubKey); + + if (pPrintProcessor) + { + if (pPrintProcessor->pwszName) + DllFreeSplStr(pPrintProcessor->pwszName); + + if (pPrintProcessor->pDatatypesInfo1) + DllFreeSplMem(pPrintProcessor->pDatatypesInfo1); + + DllFreeSplMem(pPrintProcessor); + } + + // Outside the loop + if (hSubKey) + RegCloseKey(hSubKey); + + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/** + * @name LocalEnumPrintProcessorDatatypes + * + * Obtains an array of all datatypes supported by a particular Print Processor. + * Print Provider function for EnumPrintProcessorDatatypesA/EnumPrintProcessorDatatypesW. + * + * @param pName + * Server Name. Ignored here, because every caller of LocalEnumPrintProcessorDatatypes is interested in the local directory. + * + * @param pPrintProcessorName + * The (case-insensitive) name of the Print Processor to query. + * + * @param Level + * The level of the structure supplied through pDatatypes. This must be 1. + * + * @param pDatatypes + * Pointer to the buffer that receives an array of DATATYPES_INFO_1W structures. + * Can be NULL if you just want to know the required size of the buffer. + * + * @param cbBuf + * Size of the buffer you supplied for pDatatypes, in bytes. + * + * @param pcbNeeded + * Pointer to a variable that receives the required size of the buffer for pDatatypes, in bytes. + * This parameter mustn't be NULL! + * + * @param pcReturned + * Pointer to a variable that receives the number of elements of the DATATYPES_INFO_1W array. + * This parameter mustn't be NULL! + * + * @return + * TRUE if we successfully copied the array into pDatatypes, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + DWORD dwErrorCode; + PLOCAL_PRINT_PROCESSOR pPrintProcessor; + + // Sanity checks + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + // Try to find the Print Processor. + pPrintProcessor = FindPrintProcessor(pPrintProcessorName); + if (!pPrintProcessor) + { + dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR; + goto Cleanup; + } + + // Call its EnumPrintProcessorDatatypesW function. + if (pPrintProcessor->pfnEnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned)) + dwErrorCode = ERROR_SUCCESS; + else + dwErrorCode = GetLastError(); + +Cleanup: + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/** + * @name LocalEnumPrintProcessors + * + * Obtains an array of all available Print Processors on this computer. + * Print Provider function for EnumPrintProcessorsA/EnumPrintProcessorsW. + * + * @param pName + * Server Name. Ignored here, because every caller of LocalEnumPrintProcessors is interested in the local directory. + * + * @param pEnvironment + * One of the predefined operating system and architecture "environment" strings (like "Windows NT x86"). + * Alternatively, NULL to output the Print Processor directory of the current environment. + * + * @param Level + * The level of the structure supplied through pPrintProcessorInfo. This must be 1. + * + * @param pPrintProcessorInfo + * Pointer to the buffer that receives an array of PRINTPROCESSOR_INFO_1W structures. + * Can be NULL if you just want to know the required size of the buffer. + * + * @param cbBuf + * Size of the buffer you supplied for pPrintProcessorInfo, in bytes. + * + * @param pcbNeeded + * Pointer to a variable that receives the required size of the buffer for pPrintProcessorInfo, in bytes. + * This parameter mustn't be NULL! + * + * @param pcReturned + * Pointer to a variable that receives the number of elements of the PRINTPROCESSOR_INFO_1W array. + * This parameter mustn't be NULL! + * + * @return + * TRUE if we successfully copied the array into pPrintProcessorInfo, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned) +{ + DWORD cchMaxSubKey; + DWORD cchPrintProcessor; + DWORD dwErrorCode; + DWORD dwPrintProcessorCount; + DWORD i; + HKEY hKey = NULL; + HKEY hSubKey = NULL; + PBYTE pCurrentOutputPrintProcessor; + PBYTE pCurrentOutputPrintProcessorInfo; + PRINTPROCESSOR_INFO_1W PrintProcessorInfo1; + PWSTR pwszTemp = NULL; + + // Sanity checks + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (!pcbNeeded || !pcReturned) + { + // This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER. + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Verify pEnvironment and open its registry key. + // We use the registry and not the PrintProcessorList here, because the caller may request information about a different environment. + dwErrorCode = _OpenEnvironment(pEnvironment, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Open the "Print Processors" subkey. + dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Get the number of Print Processors and maximum sub key length. + dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwPrintProcessorCount, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Allocate a temporary buffer to let RegEnumKeyExW succeed. + pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR)); + if (!pwszTemp) + { + dwErrorCode = ERROR_NOT_ENOUGH_MEMORY; + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + goto Cleanup; + } + + // Determine the required size of the output buffer. + *pcbNeeded = 0; + + for (i = 0; i < dwPrintProcessorCount; i++) + { + // RegEnumKeyExW sucks! Unlike similar API functions, it only returns the actual numbers of characters copied when you supply a buffer large enough. + // So use pwszTemp with its size cchMaxSubKey for this. + cchPrintProcessor = cchMaxSubKey + 1; + dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + *pcbNeeded += sizeof(PRINTPROCESSOR_INFO_1W) + (cchPrintProcessor + 1) * sizeof(WCHAR); + } + + // Check if the supplied buffer is large enough. + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Put the Print Processor strings right after the last PRINTPROCESSOR_INFO_1W structure. + pCurrentOutputPrintProcessorInfo = pPrintProcessorInfo; + pCurrentOutputPrintProcessor = pPrintProcessorInfo + dwPrintProcessorCount * sizeof(PRINTPROCESSOR_INFO_1W); + + // Copy over all Print Processors. + for (i = 0; i < dwPrintProcessorCount; i++) + { + // This isn't really correct, but doesn't cause any harm, because we've extensively checked the size of the supplied buffer above. + cchPrintProcessor = cchMaxSubKey + 1; + + // Copy the Print Processor name. + dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Fill and copy the PRINTPROCESSOR_INFO_1W structure belonging to this Print Processor. + PrintProcessorInfo1.pName = (PWSTR)pCurrentOutputPrintProcessor; + CopyMemory(pCurrentOutputPrintProcessorInfo, &PrintProcessorInfo1, sizeof(PRINTPROCESSOR_INFO_1W)); + + // Advance to the next PRINTPROCESSOR_INFO_1W location and string location in the output buffer. + pCurrentOutputPrintProcessor += (cchPrintProcessor + 1) * sizeof(WCHAR); + pCurrentOutputPrintProcessorInfo += sizeof(PRINTPROCESSOR_INFO_1W); + } + + // We've finished successfully! + *pcReturned = dwPrintProcessorCount; + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (pwszTemp) + DllFreeSplMem(pwszTemp); + + if (hSubKey) + RegCloseKey(hSubKey); + + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} + +/** + * @name LocalGetPrintProcessorDirectory + * + * Obtains the path to the local Print Processor directory. + * Print Provider function for GetPrintProcessorDirectoryA/GetPrintProcessorDirectoryW. + * + * @param pName + * Server Name. Ignored here, because every caller of LocalGetPrintProcessorDirectory is interested in the local directory. + * + * @param pEnvironment + * One of the predefined operating system and architecture "environment" strings (like "Windows NT x86"). + * Alternatively, NULL to output the Print Processor directory of the current environment. + * + * @param Level + * The level of the (non-existing) structure supplied through pPrintProcessorInfo. This must be 1. + * + * @param pPrintProcessorInfo + * Pointer to the buffer that receives the full path to the Print Processor directory. + * Can be NULL if you just want to know the required size of the buffer. + * + * @param cbBuf + * Size of the buffer you supplied for pPrintProcessorInfo, in bytes. + * + * @param pcbNeeded + * Pointer to a variable that receives the required size of the buffer for pPrintProcessorInfo, in bytes. + * This parameter mustn't be NULL! + * + * @return + * TRUE if we successfully copied the directory into pPrintProcessorInfo, FALSE otherwise. + * A more specific error code can be obtained through GetLastError. + */ +BOOL WINAPI +LocalGetPrintProcessorDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded) +{ + const WCHAR wszPath[] = L"\\PRTPROCS\\"; + const DWORD cchPath = _countof(wszPath) - 1; + + DWORD cbDirectoryName; + DWORD dwErrorCode; + HKEY hKey = NULL; + PWSTR pwszDirectory = (PWSTR)pPrintProcessorInfo; + + // Sanity checks + if (Level != 1) + { + dwErrorCode = ERROR_INVALID_LEVEL; + goto Cleanup; + } + + if (!pcbNeeded) + { + // This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER. + dwErrorCode = ERROR_INVALID_PARAMETER; + goto Cleanup; + } + + // Verify pEnvironment and open its registry key. + dwErrorCode = _OpenEnvironment(pEnvironment, &hKey); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("_OpenEnvironment failed with error %lu!\n", dwErrorCode); + goto Cleanup; + } + + // Determine the size of the required buffer. + dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, &cbDirectoryName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + *pcbNeeded = (cchSpoolDirectory + cchPath) * sizeof(WCHAR) + cbDirectoryName; + + // Is the supplied buffer large enough? + if (cbBuf < *pcbNeeded) + { + dwErrorCode = ERROR_INSUFFICIENT_BUFFER; + goto Cleanup; + } + + // Copy the path to the "prtprocs" directory into pPrintProcessorInfo + CopyMemory(pwszDirectory, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR)); + CopyMemory(&pwszDirectory[cchSpoolDirectory], wszPath, cchPath * sizeof(WCHAR)); + + // Get the directory name from the registry. + dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, (PBYTE)&pwszDirectory[cchSpoolDirectory + cchPath], &cbDirectoryName); + if (dwErrorCode != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode); + goto Cleanup; + } + + // We've finished successfully! + dwErrorCode = ERROR_SUCCESS; + +Cleanup: + if (hKey) + RegCloseKey(hKey); + + SetLastError(dwErrorCode); + return (dwErrorCode == ERROR_SUCCESS); +} Index: win32ss/printing/providers/localspl/tools.c =================================================================== --- win32ss/printing/providers/localspl/tools.c (nonexistent) +++ win32ss/printing/providers/localspl/tools.c (working copy) @@ -0,0 +1,77 @@ +/* + * PROJECT: ReactOS Local Spooler + * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation + * PURPOSE: Various tools + * COPYRIGHT: Copyright 2015 Colin Finck + */ + +#include "precomp.h" + +/** + * @name AllocAndRegQueryWSZ + * + * Queries a REG_SZ value in the registry, allocates memory for it and returns a buffer containing the value. + * You have to free this buffer using DllFreeSplMem. + * + * @param hKey + * HKEY variable of the key opened with RegOpenKeyExW. + * + * @param pwszValueName + * Name of the REG_SZ value to query. + * + * @return + * Pointer to the buffer containing the value or NULL in case of failure. + */ +PWSTR +AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName) +{ + DWORD cbNeeded; + LONG lStatus; + PWSTR pwszValue; + + // Determine the size of the required buffer. + lStatus = RegQueryValueExW(hKey, pwszValueName, NULL, NULL, NULL, &cbNeeded); + if (lStatus != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %ld!\n", lStatus); + return NULL; + } + + // Allocate it. + pwszValue = DllAllocSplMem(cbNeeded); + if (!pwszValue) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return NULL; + } + + // Now get the actual value. + lStatus = RegQueryValueExW(hKey, pwszValueName, NULL, NULL, (PBYTE)pwszValue, &cbNeeded); + if (lStatus != ERROR_SUCCESS) + { + ERR("RegQueryValueExW failed with status %ld!\n", lStatus); + DllFreeSplMem(pwszValue); + return NULL; + } + + return pwszValue; +} + +PDEVMODEW +DuplicateDevMode(PDEVMODEW pInput) +{ + PDEVMODEW pOutput; + + // Allocate a buffer for this DevMode. + pOutput = DllAllocSplMem(pInput->dmSize + pInput->dmDriverExtra); + if (!pOutput) + { + ERR("DllAllocSplMem failed with error %lu!\n", GetLastError()); + return NULL; + } + + // Copy it. + CopyMemory(pOutput, pInput, pInput->dmSize + pInput->dmDriverExtra); + + return pOutput; +}