winspool: Revise EnumPrinterDriversW to fix the incorrect handling of 'all'. EnumPrinterDriversA is similarly fixed by using EnumPrinterDriversW.
This commit is contained in:
parent
9c56314e3d
commit
10e70fbd18
@ -4838,45 +4838,22 @@ BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
|
|||||||
*/
|
*/
|
||||||
static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment,
|
static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment,
|
||||||
DWORD Level, LPBYTE pDriverInfo,
|
DWORD Level, LPBYTE pDriverInfo,
|
||||||
|
DWORD driver_index,
|
||||||
DWORD cbBuf, LPDWORD pcbNeeded,
|
DWORD cbBuf, LPDWORD pcbNeeded,
|
||||||
LPDWORD pcReturned, BOOL unicode)
|
LPDWORD pcFound, DWORD data_offset)
|
||||||
|
|
||||||
{ HKEY hkeyDrivers;
|
{ HKEY hkeyDrivers;
|
||||||
DWORD i, needed, number = 0, size = 0;
|
DWORD i, size = 0;
|
||||||
WCHAR DriverNameW[255];
|
|
||||||
PBYTE ptr;
|
|
||||||
const printenv_t * env;
|
const printenv_t * env;
|
||||||
|
|
||||||
TRACE("%s,%s,%d,%p,%d,%d\n",
|
TRACE("%s,%s,%d,%p,%d,%d,%d\n",
|
||||||
debugstr_w(pName), debugstr_w(pEnvironment),
|
debugstr_w(pName), debugstr_w(pEnvironment),
|
||||||
Level, pDriverInfo, cbBuf, unicode);
|
Level, pDriverInfo, driver_index, cbBuf, data_offset);
|
||||||
|
|
||||||
/* check for local drivers */
|
|
||||||
if((pName) && (pName[0])) {
|
|
||||||
FIXME("remote drivers (%s) not supported!\n", debugstr_w(pName));
|
|
||||||
SetLastError(ERROR_ACCESS_DENIED);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
env = validate_envW(pEnvironment);
|
env = validate_envW(pEnvironment);
|
||||||
if (!env) return FALSE; /* SetLastError() is in validate_envW */
|
if (!env) return FALSE; /* SetLastError() is in validate_envW */
|
||||||
|
|
||||||
/* check input parameter */
|
*pcFound = 0;
|
||||||
if ((Level < 1) || (Level == 7) || (Level > 8)) {
|
|
||||||
SetLastError(ERROR_INVALID_LEVEL);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((pcbNeeded == NULL) || (pcReturned == NULL)) {
|
|
||||||
SetLastError(RPC_X_NULL_REF_POINTER);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* initialize return values */
|
|
||||||
if(pDriverInfo)
|
|
||||||
memset( pDriverInfo, 0, cbBuf);
|
|
||||||
*pcbNeeded = 0;
|
|
||||||
*pcReturned = 0;
|
|
||||||
|
|
||||||
hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment);
|
hkeyDrivers = WINSPOOL_OpenDriverReg(pEnvironment);
|
||||||
if(!hkeyDrivers) {
|
if(!hkeyDrivers) {
|
||||||
@ -4884,39 +4861,49 @@ static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
|
if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, pcFound, NULL, NULL,
|
||||||
NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
|
NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
|
||||||
RegCloseKey(hkeyDrivers);
|
RegCloseKey(hkeyDrivers);
|
||||||
ERR("Can't query Drivers key\n");
|
ERR("Can't query Drivers key\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
TRACE("Found %d Drivers\n", number);
|
TRACE("Found %d Drivers\n", *pcFound);
|
||||||
|
|
||||||
/* get size of single struct
|
/* get size of single struct
|
||||||
* unicode and ascii structure have the same size
|
* unicode and ascii structure have the same size
|
||||||
*/
|
*/
|
||||||
size = di_sizeof[Level];
|
size = di_sizeof[Level];
|
||||||
|
|
||||||
/* calculate required buffer size */
|
if (data_offset == 0)
|
||||||
*pcbNeeded = size * number;
|
data_offset = size * (*pcFound);
|
||||||
|
*pcbNeeded = data_offset;
|
||||||
|
|
||||||
|
for( i = 0; i < *pcFound; i++) {
|
||||||
|
WCHAR DriverNameW[255];
|
||||||
|
PBYTE table_ptr = NULL;
|
||||||
|
PBYTE data_ptr = NULL;
|
||||||
|
DWORD needed = 0;
|
||||||
|
|
||||||
for( i = 0, ptr = (pDriverInfo && (cbBuf >= size)) ? pDriverInfo : NULL ;
|
|
||||||
i < number;
|
|
||||||
i++, ptr = (ptr && (cbBuf >= size * i)) ? ptr + size : NULL) {
|
|
||||||
if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW)/sizeof(DriverNameW[0]))
|
if(RegEnumKeyW(hkeyDrivers, i, DriverNameW, sizeof(DriverNameW)/sizeof(DriverNameW[0]))
|
||||||
!= ERROR_SUCCESS) {
|
!= ERROR_SUCCESS) {
|
||||||
ERR("Can't enum key number %d\n", i);
|
ERR("Can't enum key number %d\n", i);
|
||||||
RegCloseKey(hkeyDrivers);
|
RegCloseKey(hkeyDrivers);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pDriverInfo && ((driver_index + i + 1) * size) <= cbBuf)
|
||||||
|
table_ptr = pDriverInfo + (driver_index + i) * size;
|
||||||
|
if (pDriverInfo && *pcbNeeded <= cbBuf)
|
||||||
|
data_ptr = pDriverInfo + *pcbNeeded;
|
||||||
|
|
||||||
if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
|
if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
|
||||||
env, Level, ptr,
|
env, Level, table_ptr, data_ptr,
|
||||||
(cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
|
|
||||||
(cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
|
(cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
|
||||||
&needed, unicode)) {
|
&needed, TRUE)) {
|
||||||
RegCloseKey(hkeyDrivers);
|
RegCloseKey(hkeyDrivers);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pcbNeeded += needed;
|
*pcbNeeded += needed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4927,7 +4914,6 @@ static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPCWSTR pEnvironment,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*pcReturned = number;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4941,30 +4927,78 @@ BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
|
|||||||
LPDWORD pcbNeeded, LPDWORD pcReturned)
|
LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
static const WCHAR allW[] = {'a','l','l',0};
|
static const WCHAR allW[] = {'a','l','l',0};
|
||||||
|
BOOL ret;
|
||||||
|
DWORD found;
|
||||||
|
|
||||||
|
if ((pcbNeeded == NULL) || (pcReturned == NULL))
|
||||||
|
{
|
||||||
|
SetLastError(RPC_X_NULL_REF_POINTER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for local drivers */
|
||||||
|
if((pName) && (pName[0])) {
|
||||||
|
FIXME("remote drivers (%s) not supported!\n", debugstr_w(pName));
|
||||||
|
SetLastError(ERROR_ACCESS_DENIED);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check input parameter */
|
||||||
|
if ((Level < 1) || (Level == 7) || (Level > 8)) {
|
||||||
|
SetLastError(ERROR_INVALID_LEVEL);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pDriverInfo && cbBuf > 0)
|
||||||
|
memset( pDriverInfo, 0, cbBuf);
|
||||||
|
|
||||||
|
/* Exception: pull all printers */
|
||||||
if (pEnvironment && !strcmpW(pEnvironment, allW))
|
if (pEnvironment && !strcmpW(pEnvironment, allW))
|
||||||
{
|
{
|
||||||
BOOL ret;
|
DWORD i, needed, bufsize = cbBuf;
|
||||||
DWORD i, needed, returned, bufsize = cbBuf;
|
DWORD total_needed = 0;
|
||||||
|
DWORD total_found = 0;
|
||||||
|
DWORD data_offset;
|
||||||
|
|
||||||
|
/* Precompute the overall total; we need this to know
|
||||||
|
where pointers end and data begins (i.e. data_offset) */
|
||||||
for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
|
for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
|
||||||
{
|
{
|
||||||
needed = returned = 0;
|
needed = found = 0;
|
||||||
ret = WINSPOOL_EnumPrinterDrivers(pName, all_printenv[i]->envname, Level,
|
ret = WINSPOOL_EnumPrinterDrivers(pName, all_printenv[i]->envname, Level,
|
||||||
pDriverInfo, bufsize, &needed, &returned, TRUE);
|
NULL, 0, 0, &needed, &found, 0);
|
||||||
|
if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
|
||||||
|
total_needed += needed;
|
||||||
|
total_found += found;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_offset = di_sizeof[Level] * total_found;
|
||||||
|
|
||||||
|
*pcReturned = 0;
|
||||||
|
*pcbNeeded = 0;
|
||||||
|
total_found = 0;
|
||||||
|
for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
|
||||||
|
{
|
||||||
|
needed = found = 0;
|
||||||
|
ret = WINSPOOL_EnumPrinterDrivers(pName, all_printenv[i]->envname, Level,
|
||||||
|
pDriverInfo, total_found, bufsize, &needed, &found, data_offset);
|
||||||
if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
|
if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
|
||||||
else if (ret)
|
else if (ret)
|
||||||
{
|
*pcReturned += found;
|
||||||
bufsize -= needed;
|
*pcbNeeded = needed;
|
||||||
if (pDriverInfo) pDriverInfo += needed;
|
data_offset = needed;
|
||||||
if (pcReturned) *pcReturned += returned;
|
total_found += found;
|
||||||
}
|
|
||||||
if (pcbNeeded) *pcbNeeded += needed;
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
|
|
||||||
cbBuf, pcbNeeded, pcReturned, TRUE);
|
/* Normal behavior */
|
||||||
|
ret = WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
|
||||||
|
0, cbBuf, pcbNeeded, &found, 0);
|
||||||
|
if (ret)
|
||||||
|
*pcReturned = found;
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -4979,32 +5013,21 @@ BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
|
|||||||
BOOL ret;
|
BOOL ret;
|
||||||
UNICODE_STRING pNameW, pEnvironmentW;
|
UNICODE_STRING pNameW, pEnvironmentW;
|
||||||
PWSTR pwstrNameW, pwstrEnvironmentW;
|
PWSTR pwstrNameW, pwstrEnvironmentW;
|
||||||
|
LPBYTE buf = NULL;
|
||||||
|
|
||||||
|
if (cbBuf)
|
||||||
|
buf = HeapAlloc(GetProcessHeap(), 0, cbBuf);
|
||||||
|
|
||||||
pwstrNameW = asciitounicode(&pNameW, pName);
|
pwstrNameW = asciitounicode(&pNameW, pName);
|
||||||
pwstrEnvironmentW = asciitounicode(&pEnvironmentW, pEnvironment);
|
pwstrEnvironmentW = asciitounicode(&pEnvironmentW, pEnvironment);
|
||||||
|
|
||||||
if (pEnvironment && !strcmp(pEnvironment, "all"))
|
ret = EnumPrinterDriversW(pwstrNameW, pwstrEnvironmentW, Level,
|
||||||
{
|
buf, cbBuf, pcbNeeded, pcReturned);
|
||||||
DWORD i, needed, returned, bufsize = cbBuf;
|
if (ret)
|
||||||
|
convert_driverinfo_W_to_A(pDriverInfo, buf, Level, cbBuf, *pcReturned);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, buf);
|
||||||
|
|
||||||
for (i = 0; i < sizeof(all_printenv)/sizeof(all_printenv[0]); i++)
|
|
||||||
{
|
|
||||||
needed = returned = 0;
|
|
||||||
ret = WINSPOOL_EnumPrinterDrivers(pwstrNameW, all_printenv[i]->envname, Level,
|
|
||||||
pDriverInfo, bufsize, &needed, &returned, FALSE);
|
|
||||||
if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER) break;
|
|
||||||
else if (ret)
|
|
||||||
{
|
|
||||||
bufsize -= needed;
|
|
||||||
if (pDriverInfo) pDriverInfo += needed;
|
|
||||||
if (pcReturned) *pcReturned += returned;
|
|
||||||
}
|
|
||||||
if (pcbNeeded) *pcbNeeded += needed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else ret = WINSPOOL_EnumPrinterDrivers(pwstrNameW, pwstrEnvironmentW,
|
|
||||||
Level, pDriverInfo, cbBuf, pcbNeeded,
|
|
||||||
pcReturned, FALSE);
|
|
||||||
RtlFreeUnicodeString(&pNameW);
|
RtlFreeUnicodeString(&pNameW);
|
||||||
RtlFreeUnicodeString(&pEnvironmentW);
|
RtlFreeUnicodeString(&pEnvironmentW);
|
||||||
|
|
||||||
|
@ -1161,7 +1161,6 @@ static void test_EnumPrinterDrivers(void)
|
|||||||
DWORD double_needed;
|
DWORD double_needed;
|
||||||
DWORD double_returned;
|
DWORD double_returned;
|
||||||
pEnumPrinterDriversW(NULL, NULL, level, NULL, 0, &double_needed, &double_returned);
|
pEnumPrinterDriversW(NULL, NULL, level, NULL, 0, &double_needed, &double_returned);
|
||||||
todo_wine
|
|
||||||
ok(double_needed == cbBuf, "level %d: EnumPrinterDriversA returned different size %d than EnumPrinterDriversW (%d)\n", level, cbBuf, double_needed);
|
ok(double_needed == cbBuf, "level %d: EnumPrinterDriversA returned different size %d than EnumPrinterDriversW (%d)\n", level, cbBuf, double_needed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1248,7 +1247,6 @@ static void test_EnumPrinterDrivers(void)
|
|||||||
if (res && pcReturned > 0)
|
if (res && pcReturned > 0)
|
||||||
{
|
{
|
||||||
DRIVER_INFO_1 *di_1 = (DRIVER_INFO_1 *)buffer;
|
DRIVER_INFO_1 *di_1 = (DRIVER_INFO_1 *)buffer;
|
||||||
todo_wine
|
|
||||||
ok((LPBYTE) di_1->pName == NULL || (LPBYTE) di_1->pName < buffer ||
|
ok((LPBYTE) di_1->pName == NULL || (LPBYTE) di_1->pName < buffer ||
|
||||||
(LPBYTE) di_1->pName >= (LPBYTE)(di_1 + pcReturned),
|
(LPBYTE) di_1->pName >= (LPBYTE)(di_1 + pcReturned),
|
||||||
"Driver Information not in sequence; pName %p, top of data %p\n",
|
"Driver Information not in sequence; pName %p, top of data %p\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user