Commit 2adeb215 authored by Vitaly Lipatov's avatar Vitaly Lipatov

commit 23.6.0 upon wine-8.0.1

parent 04c46c19
......@@ -91,6 +91,7 @@
@ stdcall CM_Get_Device_Interface_List_SizeW(ptr ptr wstr long) setupapi.CM_Get_Device_Interface_List_SizeW
@ stdcall CM_Get_Device_Interface_List_Size_ExA(ptr ptr str long ptr) setupapi.CM_Get_Device_Interface_List_Size_ExA
@ stdcall CM_Get_Device_Interface_List_Size_ExW(ptr ptr wstr long ptr) setupapi.CM_Get_Device_Interface_List_Size_ExW
@ stub CM_Get_Device_Interface_PropertyW
@ stub CM_Get_First_Log_Conf
@ stub CM_Get_First_Log_Conf_Ex
@ stub CM_Get_Global_State
......
......@@ -620,6 +620,19 @@ static BOOL check_resource_write( void *addr )
return TRUE;
}
/* CrossOver Hack #22795 */
static BOOL is_quicken_updateicons(void)
{
WCHAR path[MAX_PATH];
DWORD exe_len = wcslen( L"UpdateIcons.exe" );
DWORD path_len = GetModuleFileNameW( NULL, path, MAX_PATH );
if (!wcsstr( path, L"quickenPatch" ))
return FALSE;
return exe_len <= path_len && !lstrcmpiW( path + path_len - exe_len, L"UpdateIcons.exe" );
}
/*******************************************************************
* UnhandledExceptionFilter (kernelbase.@)
......@@ -655,6 +668,13 @@ LONG WINAPI UnhandledExceptionFilter( EXCEPTION_POINTERS *epointers )
/* FIXME: Should check the current error mode */
/* CrossOver Hack #22795 */
if (is_quicken_updateicons())
{
FIXME( "HACK: crashing without error dialog for Quicken UpdateIcons.exe\n" );
TerminateProcess( GetCurrentProcess(), 1 );
}
if (!start_debugger_atomic( epointers ) || !NtCurrentTeb()->Peb->BeingDebugged)
return EXCEPTION_EXECUTE_HANDLER;
}
......
......@@ -644,6 +644,10 @@ static const WCHAR *hack_append_command_line( const WCHAR *cmd, const WCHAR *cmd
/* CROSSOVER HACK: bug 22598
* Add --launcher-skip to the Witcher 3 prelauncher.
*/
/* CROSSOVER HACK: bug 20279
* Add --in-process-gpu to the Warframe launcher (...\Tools\Launcher.exe), with
* various parent directories per server type.
*/
static const struct
{
......@@ -664,6 +668,7 @@ static const WCHAR *hack_append_command_line( const WCHAR *cmd, const WCHAR *cmd
{L"Battle.net.exe", L" --in-process-gpu --use-gl=swiftshader", NULL, NULL},
{L"msedgewebview2.exe", L" --in-process-gpu --use-gl=swiftshader --no-sandbox", NULL, L"--type=crashpad-handler"},
{L"redprelauncher.exe", L" --launcher-skip", NULL, NULL},
{L"\\Tools\\Launcher.exe", L" --in-process-gpu", NULL, NULL},
};
unsigned int i;
......
......@@ -36,6 +36,14 @@
#include <cups/cups.h>
#endif
#ifdef __APPLE__
#include <crt_externs.h>
#include <spawn.h>
#include <sys/wait.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/debug.h"
......@@ -57,7 +65,8 @@ static void *libcups_handle;
DO_FUNC(cupsGetOption); \
DO_FUNC(cupsParseOptions); \
DO_FUNC(cupsStartDocument); \
DO_FUNC(cupsWriteRequestData)
DO_FUNC(cupsWriteRequestData); \
DO_FUNC(cupsPrintFile)
#define CUPS_OPT_FUNCS \
DO_FUNC(cupsGetNamedDest); \
DO_FUNC(cupsLastErrorString)
......@@ -103,6 +112,11 @@ typedef struct _doc_t
cups_option_t *options;
int buf_len;
char buf[257]; /* DSC max of 256 + '\0' */
#ifdef __APPLE__
/* CW HACK 22800 */
char *filename;
int fd;
#endif
} cups;
#endif
};
......@@ -227,6 +241,124 @@ static BOOL lpr_start_doc(doc_t *doc, const WCHAR *printer_name)
return pipe_start_doc(doc, cmd);
}
#ifdef __APPLE__
/* CW HACK 22800 */
/*****************************************************************************
* is_postscript_supported
*
* Determines if CUPS supports PostScript input. macOS Sonoma removes support.
*/
static BOOL is_postscript_supported(void)
{
BOOL ret = FALSE;
const char *const argv[] = {"/usr/sbin/cupsfilter", "--list-filters", "-i", "application/postscript", "-m", "application/pdf", NULL};
pid_t pid, wret;
int status;
static int postscript_supported = -1;
TRACE("()\n");
/* Check if we've already cached the value */
if (postscript_supported >= 0)
{
ret = postscript_supported;
goto end;
}
if (posix_spawn(&pid, argv[0], NULL, NULL, argv, *_NSGetEnviron()) != 0)
{
WARN("Failed to load %s\n", debugstr_a(argv[0]));
goto end;
}
do {
wret = waitpid(pid, &status, 0);
} while (wret < 0 && errno == EINTR);
if (wret < 0)
{
WARN("waitpid() failed!\n");
return FALSE;
}
if (!WIFEXITED(status))
{
WARN("cupsfilter did not exit cleanly (%d)\n", status);
goto end;
}
ret = WEXITSTATUS(status) == 0;
end:
postscript_supported = ret;
TRACE(" -> %d\n", ret);
return ret;
}
/*****************************************************************************
* convert_postscript_to_pdf
*/
static BOOL convert_postscript_to_pdf(const char *filename, const char *pdf)
{
BOOL ret = FALSE;
char ps2pdf[MAX_PATH];
const char *ps2pdf_argv[4];
pid_t pid, wret;
int status;
int exit_status;
TRACE("(%s, %s)\n", debugstr_a(filename), debugstr_a(pdf));
strcpy(ps2pdf, getenv("CX_ROOT"));
strcat(ps2pdf, "/bin/cxps2pdf");
ps2pdf_argv[0] = "cxps2pdf";
ps2pdf_argv[1] = filename;
ps2pdf_argv[2] = pdf;
ps2pdf_argv[3] = NULL;
if (posix_spawn(&pid, ps2pdf, NULL, NULL, ps2pdf_argv, *_NSGetEnviron()) != 0)
{
WARN("Failed to load %s with arguments %s %s\n", debugstr_a(ps2pdf), debugstr_a(ps2pdf_argv[1]), debugstr_a(ps2pdf_argv[2]));
goto end;
}
do {
wret = waitpid(pid, &status, 0);
} while (wret < 0 && errno == EINTR);
if (wret < 0)
{
WARN("waitpid() failed!\n");
return FALSE;
}
if (!WIFEXITED(status))
{
WARN("ps2pdf did not exit cleanly (%d)\n", status);
goto end;
}
exit_status = WEXITSTATUS(status);
if (exit_status != 0)
{
WARN("ps2pdf returned error %d\n", exit_status);
goto end;
}
ret = TRUE;
end:
TRACE(" -> %d\n", ret);
return ret;
}
#endif
#ifdef SONAME_LIBCUPS
static int get_cups_default_options(const char *printer, int num_options, cups_option_t **options)
{
......@@ -266,8 +398,23 @@ static BOOL cups_gets(doc_t *doc, const BYTE **buf, unsigned int *size)
return FALSE;
}
#ifdef __APPLE__
/* CW HACK 22800 */
#define cups_write(a, b) mac_cups_write(doc, a, b)
static BOOL mac_cups_write(doc_t *doc, const char *buf, unsigned int size)
{
if (doc->cups.filename != NULL)
{
return (!size) || write(doc->cups.fd, buf, size) == size;
}
#else
static BOOL cups_write(const char *buf, unsigned int size)
{
#endif
if (!size)
return TRUE;
......@@ -347,6 +494,11 @@ static BOOL cups_write_doc(doc_t *doc, const BYTE *buf, unsigned int size)
for (i = 0; i < doc->cups.num_options; i++)
TRACE("\t%d: %s = %s\n", i, doc->cups.options[i].name, doc->cups.options[i].value);
#ifdef __APPLE__
/* We will write all data to a .ps file on disk here and then convert it to PDF in cups_end_doc */
if (doc->cups.filename == NULL)
{
#endif
if (pcupsGetOption("raw", doc->cups.num_options, doc->cups.options))
format = CUPS_FORMAT_RAW;
else if (!(format = pcupsGetOption("document-format", doc->cups.num_options, doc->cups.options)))
......@@ -369,6 +521,10 @@ static BOOL cups_write_doc(doc_t *doc, const BYTE *buf, unsigned int size)
return FALSE;
}
#ifdef __APPLE__
}
#endif
doc->cups.state = doc_initialized;
}
......@@ -391,6 +547,44 @@ static BOOL cups_write_doc(doc_t *doc, const BYTE *buf, unsigned int size)
static BOOL cups_end_doc(doc_t *doc)
{
#ifdef __APPLE__
/* CW HACK 22800 */
if (doc->cups.filename != NULL)
{
char tempfile[] = "/tmp/winspool.XXXXXXXX.pdf";
BOOL ret = FALSE;
close(doc->unixname.fd);
/* Compute a temporary file name for PDF file */
if (!mkstemps(tempfile, 4))
{
WARN("mkstemps failed: %d\n", errno);
goto cleanup;
}
if (!convert_postscript_to_pdf(doc->cups.filename, tempfile))
goto cleanup;
if (pcupsPrintFile(doc->cups.queue, tempfile, doc->cups.doc_title, doc->cups.num_options, doc->cups.options) == 0)
{
if (pcupsLastErrorString)
WARN("cupsPrintFile failed: %s\n", pcupsLastErrorString());
goto cleanup;
}
ret = TRUE;
cleanup:
remove(doc->cups.filename);
free(doc->cups.filename);
free(doc->cups.queue);
free(doc->cups.doc_title);
return ret;
}
#endif
if (doc->cups.buf_len)
{
if (doc->cups.state != doc_initialized)
......@@ -415,6 +609,31 @@ static BOOL cups_start_doc(doc_t *doc, const WCHAR *printer_name, const WCHAR *d
{
int len;
#ifdef __APPLE__
/* CW HACK 22800 */
if (!is_postscript_supported())
{
char tempfile[] = "/tmp/winspool.XXXXXXXX";
/* Compute a temporary file name for PS file */
if (!mkstemp(tempfile))
{
WARN("mkstemp failed: %d\n", errno);
return FALSE;
}
doc->cups.fd = open(tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (doc->cups.fd == -1)
{
WARN("Unable to open temp file %s\n", debugstr_a(tempfile));
return FALSE;
}
doc->cups.filename = strdup(tempfile);
}
#endif
doc->write_doc = cups_write_doc;
doc->end_doc = cups_end_doc;
......
......@@ -2823,6 +2823,27 @@ static void patch_libcef( const WCHAR* libname, WINE_MODREF** pwm )
TRUE
},
/* CW HACK 18682:
* libcef.dll 85.2.0.2241 used by Sea of Thieves for Xbox login.
* Can reuse patches 85_3_9_0 and 85_3_11_1 at different offsets.
*/
{
L"libcef.dll",
"85.2.0.2241",
before_85_3_9_0, after_85_3_9_0,
sizeof(before_85_3_9_0),
0x28bdd90,
FALSE
},
{
L"libcef.dll",
"85.2.0.2241",
before_85_3_11_1, after_85_3_11_1,
sizeof(before_85_3_11_1),
0x28bde1a,
TRUE
},
/* CW HACK 19114:
* libcef.dll 72.0.3626.121 used by the game beamNG.drive.
* Patch also works for version downloadable from CEF builds.
......@@ -3533,8 +3554,18 @@ static NTSTATUS load_dll( const WCHAR *load_path, const WCHAR *libname, DWORD fl
case STATUS_SUCCESS: /* valid PE file */
nts = load_native_dll( load_path, &nt_name, mapping, &image_info, &id, flags, system, pwm );
#ifdef __x86_64__
if (nts == STATUS_SUCCESS && (!wcscmp( libname, L"libcef.dll" ) || !wcscmp( libname, L"Qt5WebEngineCore.dll" )))
patch_libcef( libname, pwm );
/* CX HACK 19487 (among others): binary patches for libcef %gs access */
if (nts == STATUS_SUCCESS)
{
const WCHAR *last_slash, *filename;
last_slash = wcsrchr( libname, L'\\' );
if (!last_slash) last_slash = wcsrchr( libname, L'/' );
filename = last_slash ? last_slash + 1 : libname;
if (!wcscmp( filename, L"libcef.dll" ) || !wcscmp( filename, L"Qt5WebEngineCore.dll" ))
{
patch_libcef( filename, pwm );
}
}
#endif
break;
}
......
......@@ -1142,7 +1142,7 @@ static NSString* WineLocalizedString(unsigned int stringID)
- (void) setCursorWithFrames:(NSArray*)frames
{
if (self.cursorFrames == frames)
if (self.cursorFrames == frames || [self.cursorFrames isEqualToArray:frames])
return;
self.cursorFrames = frames;
......
......@@ -244,16 +244,16 @@ static BOOL CALLBACK get_first_resource(HMODULE module, LPCWSTR type, LPWSTR nam
*/
static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
{
struct app_icon_params *params = arg;
struct app_icon_result *result = param_ptr(params->result);
struct app_icon_entry entries[64];
HRSRC res_info;
HGLOBAL res_data;
GRPICONDIR *icon_dir;
unsigned count;
int i;
TRACE("()\n");
result->count = 0;
count = 0;
res_info = NULL;
EnumResourceNamesW(NULL, (LPCWSTR)RT_GROUP_ICON, get_first_resource, (LONG_PTR)&res_info);
......@@ -275,9 +275,9 @@ static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
goto cleanup;
}
for (i = 0; i < icon_dir->idCount && result->count < ARRAYSIZE(result->entries); i++)
for (i = 0; i < icon_dir->idCount && count < ARRAYSIZE(entries); i++)
{
struct app_icon_entry *entry = &result->entries[result->count];
struct app_icon_entry *entry = &entries[count];
int width = icon_dir->idEntries[i].bWidth;
int height = icon_dir->idEntries[i].bHeight;
BOOL found_better_bpp = FALSE;
......@@ -339,7 +339,7 @@ static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
{
entry->png = (UINT_PTR)icon_bits;
entry->icon = 0;
result->count++;
count++;
}
else
{
......@@ -349,7 +349,7 @@ static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
{
entry->icon = HandleToUlong(icon);
entry->png = 0;
result->count++;
count++;
}
else
WARN("failed to create icon %d from resource with ID %hd\n", i, icon_dir->idEntries[i].nID);
......@@ -364,7 +364,7 @@ static NTSTATUS WINAPI macdrv_app_icon(void *arg, ULONG size)
cleanup:
FreeResource(res_data);
return 0;
return NtCallbackReturn(entries, count * sizeof(entries[0]), 0);
}
static NTSTATUS WINAPI macdrv_regcreateopenkeyexa(void *arg, ULONG size)
......
......@@ -249,27 +249,33 @@ cleanup:
*/
CFArrayRef create_app_icon_images(void)
{
struct app_icon_result icons;
struct app_icon_params params = { .result = (UINT_PTR)&icons };
CFMutableArrayRef images = NULL;
struct app_icon_entry *entries;
ULONG ret_len;
unsigned count;
int i;
TRACE("()\n");
macdrv_client_func(client_func_app_icon, &params, sizeof(params));
if (!icons.count) return NULL;
if (KeUserModeCallback(client_func_app_icon, NULL, 0, (void**)&entries, &ret_len) ||
(ret_len % sizeof(*entries)))
{
WARN("incorrect callback result\n");
return NULL;
}
count = ret_len / sizeof(*entries);
if (!count || !entries) return NULL;
images = CFArrayCreateMutable(NULL, icons.count, &kCFTypeArrayCallBacks);
images = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
if (!images)
{
WARN("failed to create images array\n");
return NULL;
}
for (i = 0; i < icons.count; i++)
for (i = 0; i < count; i++)
{
struct app_icon_entry *icon = &icons.entries[i];
struct app_icon_entry *icon = &entries[i];
CGImageRef cgimage = NULL;
if (icon->png)
......
......@@ -738,6 +738,30 @@ static BOOL get_icon_info(HICON handle, ICONINFOEXW *ret)
return TRUE;
}
/* CW HACK 22829 */
static BOOL is_cs2(void)
{
static const WCHAR cs2[] = {'c', 's', '2', '.', 'e', 'x', 'e', 0};
WCHAR *path, *appname, *p;
path = NtCurrentTeb()->Peb->ProcessParameters->ImagePathName.Buffer;
appname = path;
if ((p = wcsrchr(appname, '/'))) appname = p + 1;
if ((p = wcsrchr(appname, '\\'))) appname = p + 1;
return !wcsicmp(appname, cs2);
}
static BOOL needs_cs2_hack(void)
{
static BOOL needs_hack, did_check = FALSE;
if (!did_check)
{
needs_hack = is_cs2();
did_check = TRUE;
}
return needs_hack;
}
/***********************************************************************
* SetCursor (MACDRV.@)
......@@ -825,6 +849,18 @@ void macdrv_SetCursor(HCURSOR cursor)
}
done:
if (needs_cs2_hack() && !cursor_name && cursor_frames)
{
/* CW HACK 22829: suspected memory corruption by D3DMetal causes
* a crash in CS2 when the cursor is being set.
* The only custom cursor used by CS2 is completely transparent/empty anyway,
* so just hide the cursor.
*/
TRACE("CS2 hack: hiding cursor instead of displaying custom one\n");
CFRelease(cursor_frames);
cursor_frames = NULL;
}
TRACE("setting cursor with cursor_name %s cursor_frames %p\n", debugstr_cf(cursor_name), cursor_frames);
macdrv_set_cursor(cursor_name, cursor_frames);
if (cursor_name) CFRelease(cursor_name);
......
......@@ -123,18 +123,6 @@ struct app_icon_entry
UINT64 png;
};
struct app_icon_result
{
UINT32 count;
struct app_icon_entry entries[64];
};
/* macdrv_app_icon params */
struct app_icon_params
{
UINT64 result; /* FIXME: Use NtCallbackReturn instead */
};
/* macdrv_app_quit_request params */
struct app_quit_request_params
{
......
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