Compare commits

...

27 commits

Author SHA1 Message Date
Etaash Mathamsetty
2a40f9edb5 Merge branch 'home-isolate' into 'master'
Draft: shell32: Add environment variable to prevent symlinking home folders

See merge request wine/wine!4584
2024-11-18 10:27:35 +00:00
Rémi Bernon
ae6366b33c winex11: Introduce a new window_update_client_config helper. 2024-11-15 19:08:41 +01:00
Rémi Bernon
d9cf4678a1 winex11: Introduce a new window_update_client_state helper. 2024-11-15 19:08:41 +01:00
Rémi Bernon
da936bcf35 winex11: Use the new window state tracker to get WM_STATE value. 2024-11-15 19:08:40 +01:00
Rémi Bernon
e75192fe72 winex11: Use the new window state tracker to get _NET_WM_STATE value. 2024-11-15 19:08:40 +01:00
Rémi Bernon
0dc7e40468 winex11: Ignore focus changes during WM_STATE transitions.
When WM_STATE is being quickly updated, and depending on the WM we might
receive transient focus changes, which will disrupt the Win32 state and
make us randomly lose focus.

Ignore them instead, when a window is being shown, and wait for WM_STATE
to be updated and stable. We will eventually receive a WM_TAKE_FOCUS /
FocusIn event *after* a window has been shown.

When a window is hidden or minimized, we will receive the FocusOut event
during the WM_STATE transition, and can safely handle it in this case,
as we should have done all the Win32 side effects and have changed the
foreground window already.

When there's no window state change pending, the focus change event is
unexpected, coming from the user or WM, and we handle it normally.
2024-11-15 19:08:20 +01:00
Biswapriyo Nath
700ee59470 include: Add UI Automation Annotation Type ID definitions.
Required for c7ba4a9640
2024-11-15 19:08:10 +01:00
Marc-Aurel Zent
c76a192bf6 winex11: Include kbd.h instead of ime.h. 2024-11-15 19:07:58 +01:00
Marc-Aurel Zent
9acdc03128 include: Add Japanese IME virtual key codes to kbd.h. 2024-11-15 19:07:57 +01:00
Hans Leidekker
8b121591be wininet: Use InternetTimeToSystemTimeW() to convert header values.
The current code calls mktime() which interprets its argument as local time while these
values are assumed to be in UTC.
2024-11-15 19:07:26 +01:00
Hans Leidekker
5a23afb34d wininet: Accept UTC as the equivalent of GMT.
Based on a patch by Etaash Mathamsetty.
2024-11-15 19:07:24 +01:00
Nikolay Sivov
6a01532899 comctl32/listview: Send LVN_HOTTRACK in response to mouse moves.
It's worth noting that comctl32 v6 have hottracking notifications enabled
by default, there is no need to set any extended styles.

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-15 19:07:06 +01:00
Nikolay Sivov
e5b0ead2b5 comctl32/listview: Initialize hot cursor handle.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
2024-11-15 19:07:04 +01:00
Eric Pouech
b9c06c4474 dbghelp: Fill-in data in SymSrvGetFileIndexIndo if BAD_EXE_FORMAT.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
a57eedec86 dbghelp/tests: Improve SymSrvGetFileIndexInfo tests.
Esp. the failures with ERROR_BAD_EXE_FORMAT still fill all the fields
in the returned structure.

Add more flexibility to .dbg file creation (optional DEBUG_DIRECTORY).

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
9212706ede dbghelp: Only WARN on stripped PE images.
When stripping, binutils' objcopy also sets the flag, yet
without stripping into a .DBG file.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Eric Pouech
40b314cf34 dbghelp: Don't try to load PDB for a RSDS debug directory in .buildid section.
Signed-off-by: Eric Pouech <epouech@codeweavers.com>
2024-11-15 16:25:10 +01:00
Brendan Shanks
aa24458086 Add .gitattributes file to mark generated files. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
576d7e24cd server: Use an explicit struct instead of a typedef for async I/O data. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
305ec347dc server: Use an explicit struct instead of a typedef for user APCs. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
4c0103e58c server: Use an explicit union instead of a typedef for APC results. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
1137a10ef7 server: Use an explicit union instead of a typedef for APC calls. 2024-11-15 16:25:10 +01:00
Alexandre Julliard
eae7db4fa4 server: Simplify updating the protocol version. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
75e2ec479b server: Move the generated part of trace.c to a separate header. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
45953cdbec server: Move the generated part of request.h to a separate header. 2024-11-15 16:25:09 +01:00
Alexandre Julliard
126c54cd25 server: Print a warning if page size isn't 4k. 2024-11-15 16:25:09 +01:00
Etaash Mathamsetty
562dadcb1f shell32: Add environment variable to prevent symlinking home folders. 2023-12-02 11:53:31 -05:00
36 changed files with 7342 additions and 7171 deletions

64
.gitattributes vendored Normal file
View file

@ -0,0 +1,64 @@
[attr]generated gitlab-generated linguist-generated=true
# generated by autotools
configure generated
include/config.h.in generated
# generated by dlls/dsound/make_fir
dlls/dsound/fir.h generated
# generated by dlls/opencl/make_opencl
dlls/opencl/opencl.spec generated
dlls/opencl/opencl_types.h generated
dlls/opencl/pe_thunks.c generated
dlls/opencl/unix_thunks.c generated
dlls/opencl/unixlib.h generated
# generated by dlls/opengl32/make_opengl
dlls/opengl32/opengl32.spec generated
dlls/opengl32/thunks.c generated
dlls/opengl32/unix_thunks.c generated
dlls/opengl32/unixlib.h generated
include/wine/wgl.h generated
include/wine/wgl_driver.h generated
# generated by dlls/winevulkan/make_vulkan
dlls/vulkan-1/vulkan-1.spec generated
dlls/winevulkan/loader_thunks.c generated
dlls/winevulkan/loader_thunks.h generated
dlls/winevulkan/vulkan_thunks.c generated
dlls/winevulkan/vulkan_thunks.h generated
dlls/winevulkan/winevulkan.json generated
dlls/winevulkan/winevulkan.spec generated
include/wine/vulkan.h generated
include/wine/vulkan_driver.h generated
# generated by tools/make_requests
include/wine/server_protocol.h generated
server/request_handlers.h generated
server/request_trace.h generated
# generated by tools/make_specfiles
dlls/ntdll/ntsyscalls.h generated
dlls/win32u/win32syscalls.h generated
# generated by tools/make_unicode
dlls/dwrite/bracket.c generated
dlls/dwrite/direction.c generated
dlls/dwrite/linebreak.c generated
dlls/dwrite/mirror.c generated
dlls/dwrite/scripts.c generated
dlls/dwrite/scripts.h generated
dlls/dwrite/shapers/arabic_table.c generated
dlls/gdi32/uniscribe/bracket.c generated
dlls/gdi32/uniscribe/direction.c generated
dlls/gdi32/uniscribe/indicsyllable.c generated
dlls/gdi32/uniscribe/linebreak.c generated
dlls/gdi32/uniscribe/mirror.c generated
dlls/gdi32/uniscribe/shaping.c generated
dlls/kernelbase/kernelbase.rgs generated
dlls/tzres/tzres.rc generated
dlls/win32u/vertical.c generated
dlls/wineps.drv/direction.c generated
dlls/wineps.drv/vertical.c generated
nls/*.nls generated

View file

@ -4150,6 +4150,7 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
/* see if we are supposed to be tracking mouse hovering */
if (LISTVIEW_IsHotTracking(infoPtr)) {
TRACKMOUSEEVENT trackinfo;
NMLISTVIEW nmlv = { 0 };
DWORD flags;
trackinfo.cbSize = sizeof(TRACKMOUSEEVENT);
@ -4170,6 +4171,15 @@ static LRESULT LISTVIEW_MouseMove(LISTVIEW_INFO *infoPtr, WORD fwKeys, INT x, IN
/* call TRACKMOUSEEVENT so we receive WM_MOUSEHOVER messages */
_TrackMouseEvent(&trackinfo);
}
ht.pt = pt;
LISTVIEW_HitTest(infoPtr, &ht, TRUE, TRUE);
nmlv.iItem = ht.iItem;
nmlv.iSubItem = ht.iSubItem;
nmlv.ptAction = pt;
notify_listview(infoPtr, LVN_HOTTRACK, &nmlv);
}
return 0;
@ -9585,6 +9595,7 @@ static LRESULT LISTVIEW_NCCreate(HWND hwnd, WPARAM wParam, const CREATESTRUCTW *
infoPtr->iVersion = COMCTL32_VERSION;
infoPtr->colRectsDirty = FALSE;
infoPtr->selected_column = -1;
infoPtr->hHotCursor = LoadCursorW(NULL, (LPWSTR)IDC_HAND);
/* get default font (icon title) */
SystemParametersInfoW(SPI_GETICONTITLELOGFONT, 0, &logFont, 0);

View file

@ -7255,6 +7255,19 @@ static void test_LVM_GETNEXTITEM(void)
DestroyWindow(hwnd);
}
static void test_LVM_GETHOTCURSOR(void)
{
HCURSOR cursor;
HWND hwnd;
hwnd = create_listview_control(LVS_REPORT);
cursor = (HCURSOR)SendMessageA(hwnd, LVM_GETHOTCURSOR, 0, 0);
ok(!!cursor, "Unexpected cursor %p.\n", cursor);
DestroyWindow(hwnd);
}
START_TEST(listview)
{
ULONG_PTR ctx_cookie;
@ -7322,6 +7335,7 @@ START_TEST(listview)
test_LVM_SETBKIMAGE(FALSE);
test_custom_sort();
test_LVM_GETNEXTITEM();
test_LVM_GETHOTCURSOR();
if (!load_v6_module(&ctx_cookie, &hCtx))
{
@ -7372,6 +7386,7 @@ START_TEST(listview)
test_LVM_GETNEXTITEMINDEX();
test_LVM_GETNEXTITEM();
test_LVM_SETBKIMAGE(TRUE);
test_LVM_GETHOTCURSOR();
unload_v6_module(ctx_cookie, hCtx);

View file

@ -4379,7 +4379,13 @@ static BOOL codeview_process_info(const struct process *pcs,
TRACE("Got RSDS type of PDB file: guid=%s age=%08x name=%s\n",
wine_dbgstr_guid(&rsds->guid), rsds->age, debugstr_a(rsds->name));
ret = pdb_process_file(pcs, msc_dbg, rsds->name, &rsds->guid, 0, rsds->age);
/* gcc/mingw and clang can emit build-id information, but with an empty PDB filename.
* Don't search for the .pdb file in that case.
*/
if (rsds->name[0])
ret = pdb_process_file(pcs, msc_dbg, rsds->name, &rsds->guid, 0, rsds->age);
else
ret = TRUE;
break;
}
default:
@ -4487,7 +4493,7 @@ typedef struct _FPO_DATA
__ENDTRY
/* we haven't found yet any debug information, fallback to unmatched pdb */
if (module->module.SymType == SymDeferred)
if (!ret && module->module.SymType == SymDeferred)
{
SYMSRV_INDEX_INFOW info = {.sizeofstruct = sizeof(info)};
char buffer[MAX_PATH];
@ -4549,38 +4555,35 @@ DWORD msc_get_file_indexinfo(void* image, const IMAGE_DEBUG_DIRECTORY* debug_dir
num_misc_records++;
}
}
return info->stripped && !num_misc_records ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS;
return (!num_dir || (info->stripped && !num_misc_records)) ? ERROR_BAD_EXE_FORMAT : ERROR_SUCCESS;
}
DWORD dbg_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info)
{
const IMAGE_SEPARATE_DEBUG_HEADER *header;
IMAGE_DEBUG_DIRECTORY *dbg;
DWORD num_directories;
if (size < sizeof(*header)) return ERROR_BAD_EXE_FORMAT;
if (size < sizeof(*header)) return ERROR_BAD_FORMAT;
header = image;
if (header->Signature != 0x4944 /* DI */ ||
size < sizeof(*header) + header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + header->ExportedNamesSize + header->DebugDirectorySize)
return ERROR_BAD_EXE_FORMAT;
return ERROR_BAD_FORMAT;
info->size = header->SizeOfImage;
/* seems to use header's timestamp, not debug_directory one */
info->timestamp = header->TimeDateStamp;
info->stripped = FALSE; /* FIXME */
/* header is followed by:
* - header->NumberOfSections of IMAGE_SECTION_HEADER
* - header->ExportedNameSize
* - then num_directories of IMAGE_DEBUG_DIRECTORY
*/
dbg = (IMAGE_DEBUG_DIRECTORY*)((char*)(header + 1) +
header->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
header->ExportedNamesSize);
num_directories = header->DebugDirectorySize / sizeof(IMAGE_DEBUG_DIRECTORY);
if (!num_directories) return ERROR_BAD_EXE_FORMAT;
info->age = 0;
memset(&info->guid, 0, sizeof(info->guid));
info->sig = 0;
info->dbgfile[0] = L'\0';
info->pdbfile[0] = L'\0';
info->size = header->SizeOfImage;
/* seems to use header's timestamp, not debug_directory one */
info->timestamp = header->TimeDateStamp;
info->stripped = FALSE; /* FIXME */
return ERROR_SUCCESS;
return msc_get_file_indexinfo(image, dbg, num_directories, info);
}

