Commit 5cfe1770 authored by Stefan Leichter's avatar Stefan Leichter Committed by Alexandre Julliard

- moved some code from WINSPOOL_GetPrinterDriver into new function

WINSPOOL_GetDriverInfoFromReg - bug fix in function GetPrinterDirectoryW: free local variable not the one from function interface - implemented EnumPrinterDriversA|W
parent 3ac104fa
......@@ -1637,6 +1637,171 @@ BOOL WINAPI EnumPrintersA(DWORD dwType, LPSTR lpszName,
return ret;
}
/*****************************************************************************
* WINSPOOL_GetDriverInfoFromReg [internal]
*
* Enters the information from the registry into the DRIVER_INFO struct
*
* RETURNS
* zero if the printer driver does not exist in the registry
* (only if Level > 1) otherwise nonzero
*/
static BOOL WINSPOOL_GetDriverInfoFromReg(
HKEY hkeyDrivers,
LPWSTR DriverName,
LPWSTR pEnvironment,
DWORD Level,
LPBYTE ptr, /* DRIVER_INFO */
LPBYTE pDriverStrings, /* strings buffer */
DWORD cbBuf, /* size of string buffer */
LPDWORD pcbNeeded, /* space needed for str. */
BOOL unicode) /* type of strings */
{ DWORD dw, size, type;
HKEY hkeyDriver;
LPBYTE strPtr = pDriverStrings;
TRACE("%s,%s,%ld,%p,%p,%ld,%d\n",
debugstr_w(DriverName), debugstr_w(pEnvironment),
Level, ptr, pDriverStrings, cbBuf, unicode);
if(unicode) {
*pcbNeeded = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
if (*pcbNeeded <= cbBuf)
strcpyW((LPWSTR)strPtr, DriverName);
} else {
*pcbNeeded = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0,
NULL, NULL);
if(*pcbNeeded <= cbBuf)
WideCharToMultiByte(CP_ACP, 0, DriverName, -1, strPtr, *pcbNeeded,
NULL, NULL);
}
if(Level == 1) {
if(ptr)
((PDRIVER_INFO_1W) ptr)->pName = (LPWSTR) strPtr;
return TRUE;
} else {
if(ptr)
((PDRIVER_INFO_3W) ptr)->pName = (LPWSTR) strPtr;
strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
}
if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver) != ERROR_SUCCESS) {
ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
return FALSE;
}
size = sizeof(dw);
if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw, &size) !=
ERROR_SUCCESS)
WARN("Can't get Version\n");
else if(ptr)
((PDRIVER_INFO_3A) ptr)->cVersion = dw;
if(!pEnvironment)
pEnvironment = DefaultEnvironmentW;
if(unicode)
size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
else
size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
NULL, NULL);
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf) {
if(unicode)
strcpyW((LPWSTR)strPtr, pEnvironment);
else
WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, strPtr, size,
NULL, NULL);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pEnvironment = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, 0, &size,
unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, strPtr, cbBuf, &size,
unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pDriverPath = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? (pDriverStrings + (*pcbNeeded)) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, 0, &size,
unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, strPtr, cbBuf,
&size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pDataFile = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
cbBuf, &size, unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, strPtr,
cbBuf, &size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pConfigFile = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
if(Level == 2 ) {
RegCloseKey(hkeyDriver);
return TRUE;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr, 0, &size,
unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, strPtr,
cbBuf, &size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pHelpFile = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr, 0,
&size, unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, strPtr,
cbBuf, &size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pDependentFiles = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr, 0, &size,
unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
cbBuf, &size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pMonitorName = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, strPtr, 0, &size,
unicode)) {
*pcbNeeded += size;
if(*pcbNeeded <= cbBuf)
WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, strPtr,
cbBuf, &size, unicode);
if(ptr)
((PDRIVER_INFO_3W) ptr)->pDefaultDataType = (LPWSTR)strPtr;
strPtr = (pDriverStrings) ? pDriverStrings + (*pcbNeeded) : NULL;
}
RegCloseKey(hkeyDriver);
return TRUE;
}
/*****************************************************************************
* WINSPOOL_GetPrinterDriver
......@@ -1648,9 +1813,9 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
{
OPENEDPRINTER *lpOpenedPrinter;
WCHAR DriverName[100];
DWORD ret, type, size, dw, needed = 0;
DWORD ret, type, size, needed = 0;
LPBYTE ptr = NULL;
HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers;
HKEY hkeyPrinter, hkeyPrinters, hkeyDrivers;
TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,debugstr_w(pEnvironment),
Level,pDriverInfo,cbBuf, pcbNeeded);
......@@ -1699,13 +1864,6 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
ERR("Can't create Drivers key\n");
return FALSE;
}
if(RegOpenKeyW(hkeyDrivers, DriverName, &hkeyDriver)
!= ERROR_SUCCESS) {
ERR("Can't find driver %s in registry\n", debugstr_w(DriverName));
RegCloseKey(hkeyDrivers);
SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */
return FALSE;
}
switch(Level) {
case 1:
......@@ -1722,138 +1880,22 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
return FALSE;
}
if(size <= cbBuf) {
if(size <= cbBuf)
ptr = pDriverInfo + size;
cbBuf -= size;
} else
cbBuf = 0;
needed = size;
if(unicode)
size = (lstrlenW(DriverName) + 1) * sizeof(WCHAR);
else
size = WideCharToMultiByte(CP_ACP, 0, DriverName, -1, NULL, 0, NULL,
NULL);
if(size <= cbBuf) {
cbBuf -= size;
if(unicode)
strcpyW((LPWSTR)ptr, DriverName);
else
WideCharToMultiByte(CP_ACP, 0, DriverName, -1, ptr, size, NULL,
NULL);
if(Level == 1)
((DRIVER_INFO_1W *)pDriverInfo)->pName = (LPWSTR)ptr;
else
((DRIVER_INFO_2W *)pDriverInfo)->pName = (LPWSTR)ptr;
ptr += size;
}
needed += size;
if(Level > 1) {
DRIVER_INFO_2W *di2 = (DRIVER_INFO_2W *)pDriverInfo;
size = sizeof(dw);
if(RegQueryValueExA(hkeyDriver, "Version", 0, &type, (PBYTE)&dw,
&size) !=
ERROR_SUCCESS)
WARN("Can't get Version\n");
else if(cbBuf)
di2->cVersion = dw;
if(!pEnvironment)
pEnvironment = DefaultEnvironmentW;
if(unicode)
size = (lstrlenW(pEnvironment) + 1) * sizeof(WCHAR);
else
size = WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, NULL, 0,
NULL, NULL);
if(size <= cbBuf) {
cbBuf -= size;
if(unicode)
strcpyW((LPWSTR)ptr, pEnvironment);
else
WideCharToMultiByte(CP_ACP, 0, pEnvironment, -1, ptr, size,
NULL, NULL);
di2->pEnvironment = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
if(WINSPOOL_GetStringFromReg(hkeyDriver, DriverW, ptr, cbBuf, &size,
unicode)) {
if(cbBuf && size <= cbBuf) {
di2->pDriverPath = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Data_FileW, ptr, cbBuf, &size,
unicode)) {
if(cbBuf && size <= cbBuf) {
di2->pDataFile = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Configuration_FileW, ptr,
cbBuf, &size, unicode)) {
if(cbBuf && size <= cbBuf) {
di2->pConfigFile = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverName,
pEnvironment, Level, pDriverInfo,
(cbBuf < size) ? NULL : ptr,
(cbBuf < size) ? 0 : cbBuf - size,
&needed, unicode)) {
RegCloseKey(hkeyDrivers);
return FALSE;
}
if(Level > 2) {
DRIVER_INFO_3W *di3 = (DRIVER_INFO_3W *)pDriverInfo;
if(WINSPOOL_GetStringFromReg(hkeyDriver, Help_FileW, ptr, cbBuf, &size,
unicode)) {
if(cbBuf && size <= cbBuf) {
di3->pHelpFile = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, Dependent_FilesW, ptr, cbBuf,
&size, unicode)) {
if(cbBuf && size <= cbBuf) {
di3->pDependentFiles = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, MonitorW, ptr, cbBuf, &size,
unicode)) {
if(cbBuf && size <= cbBuf) {
di3->pMonitorName = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
if(WINSPOOL_GetStringFromReg(hkeyDriver, DatatypeW, ptr, cbBuf, &size,
unicode)) {
if(cbBuf && size <= cbBuf) {
di3->pDefaultDataType = (LPWSTR)ptr;
ptr += size;
} else
cbBuf = 0;
needed += size;
}
}
RegCloseKey(hkeyDriver);
RegCloseKey(hkeyDrivers);
if(pcbNeeded) *pcbNeeded = needed;
if(cbBuf) return TRUE;
if(cbBuf >= needed) return TRUE;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
......@@ -1939,7 +1981,7 @@ BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment,
if(pNameA)
HeapFree( GetProcessHeap(), 0, pNameA );
if(pEnvironmentA)
HeapFree( GetProcessHeap(), 0, pEnvironment );
HeapFree( GetProcessHeap(), 0, pEnvironmentA );
return ret;
}
......@@ -2086,3 +2128,151 @@ BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs,
if(pcReturned) *pcReturned = 0;
return TRUE;
}
/*****************************************************************************
* WINSPOOL_EnumPrinterDrivers [internal]
*
* Delivers information about all installed printer drivers installed on
* localhost or a given server
*
* RETURNS
* nonzero on succes or zero on failure, if the buffer for the returned
* information is too small the function will return an error
*
* BUGS
* - only implemented for localhost, foreign hosts will return an error
* - the parameter pEnvironment is ignored
*/
static BOOL WINSPOOL_EnumPrinterDrivers(LPWSTR pName, LPWSTR pEnvironment,
DWORD Level, LPBYTE pDriverInfo,
DWORD cbBuf, LPDWORD pcbNeeded,
LPDWORD pcReturned, BOOL unicode)
{ HKEY hkeyDrivers;
DWORD i, needed, number = 0, size = 0;
WCHAR DriverNameW[255];
PBYTE ptr;
TRACE("%s,%s,%ld,%p,%ld,%d\n",
debugstr_w(pName), debugstr_w(pEnvironment),
Level, pDriverInfo, cbBuf, unicode);
/* check for local drivers */
if(pName) {
ERR("remote drivers unsupported! Current remote host is %s\n",
debugstr_w(pName));
return FALSE;
}
/* check input parameter */
if((Level < 1) || (Level > 3)) {
ERR("unsupported level %ld \n", Level);
return FALSE;
}
/* initialize return values */
if(pDriverInfo)
memset( pDriverInfo, 0, cbBuf);
*pcbNeeded = 0;
*pcReturned = 0;
if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) !=
ERROR_SUCCESS) {
ERR("Can't open Drivers key\n");
return FALSE;
}
if(RegQueryInfoKeyA(hkeyDrivers, NULL, NULL, NULL, &number, NULL, NULL,
NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) {
RegCloseKey(hkeyDrivers);
ERR("Can't query Drivers key\n");
return FALSE;
}
TRACE("Found %ld Drivers\n", number);
/* get size of single struct
* unicode and ascii structure have the same size
*/
switch (Level) {
case 1:
size = sizeof(DRIVER_INFO_1A);
break;
case 2:
size = sizeof(DRIVER_INFO_2A);
break;
case 3:
size = sizeof(DRIVER_INFO_3A);
break;
}
/* calculate required buffer size */
*pcbNeeded = size * number;
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))
!= ERROR_SUCCESS) {
ERR("Can't enum key number %ld\n", i);
RegCloseKey(hkeyDrivers);
return FALSE;
}
if(!WINSPOOL_GetDriverInfoFromReg(hkeyDrivers, DriverNameW,
pEnvironment, Level, ptr,
(cbBuf < *pcbNeeded) ? NULL : pDriverInfo + *pcbNeeded,
(cbBuf < *pcbNeeded) ? 0 : cbBuf - *pcbNeeded,
&needed, unicode)) {
RegCloseKey(hkeyDrivers);
return FALSE;
}
(*pcbNeeded) += needed;
}
RegCloseKey(hkeyDrivers);
if(cbBuf < *pcbNeeded){
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
/*****************************************************************************
* EnumPrinterDriversW [WINSPOOL.173]
*
* see function EnumPrinterDrivers for RETURNS, BUGS
*/
BOOL WINAPI EnumPrinterDriversW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
LPBYTE pDriverInfo, DWORD cbBuf,
LPDWORD pcbNeeded, LPDWORD pcReturned)
{
return WINSPOOL_EnumPrinterDrivers(pName, pEnvironment, Level, pDriverInfo,
cbBuf, pcbNeeded, pcReturned, TRUE);
}
/*****************************************************************************
* EnumPrinterDriversA [WINSPOOL.172]
*
* see function EnumPrinterDrivers for RETURNS, BUGS
*/
BOOL WINAPI EnumPrinterDriversA(LPSTR pName, LPSTR pEnvironment, DWORD Level,
LPBYTE pDriverInfo, DWORD cbBuf,
LPDWORD pcbNeeded, LPDWORD pcReturned)
{ BOOL ret;
WCHAR *pNameW = NULL, *pEnvironmentW = NULL;
if(pName)
pNameW = HEAP_strdupAtoW(GetProcessHeap(), 0, pName);
if(pEnvironment)
pEnvironmentW = HEAP_strdupAtoW(GetProcessHeap(), 0, pEnvironment);
ret = WINSPOOL_EnumPrinterDrivers(pNameW, pEnvironmentW, Level, pDriverInfo,
cbBuf, pcbNeeded, pcReturned, FALSE);
if(pNameW)
HeapFree(GetProcessHeap(), 0, pNameW);
if(pEnvironmentW)
HeapFree(GetProcessHeap(), 0, pEnvironmentW);
return ret;
}
......@@ -78,8 +78,8 @@ import kernel32.dll
169 stub EnumPrintProcessorDatatypesW
170 stub EnumPrintProcessorsA
171 stub EnumPrintProcessorsW
172 stub EnumPrinterDriversA
173 stub EnumPrinterDriversW
172 stdcall EnumPrinterDriversA(str str long ptr long ptr ptr) EnumPrinterDriversA
173 stdcall EnumPrinterDriversW(wstr wstr long ptr long ptr ptr) EnumPrinterDriversW
174 stdcall EnumPrintersA(long ptr long ptr long ptr ptr) EnumPrintersA
175 stdcall EnumPrintersW(long ptr long ptr long ptr ptr) EnumPrintersW
176 stub ExtDeviceMode
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment