diff --git a/dll/win32/kernel32/wine/profile.c b/dll/win32/kernel32/wine/profile.c index f89da3f2988..58282e78492 100644 --- a/dll/win32/kernel32/wine/profile.c +++ b/dll/win32/kernel32/wine/profile.c @@ -1210,7 +1210,7 @@ INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry, LPWSTR bufferW; INT retW, ret = 0; - bufferW = buffer ? HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)) : NULL; + bufferW = buffer ? HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)) : NULL; if (section) RtlCreateUnicodeStringFromAsciiz(§ionW, section); else sectionW.Buffer = NULL; if (entry) RtlCreateUnicodeStringFromAsciiz(&entryW, entry); @@ -1227,10 +1227,21 @@ INT WINAPI GetPrivateProfileStringA( LPCSTR section, LPCSTR entry, { if (retW) { + if (retW < (INT)len - 1) + { + /* also convert the final string terminator */ + if (!entryW.Buffer && retW < (INT)len - 2) + retW++; /* section enumeration: also convert the list terminator */ + retW++; + } ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW, buffer, len - 1, NULL, NULL); - if (!ret) - ret = len - 1; + if (ret == len - 1) /* overflow */ + { + ret = len - 2; + buffer[ret] = 0; + } } + /* buffer stays double-nul terminated: it was zero-initialized */ buffer[ret] = 0; } @@ -1392,15 +1403,15 @@ INT WINAPI GetPrivateProfileSectionA( LPCSTR section, LPSTR buffer, return 0; } - bufferW = HeapAlloc(GetProcessHeap(), 0, len * 2 * sizeof(WCHAR)); + bufferW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * 2 * sizeof(WCHAR)); RtlCreateUnicodeStringFromAsciiz(§ionW, section); if (filename) RtlCreateUnicodeStringFromAsciiz(&filenameW, filename); else filenameW.Buffer = NULL; retW = GetPrivateProfileSectionW(sectionW.Buffer, bufferW, len * 2, filenameW.Buffer); + if (retW == len * 2 - 2) retW++; /* overflow */ if (retW) { - if (retW == len * 2 - 2) retW++; /* overflow */ ret = WideCharToMultiByte(CP_ACP, 0, bufferW, retW + 1, buffer, len, NULL, NULL); if (!ret || ret == len) /* overflow */ { diff --git a/win32ss/printing/base/winspool/printers.c b/win32ss/printing/base/winspool/printers.c index 2f874c81e05..caea5f596ec 100644 --- a/win32ss/printing/base/winspool/printers.c +++ b/win32ss/printing/base/winspool/printers.c @@ -196,27 +196,40 @@ Cleanup: return (dwErrorCode == ERROR_SUCCESS); } +static PWSTR +AsciiStringToUnicode(LPCSTR pstr) +{ + UNICODE_STRING us; + PWSTR pwsz = NULL; + + if (pstr) + { + RtlCreateUnicodeStringFromAsciiz(&us, pstr); + pwsz = us.Buffer; + } + return pwsz; +} + +static VOID +FreeUnicodeString(PWSTR pwsz) +{ + UNICODE_STRING us; + + if (pwsz) + { + us.Buffer = pwsz; + RtlFreeUnicodeString(&us); + } +} + HANDLE WINAPI AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter) { - UNICODE_STRING pNameW, usBuffer; + UNICODE_STRING usNameW; PWSTR pwstrNameW; - PRINTER_INFO_2W *ppi2w = (PRINTER_INFO_2W*)pPrinter; PRINTER_INFO_2A *ppi2a = (PRINTER_INFO_2A*)pPrinter; + PRINTER_INFO_2W pi2w; HANDLE ret = NULL; - PWSTR pwszPrinterName = NULL; - PWSTR pwszServerName = NULL; - PWSTR pwszShareName = NULL; - PWSTR pwszPortName = NULL; - PWSTR pwszDriverName = NULL; - PWSTR pwszComment = NULL; - PWSTR pwszLocation = NULL; - PWSTR pwszSepFile = NULL; - PWSTR pwszPrintProcessor = NULL; - PWSTR pwszDatatype = NULL; - PWSTR pwszParameters = NULL; - PWSTR pPrintProcessor = NULL; - PDEVMODEW pdmw = NULL; TRACE("AddPrinterA(%s, %d, %p)\n", debugstr_a(pName), Level, pPrinter); @@ -227,91 +240,103 @@ AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter) return NULL; } - pwstrNameW = AsciiToUnicode(&pNameW,pName); + pwstrNameW = AsciiToUnicode(&usNameW, pName); + /* Do NOT overwrite the caller's ANSI structure in place. + * Use a temporary Unicode PRINTER_INFO_2W on the stack and convert + * each ANSI string field to its Unicode counterpart. */ + ZeroMemory(&pi2w, sizeof(pi2w)); + + if (ppi2a->pServerName) + { + pi2w.pServerName = AsciiStringToUnicode(ppi2a->pServerName); + if (!pi2w.pServerName) goto Cleanup; + } + if (ppi2a->pPrinterName) + { + pi2w.pPrinterName = AsciiStringToUnicode(ppi2a->pPrinterName); + if (!pi2w.pPrinterName) goto Cleanup; + } if (ppi2a->pShareName) { - pwszShareName = AsciiToUnicode(&usBuffer, ppi2a->pShareName); - if (!(ppi2w->pShareName = pwszShareName)) goto Cleanup; + pi2w.pShareName = AsciiStringToUnicode(ppi2a->pShareName); + if (!pi2w.pShareName) goto Cleanup; } if (ppi2a->pPortName) { - pwszPortName = AsciiToUnicode(&usBuffer, ppi2a->pPortName); - if (!(ppi2w->pPortName = pwszPortName)) goto Cleanup; + pi2w.pPortName = AsciiStringToUnicode(ppi2a->pPortName); + if (!pi2w.pPortName) goto Cleanup; } if (ppi2a->pDriverName) { - pwszDriverName = AsciiToUnicode(&usBuffer, ppi2a->pDriverName); - if (!(ppi2w->pDriverName = pwszDriverName)) goto Cleanup; + pi2w.pDriverName = AsciiStringToUnicode(ppi2a->pDriverName); + if (!pi2w.pDriverName) goto Cleanup; } if (ppi2a->pComment) { - pwszComment = AsciiToUnicode(&usBuffer, ppi2a->pComment); - if (!(ppi2w->pComment = pwszComment)) goto Cleanup; + pi2w.pComment = AsciiStringToUnicode(ppi2a->pComment); + if (!pi2w.pComment) goto Cleanup; } if (ppi2a->pLocation) { - pwszLocation = AsciiToUnicode(&usBuffer, ppi2a->pLocation); - if (!(ppi2w->pLocation = pwszLocation)) goto Cleanup; + pi2w.pLocation = AsciiStringToUnicode(ppi2a->pLocation); + if (!pi2w.pLocation) goto Cleanup; + } + if (ppi2a->pDevMode) + { + RosConvertAnsiDevModeToUnicodeDevmode(ppi2a->pDevMode, &pi2w.pDevMode); + if (!pi2w.pDevMode) goto Cleanup; } if (ppi2a->pSepFile) { - pwszSepFile = AsciiToUnicode(&usBuffer, ppi2a->pSepFile); - if (!(ppi2w->pSepFile = pwszSepFile)) goto Cleanup; + pi2w.pSepFile = AsciiStringToUnicode(ppi2a->pSepFile); + if (!pi2w.pSepFile) goto Cleanup; } - if (ppi2a->pServerName) + if (ppi2a->pPrintProcessor) { - pwszPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor); - if (!(ppi2w->pPrintProcessor = pwszPrintProcessor)) goto Cleanup; + pi2w.pPrintProcessor = AsciiStringToUnicode(ppi2a->pPrintProcessor); + if (!pi2w.pPrintProcessor) goto Cleanup; } if (ppi2a->pDatatype) { - pwszDatatype = AsciiToUnicode(&usBuffer, ppi2a->pDatatype); - if (!(ppi2w->pDatatype = pwszDatatype)) goto Cleanup; + pi2w.pDatatype = AsciiStringToUnicode(ppi2a->pDatatype); + if (!pi2w.pDatatype) goto Cleanup; } if (ppi2a->pParameters) { - pwszParameters = AsciiToUnicode(&usBuffer, ppi2a->pParameters); - if (!(ppi2w->pParameters = pwszParameters)) goto Cleanup; - } - if ( ppi2a->pDevMode ) - { - RosConvertAnsiDevModeToUnicodeDevmode( ppi2a->pDevMode, &pdmw ); - ppi2w->pDevMode = pdmw; - } - if (ppi2a->pServerName) - { - pwszServerName = AsciiToUnicode(&usBuffer, ppi2a->pServerName); - if (!(ppi2w->pPrinterName = pwszServerName)) goto Cleanup; - } - if (ppi2a->pPrinterName) - { - pwszPrinterName = AsciiToUnicode(&usBuffer, ppi2a->pPrinterName); - if (!(ppi2w->pPrinterName = pwszPrinterName)) goto Cleanup; - } - if (ppi2a->pPrintProcessor) - { - pPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor); - if (!(ppi2w->pPrintProcessor = pPrintProcessor)) goto Cleanup; + pi2w.pParameters = AsciiStringToUnicode(ppi2a->pParameters); + if (!pi2w.pParameters) goto Cleanup; } - ret = AddPrinterW(pwstrNameW, Level, (LPBYTE)ppi2w); + /* Copy scalar fields. */ + pi2w.pSecurityDescriptor = ppi2a->pSecurityDescriptor; + pi2w.Attributes = ppi2a->Attributes; + pi2w.Priority = ppi2a->Priority; + pi2w.DefaultPriority = ppi2a->DefaultPriority; + pi2w.StartTime = ppi2a->StartTime; + pi2w.UntilTime = ppi2a->UntilTime; + pi2w.Status = ppi2a->Status; + pi2w.cJobs = ppi2a->cJobs; + pi2w.AveragePPM = ppi2a->AveragePPM; -Cleanup: - if (pdmw) HeapFree(hProcessHeap, 0, pdmw); - if (pwszPrinterName) HeapFree(hProcessHeap, 0, pwszPrinterName); - if (pwszServerName) HeapFree(hProcessHeap, 0, pwszServerName); - if (pwszShareName) HeapFree(hProcessHeap, 0, pwszShareName); - if (pwszPortName) HeapFree(hProcessHeap, 0, pwszPortName); - if (pwszDriverName) HeapFree(hProcessHeap, 0, pwszDriverName); - if (pwszComment) HeapFree(hProcessHeap, 0, pwszComment); - if (pwszLocation) HeapFree(hProcessHeap, 0, pwszLocation); - if (pwszSepFile) HeapFree(hProcessHeap, 0, pwszSepFile); - if (pwszPrintProcessor) HeapFree(hProcessHeap, 0, pwszPrintProcessor); - if (pwszDatatype) HeapFree(hProcessHeap, 0, pwszDatatype); - if (pwszParameters) HeapFree(hProcessHeap, 0, pwszParameters); + ret = AddPrinterW(pwstrNameW, Level, (LPBYTE)&pi2w); - RtlFreeUnicodeString(&pNameW); +Cleanup: + /* Free the temporary Unicode strings. */ + FreeUnicodeString(pi2w.pServerName); + FreeUnicodeString(pi2w.pPrinterName); + FreeUnicodeString(pi2w.pShareName); + FreeUnicodeString(pi2w.pPortName); + FreeUnicodeString(pi2w.pDriverName); + FreeUnicodeString(pi2w.pComment); + FreeUnicodeString(pi2w.pLocation); + FreeUnicodeString(pi2w.pSepFile); + FreeUnicodeString(pi2w.pPrintProcessor); + FreeUnicodeString(pi2w.pDatatype); + FreeUnicodeString(pi2w.pParameters); + if (pi2w.pDevMode) HeapFree(GetProcessHeap(), 0, pi2w.pDevMode); + + RtlFreeUnicodeString(&usNameW); return ret; } @@ -3139,6 +3164,9 @@ SetDefaultPrinterW(LPCWSTR pszPrinter) goto Cleanup; } + // Keep the legacy win.ini entry in sync. + WriteProfileStringW(L"windows", wszDeviceValue, pwszDeviceValueData); + Cleanup: if (hDevicesKey) RegCloseKey(hDevicesKey); diff --git a/win32ss/printing/providers/localspl/printers.c b/win32ss/printing/providers/localspl/printers.c index aaa313d5a4c..9d16fd90d9a 100644 --- a/win32ss/printing/providers/localspl/printers.c +++ b/win32ss/printing/providers/localspl/printers.c @@ -1999,6 +1999,67 @@ LocalClosePrinter(HANDLE hPrinter) return TRUE; } +static +PWSTR +BuildDeviceEntryValue(PCWSTR pwszDriverName, PCWSTR pwszPortName, BOOL bWithTimeouts) +{ + SIZE_T cchNeeded; + PWSTR pwszValue; + + // Build a value of the format ",[,15,45]". + cchNeeded = wcslen(pwszDriverName) + 1 + wcslen(pwszPortName) + 1; + if (bWithTimeouts) + cchNeeded += 6; + + pwszValue = DllAllocSplMem(cchNeeded * sizeof(WCHAR)); + if (!pwszValue) + return NULL; + + wcscpy(pwszValue, pwszDriverName); + wcscat(pwszValue, L","); + wcscat(pwszValue, pwszPortName); + + if (bWithTimeouts) + wcscat(pwszValue, L",15,45"); + + return pwszValue; +} + +static +VOID +MaintainWinIniEntries(PCWSTR pwszPrinterName, PCWSTR pwszDriverName, PCWSTR pwszPortName) +{ + PWSTR pwszValue; + + if (!pwszPrinterName || !*pwszPrinterName) + return; + + // Passing NULL as the value deletes the entry. + if (!pwszDriverName || !*pwszDriverName || !pwszPortName || !*pwszPortName) + { + WriteProfileStringW(L"devices", pwszPrinterName, NULL); + WriteProfileStringW(L"PrinterPorts", pwszPrinterName, NULL); + return; + } + + // Maintain the legacy win.ini sections [devices] and [PrinterPorts] like the + // Windows NT print spooler does, so that applications which enumerate printers + // through them (e.g. Visual Basic 6 programs using their Printers collection) work. + pwszValue = BuildDeviceEntryValue(pwszDriverName, pwszPortName, FALSE); + if (pwszValue) + { + WriteProfileStringW(L"devices", pwszPrinterName, pwszValue); + DllFreeSplMem(pwszValue); + } + + pwszValue = BuildDeviceEntryValue(pwszDriverName, pwszPortName, TRUE); + if (pwszValue) + { + WriteProfileStringW(L"PrinterPorts", pwszPrinterName, pwszValue); + DllFreeSplMem(pwszValue); + } +} + HANDLE WINAPI LocalAddPrinter(LPWSTR pName, DWORD level, LPBYTE pPrinterInfo) { @@ -2204,6 +2265,10 @@ LocalAddPrinter(LPWSTR pName, DWORD level, LPBYTE pPrinterInfo) // The Printer was added successfully. RegCloseKey(hPrinterKey); + + // Keep the legacy win.ini entries in sync. + MaintainWinIniEntries(pInfo->pPrinterName, pLocalPrinter->pwszPrinterDriver, pPort->pwszName); + SetLastError(ROUTER_SUCCESS); return hPrinter; @@ -2274,6 +2339,9 @@ LocalDeletePrinter(HANDLE hPrinter) // Delete the Printer's registry key. RegDeleteKeyW(hPrintersKey, pPrinter->pwszPrinterName); + // Keep the legacy win.ini entries in sync. + MaintainWinIniEntries(pPrinter->pwszPrinterName, NULL, NULL); + // Free all resources of the Printer. DllFreeSplStr(pPrinter->pwszPrinterName); DllFreeSplStr(pPrinter->pwszLocation);