From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/jscript/arraybuf.c | 34 ++++++++++++++ dlls/jscript/dispex.c | 8 ++++ dlls/jscript/jscript.h | 1 + dlls/jscript/jsdisp.idl | 1 + dlls/mshtml/omnavigator.c | 19 +++++++- dlls/mshtml/tests/documentmode.js | 77 +++++++++++++++++++++++++++++++ 6 files changed, 138 insertions(+), 2 deletions(-)
diff --git a/dlls/jscript/arraybuf.c b/dlls/jscript/arraybuf.c index a01ac7d3321..7135034c482 100644 --- a/dlls/jscript/arraybuf.c +++ b/dlls/jscript/arraybuf.c @@ -19,6 +19,14 @@
#include <limits.h> #include <math.h> +#include <stdarg.h> +#include <stdlib.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "ntsecapi.h"
#include "jscript.h"
@@ -1388,3 +1396,29 @@ HRESULT init_arraybuf_constructors(script_ctx_t *ctx)
return hres; } + +HRESULT typed_array_get_random_values(jsdisp_t *obj) +{ + TypedArrayInstance *typedarr; + DWORD size; + + if(!obj || obj->builtin_info->class < FIRST_TYPEDARRAY_JSCLASS || obj->builtin_info->class > LAST_TYPEDARRAY_JSCLASS) + return E_INVALIDARG; + + if(obj->builtin_info->class == JSCLASS_FLOAT32ARRAY || obj->builtin_info->class == JSCLASS_FLOAT64ARRAY) { + /* FIXME: Return TypeMismatchError */ + return E_FAIL; + } + + typedarr = typedarr_from_jsdisp(obj); + size = typedarr->length * typed_array_descs[obj->builtin_info->class - FIRST_TYPEDARRAY_JSCLASS].size; + if(size > 65536) { + /* FIXME: Return QuotaExceededError */ + return E_FAIL; + } + + if(!RtlGenRandom(&typedarr->buffer->buf[typedarr->offset], size)) + return HRESULT_FROM_WIN32(GetLastError()); + + return S_OK; +} diff --git a/dlls/jscript/dispex.c b/dlls/jscript/dispex.c index 897df1a0773..64e00277b21 100644 --- a/dlls/jscript/dispex.c +++ b/dlls/jscript/dispex.c @@ -2430,6 +2430,13 @@ static HRESULT WINAPI WineJSDispatch_GetScriptGlobal(IWineJSDispatch *iface, IWi return S_OK; }
+static HRESULT WINAPI WineJSDispatch_GetRandomValues(IWineJSDispatch *iface) +{ + jsdisp_t *This = impl_from_IWineJSDispatch(iface); + + return typed_array_get_random_values(This); +} + static IWineJSDispatchVtbl DispatchExVtbl = { DispatchEx_QueryInterface, DispatchEx_AddRef, @@ -2451,6 +2458,7 @@ static IWineJSDispatchVtbl DispatchExVtbl = { WineJSDispatch_DefineProperty, WineJSDispatch_UpdateProperty, WineJSDispatch_GetScriptGlobal, + WineJSDispatch_GetRandomValues, };
jsdisp_t *as_jsdisp(IDispatch *disp) diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index 42d52898892..af36dd8568c 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -494,6 +494,7 @@ HRESULT regexp_string_match(script_ctx_t*,jsdisp_t*,jsstr_t*,jsval_t*);
BOOL bool_obj_value(jsdisp_t*); unsigned array_get_length(jsdisp_t*); +HRESULT typed_array_get_random_values(jsdisp_t*); HRESULT localize_number(script_ctx_t*,DOUBLE,BOOL,jsstr_t**);
BOOL is_builtin_eval_func(jsdisp_t*); diff --git a/dlls/jscript/jsdisp.idl b/dlls/jscript/jsdisp.idl index a9941b98070..5252e68a63d 100644 --- a/dlls/jscript/jsdisp.idl +++ b/dlls/jscript/jsdisp.idl @@ -56,6 +56,7 @@ interface IWineJSDispatch : IDispatchEx HRESULT DefineProperty(const WCHAR *name, unsigned int flags, VARIANT *v); HRESULT UpdateProperty(struct property_info *desc); HRESULT GetScriptGlobal(IWineJSDispatchHost **ret); + HRESULT GetRandomValues(); }
[ diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c index c6a107bbb20..fea947a3759 100644 --- a/dlls/mshtml/omnavigator.c +++ b/dlls/mshtml/omnavigator.c @@ -2925,10 +2925,25 @@ static HRESULT WINAPI crypto_get_subtle(IWineMSHTMLCrypto *iface, IDispatch **su static HRESULT WINAPI crypto_getRandomValues(IWineMSHTMLCrypto *iface, VARIANT *typedArray, IDispatch **ret) { struct crypto *crypto = impl_from_IWineMSHTMLCrypto(iface); + IWineJSDispatch *jsdisp; + HRESULT hres;
- FIXME("(%p)->(%p %p)\n", crypto, typedArray, ret); + TRACE("(%p)->(%p %p)\n", crypto, typedArray, ret);
- return E_NOTIMPL; + if(V_VT(typedArray) != VT_DISPATCH || !V_DISPATCH(typedArray)) + return E_INVALIDARG; + + hres = IDispatch_QueryInterface(V_DISPATCH(typedArray), &IID_IWineJSDispatch, (void**)&jsdisp); + if(FAILED(hres)) + return E_INVALIDARG; + + hres = IWineJSDispatch_GetRandomValues(jsdisp); + IWineJSDispatch_Release(jsdisp); + if(SUCCEEDED(hres) && ret) { + *ret = V_DISPATCH(typedArray); + IDispatch_AddRef(*ret); + } + return hres; }
static const IWineMSHTMLCryptoVtbl WineMSHTMLCryptoVtbl = { diff --git a/dlls/mshtml/tests/documentmode.js b/dlls/mshtml/tests/documentmode.js index 3a856a62a7d..76197e2d2e1 100644 --- a/dlls/mshtml/tests/documentmode.js +++ b/dlls/mshtml/tests/documentmode.js @@ -3703,6 +3703,83 @@ sync_test("__defineSetter__", function() { ok(x.setterVal === 9, "x.setterVal after setting bar = " + x.setterVal); });
+sync_test("Crypto", function() { + var crypto = window.msCrypto, arr, r; + if(!crypto) return; + + var list = [ + [ "Int8Array", 65536 ], + [ "Uint8Array", 65536 ], + [ "Int16Array", 32768 ], + [ "Uint16Array", 32768 ], + [ "Int32Array", 16384 ], + [ "Uint32Array", 16384 ] + ]; + for(var i = 0; i < list.length; i++) { + var constr = list[i][0]; + arr = (window[constr])(list[i][1]); + + ok(arr[0] === 0, constr + "[0] = " + arr[0]); + ok(arr[1] === 0, constr + "[1] = " + arr[1]); + r = crypto.getRandomValues(arr); + ok(r === arr, "getRandomValues returned " + r); + + arr = (window[constr])(list[i][1]+1); + try { + crypto.getRandomValues(arr); + }catch(ex) { + var n = ex.number >>> 0; + todo_wine. + ok(ex.name === "QuotaExceededError", "getRandomValues(oversized " + constr + ") threw " + ex.name); + todo_wine. + ok(n === 0, "getRandomValues(oversized " + constr + ") threw code " + n); + todo_wine. + ok(ex.message === "QuotaExceededError", "getRandomValues(oversized " + constr + ") threw message " + ex.message); + } + } + + try { + crypto.getRandomValues(null); + ok(false, "getRandomValues(null) did not throw exception"); + }catch(e) { + ok(e.number === 0x70057 - 0x80000000, "getRandomValues(null) threw " + e.number); + } + try { + crypto.getRandomValues(external.nullDisp); + ok(false, "getRandomValues(nullDisp) did not throw exception"); + }catch(e) { + ok(e.number === 0x70057 - 0x80000000, "getRandomValues(nullDisp) threw " + e.number); + } + try { + crypto.getRandomValues([1,2,3]); + ok(false, "getRandomValues([1,2,3]) did not throw exception"); + }catch(e) { + ok(e.number === 0x70057 - 0x80000000, "getRandomValues([1,2,3]) threw " + e.number); + } + arr = Float32Array(2); + try { + crypto.getRandomValues(arr); + ok(false, "getRandomValues(Float32Array) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + todo_wine. + ok(ex.name === "TypeMismatchError", "getRandomValues(Float32Array) threw " + ex.name); + todo_wine. + ok(n === 0, "getRandomValues(Float32Array) threw code " + n); + } + arr = Float64Array(2); + try { + crypto.getRandomValues(arr); + ok(false, "getRandomValues(Float64Array) did not throw exception"); + }catch(ex) { + var n = ex.number >>> 0; + todo_wine. + ok(ex.name === "TypeMismatchError", "getRandomValues(Float64Array) threw " + ex.name); + todo_wine. + ok(n === 0, "getRandomValues(Float64Array) threw code " + n); + } +}); + sync_test("MutationObserver", function() { if (!window.MutationObserver) { return;