Add one more level of indirection to the printer handle array to allow

more information than just the name to be stored.
Wrap accesses to the printer handle array in a critsec.
This commit is contained in:
Huw Davies 2005-07-05 11:00:09 +00:00 committed by Alexandre Julliard
parent ea632a581a
commit df9c4341ec
1 changed files with 112 additions and 44 deletions

View File

@ -57,8 +57,21 @@
WINE_DEFAULT_DEBUG_CHANNEL(winspool); WINE_DEFAULT_DEBUG_CHANNEL(winspool);
static LPWSTR *printer_array; static CRITICAL_SECTION printer_handles_cs;
static int nb_printers; static CRITICAL_SECTION_DEBUG printer_handles_cs_debug =
{
0, 0, &printer_handles_cs,
{ &printer_handles_cs_debug.ProcessLocksList, &printer_handles_cs_debug.ProcessLocksList },
0, 0, { 0, (DWORD)(__FILE__ ": printer_handles_cs") }
};
static CRITICAL_SECTION printer_handles_cs = { &printer_handles_cs_debug, -1, 0, 0, 0, 0 };
typedef struct {
LPWSTR name;
} opened_printer_t;
static opened_printer_t **printer_handles;
static int nb_printer_handles;
static DWORD (WINAPI *GDI_CallDeviceCapabilities16)( LPCSTR lpszDevice, LPCSTR lpszPort, static DWORD (WINAPI *GDI_CallDeviceCapabilities16)( LPCSTR lpszDevice, LPCSTR lpszPort,
WORD fwCapability, LPSTR lpszOutput, WORD fwCapability, LPSTR lpszOutput,
@ -546,51 +559,83 @@ void WINSPOOL_LoadSystemPrinters(void)
/****************************************************************** /******************************************************************
* WINSPOOL_GetOpenedPrinterEntry * get_opened_printer_entry
* Get the first place empty in the opened printer table * Get the first place empty in the opened printer table
*/ */
static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name ) static HANDLE get_opened_printer_entry( LPCWSTR name )
{ {
int i; UINT handle;
for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break; EnterCriticalSection(&printer_handles_cs);
if (i >= nb_printers) for (handle = 0; handle < nb_printer_handles; handle++)
if (!printer_handles[handle])
break;
if (handle >= nb_printer_handles)
{ {
LPWSTR *new_array; opened_printer_t **new_array;
if (printer_array) if (printer_handles)
new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, printer_array, new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, printer_handles,
(nb_printers + 16) * sizeof(*new_array) ); (nb_printer_handles + 16) * sizeof(*new_array) );
else else
new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
(nb_printers + 16) * sizeof(*new_array) ); (nb_printer_handles + 16) * sizeof(*new_array) );
if (!new_array) return 0; if (!new_array)
printer_array = new_array;
nb_printers += 16;
}
if ((printer_array[i] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )))
{ {
strcpyW( printer_array[i], name ); handle = 0;
return (HANDLE)(i + 1); goto end;
} }
return 0; printer_handles = new_array;
nb_printer_handles += 16;
}
if (!(printer_handles[handle] = HeapAlloc(GetProcessHeap(), 0, sizeof(**printer_handles))))
{
handle = 0;
goto end;
}
printer_handles[handle]->name = HeapAlloc(GetProcessHeap(), 0, (strlenW(name) + 1) * sizeof(WCHAR));
strcpyW(printer_handles[handle]->name, name);
handle++;
end:
LeaveCriticalSection(&printer_handles_cs);
return (HANDLE)handle;
} }
/****************************************************************** /******************************************************************
* WINSPOOL_GetOpenedPrinter * get_opened_printer
* Get the pointer to the opened printer referred by the handle * Get the pointer to the opened printer referred by the handle
*/ */
static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle) static opened_printer_t *get_opened_printer(HANDLE hprn)
{ {
int idx = (int)printerHandle; int idx = (int)hprn;
if ((idx <= 0) || (idx > nb_printers)) opened_printer_t *ret = NULL;
{
SetLastError(ERROR_INVALID_HANDLE); EnterCriticalSection(&printer_handles_cs);
return NULL;
if ((idx <= 0) || (idx > nb_printer_handles))
goto end;
ret = printer_handles[idx - 1];
end:
LeaveCriticalSection(&printer_handles_cs);
return ret;
} }
return printer_array[idx - 1];
/******************************************************************
* get_opened_printer_name
* Get the pointer to the opened printer name referred by the handle
*/
static LPCWSTR get_opened_printer_name(HANDLE hprn)
{
opened_printer_t *printer = get_opened_printer(hprn);
if(!printer) return NULL;
return printer->name;
} }
/****************************************************************** /******************************************************************
@ -599,7 +644,7 @@ static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
*/ */
static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey) static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
{ {
LPCWSTR name = WINSPOOL_GetOpenedPrinter(hPrinter); LPCWSTR name = get_opened_printer_name(hPrinter);
DWORD ret; DWORD ret;
HKEY hkeyPrinters; HKEY hkeyPrinters;
@ -839,9 +884,10 @@ LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter,
); );
if(!pDeviceName) { if(!pDeviceName) {
LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter); LPCWSTR lpNameW = get_opened_printer_name(hPrinter);
if(!lpNameW) { if(!lpNameW) {
ERR("no name from hPrinter?\n"); ERR("no name from hPrinter?\n");
SetLastError(ERROR_INVALID_HANDLE);
return -1; return -1;
} }
lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW); lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
@ -974,7 +1020,7 @@ BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter,
return TRUE; return TRUE;
/* Get the unique handle of the printer*/ /* Get the unique handle of the printer*/
*phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName ); *phPrinter = get_opened_printer_entry( lpPrinterName );
if (pDefault != NULL) if (pDefault != NULL)
FIXME("Not handling pDefault\n"); FIXME("Not handling pDefault\n");
@ -1433,14 +1479,28 @@ HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter)
BOOL WINAPI ClosePrinter(HANDLE hPrinter) BOOL WINAPI ClosePrinter(HANDLE hPrinter)
{ {
int i = (int)hPrinter; int i = (int)hPrinter;
opened_printer_t *printer = NULL;
TRACE("Handle %p\n", hPrinter); TRACE("Handle %p\n", hPrinter);
if ((i <= 0) || (i > nb_printers)) return FALSE; EnterCriticalSection(&printer_handles_cs);
HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
printer_array[i - 1] = NULL; if ((i > 0) && (i <= nb_printer_handles))
{
printer = printer_handles[i - 1];
printer_handles[i - 1] = NULL;
}
LeaveCriticalSection(&printer_handles_cs);
if(printer)
{
HeapFree(GetProcessHeap(), 0, printer->name);
HeapFree(GetProcessHeap(), 0, printer);
return TRUE; return TRUE;
} }
return FALSE;
}
/***************************************************************************** /*****************************************************************************
* DeleteFormA [WINSPOOL.@] * DeleteFormA [WINSPOOL.@]
@ -1516,10 +1576,13 @@ static DWORD WINSPOOL_SHDeleteKeyW(HKEY hKey, LPCWSTR lpszSubKey)
*/ */
BOOL WINAPI DeletePrinter(HANDLE hPrinter) BOOL WINAPI DeletePrinter(HANDLE hPrinter)
{ {
LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter); LPCWSTR lpNameW = get_opened_printer_name(hPrinter);
HKEY hkeyPrinters, hkey; HKEY hkeyPrinters, hkey;
if(!lpNameW) return FALSE; if(!lpNameW) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) == ERROR_SUCCESS) { if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) == ERROR_SUCCESS) {
WINSPOOL_SHDeleteKeyW(hkeyPrinters, lpNameW); WINSPOOL_SHDeleteKeyW(hkeyPrinters, lpNameW);
RegCloseKey(hkeyPrinters); RegCloseKey(hkeyPrinters);
@ -2134,7 +2197,10 @@ static BOOL WINSPOOL_GetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter,
TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded); TRACE("(%p,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded);
if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE; if (!(name = get_opened_printer_name(hPrinter))) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) !=
ERROR_SUCCESS) { ERROR_SUCCESS) {
@ -2664,8 +2730,10 @@ static BOOL WINSPOOL_GetPrinterDriver(HANDLE hPrinter, LPWSTR pEnvironment,
ZeroMemory(pDriverInfo, cbBuf); ZeroMemory(pDriverInfo, cbBuf);
if (!(name = WINSPOOL_GetOpenedPrinter(hPrinter))) return FALSE; if (!(name = get_opened_printer_name(hPrinter))) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
if(Level < 1 || Level > 3) { if(Level < 1 || Level > 3) {
SetLastError(ERROR_INVALID_LEVEL); SetLastError(ERROR_INVALID_LEVEL);
return FALSE; return FALSE;