diff --git a/dlls/mshtml/tests/misc.c b/dlls/mshtml/tests/misc.c
index 1702a24c804..410d24884ee 100644
--- a/dlls/mshtml/tests/misc.c
+++ b/dlls/mshtml/tests/misc.c
@@ -24,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
#include "ole2.h"
+#include "mshtml.h"
#include "initguid.h"
#include "optary.h"
@@ -106,11 +107,200 @@ static void test_HTMLLoadOptions(void)
IHtmlLoadOptions_Release(loadopts);
}
+static IHTMLDocument2 *create_doc_from_url(const WCHAR *start_url)
+{
+ BSTR url;
+ IBindCtx *bc;
+ IMoniker *url_mon;
+ IPersistMoniker *persist_mon;
+ IHTMLDocument2 *doc;
+ HRESULT hres;
+
+ hres = CreateBindCtx(0, &bc);
+ ok(hres == S_OK, "CreateBindCtx failed: 0x%08lx\n", hres);
+
+ url = SysAllocString(start_url);
+ hres = CreateURLMoniker(NULL, url, &url_mon);
+ ok(hres == S_OK, "CreateURLMoniker failed: 0x%08lx\n", hres);
+
+ hres = CoCreateInstance(&CLSID_HTMLDocument, NULL,
+ CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER, &IID_IHTMLDocument2,
+ (void**)&doc);
+ ok(hres == S_OK, "CoCreateInstance failed: 0x%08lx\n", hres);
+
+ hres = IHTMLDocument2_QueryInterface(doc, &IID_IPersistMoniker,
+ (void**)&persist_mon);
+ ok(hres == S_OK, "IHTMLDocument2_QueryInterface failed: 0x%08lx\n", hres);
+
+ hres = IPersistMoniker_Load(persist_mon, FALSE, url_mon, bc,
+ STGM_SHARE_EXCLUSIVE | STGM_READWRITE);
+ ok(hres == S_OK, "IPersistMoniker_Load failed: 0x%08lx\n", hres);
+
+ IPersistMoniker_Release(persist_mon);
+ IMoniker_Release(url_mon);
+ IBindCtx_Release(bc);
+ SysFreeString(url);
+ return doc;
+}
+
+static HRESULT get_localstorage(IHTMLDocument2 *doc, IHTMLStorage **storage)
+{
+ IHTMLWindow2 *window;
+ IHTMLWindow6 *window6;
+ HRESULT hres;
+
+ hres = IHTMLDocument2_get_parentWindow(doc, &window);
+ ok(hres == S_OK, "get_parentWindow failed: %08lx\n", hres);
+ ok(window != NULL, "window == NULL\n");
+
+ hres = IHTMLWindow2_QueryInterface(window, &IID_IHTMLWindow6, (void**)&window6);
+ IHTMLWindow2_Release(window);
+ if(FAILED(hres)) {
+ win_skip("IHTMLWindow6 not supported\n");
+ return hres;
+ }
+
+ hres = IHTMLWindow6_get_localStorage(window6, storage);
+ ok(hres == S_OK, "get_localStorage failed: %08lx\n", hres);
+ ok(*storage != NULL, "*storage == NULL\n");
+
+ IHTMLWindow6_Release(window6);
+ return hres;
+}
+
+static void test_HTMLStorage(void)
+{
+ IHTMLDocument2 *doc, *doc2;
+ IHTMLStorage *storage, *storage2;
+ VARIANT var;
+ BSTR key, value;
+ HRESULT hres;
+
+ doc = create_doc_from_url(L"http://www.codeweavers.com/");
+ doc2 = create_doc_from_url(L"http://www.codeweavers.com/");
+
+ hres = get_localstorage(doc, &storage);
+ ok(hres == S_OK, "got %08lx\n", hres);
+
+ hres = get_localstorage(doc2, &storage2);
+ ok(hres == S_OK, "got %08lx\n", hres);
+
+ key = SysAllocString(L"");
+ V_VT(&var) = 0xdead;
+ 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));
+
+ key = SysAllocString(L"undefined");
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+
+ value = SysAllocString(L"null");
+ hres = IHTMLStorage_setItem(storage, key, value);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+
+ V_VT(&var) = 0xdead;
+ hres = IHTMLStorage_getItem(storage, key, &var);
+ ok(hres == S_OK, "getItem failed: %08lx\n", hres);
+ ok(V_VT(&var) == VT_BSTR, "got %d\n", V_VT(&var));
+ if (V_VT(&var) == VT_BSTR) ok(!wcscmp(V_BSTR(&var), L"null"), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+ SysFreeString(key);
+ SysFreeString(value);
+
+ key = SysAllocString(L"winetest");
+ value = SysAllocString(L"winetest");
+ hres = IHTMLStorage_setItem(storage, key, value);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+
+ /* retrieve value from different storage instance */
+ V_VT(&var) = 0xdead;
+ hres = IHTMLStorage_getItem(storage2, key, &var);
+ ok(hres == S_OK, "getItem failed: %08lx\n", hres);
+ ok(V_VT(&var) == VT_BSTR, "got %d\n", V_VT(&var));
+ if (V_VT(&var) == VT_BSTR) ok(!wcscmp(V_BSTR(&var), L"winetest"), "got %s\n", wine_dbgstr_w(V_BSTR(&var)));
+
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+
+ V_VT(&var) = 0xdead;
+ hres = IHTMLStorage_getItem(storage2, key, &var);
+ ok(hres == S_OK, "getItem failed: %08lx\n", hres);
+ ok(V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
+ SysFreeString(key);
+ SysFreeString(value);
+
+ /* item doesn't exist */
+ key = SysAllocString(L"nosuch");
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+
+ V_VT(&var) = 0xdead;
+ 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));
+ SysFreeString(key);
+
+ hres = IHTMLStorage_getItem(storage, NULL, NULL);
+ ok(hres == E_POINTER, "getItem returned: %08lx\n", hres);
+
+ hres = IHTMLStorage_getItem(storage, key, NULL);
+ ok(hres == E_POINTER, "getItem failed: %08lx\n", hres);
+
+ V_VT(&var) = 0xdead;
+ hres = IHTMLStorage_getItem(storage, NULL, &var);
+ ok(hres == S_OK, "getItem returned: %08lx\n", hres);
+ ok(V_VT(&var) == VT_NULL, "got %d\n", V_VT(&var));
+
+ hres = IHTMLStorage_setItem(storage, NULL, NULL);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+
+ key = SysAllocString(L"winetest2");
+ hres = IHTMLStorage_setItem(storage, key, NULL);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+
+ hres = IHTMLStorage_setItem(storage, NULL, key);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+ SysFreeString(key);
+
+ hres = IHTMLStorage_removeItem(storage, NULL);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+
+ /* Unicode characters */
+ key = SysAllocString(L"winetest");
+ value = SysAllocString(L"\x20ac");
+ hres = IHTMLStorage_setItem(storage, key, value);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+ SysFreeString(value);
+ SysFreeString(key);
+
+ key = SysAllocString(L"\x20ac");
+ value = SysAllocString(L"winetest");
+ hres = IHTMLStorage_setItem(storage, key, value);
+ ok(hres == S_OK, "setItem failed: %08lx\n", hres);
+ hres = IHTMLStorage_removeItem(storage, key);
+ ok(hres == S_OK, "removeItem failed: %08lx\n", hres);
+ SysFreeString(value);
+ SysFreeString(key);
+
+ IHTMLStorage_Release(storage);
+ IHTMLStorage_Release(storage2);
+ IHTMLDocument2_Release(doc);
+ IHTMLDocument2_Release(doc2);
+}
+
START_TEST(misc)
{
CoInitialize(NULL);
test_HTMLLoadOptions();
+ test_HTMLStorage();
CoUninitialize();
}