View file

@ -832,7 +832,7 @@ BOOL WINAPI SymSrvGetFileIndexInfoW(const WCHAR *file, SYMSRV_INDEX_INFOW* info,
if (hMap) CloseHandle(hMap);
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
if (ret == ERROR_SUCCESS) wcscpy(info->file, file_name(file)); /* overflow? */
if (ret == ERROR_SUCCESS || ret == ERROR_BAD_EXE_FORMAT) wcscpy(info->file, file_name(file)); /* overflow? */
SetLastError(ret);
return ret == ERROR_SUCCESS;
}

View file

@ -656,8 +656,8 @@ static BOOL pe_load_msc_debug_info(const struct process* pcs, struct module* mod
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
{
ERR("-Debug info stripped, but no .DBG file in module %s\n",
debugstr_w(module->modulename));
WARN("-Debug info stripped, but no .DBG file in module %s\n",
debugstr_w(module->modulename));
}
else
{
@ -1019,7 +1019,7 @@ DWORD pe_get_file_indexinfo(void* image, DWORD size, SYMSRV_INDEX_INFOW* info)
if (!(nthdr = RtlImageNtHeader(image))) return ERROR_BAD_FORMAT;
dbg = RtlImageDirectoryEntryToData(image, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &dirsize);
if (!dbg || dirsize < sizeof(dbg)) return ERROR_BAD_EXE_FORMAT;
if (!dbg) dirsize = 0;
/* fill in information from NT header */
info->timestamp = nthdr->FileHeader.TimeDateStamp;

View file

@ -671,20 +671,22 @@ static BOOL create_test_pdb_ds(const WCHAR* pdb_name, const GUID* guid, DWORD ag
return TRUE;
}
static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD timestamp, DWORD size)
static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD charac, DWORD timestamp, DWORD size, struct debug_directory_blob *blob)
{
HANDLE hfile;
/* minimalistic .dbg made of a header and a DEBUG_DIRECTORY without any data */
const IMAGE_SEPARATE_DEBUG_HEADER header = {.Signature = 0x4944 /* DI */,
.Flags = 0, .Machine = machine, .Characteristics = 0x010E, .TimeDateStamp = timestamp,
IMAGE_SEPARATE_DEBUG_HEADER header =
{
.Signature = 0x4944 /* DI */,
.Flags = 0, .Machine = machine, .Characteristics = charac, .TimeDateStamp = timestamp,
.CheckSum = 0, .ImageBase = 0x00040000, .SizeOfImage = size, .NumberOfSections = 0,
.ExportedNamesSize = 0, .DebugDirectorySize = sizeof(IMAGE_DEBUG_DIRECTORY)};
const IMAGE_DEBUG_DIRECTORY debug_dir = {.Characteristics = 0, .TimeDateStamp = timestamp + 1,
.MajorVersion = 0, .MinorVersion = 0, .Type = IMAGE_DEBUG_TYPE_CODEVIEW,
.SizeOfData = 0, .AddressOfRawData = 0,
.PointerToRawData = sizeof(header) + header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
header.DebugDirectorySize};
.ExportedNamesSize = 0, .DebugDirectorySize = 0
};
DWORD where, expected_size;
if (blob)
header.DebugDirectorySize = sizeof(IMAGE_DEBUG_DIRECTORY);
hfile = CreateFileW(dbg_name, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, 0);
ok(hfile != INVALID_HANDLE_VALUE, "failed to create %ls err %lu\n", dbg_name, GetLastError());
@ -692,8 +694,18 @@ static BOOL create_test_dbg(const WCHAR* dbg_name, WORD machine, DWORD timestamp
check_write_file(hfile, &header, sizeof(header));
/* FIXME: 0 sections... as header.NumberOfSections */
check_write_file(hfile, &debug_dir, sizeof(debug_dir));
ok(SetFilePointer(hfile, 0, NULL, FILE_CURRENT) == debug_dir.PointerToRawData, "mismatch\n");
if (blob)
{
where = SetFilePointer(hfile, 0, NULL, FILE_CURRENT);
blob->debug_directory.PointerToRawData = (blob->debug_directory.SizeOfData) ?
where + sizeof(IMAGE_DEBUG_DIRECTORY) : 0;
check_write_file(hfile, &blob->debug_directory, sizeof(IMAGE_DEBUG_DIRECTORY));
check_write_file(hfile, blob->content, blob->debug_directory.SizeOfData);
}
expected_size = sizeof(header) + header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
if (blob)
expected_size += sizeof(IMAGE_DEBUG_DIRECTORY) + blob->debug_directory.SizeOfData;
ok(SetFilePointer(hfile, 0, NULL, FILE_CURRENT) == expected_size, "Incorrect file length\n");
CloseHandle(hfile);
return TRUE;
@ -725,16 +737,16 @@ static void test_srvgetindexes_pe(void)
DWORD sig;
WCHAR pdb_name[16];
WCHAR dbg_name[16];
BOOL in_error;
DWORD last_error;
}
indexes[] =
{
/* error cases */
/* 0 */{0, {-1, -1, -1}, .in_error = TRUE},
{IMAGE_FILE_DEBUG_STRIPPED, { 0, -1, -1}, .in_error = TRUE},
{IMAGE_FILE_DEBUG_STRIPPED, { 1, -1, -1}, .in_error = TRUE},
{IMAGE_FILE_DEBUG_STRIPPED, { 2, -1, -1}, .in_error = TRUE},
{IMAGE_FILE_DEBUG_STRIPPED, {-1, -1, -1}, .in_error = TRUE}, /* not 100% logical ! */
/* 0 */{0, {-1, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 0, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 1, -1, -1}, 123, &null_guid, 0xaaaabbbb, .pdb_name = L"pdbjg.pdb", .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, { 2, -1, -1}, 124, &guid1, 0, .pdb_name = L"pdbds.pdb", .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_DEBUG_STRIPPED, {-1, -1, -1}, 0, &null_guid, 0, .last_error = ERROR_BAD_EXE_FORMAT}, /* not 100% logical ! */
/* success */
/* 5 */{0, { 0, -1, -1}, 0, &null_guid, 0 },
{0, { 1, -1, -1}, 123, &null_guid, 0xaaaabbbb, .pdb_name = L"pdbjg.pdb"},
@ -796,16 +808,16 @@ static void test_srvgetindexes_pe(void)
memset(&ssii, 0xa5, sizeof(ssii));
ssii.sizeofstruct = sizeof(ssii);
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
if (indexes[i].in_error)
if (indexes[i].last_error)
{
ok(!ret, "SymSrvGetFileIndexInfo should have failed\n");
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Mismatch in GetLastError: %lu\n", GetLastError());
ok(GetLastError() == indexes[i].last_error, "Mismatch in GetLastError: %lu\n", GetLastError());
}
else
{
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
ok(ssii.age == indexes[i].age, "Mismatch in age: %lx\n", ssii.age);
if (ret || indexes[i].last_error == ERROR_BAD_EXE_FORMAT)
{
ok(ssii.age == indexes[i].age, "Mismatch in age: %lu\n", ssii.age);
ok(IsEqualGUID(&ssii.guid, indexes[i].guid),
"Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid));
@ -882,48 +894,69 @@ static void test_srvgetindexes_dbg(void)
WCHAR filename[128];
SYMSRV_INDEX_INFOW ssii;
BOOL ret;
struct debug_directory_blob *blob_refs[1];
static struct
{
/* input parameters */
WORD machine;
DWORD timestamp;
DWORD imagesize;
WORD machine;
DWORD characteristics;
DWORD timestamp;
DWORD imagesize;
int blob;
/* output parameters */
DWORD age;
const GUID *guid;
WCHAR pdbname[16];
WCHAR dbgname[16];
DWORD last_error;
}
indexes[] =
{
{IMAGE_FILE_MACHINE_I386, 0x1234, 0x00560000},
{IMAGE_FILE_MACHINE_AMD64, 0x1235, 0x00570000},
{IMAGE_FILE_MACHINE_I386, 0, 0x1234, 0x00560000, -1, 0, &null_guid, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_MACHINE_AMD64, 0, 0x1235, 0x00570000, -1, 0, &null_guid, .last_error = ERROR_BAD_EXE_FORMAT},
{IMAGE_FILE_MACHINE_I386, 0, 0x1234, 0x00560000, 0, 123, &guid1, .pdbname=L"foo.pdb"},
{IMAGE_FILE_MACHINE_AMD64, 0, 0x1235, 0x00570000, 0, 123, &guid1, .pdbname=L"foo.pdb"},
};
blob_refs[0] = make_pdb_ds_blob(0x1226, &guid1, 123, "foo.pdb");
for (i = 0; i < ARRAY_SIZE(indexes); i++)
{
winetest_push_context("dbg#%02u", i);
/* create dll */
swprintf(filename, ARRAY_SIZE(filename), L"winetest%02u.dbg", i);
ret = create_test_dbg(filename, indexes[i].machine, indexes[i].timestamp, indexes[i].imagesize);
ret = create_test_dbg(filename, indexes[i].machine, indexes[i].characteristics,
indexes[i].timestamp, indexes[i].imagesize,
indexes[i].blob == -1 ? NULL : blob_refs[indexes[i].blob]);
ok(ret, "Couldn't create dbg file %ls\n", filename);
memset(&ssii, 0x45, sizeof(ssii));
ssii.sizeofstruct = sizeof(ssii);
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
if (indexes[i].last_error)
{
ok(!ret, "SymSrvGetFileIndexInfo should have\n");
ok(GetLastError() == ERROR_BAD_EXE_FORMAT, "Unexpected last error: %lu\n", GetLastError());
}
else
ok(ret, "SymSrvGetFileIndexInfo failed: %lu\n", GetLastError());
ok(ssii.age == 0, "Mismatch in age: %lx\n", ssii.age);
ok(!memcmp(&ssii.guid, &null_guid, sizeof(GUID)),
ok(ssii.age == indexes[i].age, "Mismatch in age: %lx\n", ssii.age);
ok(IsEqualGUID(&ssii.guid, indexes[i].guid),
"Mismatch in guid: guid=%s\n", wine_dbgstr_guid(&ssii.guid));
ok(ssii.sig == 0, "Mismatch in sig: %lx\n", ssii.sig);
ok(ssii.size == indexes[i].imagesize, "Mismatch in size: %lx\n", ssii.size);
ok(!ssii.stripped, "Mismatch in stripped: %x\n", ssii.stripped);
ok(ssii.timestamp == indexes[i].timestamp, "Mismatch in timestamp: %lx\n", ssii.timestamp);
ok(!wcscmp(ssii.file, filename), "Mismatch in file: %ls\n", ssii.file);
ok(!ssii.pdbfile[0], "Mismatch in pdbfile: %ls\n", ssii.pdbfile);
ok(!ssii.dbgfile[0], "Mismatch in dbgfile: %ls\n", ssii.dbgfile);
ok(!wcscmp(ssii.pdbfile, indexes[i].pdbname), "Mismatch in pdbfile: %ls\n", ssii.pdbfile);
ok(!wcscmp(ssii.dbgfile, indexes[i].dbgname), "Mismatch in dbgfile: %ls\n", ssii.dbgfile);
DeleteFileW(filename);
winetest_pop_context();
}
for (i = 0; i < ARRAY_SIZE(blob_refs); i++) free(blob_refs[i]);
}
static void make_path(WCHAR file[MAX_PATH], const WCHAR* topdir, const WCHAR* subdir, const WCHAR* base)
@ -1533,7 +1566,8 @@ static void test_load_modules_path(void)
if (test_files[val].guid)
create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp);
else
create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000);
/*create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64, 0x10E, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000, blob); */
ok(0, "not supported yet\n");
}
else ok(0, "Unrecognized file reference %c\n", *ptr);
}
@ -1754,7 +1788,7 @@ static void test_load_modules_details(void)
if (test_files[val].guid)
create_test_pdb_ds(filename, test_files[val].guid, test_files[val].age_or_timestamp);
else
create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000);
create_test_dbg(filename, IMAGE_FILE_MACHINE_AMD64 /* FIXME */, 0x10E, test_files[val].age_or_timestamp, 0x40000 * val * 0x20000, NULL);
}
else ok(0, "Unrecognized file reference %c\n", *ptr);
}

