From: Gabriel Ivăncescu gabrielopcode@gmail.com
Signed-off-by: Gabriel Ivăncescu gabrielopcode@gmail.com --- dlls/mshtml/htmlstorage.c | 28 ++++++++++++++++++++++++++-- dlls/mshtml/tests/misc.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-)
diff --git a/dlls/mshtml/htmlstorage.c b/dlls/mshtml/htmlstorage.c index 259c65b754b..495b22c7085 100644 --- a/dlls/mshtml/htmlstorage.c +++ b/dlls/mshtml/htmlstorage.c @@ -44,6 +44,7 @@ typedef struct { struct session_map_entry { struct wine_rb_entry entry; struct wine_rb_tree data_map; + struct list data_list; /* for key() */ UINT ref; UINT num_keys; UINT origin_len; @@ -61,6 +62,7 @@ int session_storage_map_cmp(const void *key, const struct wine_rb_entry *entry) struct session_entry { struct wine_rb_entry entry; + struct list list_entry; BSTR value; WCHAR key[1]; }; @@ -94,6 +96,7 @@ static struct session_map_entry *grab_session_map_entry(BSTR origin) if(!entry) return NULL; wine_rb_init(&entry->data_map, session_entry_cmp); + list_init(&entry->data_list); entry->ref = 1; entry->num_keys = 0; entry->origin_len = origin_len; @@ -137,6 +140,7 @@ static HRESULT get_session_entry(struct session_map_entry *entry, const WCHAR *n memcpy(data->key, key, (key_len + 1) * sizeof(WCHAR));
entry->num_keys++; + list_add_tail(&entry->data_list, &data->list_entry); wine_rb_put(&entry->data_map, key, &data->entry); *ret = data; return S_OK; @@ -146,11 +150,12 @@ static void clear_session_storage(struct session_map_entry *entry) { struct session_entry *iter, *iter2;
- WINE_RB_FOR_EACH_ENTRY_DESTRUCTOR(iter, iter2, &entry->data_map, struct session_entry, entry) { + LIST_FOR_EACH_ENTRY_SAFE(iter, iter2, &entry->data_list, struct session_entry, list_entry) { SysFreeString(iter->value); heap_free(iter); } wine_rb_destroy(&entry->data_map, NULL, NULL); + list_init(&entry->data_list); entry->num_keys = 0; }
@@ -365,7 +370,25 @@ static HRESULT WINAPI HTMLStorage_get_remainingSpace(IHTMLStorage *iface, LONG * static HRESULT WINAPI HTMLStorage_key(IHTMLStorage *iface, LONG lIndex, BSTR *p) { HTMLStorage *This = impl_from_IHTMLStorage(iface); - FIXME("(%p)->(%ld %p)\n", This, lIndex, p); + struct session_entry *session_entry; + + TRACE("(%p)->(%ld %p)\n", This, lIndex, p); + + if(!This->filename) { + struct list *entry = &This->session_storage->data_list; + unsigned i = 0; + + if(lIndex >= This->session_storage->num_keys) + return E_INVALIDARG; + + do entry = entry->next; while(i++ < lIndex); + session_entry = LIST_ENTRY(entry, struct session_entry, list_entry); + + *p = SysAllocString(session_entry->key); + return *p ? S_OK : E_OUTOFMEMORY; + } + + FIXME("local storage not supported\n"); return E_NOTIMPL; }
@@ -651,6 +674,7 @@ static HRESULT WINAPI HTMLStorage_removeItem(IHTMLStorage *iface, BSTR bstrKey) hres = get_session_entry(This->session_storage, bstrKey, FALSE, &session_entry); if(SUCCEEDED(hres) && session_entry) { This->session_storage->num_keys--; + list_remove(&session_entry->list_entry); wine_rb_remove(&This->session_storage->data_map, &session_entry->entry); SysFreeString(session_entry->value); heap_free(session_entry); diff --git a/dlls/mshtml/tests/misc.c b/dlls/mshtml/tests/misc.c index c2a8c87f473..660c191ac99 100644 --- a/dlls/mshtml/tests/misc.c +++ b/dlls/mshtml/tests/misc.c @@ -405,11 +405,38 @@ static void test_HTMLStorage(void) ok(V_VT(&var) == VT_BSTR, "got %d\n", V_VT(&var)); ok(!wcscmp(V_BSTR(&var), L"bbbb"), "got %s\n", wine_dbgstr_w(V_BSTR(&var))); VariantClear(&var); + SysFreeString(key); + + 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)); + SysFreeString(key);
+ hres = IHTMLStorage_key(storage, 1, &key); + ok(hres == S_OK, "key failed %08lx\n", hres); + ok(!wcscmp(key, L"aaaa"), "key(0) = %s\n", wine_dbgstr_w(key)); + SysFreeString(key); + + hres = IHTMLStorage_key(storage, 2, &key); + ok(hres == E_INVALIDARG, "key failed %08lx\n", hres); + hres = IHTMLStorage_key(storage, -1, &key); + ok(hres == E_INVALIDARG, "key failed %08lx\n", hres); + + key = SysAllocString(L"undefined"); hres = IHTMLStorage_removeItem(storage2, key); ok(hres == S_OK, "removeItem failed: %08lx\n", hres); + SysFreeString(key); + + hres = IHTMLStorage_key(storage, 0, &key); + ok(hres == S_OK, "key failed %08lx\n", hres); + ok(!wcscmp(key, L"aaaa"), "key(0) = %s\n", wine_dbgstr_w(key)); + SysFreeString(key); + + hres = IHTMLStorage_key(storage, 1, &key); + ok(hres == E_INVALIDARG, "key failed %08lx\n", hres);
V_VT(&var) = 0xdead; + key = SysAllocString(L"undefined"); hres = IHTMLStorage_getItem(storage, key, &var); ok(hres == S_OK, "getItem failed: %08lx\n", hres); ok(V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var)); @@ -418,6 +445,9 @@ static void test_HTMLStorage(void) hres = IHTMLStorage_clear(storage2); ok(hres == S_OK, "clear failed %08lx\n", hres);
+ hres = IHTMLStorage_key(storage, 0, &key); + ok(hres == E_INVALIDARG, "key failed %08lx\n", hres); + key = SysAllocString(L"foo"); value = SysAllocString(L"bar"); hres = IHTMLStorage_setItem(storage, key, value);