mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 14:53:40 +00:00
[LOCALSPL_APITEST]
- Add more tests for fpEnumPrinters. For some reason, using SEH here works only once. We experience a hang in the testing process when you run the test again for a second time without restarting spoolsv. Needs more investigation. - Ensure that the spooler service is running before starting any testing. - Do proper cleanup in every case. [LOCALSPL] - Implement LocalEnumPrinters level 1 based on the API-Tests. - Use DllAllocSplMem/DllFreeSplMem instead of HeapAlloc/HeapFree. - Use AllocSplStr with DllFreeSplStr now that DuplicateStringW is gone. - Use _countof where applicable. [SPOOLSS] - Found out that I was not the only one needing a wcsdup equivalent. My DuplicateStringW from localspl is actually exported as AllocSplStr in spoolss. This is actually part of a range of undocumented memory functions in spoolss, so implement and document AllocSplStr, DllAllocSplMem, DllFreeSplMem, DllFreeSplStr, ReallocSplMem and ReallocSplStr. Information about some of them was gathered through black box testing and DDK samples (down to Win95 DDK), which at least contained prototypes of them. - Implement SplInitializeWinSpoolDrv based on the API-Test and simply return FALSE for SplIsUpgrade. [SPOOLSS_APITEST] - Add a test for ReallocSplStr, which was actually the most undocumented function of spoolss' memory functions. [WINSPOOL] SplInitializeWinSpoolDrv shows that we can't just auto-assign an ordinal to all winspool.drv functions. We even need to export some nameless functions by ordinal only. Redo the whole .spec file based on the ordinals found in Windows Server 2003's winspool.drv. Trust WINE for the nameless stubs. svn path=/branches/colins-printing-for-freedom/; revision=68089
This commit is contained in:
parent
f2a66788f8
commit
1e363204d6
22 changed files with 952 additions and 337 deletions
|
@ -4,6 +4,7 @@ spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
context.c
|
context.c
|
||||||
main.c
|
main.c
|
||||||
|
memory.c
|
||||||
precomp.h
|
precomp.h
|
||||||
tools.c)
|
tools.c)
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
|
HANDLE hProcessHeap;
|
||||||
PRINTPROVIDOR LocalSplFuncs;
|
PRINTPROVIDOR LocalSplFuncs;
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +17,20 @@ ClosePrinter(HANDLE hPrinter)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI
|
||||||
|
DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
|
{
|
||||||
|
switch (fdwReason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
|
hProcessHeap = GetProcessHeap();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
EndDocPrinter(HANDLE hPrinter)
|
EndDocPrinter(HANDLE hPrinter)
|
||||||
{
|
{
|
||||||
|
@ -95,6 +110,44 @@ StartDocPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
SpoolerInit()
|
SpoolerInit()
|
||||||
{
|
{
|
||||||
|
|
168
reactos/win32ss/printing/base/spoolss/memory.c
Normal file
168
reactos/win32ss/printing/base/spoolss/memory.c
Normal file
|
@ -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 <colin@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -16,10 +16,15 @@
|
||||||
#include <winspool.h>
|
#include <winspool.h>
|
||||||
#include <winsplp.h>
|
#include <winsplp.h>
|
||||||
|
|
||||||
|
#include <spoolss.h>
|
||||||
|
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
|
WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
|
||||||
|
|
||||||
// Function pointer to InitializePrintProvidor of a provider DLL
|
// Function pointer to InitializePrintProvidor of a provider DLL
|
||||||
typedef BOOL (WINAPI *PInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
|
typedef BOOL (WINAPI *PInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
|
||||||
|
|
||||||
|
// main.c
|
||||||
|
extern HANDLE hProcessHeap;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
@ stub AdjustPointersInStructuresArray
|
@ stub AdjustPointersInStructuresArray
|
||||||
@ stub AlignKMPtr
|
@ stub AlignKMPtr
|
||||||
@ stub AlignRpcPtr
|
@ stub AlignRpcPtr
|
||||||
@ stub AllocSplStr
|
@ stdcall AllocSplStr(ptr)
|
||||||
@ stub AllowRemoteCalls
|
@ stub AllowRemoteCalls
|
||||||
@ stub AppendPrinterNotifyInfoData
|
@ stub AppendPrinterNotifyInfoData
|
||||||
@ stub bGetDevModePerUser
|
@ stub bGetDevModePerUser
|
||||||
|
@ -53,9 +53,9 @@
|
||||||
@ stub DeletePrinterKeyW
|
@ stub DeletePrinterKeyW
|
||||||
@ stub DeletePrintProcessorW
|
@ stub DeletePrintProcessorW
|
||||||
@ stub DeletePrintProvidorW
|
@ stub DeletePrintProvidorW
|
||||||
@ stub DllAllocSplMem
|
@ stdcall DllAllocSplMem(long)
|
||||||
@ stub DllFreeSplMem
|
@ stdcall DllFreeSplMem(ptr)
|
||||||
@ stub DllFreeSplStr
|
@ stdcall DllFreeSplStr(ptr)
|
||||||
@ stdcall EndDocPrinter(long)
|
@ stdcall EndDocPrinter(long)
|
||||||
@ stdcall EndPagePrinter(long)
|
@ stdcall EndPagePrinter(long)
|
||||||
@ stub EnumFormsW
|
@ stub EnumFormsW
|
||||||
|
@ -115,8 +115,8 @@
|
||||||
@ stub ProvidorFindFirstPrinterChangeNotification
|
@ stub ProvidorFindFirstPrinterChangeNotification
|
||||||
@ stub pszDbgAllocMsgA
|
@ stub pszDbgAllocMsgA
|
||||||
@ stub ReadPrinter
|
@ stub ReadPrinter
|
||||||
@ stub ReallocSplMem
|
@ stdcall ReallocSplMem(ptr long long)
|
||||||
@ stub ReallocSplStr
|
@ stdcall ReallocSplStr(ptr ptr)
|
||||||
@ stub RemoteFindFirstPrinterChangeNotification
|
@ stub RemoteFindFirstPrinterChangeNotification
|
||||||
@ stub ReplyClosePrinter
|
@ stub ReplyClosePrinter
|
||||||
@ stub ReplyOpenPrinter
|
@ stub ReplyOpenPrinter
|
||||||
|
@ -146,9 +146,9 @@
|
||||||
@ stub SplCommitSpoolData
|
@ stub SplCommitSpoolData
|
||||||
@ stub SplDriverUnloadComplete
|
@ stub SplDriverUnloadComplete
|
||||||
@ stub SplGetSpoolFileInfo
|
@ stub SplGetSpoolFileInfo
|
||||||
@ stub SplInitializeWinSpoolDrv
|
@ stdcall SplInitializeWinSpoolDrv(ptr)
|
||||||
@ stub SplIsSessionZero
|
@ stub SplIsSessionZero
|
||||||
@ stub SplIsUpgrade
|
@ stdcall SplIsUpgrade()
|
||||||
@ stub SplPowerEvent
|
@ stub SplPowerEvent
|
||||||
@ stub SplProcessPnPEvent
|
@ stub SplProcessPnPEvent
|
||||||
@ stub SplPromptUIInUsersSession
|
@ stub SplPromptUIInUsersSession
|
||||||
|
|
|
@ -1,169 +1,200 @@
|
||||||
@ stub AbortPrinter
|
100 stub -noname EnumPrinterPropertySheets
|
||||||
@ stub AddFormA
|
101 stub -noname ClusterSplOpen
|
||||||
@ stub AddFormW
|
102 stub -noname ClusterSplClose
|
||||||
@ stub AddJobA
|
103 stub -noname ClusterSplIsAlive
|
||||||
@ stub AddJobW
|
104 stub PerfClose
|
||||||
@ stub AddMonitorA
|
105 stub PerfCollect
|
||||||
@ stub AddMonitorW
|
106 stub PerfOpen
|
||||||
@ stub AddPortA
|
107 stub ADVANCEDSETUPDIALOG
|
||||||
@ stub AddPortExA
|
108 stub AbortPrinter
|
||||||
@ stub AddPortExW
|
109 stub AddFormA
|
||||||
@ stub AddPortW
|
110 stub AddFormW
|
||||||
@ stub AddPrinterA
|
111 stub AddJobA
|
||||||
@ stub AddPrinterConnectionA
|
112 stub AddJobW
|
||||||
@ stub AddPrinterConnectionW
|
113 stub AddMonitorA
|
||||||
@ stub AddPrinterDriverA
|
114 stub AddMonitorW
|
||||||
@ stub AddPrinterDriverExA
|
115 stub AddPortA
|
||||||
@ stub AddPrinterDriverExW
|
116 stub AddPortExA
|
||||||
@ stub AddPrinterDriverW
|
117 stub AddPortExW
|
||||||
@ stub AddPrinterW
|
118 stub AddPortW
|
||||||
@ stub AddPrintProcessorA
|
119 stub AddPrintProcessorA
|
||||||
@ stub AddPrintProcessorW
|
120 stub AddPrintProcessorW
|
||||||
@ stub AddPrintProvidorA
|
121 stub AddPrintProvidorA
|
||||||
@ stub AddPrintProvidorW
|
122 stub AddPrintProvidorW
|
||||||
@ stub AdvancedDocumentPropertiesA
|
123 stub AddPrinterA
|
||||||
@ stub AdvancedDocumentPropertiesW
|
124 stub AddPrinterConnectionA
|
||||||
@ stub ADVANCEDSETUPDIALOG
|
125 stub AddPrinterConnectionW
|
||||||
@ stub AdvancedSetupDialog
|
126 stub AddPrinterDriverA
|
||||||
@ stdcall ClosePrinter(long)
|
127 stub AddPrinterDriverExA
|
||||||
@ stub CloseSpoolFileHandle
|
128 stub AddPrinterDriverExW
|
||||||
@ stub CommitSpoolData
|
129 stub AddPrinterDriverW
|
||||||
@ stub ConfigurePortA
|
130 stub AddPrinterW
|
||||||
@ stub ConfigurePortW
|
131 stub AdvancedDocumentPropertiesA
|
||||||
@ stub ConnectToPrinterDlg
|
132 stub AdvancedDocumentPropertiesW
|
||||||
@ stub ConvertAnsiDevModeToUnicodeDevmode
|
133 stub AdvancedSetupDialog
|
||||||
@ stub ConvertUnicodeDevModeToAnsiDevmode
|
134 stdcall ClosePrinter(long)
|
||||||
@ stub CreatePrinterIC
|
135 stub CloseSpoolFileHandle
|
||||||
@ stub DeleteFormA
|
136 stub CommitSpoolData
|
||||||
@ stub DeleteFormW
|
137 stub ConfigurePortA
|
||||||
@ stub DeleteMonitorA
|
138 stub ConfigurePortW
|
||||||
@ stub DeleteMonitorW
|
139 stub ConnectToPrinterDlg
|
||||||
@ stub DeletePortA
|
140 stub ConvertAnsiDevModeToUnicodeDevmode
|
||||||
@ stub DeletePortW
|
141 stub ConvertUnicodeDevModeToAnsiDevmode
|
||||||
@ stub DeletePrinter
|
142 stub CreatePrinterIC
|
||||||
@ stub DeletePrinterConnectionA
|
143 stub DEVICECAPABILITIES
|
||||||
@ stub DeletePrinterConnectionW
|
144 stub DEVICEMODE
|
||||||
@ stub DeletePrinterDataA
|
145 stub DeleteFormA
|
||||||
@ stub DeletePrinterDataExA
|
146 stub DeleteFormW
|
||||||
@ stub DeletePrinterDataExW
|
147 stub DeleteMonitorA
|
||||||
@ stub DeletePrinterDataW
|
148 stub DeleteMonitorW
|
||||||
@ stub DeletePrinterDriverA
|
149 stub DeletePortA
|
||||||
@ stub DeletePrinterDriverExA
|
150 stub DeletePortW
|
||||||
@ stub DeletePrinterDriverExW
|
151 stub DeletePrintProcessorA
|
||||||
@ stub DeletePrinterDriverW
|
152 stub DeletePrintProcessorW
|
||||||
@ stub DeletePrinterIC
|
153 stub DeletePrintProvidorA
|
||||||
@ stub DeletePrinterKeyA
|
154 stub DeletePrintProvidorW
|
||||||
@ stub DeletePrinterKeyW
|
155 stub DeletePrinter
|
||||||
@ stub DeletePrintProcessorA
|
156 stub DeletePrinterConnectionA
|
||||||
@ stub DeletePrintProcessorW
|
157 stub DeletePrinterConnectionW
|
||||||
@ stub DeletePrintProvidorA
|
158 stub DeletePrinterDataA
|
||||||
@ stub DeletePrintProvidorW
|
159 stub DeletePrinterDataExA
|
||||||
@ stub DEVICECAPABILITIES
|
160 stub DeletePrinterDataExW
|
||||||
@ stub DeviceCapabilities
|
161 stub DeletePrinterDataW
|
||||||
@ stdcall DeviceCapabilitiesA(str str long ptr ptr)
|
162 stub DeletePrinterDriverA
|
||||||
@ stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr)
|
163 stub DeletePrinterDriverExA
|
||||||
@ stub DEVICEMODE
|
164 stub DeletePrinterDriverExW
|
||||||
@ stub DeviceMode
|
165 stub DeletePrinterDriverW
|
||||||
@ stub DevicePropertySheets
|
166 stub DeletePrinterIC
|
||||||
@ stub DevQueryPrint
|
167 stub DeletePrinterKeyA
|
||||||
@ stub DevQueryPrintEx
|
168 stub DeletePrinterKeyW
|
||||||
@ stub DocumentEvent
|
169 stub DevQueryPrint
|
||||||
@ stdcall DocumentPropertiesA(long long ptr ptr ptr long)
|
170 stub DevQueryPrintEx
|
||||||
@ stdcall DocumentPropertiesW(long long ptr ptr ptr long)
|
171 stub DeviceCapabilities
|
||||||
@ stub DocumentPropertySheets
|
172 stdcall DeviceCapabilitiesA(str str long ptr ptr)
|
||||||
@ stdcall EndDocPrinter(long)
|
173 stdcall DeviceCapabilitiesW(wstr wstr long ptr ptr)
|
||||||
@ stdcall EndPagePrinter(long)
|
174 stub DeviceMode
|
||||||
@ stub EnumFormsA
|
175 stub DevicePropertySheets
|
||||||
@ stub EnumFormsW
|
176 stub DocumentEvent
|
||||||
@ stub EnumJobsA
|
177 stdcall DocumentPropertiesA(long long ptr ptr ptr long)
|
||||||
@ stub EnumJobsW
|
178 stdcall DocumentPropertiesW(long long ptr ptr ptr long)
|
||||||
@ stub EnumMonitorsA
|
179 stub DocumentPropertySheets
|
||||||
@ stub EnumMonitorsW
|
180 stub EXTDEVICEMODE
|
||||||
@ stub EnumPortsA
|
181 stdcall EndDocPrinter(long)
|
||||||
@ stub EnumPortsW
|
182 stdcall EndPagePrinter(long)
|
||||||
@ stub EnumPrinterDataA
|
183 stub EnumFormsA
|
||||||
@ stub EnumPrinterDataExA
|
184 stub EnumFormsW
|
||||||
@ stub EnumPrinterDataExW
|
185 stub EnumJobsA
|
||||||
@ stub EnumPrinterDataW
|
186 stub EnumJobsW
|
||||||
@ stub EnumPrinterDriversA
|
187 stub EnumMonitorsA
|
||||||
@ stub EnumPrinterDriversW
|
188 stub EnumMonitorsW
|
||||||
@ stub EnumPrinterKeyA
|
189 stub EnumPortsA
|
||||||
@ stub EnumPrinterKeyW
|
190 stub EnumPortsW
|
||||||
@ stdcall EnumPrintersA(long ptr long ptr long ptr ptr)
|
191 stdcall EnumPrintProcessorDatatypesA(ptr ptr long ptr long ptr ptr)
|
||||||
@ stdcall EnumPrintersW(long ptr long ptr long ptr ptr)
|
192 stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr)
|
||||||
@ stdcall EnumPrintProcessorDatatypesA(ptr ptr long ptr long ptr ptr)
|
193 stub EnumPrintProcessorsA
|
||||||
@ stdcall EnumPrintProcessorDatatypesW(ptr ptr long ptr long ptr ptr)
|
194 stub EnumPrintProcessorsW
|
||||||
@ stub EnumPrintProcessorsA
|
195 stub EnumPrinterDataA
|
||||||
@ stub EnumPrintProcessorsW
|
196 stub EnumPrinterDataExA
|
||||||
@ stub EXTDEVICEMODE
|
197 stub EnumPrinterDataExW
|
||||||
@ stub ExtDeviceMode
|
198 stub EnumPrinterDataW
|
||||||
@ stub FindClosePrinterChangeNotification
|
199 stub EnumPrinterDriversA
|
||||||
@ stub FindFirstPrinterChangeNotification
|
200 stub EnumPrinterDriversW
|
||||||
@ stub FindNextPrinterChangeNotification
|
201 stdcall GetDefaultPrinterA(ptr ptr)
|
||||||
@ stub FlushPrinter
|
202 stub SetDefaultPrinterA
|
||||||
@ stub FreePrinterNotifyInfo
|
203 stdcall GetDefaultPrinterW(ptr ptr)
|
||||||
@ stdcall GetDefaultPrinterA(ptr ptr)
|
204 stub SetDefaultPrinterW
|
||||||
@ stdcall GetDefaultPrinterW(ptr ptr)
|
205 stub -noname SplReadPrinter
|
||||||
@ stub GetFormA
|
206 stub -noname AddPerMachineConnectionA
|
||||||
@ stub GetFormW
|
207 stub -noname AddPerMachineConnectionW
|
||||||
@ stub GetJobA
|
208 stub -noname DeletePerMachineConnectionA
|
||||||
@ stub GetJobW
|
209 stub -noname DeletePerMachineConnectionW
|
||||||
@ stdcall GetPrinterA(long long ptr long ptr)
|
210 stub -noname EnumPerMachineConnectionsA
|
||||||
@ stub GetPrinterDataA
|
211 stub -noname EnumPerMachineConnectionsW
|
||||||
@ stub GetPrinterDataExA
|
212 stub -noname LoadPrinterDriver
|
||||||
@ stub GetPrinterDataExW
|
213 stub -noname RefCntLoadDriver
|
||||||
@ stub GetPrinterDataW
|
214 stub -noname RefCntUnloadDriver
|
||||||
@ stdcall GetPrinterDriverA(long str long ptr long ptr)
|
215 stub -noname ForceUnloadDriver
|
||||||
@ stub GetPrinterDriverDirectoryA
|
216 stub -noname PublishPrinterA
|
||||||
@ stub GetPrinterDriverDirectoryW
|
217 stub -noname PublishPrinterW
|
||||||
@ stdcall GetPrinterDriverW(long wstr long ptr long ptr)
|
218 stub -noname CallCommonPropertySheetUI
|
||||||
@ stdcall GetPrinterW(long long ptr long ptr)
|
219 stub -noname PrintUIQueueCreate
|
||||||
@ stub GetPrintProcessorDirectoryA
|
220 stub -noname PrintUIPrinterPropPages
|
||||||
@ stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr)
|
221 stub -noname PrintUIDocumentDefaults
|
||||||
@ stub GetSpoolFileHandle
|
222 stub -noname SendRecvBidiData
|
||||||
@ stub IsValidDevmodeA
|
223 stub -noname RouterFreeBidiResponseContainer
|
||||||
@ stub IsValidDevmodeW
|
224 stub -noname ExternalConnectToLd64In32Server
|
||||||
@ stdcall OpenPrinterA(str ptr ptr)
|
225 stub EnumPrinterKeyA
|
||||||
@ stdcall OpenPrinterW(wstr ptr ptr)
|
226 stub -noname PrintUIWebPnpEntry
|
||||||
@ stub PerfClose
|
227 stub -noname PrintUIWebPnpPostEntry
|
||||||
@ stub PerfCollect
|
228 stub -noname PrintUICreateInstance
|
||||||
@ stub PerfOpen
|
229 stub -noname PrintUIDocumentPropertiesWrap
|
||||||
@ stub PlayGdiScriptOnPrinterIC
|
230 stub -noname PrintUIPrinterSetup
|
||||||
@ stub PrinterMessageBoxA
|
231 stub -noname PrintUIServerPropPages
|
||||||
@ stub PrinterMessageBoxW
|
232 stub -noname AddDriverCatalog
|
||||||
@ stub PrinterProperties
|
233 stub EnumPrinterKeyW
|
||||||
@ stub QueryColorProfile
|
234 stdcall EnumPrintersA(long ptr long ptr long ptr ptr)
|
||||||
@ stub QueryRemoteFonts
|
235 stdcall EnumPrintersW(long ptr long ptr long ptr ptr)
|
||||||
@ stub QuerySpoolMode
|
236 stub ExtDeviceMode
|
||||||
@ stub ReadPrinter
|
237 stub FindClosePrinterChangeNotification
|
||||||
@ stub ResetPrinterA
|
238 stub FindFirstPrinterChangeNotification
|
||||||
@ stub ResetPrinterW
|
239 stub FindNextPrinterChangeNotification
|
||||||
@ stub ScheduleJob
|
240 stub FlushPrinter
|
||||||
@ stub SeekPrinter
|
241 stub FreePrinterNotifyInfo
|
||||||
@ stub SetAllocFailCount
|
242 stub GetFormA
|
||||||
@ stub SetDefaultPrinterA
|
243 stub GetFormW
|
||||||
@ stub SetDefaultPrinterW
|
244 stub GetJobA
|
||||||
@ stub SetFormA
|
245 stub GetJobW
|
||||||
@ stub SetFormW
|
246 stub GetPrintProcessorDirectoryA
|
||||||
@ stub SetJobA
|
247 stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr)
|
||||||
@ stub SetJobW
|
248 stdcall GetPrinterA(long long ptr long ptr)
|
||||||
@ stub SetPortA
|
249 stub GetPrinterDataA
|
||||||
@ stub SetPortW
|
250 stub GetPrinterDataExA
|
||||||
@ stub SetPrinterA
|
251 stub GetPrinterDataExW
|
||||||
@ stub SetPrinterDataA
|
252 stub GetPrinterDataW
|
||||||
@ stub SetPrinterDataExA
|
253 stdcall GetPrinterDriverA(long str long ptr long ptr)
|
||||||
@ stub SetPrinterDataExW
|
254 stub GetPrinterDriverDirectoryA
|
||||||
@ stub SetPrinterDataW
|
255 stub GetPrinterDriverDirectoryW
|
||||||
@ stub SetPrinterW
|
256 stdcall GetPrinterDriverW(long wstr long ptr long ptr)
|
||||||
@ stub SplDriverUnloadComplete
|
257 stdcall GetPrinterW(long long ptr long ptr)
|
||||||
@ stub SpoolerDevQueryPrintW
|
258 stub GetSpoolFileHandle
|
||||||
@ stdcall SpoolerInit()
|
259 stub IsValidDevmodeA
|
||||||
@ stub SpoolerPrinterEvent
|
260 stub IsValidDevmodeW
|
||||||
@ stub StartDocDlgA
|
261 stdcall OpenPrinterA(str ptr ptr)
|
||||||
@ stub StartDocDlgW
|
262 stdcall OpenPrinterW(wstr ptr ptr)
|
||||||
@ stub StartDocPrinterA
|
263 stub PlayGdiScriptOnPrinterIC
|
||||||
@ stdcall StartDocPrinterW(long long ptr)
|
264 stub PrinterMessageBoxA
|
||||||
@ stdcall StartPagePrinter(long)
|
265 stub PrinterMessageBoxW
|
||||||
@ stub WaitForPrinterChange
|
266 stub PrinterProperties
|
||||||
@ stdcall WritePrinter(long ptr long ptr)
|
267 stub QueryColorProfile
|
||||||
@ stdcall XcvDataW(long wstr ptr long ptr long ptr ptr)
|
268 stub QueryRemoteFonts
|
||||||
|
269 stub QuerySpoolMode
|
||||||
|
270 stub ReadPrinter
|
||||||
|
271 stub ResetPrinterA
|
||||||
|
272 stub ResetPrinterW
|
||||||
|
273 stub ScheduleJob
|
||||||
|
274 stub SeekPrinter
|
||||||
|
275 stub SetAllocFailCount
|
||||||
|
276 stub SetFormA
|
||||||
|
277 stub SetFormW
|
||||||
|
278 stub SetJobA
|
||||||
|
279 stub SetJobW
|
||||||
|
280 stub SetPortA
|
||||||
|
281 stub SetPortW
|
||||||
|
282 stub SetPrinterA
|
||||||
|
283 stub SetPrinterDataA
|
||||||
|
284 stub SetPrinterDataExA
|
||||||
|
285 stub SetPrinterDataExW
|
||||||
|
286 stub SetPrinterDataW
|
||||||
|
287 stub SetPrinterW
|
||||||
|
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)
|
||||||
|
|
|
@ -8,7 +8,13 @@
|
||||||
#ifndef _REACTOS_SPOOLSS_H
|
#ifndef _REACTOS_SPOOLSS_H
|
||||||
#define _REACTOS_SPOOLSS_H
|
#define _REACTOS_SPOOLSS_H
|
||||||
|
|
||||||
PBYTE WINAPI
|
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
|
||||||
PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd);
|
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
|
||||||
|
BOOL WINAPI DllFreeSplMem(PVOID pMem);
|
||||||
|
BOOL WINAPI DllFreeSplStr(PWSTR pwszString);
|
||||||
|
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
|
#endif
|
||||||
|
|
|
@ -17,6 +17,6 @@ add_library(localspl SHARED
|
||||||
|
|
||||||
set_module_type(localspl win32dll UNICODE)
|
set_module_type(localspl win32dll UNICODE)
|
||||||
target_link_libraries(localspl wine)
|
target_link_libraries(localspl wine)
|
||||||
add_importlibs(localspl advapi32 msvcrt kernel32 ntdll)
|
add_importlibs(localspl advapi32 spoolss msvcrt kernel32 ntdll)
|
||||||
add_pch(localspl precomp.h SOURCE)
|
add_pch(localspl precomp.h SOURCE)
|
||||||
add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all)
|
add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all)
|
||||||
|
|
|
@ -13,7 +13,7 @@ void
|
||||||
InitializeJobQueue()
|
InitializeJobQueue()
|
||||||
{
|
{
|
||||||
const WCHAR wszPath[] = L"\\PRINTERS\\?????.SHD";
|
const WCHAR wszPath[] = L"\\PRINTERS\\?????.SHD";
|
||||||
const DWORD cchPath = sizeof(wszPath) / sizeof(WCHAR) - 1;
|
const DWORD cchPath = _countof(wszPath) - 1;
|
||||||
const DWORD cchFolders = sizeof("\\PRINTERS\\") - 1;
|
const DWORD cchFolders = sizeof("\\PRINTERS\\") - 1;
|
||||||
const DWORD cchPattern = sizeof("?????") - 1;
|
const DWORD cchPattern = sizeof("?????") - 1;
|
||||||
|
|
||||||
|
@ -86,10 +86,10 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
|
||||||
|
|
||||||
// Get its file size (small enough for a single DWORD) and allocate memory for all of it.
|
// Get its file size (small enough for a single DWORD) and allocate memory for all of it.
|
||||||
cbFileSize = GetFileSize(hFile, NULL);
|
cbFileSize = GetFileSize(hFile, NULL);
|
||||||
pShadowFile = HeapAlloc(hProcessHeap, 0, cbFileSize);
|
pShadowFile = DllAllocSplMem(cbFileSize);
|
||||||
if (!pShadowFile)
|
if (!pShadowFile)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,17 +117,17 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new job structure and copy over the relevant fields.
|
// Create a new job structure and copy over the relevant fields.
|
||||||
pJob = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_JOB));
|
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
|
||||||
if (!pJob)
|
if (!pJob)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pJob->dwJobID = pShadowFile->dwJobID;
|
pJob->dwJobID = pShadowFile->dwJobID;
|
||||||
pJob->Printer = pPrinter;
|
pJob->Printer = pPrinter;
|
||||||
pJob->pwszDatatype = DuplicateStringW((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype));
|
pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype));
|
||||||
pJob->pwszDocumentName = DuplicateStringW((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName));
|
pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName));
|
||||||
pJob->pwszOutputFile = NULL;
|
pJob->pwszOutputFile = NULL;
|
||||||
CopyMemory(&pJob->DevMode, (PDEVMODEW)((ULONG_PTR)pShadowFile + pShadowFile->offDevMode), sizeof(DEVMODEW));
|
CopyMemory(&pJob->DevMode, (PDEVMODEW)((ULONG_PTR)pShadowFile + pShadowFile->offDevMode), sizeof(DEVMODEW));
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pShadowFile)
|
if (pShadowFile)
|
||||||
HeapFree(hProcessHeap, 0, pShadowFile);
|
DllFreeSplMem(pShadowFile);
|
||||||
|
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
|
@ -171,10 +171,10 @@ WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob)
|
||||||
cbFileSize = sizeof(SHD_HEADER) + cbDatatype + cbDocumentName + cbPrinterName;
|
cbFileSize = sizeof(SHD_HEADER) + cbDatatype + cbDocumentName + cbPrinterName;
|
||||||
|
|
||||||
// Allocate memory for it.
|
// Allocate memory for it.
|
||||||
pShadowFile = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, cbFileSize);
|
pShadowFile = DllAllocSplMem(cbFileSize);
|
||||||
if (!pShadowFile)
|
if (!pShadowFile)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob)
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pShadowFile)
|
if (pShadowFile)
|
||||||
HeapFree(hProcessHeap, 0, pShadowFile);
|
DllFreeSplMem(pShadowFile);
|
||||||
|
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
if (hFile != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
|
@ -223,10 +223,10 @@ FreeJob(PLOCAL_JOB pJob)
|
||||||
{
|
{
|
||||||
////////// TODO /////////
|
////////// TODO /////////
|
||||||
/// Add some checks
|
/// Add some checks
|
||||||
HeapFree(hProcessHeap, 0, pJob->pwszDatatype);
|
DllFreeSplStr(pJob->pwszDatatype);
|
||||||
HeapFree(hProcessHeap, 0, pJob->pwszDocumentName);
|
DllFreeSplStr(pJob->pwszDocumentName);
|
||||||
HeapFree(hProcessHeap, 0, pJob->pwszOutputFile);
|
DllFreeSplStr(pJob->pwszOutputFile);
|
||||||
HeapFree(hProcessHeap, 0, pJob);
|
DllFreeSplMem(pJob);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
|
|
||||||
// Global Variables
|
// Global Variables
|
||||||
HANDLE hProcessHeap;
|
|
||||||
WCHAR wszSpoolDirectory[MAX_PATH];
|
WCHAR wszSpoolDirectory[MAX_PATH];
|
||||||
DWORD cchSpoolDirectory;
|
DWORD cchSpoolDirectory;
|
||||||
|
|
||||||
|
@ -24,6 +23,12 @@ const WCHAR wszCurrentEnvironment[] =
|
||||||
#error Unsupported architecture
|
#error Unsupported architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const WCHAR* wszPrintProviderInfo[3] = {
|
||||||
|
L"Windows NT Local Print Providor", // Name
|
||||||
|
L"Windows NT Local Printers", // Description
|
||||||
|
L"Locally connected Printers" // Comment
|
||||||
|
};
|
||||||
|
|
||||||
static const PRINTPROVIDOR PrintProviderFunctions = {
|
static const PRINTPROVIDOR PrintProviderFunctions = {
|
||||||
LocalOpenPrinter, // fpOpenPrinter
|
LocalOpenPrinter, // fpOpenPrinter
|
||||||
NULL, // fpSetJob
|
NULL, // fpSetJob
|
||||||
|
@ -117,7 +122,7 @@ static void
|
||||||
_GetSpoolDirectory()
|
_GetSpoolDirectory()
|
||||||
{
|
{
|
||||||
const WCHAR wszSpoolPath[] = L"\\spool";
|
const WCHAR wszSpoolPath[] = L"\\spool";
|
||||||
const DWORD cchSpoolPath = sizeof(wszSpoolPath) / sizeof(WCHAR) - 1;
|
const DWORD cchSpoolPath = _countof(wszSpoolPath) - 1;
|
||||||
|
|
||||||
// Get the system directory and append the "spool" subdirectory.
|
// 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...
|
// Forget about length checks here. If this doesn't fit into MAX_PATH, our OS has more serious problems...
|
||||||
|
@ -133,7 +138,6 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
hProcessHeap = GetProcessHeap();
|
|
||||||
_GetSpoolDirectory();
|
_GetSpoolDirectory();
|
||||||
InitializePrintProcessorTable();
|
InitializePrintProcessorTable();
|
||||||
InitializePrinterTable();
|
InitializePrinterTable();
|
||||||
|
@ -146,14 +150,7 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
|
InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
|
||||||
{
|
{
|
||||||
DWORD cbCopy;
|
CopyMemory(pPrintProvidor, &PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
|
||||||
|
|
||||||
if (cbPrintProvidor < sizeof(PRINTPROVIDOR))
|
|
||||||
cbCopy = cbPrintProvidor;
|
|
||||||
else
|
|
||||||
cbCopy = sizeof(PRINTPROVIDOR);
|
|
||||||
|
|
||||||
CopyMemory(pPrintProvidor, &PrintProviderFunctions, cbCopy);
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#define WIN32_NO_STATUS
|
#define WIN32_NO_STATUS
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
|
||||||
#include <windef.h>
|
#include <windef.h>
|
||||||
|
@ -20,6 +21,8 @@
|
||||||
#include <winsplp.h>
|
#include <winsplp.h>
|
||||||
#include <ndk/rtlfuncs.h>
|
#include <ndk/rtlfuncs.h>
|
||||||
|
|
||||||
|
#include <spoolss.h>
|
||||||
|
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(localspl);
|
WINE_DEFAULT_DEBUG_CHANNEL(localspl);
|
||||||
|
|
||||||
|
@ -62,6 +65,8 @@ LOCAL_PRINT_PROCESSOR, *PLOCAL_PRINT_PROCESSOR;
|
||||||
typedef struct _LOCAL_PRINTER
|
typedef struct _LOCAL_PRINTER
|
||||||
{
|
{
|
||||||
PWSTR pwszPrinterName;
|
PWSTR pwszPrinterName;
|
||||||
|
PWSTR pwszPrinterDriver;
|
||||||
|
PWSTR pwszDescription;
|
||||||
PWSTR pwszDefaultDatatype;
|
PWSTR pwszDefaultDatatype;
|
||||||
DEVMODEW DefaultDevMode;
|
DEVMODEW DefaultDevMode;
|
||||||
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
||||||
|
@ -157,7 +162,7 @@ BOOL WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob);
|
||||||
|
|
||||||
// main.c
|
// main.c
|
||||||
extern const WCHAR wszCurrentEnvironment[];
|
extern const WCHAR wszCurrentEnvironment[];
|
||||||
extern HANDLE hProcessHeap;
|
extern const WCHAR* wszPrintProviderInfo[3];
|
||||||
extern WCHAR wszSpoolDirectory[MAX_PATH];
|
extern WCHAR wszSpoolDirectory[MAX_PATH];
|
||||||
extern DWORD cchSpoolDirectory;
|
extern DWORD cchSpoolDirectory;
|
||||||
|
|
||||||
|
@ -182,7 +187,6 @@ BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, D
|
||||||
|
|
||||||
// tools.c
|
// tools.c
|
||||||
PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName);
|
PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName);
|
||||||
PWSTR DuplicateStringW(PCWSTR pwszInput);
|
|
||||||
PVOID NTAPI GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize);
|
PVOID NTAPI GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize);
|
||||||
VOID NTAPI GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer);
|
VOID NTAPI GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer);
|
||||||
|
|
||||||
|
|
|
@ -90,20 +90,20 @@ InitializePrinterTable()
|
||||||
if (pPrinter)
|
if (pPrinter)
|
||||||
{
|
{
|
||||||
if (pPrinter->pwszDefaultDatatype)
|
if (pPrinter->pwszDefaultDatatype)
|
||||||
HeapFree(hProcessHeap, 0, pPrinter->pwszDefaultDatatype);
|
DllFreeSplStr(pPrinter->pwszDefaultDatatype);
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pPrinter);
|
DllFreeSplMem(pPrinter);
|
||||||
pPrinter = NULL;
|
pPrinter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwszPrintProcessor)
|
if (pwszPrintProcessor)
|
||||||
{
|
{
|
||||||
HeapFree(hProcessHeap, 0, pwszPrintProcessor);
|
DllFreeSplStr(pwszPrintProcessor);
|
||||||
pwszPrintProcessor = NULL;
|
pwszPrintProcessor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the name of this printer.
|
// Get the name of this printer.
|
||||||
cchPrinterName = sizeof(wszPrinterName) / sizeof(WCHAR);
|
cchPrinterName = _countof(wszPrinterName);
|
||||||
lStatus = RegEnumKeyExW(hKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL);
|
lStatus = RegEnumKeyExW(hKey, i, wszPrinterName, &cchPrinterName, NULL, NULL, NULL, NULL);
|
||||||
if (lStatus == ERROR_MORE_DATA)
|
if (lStatus == ERROR_MORE_DATA)
|
||||||
{
|
{
|
||||||
|
@ -138,17 +138,27 @@ InitializePrinterTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new LOCAL_PRINTER structure for it.
|
// Create a new LOCAL_PRINTER structure for it.
|
||||||
pPrinter = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_PRINTER));
|
pPrinter = DllAllocSplMem(sizeof(LOCAL_PRINTER));
|
||||||
if (!pPrinter)
|
if (!pPrinter)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pPrinter->pwszPrinterName = DuplicateStringW(wszPrinterName);
|
pPrinter->pwszPrinterName = AllocSplStr(wszPrinterName);
|
||||||
pPrinter->pPrintProcessor = pPrintProcessor;
|
pPrinter->pPrintProcessor = pPrintProcessor;
|
||||||
InitializeListHead(&pPrinter->JobQueue);
|
InitializeListHead(&pPrinter->JobQueue);
|
||||||
|
|
||||||
|
// 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.
|
// Get the default datatype.
|
||||||
pPrinter->pwszDefaultDatatype = AllocAndRegQueryWSZ(hSubKey, L"Datatype");
|
pPrinter->pwszDefaultDatatype = AllocAndRegQueryWSZ(hSubKey, L"Datatype");
|
||||||
if (!pPrinter->pwszDefaultDatatype)
|
if (!pPrinter->pwszDefaultDatatype)
|
||||||
|
@ -183,14 +193,14 @@ InitializePrinterTable()
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszPrintProcessor)
|
if (pwszPrintProcessor)
|
||||||
HeapFree(hProcessHeap, 0, pwszPrintProcessor);
|
DllFreeSplStr(pwszPrintProcessor);
|
||||||
|
|
||||||
if (pPrinter)
|
if (pPrinter)
|
||||||
{
|
{
|
||||||
if (pPrinter->pwszDefaultDatatype)
|
if (pPrinter->pwszDefaultDatatype)
|
||||||
HeapFree(hProcessHeap, 0, pPrinter->pwszDefaultDatatype);
|
DllFreeSplStr(pPrinter->pwszDefaultDatatype);
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pPrinter);
|
DllFreeSplMem(pPrinter);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hSubKey)
|
if (hSubKey)
|
||||||
|
@ -201,13 +211,191 @@ Cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOL
|
||||||
|
_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 i;
|
||||||
|
PBYTE pPrinterInfo;
|
||||||
|
PBYTE pPrinterString;
|
||||||
|
PLOCAL_PRINTER pPrinter;
|
||||||
|
PRINTER_INFO_1W PrinterInfo1;
|
||||||
|
PVOID pRestartKey = NULL;
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INVALID_NAME);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
SetLastError(ERROR_INVALID_NAME);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
|
||||||
|
*pcReturned = 1;
|
||||||
|
|
||||||
|
// Check if the supplied buffer is large enough.
|
||||||
|
if (cbBuf < *pcbNeeded)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy over the print processor information.
|
||||||
|
((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
|
||||||
|
PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets, &pPrinterEnum[*pcbNeeded]);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the required buffer size and the number of printers.
|
||||||
|
for (pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey); pPrinter; pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey))
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
*pcReturned++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the supplied buffer is large enough.
|
||||||
|
if (cbBuf < *pcbNeeded)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 + *pcReturned * sizeof(PRINTER_INFO_1W);
|
||||||
|
|
||||||
|
// Copy over the printer information.
|
||||||
|
for (pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey); pPrinter; pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey))
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
///////////// TODO /////////////////////
|
// Do no sanity checks here. This is verified by localspl_apitest!
|
||||||
|
|
||||||
|
// Begin counting.
|
||||||
|
*pcbNeeded = 0;
|
||||||
|
*pcReturned = 0;
|
||||||
|
|
||||||
|
// Think positive :)
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
|
||||||
|
if (Flags & PRINTER_ENUM_LOCAL)
|
||||||
|
{
|
||||||
|
// The function behaves quite differently for each level.
|
||||||
|
if (Level == 1)
|
||||||
|
return _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
||||||
|
|
||||||
|
// TODO: Handle other levels.
|
||||||
|
|
||||||
|
// The caller supplied an invalid level.
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Treat it as success if the caller queried no information and we don't need to return any.
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
|
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
|
||||||
{
|
{
|
||||||
|
@ -250,7 +438,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
*p = 0;
|
*p = 0;
|
||||||
|
|
||||||
// Get the local computer name for comparison.
|
// Get the local computer name for comparison.
|
||||||
cchComputerName = sizeof(wszComputerName) / sizeof(WCHAR);
|
cchComputerName = _countof(wszComputerName);
|
||||||
if (!GetComputerNameW(wszComputerName, &cchComputerName))
|
if (!GetComputerNameW(wszComputerName, &cchComputerName))
|
||||||
{
|
{
|
||||||
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
|
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
|
||||||
|
@ -286,7 +474,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
if (cchPrinterName)
|
if (cchPrinterName)
|
||||||
{
|
{
|
||||||
// Yes, extract it.
|
// Yes, extract it.
|
||||||
pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cchPrinterName + 1) * sizeof(WCHAR));
|
pwszPrinterName = DllAllocSplMem((cchPrinterName + 1) * sizeof(WCHAR));
|
||||||
CopyMemory(pwszPrinterName, lpPrinterName, cchPrinterName * sizeof(WCHAR));
|
CopyMemory(pwszPrinterName, lpPrinterName, cchPrinterName * sizeof(WCHAR));
|
||||||
pwszPrinterName[cchPrinterName] = 0;
|
pwszPrinterName[cchPrinterName] = 0;
|
||||||
|
|
||||||
|
@ -300,7 +488,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new printer handle.
|
// Create a new printer handle.
|
||||||
pPrinterHandle = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(LOCAL_PRINTER_HANDLE));
|
pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
|
||||||
pPrinterHandle->Printer = pPrinter;
|
pPrinterHandle->Printer = pPrinter;
|
||||||
|
|
||||||
// Check if a datatype was given.
|
// Check if a datatype was given.
|
||||||
|
@ -313,12 +501,12 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pPrinterHandle->pwszDatatype = DuplicateStringW(pDefault->pDatatype);
|
pPrinterHandle->pwszDatatype = AllocSplStr(pDefault->pDatatype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use the default datatype.
|
// Use the default datatype.
|
||||||
pPrinterHandle->pwszDatatype = DuplicateStringW(pPrinter->pwszDefaultDatatype);
|
pPrinterHandle->pwszDatatype = AllocSplStr(pPrinter->pwszDefaultDatatype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a DevMode was given, otherwise use the default.
|
// Check if a DevMode was given, otherwise use the default.
|
||||||
|
@ -389,7 +577,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new handle that references a printer.
|
// Create a new handle that references a printer.
|
||||||
pHandle = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_HANDLE));
|
pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
|
||||||
pHandle->HandleType = Printer;
|
pHandle->HandleType = Printer;
|
||||||
pHandle->SpecificHandle = pPrinterHandle;
|
pHandle->SpecificHandle = pPrinterHandle;
|
||||||
}
|
}
|
||||||
|
@ -413,7 +601,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
p += sizeof("XcvMonitor ") - 1;
|
p += sizeof("XcvMonitor ") - 1;
|
||||||
|
|
||||||
///////////// TODO /////////////////////
|
///////////// TODO /////////////////////
|
||||||
pHandle = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_HANDLE));
|
pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
|
||||||
pHandle->HandleType = Monitor;
|
pHandle->HandleType = Monitor;
|
||||||
//pHandle->SpecificHandle = pMonitorHandle;
|
//pHandle->SpecificHandle = pMonitorHandle;
|
||||||
}
|
}
|
||||||
|
@ -423,7 +611,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
p += sizeof("XcvPort ") - 1;
|
p += sizeof("XcvPort ") - 1;
|
||||||
|
|
||||||
//////////// TODO //////////////////////
|
//////////// TODO //////////////////////
|
||||||
pHandle = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_HANDLE));
|
pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
|
||||||
pHandle->HandleType = Port;
|
pHandle->HandleType = Port;
|
||||||
//pHandle->SpecificHandle = pPortHandle;
|
//pHandle->SpecificHandle = pPortHandle;
|
||||||
}
|
}
|
||||||
|
@ -445,13 +633,13 @@ Cleanup:
|
||||||
if (pPrinterHandle)
|
if (pPrinterHandle)
|
||||||
{
|
{
|
||||||
if (pPrinterHandle->pwszDatatype)
|
if (pPrinterHandle->pwszDatatype)
|
||||||
HeapFree(hProcessHeap, 0, pPrinterHandle->pwszDatatype);
|
DllFreeSplStr(pPrinterHandle->pwszDatatype);
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pPrinterHandle);
|
DllFreeSplMem(pPrinterHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwszPrinterName)
|
if (pwszPrinterName)
|
||||||
HeapFree(hProcessHeap, 0, pwszPrinterName);
|
DllFreeSplMem(pwszPrinterName);
|
||||||
|
|
||||||
return bReturnValue;
|
return bReturnValue;
|
||||||
}
|
}
|
||||||
|
@ -498,7 +686,7 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
pDocumentInfo1 = (PDOC_INFO_1W)pDocInfo;
|
pDocumentInfo1 = (PDOC_INFO_1W)pDocInfo;
|
||||||
|
|
||||||
// Create a new job.
|
// Create a new job.
|
||||||
pJob = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(LOCAL_JOB));
|
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
|
||||||
pJob->Printer = pPrinterHandle->Printer;
|
pJob->Printer = pPrinterHandle->Printer;
|
||||||
|
|
||||||
// Check if a datatype was given.
|
// Check if a datatype was given.
|
||||||
|
@ -511,12 +699,12 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pJob->pwszDatatype = DuplicateStringW(pDocumentInfo1->pDatatype);
|
pJob->pwszDatatype = AllocSplStr(pDocumentInfo1->pDatatype);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Use the printer handle datatype.
|
// Use the printer handle datatype.
|
||||||
pJob->pwszDatatype = DuplicateStringW(pPrinterHandle->pwszDatatype);
|
pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over printer defaults.
|
// Copy over printer defaults.
|
||||||
|
@ -524,17 +712,17 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
|
|
||||||
// Copy over supplied information.
|
// Copy over supplied information.
|
||||||
if (pDocumentInfo1->pDocName)
|
if (pDocumentInfo1->pDocName)
|
||||||
pJob->pwszDocumentName = DuplicateStringW(pDocumentInfo1->pDocName);
|
pJob->pwszDocumentName = AllocSplStr(pDocumentInfo1->pDocName);
|
||||||
|
|
||||||
if (pDocumentInfo1->pOutputFile)
|
if (pDocumentInfo1->pOutputFile)
|
||||||
pJob->pwszOutputFile = DuplicateStringW(pDocumentInfo1->pOutputFile);
|
pJob->pwszOutputFile = AllocSplStr(pDocumentInfo1->pOutputFile);
|
||||||
|
|
||||||
// Enqueue the job.
|
// Enqueue the job.
|
||||||
///////////// TODO /////////////////////
|
///////////// TODO /////////////////////
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pJob)
|
if (pJob)
|
||||||
HeapFree(hProcessHeap, 0, pJob);
|
DllFreeSplMem(pJob);
|
||||||
|
|
||||||
return dwReturnValue;
|
return dwReturnValue;
|
||||||
}
|
}
|
||||||
|
@ -584,7 +772,7 @@ LocalClosePrinter(HANDLE hPrinter)
|
||||||
/// Check the handle type, do thoroughful checks on all data fields and clean them.
|
/// Check the handle type, do thoroughful checks on all data fields and clean them.
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pHandle);
|
DllFreeSplMem(pHandle);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ static BOOL
|
||||||
_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
||||||
{
|
{
|
||||||
const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
|
const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
|
||||||
const DWORD cchEnvironmentsKey = sizeof(wszEnvironmentsKey) / sizeof(WCHAR) - 1;
|
const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1;
|
||||||
|
|
||||||
BOOL bReturnValue = FALSE;
|
BOOL bReturnValue = FALSE;
|
||||||
DWORD cchEnvironment;
|
DWORD cchEnvironment;
|
||||||
|
@ -44,10 +44,10 @@ _OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
||||||
|
|
||||||
// Construct the registry key of the demanded environment.
|
// Construct the registry key of the demanded environment.
|
||||||
cchEnvironment = wcslen(pEnvironment);
|
cchEnvironment = wcslen(pEnvironment);
|
||||||
pwszEnvironmentKey = HeapAlloc(hProcessHeap, 0, (cchEnvironmentsKey + cchEnvironment + 1) * sizeof(WCHAR));
|
pwszEnvironmentKey = DllAllocSplMem((cchEnvironmentsKey + cchEnvironment + 1) * sizeof(WCHAR));
|
||||||
if (!pwszEnvironmentKey)
|
if (!pwszEnvironmentKey)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ _OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszEnvironmentKey)
|
if (pwszEnvironmentKey)
|
||||||
HeapFree(hProcessHeap, 0, pwszEnvironmentKey);
|
DllFreeSplMem(pwszEnvironmentKey);
|
||||||
|
|
||||||
return bReturnValue;
|
return bReturnValue;
|
||||||
}
|
}
|
||||||
|
@ -182,10 +182,10 @@ InitializePrintProcessorTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a temporary buffer for the Print Processor names.
|
// Allocate a temporary buffer for the Print Processor names.
|
||||||
pwszPrintProcessorName = HeapAlloc(hProcessHeap, 0, (cchMaxSubKey + 1) * sizeof(WCHAR));
|
pwszPrintProcessorName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
|
||||||
if (!pwszPrintProcessorName)
|
if (!pwszPrintProcessorName)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,15 +202,15 @@ InitializePrintProcessorTable()
|
||||||
if (pPrintProcessor)
|
if (pPrintProcessor)
|
||||||
{
|
{
|
||||||
if (pPrintProcessor->pwszName)
|
if (pPrintProcessor->pwszName)
|
||||||
HeapFree(hProcessHeap, 0, pPrintProcessor->pwszName);
|
DllFreeSplStr(pPrintProcessor->pwszName);
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pPrintProcessor);
|
DllFreeSplMem(pPrintProcessor);
|
||||||
pPrintProcessor = NULL;
|
pPrintProcessor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pDatatypesInfo1)
|
if (pDatatypesInfo1)
|
||||||
{
|
{
|
||||||
HeapFree(hProcessHeap, 0, pDatatypesInfo1);
|
DllFreeSplMem(pDatatypesInfo1);
|
||||||
pDatatypesInfo1 = NULL;
|
pDatatypesInfo1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,8 +259,8 @@ InitializePrintProcessorTable()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new LOCAL_PRINT_PROCESSOR structure for it.
|
// Create a new LOCAL_PRINT_PROCESSOR structure for it.
|
||||||
pPrintProcessor = HeapAlloc(hProcessHeap, 0, sizeof(LOCAL_PRINT_PROCESSOR));
|
pPrintProcessor = DllAllocSplMem(sizeof(LOCAL_PRINT_PROCESSOR));
|
||||||
pPrintProcessor->pwszName = DuplicateStringW(pwszPrintProcessorName);
|
pPrintProcessor->pwszName = AllocSplStr(pwszPrintProcessorName);
|
||||||
|
|
||||||
// Get and verify all its function pointers.
|
// Get and verify all its function pointers.
|
||||||
pPrintProcessor->pfnClosePrintProcessor = (PClosePrintProcessor)GetProcAddress(hinstPrintProcessor, "ClosePrintProcessor");
|
pPrintProcessor->pfnClosePrintProcessor = (PClosePrintProcessor)GetProcAddress(hinstPrintProcessor, "ClosePrintProcessor");
|
||||||
|
@ -307,10 +307,10 @@ InitializePrintProcessorTable()
|
||||||
|
|
||||||
// Get all supported datatypes.
|
// Get all supported datatypes.
|
||||||
pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0, &cbDatatypes, &dwDatatypes);
|
pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0, &cbDatatypes, &dwDatatypes);
|
||||||
pDatatypesInfo1 = HeapAlloc(hProcessHeap, 0, cbDatatypes);
|
pDatatypesInfo1 = DllAllocSplMem(cbDatatypes);
|
||||||
if (!pDatatypesInfo1)
|
if (!pDatatypesInfo1)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ InitializePrintProcessorTable()
|
||||||
|
|
||||||
for (j = 0; j < dwDatatypes; j++)
|
for (j = 0; j < dwDatatypes; j++)
|
||||||
{
|
{
|
||||||
pwszDatatype = DuplicateStringW(pDatatypesInfo1->pName);
|
pwszDatatype = AllocSplStr(pDatatypesInfo1->pName);
|
||||||
|
|
||||||
if (!RtlInsertElementGenericTable(&pPrintProcessor->DatatypeTable, pDatatypesInfo1->pName, sizeof(PWSTR), NULL))
|
if (!RtlInsertElementGenericTable(&pPrintProcessor->DatatypeTable, pDatatypesInfo1->pName, sizeof(PWSTR), NULL))
|
||||||
{
|
{
|
||||||
|
@ -350,21 +350,21 @@ InitializePrintProcessorTable()
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszDatatype)
|
if (pwszDatatype)
|
||||||
HeapFree(hProcessHeap, 0, pwszDatatype);
|
DllFreeSplStr(pwszDatatype);
|
||||||
|
|
||||||
if (pDatatypesInfo1)
|
if (pDatatypesInfo1)
|
||||||
HeapFree(hProcessHeap, 0, pDatatypesInfo1);
|
DllFreeSplMem(pDatatypesInfo1);
|
||||||
|
|
||||||
if (pPrintProcessor)
|
if (pPrintProcessor)
|
||||||
{
|
{
|
||||||
if (pPrintProcessor->pwszName)
|
if (pPrintProcessor->pwszName)
|
||||||
HeapFree(hProcessHeap, 0, pPrintProcessor->pwszName);
|
DllFreeSplStr(pPrintProcessor->pwszName);
|
||||||
|
|
||||||
HeapFree(hProcessHeap, 0, pPrintProcessor);
|
DllFreeSplMem(pPrintProcessor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pwszPrintProcessorName)
|
if (pwszPrintProcessorName)
|
||||||
HeapFree(hProcessHeap, 0, pwszPrintProcessorName);
|
DllFreeSplStr(pwszPrintProcessorName);
|
||||||
|
|
||||||
if (hSubSubKey)
|
if (hSubSubKey)
|
||||||
RegCloseKey(hSubSubKey);
|
RegCloseKey(hSubSubKey);
|
||||||
|
@ -482,7 +482,6 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
PBYTE pCurrentOutputPrintProcessor;
|
PBYTE pCurrentOutputPrintProcessor;
|
||||||
PBYTE pCurrentOutputPrintProcessorInfo;
|
PBYTE pCurrentOutputPrintProcessorInfo;
|
||||||
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
|
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
|
||||||
PWSTR pwszEnvironmentKey = NULL;
|
|
||||||
PWSTR pwszTemp = NULL;
|
PWSTR pwszTemp = NULL;
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
|
@ -520,10 +519,10 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a temporary buffer to let RegEnumKeyExW succeed.
|
// Allocate a temporary buffer to let RegEnumKeyExW succeed.
|
||||||
pwszTemp = HeapAlloc(hProcessHeap, 0, (cchMaxSubKey + 1) * sizeof(WCHAR));
|
pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
|
||||||
if (!pwszTemp)
|
if (!pwszTemp)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,10 +584,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszTemp)
|
if (pwszTemp)
|
||||||
HeapFree(hProcessHeap, 0, pwszTemp);
|
DllFreeSplMem(pwszTemp);
|
||||||
|
|
||||||
if (pwszEnvironmentKey)
|
|
||||||
HeapFree(hProcessHeap, 0, pwszEnvironmentKey);
|
|
||||||
|
|
||||||
if (hSubKey)
|
if (hSubKey)
|
||||||
RegCloseKey(hSubKey);
|
RegCloseKey(hSubKey);
|
||||||
|
@ -634,13 +630,12 @@ BOOL WINAPI
|
||||||
LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded)
|
LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded)
|
||||||
{
|
{
|
||||||
const WCHAR wszPath[] = L"\\PRTPROCS\\";
|
const WCHAR wszPath[] = L"\\PRTPROCS\\";
|
||||||
const DWORD cchPath = sizeof(wszPath) / sizeof(WCHAR) - 1;
|
const DWORD cchPath = _countof(wszPath) - 1;
|
||||||
|
|
||||||
BOOL bReturnValue = FALSE;
|
BOOL bReturnValue = FALSE;
|
||||||
DWORD cbDataWritten;
|
DWORD cbDataWritten;
|
||||||
HKEY hKey = NULL;
|
HKEY hKey = NULL;
|
||||||
LONG lStatus;
|
LONG lStatus;
|
||||||
PWSTR pwszEnvironmentKey = NULL;
|
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
|
@ -695,9 +690,6 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
|
||||||
bReturnValue = TRUE;
|
bReturnValue = TRUE;
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszEnvironmentKey)
|
|
||||||
HeapFree(hProcessHeap, 0, pwszEnvironmentKey);
|
|
||||||
|
|
||||||
if (hKey)
|
if (hKey)
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* @name AllocAndRegQueryWSZ
|
* @name AllocAndRegQueryWSZ
|
||||||
*
|
*
|
||||||
* Queries a REG_SZ value in the registry, allocates memory for it and returns a buffer containing the value.
|
* 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 HeapFree.
|
* You have to free this buffer using DllFreeSplMem.
|
||||||
*
|
*
|
||||||
* @param hKey
|
* @param hKey
|
||||||
* HKEY variable of the key opened with RegOpenKeyExW.
|
* HKEY variable of the key opened with RegOpenKeyExW.
|
||||||
|
@ -38,10 +38,10 @@ AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate it.
|
// Allocate it.
|
||||||
pwszValue = HeapAlloc(hProcessHeap, 0, cbNeeded);
|
pwszValue = DllAllocSplMem(cbNeeded);
|
||||||
if (!pwszValue)
|
if (!pwszValue)
|
||||||
{
|
{
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,63 +50,31 @@ AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName)
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (lStatus != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
|
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
|
||||||
HeapFree(hProcessHeap, 0, pwszValue);
|
DllFreeSplMem(pwszValue);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pwszValue;
|
return pwszValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @name DuplicateStringW
|
|
||||||
*
|
|
||||||
* Allocates memory for a Unicode string and copies the input string into it.
|
|
||||||
* Equivalent of wcsdup, but the returned buffer must be freed with HeapFree instead of free.
|
|
||||||
*
|
|
||||||
* @param pwszInput
|
|
||||||
* The input string to copy
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* Pointer to the copied string or NULL if no memory could be allocated.
|
|
||||||
*/
|
|
||||||
PWSTR
|
|
||||||
DuplicateStringW(PCWSTR pwszInput)
|
|
||||||
{
|
|
||||||
DWORD cchInput;
|
|
||||||
PWSTR pwszOutput;
|
|
||||||
|
|
||||||
cchInput = wcslen(pwszInput);
|
|
||||||
|
|
||||||
pwszOutput = HeapAlloc(hProcessHeap, 0, (cchInput + 1) * sizeof(WCHAR));
|
|
||||||
if (!pwszOutput)
|
|
||||||
{
|
|
||||||
ERR("HeapAlloc failed with error %lu!\n", GetLastError());
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CopyMemory(pwszOutput, pwszInput, (cchInput + 1) * sizeof(WCHAR));
|
|
||||||
|
|
||||||
return pwszOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name GenericTableAllocateRoutine
|
* @name GenericTableAllocateRoutine
|
||||||
*
|
*
|
||||||
* RTL_GENERIC_ALLOCATE_ROUTINE for all our RTL_GENERIC_TABLEs, using HeapAlloc.
|
* RTL_GENERIC_ALLOCATE_ROUTINE for all our RTL_GENERIC_TABLEs, using DllAllocSplMem.
|
||||||
*/
|
*/
|
||||||
PVOID NTAPI
|
PVOID NTAPI
|
||||||
GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize)
|
GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize)
|
||||||
{
|
{
|
||||||
return HeapAlloc(hProcessHeap, 0, ByteSize);
|
return DllAllocSplMem(ByteSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name GenericTableFreeRoutine
|
* @name GenericTableFreeRoutine
|
||||||
*
|
*
|
||||||
* RTL_GENERIC_FREE_ROUTINE for all our RTL_GENERIC_TABLEs, using HeapFree.
|
* RTL_GENERIC_FREE_ROUTINE for all our RTL_GENERIC_TABLEs, using DllFreeSplMem.
|
||||||
*/
|
*/
|
||||||
VOID NTAPI
|
VOID NTAPI
|
||||||
GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer)
|
GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer)
|
||||||
{
|
{
|
||||||
HeapFree(hProcessHeap, 0, Buffer);
|
DllFreeSplMem(Buffer);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
|
||||||
|
include_directories(${REACTOS_SOURCE_DIR}/win32ss/printing/include)
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
fpEnumPrinters.c
|
fpEnumPrinters.c
|
||||||
main.c)
|
main.c)
|
||||||
|
@ -6,6 +8,6 @@ list(APPEND SOURCE
|
||||||
add_library(localspl_apitest.dll SHARED ${SOURCE})
|
add_library(localspl_apitest.dll SHARED ${SOURCE})
|
||||||
target_link_libraries(localspl_apitest.dll wine ${PSEH_LIB})
|
target_link_libraries(localspl_apitest.dll wine ${PSEH_LIB})
|
||||||
set_module_type(localspl_apitest.dll win32dll)
|
set_module_type(localspl_apitest.dll win32dll)
|
||||||
add_importlibs(localspl_apitest.dll msvcrt kernel32 ntdll)
|
add_importlibs(localspl_apitest.dll spoolss msvcrt kernel32 ntdll)
|
||||||
set_target_properties(localspl_apitest.dll PROPERTIES SUFFIX "")
|
set_target_properties(localspl_apitest.dll PROPERTIES SUFFIX "")
|
||||||
add_cd_file(TARGET localspl_apitest.dll DESTINATION reactos/bin FOR all)
|
add_cd_file(TARGET localspl_apitest.dll DESTINATION reactos/bin FOR all)
|
||||||
|
|
|
@ -16,15 +16,19 @@
|
||||||
#include <winsplp.h>
|
#include <winsplp.h>
|
||||||
|
|
||||||
#include "../localspl_apitest.h"
|
#include "../localspl_apitest.h"
|
||||||
|
#include <spoolss.h>
|
||||||
|
|
||||||
START_TEST(fpEnumPrinters)
|
START_TEST(fpEnumPrinters)
|
||||||
{
|
{
|
||||||
DWORD cbNeeded;
|
DWORD cbNeeded;
|
||||||
|
DWORD cbTemp;
|
||||||
DWORD dwReturned;
|
DWORD dwReturned;
|
||||||
|
DWORD i;
|
||||||
HMODULE hLocalspl;
|
HMODULE hLocalspl;
|
||||||
PInitializePrintProvidor pfnInitializePrintProvidor;
|
PInitializePrintProvidor pfnInitializePrintProvidor;
|
||||||
PRINTPROVIDOR pp;
|
PRINTPROVIDOR pp;
|
||||||
PPRINTER_INFO_1W pPrinterInfo1;
|
PPRINTER_INFO_1W pPrinterInfo1;
|
||||||
|
PVOID pMem;
|
||||||
|
|
||||||
// Get us a handle to the loaded localspl.dll.
|
// Get us a handle to the loaded localspl.dll.
|
||||||
hLocalspl = GetModuleHandleW(L"localspl");
|
hLocalspl = GetModuleHandleW(L"localspl");
|
||||||
|
@ -69,4 +73,88 @@ START_TEST(fpEnumPrinters)
|
||||||
ok(wcscmp(pPrinterInfo1->pName, L"Windows NT Local Print Providor") == 0, "pPrinterInfo1->pName is \"%S\"!\n", pPrinterInfo1->pName);
|
ok(wcscmp(pPrinterInfo1->pName, L"Windows NT Local Print Providor") == 0, "pPrinterInfo1->pName is \"%S\"!\n", pPrinterInfo1->pName);
|
||||||
ok(wcscmp(pPrinterInfo1->pDescription, L"Windows NT Local Printers") == 0, "pPrinterInfo1->pDescription is \"%S\"!\n", pPrinterInfo1->pDescription);
|
ok(wcscmp(pPrinterInfo1->pDescription, L"Windows NT Local Printers") == 0, "pPrinterInfo1->pDescription is \"%S\"!\n", pPrinterInfo1->pDescription);
|
||||||
ok(wcscmp(pPrinterInfo1->pComment, L"Locally connected Printers") == 0, "pPrinterInfo1->pComment is \"%S\"!\n", pPrinterInfo1->pComment);
|
ok(wcscmp(pPrinterInfo1->pComment, L"Locally connected Printers") == 0, "pPrinterInfo1->pComment is \"%S\"!\n", pPrinterInfo1->pComment);
|
||||||
|
|
||||||
|
// Level 7 is the highest supported for localspl under Windows Server 2003.
|
||||||
|
// Higher levels need to fail, but they don't set an error code, just cbNeeded to 0.
|
||||||
|
cbNeeded = 0xDEADBEEF;
|
||||||
|
dwReturned = 0xDEADBEEF;
|
||||||
|
SetLastError(0xDEADBEEF);
|
||||||
|
ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, 8, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE!\n");
|
||||||
|
ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu!\n", GetLastError());
|
||||||
|
ok(cbNeeded == 0, "cbNeeded is %lu!\n", cbNeeded);
|
||||||
|
ok(dwReturned == 0, "dwReturned is %lu!\n", dwReturned);
|
||||||
|
|
||||||
|
// Verify that all valid levels work.
|
||||||
|
// In contrast to EnumPrintersW, which only accepts levels 0, 1, 2, 4 and 5, localspl returns information for level 0 to 7.
|
||||||
|
for (i = 0; i <= 7; i++)
|
||||||
|
{
|
||||||
|
// FIXME: For some reason, using SEH here works only once.
|
||||||
|
// We experience a hang in the testing process when you run the test again for a second time without restarting spoolsv.
|
||||||
|
#if 0
|
||||||
|
// Try with no valid arguments at all.
|
||||||
|
// This scenario is usually caugt by RPC, so it just raises an exception here.
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
dwReturned = 0;
|
||||||
|
pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, 0, NULL, NULL);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
dwReturned = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Now get the required buffer size.
|
||||||
|
cbNeeded = 0xDEADBEEF;
|
||||||
|
dwReturned = 0xDEADBEEF;
|
||||||
|
SetLastError(0xDEADBEEF);
|
||||||
|
ok(!pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns TRUE for Level %lu!\n", i);
|
||||||
|
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
|
||||||
|
ok(cbNeeded > 0, "cbNeeded is 0 for Level %lu!\n", i);
|
||||||
|
ok(dwReturned == 0, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Now provide the demanded size, but no buffer. This also mustn't touch cbNeeded.
|
||||||
|
// This scenario is also caught by RPC and we just have an exception here.
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
dwReturned = 0;
|
||||||
|
pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, NULL, cbNeeded, &cbTemp, &dwReturned);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
dwReturned = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
ok(dwReturned == EXCEPTION_ACCESS_VIOLATION, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
|
||||||
|
ok(cbNeeded == cbTemp, "cbNeeded is %lu, cbTemp is %lu for Level %lu!\n", cbNeeded, cbTemp, i);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Finally use the function as intended and aim for success!
|
||||||
|
pMem = DllAllocSplMem(cbNeeded);
|
||||||
|
SetLastError(0xDEADBEEF);
|
||||||
|
ok(pp.fpEnumPrinters(PRINTER_ENUM_LOCAL, NULL, i, pMem, cbNeeded, &cbTemp, &dwReturned), "fpEnumPrinters returns FALSE for Level %lu!\n", i);
|
||||||
|
|
||||||
|
// This is crazy. For level 3, fpEnumPrinters always returns ERROR_INSUFFICIENT_BUFFER even if we supply a buffer large enough.
|
||||||
|
if (i == 3)
|
||||||
|
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
|
||||||
|
else
|
||||||
|
ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
|
||||||
|
|
||||||
|
DllFreeSplMem(pMem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fpEnumPrinters has to succeed independent of the level (valid or not) if we query no information.
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
SetLastError(0xDEADBEEF);
|
||||||
|
ok(pp.fpEnumPrinters(0, NULL, i, NULL, 0, &cbNeeded, &dwReturned), "fpEnumPrinters returns FALSE for Level %lu!\n", i);
|
||||||
|
ok(GetLastError() == ERROR_SUCCESS, "fpEnumPrinters returns error %lu for Level %lu!\n", GetLastError(), i);
|
||||||
|
ok(cbNeeded == 0, "cbNeeded is %lu for Level %lu!\n", cbNeeded, i);
|
||||||
|
ok(dwReturned == 0, "dwReturned is %lu for Level %lu!\n", dwReturned, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include <winspool.h>
|
#include <winspool.h>
|
||||||
#include <winsplp.h>
|
#include <winsplp.h>
|
||||||
|
|
||||||
|
|
||||||
#include "../localspl_apitest.h"
|
#include "../localspl_apitest.h"
|
||||||
|
|
||||||
//#define NDEBUG
|
//#define NDEBUG
|
||||||
|
|
|
@ -40,14 +40,17 @@
|
||||||
static void
|
static void
|
||||||
_RunRemoteTest(const char* szTestName)
|
_RunRemoteTest(const char* szTestName)
|
||||||
{
|
{
|
||||||
|
BOOL bSuccessful = FALSE;
|
||||||
char szBuffer[1024];
|
char szBuffer[1024];
|
||||||
DWORD cbRead;
|
DWORD cbRead;
|
||||||
DWORD cbWritten;
|
DWORD cbWritten;
|
||||||
HANDLE hCommandPipe;
|
HANDLE hCommandPipe = INVALID_HANDLE_VALUE;
|
||||||
HANDLE hOutputPipe;
|
HANDLE hFind = NULL;
|
||||||
|
HANDLE hOutputPipe = INVALID_HANDLE_VALUE;
|
||||||
PWSTR p;
|
PWSTR p;
|
||||||
SC_HANDLE hSC;
|
SC_HANDLE hSC = NULL;
|
||||||
SC_HANDLE hService;
|
SC_HANDLE hService = NULL;
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
WCHAR wszFilePath[MAX_PATH + 20];
|
WCHAR wszFilePath[MAX_PATH + 20];
|
||||||
WIN32_FIND_DATAW fd;
|
WIN32_FIND_DATAW fd;
|
||||||
|
|
||||||
|
@ -59,7 +62,7 @@ _RunRemoteTest(const char* szTestName)
|
||||||
if (!GetModuleFileNameW(NULL, wszFilePath, MAX_PATH))
|
if (!GetModuleFileNameW(NULL, wszFilePath, MAX_PATH))
|
||||||
{
|
{
|
||||||
skip("GetModuleFileNameW failed with error %lu!\n", GetLastError());
|
skip("GetModuleFileNameW failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the extension.
|
// Replace the extension.
|
||||||
|
@ -67,16 +70,17 @@ _RunRemoteTest(const char* szTestName)
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
skip("File path has no file extension: %S\n", wszFilePath);
|
skip("File path has no file extension: %S\n", wszFilePath);
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
wcscpy(p, L".dll");
|
wcscpy(p, L".dll");
|
||||||
|
|
||||||
// Check if the corresponding DLL file exists.
|
// Check if the corresponding DLL file exists.
|
||||||
if (!FindFirstFileW(wszFilePath, &fd))
|
hFind = FindFirstFileW(wszFilePath, &fd);
|
||||||
|
if (!hFind)
|
||||||
{
|
{
|
||||||
skip("My DLL file \"%S\" does not exist!\n", wszFilePath);
|
skip("My DLL file \"%S\" does not exist!\n", wszFilePath);
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change the extension back to .exe and add the parameters.
|
// Change the extension back to .exe and add the parameters.
|
||||||
|
@ -87,9 +91,31 @@ _RunRemoteTest(const char* szTestName)
|
||||||
if (!hSC)
|
if (!hSC)
|
||||||
{
|
{
|
||||||
skip("OpenSCManagerW failed with error %lu!\n", GetLastError());
|
skip("OpenSCManagerW failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the spooler service is running.
|
||||||
|
hService = OpenServiceW(hSC, L"spooler", SERVICE_QUERY_STATUS);
|
||||||
|
if (!hService)
|
||||||
|
{
|
||||||
|
skip("OpenServiceW failed for the spooler service with error %lu!\n", GetLastError());
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!QueryServiceStatus(hService, &ServiceStatus))
|
||||||
|
{
|
||||||
|
skip("QueryServiceStatus failed for the spooler service with error %lu!\n", GetLastError());
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
|
||||||
|
{
|
||||||
|
skip("Spooler Service is not running!\n");
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseServiceHandle(hService);
|
||||||
|
|
||||||
// Try to open the service if we've created it in a previous run.
|
// Try to open the service if we've created it in a previous run.
|
||||||
hService = OpenServiceW(hSC, SERVICE_NAME, SERVICE_ALL_ACCESS);
|
hService = OpenServiceW(hSC, SERVICE_NAME, SERVICE_ALL_ACCESS);
|
||||||
if (!hService)
|
if (!hService)
|
||||||
|
@ -101,13 +127,13 @@ _RunRemoteTest(const char* szTestName)
|
||||||
if (!hService)
|
if (!hService)
|
||||||
{
|
{
|
||||||
skip("CreateServiceW failed with error %lu!\n", GetLastError());
|
skip("CreateServiceW failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
skip("OpenServiceW failed with error %lu!\n", GetLastError());
|
skip("OpenServiceW failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,56 +142,69 @@ _RunRemoteTest(const char* szTestName)
|
||||||
if (hCommandPipe == INVALID_HANDLE_VALUE)
|
if (hCommandPipe == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
skip("CreateNamedPipeW failed for the command pipe with error %lu!\n", GetLastError());
|
skip("CreateNamedPipeW failed for the command pipe with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
hOutputPipe = CreateNamedPipeW(OUTPUT_PIPE_NAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 10000, NULL);
|
hOutputPipe = CreateNamedPipeW(OUTPUT_PIPE_NAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 10000, NULL);
|
||||||
if (hOutputPipe == INVALID_HANDLE_VALUE)
|
if (hOutputPipe == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
skip("CreateNamedPipeW failed for the output pipe with error %lu!\n", GetLastError());
|
skip("CreateNamedPipeW failed for the output pipe with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the service with "service" and a dummy parameter (to distinguish it from a call by rosautotest to localspl_apitest:service)
|
// Start the service with "service" and a dummy parameter (to distinguish it from a call by rosautotest to localspl_apitest:service)
|
||||||
if (!StartServiceW(hService, 0, NULL))
|
if (!StartServiceW(hService, 0, NULL))
|
||||||
{
|
{
|
||||||
skip("StartServiceW failed with error %lu!\n", GetLastError());
|
skip("StartServiceW failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseServiceHandle(hService);
|
|
||||||
CloseServiceHandle(hSC);
|
|
||||||
|
|
||||||
// Wait till it has injected the DLL and the DLL expects its test name.
|
// Wait till it has injected the DLL and the DLL expects its test name.
|
||||||
if (!ConnectNamedPipe(hCommandPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED)
|
if (!ConnectNamedPipe(hCommandPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED)
|
||||||
{
|
{
|
||||||
skip("ConnectNamedPipe failed for the command pipe with error %lu!\n", GetLastError());
|
skip("ConnectNamedPipe failed for the command pipe with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send the test name.
|
// Send the test name.
|
||||||
if (!WriteFile(hCommandPipe, szTestName, strlen(szTestName) + sizeof(char), &cbWritten, NULL))
|
if (!WriteFile(hCommandPipe, szTestName, strlen(szTestName) + sizeof(char), &cbWritten, NULL))
|
||||||
{
|
{
|
||||||
skip("WriteFile failed with error %lu!\n", GetLastError());
|
skip("WriteFile failed with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(hCommandPipe);
|
|
||||||
|
|
||||||
// Now wait for the DLL to connect to the output pipe.
|
// Now wait for the DLL to connect to the output pipe.
|
||||||
if (!ConnectNamedPipe(hOutputPipe, NULL))
|
if (!ConnectNamedPipe(hOutputPipe, NULL))
|
||||||
{
|
{
|
||||||
skip("ConnectNamedPipe failed for the output pipe with error %lu!\n", GetLastError());
|
skip("ConnectNamedPipe failed for the output pipe with error %lu!\n", GetLastError());
|
||||||
return;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get all testing messages from the pipe and output them on stdout.
|
// Get all testing messages from the pipe and output them on stdout.
|
||||||
while (ReadFile(hOutputPipe, szBuffer, sizeof(szBuffer), &cbRead, NULL) && cbRead)
|
while (ReadFile(hOutputPipe, szBuffer, sizeof(szBuffer), &cbRead, NULL) && cbRead)
|
||||||
fwrite(szBuffer, sizeof(char), cbRead, stdout);
|
fwrite(szBuffer, sizeof(char), cbRead, stdout);
|
||||||
|
|
||||||
|
bSuccessful = TRUE;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
if (hCommandPipe)
|
||||||
|
CloseHandle(hCommandPipe);
|
||||||
|
|
||||||
|
if (hOutputPipe)
|
||||||
CloseHandle(hOutputPipe);
|
CloseHandle(hOutputPipe);
|
||||||
|
|
||||||
// Prevent the testing framework from outputting a "0 tests executed" line here.
|
if (hFind)
|
||||||
|
FindClose(hFind);
|
||||||
|
|
||||||
|
if (hService)
|
||||||
|
CloseServiceHandle(hService);
|
||||||
|
|
||||||
|
if (hSC)
|
||||||
|
CloseServiceHandle(hSC);
|
||||||
|
|
||||||
|
// If we successfully received test output through the named pipe, we have also output a summary line already.
|
||||||
|
// Prevent the testing framework from outputting another "0 tests executed" line in this case.
|
||||||
|
if (bSuccessful)
|
||||||
ExitProcess(0);
|
ExitProcess(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ include_directories(${REACTOS_SOURCE_DIR}/win32ss/printing/include)
|
||||||
|
|
||||||
list(APPEND SOURCE
|
list(APPEND SOURCE
|
||||||
PackStrings.c
|
PackStrings.c
|
||||||
|
ReallocSplStr.c
|
||||||
SplInitializeWinSpoolDrv.c
|
SplInitializeWinSpoolDrv.c
|
||||||
testlist.c)
|
testlist.c)
|
||||||
|
|
||||||
|
|
66
rostests/apitests/spoolss/ReallocSplStr.c
Normal file
66
rostests/apitests/spoolss/ReallocSplStr.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* PROJECT: ReactOS Spooler Router API Tests
|
||||||
|
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
|
||||||
|
* PURPOSE: Tests for ReallocSplStr
|
||||||
|
* COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <apitest.h>
|
||||||
|
|
||||||
|
#define WIN32_NO_STATUS
|
||||||
|
#include <windef.h>
|
||||||
|
#include <winbase.h>
|
||||||
|
#include <spoolss.h>
|
||||||
|
|
||||||
|
START_TEST(ReallocSplStr)
|
||||||
|
{
|
||||||
|
const WCHAR wszTestString1[] = L"Test";
|
||||||
|
const WCHAR wszTestString2[] = L"New";
|
||||||
|
|
||||||
|
DWORD dwResult;
|
||||||
|
PWSTR pwszBackup;
|
||||||
|
PWSTR pwszTest;
|
||||||
|
|
||||||
|
// Verify that ReallocSplStr raises an exception if all parameters are NULL.
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
dwResult = 0;
|
||||||
|
ReallocSplStr(NULL, NULL);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
dwResult = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
ok(dwResult == EXCEPTION_ACCESS_VIOLATION, "dwResult is %lx!\n", dwResult);
|
||||||
|
|
||||||
|
// Allocate a string for testing.
|
||||||
|
pwszTest = AllocSplStr(wszTestString1);
|
||||||
|
if (!pwszTest)
|
||||||
|
{
|
||||||
|
skip("AllocSplStr failed with error %lu!\n", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that ReallocSplStr frees the old string even if pwszInput is NULL.
|
||||||
|
ok(ReallocSplStr(&pwszTest, NULL), "ReallocSplStr is FALSE!\n");
|
||||||
|
ok(pwszTest == NULL, "pwszTest is %p\n", pwszTest);
|
||||||
|
|
||||||
|
// Now verify that ReallocSplStr copies the new string into a new block and frees the old one.
|
||||||
|
pwszBackup = pwszTest;
|
||||||
|
ok(ReallocSplStr(&pwszTest, wszTestString2), "ReallocSplStr is FALSE!\n");
|
||||||
|
ok(wcscmp(pwszTest, wszTestString2) == 0, "New string was not copied into pwszTest!\n");
|
||||||
|
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
dwResult = (DWORD)wcscmp(pwszBackup, wszTestString1);
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
dwResult = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END;
|
||||||
|
|
||||||
|
ok(dwResult == EXCEPTION_ACCESS_VIOLATION, "dwResult is %lx!\n", dwResult);
|
||||||
|
}
|
|
@ -15,9 +15,14 @@
|
||||||
START_TEST(SplInitializeWinSpoolDrv)
|
START_TEST(SplInitializeWinSpoolDrv)
|
||||||
{
|
{
|
||||||
HINSTANCE hWinspool;
|
HINSTANCE hWinspool;
|
||||||
void* Table[9];
|
PVOID Table[9];
|
||||||
|
|
||||||
hWinspool = LoadLibraryW(L"winspool.drv");
|
hWinspool = LoadLibraryW(L"winspool.drv");
|
||||||
|
if (!hWinspool)
|
||||||
|
{
|
||||||
|
skip("Could not load winspool.drv, last error is %lu!\n", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ok(SplInitializeWinSpoolDrv(Table), "SplInitializeWinSpoolDrv returns FALSE!\n");
|
ok(SplInitializeWinSpoolDrv(Table), "SplInitializeWinSpoolDrv returns FALSE!\n");
|
||||||
ok(Table[0] == GetProcAddress(hWinspool, "OpenPrinterW"), "Table[0] is %p\n", Table[0]);
|
ok(Table[0] == GetProcAddress(hWinspool, "OpenPrinterW"), "Table[0] is %p\n", Table[0]);
|
||||||
|
|
|
@ -11,11 +11,13 @@
|
||||||
#include <apitest.h>
|
#include <apitest.h>
|
||||||
|
|
||||||
extern void func_PackStrings(void);
|
extern void func_PackStrings(void);
|
||||||
|
extern void func_ReallocSplStr(void);
|
||||||
extern void func_SplInitializeWinSpoolDrv(void);
|
extern void func_SplInitializeWinSpoolDrv(void);
|
||||||
|
|
||||||
const struct test winetest_testlist[] =
|
const struct test winetest_testlist[] =
|
||||||
{
|
{
|
||||||
{ "PackStrings", func_PackStrings },
|
{ "PackStrings", func_PackStrings },
|
||||||
|
{ "ReallocSplStr", func_ReallocSplStr },
|
||||||
{ "SplInitializeWinSpoolDrv", func_SplInitializeWinSpoolDrv },
|
{ "SplInitializeWinSpoolDrv", func_SplInitializeWinSpoolDrv },
|
||||||
|
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue