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 | 28 ++++++++++++++++++++++++-- dlls/mshtml/mshtml_private.h | 1 + dlls/mshtml/tests/misc.c | 39 +++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 9b0beff8f9f..2b529498a64 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; @@ -83,6 +86,7 @@ static struct session_storage_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)); @@ -120,12 +124,15 @@ static HRESULT get_session_entry(struct session_storage_map_entry *entry, BSTR k }
key_len = SysStringLen(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])))) return E_OUTOFMEMORY; data->value = NULL; data->key_len = key_len; memcpy(data->key, key, key_len * 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); @@ -143,6 +150,7 @@ static void clear_session_storage(struct session_storage_map_entry *entry) } wine_rb_destroy(&entry->data_map, NULL, NULL); list_init(&entry->data_list); + entry->quota = MAX_QUOTA; entry->num_keys = 0; }
@@ -407,7 +415,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; }
@@ -671,7 +687,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;
@@ -679,6 +696,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; } @@ -743,6 +766,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 += session_entry->key_len + 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/mshtml_private.h b/dlls/mshtml/mshtml_private.h index cf3e769b0e8..0f353fadf31 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -1246,6 +1246,7 @@ struct session_storage_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]; 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);