From: Gabriel Ivăncescu gabrielopcode@gmail.com
And a character quota that matches native.
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstorage.c | 29 +++++++++++++++++++++++++++-- dlls/mshtml/tests/misc.c | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 75ef6855abe..531488ff953 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -32,6 +32,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+/* Native defaults to 5 million chars per origin */ +enum { MAX_QUOTA = 5000000 }; + typedef struct { DispatchEx dispex; IHTMLStorage IHTMLStorage_iface; @@ -46,6 +49,7 @@ struct session_map_entry { struct wine_rb_tree data_map; struct list data_list; /* for key() */ UINT ref; + UINT quota; UINT num_keys; UINT origin_len; WCHAR origin[1]; @@ -98,6 +102,7 @@ static struct session_map_entry *grab_session_map_entry(BSTR origin) wine_rb_init(&entry->data_map, session_entry_cmp); list_init(&entry->data_list); entry->ref = 1; + entry->quota = MAX_QUOTA; entry->num_keys = 0; entry->origin_len = origin_len; memcpy(entry->origin, origin, origin_len * sizeof(WCHAR)); @@ -134,11 +139,14 @@ static HRESULT get_session_entry(struct session_map_entry *entry, const WCHAR *n }
key_len = wcslen(key); + if(entry->quota < key_len) + return E_OUTOFMEMORY; /* native returns this when quota is exceeded */ if(!(data = heap_alloc(FIELD_OFFSET(struct session_entry, key[key_len + 1])))) return E_OUTOFMEMORY; data->value = NULL; memcpy(data->key, key, (key_len + 1) * sizeof(WCHAR));
+ entry->quota -= key_len; entry->num_keys++; list_add_tail(&entry->data_list, &data->list_entry); wine_rb_put(&entry->data_map, key, &data->entry); @@ -156,6 +164,7 @@ static void clear_session_storage(struct session_map_entry *entry) } wine_rb_destroy(&entry->data_map, NULL, NULL); list_init(&entry->data_list); + entry->quota = MAX_QUOTA; entry->num_keys = 0; }
@@ -420,7 +429,15 @@ static HRESULT WINAPI HTMLStorage_get_length(IHTMLStorage *iface, LONG *p) static HRESULT WINAPI HTMLStorage_get_remainingSpace(IHTMLStorage *iface, LONG *p) { HTMLStorage *This = impl_from_IHTMLStorage(iface); - FIXME("(%p)->(%p)\n", This, p); + + TRACE("(%p)->(%p)\n", This, p); + + if(!This->filename) { + *p = This->session_storage->quota; + return S_OK; + } + + FIXME("local storage not supported\n"); return E_NOTIMPL; }
@@ -685,7 +702,8 @@ static HRESULT WINAPI HTMLStorage_setItem(IHTMLStorage *iface, BSTR bstrKey, BST TRACE("(%p)->(%s %s)\n", This, debugstr_w(bstrKey), debugstr_w(bstrValue));
if(!This->filename) { - BSTR value = SysAllocStringLen(bstrValue, SysStringLen(bstrValue)); + UINT value_len = SysStringLen(bstrValue); + BSTR value = SysAllocStringLen(bstrValue, value_len); if(!value) return E_OUTOFMEMORY;
@@ -693,6 +711,12 @@ static HRESULT WINAPI HTMLStorage_setItem(IHTMLStorage *iface, BSTR bstrKey, BST if(FAILED(hres)) SysFreeString(value); else { + UINT old_len = SysStringLen(session_entry->value); + if(old_len < value_len && This->session_storage->quota < value_len - old_len) { + SysFreeString(value); + return E_OUTOFMEMORY; /* native returns this when quota is exceeded */ + } + This->session_storage->quota -= value_len - old_len; SysFreeString(session_entry->value); session_entry->value = value; } @@ -757,6 +781,7 @@ static HRESULT WINAPI HTMLStorage_removeItem(IHTMLStorage *iface, BSTR bstrKey) if(!This->filename) { hres = get_session_entry(This->session_storage, bstrKey, FALSE, &session_entry); if(SUCCEEDED(hres) && session_entry) { + This->session_storage->quota += wcslen(session_entry->key) + SysStringLen(session_entry->value); This->session_storage->num_keys--; list_remove(&session_entry->list_entry); wine_rb_remove(&This->session_storage->data_map, &session_entry->entry); diff --git a/dlls/mshtml/tests/misc.c b/dlls/mshtml/tests/misc.c index d1bdd2d544e..c2c8370cc4b 100644 --- a/dlls/mshtml/tests/misc.c +++ b/dlls/mshtml/tests/misc.c @@ -197,7 +197,7 @@ static void test_HTMLStorage(void) { IHTMLDocument2 *doc, *doc2; IHTMLStorage *storage, *storage2; - LONG length, lval; + LONG space, length, lval; VARIANT var; BSTR key, value; HRESULT hres; @@ -346,6 +346,10 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "get_length failed %08lx\n", hres); ok(lval == 0, "length = %ld\n", lval);
+ hres = IHTMLStorage_get_remainingSpace(storage, &space); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(space >= 5000000, "remainingSpace = %ld\n", space); + key = SysAllocString(L""); V_VT(&var) = 0xdead; hres = IHTMLStorage_getItem(storage, key, &var); @@ -369,6 +373,13 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "get_length failed %08lx\n", hres); ok(lval == 1, "length = %ld\n", lval);
+ hres = IHTMLStorage_get_remainingSpace(storage, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space - 13, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_get_remainingSpace(storage2, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space - 13, "remainingSpace = %ld\n", lval); + V_VT(&var) = 0xdead; hres = IHTMLStorage_getItem(storage, key, &var); ok(hres == S_OK, "getItem failed: %08lx\n", hres); @@ -443,6 +454,13 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "get_length failed %08lx\n", hres); ok(lval == 2, "length = %ld\n", lval);
+ hres = IHTMLStorage_get_remainingSpace(storage, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space - 21, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_get_remainingSpace(storage2, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space - 21, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_key(storage, 0, &key); ok(hres == S_OK, "key failed %08lx\n", hres); ok(!wcscmp(key, L"undefined"), "key(0) = %s\n", wine_dbgstr_w(key)); @@ -488,6 +506,13 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "get_length failed %08lx\n", hres); ok(lval == 0, "length = %ld\n", lval);
+ hres = IHTMLStorage_get_remainingSpace(storage, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_get_remainingSpace(storage2, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_key(storage, 0, &key); ok(hres == E_INVALIDARG, "key failed %08lx\n", hres);
@@ -526,6 +551,10 @@ static void test_HTMLStorage(void) ok(!wcscmp(V_BSTR(&var), L"bar"), "got %s\n", wine_dbgstr_w(V_BSTR(&var))); VariantClear(&var);
+ hres = IHTMLStorage_get_remainingSpace(storage, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space - 6, "remainingSpace = %ld\n", lval); + IHTMLStorage_Release(storage2); IHTMLDocument2_Release(doc2);
@@ -538,6 +567,10 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "getItem failed: %08lx\n", hres); ok(V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
+ hres = IHTMLStorage_get_remainingSpace(storage2, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_setItem(storage2, key, value); ok(hres == S_OK, "setItem failed: %08lx\n", hres);
@@ -570,6 +603,10 @@ static void test_HTMLStorage(void) ok(hres == S_OK, "getItem failed: %08lx\n", hres); ok(V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
+ hres = IHTMLStorage_get_remainingSpace(storage2, &lval); + ok(hres == S_OK, "get_remainingSpace failed %08lx\n", hres); + ok(lval == space, "remainingSpace = %ld\n", lval); + hres = IHTMLStorage_clear(storage); ok(hres == S_OK, "clear failed %08lx\n", hres);