> But then you assume that all objects implementing the interface will use the same struct layout for that. I can't think of an example inside MSHTML where it's currently not the case, but that's not generally a promise that QI gives.
In theory, there's a similar concern when looking up the function via IID and DISPID, specifically, that it might find a different function. In practice as you said it probably doesn't happen but…
> So what's the point of it then? Avoiding one argument in a call?
Continuing the above, IMO the following would make it the most robust: we look it up as mentioned from the func_info_t's dispid and IID, and then compare to see if it's the same `func_info_t` pointer. If not, return E_UNEXPECTED since it's the wrong function. And yes, one less argument to keep track of, but also one less thing to keep track of (in the ProxyFunction for instance, and everywhere else).
> I think that you misinterprets your observations. Here is a test proving that currentStyle should have a setter that throws an error (unless used for modifiable style object):
Okay, thanks for the test, I guess there's more at play here indeed.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/5444#note_72591
> Yeah, I forgot to validate it in my branch. In BuiltinFuncCall, something like this would work:
But then you assume that all objects implementing the interface will use the same struct layout for that. I can't think of an example inside MSHTML where it's currently not the case, but that's not generally a promise that QI gives.
> Alternatively, we can pass around `func_info_t` instead of dispid and tid, but still look it up like in your branch.
So what's the point of it then? Avoiding one argument in a call?
> I mean the test will simply start failing if it picks `IHTMLCSSStyleDeclaration` because the assignment does not throw exception anymore (when it should be!).
I think that you misinterprets your observations. Here is a test proving that currentStyle should have a setter that throws an error (unless used for modifiable style object):
```
sync_test("currentStyle", function() {
if (document.documentMode < 9)
return;
var s = document.body.currentStyle;
var d = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Object.getPrototypeOf(s)), "zoom");
ok(typeof(d.get) === "function", "d.get = " + d.get);
ok(typeof(d.set) === "function", "d.set = " + d.set);
d.set.call(document.body.style, "1");
try {
d.set.call(s, "1");
ok(false, "exception expected");
}catch(e) { trace("MSG: " + e.message); }
});
```
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/5444#note_72588
This MR adds support for creating file mapping objects backed by large pages on Linux, by making the following changes:
## wineserver
* On Linux, `create_temp_file` will first attempt to use memfds as the backing fd. If it fails, it'll return to the current codepath, creating a temporary file in either the server or config directory.
* The created memfd will be sealed against writes, if the caller requesting the appropriate page protection flags.
* This removes the requirement that FDs be only created on filesystems/directories that aren't `noexec`.
* In the server method `create_mapping` , if large pages have been requested by the caller, hold that the calling thread's token holds `SeLockMemoryPrivilege` .
* Additionally, add `SeLockMemoryPrivilege` to the list of privileges enabled for the Administrator.
## `ntdll`
* Add `virtual_get_min_large_page_size` and its exported wrapper `wine_unix_get_min_large_page_size`.
* On Linux, the minimum page size is determined by going through `/sys/kernel/mm/hugepages`. If hugepage support was not detected, `STATUS_NOT_SUPPORTED` is returned instead. On other platforms, the older hard-coded value of 2\*1024\*1024 is returned instead.
* `NtCreateSection` will validate certain parameters if large pages are requested. Specifically, it will return STATUS_INVALID_PARAMETER if the requested mapping is not anonymous/unnamed, or the size is not a multiple of the minimum supported page size.
## `kernelbase`
* `GetLargePageMinimum` will use `wine_unix_get_min_large_page_size`.
## `kernel32/tests`
* Add new test test_large_page_file_mapping, which validates privilege enforcements and parameter validation while creating large pages backed file mapping obejcts. The tests are skipped if `GetLargePageMinimum` returns 0.
--
v13: kernel32: Add tests for large page mapping support.
ntdll: Validate parameters to NtCreateSection if large pages are requested.
server: Use memfd to back anonymous mappings on Linux.
kernelbase: Implement GetLargePageMinimum by returning the value of LargePageMinimum in _KUSER_SHARED_DATA.
server: Set LargePageMinimum in _KUSER_SHARED_DATA on Linux.
server: Require SeLockMemoryPrivilege to create large page mappings.
https://gitlab.winehq.org/wine/wine/-/merge_requests/5769
On Wed Jun 5 21:57:54 2024 +0000, Jacek Caban wrote:
> > But it was still ambiguous as I explained.
> If you mean the "zoom" example, I'd appreciate for some details. That
> one should already use `IHTMLCSSStyleDeclaration` interface, not
> `IHTMLStyle*` ones.
> > But since we pass the mshtml-internal tid (called iid in args) which
> is opaque to jscript, I don't really see why this is better than passing
> the `func_info_t` directly? Well IMO passing the pair is already more
> complex and requires more lookups, more args, etc, but that's just me.
> `get_dispex_from_this` is one thing, going through the interface take
> cares of that. For that part, you could just replace the argument in my branch.
> But we should also somehow make sure that the hook is safe to call. By
> binding function info to the exact object instance, we guarantee that
> it's safe to call `impl_from_*` from hooks. If you accept any function
> info as an input, you need to somehow validate that it's safe to call
> it. Something like moving QI earlier would only partially mitigate that.
> I'm open to other approaches, but unless I'm missing something, there is
> no such validation in your current branch.
> It seems to me that things like 1ffeaa446613 come from some variation of
> solution to that problem. Maybe it was needed in earlier version, but it
> shouldn't be needed with "this" being resolved on jscript side. It's no
> longer arbitrary when it's used for a `IJSDispatchHost` call. I would
> suggest to try removing it.
Yeah, I forgot to validate it in my branch. In BuiltinFuncCall,
something like this would work:
```c
if(func->hook) {
hres =
IWineJSDispatchHost_QueryInterface(&This->IWineJSDispatchHost_iface,
tid_ids[func->tid], (void**)&unk);
if(FAILED(hres))
return hres;
IUnknown_Release(unk);
hres = func->hook(This, setter ? DISPATCH_PROPERTYPUT :
DISPATCH_PROPERTYGET, dp, ret, ei, caller);
if(hres != S_FALSE)
return hres;
}
```
Alternatively, we can pass around `func_info_t` instead of dispid and
tid, but still look it up like in your branch. We can obtain the dispid
and tid from `func_info_t` so that's all that's needed. I'm not sure if
that's an improvement over my approach, but I think it's definitely a
simplification over yours. What do you think?
BTW for `zoom`, the assignment should fail as it does on native (as the
test does), are you sure it's supposed to be using
`IHTMLCSSStyleDeclaration` which doesn't fail? I mean the test will
simply start failing if it picks `IHTMLCSSStyleDeclaration` because the
assignment does not throw exception anymore (when it should be!).
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/5444#note_72586
This MR adds support for creating file mapping objects backed by large pages on Linux, by making the following changes:
## wineserver
* On Linux, `create_temp_file` will first attempt to use memfds as the backing fd. If it fails, it'll return to the current codepath, creating a temporary file in either the server or config directory.
* The created memfd will be sealed against writes, if the caller requesting the appropriate page protection flags.
* This removes the requirement that FDs be only created on filesystems/directories that aren't `noexec`.
* In the server method `create_mapping` , if large pages have been requested by the caller, hold that the calling thread's token holds `SeLockMemoryPrivilege` .
* Additionally, add `SeLockMemoryPrivilege` to the list of privileges enabled for the Administrator.
## `ntdll`
* Add `virtual_get_min_large_page_size` and its exported wrapper `wine_unix_get_min_large_page_size`.
* On Linux, the minimum page size is determined by going through `/sys/kernel/mm/hugepages`. If hugepage support was not detected, `STATUS_NOT_SUPPORTED` is returned instead. On other platforms, the older hard-coded value of 2\*1024\*1024 is returned instead.
* `NtCreateSection` will validate certain parameters if large pages are requested. Specifically, it will return STATUS_INVALID_PARAMETER if the requested mapping is not anonymous/unnamed, or the size is not a multiple of the minimum supported page size.
## `kernelbase`
* `GetLargePageMinimum` will use `wine_unix_get_min_large_page_size`.
## `kernel32/tests`
* Add new test test_large_page_file_mapping, which validates privilege enforcements and parameter validation while creating large pages backed file mapping obejcts. The tests are skipped if `GetLargePageMinimum` returns 0.
--
v12: kernel32: Add tests for large page mapping support.
ntdll: Validate parameters to NtCreateSection if large pages are requested.
server: Use memfd to back anonymous mappings on Linux.
kernelbase: Implement GetLargePageMinimum by returning the value of LargePageMinimum in _KUSER_SHARED_DATA.
server: Set LargePageMinimum in _KUSER_SHARED_DATA on Linux.
server: Require SeLockMemoryPrivilege to create large page mappings.
https://gitlab.winehq.org/wine/wine/-/merge_requests/5769
I have a .Net application that during handling of WM_NCPAINT for one of its windows
genarates exception "Arithmetic operation resulted in an overflow.". This happens
only in a 64-bit prefix and only for WPARAM that contains an HRGN handle with value
over than 0x7fffffff.
The application does the following:
public static IntPtr GetNativeDC(Message m, IntPtr handle)
{
if (m.Msg != 0x85) // WM_NCPAINT
{
return NUser32.GetWindowDC(handle);
}
int num = 0x200013; // DCX_VALIDATE | DCX_CLIPSIBLINGS | DCX_CACHE | DCX_WINDOW
IntPtr intPtr = IntPtr.Zero;
IntPtr wParam = m.WParam;
if (wParam.ToInt32() != 1)
{
num |= 0x80; // DCX_INTERSECTRGN
intPtr = CreateRectRgn(0, 0, 1, 1);
CombineRgn(intPtr, wParam, IntPtr.Zero, 5); // RGN_COPY
}
return NUser32.GetDCEx(handle, intPtr, num);
}
The exception is generated by wParam.ToInt32(). MSDN description for ToInt32()
https://learn.microsoft.com/en-us/dotnet/api/system.intptr.toint32?view=net…
states
Exceptions
OverflowException
In a 64-bit process, the value of this instance is too large or too small
to represent as a 32-bit signed integer.
MSDN also has a reference to ToInt32() source:
https://github.com/dotnet/runtime/blob/5535e31a712343a63f5d7d796cd874e563e5…
public int ToInt32()
{
#if TARGET_64BIT
return checked((int)_value);
#else
return (int)_value;
#endif
}
It's not clear why a sign extension may lead to an overflow exception.
This patch fixes the problem, and provides a test case that confirms that
entry.Generation field of a GDI32 object is limited by 127 on a 64-bit
platform, while 32-bit Windows doesn't have such a limitation.
--
v2: win32u: Limit GDI object generation by 128.
https://gitlab.winehq.org/wine/wine/-/merge_requests/5777