View file

@ -354,7 +354,7 @@ static int wait_select_reply( void *cookie )
/***********************************************************************
* invoke_user_apc
*/
static NTSTATUS invoke_user_apc( CONTEXT *context, const user_apc_t *apc, NTSTATUS status )
static NTSTATUS invoke_user_apc( CONTEXT *context, const struct user_apc *apc, NTSTATUS status )
{
return call_user_apc_dispatcher( context, apc->args[0], apc->args[1], apc->args[2],
wine_server_get_ptr( apc->func ), status );
@ -364,7 +364,7 @@ static NTSTATUS invoke_user_apc( CONTEXT *context, const user_apc_t *apc, NTSTAT
/***********************************************************************
* invoke_system_apc
*/
static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOOL self )
static void invoke_system_apc( const union apc_call *call, union apc_result *result, BOOL self )
{
SIZE_T size, bits;
void *addr;
@ -688,19 +688,19 @@ static void invoke_system_apc( const apc_call_t *call, apc_result_t *result, BOO
* server_select
*/
unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, user_apc_t *user_apc )
timeout_t abs_timeout, context_t *context, struct user_apc *user_apc )
{
unsigned int ret;
int cookie;
obj_handle_t apc_handle = 0;
BOOL suspend_context = !!context;
apc_result_t result;
union apc_result result;
sigset_t old_set;
int signaled;
data_size_t reply_size;
struct
{
apc_call_t call;
union apc_call call;
context_t context[2];
} reply_data;
@ -768,7 +768,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
{
timeout_t abs_timeout = timeout ? timeout->QuadPart : TIMEOUT_INFINITE;
unsigned int ret;
user_apc_t apc;
struct user_apc apc;
if (abs_timeout < 0)
{
@ -794,7 +794,7 @@ unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT f
*/
NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
{
user_apc_t apc;
struct user_apc apc;
NTSTATUS status;
if (alertable)
@ -811,7 +811,7 @@ NTSTATUS WINAPI NtContinue( CONTEXT *context, BOOLEAN alertable )
*/
NTSTATUS WINAPI NtTestAlert(void)
{
user_apc_t apc;
struct user_apc apc;
NTSTATUS status;
status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_ALERTABLE, 0, NULL, &apc );
@ -823,7 +823,7 @@ NTSTATUS WINAPI NtTestAlert(void)
/***********************************************************************
* server_queue_process_apc
*/
unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call, apc_result_t *result )
unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call, union apc_result *result )
{
for (;;)
{
@ -1759,8 +1759,8 @@ NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source, HANDLE
if ((options & DUPLICATE_CLOSE_SOURCE) && source_process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );

View file

@ -1323,8 +1323,8 @@ NTSTATUS WINAPI NtCreateThreadEx( HANDLE *handle, ACCESS_MASK access, OBJECT_ATT
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -1712,7 +1712,7 @@ NTSTATUS WINAPI NtQueueApcThread( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1
ULONG_PTR arg2, ULONG_PTR arg3 )
{
unsigned int ret;
apc_call_t call;
union apc_call call;
SERVER_START_REQ( queue_apc )
{

View file

@ -209,11 +209,11 @@ extern unsigned int server_call_unlocked( void *req_ptr );
extern void server_enter_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
extern void server_leave_uninterrupted_section( pthread_mutex_t *mutex, sigset_t *sigset );
extern unsigned int server_select( const select_op_t *select_op, data_size_t size, UINT flags,
timeout_t abs_timeout, context_t *context, user_apc_t *user_apc );
timeout_t abs_timeout, context_t *context, struct user_apc *user_apc );
extern unsigned int server_wait( const select_op_t *select_op, data_size_t size, UINT flags,
const LARGE_INTEGER *timeout );
extern unsigned int server_queue_process_apc( HANDLE process, const apc_call_t *call,
apc_result_t *result );
extern unsigned int server_queue_process_apc( HANDLE process, const union apc_call *call,
union apc_result *result );
extern int server_get_unix_fd( HANDLE handle, unsigned int wanted_access, int *unix_fd,
int *needs_close, enum server_fd_type *type, unsigned int *options );
extern void wine_server_send_fd( int fd );
@ -436,10 +436,10 @@ static inline void mutex_unlock( pthread_mutex_t *mutex )
if (!process_exiting) pthread_mutex_unlock( mutex );
}
static inline async_data_t server_async( HANDLE handle, struct async_fileio *user, HANDLE event,
PIO_APC_ROUTINE apc, void *apc_context, client_ptr_t iosb )
static inline struct async_data server_async( HANDLE handle, struct async_fileio *user, HANDLE event,
PIO_APC_ROUTINE apc, void *apc_context, client_ptr_t iosb )
{
async_data_t async;
struct async_data async;
async.handle = wine_server_obj_handle( handle );
async.user = wine_server_client_ptr( user );
async.iosb = iosb;

View file

@ -4671,8 +4671,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG_PTR z
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
unsigned int status;
memset( &call, 0, sizeof(call) );
@ -4817,8 +4817,8 @@ NTSTATUS WINAPI NtAllocateVirtualMemoryEx( HANDLE process, PVOID *ret, SIZE_T *s
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -4864,8 +4864,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -4962,8 +4962,8 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5146,8 +5146,8 @@ static unsigned int get_basic_memory_info( HANDLE process, LPCVOID addr,
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5559,8 +5559,8 @@ NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size,
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5596,8 +5596,8 @@ NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5672,8 +5672,8 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5744,8 +5744,8 @@ NTSTATUS WINAPI NtMapViewOfSectionEx( HANDLE handle, HANDLE process, PVOID *addr
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5788,8 +5788,8 @@ static NTSTATUS unmap_view_of_section( HANDLE process, PVOID addr, ULONG flags )
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -5973,8 +5973,8 @@ NTSTATUS WINAPI NtFlushVirtualMemory( HANDLE process, LPCVOID *addr_ptr,
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );
@ -6359,8 +6359,8 @@ NTSTATUS WINAPI NtWow64AllocateVirtualMemory64( HANDLE process, ULONG64 *ret, UL
if (process != NtCurrentProcess())
{
apc_call_t call;
apc_result_t result;
union apc_call call;
union apc_result result;
memset( &call, 0, sizeof(call) );

View file

@ -2653,6 +2653,7 @@ end:
static char *xdg_config;
static DWORD xdg_config_len;
static BOOL do_symlink = TRUE;
static BOOL WINAPI init_xdg_dirs( INIT_ONCE *once, void *param, void **context )
{
@ -2662,6 +2663,14 @@ static BOOL WINAPI init_xdg_dirs( INIT_ONCE *once, void *param, void **context )
HANDLE file;
DWORD len;
if (_wgetenv( L"WINEISOLATEHOME" ))
{
do_symlink = FALSE;
xdg_config = NULL;
TRACE("WINEISOLATEHOME is set, not creating symlinks to user home\n");
return TRUE;
}
if (!(var = _wgetenv( L"XDG_CONFIG_HOME" )) || var[0] != '/')
{
if (!(var = _wgetenv( L"WINEHOMEDIR" ))) return TRUE;
@ -2791,7 +2800,7 @@ done:
* _SHCreateSymbolicLink [Internal]
*
* Sets up a symbolic link for one of the special shell folders to point into
* the users home directory.
* the users home directory. Will not do so when WINEISOLATEHOME is set.
*
* PARAMS
* nFolder [I] CSIDL identifying the folder.
@ -2800,6 +2809,8 @@ static void _SHCreateSymbolicLink(int nFolder, const WCHAR *path)
{
DWORD folder = nFolder & CSIDL_FOLDER_MASK;
if (!do_symlink) return;
switch (folder) {
case CSIDL_PERSONAL:
create_link( path, "XDG_DOCUMENTS_DIR", "$HOME/Documents" );

View file

@ -761,12 +761,20 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
}
else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
{
HWND last_focus = x11drv_thread_data()->last_focus;
HWND last_focus = x11drv_thread_data()->last_focus, foreground = NtUserGetForegroundWindow();
TRACE( "got take focus msg for %p, enabled=%d, visible=%d (style %08x), focus=%p, active=%p, fg=%p, last=%p\n",
hwnd, NtUserIsWindowEnabled(hwnd), NtUserIsWindowVisible(hwnd),
(int)NtUserGetWindowLongW(hwnd, GWL_STYLE),
get_focus(), get_active_window(), NtUserGetForegroundWindow(), last_focus );
if (window_has_pending_wm_state( hwnd, -1 ))
{
WARN( "Ignoring window %p/%lx WM_TAKE_FOCUS serial %lu, event_time %ld, foreground %p during WM_STATE change\n",
hwnd, event->window, event->serial, event_time, foreground );
return;
}
TRACE( "window %p/%lx WM_TAKE_FOCUS serial %lu, event_time %ld, foreground %p\n", hwnd, event->window,
event->serial, event_time, foreground );
TRACE( " enabled %u, visible %u, style %#x, focus %p, active %p, last %p\n",
NtUserIsWindowEnabled( hwnd ), NtUserIsWindowVisible( hwnd ), (int)NtUserGetWindowLongW( hwnd, GWL_STYLE ),
get_focus(), get_active_window(), last_focus );
if (can_activate_window(hwnd))
{
@ -783,7 +791,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
}
else if (hwnd == NtUserGetDesktopWindow())
{
hwnd = NtUserGetForegroundWindow();
hwnd = foreground;
if (!hwnd) hwnd = last_focus;
if (!hwnd) hwnd = NtUserGetDesktopWindow();
set_focus( event->display, hwnd, event_time );
@ -845,14 +853,23 @@ BOOL is_current_process_focused(void)
*/
static BOOL X11DRV_FocusIn( HWND hwnd, XEvent *xev )
{
HWND foreground = NtUserGetForegroundWindow();
XFocusChangeEvent *event = &xev->xfocus;
BOOL was_grabbed;
if (event->detail == NotifyPointer) return FALSE;
if (!hwnd) return FALSE;
TRACE( "win %p xwin %lx detail=%s mode=%s\n", hwnd, event->window, focus_details[event->detail], focus_modes[event->mode] );
if (window_has_pending_wm_state( hwnd, -1 ))
{
WARN( "Ignoring window %p/%lx FocusIn serial %lu, detail %s, mode %s, foreground %p during WM_STATE change\n",
hwnd, event->window, event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
return FALSE;
}
TRACE( "window %p/%lx FocusIn serial %lu, detail %s, mode %s, foreground %p\n", hwnd, event->window,
event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
if (event->detail == NotifyPointer) return FALSE;
/* when focusing in the virtual desktop window, re-apply the cursor clipping rect */
if (is_virtual_desktop() && hwnd == NtUserGetDesktopWindow()) reapply_cursor_clipping();
if (hwnd == NtUserGetDesktopWindow()) return FALSE;
@ -921,10 +938,9 @@ static void focus_out( Display *display , HWND hwnd )
*/
static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev )
{
HWND foreground = NtUserGetForegroundWindow();
XFocusChangeEvent *event = &xev->xfocus;
TRACE( "win %p xwin %lx detail=%s mode=%s\n", hwnd, event->window, focus_details[event->detail], focus_modes[event->mode] );
if (event->detail == NotifyPointer)
{
if (!hwnd && event->window == x11drv_thread_data()->clip_window)
@ -938,6 +954,16 @@ static BOOL X11DRV_FocusOut( HWND hwnd, XEvent *xev )
}
if (!hwnd) return FALSE;
if (window_has_pending_wm_state( hwnd, NormalState )) /* ignore FocusOut only if the window is being shown */
{
WARN( "Ignoring window %p/%lx FocusOut serial %lu, detail %s, mode %s, foreground %p during WM_STATE change\n",
hwnd, event->window, event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
return FALSE;
}
TRACE( "window %p/%lx FocusOut serial %lu, detail %s, mode %s, foreground %p\n", hwnd, event->window,
event->serial, focus_details[event->detail], focus_modes[event->mode], foreground );
/* in virtual desktop mode or when keyboard is grabbed, release any cursor grab but keep the clipping rect */
keyboard_grabbed = event->mode == NotifyGrab || event->mode == NotifyWhileGrabbed;
if (is_virtual_desktop() || keyboard_grabbed) ungrab_clipping_window();
@ -1078,8 +1104,7 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
struct x11drv_win_data *data;
RECT rect;
POINT pos = {event->x, event->y};
UINT style, flags = 0, config_cmd = 0;
int cx, cy, x, y;
UINT config_cmd;
if (!hwnd) return FALSE;
if (!(data = get_win_data( hwnd ))) return FALSE;
@ -1098,69 +1123,8 @@ static BOOL X11DRV_ConfigureNotify( HWND hwnd, XEvent *xev )
SetRect( &rect, pos.x, pos.y, pos.x + event->width, pos.y + event->height );
window_configure_notify( data, event->serial, &rect );
if (!data->mapped || data->iconic) goto done;
if (!data->whole_window || !data->managed) goto done;
if (data->configure_serial && (long)(data->configure_serial - event->serial) > 0)
{
TRACE( "win %p/%lx event %d,%d,%dx%d ignoring old serial %lu/%lu\n",
hwnd, data->whole_window, event->x, event->y, event->width, event->height,
event->serial, data->configure_serial );
goto done;
}
rect = window_rect_from_visible( &data->rects, rect );
TRACE( "win %p/%lx new X rect %d,%d,%dx%d (event %d,%d,%dx%d)\n",
hwnd, data->whole_window, (int)rect.left, (int)rect.top,
(int)(rect.right-rect.left), (int)(rect.bottom-rect.top),
event->x, event->y, event->width, event->height );
/* Compare what has changed */
x = rect.left;
y = rect.top;
cx = rect.right - rect.left;
cy = rect.bottom - rect.top;
flags = SWP_NOACTIVATE | SWP_NOZORDER;
if (!data->whole_window) flags |= SWP_NOCOPYBITS; /* we can't copy bits of foreign windows */
if (data->rects.window.left == x && data->rects.window.top == y) flags |= SWP_NOMOVE;
else
TRACE( "%p moving from (%d,%d) to (%d,%d)\n",
hwnd, (int)data->rects.window.left, (int)data->rects.window.top, x, y );
if ((data->rects.window.right - data->rects.window.left == cx &&
data->rects.window.bottom - data->rects.window.top == cy) ||
IsRectEmpty( &data->rects.window ))
flags |= SWP_NOSIZE;
else
TRACE( "%p resizing from (%dx%d) to (%dx%d)\n",
hwnd, (int)(data->rects.window.right - data->rects.window.left),
(int)(data->rects.window.bottom - data->rects.window.top), cx, cy );
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if ((style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen)
{
data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window );
if ((data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && !(style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is maximized\n", data->hwnd, data->whole_window );
config_cmd = SC_MAXIMIZE;
}
else if (!(data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && (style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window );
config_cmd = SC_RESTORE;
}
}
if (!config_cmd && (flags & (SWP_NOSIZE | SWP_NOMOVE)) != (SWP_NOSIZE | SWP_NOMOVE))
{
TRACE( "window %p/%lx config changed %s -> %s, flags %#x\n", data->hwnd, data->whole_window,
wine_dbgstr_rect(&data->rects.window), wine_dbgstr_rect(&rect), flags );
config_cmd = MAKELONG(SC_MOVE, flags);
}
done:
config_cmd = window_update_client_config( data );
rect = window_rect_from_visible( &data->rects, data->current_state.rect );
release_win_data( data );
if (config_cmd)
@ -1232,7 +1196,7 @@ static int get_window_xembed_info( Display *display, Window window )
static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL update_window )
{
struct x11drv_win_data *data;
UINT style, value = 0, state_cmd = 0;
UINT value = 0, state_cmd = 0;
if (!(data = get_win_data( hwnd ))) return;
if (event->state == PropertyNewValue) value = get_window_wm_state( event->display, event->window );
@ -1253,50 +1217,13 @@ static void handle_wm_state_notify( HWND hwnd, XPropertyEvent *event, BOOL updat
TRACE( "%p/%lx: new WM_STATE %d from %d\n",
data->hwnd, data->whole_window, new_state, old_state );
data->wm_state = new_state;
/* ignore the initial state transition out of withdrawn state */
/* metacity does Withdrawn->NormalState->IconicState when mapping an iconic window */
if (!old_state) goto done;
}
}
break;
}
if (!update_window || !data->managed || !data->mapped) goto done;
if (update_window) state_cmd = window_update_client_state( data );
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if (data->iconic && data->wm_state == NormalState) /* restore window */
{
data->iconic = FALSE;
data->net_wm_state = get_window_net_wm_state( event->display, data->whole_window );
if ((style & WS_CAPTION) == WS_CAPTION && (data->net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if ((style & WS_MAXIMIZEBOX) && !(style & WS_DISABLED))
{
TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window );
state_cmd = SC_MAXIMIZE;
}
}
else
{
if (style & (WS_MINIMIZE | WS_MAXIMIZE))
{
BOOL activate = (style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE);
TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window );
state_cmd = MAKELONG(SC_RESTORE, activate);
}
}
}
else if (!data->iconic && data->wm_state == IconicState)
{
data->iconic = TRUE;
if ((style & WS_MINIMIZEBOX) && !(style & WS_DISABLED))
{
TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window );
state_cmd = SC_MINIMIZE;
}
}
done:
release_win_data( data );
if (state_cmd)

View file

@ -46,7 +46,7 @@
#include "winuser.h"
#include "winreg.h"
#include "winnls.h"
#include "ime.h"
#include "kbd.h"
#include "wine/server.h"
#include "wine/debug.h"

View file

@ -1160,7 +1160,7 @@ static void update_net_wm_fullscreen_monitors( struct x11drv_win_data *data )
long monitors[4];
XEvent xev;
if (!(data->net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop()
if (!(data->pending_state.net_wm_state & (1 << NET_WM_STATE_FULLSCREEN)) || is_virtual_desktop()
|| NtUserGetWindowLongW( data->hwnd, GWL_STYLE ) & WS_MINIMIZE)
return;
@ -1328,7 +1328,7 @@ static void update_net_wm_states( struct x11drv_win_data *data )
style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if (style & WS_MINIMIZE)
new_state |= data->net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED));
new_state |= data->pending_state.net_wm_state & ((1 << NET_WM_STATE_FULLSCREEN)|(1 << NET_WM_STATE_MAXIMIZED));
if (data->is_fullscreen)
{
if ((style & WS_MAXIMIZE) && (style & WS_CAPTION) == WS_CAPTION)
@ -1352,7 +1352,6 @@ static void update_net_wm_states( struct x11drv_win_data *data )
}
window_set_net_wm_state( data, new_state );
data->net_wm_state = new_state;
update_net_wm_fullscreen_monitors( data );
}
@ -1418,8 +1417,8 @@ static void window_set_wm_state( struct x11drv_win_data *data, UINT new_state )
data->pending_state.wm_state = new_state;
data->wm_state_serial = NextRequest( data->display );
TRACE( "window %p/%lx, requesting WM_STATE %#x -> %#x serial %lu\n", data->hwnd, data->whole_window,
old_state, new_state, data->wm_state_serial );
TRACE( "window %p/%lx, requesting WM_STATE %#x -> %#x serial %lu, foreground %p\n", data->hwnd, data->whole_window,
old_state, new_state, data->wm_state_serial, NtUserGetForegroundWindow() );
switch (MAKELONG(old_state, new_state))
{
@ -1490,11 +1489,87 @@ static void unmap_window( HWND hwnd )
TRACE( "win %p/%lx\n", data->hwnd, data->whole_window );
window_set_wm_state( data, WithdrawnState );
data->mapped = FALSE;
data->net_wm_state = 0;
}
release_win_data( data );
}
UINT window_update_client_state( struct x11drv_win_data *data )
{
UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE );
if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */
if (!data->mapped) return 0; /* ignore state changes on invisible windows */
if (data->iconic && data->current_state.wm_state == NormalState) /* restore window */
{
data->iconic = FALSE;
if ((old_style & WS_CAPTION) == WS_CAPTION && (data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)))
{
if ((old_style & WS_MAXIMIZEBOX) && !(old_style & WS_DISABLED))
{
TRACE( "restoring to max %p/%lx\n", data->hwnd, data->whole_window );
return SC_MAXIMIZE;
}
}
else if (old_style & (WS_MINIMIZE | WS_MAXIMIZE))
{
BOOL activate = (old_style & (WS_MINIMIZE | WS_VISIBLE)) == (WS_MINIMIZE | WS_VISIBLE);
TRACE( "restoring win %p/%lx\n", data->hwnd, data->whole_window );
return MAKELONG(SC_RESTORE, activate);
}
}
else if (!data->iconic && data->current_state.wm_state == IconicState)
{
data->iconic = TRUE;
if ((old_style & WS_MINIMIZEBOX) && !(old_style & WS_DISABLED))
{
TRACE( "minimizing win %p/%lx\n", data->hwnd, data->whole_window );
return SC_MINIMIZE;
}
}
return 0;
}
UINT window_update_client_config( struct x11drv_win_data *data )
{
UINT old_style = NtUserGetWindowLongW( data->hwnd, GWL_STYLE ), flags;
RECT rect, old_rect = data->rects.window, new_rect;
if (!data->managed) return 0; /* unmanaged windows are managed by the Win32 side */
if (!data->mapped) return 0; /* ignore config changes on invisible windows */
if (data->iconic) return 0; /* ignore config changes on minimized windows */
if (data->configure_serial) return 0; /* another config update is pending, wait for it to complete */
if ((old_style & WS_CAPTION) == WS_CAPTION || !data->is_fullscreen)
{
if ((data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && !(old_style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is maximized\n", data->hwnd, data->whole_window );
return SC_MAXIMIZE;
}
if (!(data->current_state.net_wm_state & (1 << NET_WM_STATE_MAXIMIZED)) && (old_style & WS_MAXIMIZE))
{
TRACE( "window %p/%lx is no longer maximized\n", data->hwnd, data->whole_window );
return SC_RESTORE;
}
}
flags = SWP_NOACTIVATE | SWP_NOZORDER;
rect = new_rect = window_rect_from_visible( &data->rects, data->current_state.rect );
if (new_rect.left == old_rect.left && new_rect.top == old_rect.top) flags |= SWP_NOMOVE;
else OffsetRect( &rect, old_rect.left - new_rect.left, old_rect.top - new_rect.top );
if (rect.right == old_rect.right && rect.bottom == old_rect.bottom) flags |= SWP_NOSIZE;
else if (IsRectEmpty( &rect )) flags |= SWP_NOSIZE;
if ((flags & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE)) return 0;
TRACE( "window %p/%lx config changed %s -> %s, flags %#x\n", data->hwnd, data->whole_window,
wine_dbgstr_rect(&old_rect), wine_dbgstr_rect(&new_rect), flags );
return MAKELONG(SC_MOVE, flags);
}
void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value )
{
UINT *pending = &data->pending_state.wm_state, *current = &data->current_state.wm_state;
@ -1593,6 +1668,19 @@ void window_configure_notify( struct x11drv_win_data *data, unsigned long serial
*expect_serial = 0;
}
BOOL window_has_pending_wm_state( HWND hwnd, UINT state )
{
struct x11drv_win_data *data;
BOOL pending;
if (!(data = get_win_data( hwnd ))) return FALSE;
if (state != -1 && data->pending_state.wm_state != state) pending = FALSE;
else pending = !!data->wm_state_serial;
release_win_data( data );
return pending;
}
/***********************************************************************
* make_window_embedded
*/
@ -1600,7 +1688,6 @@ void make_window_embedded( struct x11drv_win_data *data )
{
/* the window cannot be mapped before being embedded */
window_set_wm_state( data, WithdrawnState );
data->net_wm_state = 0;
data->embedded = TRUE;
data->managed = TRUE;
sync_window_style( data );
@ -2012,7 +2099,6 @@ static void destroy_whole_window( struct x11drv_win_data *data, BOOL already_des
data->whole_window = data->client_window = 0;
data->whole_colormap = 0;
data->wm_state = WithdrawnState;
data->net_wm_state = 0;
data->mapped = FALSE;
memset( &data->pending_state, 0, sizeof(data->pending_state) );

View file

@ -634,7 +634,6 @@ struct x11drv_win_data
UINT is_fullscreen : 1; /* is the window visible rect fullscreen */
UINT parent_invalid : 1; /* is the parent host window possibly invalid */
int wm_state; /* current value of the WM_STATE property */
DWORD net_wm_state; /* bit mask of active x11drv_net_wm_state values */
Window embedder; /* window id of embedder */
Pixmap icon_pixmap;
Pixmap icon_mask;
@ -659,9 +658,13 @@ extern void set_gl_drawable_parent( HWND hwnd, HWND parent );
extern void destroy_gl_drawable( HWND hwnd );
extern void destroy_vk_surface( HWND hwnd );
extern BOOL window_has_pending_wm_state( HWND hwnd, UINT state );
extern void window_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value );
extern void window_net_wm_state_notify( struct x11drv_win_data *data, unsigned long serial, UINT value );
extern void window_configure_notify( struct x11drv_win_data *data, unsigned long serial, const RECT *rect );
extern UINT window_update_client_state( struct x11drv_win_data *data );
extern UINT window_update_client_config( struct x11drv_win_data *data );
extern void wait_for_withdrawn_state( HWND hwnd, BOOL set );
extern Window init_clip_window(void);
extern void update_user_time( Time time );

View file

@ -3886,26 +3886,23 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
}
else if (dwInfoLevel & HTTP_QUERY_FLAG_SYSTEMTIME && lpBuffer)
{
time_t tmpTime;
struct tm tmpTM;
SYSTEMTIME *STHook;
SYSTEMTIME st;
tmpTime = ConvertTimeString(lphttpHdr->lpszValue);
tmpTM = *gmtime(&tmpTime);
STHook = (SYSTEMTIME *)lpBuffer;
STHook->wDay = tmpTM.tm_mday;
STHook->wHour = tmpTM.tm_hour;
STHook->wMilliseconds = 0;
STHook->wMinute = tmpTM.tm_min;
STHook->wDayOfWeek = tmpTM.tm_wday;
STHook->wMonth = tmpTM.tm_mon + 1;
STHook->wSecond = tmpTM.tm_sec;
STHook->wYear = 1900+tmpTM.tm_year;
TRACE(" returning time: %04d/%02d/%02d - %d - %02d:%02d:%02d.%02d\n",
STHook->wYear, STHook->wMonth, STHook->wDay, STHook->wDayOfWeek,
STHook->wHour, STHook->wMinute, STHook->wSecond, STHook->wMilliseconds);
if (!InternetTimeToSystemTimeW(lphttpHdr->lpszValue, &st, 0))
{
LeaveCriticalSection( &request->headers_section );
return ERROR_HTTP_INVALID_HEADER;
}
if (*lpdwBufferLength < sizeof(st))
{
*lpdwBufferLength = sizeof(st);
LeaveCriticalSection( &request->headers_section );
return ERROR_INSUFFICIENT_BUFFER;
}
TRACE(" returning time: %04u/%02u/%02u - %u - %02u:%02u:%02u.%02u\n",
st.wYear, st.wMonth, st.wDay, st.wDayOfWeek, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
memcpy(lpBuffer, &st, sizeof(st));
*lpdwBufferLength = sizeof(st);
}
else if (lphttpHdr->lpszValue)
{
@ -4521,7 +4518,7 @@ static BOOL HTTP_ParseDateAsAsctime(LPCWSTR value, FILETIME *ft)
/* asctime() doesn't report a timezone, but some web servers do, so accept
* with or without GMT.
*/
if (*ptr && wcscmp(ptr, L"GMT"))
if (*ptr && (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC")))
{
ERR("unexpected timezone %s\n", debugstr_w(ptr));
return FALSE;
@ -4598,7 +4595,7 @@ static BOOL HTTP_ParseRfc1123Date(LPCWSTR value, FILETIME *ft)
while (iswspace(*ptr))
ptr++;
if (wcscmp(ptr, L"GMT"))
if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
{
ERR("unexpected time zone %s\n", debugstr_w(ptr));
return FALSE;
@ -4715,7 +4712,7 @@ static BOOL HTTP_ParseRfc850Date(LPCWSTR value, FILETIME *ft)
while (iswspace(*ptr))
ptr++;
if (wcscmp(ptr, L"GMT"))
if (wcscmp(ptr, L"GMT") && wcscmp(ptr, L"UTC"))
{
ERR("unexpected time zone %s\n", debugstr_w(ptr));
return FALSE;

View file

@ -2412,6 +2412,7 @@ static const char okmsg2[] =
"Content-Length: 0\r\n"
"Set-Cookie: one\r\n"
"Set-Cookie: two\r\n"
"Last-Modified: Mon, 01 Dec 2008 13:44:34 UTC\r\n"
"\r\n";
static DWORD64 content_length;
@ -4566,9 +4567,11 @@ static void test_head_request(int port)
static void test_HttpQueryInfo(int port)
{
static const SYSTEMTIME expect = {2008, 12, 1, 1, 13, 44, 34};
test_request_t req;
DWORD size, index, error;
char buffer[1024];
SYSTEMTIME st;
BOOL ret;
open_simple_request(&req, "localhost", port, NULL, "/testD");
@ -4589,9 +4592,27 @@ static void test_HttpQueryInfo(int port)
ok(index == 1, "expected 1 got %lu\n", index);
index = 0;
size = sizeof(buffer);
ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, buffer, &size, &index);
size = 0;
ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %lu\n", GetLastError());
ok(size == sizeof(st), "got %lu\n", size);
index = 0;
size = sizeof(st) + 1;
memset(&st, 0, sizeof(st));
ret = HttpQueryInfoA(req.request, HTTP_QUERY_DATE | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(ret, "HttpQueryInfo failed %lu\n", GetLastError());
ok(!memcmp(&st, &expect, sizeof(st)), "wrong time\n");
ok(size == sizeof(st), "got %lu\n", size);
ok(index == 1, "expected 1 got %lu\n", index);
index = 0;
size = sizeof(st);
memset(&st, 0, sizeof(st));
ret = HttpQueryInfoA(req.request, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &st, &size, &index);
ok(ret, "HttpQueryInfo failed %lu\n", GetLastError());
ok(!memcmp(&st, &expect, sizeof(st)), "wrong time\n");
ok(size == sizeof(st), "got %lu\n", size);
ok(index == 1, "expected 1 got %lu\n", index);
index = 0;

View file

@ -1116,9 +1116,11 @@ static void test_InternetTimeToSystemTime(void)
test_data[] =
{
{ "Fri, 07 Jan 2005 12:06:35 GMT", &expect1, TRUE },
{ "Fri, 07 Jan 2005 12:06:35 UTC", &expect1, TRUE },
{ " fri, 7 jan 2005 12 06 35", &expect1, TRUE },
{ "Fri, 07-01-2005 12:06:35", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 UTC", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT;", &expect1, TRUE },
{ "5, 07-01-2005 12:06:35 GMT123", &expect1, TRUE },
{ "2, 11 01 2022 11 13 05", &expect2, TRUE },
@ -1126,6 +1128,9 @@ static void test_InternetTimeToSystemTime(void)
{ "2, 11*01/2022 11+13=05", &expect2, TRUE },
{ "2, 11-Jan-2022 11:13:05", &expect2, TRUE },
{ "Fr", NULL, FALSE },
{ "Fri Jan 7 12:06:35 2005", &expect1, TRUE, TRUE },
{ "Fri Jan 7 12:06:35 2005 GMT", &expect1, TRUE, TRUE },
{ "Fri Jan 7 12:06:35 2005 UTC", &expect1, TRUE, TRUE },
};
ret = pInternetTimeToSystemTimeA(NULL, NULL, 0);

View file

@ -39,92 +39,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(wininet);
#define TIME_STRING_LEN 30
time_t ConvertTimeString(LPCWSTR asctime)
{
WCHAR tmpChar[TIME_STRING_LEN];
WCHAR *tmpChar2;
struct tm t;
int timelen = lstrlenW(asctime);
if(!timelen)
return 0;
/* FIXME: the atoiWs below rely on that tmpChar is \0 padded */
memset( tmpChar, 0, sizeof(tmpChar) );
lstrcpynW(tmpChar, asctime, TIME_STRING_LEN);
/* Assert that the string is the expected length */
if (lstrlenW(asctime) >= TIME_STRING_LEN) FIXME("\n");
/* Convert a time such as 'Mon, 15 Nov 1999 16:09:35 GMT' into a SYSTEMTIME structure
* We assume the time is in this format
* and divide it into easy to swallow chunks
*/
tmpChar[3]='\0';
tmpChar[7]='\0';
tmpChar[11]='\0';
tmpChar[16]='\0';
tmpChar[19]='\0';
tmpChar[22]='\0';
tmpChar[25]='\0';
memset( &t, 0, sizeof(t) );
t.tm_year = wcstol(tmpChar+12, NULL, 10) - 1900;
t.tm_mday = wcstol(tmpChar+5, NULL, 10);
t.tm_hour = wcstol(tmpChar+17, NULL, 10);
t.tm_min = wcstol(tmpChar+20, NULL, 10);
t.tm_sec = wcstol(tmpChar+23, NULL, 10);
/* and month */
tmpChar2 = tmpChar + 8;
switch(tmpChar2[2])
{
case 'n':
if(tmpChar2[1]=='a')
t.tm_mon = 0;
else
t.tm_mon = 5;
break;
case 'b':
t.tm_mon = 1;
break;
case 'r':
if(tmpChar2[1]=='a')
t.tm_mon = 2;
else
t.tm_mon = 3;
break;
case 'y':
t.tm_mon = 4;
break;
case 'l':
t.tm_mon = 6;
break;
case 'g':
t.tm_mon = 7;
break;
case 'p':
t.tm_mon = 8;
break;
case 't':
t.tm_mon = 9;
break;
case 'v':
t.tm_mon = 10;
break;
case 'c':
t.tm_mon = 11;
break;
default:
FIXME("\n");
}
return mktime(&t);
}
BOOL GetAddress(const WCHAR *name, INTERNET_PORT port, struct sockaddr *psa, int *sa_len, char *addr_str)
{
ADDRINFOW *res, hints;

View file

@ -343,4 +343,19 @@ typedef struct tagKbdLayer
#error "Unsupported KBD_TYPE"
#endif
#define VK_DBE_ALPHANUMERIC 0x0f0
#define VK_DBE_KATAKANA 0x0f1
#define VK_DBE_HIRAGANA 0x0f2
#define VK_DBE_SBCSCHAR 0x0f3
#define VK_DBE_DBCSCHAR 0x0f4
#define VK_DBE_ROMAN 0x0f5
#define VK_DBE_NOROMAN 0x0f6
#define VK_DBE_ENTERWORDREGISTERMODE 0x0f7
#define VK_DBE_ENTERIMECONFIGMODE 0x0f8
#define VK_DBE_FLUSHSTRING 0x0f9
#define VK_DBE_CODEINPUT 0x0fa
#define VK_DBE_NOCODEINPUT 0x0fb
#define VK_DBE_DETERMINESTRING 0x0fc
#define VK_DBE_ENTERDLGCONVERSIONMODE 0x0fd
#endif /* __WINE_KBD_H */

View file

@ -430,6 +430,36 @@ library UIAutomationClient {
const long UIA_AppBarControlTypeId = 50040;
}
[dllname("<no entry points>")]
module UIA_AnnotationTypes
{
const long AnnotationType_Unknown = 60000;
const long AnnotationType_SpellingError = 60001;
const long AnnotationType_GrammarError = 60002;
const long AnnotationType_Comment = 60003;
const long AnnotationType_FormulaError = 60004;
const long AnnotationType_TrackChanges = 60005;
const long AnnotationType_Header = 60006;
const long AnnotationType_Footer = 60007;
const long AnnotationType_Highlighted = 60008;
const long AnnotationType_Endnote = 60009;
const long AnnotationType_Footnote = 60010;
const long AnnotationType_InsertionChange = 60011;
const long AnnotationType_DeletionChange = 60012;
const long AnnotationType_MoveChange = 60013;
const long AnnotationType_FormatChange = 60014;
const long AnnotationType_UnsyncedChange = 60015;
const long AnnotationType_EditingLockedChange = 60016;
const long AnnotationType_ExternalChange = 60017;
const long AnnotationType_ConflictingChange = 60018;
const long AnnotationType_Author = 60019;
const long AnnotationType_AdvancedProofingIssue = 60020;
const long AnnotationType_DataValidationError = 60021;
const long AnnotationType_CircularReferenceError = 60022;
const long AnnotationType_Mathematics = 60023;
const long AnnotationType_Sensitive = 60024;
}
[dllname("<no entry points>")]
module UIA_LandmarkTypeIds
{

View file

@ -260,7 +260,7 @@ typedef struct
} rectangle_t;
typedef struct
struct async_data
{
obj_handle_t handle;
obj_handle_t event;
@ -268,7 +268,7 @@ typedef struct
client_ptr_t user;
client_ptr_t apc;
apc_param_t apc_context;
} async_data_t;
};
@ -488,18 +488,18 @@ enum apc_type
APC_DUP_HANDLE
};
typedef struct
struct user_apc
{
enum apc_type type;
int __pad;
client_ptr_t func;
apc_param_t args[3];
} user_apc_t;
};
typedef union
union apc_call
{
enum apc_type type;
user_apc_t user;
struct user_apc user;
struct
{
enum apc_type type;
@ -620,9 +620,9 @@ typedef union
unsigned int attributes;
unsigned int options;
} dup_handle;
} apc_call_t;
};
typedef union
union apc_result
{
enum apc_type type;
struct
@ -732,7 +732,7 @@ typedef union
enum apc_type type;
unsigned int status;
} break_process;
} apc_result_t;
};
enum irp_type
{
@ -1343,7 +1343,7 @@ struct get_apc_result_request
struct get_apc_result_reply
{
struct reply_header __header;
apc_result_t result;
union apc_result result;
};
@ -1829,7 +1829,7 @@ struct flush_request
{
struct request_header __header;
char __pad_12[4];
async_data_t async;
struct async_data async;
};
struct flush_reply
{
@ -1857,7 +1857,7 @@ struct get_volume_info_request
{
struct request_header __header;
obj_handle_t handle;
async_data_t async;
struct async_data async;
unsigned int info_class;
char __pad_60[4];
};
@ -1906,7 +1906,7 @@ struct recv_socket_request
{
struct request_header __header;
int oob;
async_data_t async;
struct async_data async;
int force_async;
char __pad_60[4];
};
@ -1925,7 +1925,7 @@ struct send_socket_request
{
struct request_header __header;
unsigned int flags;
async_data_t async;
struct async_data async;
};
struct send_socket_reply
{
@ -2016,7 +2016,7 @@ struct read_directory_changes_request
unsigned int filter;
int subtree;
int want_data;
async_data_t async;
struct async_data async;
};
struct read_directory_changes_reply
{
@ -3152,7 +3152,7 @@ struct register_async_request
{
struct request_header __header;
int type;
async_data_t async;
struct async_data async;
int count;
char __pad_60[4];
};
@ -3216,7 +3216,7 @@ struct read_request
{
struct request_header __header;
char __pad_12[4];
async_data_t async;
struct async_data async;
file_pos_t pos;
};
struct read_reply
@ -3233,7 +3233,7 @@ struct write_request
{
struct request_header __header;
char __pad_12[4];
async_data_t async;
struct async_data async;
file_pos_t pos;
/* VARARG(data,bytes); */
};
@ -3252,7 +3252,7 @@ struct ioctl_request
{
struct request_header __header;
ioctl_code_t code;
async_data_t async;
struct async_data async;
/* VARARG(in_data,bytes); */
};
struct ioctl_reply
@ -6758,10 +6758,6 @@ union generic_reply
struct set_keyboard_repeat_reply set_keyboard_repeat_reply;
};
/* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 848
/* ### protocol_version end ### */
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View file

@ -45,7 +45,7 @@ struct async
struct timeout_user *timeout;
unsigned int timeout_status; /* status to report upon timeout */
struct event *event;
async_data_t data; /* data for async I/O call */
struct async_data data; /* data for async I/O call */
struct iosb *iosb; /* I/O status block */
obj_handle_t wait_handle; /* pre-allocated wait handle */
unsigned int initial_status; /* status returned from initial request */
@ -180,7 +180,7 @@ void async_terminate( struct async *async, unsigned int status )
if (!async->direct_result)
{
apc_call_t data;
union apc_call data;
memset( &data, 0, sizeof(data) );
data.type = APC_ASYNC_IO;
@ -248,7 +248,7 @@ void queue_async( struct async_queue *queue, struct async *async )
}
/* create an async on a given queue of a fd */
struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb )
struct async *create_async( struct fd *fd, struct thread *thread, const struct async_data *data, struct iosb *iosb )
{
struct event *event = NULL;
struct async *async;
@ -515,7 +515,7 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
{
if (async->data.apc)
{
apc_call_t data;
union apc_call data;
memset( &data, 0, sizeof(data) );
data.type = APC_USER;
data.user.func = async->data.apc;
@ -753,7 +753,7 @@ static struct iosb *create_iosb( const void *in_data, data_size_t in_size, data_
/* create an async associated with iosb for async-based requests
* returned async must be passed to async_handoff */
struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data, int is_system )
struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const struct async_data *data, int is_system )
{
struct async *async;
struct iosb *iosb;

View file

@ -252,8 +252,8 @@ extern struct object *create_serial( struct fd *fd );
typedef void (*async_completion_callback)( void *private );
extern void free_async_queue( struct async_queue *queue );
extern struct async *create_async( struct fd *fd, struct thread *thread, const async_data_t *data, struct iosb *iosb );
extern struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const async_data_t *data,
extern struct async *create_async( struct fd *fd, struct thread *thread, const struct async_data *data, struct iosb *iosb );
extern struct async *create_request_async( struct fd *fd, unsigned int comp_flags, const struct async_data *data,
int is_system );
extern obj_handle_t async_handoff( struct async *async, data_size_t *result, int force_blocking );
extern void queue_async( struct async_queue *queue, struct async *async );

View file

@ -262,6 +262,9 @@ void init_memory(void)
page_mask = sysconf( _SC_PAGESIZE ) - 1;
free_map_addr( 0x60000000, 0x1c000000 );
free_map_addr( 0x600000000000, 0x100000000000 );
if (page_mask != 0xfff)
fprintf( stderr, "wineserver: page size is %uk but Wine requires 4k pages, expect problems\n",
(int)(page_mask + 1) / 1024 );
}
static void ranges_dump( struct object *obj, int verbose )

View file

@ -276,7 +276,7 @@ typedef struct
} rectangle_t;
/* structure for parameters of async I/O calls */
typedef struct
struct async_data
{
obj_handle_t handle; /* object to perform I/O on */
obj_handle_t event; /* event to signal when done */
@ -284,7 +284,7 @@ typedef struct
client_ptr_t user; /* opaque user data containing callback pointer and async-specific data */
client_ptr_t apc; /* user APC to call */
apc_param_t apc_context; /* user APC context or completion value */
} async_data_t;
};
/* structures for extra message data */
@ -504,18 +504,18 @@ enum apc_type
APC_DUP_HANDLE
};
typedef struct
struct user_apc
{
enum apc_type type; /* APC_USER */
int __pad;
client_ptr_t func; /* void (__stdcall *func)(ULONG_PTR,ULONG_PTR,ULONG_PTR); */
apc_param_t args[3]; /* arguments for user function */
} user_apc_t;
};
typedef union
union apc_call
{
enum apc_type type;
user_apc_t user;
struct user_apc user;
struct
{
enum apc_type type; /* APC_ASYNC_IO */
@ -636,9 +636,9 @@ typedef union
unsigned int attributes; /* object attributes */
unsigned int options; /* duplicate options */
} dup_handle;
} apc_call_t;
};
typedef union
union apc_result
{
enum apc_type type;
struct
@ -748,7 +748,7 @@ typedef union
enum apc_type type; /* APC_BREAK_PROCESS */
unsigned int status; /* status returned by call */
} break_process;
} apc_result_t;
};
enum irp_type
{
@ -1232,7 +1232,7 @@ typedef struct
@REQ(get_apc_result)
obj_handle_t handle; /* handle to the APC */
@REPLY
apc_result_t result; /* result of the APC */
union apc_result result; /* result of the APC */
@END
@ -1539,7 +1539,7 @@ enum server_fd_type
/* Flush a file buffers */
@REQ(flush)
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
@REPLY
obj_handle_t event; /* event set when finished */
@END
@ -1555,7 +1555,7 @@ enum server_fd_type
/* Query volume information */
@REQ(get_volume_info)
obj_handle_t handle; /* handle to the file */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
unsigned int info_class; /* queried information class */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking read */
@ -1586,7 +1586,7 @@ enum server_fd_type
/* Perform a recv on a socket */
@REQ(recv_socket)
int oob; /* are we receiving OOB data? */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
int force_async; /* Force asynchronous mode? */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking recv */
@ -1598,7 +1598,7 @@ enum server_fd_type
/* Perform a send on a socket */
@REQ(send_socket)
unsigned int flags; /* SERVER_SOCKET_IO_* flags */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking send */
unsigned int options; /* device open options */
@ -1656,7 +1656,7 @@ enum server_fd_type
unsigned int filter; /* notification filter */
int subtree; /* watch the subtree? */
int want_data; /* flag indicating whether change data should be collected */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
@END
@ -2355,7 +2355,7 @@ enum message_type
/* Create an async I/O */
@REQ(register_async)
int type; /* type of queue to look after */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
int count; /* count - usually # of bytes to be read/written */
@END
#define ASYNC_TYPE_READ 0x01
@ -2392,7 +2392,7 @@ enum message_type
/* Perform a read on a file object */
@REQ(read)
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
file_pos_t pos; /* read position */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking read */
@ -2403,7 +2403,7 @@ enum message_type
/* Perform a write on a file object */
@REQ(write)
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
file_pos_t pos; /* write position */
VARARG(data,bytes); /* write data */
@REPLY
@ -2416,7 +2416,7 @@ enum message_type
/* Perform an ioctl on a file */
@REQ(ioctl)
ioctl_code_t code; /* ioctl code */
async_data_t async; /* async I/O parameters */
struct async_data async; /* async I/O parameters */
VARARG(in_data,bytes); /* ioctl input data */
@REPLY
obj_handle_t wait; /* handle to wait on for blocking ioctl */

View file

@ -60,8 +60,7 @@
#include "thread.h"
#include "security.h"
#include "handle.h"
#define WANT_REQUEST_HANDLERS
#include "request.h"
#include "request_handlers.h"
/* Some versions of glibc don't define this */
#ifndef SCM_RIGHTS

File diff suppressed because it is too large Load diff

2264
server/request_handlers.h generated Normal file

File diff suppressed because it is too large Load diff

4399
server/request_trace.h generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -79,8 +79,8 @@ struct thread_apc
struct thread *caller; /* thread that queued this apc */
struct object *owner; /* object that queued this apc */
int executed; /* has it been executed by the client? */
apc_call_t call; /* call arguments */
apc_result_t result; /* call results once executed */
union apc_call call; /* call arguments */
union apc_result result; /* call results once executed */
};
static void dump_thread_apc( struct object *obj, int verbose );
@ -508,7 +508,7 @@ static void thread_apc_destroy( struct object *obj )
}
/* queue an async procedure call */
static struct thread_apc *create_apc( struct object *owner, const apc_call_t *call_data )
static struct thread_apc *create_apc( struct object *owner, const union apc_call *call_data )
{
struct thread_apc *apc;
@ -1155,7 +1155,7 @@ static int queue_apc( struct process *process, struct thread *thread, struct thr
}
/* queue an async procedure call */
int thread_queue_apc( struct process *process, struct thread *thread, struct object *owner, const apc_call_t *call_data )
int thread_queue_apc( struct process *process, struct thread *thread, struct object *owner, const union apc_call *call_data )
{
struct thread_apc *apc;
int ret = 0;
@ -1584,7 +1584,7 @@ DECL_HANDLER(select)
data_size_t op_size, ctx_size;
struct context *ctx;
struct thread_apc *apc;
const apc_result_t *result = get_req_data();
const union apc_result *result = get_req_data();
unsigned int ctx_count;
if (get_req_data_size() < sizeof(*result)) goto invalid_param;
@ -1665,13 +1665,13 @@ DECL_HANDLER(select)
reply->signaled = select_on( &select_op, op_size, req->cookie, req->flags, req->timeout );
if (get_error() == STATUS_USER_APC && get_reply_max_size() >= sizeof(apc_call_t))
if (get_error() == STATUS_USER_APC && get_reply_max_size() >= sizeof(union apc_call))
{
apc = thread_dequeue_apc( current, 0 );
set_reply_data( &apc->call, sizeof(apc->call) );
release_object( apc );
}
else if (get_error() == STATUS_KERNEL_APC && get_reply_max_size() >= sizeof(apc_call_t))
else if (get_error() == STATUS_KERNEL_APC && get_reply_max_size() >= sizeof(union apc_call))
{
apc = thread_dequeue_apc( current, 1 );
if ((reply->apc_handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 )))
@ -1685,13 +1685,13 @@ DECL_HANDLER(select)
}
release_object( apc );
}
else if (reply->signaled && get_reply_max_size() >= sizeof(apc_call_t) + sizeof(context_t) &&
else if (reply->signaled && get_reply_max_size() >= sizeof(union apc_call) + sizeof(context_t) &&
current->context && current->suspend_cookie == req->cookie)
{
ctx = current->context;
if (ctx->regs[CTX_NATIVE].flags || ctx->regs[CTX_WOW].flags)
{
apc_call_t *data;
union apc_call *data;
data_size_t size = sizeof(*data) + (ctx->regs[CTX_WOW].flags ? 2 : 1) * sizeof(context_t);
unsigned int flags = system_flags & ctx->regs[CTX_NATIVE].flags;
@ -1718,7 +1718,7 @@ DECL_HANDLER(queue_apc)
struct thread *thread = NULL;
struct process *process = NULL;
struct thread_apc *apc;
const apc_call_t *call = get_req_data();
const union apc_call *call = get_req_data();
if (get_req_data_size() < sizeof(*call)) call = NULL;

View file

@ -117,7 +117,7 @@ extern int add_queue( struct object *obj, struct wait_queue_entry *entry );
extern void remove_queue( struct object *obj, struct wait_queue_entry *entry );
extern void kill_thread( struct thread *thread, int violent_death );
extern void wake_up( struct object *obj, int max );
extern int thread_queue_apc( struct process *process, struct thread *thread, struct object *owner, const apc_call_t *call_data );
extern int thread_queue_apc( struct process *process, struct thread *thread, struct object *owner, const union apc_call *call_data );
extern void thread_cancel_apc( struct thread *thread, struct object *owner, enum apc_type type );
extern int thread_add_inflight_fd( struct thread *thread, int client, int server );
extern int thread_get_inflight_fd( struct thread *thread, int client );

View file

@ -123,7 +123,7 @@ static void timer_callback( void *private )
/* queue an APC */
if (timer->thread)
{
apc_call_t data;
union apc_call data;
assert (timer->callback);
memset( &data, 0, sizeof(data) );

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
#! /usr/bin/perl -w
#
# Build the server/trace.c and server/request.h files
# Build the server protocol definitions
# from the contents of server/protocol.def.
#
# Copyright (C) 1998 Alexandre Julliard
@ -32,30 +32,18 @@ my %formats =
"data_size_t" => [ 4, 4, "%u" ],
"obj_handle_t" => [ 4, 4, "%04x" ],
"atom_t" => [ 4, 4, "%04x" ],
"user_handle_t" => [ 4, 4, "%08x" ],
"process_id_t" => [ 4, 4, "%04x" ],
"thread_id_t" => [ 4, 4, "%04x" ],
"client_ptr_t" => [ 8, 8, "&dump_uint64" ],
"mod_handle_t" => [ 8, 8, "&dump_uint64" ],
"lparam_t" => [ 8, 8, "&dump_uint64" ],
"apc_param_t" => [ 8, 8, "&dump_uint64" ],
"file_pos_t" => [ 8, 8, "&dump_uint64" ],
"mem_size_t" => [ 8, 8, "&dump_uint64" ],
"affinity_t" => [ 8, 8, "&dump_uint64" ],
"object_id_t" => [ 8, 8, "&dump_uint64" ],
"timeout_t" => [ 8, 8, "&dump_timeout" ],
"abstime_t" => [ 8, 8, "&dump_abstime" ],
"rectangle_t" => [ 16, 4, "&dump_rectangle" ],
"apc_result_t" => [ 40, 8, "&dump_apc_result" ],
"async_data_t" => [ 40, 8, "&dump_async_data" ],
"irp_params_t" => [ 32, 8, "&dump_irp_params" ],
"struct luid" => [ 8, 4, "&dump_luid" ],
"generic_map_t" => [ 16, 4, "&dump_generic_map" ],
"ioctl_code_t" => [ 4, 4, "&dump_ioctl_code" ],
"hw_input_t" => [ 40, 8, "&dump_hw_input" ],
"obj_locator_t" => [ 16, 8, "&dump_obj_locator" ],
"unsigned __int64" => [ 8, 8, "&uint64" ],
"timeout_t" => [ 8, 8 ],
"abstime_t" => [ 8, 8 ],
"rectangle_t" => [ 16, 4 ],
"irp_params_t" => [ 32, 8 ],
"generic_map_t" => [ 16, 4 ],
"ioctl_code_t" => [ 4, 4 ],
"hw_input_t" => [ 40, 8 ],
"obj_locator_t" => [ 16, 8 ],
# varargs-only structures
"apc_call_t" => [ 64, 8 ],
"context_t" => [ 1728, 8 ],
"cursor_pos_t" => [ 24, 8 ],
"debug_event_t" => [ 160, 8 ],
@ -66,21 +54,33 @@ my %formats =
"startup_info_t" => [ 96, 4 ],
"tcp_connection" => [ 60, 4 ],
"udp_endpoint" => [ 32, 4 ],
"user_apc_t" => [ 40, 8 ],
"union apc_call" => [ 64, 8 ],
"union apc_result" => [ 40, 8 ],
"struct async_data" => [ 40, 8 ],
"struct filesystem_event" => [ 12, 4 ],
"struct handle_info" => [ 20, 4 ],
"struct luid" => [ 8, 4 ],
"struct luid_attr" => [ 12, 4 ],
"struct object_attributes" => [ 16, 4 ],
"struct object_type_info" => [ 44, 4 ],
"struct process_info" => [ 40, 8 ],
"struct rawinput_device" => [ 12, 4 ],
"struct thread_info" => [ 40, 8 ],
"struct user_apc" => [ 40, 8 ],
);
my $file_header =
"/*\n * Wine server protocol definitions\n *\n" .
" * This file is automatically generated; DO NO EDIT!\n" .
" * Edit server/protocol.def instead and re-run tools/make_requests\n" .
" */\n\n";
my @requests = ();
my %replies = ();
my %dump_funcs = ();
my @asserts = ();
my @protocol_lines = ();
my @trace_lines = ();
my $max_req_size = 64;
@ -93,7 +93,7 @@ sub add_padding($$)
if ($offset % $padding)
{
my $count = $padding - ($offset % $padding);
print SERVER_PROT " char __pad_$offset\[$count\];\n";
push @protocol_lines, " char __pad_$offset\[$count\];\n";
$offset += $count;
}
return $offset;
@ -115,10 +115,24 @@ sub DO_DUMP_FUNC($$@)
if (defined($formats{$type}))
{
my $fmt = ${$formats{$type}}[2];
if ($fmt =~ /^&(.*)/)
while ($fmt && $fmt !~ /^[%&]/)
{
$type = $fmt;
$fmt = ${$formats{$type}}[2];
}
if (!$fmt)
{
my $func = $type;
$func =~ s/^(struct|union)\s+//;
$func =~ s/_t$//;
push @trace_lines, " dump_$func( \"$prefix$var=\", &req->$var );\n";
$dump_funcs{$func} = $type;
}
elsif ($fmt =~ /^&(.*)/)
{
my $func = $1;
push @trace_lines, " $func( \"$prefix$var=\", &req->$var );\n";
push @trace_lines, " dump_$func( \"$prefix$var=\", &req->$var );\n";
$dump_funcs{$func} = $type;
}
elsif ($fmt =~ /^(%.*)\s+\((.*)\)/)
{
@ -178,8 +192,8 @@ sub PARSE_REQUESTS()
@in_struct = ();
@out_struct = ();
$offset = 12;
print SERVER_PROT "struct ${name}_request\n{\n";
print SERVER_PROT " struct request_header __header;\n";
push @protocol_lines, "struct ${name}_request\n{\n";
push @protocol_lines, " struct request_header __header;\n";
$state++;
next;
}
@ -190,9 +204,9 @@ sub PARSE_REQUESTS()
$offset = add_padding( $offset, 8 ); # all requests should be 8-byte aligned
die "request $name too large ($offset)" if ($offset > $max_req_size);
push @asserts, "C_ASSERT( sizeof(struct ${name}_request) == $offset );\n";
print SERVER_PROT "};\n";
print SERVER_PROT "struct ${name}_reply\n{\n";
print SERVER_PROT " struct reply_header __header;\n";
push @protocol_lines, "};\n";
push @protocol_lines, "struct ${name}_reply\n{\n";
push @protocol_lines, " struct reply_header __header;\n";
$offset = 8;
$state++;
next;
@ -203,14 +217,14 @@ sub PARSE_REQUESTS()
die "Misplaced \@END" unless ($state == 2 || $state == 3);
$offset = add_padding( $offset, 8 ); # all requests should be 8-byte aligned
print SERVER_PROT "};\n";
push @protocol_lines, "};\n";
if ($state == 2) # build dummy reply struct
{
die "request $name too large ($offset)" if ($offset > $max_req_size);
push @asserts, "C_ASSERT( sizeof(struct ${name}_request) == $offset );\n";
print SERVER_PROT "struct ${name}_reply\n{\n";
print SERVER_PROT " struct reply_header __header;\n";
print SERVER_PROT "};\n";
push @protocol_lines, "struct ${name}_reply\n{\n";
push @protocol_lines, " struct reply_header __header;\n";
push @protocol_lines, "};\n";
}
else
{
@ -234,26 +248,22 @@ sub PARSE_REQUESTS()
# skip empty lines (but keep them in output file)
if (/^$/)
{
print SERVER_PROT "\n";
push @protocol_lines, "\n";
next;
}
if (/^\s*VARARG\((\w+),(\w+),(\d+)\)/)
if (/^\s*VARARG\((\w+),(\w+),(\w+)\)/)
{
$var = $1;
$type = "dump_varargs_$2( \"%s\", min(cur_size,$3) )";
s!(VARARG\(.*\)\s*;)!/* $1 */!;
}
elsif (/^\s*VARARG\((\w+),(\w+),(\w+)\)/)
{
$var = $1;
$type = "dump_varargs_" . $2 . "( \"%s\", min(cur_size,req->" . $3 . ") )";
$type = "dump_varargs_$2( \"%s\", min( cur_size, req->" . $3 . " ))";
$dump_funcs{"varargs_$2"} = $2;
s!(VARARG\(.*\)\s*;)!/* $1 */!;
}
elsif (/^\s*VARARG\((\w+),(\w+)\)/)
{
$var = $1;
$type = "dump_varargs_" . $2 . "( \"%s\", cur_size )";
$type = "dump_varargs_$2( \"%s\", cur_size )";
$dump_funcs{"varargs_$2"} = $2;
s!(VARARG\(.*\)\s*;)!/* $1 */!;
}
elsif (/^\s*(\w+\**(\s+\w+\**)*)\s+(\w+);/)
@ -266,16 +276,16 @@ sub PARSE_REQUESTS()
{
my $count = $fmt[1] - ($offset & ($fmt[1] - 1));
print "protocol.def:$.: warning: $name $offset $type $var needs padding\n" if $warnings;
print SERVER_PROT " char __pad_$offset\[$count\];\n";
push @protocol_lines, " char __pad_$offset\[$count\];\n";
$offset += $count;
}
if ($state == 2)
{
push @asserts, "C_ASSERT( FIELD_OFFSET(struct ${name}_request, $var) == $offset );\n";
push @asserts, "C_ASSERT( offsetof(struct ${name}_request, $var) == $offset );\n";
}
else
{
push @asserts, "C_ASSERT( FIELD_OFFSET(struct ${name}_reply, $var) == $offset );\n";
push @asserts, "C_ASSERT( offsetof(struct ${name}_reply, $var) == $offset );\n";
}
$offset += $fmt[0];
}
@ -286,9 +296,18 @@ sub PARSE_REQUESTS()
if ($state == 2) { push @in_struct, $type, $var; }
if ($state == 3) { push @out_struct, $type, $var; }
}
elsif (/^typedef\s+(.*)\s+(\w+_t);$/)
{
if (defined $formats{$1} && !defined $formats{$2})
{
@{$formats{$2}} = @{$formats{$1}};
$formats{$2}->[2] = $1;
}
}
# Pass it through into the output file
print SERVER_PROT $_ . "\n";
push @protocol_lines, $_ . "\n";
}
close PROTOCOL;
}
@ -337,9 +356,15 @@ sub GET_ERROR_NAMES()
}
# update a file if changed
sub update_file($)
sub update_file($@)
{
my $file = shift;
my ($file, @lines) = @_;
open OUTPUT, ">$file.new" or die "Cannot create $file.new";
print OUTPUT $file_header;
print OUTPUT @lines;
close OUTPUT;
my $ret = !(-f $file) || system "cmp $file $file.new >/dev/null";
if (!$ret)
{
@ -353,42 +378,6 @@ sub update_file($)
return $ret;
}
# replace some lines in a file between two markers
sub replace_in_file($$$@)
{
my $file = shift;
my $start = shift;
my $end = shift;
open NEW_FILE, ">$file.new" or die "cannot create $file.new";
if (defined($start))
{
open OLD_FILE, "$file" or die "cannot open $file";
while (<OLD_FILE>)
{
print NEW_FILE $_;
last if /$start/;
}
}
print NEW_FILE "\n", @_, "\n";
if (defined($end))
{
my $skip=1;
while (<OLD_FILE>)
{
$skip = 0 if /$end/;
print NEW_FILE $_ unless $skip;
}
}
close OLD_FILE if defined($start);
close NEW_FILE;
return update_file($file);
}
### Main
# Get the server protocol version
@ -398,13 +387,8 @@ my %errors = GET_ERROR_NAMES();
### Create server_protocol.h and print header
open SERVER_PROT, ">include/wine/server_protocol.h.new" or die "Cannot create include/wine/server_protocol.h.new";
print SERVER_PROT "/*\n * Wine server protocol definitions\n *\n";
print SERVER_PROT " * This file is automatically generated; DO NO EDIT!\n";
print SERVER_PROT " * Edit server/protocol.def instead and re-run tools/make_requests\n";
print SERVER_PROT " */\n\n";
print SERVER_PROT "#ifndef __WINE_WINE_SERVER_PROTOCOL_H\n";
print SERVER_PROT "#define __WINE_WINE_SERVER_PROTOCOL_H\n";
push @protocol_lines, "#ifndef __WINE_WINE_SERVER_PROTOCOL_H\n";
push @protocol_lines, "#define __WINE_WINE_SERVER_PROTOCOL_H\n";
### Parse requests to find request/reply structure definitions
@ -412,57 +396,53 @@ PARSE_REQUESTS();
### Build the request list and structures
print SERVER_PROT "\n\nenum request\n{\n";
foreach my $req (@requests) { print SERVER_PROT " REQ_$req,\n"; }
print SERVER_PROT " REQ_NB_REQUESTS\n};\n\n";
push @protocol_lines, "\n\nenum request\n{\n";
foreach my $req (@requests) { push @protocol_lines, " REQ_$req,\n"; }
push @protocol_lines, " REQ_NB_REQUESTS\n};\n\n";
print SERVER_PROT "union generic_request\n{\n";
print SERVER_PROT " struct request_max_size max_size;\n";
print SERVER_PROT " struct request_header request_header;\n";
foreach my $req (@requests) { print SERVER_PROT " struct ${req}_request ${req}_request;\n"; }
print SERVER_PROT "};\n";
push @protocol_lines, "union generic_request\n{\n";
push @protocol_lines, " struct request_max_size max_size;\n";
push @protocol_lines, " struct request_header request_header;\n";
foreach my $req (@requests) { push @protocol_lines, " struct ${req}_request ${req}_request;\n"; }
push @protocol_lines, "};\n";
print SERVER_PROT "union generic_reply\n{\n";
print SERVER_PROT " struct request_max_size max_size;\n";
print SERVER_PROT " struct reply_header reply_header;\n";
foreach my $req (@requests) { print SERVER_PROT " struct ${req}_reply ${req}_reply;\n"; }
print SERVER_PROT "};\n\n";
push @protocol_lines, "union generic_reply\n{\n";
push @protocol_lines, " struct request_max_size max_size;\n";
push @protocol_lines, " struct reply_header reply_header;\n";
foreach my $req (@requests) { push @protocol_lines, " struct ${req}_reply ${req}_reply;\n"; }
push @protocol_lines, "};\n\n";
print SERVER_PROT "/* ### protocol_version begin ### */\n\n";
printf SERVER_PROT "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol;
print SERVER_PROT "/* ### protocol_version end ### */\n\n";
print SERVER_PROT "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n";
push @protocol_lines, sprintf "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol;
push @protocol_lines, "#endif /* __WINE_WINE_SERVER_PROTOCOL_H */\n";
open SERVER_PROT, ">include/wine/server_protocol.h.new" or die "Cannot create include/wine/server_protocol.h.new";
print SERVER_PROT @protocol_lines;
close SERVER_PROT;
if (update_file( "include/wine/server_protocol.h" ))
if (update_file( "include/wine/server_protocol.h", @protocol_lines ))
{
my @version_lines = ();
push @version_lines, sprintf( "#define SERVER_PROTOCOL_VERSION %d\n", $protocol + 1 );
replace_in_file( "include/wine/server_protocol.h",
"### protocol_version begin ###",
"### protocol_version end ###",
@version_lines );
$protocol_lines[$#protocol_lines - 1] = sprintf "#define SERVER_PROTOCOL_VERSION %d\n\n", $protocol + 1;
update_file( "include/wine/server_protocol.h", @protocol_lines );
}
### Output the dumping function tables
push @trace_lines, "static const dump_func req_dumpers[REQ_NB_REQUESTS] = {\n";
push @trace_lines, "typedef void (*dump_func)( const void *req );\n\n";
push @trace_lines, "static const dump_func req_dumpers[REQ_NB_REQUESTS] =\n{\n";
foreach my $req (@requests)
{
push @trace_lines, " (dump_func)dump_${req}_request,\n";
}
push @trace_lines, "};\n\n";
push @trace_lines, "static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {\n";
push @trace_lines, "static const dump_func reply_dumpers[REQ_NB_REQUESTS] =\n{\n";
foreach my $req (@requests)
{
push @trace_lines, " ", $replies{$req} ? "(dump_func)dump_${req}_reply,\n" : "NULL,\n";
}
push @trace_lines, "};\n\n";
push @trace_lines, "static const char * const req_names[REQ_NB_REQUESTS] = {\n";
push @trace_lines, "static const char * const req_names[REQ_NB_REQUESTS] =\n{\n";
foreach my $req (@requests)
{
push @trace_lines, " \"$req\",\n";
@ -481,18 +461,32 @@ foreach my $err (sort keys %errors)
push @trace_lines, " { NULL, 0 }\n";
push @trace_lines, "};\n";
replace_in_file( "server/trace.c",
"### make_requests begin ###",
"### make_requests end ###",
@trace_lines );
my @trace_header = ();
foreach my $func (sort keys %dump_funcs)
{
if ($func =~ /^varargs_/)
{
push @trace_header, "static void dump_$func( const char *prefix, data_size_t size );\n";
}
else
{
push @trace_header, "static void dump_$func( const char *prefix, const $dump_funcs{$func} *val );\n";
}
}
push @trace_header, "\nstatic const void *cur_data;\n";
push @trace_header, "static data_size_t cur_size;\n\n";
update_file( "server/request_trace.h", @trace_header, @trace_lines);
### Output the request handlers list
my @request_lines = ();
my @request_lines = ( "#include \"request.h\"\n\n" );
foreach my $req (@requests) { push @request_lines, "DECL_HANDLER($req);\n"; }
push @request_lines, "\n#ifdef WANT_REQUEST_HANDLERS\n\n";
push @request_lines, "typedef void (*req_handler)( const void *req, void *reply );\n";
push @request_lines, "\ntypedef void (*req_handler)( const void *req, void *reply );\n";
push @request_lines, "static const req_handler req_handlers[REQ_NB_REQUESTS] =\n{\n";
foreach my $req (@requests)
{
@ -506,10 +500,5 @@ foreach my $type (sort keys %formats)
die "$type: invalid size $size for alignment $align" if $size % $align;
push @request_lines, "C_ASSERT( sizeof($type) == $size );\n";
}
push @request_lines, @asserts;
push @request_lines, "\n#endif /* WANT_REQUEST_HANDLERS */\n";
replace_in_file( "server/request.h",
"### make_requests begin ###",
"### make_requests end ###",
@request_lines );
update_file( "server/request_handlers.h", @request_lines, @asserts );