Index: CMakeLists.txt =================================================================== --- CMakeLists.txt (revision 69819) +++ CMakeLists.txt (working copy) @@ -276,6 +276,7 @@ add_subdirectory(modules) add_subdirectory(ntoskrnl) add_subdirectory(subsystems) + add_subdirectory(temp) add_subdirectory(tools/wpp) add_subdirectory(win32ss) Index: base/applications/cmdutils/CMakeLists.txt =================================================================== --- base/applications/cmdutils/CMakeLists.txt (revision 69819) +++ base/applications/cmdutils/CMakeLists.txt (working copy) @@ -9,6 +9,7 @@ add_subdirectory(lodctr) add_subdirectory(mode) add_subdirectory(more) +#add_subdirectory(print) add_subdirectory(reg) add_subdirectory(sort) add_subdirectory(taskkill) Index: base/services/CMakeLists.txt =================================================================== --- base/services/CMakeLists.txt (revision 69819) +++ base/services/CMakeLists.txt (working copy) @@ -3,7 +3,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 69819) +++ base/services/spoolsv/CMakeLists.txt (working copy) @@ -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 69819) +++ base/services/spoolsv/spoolsv.c (working copy) @@ -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 69819) +++ base/services/spoolsv/spoolsv.rc (working copy) @@ -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 69819) +++ boot/bootdata/hivesys.inf (working copy) @@ -1207,14 +1207,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 69819) +++ 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) @@ -138,7 +136,6 @@ add_subdirectory(ntdsapi) add_subdirectory(ntlanman) add_subdirectory(ntmarta) -add_subdirectory(ntprint) add_subdirectory(objsel) add_subdirectory(odbc32) add_subdirectory(odbccp32) @@ -193,7 +190,6 @@ add_subdirectory(sndblst) add_subdirectory(snmpapi) add_subdirectory(softpub) -add_subdirectory(spoolss) add_subdirectory(srclient) add_subdirectory(stdole2.tlb) add_subdirectory(stdole32.tlb) @@ -234,7 +230,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 69819) +++ dll/win32/localspl/CMakeLists.txt (working copy) @@ -1,22 +0,0 @@ - -add_definitions(-D__WINESRC__) -include_directories(${REACTOS_SOURCE_DIR}/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 shlwapi 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 69819) +++ dll/win32/localspl/lang/spl_Cy.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Da.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_De.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_En.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Es.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Fr.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_He.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Hu.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_It.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Ja.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Ko.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Lt.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Nl.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_No.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Pl.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Pt.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Ro.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Ru.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Si.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Sq.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Sv.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Tr.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Uk.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/lang/spl_Zh.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/localmon.c (working copy) @@ -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 69819) +++ dll/win32/localspl/localspl.rc (working copy) @@ -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 69819) +++ dll/win32/localspl/localspl.spec (working copy) @@ -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 69819) +++ dll/win32/localspl/localspl_main.c (working copy) @@ -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 69819) +++ dll/win32/localspl/localspl_private.h (working copy) @@ -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 69819) +++ dll/win32/localspl/provider.c (working copy) @@ -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(SHDeleteKeyW(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 69819) +++ dll/win32/localspl/resource.h (working copy) @@ -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/localui/CMakeLists.txt =================================================================== --- dll/win32/localui/CMakeLists.txt (revision 69819) +++ dll/win32/localui/CMakeLists.txt (working copy) @@ -1,14 +0,0 @@ - -add_definitions(-D__WINESRC__) -include_directories(${REACTOS_SOURCE_DIR}/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: dll/win32/localui/lang/ui_Da.rc =================================================================== --- dll/win32/localui/lang/ui_Da.rc (revision 69819) +++ dll/win32/localui/lang/ui_Da.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_De.rc =================================================================== --- dll/win32/localui/lang/ui_De.rc (revision 69819) +++ dll/win32/localui/lang/ui_De.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_En.rc =================================================================== --- dll/win32/localui/lang/ui_En.rc (revision 69819) +++ dll/win32/localui/lang/ui_En.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Es.rc =================================================================== --- dll/win32/localui/lang/ui_Es.rc (revision 69819) +++ dll/win32/localui/lang/ui_Es.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Fr.rc =================================================================== --- dll/win32/localui/lang/ui_Fr.rc (revision 69819) +++ dll/win32/localui/lang/ui_Fr.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_He.rc =================================================================== --- dll/win32/localui/lang/ui_He.rc (revision 69819) +++ dll/win32/localui/lang/ui_He.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Hu.rc =================================================================== --- dll/win32/localui/lang/ui_Hu.rc (revision 69819) +++ dll/win32/localui/lang/ui_Hu.rc (working copy) @@ -1,57 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_It.rc =================================================================== --- dll/win32/localui/lang/ui_It.rc (revision 69819) +++ dll/win32/localui/lang/ui_It.rc (working copy) @@ -1,58 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Ja.rc =================================================================== --- dll/win32/localui/lang/ui_Ja.rc (revision 69819) +++ dll/win32/localui/lang/ui_Ja.rc (working copy) @@ -1,57 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Ko.rc =================================================================== --- dll/win32/localui/lang/ui_Ko.rc (revision 69819) +++ dll/win32/localui/lang/ui_Ko.rc (working copy) @@ -1,55 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Lt.rc =================================================================== --- dll/win32/localui/lang/ui_Lt.rc (revision 69819) +++ dll/win32/localui/lang/ui_Lt.rc (working copy) @@ -1,57 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Nl.rc =================================================================== --- dll/win32/localui/lang/ui_Nl.rc (revision 69819) +++ dll/win32/localui/lang/ui_Nl.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_No.rc =================================================================== --- dll/win32/localui/lang/ui_No.rc (revision 69819) +++ dll/win32/localui/lang/ui_No.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Pl.rc =================================================================== --- dll/win32/localui/lang/ui_Pl.rc (revision 69819) +++ dll/win32/localui/lang/ui_Pl.rc (working copy) @@ -1,55 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Pt.rc =================================================================== --- dll/win32/localui/lang/ui_Pt.rc (revision 69819) +++ dll/win32/localui/lang/ui_Pt.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Ro.rc =================================================================== --- dll/win32/localui/lang/ui_Ro.rc (revision 69819) +++ dll/win32/localui/lang/ui_Ro.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Ru.rc =================================================================== --- dll/win32/localui/lang/ui_Ru.rc (revision 69819) +++ dll/win32/localui/lang/ui_Ru.rc (working copy) @@ -1,57 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Si.rc =================================================================== --- dll/win32/localui/lang/ui_Si.rc (revision 69819) +++ dll/win32/localui/lang/ui_Si.rc (working copy) @@ -1,56 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Sq.rc =================================================================== --- dll/win32/localui/lang/ui_Sq.rc (revision 69819) +++ dll/win32/localui/lang/ui_Sq.rc (working copy) @@ -1,55 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Sv.rc =================================================================== --- dll/win32/localui/lang/ui_Sv.rc (revision 69819) +++ dll/win32/localui/lang/ui_Sv.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Tr.rc =================================================================== --- dll/win32/localui/lang/ui_Tr.rc (revision 69819) +++ dll/win32/localui/lang/ui_Tr.rc (working copy) @@ -1,54 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Uk.rc =================================================================== --- dll/win32/localui/lang/ui_Uk.rc (revision 69819) +++ dll/win32/localui/lang/ui_Uk.rc (working copy) @@ -1,57 +0,0 @@ -/* - * 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: dll/win32/localui/lang/ui_Zh.rc =================================================================== --- dll/win32/localui/lang/ui_Zh.rc (revision 69819) +++ dll/win32/localui/lang/ui_Zh.rc (working copy) @@ -1,91 +0,0 @@ -/* - * 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: dll/win32/localui/localui.c =================================================================== --- dll/win32/localui/localui.c (revision 69819) +++ dll/win32/localui/localui.c (working copy) @@ -1,696 +0,0 @@ -/* - * 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: dll/win32/localui/localui.h =================================================================== --- dll/win32/localui/localui.h (revision 69819) +++ dll/win32/localui/localui.h (working copy) @@ -1,62 +0,0 @@ -/* - * 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: dll/win32/localui/localui.rc =================================================================== --- dll/win32/localui/localui.rc (revision 69819) +++ dll/win32/localui/localui.rc (working copy) @@ -1,112 +0,0 @@ -/* - * 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: dll/win32/localui/localui.spec =================================================================== --- dll/win32/localui/localui.spec (revision 69819) +++ dll/win32/localui/localui.spec (working copy) @@ -1 +0,0 @@ -@ stdcall InitializePrintMonitorUI() Index: dll/win32/ntprint/CMakeLists.txt =================================================================== --- dll/win32/ntprint/CMakeLists.txt (revision 69819) +++ dll/win32/ntprint/CMakeLists.txt (working copy) @@ -1,16 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/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 69819) +++ dll/win32/ntprint/ntprint.c (working copy) @@ -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 69819) +++ dll/win32/ntprint/ntprint.rc (working copy) @@ -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 69819) +++ dll/win32/ntprint/ntprint.spec (working copy) @@ -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/rpcrt4/rpc_binding.c =================================================================== --- dll/win32/rpcrt4/rpc_binding.c (revision 69819) +++ dll/win32/rpcrt4/rpc_binding.c (working copy) @@ -802,7 +802,17 @@ return RPC_S_OK; } + /*********************************************************************** + * RpcBindingServerFromClient (RPCRT4.@) + */ +RPC_STATUS WINAPI RpcBindingServerFromClient(RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding) +{ + /* This is a stub, just fail for now. */ + return RPC_S_INVALID_ARG; +} + +/*********************************************************************** * RpcBindingSetObject (RPCRT4.@) */ RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ) Index: dll/win32/rpcrt4/rpcrt4.spec =================================================================== --- dll/win32/rpcrt4/rpcrt4.spec (revision 69819) +++ dll/win32/rpcrt4/rpcrt4.spec (working copy) @@ -345,7 +345,7 @@ 345 stdcall RpcBindingInqObject(ptr ptr) 346 stub RpcBindingInqOption 347 stdcall RpcBindingReset(ptr) -348 stub RpcBindingServerFromClient +348 stdcall RpcBindingServerFromClient(ptr ptr) 349 stdcall RpcBindingSetAuthInfoA(ptr str long long ptr long) 350 stdcall RpcBindingSetAuthInfoExA(ptr str long long ptr long ptr) 351 stdcall RpcBindingSetAuthInfoExW(ptr wstr long long ptr long ptr) Index: dll/win32/spoolss/CMakeLists.txt =================================================================== --- dll/win32/spoolss/CMakeLists.txt (revision 69819) +++ dll/win32/spoolss/CMakeLists.txt (working copy) @@ -1,20 +0,0 @@ - -add_definitions(-D__WINESRC__) -include_directories(${REACTOS_SOURCE_DIR}/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 69819) +++ dll/win32/spoolss/router.c (working copy) @@ -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 69819) +++ dll/win32/spoolss/spoolss.h (working copy) @@ -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 69819) +++ dll/win32/spoolss/spoolss.spec (working copy) @@ -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 69819) +++ dll/win32/spoolss/spoolss_main.c (working copy) @@ -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 69819) +++ dll/win32/winspool/CMakeLists.txt (working copy) @@ -1,21 +0,0 @@ - -include_directories(${REACTOS_SOURCE_DIR}/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 69819) +++ dll/win32/winspool/info.c (working copy) @@ -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 69819) +++ dll/win32/winspool/precomp.h (working copy) @@ -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 69819) +++ dll/win32/winspool/stubs.c (working copy) @@ -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 69819) +++ dll/win32/winspool/winspool.rc (working copy) @@ -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 69819) +++ dll/win32/winspool/winspool.spec (working copy) @@ -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 -@ stub IsValidDevmodeW -@ 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: include/psdk/rpcdce.h =================================================================== --- include/psdk/rpcdce.h (revision 69819) +++ include/psdk/rpcdce.h (working copy) @@ -338,6 +338,8 @@ RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingReset( RPC_BINDING_HANDLE Binding ); RPCRTAPI RPC_STATUS RPC_ENTRY + RpcBindingServerFromClient( RPC_BINDING_HANDLE ClientBinding, RPC_BINDING_HANDLE* ServerBinding ); +RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid ); RPCRTAPI RPC_STATUS RPC_ENTRY RpcBindingSetOption( RPC_BINDING_HANDLE Binding, ULONG Option, ULONG_PTR OptionValue ); Index: include/psdk/winspool.h =================================================================== --- include/psdk/winspool.h (revision 69819) +++ include/psdk/winspool.h (working copy) @@ -1,1981 +1,1675 @@ +/** + * 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 -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4820) -#endif + typedef struct _PRINTER_INFO_1A { + DWORD Flags; + LPSTR pDescription; + LPSTR pName; + LPSTR pComment; + } PRINTER_INFO_1A,*PPRINTER_INFO_1A,*LPPRINTER_INFO_1A; -#define DI_CHANNEL 1 -#define DI_CHANNEL_WRITE 2 -#define DI_READ_SPOOL_JOB 3 + typedef struct _PRINTER_INFO_1W { + DWORD Flags; + LPWSTR pDescription; + LPWSTR pName; + LPWSTR pComment; + } PRINTER_INFO_1W,*PPRINTER_INFO_1W,*LPPRINTER_INFO_1W; -#define FORM_BUILTIN 1 + __MINGW_TYPEDEF_AW(PRINTER_INFO_1) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_1) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_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 + 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; -#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 + 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; -#define JOB_POSITION_UNSPECIFIED 0 + __MINGW_TYPEDEF_AW(PRINTER_INFO_2) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_2) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_2) -#define JOB_NOTIFY_TYPE 1 + typedef struct _PRINTER_INFO_3 { + PSECURITY_DESCRIPTOR pSecurityDescriptor; + } PRINTER_INFO_3,*PPRINTER_INFO_3,*LPPRINTER_INFO_3; -#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 + typedef struct _PRINTER_INFO_4A { + LPSTR pPrinterName; + LPSTR pServerName; + DWORD Attributes; + } PRINTER_INFO_4A,*PPRINTER_INFO_4A,*LPPRINTER_INFO_4A; -#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) + typedef struct _PRINTER_INFO_4W { + LPWSTR pPrinterName; + LPWSTR pServerName; + DWORD Attributes; + } PRINTER_INFO_4W,*PPRINTER_INFO_4W,*LPPRINTER_INFO_4W; -#define PRINTER_NOTIFY_OPTIONS_REFRESH 1 -#define PRINTER_ACCESS_ADMINISTER 4 -#define PRINTER_ACCESS_USE 8 + __MINGW_TYPEDEF_AW(PRINTER_INFO_4) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_4) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_4) -#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 + typedef struct _PRINTER_INFO_5A { + LPSTR pPrinterName; + LPSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; + } PRINTER_INFO_5A,*PPRINTER_INFO_5A,*LPPRINTER_INFO_5A; -#define PRINTER_CONTROL_PAUSE 1 -#define PRINTER_CONTROL_RESUME 2 -#define PRINTER_CONTROL_PURGE 3 -#define PRINTER_CONTROL_SET_STATUS 4 + typedef struct _PRINTER_INFO_5W { + LPWSTR pPrinterName; + LPWSTR pPortName; + DWORD Attributes; + DWORD DeviceNotSelectedTimeout; + DWORD TransmissionRetryTimeout; + } PRINTER_INFO_5W,*PPRINTER_INFO_5W,*LPPRINTER_INFO_5W; -#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 + __MINGW_TYPEDEF_AW(PRINTER_INFO_5) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_5) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_5) -#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 + typedef struct _PRINTER_INFO_6 { + DWORD dwStatus; + } PRINTER_INFO_6,*PPRINTER_INFO_6,*LPPRINTER_INFO_6; -#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 + typedef struct _PRINTER_INFO_7A { + LPSTR pszObjectGUID; + DWORD dwAction; + } PRINTER_INFO_7A,*PPRINTER_INFO_7A,*LPPRINTER_INFO_7A; -#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 + typedef struct _PRINTER_INFO_7W { + LPWSTR pszObjectGUID; + DWORD dwAction; + } PRINTER_INFO_7W,*PPRINTER_INFO_7W,*LPPRINTER_INFO_7W; -#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 + __MINGW_TYPEDEF_AW(PRINTER_INFO_7) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_7) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_7) -#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 DSPRINT_PUBLISH 0x00000001 +#define DSPRINT_UPDATE 0x00000002 +#define DSPRINT_UNPUBLISH 0x00000004 +#define DSPRINT_REPUBLISH 0x00000008 +#define DSPRINT_PENDING 0x80000000 -#define NO_PRIORITY 0 -#define MAX_PRIORITY 99 -#define MIN_PRIORITY 1 -#define DEF_PRIORITY 1 + typedef struct _PRINTER_INFO_8A { + LPDEVMODEA pDevMode; + } PRINTER_INFO_8A,*PPRINTER_INFO_8A,*LPPRINTER_INFO_8A; -#define PORT_TYPE_WRITE 1 -#define PORT_TYPE_READ 2 -#define PORT_TYPE_REDIRECTED 4 -#define PORT_TYPE_NET_ATTACHED 8 + typedef struct _PRINTER_INFO_8W { + LPDEVMODEW pDevMode; + } PRINTER_INFO_8W,*PPRINTER_INFO_8W,*LPPRINTER_INFO_8W; -#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) + __MINGW_TYPEDEF_AW(PRINTER_INFO_8) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_8) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_8) -#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_INFO_9A { + LPDEVMODEA pDevMode; + } PRINTER_INFO_9A,*PPRINTER_INFO_9A,*LPPRINTER_INFO_9A; -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_INFO_9W { + LPDEVMODEW pDevMode; + } PRINTER_INFO_9W,*PPRINTER_INFO_9W,*LPPRINTER_INFO_9W; -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; + __MINGW_TYPEDEF_AW(PRINTER_INFO_9) + __MINGW_TYPEDEF_AW(PPRINTER_INFO_9) + __MINGW_TYPEDEF_AW(LPPRINTER_INFO_9) -#ifndef RC_INVOKED +#define PRINTER_CONTROL_PAUSE 1 +#define PRINTER_CONTROL_RESUME 2 +#define PRINTER_CONTROL_PURGE 3 +#define PRINTER_CONTROL_SET_STATUS 4 -typedef struct _ADDJOB_INFO_1A { - LPSTR Path; - DWORD JobId; -} ADDJOB_INFO_1A, *PADDJOB_INFO_1A, *LPADDJOB_INFO_1A; +#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 -typedef struct _ADDJOB_INFO_1W { - LPWSTR Path; - DWORD JobId; -} ADDJOB_INFO_1W, *PADDJOB_INFO_1W, *LPADDJOB_INFO_1W; +#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 -typedef struct _DATATYPES_INFO_1A { - LPSTR pName; -} DATATYPES_INFO_1A, *PDATATYPES_INFO_1A, *LPDATATYPES_INFO_1A; +#define PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x00000080 +#define PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x00000100 +#define PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x00000200 -typedef struct _DATATYPES_INFO_1W { - LPWSTR pName; -} DATATYPES_INFO_1W, *PDATATYPES_INFO_1W, *LPDATATYPES_INFO_1W; +#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 -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; +#define NO_PRIORITY 0 +#define MAX_PRIORITY 99 +#define MIN_PRIORITY 1 +#define DEF_PRIORITY 1 -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_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_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_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_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_1) + __MINGW_TYPEDEF_AW(PJOB_INFO_1) + __MINGW_TYPEDEF_AW(LPJOB_INFO_1) -typedef struct _JOB_INFO_3 { - DWORD JobId; - DWORD NextJobId; - DWORD Reserved; -} JOB_INFO_3, *PJOB_INFO_3, *LPJOB_INFO_3; + 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_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_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_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; + __MINGW_TYPEDEF_AW(JOB_INFO_2) + __MINGW_TYPEDEF_AW(PJOB_INFO_2) + __MINGW_TYPEDEF_AW(LPJOB_INFO_2) -typedef struct _DOC_INFO_1A { - LPSTR pDocName; - LPSTR pOutputFile; - LPSTR pDatatype; -} DOC_INFO_1A, *PDOC_INFO_1A, *LPDOC_INFO_1A; + typedef struct _JOB_INFO_3 { + DWORD JobId; + DWORD NextJobId; + DWORD Reserved; + } JOB_INFO_3,*PJOB_INFO_3,*LPJOB_INFO_3; -typedef struct _DOC_INFO_1W { - LPWSTR pDocName; - LPWSTR pOutputFile; - LPWSTR pDatatype; -} DOC_INFO_1W, *PDOC_INFO_1W, *LPDOC_INFO_1W; +#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 -typedef struct _DOC_INFO_2A { - LPSTR pDocName; - LPSTR pOutputFile; - LPSTR pDatatype; - DWORD dwMode; - DWORD JobId; -} DOC_INFO_2A, *PDOC_INFO_2A, *LPDOC_INFO_2A; +#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 -typedef struct _DOC_INFO_2W { - LPWSTR pDocName; - LPWSTR pOutputFile; - LPWSTR pDatatype; - DWORD dwMode; - DWORD JobId; -} DOC_INFO_2W, *PDOC_INFO_2W, *LPDOC_INFO_2W; +#define JOB_POSITION_UNSPECIFIED 0 -typedef struct _DRIVER_INFO_1A { - LPSTR pName; -} DRIVER_INFO_1A, *PDRIVER_INFO_1A, *LPDRIVER_INFO_1A; + typedef struct _ADDJOB_INFO_1A { + LPSTR Path; + DWORD JobId; + } ADDJOB_INFO_1A,*PADDJOB_INFO_1A,*LPADDJOB_INFO_1A; -typedef struct _DRIVER_INFO_1W { - LPWSTR pName; -} DRIVER_INFO_1W, *PDRIVER_INFO_1W, *LPDRIVER_INFO_1W; + typedef struct _ADDJOB_INFO_1W { + LPWSTR Path; + DWORD JobId; + } ADDJOB_INFO_1W,*PADDJOB_INFO_1W,*LPADDJOB_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; + __MINGW_TYPEDEF_AW(ADDJOB_INFO_1) + __MINGW_TYPEDEF_AW(PADDJOB_INFO_1) + __MINGW_TYPEDEF_AW(LPADDJOB_INFO_1) -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_1A { + LPSTR pName; + } DRIVER_INFO_1A,*PDRIVER_INFO_1A,*LPDRIVER_INFO_1A; -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_1W { + LPWSTR pName; + } DRIVER_INFO_1W,*PDRIVER_INFO_1W,*LPDRIVER_INFO_1W; -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_1) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_1) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_1) -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_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_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_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_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; + __MINGW_TYPEDEF_AW(DRIVER_INFO_2) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_2) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_2) -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_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_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_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_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_3) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_3) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_3) -#define PRINTER_DRIVER_PACKAGE_AWARE 0x00000001 + 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_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_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_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; + __MINGW_TYPEDEF_AW(DRIVER_INFO_4) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_4) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_4) -// FLAGS for dwDriverAttributes -#define DRIVER_KERNELMODE 0x00000001 -#define DRIVER_USERMODE 0x00000002 + 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; -// FLAGS for DeletePrinterDriverEx. -#define DPD_DELETE_UNUSED_FILES 0x00000001 -#define DPD_DELETE_SPECIFIC_VERSION 0x00000002 -#define DPD_DELETE_ALL_FILES 0x00000004 + 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; -// 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 + __MINGW_TYPEDEF_AW(DRIVER_INFO_5) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_5) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_5) -typedef struct _MONITOR_INFO_1A { - LPSTR pName; -} MONITOR_INFO_1A, *PMONITOR_INFO_1A, *LPMONITOR_INFO_1A; + 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 _MONITOR_INFO_1W { - LPWSTR pName; -} MONITOR_INFO_1W, *PMONITOR_INFO_1W, *LPMONITOR_INFO_1W; + 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; -typedef struct _PORT_INFO_1A { - LPSTR pName; -} PORT_INFO_1A, *PPORT_INFO_1A, *LPPORT_INFO_1A; + __MINGW_TYPEDEF_AW(DRIVER_INFO_6) + __MINGW_TYPEDEF_AW(PDRIVER_INFO_6) + __MINGW_TYPEDEF_AW(LPDRIVER_INFO_6) -typedef struct _PORT_INFO_1W { - LPWSTR pName; -} PORT_INFO_1W, *PPORT_INFO_1W, *LPPORT_INFO_1W; +#define DRIVER_KERNELMODE 0x00000001 +#define DRIVER_USERMODE 0x00000002 -typedef struct _MONITOR_INFO_2A { - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDLLName; -} MONITOR_INFO_2A, *PMONITOR_INFO_2A, *LPMONITOR_INFO_2A; +#define DPD_DELETE_UNUSED_FILES 0x00000001 +#define DPD_DELETE_SPECIFIC_VERSION 0x00000002 +#define DPD_DELETE_ALL_FILES 0x00000004 -typedef struct _MONITOR_INFO_2W { - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDLLName; -} MONITOR_INFO_2W, *PMONITOR_INFO_2W, *LPMONITOR_INFO_2W; +#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 _PORT_INFO_2A { - LPSTR pPortName; - LPSTR pMonitorName; - LPSTR pDescription; - DWORD fPortType; - DWORD Reserved; -} PORT_INFO_2A, *PPORT_INFO_2A, *LPPORT_INFO_2A; + typedef struct _DOC_INFO_1A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + } DOC_INFO_1A,*PDOC_INFO_1A,*LPDOC_INFO_1A; -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 _DOC_INFO_1W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + } DOC_INFO_1W,*PDOC_INFO_1W,*LPDOC_INFO_1W; -typedef struct _PORT_INFO_3A { - DWORD dwStatus; - LPSTR pszStatus; - DWORD dwSeverity; -} PORT_INFO_3A, *PPORT_INFO_3A, *LPPORT_INFO_3A; + __MINGW_TYPEDEF_AW(DOC_INFO_1) + __MINGW_TYPEDEF_AW(PDOC_INFO_1) + __MINGW_TYPEDEF_AW(LPDOC_INFO_1) -typedef struct _PORT_INFO_3W { - DWORD dwStatus; - LPWSTR pszStatus; - DWORD dwSeverity; -} PORT_INFO_3W, *PPORT_INFO_3W, *LPPORT_INFO_3W; + typedef struct _FORM_INFO_1A { + DWORD Flags; + LPSTR pName; + SIZEL Size; + RECTL ImageableArea; + } FORM_INFO_1A,*PFORM_INFO_1A,*LPFORM_INFO_1A; -typedef struct _PRINTER_INFO_1A { - DWORD Flags; - LPSTR pDescription; - LPSTR pName; - LPSTR pComment; -} PRINTER_INFO_1A, *PPRINTER_INFO_1A, *LPPRINTER_INFO_1A; + typedef struct _FORM_INFO_1W { + DWORD Flags; + LPWSTR pName; + SIZEL Size; + RECTL ImageableArea; + } FORM_INFO_1W,*PFORM_INFO_1W,*LPFORM_INFO_1W; -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(FORM_INFO_1) + __MINGW_TYPEDEF_AW(PFORM_INFO_1) + __MINGW_TYPEDEF_AW(LPFORM_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 _DOC_INFO_2A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + DWORD dwMode; + DWORD JobId; + } DOC_INFO_2A,*PDOC_INFO_2A,*LPDOC_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 _DOC_INFO_2W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + DWORD dwMode; + DWORD JobId; + } DOC_INFO_2W,*PDOC_INFO_2W,*LPDOC_INFO_2W; -typedef struct _PRINTER_INFO_3 { - PSECURITY_DESCRIPTOR pSecurityDescriptor; -} PRINTER_INFO_3, *PPRINTER_INFO_3, *LPPRINTER_INFO_3; + __MINGW_TYPEDEF_AW(DOC_INFO_2) + __MINGW_TYPEDEF_AW(PDOC_INFO_2) + __MINGW_TYPEDEF_AW(LPDOC_INFO_2) -typedef struct _PRINTER_INFO_4A { - LPSTR pPrinterName; - LPSTR pServerName; - DWORD Attributes; -} PRINTER_INFO_4A, *PPRINTER_INFO_4A, *LPPRINTER_INFO_4A; +#define DI_CHANNEL 1 +#define DI_READ_SPOOL_JOB 3 -typedef struct _PRINTER_INFO_4W { - LPWSTR pPrinterName; - LPWSTR pServerName; - DWORD Attributes; -} PRINTER_INFO_4W, *PPRINTER_INFO_4W, *LPPRINTER_INFO_4W; + typedef struct _DOC_INFO_3A { + LPSTR pDocName; + LPSTR pOutputFile; + LPSTR pDatatype; + DWORD dwFlags; + } DOC_INFO_3A,*PDOC_INFO_3A,*LPDOC_INFO_3A; -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 _DOC_INFO_3W { + LPWSTR pDocName; + LPWSTR pOutputFile; + LPWSTR pDatatype; + DWORD dwFlags; + } DOC_INFO_3W,*PDOC_INFO_3W,*LPDOC_INFO_3W; -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(DOC_INFO_3) + __MINGW_TYPEDEF_AW(PDOC_INFO_3) + __MINGW_TYPEDEF_AW(LPDOC_INFO_3) -typedef struct _PRINTER_INFO_6 { - DWORD dwStatus; -} PRINTER_INFO_6, *PPRINTER_INFO_6, *LPPRINTER_INFO_6; +#define DI_MEMORYMAP_WRITE 0x00000001 -typedef struct _PRINTER_INFO_7A { - LPSTR pszObjectGUID; - DWORD dwAction; -} PRINTER_INFO_7A, *PPRINTER_INFO_7A, *LPPRINTER_INFO_7A; +#define FORM_USER 0x00000000 +#define FORM_BUILTIN 0x00000001 +#define FORM_PRINTER 0x00000002 -typedef struct _PRINTER_INFO_7W { - LPWSTR pszObjectGUID; - DWORD dwAction; -} PRINTER_INFO_7W, *PPRINTER_INFO_7W, *LPPRINTER_INFO_7W; + typedef struct _PRINTPROCESSOR_INFO_1A { + LPSTR pName; + } PRINTPROCESSOR_INFO_1A,*PPRINTPROCESSOR_INFO_1A,*LPPRINTPROCESSOR_INFO_1A; -typedef struct _PRINTER_INFO_8A { - LPDEVMODEA pDevMode; -} PRINTER_INFO_8A, *PPRINTER_INFO_8A, *LPPRINTER_INFO_8A; + typedef struct _PRINTPROCESSOR_INFO_1W { + LPWSTR pName; + } PRINTPROCESSOR_INFO_1W,*PPRINTPROCESSOR_INFO_1W,*LPPRINTPROCESSOR_INFO_1W; -typedef struct _PRINTER_INFO_8W { - LPDEVMODEW pDevMode; -} PRINTER_INFO_8W, *PPRINTER_INFO_8W, *LPPRINTER_INFO_8W; + __MINGW_TYPEDEF_AW(PRINTPROCESSOR_INFO_1) + __MINGW_TYPEDEF_AW(PPRINTPROCESSOR_INFO_1) + __MINGW_TYPEDEF_AW(LPPRINTPROCESSOR_INFO_1) -typedef struct _PRINTER_INFO_9A { - LPDEVMODEA pDevMode; -} PRINTER_INFO_9A, *PPRINTER_INFO_9A, *LPPRINTER_INFO_9A; + typedef struct _PRINTPROCESSOR_CAPS_1 { + DWORD dwLevel; + DWORD dwNupOptions; + DWORD dwPageOrderFlags; + DWORD dwNumberOfCopies; + } PRINTPROCESSOR_CAPS_1,*PPRINTPROCESSOR_CAPS_1; -typedef struct _PRINTER_INFO_9W { - LPDEVMODEW pDevMode; -} PRINTER_INFO_9W, *PPRINTER_INFO_9W, *LPPRINTER_INFO_9W; +#define NORMAL_PRINT 0x00000000 +#define REVERSE_PRINT 0x00000001 -typedef struct _PRINTPROCESSOR_INFO_1A { - LPSTR pName; -} PRINTPROCESSOR_INFO_1A, *PPRINTPROCESSOR_INFO_1A, *LPPRINTPROCESSOR_INFO_1A; + 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 _PRINTPROCESSOR_INFO_1W { - LPWSTR pName; -} PRINTPROCESSOR_INFO_1W, *PPRINTPROCESSOR_INFO_1W, *LPPRINTPROCESSOR_INFO_1W; + __MINGW_TYPEDEF_AW(PORT_INFO_1) + __MINGW_TYPEDEF_AW(PPORT_INFO_1) + __MINGW_TYPEDEF_AW(LPPORT_INFO_1) -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 _PORT_INFO_2A { + LPSTR pPortName; + LPSTR pMonitorName; + LPSTR pDescription; + DWORD fPortType; + DWORD Reserved; + } PORT_INFO_2A,*PPORT_INFO_2A,*LPPORT_INFO_2A; -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 _PORT_INFO_2W { + LPWSTR pPortName; + LPWSTR pMonitorName; + LPWSTR pDescription; + DWORD fPortType; + DWORD Reserved; + } PORT_INFO_2W,*PPORT_INFO_2W,*LPPORT_INFO_2W; -typedef struct _FORM_INFO_1A { - DWORD Flags; - LPSTR pName; - SIZEL Size; - RECTL ImageableArea; -} FORM_INFO_1A, *PFORM_INFO_1A, *LPFORM_INFO_1A; + __MINGW_TYPEDEF_AW(PORT_INFO_2) + __MINGW_TYPEDEF_AW(PPORT_INFO_2) + __MINGW_TYPEDEF_AW(LPPORT_INFO_2) -typedef struct _FORM_INFO_1W { - DWORD Flags; - LPWSTR pName; - SIZEL Size; - RECTL ImageableArea; -} FORM_INFO_1W, *PFORM_INFO_1W, *LPFORM_INFO_1W; +#define PORT_TYPE_WRITE 0x0001 +#define PORT_TYPE_READ 0x0002 +#define PORT_TYPE_REDIRECTED 0x0004 +#define PORT_TYPE_NET_ATTACHED 0x0008 -#if (NTDDI_VERSION >= NTDDI_VISTA) + typedef struct _PORT_INFO_3A { + DWORD dwStatus; + LPSTR pszStatus; + DWORD dwSeverity; + } PORT_INFO_3A,*PPORT_INFO_3A,*LPPORT_INFO_3A; -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 _PORT_INFO_3W { + DWORD dwStatus; + LPWSTR pszStatus; + DWORD dwSeverity; + } PORT_INFO_3W,*PPORT_INFO_3W,*LPPORT_INFO_3W; -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; + __MINGW_TYPEDEF_AW(PORT_INFO_3) + __MINGW_TYPEDEF_AW(PPORT_INFO_3) + __MINGW_TYPEDEF_AW(LPPORT_INFO_3) -#endif /* (NTDDI_VERSION >= NTDDI_VISTA) */ +#define PORT_STATUS_TYPE_ERROR 1 +#define PORT_STATUS_TYPE_WARNING 2 +#define PORT_STATUS_TYPE_INFO 3 -typedef struct _PRINTER_DEFAULTSA { - LPSTR pDatatype; - LPDEVMODE pDevMode; - ACCESS_MASK DesiredAccess; -} PRINTER_DEFAULTSA, *PPRINTER_DEFAULTSA, *LPPRINTER_DEFAULTSA; +#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_DEFAULTSW { - LPWSTR pDatatype; - LPDEVMODE pDevMode; - ACCESS_MASK DesiredAccess; -} PRINTER_DEFAULTSW, *PPRINTER_DEFAULTSW, *LPPRINTER_DEFAULTSW; + typedef struct _MONITOR_INFO_1A{ + LPSTR pName; + } MONITOR_INFO_1A,*PMONITOR_INFO_1A,*LPMONITOR_INFO_1A; -typedef struct _PROVIDOR_INFO_1A { - LPSTR pName; - LPSTR pEnvironment; - LPSTR pDLLName; -} PROVIDOR_INFO_1A, *PPROVIDOR_INFO_1A, *LPPROVIDOR_INFO_1A; + typedef struct _MONITOR_INFO_1W{ + LPWSTR pName; + } MONITOR_INFO_1W,*PMONITOR_INFO_1W,*LPMONITOR_INFO_1W; -typedef struct _PROVIDOR_INFO_1W { - LPWSTR pName; - LPWSTR pEnvironment; - LPWSTR pDLLName; -} PROVIDOR_INFO_1W, *LPPROVIDOR_INFO_1W; + __MINGW_TYPEDEF_AW(MONITOR_INFO_1) + __MINGW_TYPEDEF_AW(PMONITOR_INFO_1) + __MINGW_TYPEDEF_AW(LPMONITOR_INFO_1) -typedef struct _PROVIDOR_INFO_2A { - LPSTR pOrder; -} PROVIDOR_INFO_2A, *PPROVIDOR_INFO_2A, *LPPROVIDOR_INFO_2A; + typedef struct _MONITOR_INFO_2A { + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDLLName; + } MONITOR_INFO_2A,*PMONITOR_INFO_2A,*LPMONITOR_INFO_2A; -typedef struct _PROVIDOR_INFO_2W { - LPWSTR pOrder; -} PROVIDOR_INFO_2W, *LPPROVIDOR_INFO_2W; + typedef struct _MONITOR_INFO_2W { + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDLLName; + } MONITOR_INFO_2W,*PMONITOR_INFO_2W,*LPMONITOR_INFO_2W; -typedef struct _BINARY_CONTAINER { - DWORD cbBuf; - LPBYTE pData; -} BINARY_CONTAINER, *PBINARY_CONTAINER; + __MINGW_TYPEDEF_AW(MONITOR_INFO_2) + __MINGW_TYPEDEF_AW(PMONITOR_INFO_2) + __MINGW_TYPEDEF_AW(LPMONITOR_INFO_2) -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 _DATATYPES_INFO_1A { + LPSTR pName; + } DATATYPES_INFO_1A,*PDATATYPES_INFO_1A,*LPDATATYPES_INFO_1A; -typedef struct _BIDI_REQUEST_DATA { - DWORD dwReqNumber; - LPWSTR pSchema; - BIDI_DATA data; -} BIDI_REQUEST_DATA, *LPBIDI_REQUEST_DATA, *PBIDI_REQUEST_DATA; + typedef struct _DATATYPES_INFO_1W { + LPWSTR pName; + } DATATYPES_INFO_1W,*PDATATYPES_INFO_1W,*LPDATATYPES_INFO_1W; -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; + __MINGW_TYPEDEF_AW(DATATYPES_INFO_1) + __MINGW_TYPEDEF_AW(PDATATYPES_INFO_1) + __MINGW_TYPEDEF_AW(LPDATATYPES_INFO_1) -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 _PRINTER_DEFAULTSA { + LPSTR pDatatype; + LPDEVMODEA pDevMode; + ACCESS_MASK DesiredAccess; + } PRINTER_DEFAULTSA,*PPRINTER_DEFAULTSA,*LPPRINTER_DEFAULTSA; -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; + typedef struct _PRINTER_DEFAULTSW { + LPWSTR pDatatype; + LPDEVMODEW pDevMode; + ACCESS_MASK DesiredAccess; + } PRINTER_DEFAULTSW,*PPRINTER_DEFAULTSW,*LPPRINTER_DEFAULTSW; -#ifdef UNICODE + __MINGW_TYPEDEF_AW(PRINTER_DEFAULTS) + __MINGW_TYPEDEF_AW(PPRINTER_DEFAULTS) + __MINGW_TYPEDEF_AW(LPPRINTER_DEFAULTS) -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; + typedef struct _PRINTER_ENUM_VALUESA { + LPSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; + } PRINTER_ENUM_VALUESA,*PPRINTER_ENUM_VALUESA,*LPPRINTER_ENUM_VALUESA; -#else /* UNICODE */ + typedef struct _PRINTER_ENUM_VALUESW { + LPWSTR pValueName; + DWORD cbValueName; + DWORD dwType; + LPBYTE pData; + DWORD cbData; + } PRINTER_ENUM_VALUESW,*PPRINTER_ENUM_VALUESW,*LPPRINTER_ENUM_VALUESW; -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; + __MINGW_TYPEDEF_AW(PRINTER_ENUM_VALUES) + __MINGW_TYPEDEF_AW(PPRINTER_ENUM_VALUES) + __MINGW_TYPEDEF_AW(LPPRINTER_ENUM_VALUES) -#endif /* UNICODE */ +#define EnumPrinters __MINGW_NAME_AW(EnumPrinters) -BOOL WINAPI AbortPrinter(_In_ HANDLE); + 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); -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); +#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 -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); +#define PRINTER_ENUM_EXPAND 0x00004000 +#define PRINTER_ENUM_CONTAINER 0x00008000 -BOOL -WINAPI -AddJobA( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pData, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); +#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 -BOOL -WINAPI -AddJobW( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pData, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); +#define SPOOL_FILE_PERSISTENT 0x00000001 +#define SPOOL_FILE_TEMPORARY 0x00000002 -BOOL -WINAPI -AddMonitorA( - _In_opt_ LPSTR pName, - _In_ DWORD Level, - _In_reads_bytes_opt_(sizeof(MONITOR_INFO_2)) LPBYTE pMonitors); +#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) -BOOL -WINAPI -AddMonitorW( - _In_opt_ LPWSTR pName, - _In_ DWORD Level, - _In_reads_bytes_opt_(sizeof(MONITOR_INFO_2)) LPBYTE pMonitors); + 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); -BOOL WINAPI AddPortA(_In_opt_ LPSTR, _In_ HWND, _In_ LPSTR); -BOOL WINAPI AddPortW(_In_opt_ LPWSTR, _In_ HWND, _In_ LPWSTR); +#define PRINTER_NOTIFY_TYPE 0x00 +#define JOB_NOTIFY_TYPE 0x01 -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); +#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 -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); +#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 -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); + 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; -BOOL -WINAPI -AddPrintProcessorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPathName, - _In_ LPSTR pPrintProcessorName); +#define PRINTER_NOTIFY_OPTIONS_REFRESH 0x01 -BOOL -WINAPI -AddPrintProcessorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPathName, - _In_ LPWSTR pPrintProcessorName); + 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; -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); +#define PRINTER_NOTIFY_INFO_DISCARDED 0x01 -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); + 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; -LONG -WINAPI -AdvancedDocumentPropertiesA( - _In_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPSTR pDeviceName, - _Inout_opt_ PDEVMODEA pDevModeOutput, - _In_opt_ PDEVMODEA pDevModeInput); + 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; -LONG -WINAPI -AdvancedDocumentPropertiesW( - _In_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPWSTR pDeviceName, - _Inout_opt_ PDEVMODEW pDevModeOutput, - _In_opt_ PDEVMODEW pDevModeInput); + typedef struct _BINARY_CONTAINER{ + DWORD cbBuf; + LPBYTE pData; + } BINARY_CONTAINER,*PBINARY_CONTAINER; -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); + 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; -BOOL -WINAPI -DeletePrinterDriverA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pDriverName); + typedef struct _BIDI_REQUEST_DATA{ + DWORD dwReqNumber; + LPWSTR pSchema; + BIDI_DATA data; + } BIDI_REQUEST_DATA ,*PBIDI_REQUEST_DATA ,*LPBIDI_REQUEST_DATA; -BOOL -WINAPI -DeletePrinterDriverW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pDriverName); + 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; -BOOL -WINAPI -DeletePrintProcessorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPrintProcessorName); + typedef struct _BIDI_RESPONSE_DATA{ + DWORD dwResult; + DWORD dwReqNumber; + LPWSTR pSchema; + BIDI_DATA data; + } BIDI_RESPONSE_DATA,*PBIDI_RESPONSE_DATA,*LPBIDI_RESPONSE_DATA; -BOOL -WINAPI -DeletePrintProcessorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPrintProcessorName); + 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; -BOOL -WINAPI -DeletePrintProvidorA( - _In_opt_ LPSTR pName, - _In_opt_ LPSTR pEnvironment, - _In_ LPSTR pPrintProvidorName); +#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" -BOOL -WINAPI -DeletePrintProvidorW( - _In_opt_ LPWSTR pName, - _In_opt_ LPWSTR pEnvironment, - _In_ LPWSTR pPrintProvidorName); + 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; -LONG -WINAPI -DocumentPropertiesA( - _In_opt_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPSTR pDeviceName, - _Out_opt_ PDEVMODEA pDevModeOutput, - _In_opt_ PDEVMODEA pDevModeInput, - _In_ DWORD fMode); +#define BIDI_ACCESS_ADMINISTRATOR 0x1 +#define BIDI_ACCESS_USER 0x2 -LONG -WINAPI -DocumentPropertiesW( - _In_opt_ HWND hWnd, - _In_ HANDLE hPrinter, - _In_ LPWSTR pDeviceName, - _Out_opt_ PDEVMODEW pDevModeOutput, - _In_opt_ PDEVMODEW pDevModeInput, - _In_ DWORD fMode); +#define ERROR_BIDI_STATUS_OK 0 +#define ERROR_BIDI_NOT_SUPPORTED ERROR_NOT_SUPPORTED -BOOL WINAPI EndDocPrinter(_In_ HANDLE); -BOOL WINAPI EndPagePrinter(_In_ HANDLE); +#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) -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); + 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); -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); +#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 -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); +#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) -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); + 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); -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); +#define PRINTER_ERROR_INFORMATION 0x80000000 +#define PRINTER_ERROR_WARNING 0x40000000 +#define PRINTER_ERROR_SEVERE 0x20000000 -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); +#define PRINTER_ERROR_OUTOFPAPER 0x00000001 +#define PRINTER_ERROR_JAM 0x00000002 +#define PRINTER_ERROR_OUTOFTONER 0x00000004 -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); + 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); -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); +#define XcvData XcvDataW -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); + 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); -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); + typedef struct _PROVIDOR_INFO_1A{ + LPSTR pName; + LPSTR pEnvironment; + LPSTR pDLLName; + } PROVIDOR_INFO_1A,*PPROVIDOR_INFO_1A,*LPPROVIDOR_INFO_1A; -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); + typedef struct _PROVIDOR_INFO_1W{ + LPWSTR pName; + LPWSTR pEnvironment; + LPWSTR pDLLName; + } PROVIDOR_INFO_1W,*PPROVIDOR_INFO_1W,*LPPROVIDOR_INFO_1W; -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); + __MINGW_TYPEDEF_AW(PROVIDOR_INFO_1) + __MINGW_TYPEDEF_AW(PPROVIDOR_INFO_1) + __MINGW_TYPEDEF_AW(LPPROVIDOR_INFO_1) -_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); + typedef struct _PROVIDOR_INFO_2A{ + LPSTR pOrder; + } PROVIDOR_INFO_2A,*PPROVIDOR_INFO_2A,*LPPROVIDOR_INFO_2A; -_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); + typedef struct _PROVIDOR_INFO_2W{ + LPWSTR pOrder; + } PROVIDOR_INFO_2W,*PPROVIDOR_INFO_2W,*LPPROVIDOR_INFO_2W; -_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); + __MINGW_TYPEDEF_AW(PROVIDOR_INFO_2) + __MINGW_TYPEDEF_AW(PPROVIDOR_INFO_2) + __MINGW_TYPEDEF_AW(LPPROVIDOR_INFO_2) -_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); +#define AddPrintProvidor __MINGW_NAME_AW(AddPrintProvidor) +#define DeletePrintProvidor __MINGW_NAME_AW(DeletePrintProvidor) +#define IsValidDevmode __MINGW_NAME_AW(IsValidDevmode) -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); + 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); -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); +#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") -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); +#define SERVER_ACCESS_ADMINISTER 0x00000001 +#define SERVER_ACCESS_ENUMERATE 0x00000002 -BOOL WINAPI FindClosePrinterChangeNotification(_In_ HANDLE); +#define PRINTER_ACCESS_ADMINISTER 0x00000004 +#define PRINTER_ACCESS_USE 0x00000008 -HANDLE -WINAPI -FindFirstPrinterChangeNotification( - _In_ HANDLE hPrinter, - DWORD fdwFilter, - DWORD fdwOptions, - _In_opt_ PVOID pPrinterNotifyOptions); +#define JOB_ACCESS_ADMINISTER 0x00000010 +#define JOB_ACCESS_READ 0x00000020 -BOOL -WINAPI -FindNextPrinterChangeNotification( - _In_ HANDLE hChange, - _Out_opt_ PDWORD pdwChange, - _In_opt_ LPVOID pvReserved, - _Out_opt_ LPVOID *ppPrinterNotifyInfo); +#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) -BOOL WINAPI FreePrinterNotifyInfo(_In_ PPRINTER_NOTIFY_INFO); +#define SPLDS_SPOOLER_KEY TEXT("DsSpooler") +#define SPLDS_DRIVER_KEY TEXT("DsDriver") +#define SPLDS_USER_KEY TEXT("DsUser") -#if _WIN32_WINNT >= 0x0500 +#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") -BOOL -WINAPI -GetDefaultPrinterA( - _Out_writes_opt_(*pcchBuffer) LPSTR pszBuffer, - _Inout_ LPDWORD pcchBuffer); +#define SPLDS_PRINTER_NAME_ALIASES TEXT("printerNameAliases") +#define SPLDS_PRINTER_LOCATIONS TEXT("printerLocations") +#define SPLDS_PRINTER_MODEL TEXT("printerModel") -BOOL -WINAPI -GetDefaultPrinterW( - _Out_writes_opt_(*pcchBuffer) LPWSTR pszBuffer, - _Inout_ LPDWORD pcchBuffer); +#if (_WIN32_WINNT >= 0x0600) +#define AddPrinterConnection2 __MINGW_NAME_AW(AddPrinterConnection2) +#define DeletePrinterDriverPackage __MINGW_NAME_AW(DeletePrinterDriverPackage) +#define DocumentEvent __MINGW_NAME_AW(DocumentEvent) -#endif +#define PRINTER_CONNECTION_MISMATCH 0x00000020 +#define PRINTER_CONNECTION_NO_UI 0x00000040 -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); +typedef enum tagPRINTER_OPTION_FLAGS { + PRINTER_OPTION_NO_CACHE, + PRINTER_OPTION_CACHE, + PRINTER_OPTION_CLIENT_CHANGE +} PRINTER_OPTION_FLAGS; -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); +typedef enum tagEPrintXPSJobOperation { + kJobProduction, + kJobConsumption +} EPrintXPSJobOperation; -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); +typedef enum tagEPrintXPSJobProgress { + kAddingDocumentSequence, + kDocumentSequenceAdded, + kAddingFixedDocument, + kFixedDocumentAdded, + kAddingFixedPage, + kFixedPageAdded, + kResourceAdded, + kFontAdded, + kImageAdded, + kXpsDocumentCommitted +} EPrintXPSJobProgress; -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); +typedef struct _PRINTER_CONNECTION_INFO_1 { + DWORD dwFlags; + LPTSTR pszDriverName; +} PRINTER_CONNECTION_INFO_1, *PPRINTER_CONNECTION_INFO_1; -BOOL -WINAPI -GetPrinterA( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrinter, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); + 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.*/ -BOOL -WINAPI -GetPrinterW( - _In_ HANDLE hPrinter, - _In_ DWORD Level, - _Out_writes_bytes_opt_(cbBuf) LPBYTE pPrinter, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcbNeeded); +HRESULT WINAPI DeletePrinterDriverPackageA( + LPCSTR pszServer, + LPCSTR pszInfPath, + LPCSTR pszEnvironment +); -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); +HRESULT WINAPI DeletePrinterDriverPackageW( + LPCWSTR pszServer, + LPCWSTR pszInfPath, + LPCWSTR pszEnvironment +); -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); +HRESULT DocumentEventA( + HANDLE hPrinter, + HDC hdc, + INT iEsc, + ULONG cbIn, + PVOID pvIn, + ULONG cbOut, + PVOID pvOut +); -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); +HRESULT DocumentEventW( + HANDLE hPrinter, + HDC hdc, + INT iEsc, + ULONG cbIn, + PVOID pvIn, + ULONG cbOut, + PVOID pvOut +); -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); +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; -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); +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; -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); +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; -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); +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; -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); +__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) -#if NTDDI_VERSION >= NTDDI_WINXPSP2 -BOOL WINAPI IsValidDevmodeA(_In_opt_ PDEVMODEA, size_t); -BOOL WINAPI IsValidDevmodeW(_In_opt_ PDEVMODEW, size_t); -#endif +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; -BOOL -WINAPI -OpenPrinterA( - _In_opt_ LPSTR pPrinterName, - _Out_ LPHANDLE phPrinter, - _In_opt_ LPPRINTER_DEFAULTSA pDefault); +HRESULT ReportJobProcessingProgress( + HANDLE printerHandle, + ULONG jobId, + EPrintXPSJobOperation jobOperation, + EPrintXPSJobProgress jobProgress +); -BOOL -WINAPI -OpenPrinterW( - _In_opt_ LPWSTR pPrinterName, - _Out_ LPHANDLE phPrinter, - _In_opt_ LPPRINTER_DEFAULTSW pDefault); +typedef struct _CORE_PRINTER_DRIVERA { + GUID CoreDriverGUID; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + CHAR szPackageID[MAX_PATH]; +} CORE_PRINTER_DRIVERA, *PCORE_PRINTER_DRIVERA; -DWORD -WINAPI -PrinterMessageBoxA( - _In_ HANDLE hPrinter, - DWORD Error, - _In_ HWND hWnd, - _In_ LPSTR pText, - _In_ LPSTR pCaption, - DWORD dwType); +typedef struct _CORE_PRINTER_DRIVERW { + GUID CoreDriverGUID; + FILETIME ftDriverDate; + DWORDLONG dwlDriverVersion; + WCHAR szPackageID[MAX_PATH]; +} CORE_PRINTER_DRIVERW, *PCORE_PRINTER_DRIVERW; -DWORD -WINAPI -PrinterMessageBoxW( - _In_ HANDLE hPrinter, - DWORD Error, - _In_ HWND hWnd, - _In_ LPWSTR pText, - _In_ LPWSTR pCaption, - DWORD dwType); +typedef struct _PRINTER_OPTIONS { + UINT cbSize; + DWORD dwFlags; +} PRINTER_OPTIONS, *PPRINTER_OPTIONS; -BOOL WINAPI PrinterProperties(_In_ HWND, _In_ HANDLE); +__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) -BOOL -WINAPI -ReadPrinter( - _In_ HANDLE hPrinter, - _Out_writes_bytes_(cbBuf) LPVOID pBuf, - _In_ DWORD cbBuf, - _Out_ LPDWORD pNoBytesRead); +HRESULT WINAPI GetCorePrinterDriversA( + LPCSTR pszServer, + LPCSTR pszEnvironment, + LPCSTR pszzCoreDriverDependencies, + DWORD cCorePrinterDrivers, + PCORE_PRINTER_DRIVERA pCorePrinterDrivers +); -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); +HRESULT WINAPI GetCorePrinterDriversW( + LPCWSTR pszServer, + LPCWSTR pszEnvironment, + LPCWSTR pszzCoreDriverDependencies, + DWORD cCorePrinterDrivers, + PCORE_PRINTER_DRIVERW pCorePrinterDrivers +); -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); +/*Unsupported*/ +WINBOOL WINAPI GetPrinterDriver2A( + HWND hWnd, + HANDLE hPrinter, + LPSTR pEnvironment, + DWORD Level, + LPBYTE pDriverInfo, + DWORD cbBuf, + LPDWORD pcbNeeded +); -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); +WINBOOL WINAPI GetPrinterDriver2W( + HWND hWnd, + HANDLE hPrinter, + LPWSTR pEnvironment, + DWORD Level, + LPBYTE pDriverInfo, + DWORD cbBuf, + LPDWORD pcbNeeded +); -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); +HRESULT WINAPI GetPrinterDriverPackagePathA( + LPCSTR pszServer, + LPCSTR pszEnvironment, + LPCSTR pszLanguage, + LPCSTR pszPackageID, + LPSTR pszDriverPackageCab, + DWORD cchDriverPackageCab, + LPDWORD pcchRequiredSize +); -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); +HRESULT WINAPI GetPrinterDriverPackagePathW( + LPCWSTR pszServer, + LPCWSTR pszEnvironment, + LPCWSTR pszLanguage, + LPCWSTR pszPackageID, + LPWSTR pszDriverPackageCab, + DWORD cchDriverPackageCab, + LPDWORD pcchRequiredSize +); -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); +HANDLE WINAPI GetSpoolFileHandleA( + HANDLE hPrinter +); -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); +HANDLE WINAPI GetSpoolFileHandleW( + HANDLE hPrinter +); -BOOL -WINAPI -SetPrinterDataA( - _In_ HANDLE hPrinter, - _In_ LPSTR pValueName, - _In_ DWORD Type, - _In_reads_bytes_(cbData) LPBYTE pData, - _In_ DWORD cbData); +HANDLE WINAPI CommitSpoolData( + HANDLE hPrinter, + HANDLE hSpoolFile, + DWORD cbCommit +); -BOOL -WINAPI -SetPrinterDataW( - _In_ HANDLE hPrinter, - _In_ LPWSTR pValueName, - _In_ DWORD Type, - _In_reads_bytes_(cbData) LPBYTE pData, - _In_ DWORD cbData); +WINBOOL WINAPI CloseSpoolFileHandle( + HANDLE hPrinter, + HANDLE hSpoolFile +); -#ifdef _WINE -LPSTR WINAPI StartDocDlgA(HANDLE hPrinter, DOCINFOA *doc); -LPWSTR WINAPI StartDocDlgW(HANDLE hPrinter, DOCINFOW *doc); -#define StartDocDlg WINELIB_NAME_AW(StartDocDlg) -#endif +WINBOOL WINAPI OpenPrinter2A( + LPCSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTS pDefault, + PPRINTER_OPTIONS pOptions +); -DWORD -WINAPI -StartDocPrinterA( - _In_ HANDLE hPrinter, - _In_range_(1, 3) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(DOC_INFO_1))) LPBYTE pDocInfo); +WINBOOL WINAPI OpenPrinter2W( + LPCWSTR pPrinterName, + LPHANDLE phPrinter, + LPPRINTER_DEFAULTS pDefault, + PPRINTER_OPTIONS pOptions +); -DWORD -WINAPI -StartDocPrinterW( - _In_ HANDLE hPrinter, - _In_range_(1, 3) DWORD Level, - _When_(Level == 1, _In_reads_bytes_(sizeof(DOC_INFO_1))) LPBYTE pDocInfo); +#define OpenPrinter2 __MINGW_NAME_AW(OpenPrinter2) -BOOL WINAPI StartPagePrinter(_In_ HANDLE); -DWORD WINAPI WaitForPrinterChange(_In_ HANDLE, _In_ DWORD); +HRESULT WINAPI UploadPrinterDriverPackageA( + LPCSTR pszServer, + LPCSTR pszInfPath, + LPCSTR pszEnvironment, + DWORD dwFlags, + HWND hwnd, + LPSTR pszDestInfPath, + PULONG pcchDestInfPath +); -BOOL -WINAPI -WritePrinter( - _In_ HANDLE hPrinter, - _In_reads_bytes_(cbBuf) LPVOID pBuf, - _In_ DWORD cbBuf, - _Out_ LPDWORD pcWritten); +HRESULT WINAPI UploadPrinterDriverPackageW( + LPCWSTR pszServer, + LPCWSTR pszInfPath, + LPCWSTR pszEnvironment, + DWORD dwFlags, + HWND hwnd, + LPWSTR pszDestInfPath, + PULONG pcchDestInfPath +); -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); +#define UploadPrinterDriverPackage __MINGW_NAME_AW(UploadPrinterDriverPackage) -#ifdef UNICODE +#endif /*(_WIN32_WINNT >= 0x0600)*/ -#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_ */ +#endif Index: include/reactos/idl/winspool.idl =================================================================== --- include/reactos/idl/winspool.idl (revision 0) +++ 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: lib/CMakeLists.txt =================================================================== --- lib/CMakeLists.txt (revision 69819) +++ lib/CMakeLists.txt (working copy) @@ -27,6 +27,7 @@ add_subdirectory(rtl) add_subdirectory(sdk) +add_subdirectory(skiplist) add_subdirectory(smlib) add_subdirectory(tdilib) Index: lib/skiplist/CMakeLists.txt =================================================================== --- lib/skiplist/CMakeLists.txt (revision 0) +++ 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: lib/skiplist/skiplist.c =================================================================== --- lib/skiplist/skiplist.c (revision 0) +++ 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: lib/skiplist/skiplist.h =================================================================== --- lib/skiplist/skiplist.h (revision 0) +++ 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: lib/skiplist/skiplist_test.c =================================================================== --- lib/skiplist/skiplist_test.c (revision 0) +++ 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: temp/CMakeLists.txt =================================================================== --- temp/CMakeLists.txt (revision 0) +++ temp/CMakeLists.txt (working copy) @@ -0,0 +1 @@ +add_subdirectory(winspool_print) Index: temp/winspool_print/CMakeLists.txt =================================================================== --- temp/winspool_print/CMakeLists.txt (revision 0) +++ temp/winspool_print/CMakeLists.txt (working copy) @@ -0,0 +1,4 @@ +add_executable(winspool_print main.c) +set_module_type(winspool_print win32cui) +add_importlibs(winspool_print winspool msvcrt kernel32) +add_cd_file(TARGET winspool_print DESTINATION reactos/system32 FOR all) Index: temp/winspool_print/main.c =================================================================== --- temp/winspool_print/main.c (revision 0) +++ temp/winspool_print/main.c (working copy) @@ -0,0 +1,76 @@ +#include +#include + +int main() +{ + int ReturnValue = 1; + DWORD dwRead; + DWORD dwWritten; + HANDLE hFile = INVALID_HANDLE_VALUE; + HANDLE hPrinter = NULL; + DOC_INFO_1W docInfo; + BYTE Buffer[20000]; + + hFile = CreateFileW(L"testfile", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + printf("CreateFileW failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!ReadFile(hFile, Buffer, sizeof(Buffer), &dwRead, NULL)) + { + printf("ReadFile failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!OpenPrinterW(L"Dummy Printer On LPT1", &hPrinter, NULL)) + { + printf("OpenPrinterW failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + ZeroMemory(&docInfo, sizeof(docInfo)); + docInfo.pDocName = L"winspool_print"; + + if (!StartDocPrinterW(hPrinter, 1, (LPBYTE)&docInfo)) + { + printf("StartDocPrinterW failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!StartPagePrinter(hPrinter)) + { + printf("StartPagePrinter failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!WritePrinter(hPrinter, Buffer, dwRead, &dwWritten)) + { + printf("WritePrinter failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!EndPagePrinter(hPrinter)) + { + printf("EndPagePrinter failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + if (!EndDocPrinter(hPrinter)) + { + printf("EndDocPrinter failed, last error is %lu!\n", GetLastError()); + goto Cleanup; + } + + ReturnValue = 0; + +Cleanup: + if (hFile != INVALID_HANDLE_VALUE) + CloseHandle(hFile); + + if (hPrinter) + ClosePrinter(hPrinter); + + return ReturnValue; +} Index: win32ss/CMakeLists.txt =================================================================== --- win32ss/CMakeLists.txt (revision 69819) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ win32ss/printing/base/spoolsv/CMakeLists.txt (working copy) @@ -0,0 +1,30 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/idl) +add_rpc_files(server ${REACTOS_SOURCE_DIR}/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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ win32ss/printing/base/winspool/CMakeLists.txt (working copy) @@ -0,0 +1,30 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/idl) +add_rpc_files(client ${REACTOS_SOURCE_DIR}/include/reactos/idl/winspool.idl) +spec2def(winspool.drv winspool.spec ADD_IMPORTLIB) + +list(APPEND SOURCE + 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/jobs.c =================================================================== --- win32ss/printing/base/winspool/jobs.c (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ win32ss/printing/base/winspool/printers.c (working copy) @@ -0,0 +1,712 @@ +/* + * 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; + PWSTR pwszPrinterName = NULL; + PWSTR pwszDatatype = NULL; + PRINTER_DEFAULTSW wDefault = { 0 }; + size_t StringLength; + + if (pPrinterName) + { + // Convert pPrinterName to a Unicode string pwszPrinterName + StringLength = strlen(pPrinterName) + 1; + + pwszPrinterName = HeapAlloc(hProcessHeap, 0, StringLength * sizeof(WCHAR)); + if (!pwszPrinterName) + { + ERR("HeapAlloc failed for pwszPrinterName with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, StringLength); + } + + if (pDefault) + { + wDefault.DesiredAccess = pDefault->DesiredAccess; + + if (pDefault->pDatatype) + { + // Convert pDefault->pDatatype to a Unicode string pwszDatatype that later becomes wDefault.pDatatype + StringLength = strlen(pDefault->pDatatype) + 1; + + pwszDatatype = HeapAlloc(hProcessHeap, 0, StringLength * sizeof(WCHAR)); + if (!pwszDatatype) + { + ERR("HeapAlloc failed for pwszDatatype with last error %lu!\n", GetLastError()); + goto Cleanup; + } + + MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, pwszDatatype, StringLength); + wDefault.pDatatype = pwszDatatype; + } + + if (pDefault->pDevMode) + wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode); + } + + bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault); + +Cleanup: + if (wDefault.pDevMode) + HeapFree(hProcessHeap, 0, wDefault.pDevMode); + + if (pwszPrinterName) + HeapFree(hProcessHeap, 0, pwszPrinterName); + + if (pwszDatatype) + HeapFree(hProcessHeap, 0, pwszDatatype); + + 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 +StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo) +{ + DWORD cbAddJobInfo1; + DWORD cbNeeded; + DWORD dwErrorCode; + 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; + +Cleanup: + if (pAddJobInfo1) + HeapFree(hProcessHeap, 0, pAddJobInfo1); + + SetLastError(dwErrorCode); + return pHandle->dwJobID; +} + +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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 stub IsValidDevmodeA +260 stub IsValidDevmodeW +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 stub StartDocPrinterA +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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ win32ss/printing/monitors/localmon/ui/CMakeLists.txt (working copy) @@ -0,0 +1,14 @@ + +add_definitions(-D__WINESRC__) +include_directories(${REACTOS_SOURCE_DIR}/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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ win32ss/printing/providers/localspl/CMakeLists.txt (working copy) @@ -0,0 +1,27 @@ + +spec2def(localspl.dll localspl.spec ADD_IMPORTLIB) + +include_directories(${REACTOS_SOURCE_DIR}/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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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 (revision 0) +++ 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; +}