winspool: better printer handles
Huw D M Davies
h.davies1 at physics.ox.ac.uk
Mon Jul 4 07:57:23 CDT 2005
Huw Davies <huw at codeweavers.com>
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
--
Huw Davies
huw at codeweavers.com
Index: dlls/winspool/info.c
===================================================================
RCS file: /home/wine/wine/dlls/winspool/info.c,v
retrieving revision 1.109
diff -u -p -r1.109 info.c
--- dlls/winspool/info.c 30 Jun 2005 18:10:59 -0000 1.109
+++ dlls/winspool/info.c 4 Jul 2005 12:54:23 -0000
@@ -57,8 +57,21 @@
WINE_DEFAULT_DEBUG_CHANNEL(winspool);
-static LPWSTR *printer_array;
-static int nb_printers;
+static CRITICAL_SECTION printer_handles_cs;
+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,
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
*/
-static HANDLE WINSPOOL_GetOpenedPrinterEntry( LPCWSTR name )
+static HANDLE get_opened_printer_entry( LPCWSTR name )
{
- int i;
+ UINT handle;
+
+ EnterCriticalSection(&printer_handles_cs);
- for (i = 0; i < nb_printers; i++) if (!printer_array[i]) break;
+ for (handle = 0; handle < nb_printer_handles; handle++)
+ if (!printer_handles[handle])
+ break;
- if (i >= nb_printers)
+ if (handle >= nb_printer_handles)
{
- LPWSTR *new_array;
- if (printer_array)
- new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, printer_array,
- (nb_printers + 16) * sizeof(*new_array) );
- else
- new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
- (nb_printers + 16) * sizeof(*new_array) );
-
- if (!new_array) return 0;
- printer_array = new_array;
- nb_printers += 16;
+ opened_printer_t **new_array;
+ if (printer_handles)
+ new_array = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, printer_handles,
+ (nb_printer_handles + 16) * sizeof(*new_array) );
+ else
+ new_array = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
+ (nb_printer_handles + 16) * sizeof(*new_array) );
+
+ if (!new_array)
+ {
+ handle = 0;
+ goto end;
+ }
+ printer_handles = new_array;
+ nb_printer_handles += 16;
}
- if ((printer_array[i] = HeapAlloc( GetProcessHeap(), 0, (strlenW(name)+1)*sizeof(WCHAR) )))
+ if (!(printer_handles[handle] = HeapAlloc(GetProcessHeap(), 0, sizeof(**printer_handles))))
{
- strcpyW( printer_array[i], name );
- return (HANDLE)(i + 1);
+ handle = 0;
+ goto end;
}
- return 0;
+
+ 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
*/
-static LPCWSTR WINSPOOL_GetOpenedPrinter(HANDLE printerHandle)
+static opened_printer_t *get_opened_printer(HANDLE hprn)
{
- int idx = (int)printerHandle;
- if ((idx <= 0) || (idx > nb_printers))
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return NULL;
- }
- return printer_array[idx - 1];
+ int idx = (int)hprn;
+ opened_printer_t *ret = NULL;
+
+ EnterCriticalSection(&printer_handles_cs);
+
+ if ((idx <= 0) || (idx > nb_printer_handles))
+ goto end;
+
+ ret = printer_handles[idx - 1];
+end:
+ LeaveCriticalSection(&printer_handles_cs);
+ return ret;
+}
+
+/******************************************************************
+ * 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
*/
static DWORD WINSPOOL_GetOpenedPrinterRegKey(HANDLE hPrinter, HKEY *phkey)
{
- LPCWSTR name = WINSPOOL_GetOpenedPrinter(hPrinter);
+ LPCWSTR name = get_opened_printer_name(hPrinter);
DWORD ret;
HKEY hkeyPrinters;
@@ -612,8 +657,8 @@ static DWORD WINSPOOL_GetOpenedPrinterRe
if(RegOpenKeyW(hkeyPrinters, name, phkey) != ERROR_SUCCESS)
{
ERR("Can't find opened printer %s in registry\n",
- debugstr_w(name));
- RegCloseKey(hkeyPrinters);
+ debugstr_w(name));
+ RegCloseKey(hkeyPrinters);
return ERROR_INVALID_PRINTER_NAME; /* ? */
}
RegCloseKey(hkeyPrinters);
@@ -839,9 +884,10 @@ LONG WINAPI DocumentPropertiesA(HWND hWn
);
if(!pDeviceName) {
- LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
+ LPCWSTR lpNameW = get_opened_printer_name(hPrinter);
if(!lpNameW) {
ERR("no name from hPrinter?\n");
+ SetLastError(ERROR_INVALID_HANDLE);
return -1;
}
lpName = HEAP_strdupWtoA(GetProcessHeap(),0,lpNameW);
@@ -974,7 +1020,7 @@ BOOL WINAPI OpenPrinterW(LPWSTR lpPrinte
return TRUE;
/* Get the unique handle of the printer*/
- *phPrinter = WINSPOOL_GetOpenedPrinterEntry( lpPrinterName );
+ *phPrinter = get_opened_printer_entry( lpPrinterName );
if (pDefault != NULL)
FIXME("Not handling pDefault\n");
@@ -1433,13 +1479,27 @@ HANDLE WINAPI AddPrinterA(LPSTR pName, D
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
{
int i = (int)hPrinter;
+ opened_printer_t *printer = NULL;
TRACE("Handle %p\n", hPrinter);
- if ((i <= 0) || (i > nb_printers)) return FALSE;
- HeapFree( GetProcessHeap(), 0, printer_array[i - 1] );
- printer_array[i - 1] = NULL;
- return TRUE;
+ EnterCriticalSection(&printer_handles_cs);
+
+ 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 FALSE;
}
/*****************************************************************************
@@ -1516,10 +1576,13 @@ static DWORD WINSPOOL_SHDeleteKeyW(HKEY
*/
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
{
- LPCWSTR lpNameW = WINSPOOL_GetOpenedPrinter(hPrinter);
+ LPCWSTR lpNameW = get_opened_printer_name(hPrinter);
HKEY hkeyPrinters, hkey;
- if(!lpNameW) return FALSE;
+ if(!lpNameW) {
+ SetLastError(ERROR_INVALID_HANDLE);
+ return FALSE;
+ }
if(RegOpenKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) == ERROR_SUCCESS) {
WINSPOOL_SHDeleteKeyW(hkeyPrinters, lpNameW);
RegCloseKey(hkeyPrinters);
@@ -2134,7 +2197,10 @@ static BOOL WINSPOOL_GetPrinter(HANDLE h
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) !=
ERROR_SUCCESS) {
@@ -2664,8 +2730,10 @@ static BOOL WINSPOOL_GetPrinterDriver(HA
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) {
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
More information about the wine-patches
mailing list