| /* |
| * WINSPOOL functions |
| * |
| * Copyright 1996 John Harvey |
| * Copyright 1998 Andreas Mohr |
| * Copyright 1999 Klaas van Gend |
| */ |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include <ctype.h> |
| #include "winspool.h" |
| #include "winbase.h" |
| #include "winerror.h" |
| #include "winreg.h" |
| #include "debugtools.h" |
| #include "heap.h" |
| #include "commctrl.h" |
| |
| DEFAULT_DEBUG_CHANNEL(winspool) |
| |
| CRITICAL_SECTION PRINT32_RegistryBlocker; |
| |
| typedef struct _OPENEDPRINTERA |
| { |
| LPSTR lpsPrinterName; |
| HANDLE hPrinter; |
| LPPRINTER_DEFAULTSA lpDefault; |
| } OPENEDPRINTERA, *LPOPENEDPRINTERA; |
| |
| /* The OpenedPrinter Table dynamic array */ |
| static HDPA pOpenedPrinterDPA = NULL; |
| |
| extern HDPA (WINAPI* WINSPOOL_DPA_CreateEx) (INT, HANDLE); |
| extern LPVOID (WINAPI* WINSPOOL_DPA_GetPtr) (const HDPA, INT); |
| extern INT (WINAPI* WINSPOOL_DPA_InsertPtr) (const HDPA, INT, LPVOID); |
| |
| static char Printers[] = |
| "System\\CurrentControlSet\\control\\Print\\Printers\\"; |
| static char Drivers[] = |
| "System\\CurrentControlSet\\control\\Print\\Environments\\Wine\\Drivers\\"; |
| |
| /****************************************************************** |
| * WINSPOOL_GetOpenedPrinterEntryA |
| * Get the first place empty in the opened printer table |
| */ |
| static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterEntryA() |
| { |
| int i; |
| LPOPENEDPRINTERA pOpenedPrinter; |
| |
| /* |
| * Create the opened printers' handle dynamic array. |
| */ |
| if (!pOpenedPrinterDPA) |
| { |
| pOpenedPrinterDPA = WINSPOOL_DPA_CreateEx(10, GetProcessHeap()); |
| for (i = 0; i < 10; i++) |
| { |
| pOpenedPrinter = HeapAlloc(GetProcessHeap(), |
| HEAP_ZERO_MEMORY, |
| sizeof(OPENEDPRINTERA)); |
| pOpenedPrinter->hPrinter = -1; |
| WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter); |
| } |
| } |
| |
| /* |
| * Search for a handle not yet allocated. |
| */ |
| for (i = 0; i < pOpenedPrinterDPA->nItemCount; i++) |
| { |
| pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, i); |
| |
| if (pOpenedPrinter->hPrinter == -1) |
| { |
| pOpenedPrinter->hPrinter = i + 1; |
| return pOpenedPrinter; |
| } |
| } |
| |
| /* |
| * Didn't find one, insert new element in the array. |
| */ |
| if (i == pOpenedPrinterDPA->nItemCount) |
| { |
| pOpenedPrinter = HeapAlloc(GetProcessHeap(), |
| HEAP_ZERO_MEMORY, |
| sizeof(OPENEDPRINTERA)); |
| pOpenedPrinter->hPrinter = i + 1; |
| WINSPOOL_DPA_InsertPtr(pOpenedPrinterDPA, i, pOpenedPrinter); |
| return pOpenedPrinter; |
| } |
| |
| return NULL; |
| } |
| |
| /****************************************************************** |
| * WINSPOOL_GetOpenedPrinterA |
| * Get the pointer to the opened printer referred by the handle |
| */ |
| static LPOPENEDPRINTERA WINSPOOL_GetOpenedPrinterA(int printerHandle) |
| { |
| LPOPENEDPRINTERA pOpenedPrinter; |
| |
| if(!pOpenedPrinterDPA) return NULL; |
| if((printerHandle <=0) || |
| (printerHandle > (pOpenedPrinterDPA->nItemCount - 1))) |
| return NULL; |
| |
| pOpenedPrinter = WINSPOOL_DPA_GetPtr(pOpenedPrinterDPA, printerHandle-1); |
| |
| return pOpenedPrinter; |
| } |
| |
| /****************************************************************** |
| * DeviceCapabilities32A [WINSPOOL.151] |
| * |
| */ |
| INT WINAPI DeviceCapabilitiesA(LPCSTR pDeivce,LPCSTR pPort, WORD cap, |
| LPSTR pOutput, LPDEVMODEA lpdm) |
| { |
| INT ret; |
| ret = GDI_CallDeviceCapabilities16(pDeivce, pPort, cap, pOutput, lpdm); |
| |
| /* If DC_PAPERSIZE map POINT16s to POINTs */ |
| if(ret != -1 && cap == DC_PAPERSIZE && pOutput) { |
| POINT16 *tmp = HeapAlloc( GetProcessHeap(), 0, ret * sizeof(POINT16) ); |
| INT i; |
| memcpy(tmp, pOutput, ret * sizeof(POINT16)); |
| for(i = 0; i < ret; i++) |
| CONV_POINT16TO32(tmp + i, (POINT*)pOutput + i); |
| HeapFree( GetProcessHeap(), 0, tmp ); |
| } |
| return ret; |
| } |
| |
| |
| /***************************************************************************** |
| * DeviceCapabilities32W |
| */ |
| INT WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, |
| WORD fwCapability, LPWSTR pOutput, |
| const DEVMODEW *pDevMode) |
| { |
| FIXME("(%p,%p,%d,%p,%p): stub\n", |
| pDevice, pPort, fwCapability, pOutput, pDevMode); |
| return -1; |
| } |
| |
| /****************************************************************** |
| * DocumentProperties32A [WINSPOOL.155] |
| * |
| */ |
| LONG WINAPI DocumentPropertiesA(HWND hWnd,HANDLE hPrinter, |
| LPSTR pDeviceName, LPDEVMODEA pDevModeOutput, |
| LPDEVMODEA pDevModeInput,DWORD fMode ) |
| { |
| LPOPENEDPRINTERA lpOpenedPrinter; |
| LPSTR lpName = pDeviceName; |
| |
| TRACE("(%d,%d,%s,%p,%p,%ld)\n", |
| hWnd,hPrinter,pDeviceName,pDevModeOutput,pDevModeInput,fMode |
| ); |
| |
| if(!pDeviceName) { |
| lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter); |
| if(!lpOpenedPrinter) { |
| SetLastError(ERROR_INVALID_HANDLE); |
| return -1; |
| } |
| lpName = lpOpenedPrinter->lpsPrinterName; |
| } |
| |
| return GDI_CallExtDeviceMode16(hWnd, pDevModeOutput, lpName, NULL, |
| pDevModeInput, NULL, fMode); |
| |
| } |
| |
| |
| /***************************************************************************** |
| * DocumentProperties32W |
| */ |
| LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, |
| LPWSTR pDeviceName, |
| LPDEVMODEW pDevModeOutput, |
| LPDEVMODEW pDevModeInput, DWORD fMode) |
| { |
| FIXME("(%d,%d,%s,%p,%p,%ld): stub\n", |
| hWnd,hPrinter,debugstr_w(pDeviceName),pDevModeOutput,pDevModeInput, |
| fMode); |
| return -1; |
| } |
| |
| |
| /****************************************************************** |
| * OpenPrinter32A [WINSPOOL.196] |
| * |
| */ |
| BOOL WINAPI OpenPrinterA(LPSTR lpPrinterName,HANDLE *phPrinter, |
| LPPRINTER_DEFAULTSA pDefault) |
| { |
| /* Not implemented: use the DesiredAccess of pDefault to set |
| the access rights to the printer */ |
| |
| LPOPENEDPRINTERA lpOpenedPrinter; |
| HKEY hkeyPrinters, hkeyPrinter; |
| |
| TRACE("(printerName: %s, pDefault %p\n", lpPrinterName, pDefault); |
| |
| /* Check Printer exists */ |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Printers key\n"); |
| SetLastError(ERROR_FILE_NOT_FOUND); /* ?? */ |
| return FALSE; |
| } |
| |
| if(RegOpenKeyA(hkeyPrinters, lpPrinterName, &hkeyPrinter) |
| != ERROR_SUCCESS) { |
| WARN("Can't find printer `%s' in registry\n", lpPrinterName); |
| RegCloseKey(hkeyPrinters); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return FALSE; |
| } |
| RegCloseKey(hkeyPrinter); |
| RegCloseKey(hkeyPrinters); |
| |
| if(!phPrinter) /* This seems to be what win95 does anyway */ |
| return TRUE; |
| |
| /* Get a place in the opened printer buffer*/ |
| lpOpenedPrinter = WINSPOOL_GetOpenedPrinterEntryA(); |
| if(!lpOpenedPrinter) { |
| ERR("Can't allocate printer slot\n"); |
| SetLastError(ERROR_OUTOFMEMORY); |
| return FALSE; |
| } |
| |
| /* Get the name of the printer */ |
| lpOpenedPrinter->lpsPrinterName = |
| HEAP_strdupA( GetProcessHeap(), 0, lpPrinterName ); |
| |
| /* Get the unique handle of the printer*/ |
| *phPrinter = lpOpenedPrinter->hPrinter; |
| |
| if (pDefault != NULL) { |
| lpOpenedPrinter->lpDefault = |
| HeapAlloc(GetProcessHeap(), 0, sizeof(PRINTER_DEFAULTSA)); |
| lpOpenedPrinter->lpDefault->pDevMode = |
| HeapAlloc(GetProcessHeap(), 0, sizeof(DEVMODEA)); |
| memcpy(lpOpenedPrinter->lpDefault->pDevMode, pDefault->pDevMode, |
| sizeof(DEVMODEA)); |
| lpOpenedPrinter->lpDefault->pDatatype = |
| HEAP_strdupA( GetProcessHeap(), 0, pDefault->pDatatype ); |
| lpOpenedPrinter->lpDefault->DesiredAccess = |
| pDefault->DesiredAccess; |
| } |
| |
| return TRUE; |
| |
| } |
| |
| /****************************************************************** |
| * OpenPrinter32W [WINSPOOL.197] |
| * |
| */ |
| BOOL WINAPI OpenPrinterW(LPWSTR lpPrinterName,HANDLE *phPrinter, |
| LPPRINTER_DEFAULTSW pDefault) |
| { |
| FIXME("(%s,%p,%p):stub\n",debugstr_w(lpPrinterName), phPrinter, |
| pDefault); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| |
| |
| |
| /****************************************************************** |
| * ENUMPRINTERS_GetDWORDFromRegistryA internal |
| * |
| * Reads a DWORD from registry KeyName |
| * |
| * RETURNS |
| * value on OK or NULL on error |
| */ |
| DWORD ENUMPRINTERS_GetDWORDFromRegistryA( |
| HKEY hPrinterSettings, /* handle to registry key */ |
| LPSTR KeyName /* name key to retrieve string from*/ |
| ){ |
| DWORD DataSize=8; |
| DWORD DataType; |
| BYTE Data[8]; |
| DWORD Result=684; |
| |
| if (RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType, |
| Data, &DataSize)!=ERROR_SUCCESS) |
| FIXME("Query of register '%s' didn't succeed?\n", KeyName); |
| if (DataType == REG_DWORD_LITTLE_ENDIAN) |
| Result = Data[0] + (Data[1]<<8) + (Data[2]<<16) + (Data[3]<<24); |
| if (DataType == REG_DWORD_BIG_ENDIAN) |
| Result = Data[3] + (Data[2]<<8) + (Data[1]<<16) + (Data[0]<<24); |
| return(Result); |
| } |
| |
| |
| /****************************************************************** |
| * ENUMPRINTERS_AddStringFromRegistryA internal |
| * |
| * Reads a string from registry KeyName and writes it at |
| * lpbPrinters[dwNextStringPos]. Store reference to string in Dest. |
| * |
| * RETURNS |
| * FALSE if there is still space left in the buffer. |
| */ |
| BOOL ENUMPRINTERS_AddStringFromRegistryA( |
| HKEY hPrinterSettings, /* handle to registry key */ |
| LPSTR KeyName, /* name key to retrieve string from*/ |
| LPSTR* Dest, /* pointer to write string addres to */ |
| LPBYTE lpbPrinters, /* buffer which receives info*/ |
| LPDWORD dwNextStringPos,/* pos in buffer for next string */ |
| DWORD dwBufSize, /* max size of buffer in bytes */ |
| BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ |
| ){ |
| DWORD DataSize=34; |
| DWORD DataType, ret; |
| LPSTR Data = (LPSTR) malloc(DataSize*sizeof(char)); |
| |
| TRACE("Reading '%s'\n", KeyName); |
| while((ret = RegQueryValueExA(hPrinterSettings, KeyName, NULL, &DataType, |
| Data, &DataSize))==ERROR_MORE_DATA) |
| { |
| Data = (LPSTR) realloc(Data, DataSize+2); |
| } |
| if (ret != ERROR_SUCCESS) { |
| if(!bCalcSpaceOnly) |
| *Dest = NULL; |
| } |
| else if (DataType == REG_SZ) |
| { |
| if (bCalcSpaceOnly==FALSE) |
| *Dest = &lpbPrinters[*dwNextStringPos]; |
| *dwNextStringPos += DataSize+1; |
| if (*dwNextStringPos > dwBufSize) |
| bCalcSpaceOnly=TRUE; |
| if (bCalcSpaceOnly==FALSE) |
| { |
| if (DataSize==0) /* DataSize = 0 means empty string, even though*/ |
| *Dest[0]=0; /* the data itself needs not to be empty */ |
| else |
| strcpy(*Dest, Data); |
| } |
| } |
| else |
| WARN("Expected string setting, got %lx\n", DataType); |
| |
| if (Data) |
| free(Data); |
| return(bCalcSpaceOnly); |
| } |
| |
| |
| |
| /****************************************************************** |
| * ENUMPRINTERS_AddInfo2A internal |
| * |
| * Creates a PRINTER_INFO_2A structure at: lpbPrinters[dwNextStructPos] |
| * for printer PrinterNameKey. |
| * Note that there is no check whether the information really fits! |
| * |
| * RETURNS |
| * FALSE if there is still space left in the buffer. |
| * |
| * BUGS: |
| * This function should not only read the registry but also ask the driver |
| * for information. |
| */ |
| BOOL ENUMPRINTERS_AddInfo2A( |
| LPSTR lpszPrinterName,/* name of printer to fill struct for*/ |
| LPBYTE lpbPrinters, /* buffer which receives info*/ |
| DWORD dwNextStructPos, /* pos in buffer for struct */ |
| LPDWORD dwNextStringPos, /* pos in buffer for next string */ |
| DWORD dwBufSize, /* max size of buffer in bytes */ |
| BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ |
| ){ |
| HKEY hPrinterSettings; |
| DWORD DevSize=0; |
| DWORD DataType; |
| LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+ |
| strlen(lpszPrinterName)+2); |
| LPPRINTER_INFO_2A lpPInfo2 = (LPPRINTER_INFO_2A) &lpbPrinters[dwNextStructPos]; |
| |
| /* open the registry to find the attributes, etc of the printer */ |
| if (lpszPrinterSettings!=NULL) |
| { |
| strcpy(lpszPrinterSettings,Printers); |
| strcat(lpszPrinterSettings,lpszPrinterName); |
| } |
| if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, |
| KEY_READ, &hPrinterSettings) != ERROR_SUCCESS) |
| { |
| WARN("The registry did not contain my printer anymore?\n"); |
| } |
| else |
| { |
| if (bCalcSpaceOnly==FALSE) |
| lpPInfo2->pServerName = NULL; |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Name", &(lpPInfo2->pPrinterName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Share Name", &(lpPInfo2->pShareName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Port", &(lpPInfo2->pPortName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Printer Driver", &(lpPInfo2->pDriverName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Description", &(lpPInfo2->pComment), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Location", &(lpPInfo2->pLocation), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Separator File", &(lpPInfo2->pSepFile), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Print Processor", &(lpPInfo2->pPrintProcessor), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Datatype", &(lpPInfo2->pDatatype), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Parameters", &(lpPInfo2->pParameters), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| if (bCalcSpaceOnly == FALSE) |
| { |
| lpPInfo2->pSecurityDescriptor = NULL; /* EnumPrinters doesn't return this*/ |
| |
| /* FIXME: Attributes gets LOCAL as no REMOTE exists*/ |
| lpPInfo2->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "Attributes") +PRINTER_ATTRIBUTE_LOCAL; |
| lpPInfo2->Priority = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "Priority"); |
| lpPInfo2->DefaultPriority = ENUMPRINTERS_GetDWORDFromRegistryA( |
| hPrinterSettings, "Default Priority"); |
| lpPInfo2->StartTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "StartTime"); |
| lpPInfo2->UntilTime = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "UntilTime"); |
| lpPInfo2->Status = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "Status"); |
| lpPInfo2->cJobs = 0; /* FIXME: according to MSDN, this does not |
| * reflect the TotalJobs Key ??? */ |
| lpPInfo2->AveragePPM = 0; /* FIXME: according to MSDN, this does not |
| * reflect the TotalPages Key ??? */ |
| |
| /* and read the devModes structure... */ |
| RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType, |
| NULL, &DevSize); /* should return ERROR_MORE_DATA */ |
| lpPInfo2->pDevMode = (LPDEVMODEA) &lpbPrinters[*dwNextStringPos]; |
| *dwNextStringPos += DevSize + 1; |
| } |
| if (*dwNextStringPos > dwBufSize) |
| bCalcSpaceOnly=TRUE; |
| if (bCalcSpaceOnly==FALSE) |
| RegQueryValueExA(hPrinterSettings, "pDevMode", NULL, &DataType, |
| (LPBYTE)lpPInfo2->pDevMode, &DevSize); |
| } |
| |
| if (lpszPrinterSettings) |
| free(lpszPrinterSettings); |
| |
| return(bCalcSpaceOnly); |
| } |
| |
| /****************************************************************** |
| * ENUMPRINTERS_AddInfo4A internal |
| * |
| * Creates a PRINTER_INFO_4A structure at: lpbPrinters[dwNextStructPos] |
| * for printer PrinterNameKey. |
| * Note that there is no check whether the information really fits! |
| * |
| * RETURNS |
| * FALSE if there is still space left in the buffer. |
| * |
| * BUGS: |
| * This function should not exist in Win95 mode, but does anyway. |
| */ |
| BOOL ENUMPRINTERS_AddInfo4A( |
| LPSTR lpszPrinterName,/* name of printer to fill struct for*/ |
| LPBYTE lpbPrinters, /* buffer which receives info*/ |
| DWORD dwNextStructPos, /* pos in buffer for struct */ |
| LPDWORD dwNextStringPos, /* pos in buffer for next string */ |
| DWORD dwBufSize, /* max size of buffer in bytes */ |
| BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ |
| ){ |
| HKEY hPrinterSettings; |
| LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+ |
| strlen(lpszPrinterName)+2); |
| LPPRINTER_INFO_4A lpPInfo4 = (LPPRINTER_INFO_4A) &lpbPrinters[dwNextStructPos]; |
| |
| /* open the registry to find the attributes of the printer */ |
| if (lpszPrinterSettings!=NULL) |
| { |
| strcpy(lpszPrinterSettings,Printers); |
| strcat(lpszPrinterSettings,lpszPrinterName); |
| } |
| if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, |
| KEY_READ, &hPrinterSettings) != ERROR_SUCCESS) |
| { |
| WARN("The registry did not contain my printer anymore?\n"); |
| } |
| else |
| { |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Name", &(lpPInfo4->pPrinterName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| /* FIXME: Attributes gets LOCAL as no REMOTE exists*/ |
| if (bCalcSpaceOnly==FALSE) |
| lpPInfo4->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "Attributes") +PRINTER_ATTRIBUTE_LOCAL; |
| } |
| if (lpszPrinterSettings) |
| free(lpszPrinterSettings); |
| |
| return(bCalcSpaceOnly); |
| } |
| |
| /****************************************************************** |
| * ENUMPRINTERS_AddInfo5A internal |
| * |
| * Creates a PRINTER_INFO_5A structure at: lpbPrinters[dwNextStructPos] |
| * for printer PrinterNameKey. |
| * Settings are read from the registry. |
| * Note that there is no check whether the information really fits! |
| * RETURNS |
| * FALSE if there is still space left in the buffer. |
| */ |
| BOOL ENUMPRINTERS_AddInfo5A( |
| LPSTR lpszPrinterName,/* name of printer to fill struct for*/ |
| LPBYTE lpbPrinters, /* buffer which receives info*/ |
| DWORD dwNextStructPos, /* pos in buffer for struct */ |
| LPDWORD dwNextStringPos, /* pos in buffer for next string */ |
| DWORD dwBufSize, /* max size of buffer in bytes */ |
| BOOL bCalcSpaceOnly /* TRUE if out-of-space in buffer */ |
| ){ |
| HKEY hPrinterSettings; |
| LPSTR lpszPrinterSettings = (LPSTR) malloc(strlen(Printers)+ |
| strlen(lpszPrinterName)+2); |
| LPPRINTER_INFO_5A lpPInfo5 = (LPPRINTER_INFO_5A) &lpbPrinters[dwNextStructPos]; |
| |
| /* open the registry to find the attributes, etc of the printer */ |
| if (lpszPrinterSettings!=NULL) |
| { |
| strcpy(lpszPrinterSettings,Printers); |
| strcat(lpszPrinterSettings,lpszPrinterName); |
| } |
| if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpszPrinterSettings, 0, |
| KEY_READ, &hPrinterSettings) != ERROR_SUCCESS) |
| { |
| WARN("The registry did not contain my printer anymore?\n"); |
| } |
| else |
| { |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Name", &(lpPInfo5->pPrinterName), |
| lpbPrinters, dwNextStringPos, |
| dwBufSize, bCalcSpaceOnly); |
| bCalcSpaceOnly = ENUMPRINTERS_AddStringFromRegistryA(hPrinterSettings, |
| "Port", &(lpPInfo5->pPortName), lpbPrinters, |
| dwNextStringPos, dwBufSize, bCalcSpaceOnly); |
| /* FIXME: Attributes gets LOCAL as no REMOTE exists*/ |
| if (bCalcSpaceOnly == FALSE) |
| { |
| lpPInfo5->Attributes = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "Attributes") +PRINTER_ATTRIBUTE_LOCAL; |
| lpPInfo5->DeviceNotSelectedTimeOut |
| = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "txTimeout"); |
| lpPInfo5->TransmissionRetryTimeout |
| = ENUMPRINTERS_GetDWORDFromRegistryA(hPrinterSettings, |
| "dnsTimeout"); |
| } |
| } |
| |
| if (lpszPrinterSettings) |
| free(lpszPrinterSettings); |
| |
| return(bCalcSpaceOnly); |
| } |
| |
| |
| /****************************************************************** |
| * EnumPrintersA [WINSPOOL.174] |
| * |
| * Enumerates the available printers, print servers and print |
| * providers, depending on the specified flags, name and level. |
| * |
| * RETURNS: |
| * |
| * If level is set to 1: |
| * Not implemented yet! |
| * Returns TRUE with an empty list. |
| * |
| * If level is set to 2: |
| * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL. |
| * Returns an array of PRINTER_INFO_2 data structures in the |
| * lpbPrinters buffer. Note that according to MSDN also an |
| * OpenPrinter should be performed on every remote printer. |
| * |
| * If level is set to 4 (officially WinNT only): |
| * Possible flags: PRINTER_ENUM_CONNECTIONS, PRINTER_ENUM_LOCAL. |
| * Fast: Only the registry is queried to retrieve printer names, |
| * no connection to the driver is made. |
| * Returns an array of PRINTER_INFO_4 data structures in the |
| * lpbPrinters buffer. |
| * |
| * If level is set to 5 (officially WinNT4/Win9x only): |
| * Fast: Only the registry is queried to retrieve printer names, |
| * no connection to the driver is made. |
| * Returns an array of PRINTER_INFO_5 data structures in the |
| * lpbPrinters buffer. |
| * |
| * If level set to 3 or 6+: |
| * returns zero (faillure!) |
| * |
| * Returns nonzero (TRUE) on succes, or zero on faillure, use GetLastError |
| * for information. |
| * |
| * BUGS: |
| * - Only PRINTER_ENUM_LOCAL and PRINTER_ENUM_NAME are implemented. |
| * - Only levels 2, 4 and 5 are implemented at the moment. |
| * - 16-bit printer drivers are not enumerated. |
| * - Returned amount of bytes used/needed does not match the real Windoze |
| * implementation (as in this implementation, all strings are part |
| * of the buffer, whereas Win32 keeps them somewhere else) |
| * - At level 2, EnumPrinters should also call OpenPrinter for remote printers. |
| * |
| * NOTE: |
| * - In a regular Wine installation, no registry settings for printers |
| * exist, which makes this function return an empty list. |
| */ |
| BOOL WINAPI EnumPrintersA( |
| DWORD dwType, /* Types of print objects to enumerate */ |
| LPSTR lpszName, /* name of objects to enumerate */ |
| DWORD dwLevel, /* type of printer info structure */ |
| LPBYTE lpbPrinters, /* buffer which receives info */ |
| DWORD cbBuf, /* max size of buffer in bytes */ |
| LPDWORD lpdwNeeded, /* pointer to var: # bytes used/needed */ |
| LPDWORD lpdwReturned /* number of entries returned */ |
| ) |
| { |
| HKEY hPrinterListKey; |
| DWORD dwIndex=0; |
| char PrinterName[255]; |
| DWORD PrinterNameLength=255; |
| FILETIME FileTime; |
| DWORD dwNextStringPos; /* position of next space for a string in the buffer*/ |
| DWORD dwStructPrinterInfoSize; /* size of a Printer_Info_X structure */ |
| BOOL bCalcSpaceOnly=FALSE;/*if TRUE: don't store data, just calculate space*/ |
| |
| TRACE("entered.\n"); |
| |
| /* test whether we're requested to really fill in. If so, |
| * zero out the data area, and initialise some returns to zero, |
| * to prevent problems |
| */ |
| if (lpbPrinters==NULL || cbBuf==0) |
| bCalcSpaceOnly=TRUE; |
| else |
| { |
| int i; |
| for (i=0; i<cbBuf; i++) |
| lpbPrinters[i]=0; |
| } |
| *lpdwReturned=0; |
| *lpdwNeeded = 0; |
| |
| /* check for valid Flags */ |
| if (!((dwType & PRINTER_ENUM_LOCAL) || (dwType & PRINTER_ENUM_NAME))) |
| { |
| FIXME("dwType = %08lx\n", dwType); |
| SetLastError(ERROR_INVALID_FLAGS); |
| return(0); |
| } |
| switch(dwLevel) |
| { |
| case 1: |
| return(TRUE); |
| case 2: |
| case 4: |
| case 5: |
| break; |
| default: |
| SetLastError(ERROR_INVALID_LEVEL); |
| return(FALSE); |
| } |
| |
| /* Enter critical section to prevent AddPrinters() et al. to |
| * modify whilst we're reading in the registry |
| */ |
| InitializeCriticalSection(&PRINT32_RegistryBlocker); |
| EnterCriticalSection(&PRINT32_RegistryBlocker); |
| |
| /* get a pointer to a list of all printer names in the registry */ |
| if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Printers, 0, KEY_READ, |
| &hPrinterListKey) !=ERROR_SUCCESS) |
| { |
| /* Oh no! An empty list of printers! |
| * (which is a valid configuration anyway) |
| */ |
| TRACE("No entries in the Printers part of the registry\n"); |
| } |
| |
| /* count the number of entries and check if it fits in the buffer |
| */ |
| while(RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength, |
| NULL, NULL, NULL, &FileTime)==ERROR_SUCCESS) |
| { |
| PrinterNameLength=255; |
| dwIndex++; |
| } |
| *lpdwReturned = dwIndex; |
| switch(dwLevel) |
| { |
| case 1: |
| dwStructPrinterInfoSize = sizeof(PRINTER_INFO_1A); |
| break; |
| case 2: |
| dwStructPrinterInfoSize = sizeof(PRINTER_INFO_2A); |
| break; |
| case 4: |
| dwStructPrinterInfoSize = sizeof(PRINTER_INFO_4A); |
| break; |
| case 5: |
| dwStructPrinterInfoSize = sizeof(PRINTER_INFO_5A); |
| break; |
| default: |
| dwStructPrinterInfoSize = 0; |
| break; |
| } |
| if (dwIndex*dwStructPrinterInfoSize+1 > cbBuf) |
| bCalcSpaceOnly = TRUE; |
| |
| /* the strings which contain e.g. PrinterName, PortName, etc, |
| * are also stored in lpbPrinters, but after the regular structs. |
| * dwNextStringPos will always point to the next free place for a |
| * string. |
| */ |
| dwNextStringPos=(dwIndex+1)*dwStructPrinterInfoSize; |
| |
| /* check each entry: if OK, add to list in corresponding INFO . |
| */ |
| for(dwIndex=0; dwIndex < *lpdwReturned; dwIndex++) |
| { |
| PrinterNameLength=255; |
| if (RegEnumKeyExA(hPrinterListKey, dwIndex, PrinterName, &PrinterNameLength, |
| NULL, NULL, NULL, &FileTime)!=ERROR_SUCCESS) |
| break; /* exit for loop*/ |
| TRACE("Got printer '%s'\n", PrinterName); |
| |
| /* check whether this printer is allowed in the list |
| * by comparing name to lpszName |
| */ |
| if (dwType & PRINTER_ENUM_NAME) |
| if (strcmp(PrinterName,lpszName)!=0) |
| continue; |
| |
| switch(dwLevel) |
| { |
| case 1: |
| /* FIXME: unimplemented */ |
| break; |
| case 2: |
| bCalcSpaceOnly = ENUMPRINTERS_AddInfo2A(PrinterName, lpbPrinters, |
| dwIndex*dwStructPrinterInfoSize, |
| &dwNextStringPos, cbBuf, bCalcSpaceOnly); |
| break; |
| case 4: |
| bCalcSpaceOnly = ENUMPRINTERS_AddInfo4A(PrinterName, lpbPrinters, |
| dwIndex*dwStructPrinterInfoSize, |
| &dwNextStringPos, cbBuf, bCalcSpaceOnly); |
| break; |
| case 5: |
| bCalcSpaceOnly = ENUMPRINTERS_AddInfo5A(PrinterName, lpbPrinters, |
| dwIndex*dwStructPrinterInfoSize, |
| &dwNextStringPos, cbBuf, bCalcSpaceOnly); |
| break; |
| } |
| } |
| RegCloseKey(hPrinterListKey); |
| LeaveCriticalSection(&PRINT32_RegistryBlocker); |
| *lpdwNeeded = dwNextStringPos + 10; /*Hack*/ |
| |
| if (bCalcSpaceOnly==TRUE) |
| { |
| if (lpbPrinters!=NULL) |
| { |
| int i; |
| for (i=0; i<cbBuf; i++) |
| lpbPrinters[i]=0; |
| } |
| *lpdwReturned=0; |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| return FALSE; |
| } |
| return(TRUE); |
| } |
| |
| /****************************************************************** |
| * EnumPrinters32W [WINSPOOL.175] |
| * |
| */ |
| BOOL WINAPI EnumPrintersW(DWORD dwType, LPWSTR lpszName, |
| DWORD dwLevel, LPBYTE lpbPrinters, |
| DWORD cbBuf, LPDWORD lpdwNeeded, |
| LPDWORD lpdwReturned) |
| { |
| FIXME("Nearly empty stub\n"); |
| *lpdwReturned=0; |
| *lpdwNeeded = 0; |
| return TRUE; |
| } |
| |
| /****************************************************************** |
| * AddMonitor32A [WINSPOOL.107] |
| * |
| */ |
| BOOL WINAPI AddMonitorA(LPSTR pName, DWORD Level, LPBYTE pMonitors) |
| { |
| FIXME("(%s,%lx,%p):stub!\n", pName, Level, pMonitors); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| /****************************************************************** |
| * DeletePrinterDriver32A [WINSPOOL.146] |
| * |
| */ |
| BOOL WINAPI |
| DeletePrinterDriverA (LPSTR pName, LPSTR pEnvironment, LPSTR pDriverName) |
| { |
| FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment), |
| debugstr_a(pDriverName)); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| |
| /****************************************************************** |
| * DeleteMonitor32A [WINSPOOL.135] |
| * |
| */ |
| BOOL WINAPI |
| DeleteMonitorA (LPSTR pName, LPSTR pEnvironment, LPSTR pMonitorName) |
| { |
| FIXME("(%s,%s,%s):stub\n",debugstr_a(pName),debugstr_a(pEnvironment), |
| debugstr_a(pMonitorName)); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| |
| /****************************************************************** |
| * DeletePort32A [WINSPOOL.137] |
| * |
| */ |
| BOOL WINAPI |
| DeletePortA (LPSTR pName, HWND hWnd, LPSTR pPortName) |
| { |
| FIXME("(%s,0x%08x,%s):stub\n",debugstr_a(pName),hWnd, |
| debugstr_a(pPortName)); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| /****************************************************************************** |
| * SetPrinter32W [WINSPOOL.214] |
| */ |
| BOOL WINAPI |
| SetPrinterW( |
| HANDLE hPrinter, |
| DWORD Level, |
| LPBYTE pPrinter, |
| DWORD Command) { |
| |
| FIXME("():stub\n"); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| /****************************************************************************** |
| * WritePrinter32 [WINSPOOL.223] |
| */ |
| BOOL WINAPI |
| WritePrinter( |
| HANDLE hPrinter, |
| LPVOID pBuf, |
| DWORD cbBuf, |
| LPDWORD pcWritten) { |
| |
| FIXME("():stub\n"); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * AddForm32A [WINSPOOL.103] |
| */ |
| BOOL WINAPI AddFormA(HANDLE hPrinter, DWORD Level, LPBYTE pForm) |
| { |
| FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * AddForm32W [WINSPOOL.104] |
| */ |
| BOOL WINAPI AddFormW(HANDLE hPrinter, DWORD Level, LPBYTE pForm) |
| { |
| FIXME("(%d,%ld,%p): stub\n", hPrinter, Level, pForm); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * AddJob32A [WINSPOOL.105] |
| */ |
| BOOL WINAPI AddJobA(HANDLE hPrinter, DWORD Level, LPBYTE pData, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf, |
| pcbNeeded); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * AddJob32W [WINSPOOL.106] |
| */ |
| BOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, |
| LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pData, cbBuf, |
| pcbNeeded); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * AddPrinter32A [WINSPOOL.117] |
| */ |
| HANDLE WINAPI AddPrinterA(LPSTR pName, DWORD Level, LPBYTE pPrinter) |
| { |
| PRINTER_INFO_2A *pi = (PRINTER_INFO_2A *) pPrinter; |
| |
| HANDLE retval; |
| HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers; |
| |
| TRACE("(%s,%ld,%p)\n", pName, Level, pPrinter); |
| |
| if(pName != NULL) { |
| FIXME("pName = `%s' - unsupported\n", pName); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return 0; |
| } |
| if(Level != 2) { |
| WARN("Level = %ld\n", Level); |
| SetLastError(ERROR_INVALID_LEVEL); |
| return 0; |
| } |
| if(!pPrinter) { |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return 0; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Printers key\n"); |
| return 0; |
| } |
| if(RegOpenKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) == |
| ERROR_SUCCESS) { |
| SetLastError(ERROR_PRINTER_ALREADY_EXISTS); |
| RegCloseKey(hkeyPrinter); |
| RegCloseKey(hkeyPrinters); |
| return 0; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Drivers key\n"); |
| RegCloseKey(hkeyPrinters); |
| return 0; |
| } |
| if(RegOpenKeyA(hkeyDrivers, pi->pDriverName, &hkeyDriver) != |
| ERROR_SUCCESS) { |
| WARN("Can't find driver `%s'\n", pi->pDriverName); |
| RegCloseKey(hkeyPrinters); |
| RegCloseKey(hkeyDrivers); |
| SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); |
| return 0; |
| } |
| RegCloseKey(hkeyDriver); |
| RegCloseKey(hkeyDrivers); |
| if(strcasecmp(pi->pPrintProcessor, "WinPrint")) { /* FIXME */ |
| WARN("Can't find processor `%s'\n", pi->pPrintProcessor); |
| SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR); |
| RegCloseKey(hkeyPrinters); |
| return 0; |
| } |
| if(RegCreateKeyA(hkeyPrinters, pi->pPrinterName, &hkeyPrinter) != |
| ERROR_SUCCESS) { |
| WARN("Can't create printer `%s'\n", pi->pPrinterName); |
| SetLastError(ERROR_INVALID_PRINTER_NAME); |
| RegCloseKey(hkeyPrinters); |
| return 0; |
| } |
| RegSetValueExA(hkeyPrinter, "Attributes", 0, REG_DWORD, |
| (LPSTR)&pi->Attributes, sizeof(DWORD)); |
| RegSetValueExA(hkeyPrinter, "Default DevMode", 0, REG_BINARY, |
| (LPSTR)&pi->pDevMode, |
| pi->pDevMode ? pi->pDevMode->dmSize : 0); |
| RegSetValueExA(hkeyPrinter, "Description", 0, REG_SZ, pi->pComment, 0); |
| RegSetValueExA(hkeyPrinter, "Location", 0, REG_SZ, pi->pLocation, 0); |
| RegSetValueExA(hkeyPrinter, "Name", 0, REG_SZ, pi->pPrinterName, 0); |
| RegSetValueExA(hkeyPrinter, "Parameters", 0, REG_SZ, pi->pParameters, 0); |
| RegSetValueExA(hkeyPrinter, "Port", 0, REG_SZ, pi->pPortName, 0); |
| RegSetValueExA(hkeyPrinter, "Print Processor", 0, REG_SZ, |
| pi->pPrintProcessor, 0); |
| RegSetValueExA(hkeyPrinter, "Printer Driver", 0, REG_SZ, pi->pDriverName, |
| 0); |
| RegSetValueExA(hkeyPrinter, "Priority", 0, REG_DWORD, |
| (LPSTR)&pi->Priority, sizeof(DWORD)); |
| RegSetValueExA(hkeyPrinter, "Separator File", 0, REG_SZ, pi->pSepFile, 0); |
| RegSetValueExA(hkeyPrinter, "Share Name", 0, REG_SZ, pi->pShareName, 0); |
| RegSetValueExA(hkeyPrinter, "Start Time", 0, REG_DWORD, |
| (LPSTR)&pi->StartTime, sizeof(DWORD)); |
| RegSetValueExA(hkeyPrinter, "Status", 0, REG_DWORD, |
| (LPSTR)&pi->Status, sizeof(DWORD)); |
| RegSetValueExA(hkeyPrinter, "Until Time", 0, REG_DWORD, |
| (LPSTR)&pi->UntilTime, sizeof(DWORD)); |
| |
| RegCloseKey(hkeyPrinter); |
| RegCloseKey(hkeyPrinters); |
| if(!OpenPrinterA(pi->pPrinterName, &retval, NULL)) { |
| ERR("OpenPrinter failing\n"); |
| return 0; |
| } |
| return retval; |
| } |
| |
| /***************************************************************************** |
| * AddPrinter32W [WINSPOOL.122] |
| */ |
| HANDLE WINAPI AddPrinterW(LPWSTR pName, DWORD Level, LPBYTE pPrinter) |
| { |
| FIXME("(%p,%ld,%p): stub\n", pName, Level, pPrinter); |
| return 0; |
| } |
| |
| |
| /***************************************************************************** |
| * ClosePrinter32 [WINSPOOL.126] |
| */ |
| BOOL WINAPI ClosePrinter(HANDLE hPrinter) |
| { |
| LPOPENEDPRINTERA lpOpenedPrinter; |
| |
| TRACE("Handle %d\n", hPrinter); |
| |
| if (!pOpenedPrinterDPA) |
| return FALSE; |
| |
| if ((hPrinter != -1) && (hPrinter < (pOpenedPrinterDPA->nItemCount - 1))) |
| { |
| lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter); |
| HeapFree(GetProcessHeap(), 0, lpOpenedPrinter->lpsPrinterName); |
| lpOpenedPrinter->lpsPrinterName = NULL; |
| |
| /* Free the memory of lpDefault if it has been initialized*/ |
| if(lpOpenedPrinter->lpDefault != NULL) |
| { |
| HeapFree(GetProcessHeap(), 0, |
| lpOpenedPrinter->lpDefault->pDevMode); |
| HeapFree(GetProcessHeap(), 0, |
| lpOpenedPrinter->lpDefault->pDatatype); |
| HeapFree(GetProcessHeap(), 0, |
| lpOpenedPrinter->lpDefault); |
| lpOpenedPrinter->lpDefault = NULL; |
| } |
| |
| lpOpenedPrinter->hPrinter = -1; |
| |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * DeleteForm32A [WINSPOOL.133] |
| */ |
| BOOL WINAPI DeleteFormA(HANDLE hPrinter, LPSTR pFormName) |
| { |
| FIXME("(%d,%s): stub\n", hPrinter, pFormName); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * DeleteForm32W [WINSPOOL.134] |
| */ |
| BOOL WINAPI DeleteFormW(HANDLE hPrinter, LPWSTR pFormName) |
| { |
| FIXME("(%d,%s): stub\n", hPrinter, debugstr_w(pFormName)); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * DeletePrinter32 [WINSPOOL.143] |
| */ |
| BOOL WINAPI DeletePrinter(HANDLE hPrinter) |
| { |
| FIXME("(%d): stub\n", hPrinter); |
| return 1; |
| } |
| |
| /***************************************************************************** |
| * SetPrinter32A [WINSPOOL.211] |
| */ |
| BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| DWORD Command) |
| { |
| FIXME("(%d,%ld,%p,%ld): stub\n",hPrinter,Level,pPrinter,Command); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * SetJob32A [WINSPOOL.209] |
| */ |
| BOOL WINAPI SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, |
| LPBYTE pJob, DWORD Command) |
| { |
| FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob, |
| Command); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * SetJob32W [WINSPOOL.210] |
| */ |
| BOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, |
| LPBYTE pJob, DWORD Command) |
| { |
| FIXME("(%d,%ld,%ld,%p,%ld): stub\n",hPrinter,JobId,Level,pJob, |
| Command); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * GetForm32A [WINSPOOL.181] |
| */ |
| BOOL WINAPI GetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level, |
| LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter,pFormName, |
| Level,pForm,cbBuf,pcbNeeded); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * GetForm32W [WINSPOOL.182] |
| */ |
| BOOL WINAPI GetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level, |
| LPBYTE pForm, DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%s,%ld,%p,%ld,%p): stub\n",hPrinter, |
| debugstr_w(pFormName),Level,pForm,cbBuf,pcbNeeded); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * SetForm32A [WINSPOOL.207] |
| */ |
| BOOL WINAPI SetFormA(HANDLE hPrinter, LPSTR pFormName, DWORD Level, |
| LPBYTE pForm) |
| { |
| FIXME("(%d,%s,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * SetForm32W [WINSPOOL.208] |
| */ |
| BOOL WINAPI SetFormW(HANDLE hPrinter, LPWSTR pFormName, DWORD Level, |
| LPBYTE pForm) |
| { |
| FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pFormName,Level,pForm); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * ReadPrinter32 [WINSPOOL.202] |
| */ |
| BOOL WINAPI ReadPrinter(HANDLE hPrinter, LPVOID pBuf, DWORD cbBuf, |
| LPDWORD pNoBytesRead) |
| { |
| FIXME("(%d,%p,%ld,%p): stub\n",hPrinter,pBuf,cbBuf,pNoBytesRead); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * ResetPrinter32A [WINSPOOL.203] |
| */ |
| BOOL WINAPI ResetPrinterA(HANDLE hPrinter, LPPRINTER_DEFAULTSA pDefault) |
| { |
| FIXME("(%d, %p): stub\n", hPrinter, pDefault); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * ResetPrinter32W [WINSPOOL.204] |
| */ |
| BOOL WINAPI ResetPrinterW(HANDLE hPrinter, LPPRINTER_DEFAULTSW pDefault) |
| { |
| FIXME("(%d, %p): stub\n", hPrinter, pDefault); |
| return FALSE; |
| } |
| |
| |
| /***************************************************************************** |
| * WINSPOOL_GetStringFromRegA |
| * |
| * Get ValueName from hkey storing result in str. buflen is space left in str |
| */ |
| static BOOL WINSPOOL_GetStringFromRegA(HKEY hkey, LPCSTR ValueName, LPSTR ptr, |
| DWORD buflen, DWORD *needed) |
| { |
| DWORD sz = buflen, type; |
| LONG ret; |
| |
| ret = RegQueryValueExA(hkey, ValueName, 0, &type, ptr, &sz); |
| |
| if(ret != ERROR_SUCCESS && ret != ERROR_MORE_DATA) { |
| ERR("Got ret = %ld\n", ret); |
| return FALSE; |
| } |
| *needed = sz; |
| return TRUE; |
| } |
| |
| /********************************************************************* |
| * WINSPOOL_GetPrinter_2A |
| * |
| * Fills out a PRINTER_INFO_2A struct storing the strings in buf. |
| */ |
| static BOOL WINSPOOL_GetPrinter_2A(HKEY hkeyPrinter, PRINTER_INFO_2A *pi2, |
| LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| DWORD size, left = cbBuf; |
| BOOL space = (cbBuf > 0); |
| LPBYTE ptr = buf; |
| |
| *pcbNeeded = 0; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size); |
| if(space && size <= left) { |
| pi2->pPrinterName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size); |
| if(space && size <= left) { |
| pi2->pPortName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Printer Driver", ptr, left, |
| &size); |
| if(space && size <= left) { |
| pi2->pDriverName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Default DevMode", ptr, left, |
| &size); |
| if(space && size <= left) { |
| pi2->pDevMode = (LPDEVMODEA)ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Print Processor", ptr, left, |
| &size); |
| if(space && size <= left) { |
| pi2->pPrintProcessor = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| if(!space && pi2) /* zero out pi2 if we can't completely fill buf */ |
| memset(pi2, 0, sizeof(*pi2)); |
| |
| return space; |
| } |
| |
| /********************************************************************* |
| * WINSPOOL_GetPrinter_4A |
| * |
| * Fills out a PRINTER_INFO_4A struct storing the strings in buf. |
| */ |
| static BOOL WINSPOOL_GetPrinter_4A(HKEY hkeyPrinter, PRINTER_INFO_4A *pi4, |
| LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| DWORD size, left = cbBuf; |
| BOOL space = (cbBuf > 0); |
| LPBYTE ptr = buf; |
| |
| *pcbNeeded = 0; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size); |
| if(space && size <= left) { |
| pi4->pPrinterName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| |
| *pcbNeeded += size; |
| |
| if(!space && pi4) /* zero out pi4 if we can't completely fill buf */ |
| memset(pi4, 0, sizeof(*pi4)); |
| |
| return space; |
| } |
| |
| /********************************************************************* |
| * WINSPOOL_GetPrinter_5A |
| * |
| * Fills out a PRINTER_INFO_5A struct storing the strings in buf. |
| */ |
| static BOOL WINSPOOL_GetPrinter_5A(HKEY hkeyPrinter, PRINTER_INFO_5A *pi5, |
| LPBYTE buf, DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| DWORD size, left = cbBuf; |
| BOOL space = (cbBuf > 0); |
| LPBYTE ptr = buf; |
| |
| *pcbNeeded = 0; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Name", ptr, left, &size); |
| if(space && size <= left) { |
| pi5->pPrinterName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyPrinter, "Port", ptr, left, &size); |
| if(space && size <= left) { |
| pi5->pPortName = ptr; |
| ptr += size; |
| left -= size; |
| } else |
| space = FALSE; |
| *pcbNeeded += size; |
| |
| if(!space && pi5) /* zero out pi5 if we can't completely fill buf */ |
| memset(pi5, 0, sizeof(*pi5)); |
| |
| return space; |
| } |
| |
| /***************************************************************************** |
| * GetPrinterA [WINSPOOL.187] |
| */ |
| BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| OPENEDPRINTERA *lpOpenedPrinter; |
| DWORD size, needed = 0; |
| LPBYTE ptr = NULL; |
| HKEY hkeyPrinter, hkeyPrinters; |
| BOOL ret; |
| |
| TRACE("(%d,%ld,%p,%ld,%p)\n",hPrinter,Level,pPrinter,cbBuf, pcbNeeded); |
| |
| lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter); |
| if(!lpOpenedPrinter) { |
| SetLastError(ERROR_INVALID_HANDLE); |
| return FALSE; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Printers key\n"); |
| return FALSE; |
| } |
| if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter) |
| != ERROR_SUCCESS) { |
| ERR("Can't find opened printer `%s' in registry\n", |
| lpOpenedPrinter->lpsPrinterName); |
| RegCloseKey(hkeyPrinters); |
| SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */ |
| return FALSE; |
| } |
| |
| switch(Level) { |
| case 2: |
| { |
| PRINTER_INFO_2A *pi2 = (PRINTER_INFO_2A *)pPrinter; |
| |
| size = sizeof(PRINTER_INFO_2A); |
| if(size <= cbBuf) { |
| ptr = pPrinter + size; |
| cbBuf -= size; |
| memset(pPrinter, 0, size); |
| } else { |
| pi2 = NULL; |
| cbBuf = 0; |
| } |
| ret = WINSPOOL_GetPrinter_2A(hkeyPrinter, pi2, ptr, cbBuf, &needed); |
| needed += size; |
| break; |
| } |
| |
| case 4: |
| { |
| PRINTER_INFO_4A *pi4 = (PRINTER_INFO_4A *)pPrinter; |
| |
| size = sizeof(PRINTER_INFO_4A); |
| if(size <= cbBuf) { |
| ptr = pPrinter + size; |
| cbBuf -= size; |
| memset(pPrinter, 0, size); |
| } else { |
| pi4 = NULL; |
| cbBuf = 0; |
| } |
| ret = WINSPOOL_GetPrinter_4A(hkeyPrinter, pi4, ptr, cbBuf, &needed); |
| needed += size; |
| break; |
| } |
| |
| |
| case 5: |
| { |
| PRINTER_INFO_5A *pi5 = (PRINTER_INFO_5A *)pPrinter; |
| |
| size = sizeof(PRINTER_INFO_5A); |
| if(size <= cbBuf) { |
| ptr = pPrinter + size; |
| cbBuf -= size; |
| memset(pPrinter, 0, size); |
| } else { |
| pi5 = NULL; |
| cbBuf = 0; |
| } |
| |
| ret = WINSPOOL_GetPrinter_5A(hkeyPrinter, pi5, ptr, cbBuf, &needed); |
| needed += size; |
| break; |
| } |
| |
| default: |
| FIXME("Unimplemented level %ld\n", Level); |
| SetLastError(ERROR_INVALID_LEVEL); |
| RegCloseKey(hkeyPrinters); |
| RegCloseKey(hkeyPrinter); |
| return FALSE; |
| } |
| |
| RegCloseKey(hkeyPrinter); |
| RegCloseKey(hkeyPrinters); |
| |
| if(pcbNeeded) *pcbNeeded = needed; |
| if(!ret) |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| return ret; |
| } |
| |
| |
| /***************************************************************************** |
| * GetPrinterW [WINSPOOL.194] |
| */ |
| BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%ld,%p,%ld,%p): stub\n", hPrinter, Level, pPrinter, |
| cbBuf, pcbNeeded); |
| return FALSE; |
| } |
| |
| |
| /***************************************************************************** |
| * GetPrinterDriver32A [WINSPOOL.190] |
| */ |
| BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, |
| DWORD Level, LPBYTE pDriverInfo, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| OPENEDPRINTERA *lpOpenedPrinter; |
| char DriverName[100]; |
| DWORD ret, type, size, dw, needed = 0; |
| LPBYTE ptr = NULL; |
| HKEY hkeyPrinter, hkeyPrinters, hkeyDriver, hkeyDrivers; |
| |
| TRACE("(%d,%s,%ld,%p,%ld,%p)\n",hPrinter,pEnvironment, |
| Level,pDriverInfo,cbBuf, pcbNeeded); |
| |
| lpOpenedPrinter = WINSPOOL_GetOpenedPrinterA(hPrinter); |
| if(!lpOpenedPrinter) { |
| SetLastError(ERROR_INVALID_HANDLE); |
| return FALSE; |
| } |
| if(pEnvironment) { |
| FIXME("pEnvironment = `%s'\n", pEnvironment); |
| SetLastError(ERROR_INVALID_ENVIRONMENT); |
| return FALSE; |
| } |
| if(Level < 1 || Level > 3) { |
| SetLastError(ERROR_INVALID_LEVEL); |
| return FALSE; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Printers, &hkeyPrinters) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Printers key\n"); |
| return FALSE; |
| } |
| if(RegOpenKeyA(hkeyPrinters, lpOpenedPrinter->lpsPrinterName, &hkeyPrinter) |
| != ERROR_SUCCESS) { |
| ERR("Can't find opened printer `%s' in registry\n", |
| lpOpenedPrinter->lpsPrinterName); |
| RegCloseKey(hkeyPrinters); |
| SetLastError(ERROR_INVALID_PRINTER_NAME); /* ? */ |
| return FALSE; |
| } |
| size = sizeof(DriverName); |
| ret = RegQueryValueExA(hkeyPrinter, "Printer Driver", 0, &type, DriverName, |
| &size); |
| RegCloseKey(hkeyPrinter); |
| RegCloseKey(hkeyPrinters); |
| if(ret != ERROR_SUCCESS) { |
| ERR("Can't get DriverName for printer `%s'\n", |
| lpOpenedPrinter->lpsPrinterName); |
| return FALSE; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Drivers key\n"); |
| return FALSE; |
| } |
| if(RegOpenKeyA(hkeyDrivers, DriverName, &hkeyDriver) |
| != ERROR_SUCCESS) { |
| ERR("Can't find driver `%s' in registry\n", DriverName); |
| RegCloseKey(hkeyDrivers); |
| SetLastError(ERROR_UNKNOWN_PRINTER_DRIVER); /* ? */ |
| return FALSE; |
| } |
| |
| 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; |
| default: |
| ERR("Invalid level\n"); |
| return FALSE; |
| } |
| |
| if(size <= cbBuf) { |
| ptr = pDriverInfo + size; |
| cbBuf -= size; |
| } else |
| cbBuf = 0; |
| needed = size; |
| |
| size = strlen(DriverName) + 1; |
| if(size <= cbBuf) { |
| cbBuf -= size; |
| strcpy(ptr, DriverName); |
| if(Level == 1) |
| ((DRIVER_INFO_1A *)pDriverInfo)->pName = ptr; |
| else |
| ((DRIVER_INFO_2A *)pDriverInfo)->pName = ptr; |
| ptr += size; |
| } |
| needed += size; |
| |
| if(Level > 1) { |
| DRIVER_INFO_2A *di2 = (DRIVER_INFO_2A *)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; |
| |
| size = strlen("Wine") + 1; /* FIXME */ |
| if(size <= cbBuf) { |
| cbBuf -= size; |
| strcpy(ptr, "Wine"); |
| di2->pEnvironment = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Driver", ptr, cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di2->pDriverPath = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Data File", ptr, cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di2->pDataFile = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Configuration File", ptr, |
| cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di2->pConfigFile = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| } |
| |
| if(Level > 2) { |
| DRIVER_INFO_3A *di3 = (DRIVER_INFO_3A *)pDriverInfo; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Help File", ptr, cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di3->pHelpFile = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Dependent Files", ptr, cbBuf, |
| &size); |
| if(cbBuf && size <= cbBuf) { |
| di3->pDependentFiles = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "Monitor", ptr, cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di3->pMonitorName = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| |
| WINSPOOL_GetStringFromRegA(hkeyDriver, "DataType", ptr, cbBuf, &size); |
| if(cbBuf && size <= cbBuf) { |
| di3->pDefaultDataType = ptr; |
| ptr += size; |
| } else |
| cbBuf = 0; |
| needed += size; |
| } |
| RegCloseKey(hkeyDriver); |
| RegCloseKey(hkeyDrivers); |
| |
| if(pcbNeeded) *pcbNeeded = needed; |
| if(cbBuf) return TRUE; |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * GetPrinterDriver32W [WINSPOOL.193] |
| */ |
| BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, |
| DWORD Level, LPBYTE pDriverInfo, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| FIXME("(%d,%p,%ld,%p,%ld,%p): stub\n",hPrinter,pEnvironment, |
| Level,pDriverInfo,cbBuf, pcbNeeded); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * GetPrinterDriverDirectoryA [WINSPOOL.191] |
| */ |
| BOOL WINAPI GetPrinterDriverDirectoryA(LPSTR pName, LPSTR pEnvironment, |
| DWORD Level, LPBYTE pDriverDirectory, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| DWORD needed; |
| |
| TRACE("(%s, %s, %ld, %p, %ld, %p)\n", pName, pEnvironment, Level, |
| pDriverDirectory, cbBuf, pcbNeeded); |
| if(pName != NULL) { |
| FIXME("pName = `%s' - unsupported\n", pName); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return FALSE; |
| } |
| if(pEnvironment != NULL) { |
| FIXME("pEnvironment = `%s' - unsupported\n", pEnvironment); |
| SetLastError(ERROR_INVALID_ENVIRONMENT); |
| return FALSE; |
| } |
| if(Level != 1) /* win95 ignores this so we just carry on */ |
| WARN("Level = %ld - assuming 1\n", Level); |
| |
| /* FIXME should read from registry */ |
| needed = GetSystemDirectoryA(pDriverDirectory, cbBuf); |
| needed++; |
| if(pcbNeeded) |
| *pcbNeeded = needed; |
| if(needed > cbBuf) { |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); |
| return FALSE; |
| } |
| return TRUE; |
| } |
| |
| |
| /***************************************************************************** |
| * GetPrinterDriverDirectoryW [WINSPOOL.192] |
| */ |
| BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR pName, LPWSTR pEnvironment, |
| DWORD Level, LPBYTE pDriverDirectory, |
| DWORD cbBuf, LPDWORD pcbNeeded) |
| { |
| LPSTR pNameA = NULL, pEnvironmentA = NULL; |
| BOOL ret; |
| |
| if(pName) |
| pNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, pName ); |
| if(pEnvironment) |
| pEnvironmentA = HEAP_strdupWtoA( GetProcessHeap(), 0, pEnvironment ); |
| ret = GetPrinterDriverDirectoryA( pNameA, pEnvironmentA, Level, |
| pDriverDirectory, cbBuf, pcbNeeded ); |
| if(pNameA) |
| HeapFree( GetProcessHeap(), 0, pNameA ); |
| if(pEnvironmentA) |
| HeapFree( GetProcessHeap(), 0, pEnvironment ); |
| |
| return ret; |
| } |
| |
| /***************************************************************************** |
| * AddPrinterDriver32A [WINSPOOL.120] |
| */ |
| BOOL WINAPI AddPrinterDriverA(LPSTR pName, DWORD level, LPBYTE pDriverInfo) |
| { |
| DRIVER_INFO_3A di3; |
| HKEY hkeyDrivers, hkeyName; |
| |
| TRACE("(%s,%ld,%p)\n",pName,level,pDriverInfo); |
| |
| if(level != 2 && level != 3) { |
| SetLastError(ERROR_INVALID_LEVEL); |
| return FALSE; |
| } |
| if(pName != NULL) { |
| FIXME("pName= `%s' - unsupported\n", pName); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return FALSE; |
| } |
| if(!pDriverInfo) { |
| WARN("pDriverInfo == NULL"); |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return FALSE; |
| } |
| |
| if(level == 3) |
| di3 = *(DRIVER_INFO_3A *)pDriverInfo; |
| else { |
| memset(&di3, 0, sizeof(di3)); |
| *(DRIVER_INFO_2A *)&di3 = *(DRIVER_INFO_2A *)pDriverInfo; |
| } |
| |
| if(!di3.pName || !di3.pDriverPath || !di3.pConfigFile || |
| !di3.pDataFile) { |
| SetLastError(ERROR_INVALID_PARAMETER); |
| return FALSE; |
| } |
| if(!di3.pDefaultDataType) di3.pDefaultDataType = ""; |
| if(!di3.pDependentFiles) di3.pDependentFiles = "\0"; |
| if(!di3.pHelpFile) di3.pHelpFile = ""; |
| if(!di3.pMonitorName) di3.pMonitorName = ""; |
| |
| if(di3.pEnvironment) { |
| FIXME("pEnvironment = `%s'\n", di3.pEnvironment); |
| SetLastError(ERROR_INVALID_ENVIRONMENT); |
| return FALSE; |
| } |
| if(RegCreateKeyA(HKEY_LOCAL_MACHINE, Drivers, &hkeyDrivers) != |
| ERROR_SUCCESS) { |
| ERR("Can't create Drivers key\n"); |
| return FALSE; |
| } |
| |
| if(level == 2) { /* apparently can't overwrite with level2 */ |
| if(RegOpenKeyA(hkeyDrivers, di3.pName, &hkeyName) == ERROR_SUCCESS) { |
| RegCloseKey(hkeyName); |
| RegCloseKey(hkeyDrivers); |
| WARN("Trying to create existing printer driver `%s'\n", di3.pName); |
| SetLastError(ERROR_PRINTER_DRIVER_ALREADY_INSTALLED); |
| return FALSE; |
| } |
| } |
| if(RegCreateKeyA(hkeyDrivers, di3.pName, &hkeyName) != ERROR_SUCCESS) { |
| RegCloseKey(hkeyDrivers); |
| ERR("Can't create Name key\n"); |
| return FALSE; |
| } |
| RegSetValueExA(hkeyName, "Configuration File", 0, REG_SZ, di3.pConfigFile, |
| 0); |
| RegSetValueExA(hkeyName, "Data File", 0, REG_SZ, di3.pDataFile, 0); |
| RegSetValueExA(hkeyName, "Driver", 0, REG_SZ, di3.pDriverPath, 0); |
| RegSetValueExA(hkeyName, "Version", 0, REG_DWORD, (LPSTR)&di3.cVersion, |
| sizeof(DWORD)); |
| RegSetValueExA(hkeyName, "Datatype", 0, REG_SZ, di3.pDefaultDataType, 0); |
| RegSetValueExA(hkeyName, "Dependent Files", 0, REG_MULTI_SZ, |
| di3.pDependentFiles, 0); |
| RegSetValueExA(hkeyName, "Help File", 0, REG_SZ, di3.pHelpFile, 0); |
| RegSetValueExA(hkeyName, "Monitor", 0, REG_SZ, di3.pMonitorName, 0); |
| RegCloseKey(hkeyName); |
| RegCloseKey(hkeyDrivers); |
| |
| return TRUE; |
| } |
| /***************************************************************************** |
| * AddPrinterDriver32W [WINSPOOL.121] |
| */ |
| BOOL WINAPI AddPrinterDriverW(LPWSTR printerName,DWORD level, |
| LPBYTE pDriverInfo) |
| { |
| FIXME("(%s,%ld,%p): stub\n",debugstr_w(printerName), |
| level,pDriverInfo); |
| return FALSE; |
| } |
| |
| |
| /***************************************************************************** |
| * PrinterProperties [WINSPOOL.201] |
| * |
| * Displays a dialog to set the properties of the printer. |
| * |
| * RETURNS |
| * nonzero on succes or zero on faillure |
| * |
| * BUGS |
| * implemented as stub only |
| */ |
| BOOL WINAPI PrinterProperties(HWND hWnd, /* handle to parent window */ |
| HANDLE hPrinter /* handle to printer object */ |
| ){ |
| FIXME("(%d,%d): stub\n", hWnd, hPrinter); |
| SetLastError(ERROR_CALL_NOT_IMPLEMENTED); |
| return FALSE; |
| } |
| |
| /***************************************************************************** |
| * EnumJobsA [WINSPOOL.162] |
| * |
| */ |
| BOOL WINAPI EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, |
| DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, |
| LPDWORD pcReturned) |
| { |
| FIXME("stub\n"); |
| if(pcbNeeded) *pcbNeeded = 0; |
| if(pcReturned) *pcReturned = 0; |
| return TRUE; |
| } |
| |
| |
| /***************************************************************************** |
| * EnumJobsW [WINSPOOL.163] |
| * |
| */ |
| BOOL WINAPI EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, |
| DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded, |
| LPDWORD pcReturned) |
| { |
| FIXME("stub\n"); |
| if(pcbNeeded) *pcbNeeded = 0; |
| if(pcReturned) *pcReturned = 0; |
| return TRUE; |
| } |