diff --git a/dlls/mshtml/htmldoc.c b/dlls/mshtml/htmldoc.c
index 5ba16321386..18bd05f78d5 100644
--- a/dlls/mshtml/htmldoc.c
+++ b/dlls/mshtml/htmldoc.c
@@ -369,8 +369,29 @@ static HRESULT WINAPI HTMLDocument_get_selection(IHTMLDocument2 *iface, IHTMLSel
static HRESULT WINAPI HTMLDocument_get_readyState(IHTMLDocument2 *iface, BSTR *p)
{
- FIXME("(%p)->(%p)\n", iface, p);
- return E_NOTIMPL;
+ HTMLDocument *This = HTMLDOC_THIS(iface);
+
+ static const WCHAR wszUninitialized[] = {'u','n','i','n','i','t','i','a','l','i','z','e','d',0};
+ static const WCHAR wszLoading[] = {'l','o','a','d','i','n','g',0};
+ static const WCHAR wszLoaded[] = {'l','o','a','d','e','d',0};
+ static const WCHAR wszInteractive[] = {'i','n','t','e','r','a','c','t','i','v','e',0};
+ static const WCHAR wszComplete[] = {'c','o','m','p','l','e','t','e',0};
+
+ static const LPCWSTR readystate_str[] = {
+ wszUninitialized,
+ wszLoading,
+ wszLoaded,
+ wszInteractive,
+ wszComplete
+ };
+
+ TRACE("(%p)->(%p)\n", iface, p);
+
+ if(!p)
+ return E_POINTER;
+
+ *p = SysAllocString(readystate_str[This->readystate]);
+ return S_OK;
}
static HRESULT WINAPI HTMLDocument_get_frames(IHTMLDocument2 *iface, IHTMLFramesCollection2 **p)
@@ -1075,6 +1096,7 @@ HRESULT HTMLDocument_Create(IUnknown *pUnkOuter, REFIID riid, void** ppvObject)
ret->ref = 0;
ret->nscontainer = NULL;
ret->nodes = NULL;
+ ret->readystate = READYSTATE_UNINITIALIZED;
hres = IHTMLDocument_QueryInterface(HTMLDOC(ret), riid, ppvObject);
if(FAILED(hres)) {
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index b71277b804d..b4ed5562d0d 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -92,6 +92,7 @@ struct HTMLDocument {
HWND tooltips_hwnd;
USERMODE usermode;
+ READYSTATE readystate;
BOOL in_place_active;
BOOL ui_active;
BOOL window_active;
diff --git a/dlls/mshtml/olecmd.c b/dlls/mshtml/olecmd.c
index d66b2f04677..c517630427c 100644
--- a/dlls/mshtml/olecmd.c
+++ b/dlls/mshtml/olecmd.c
@@ -508,6 +508,10 @@ static HRESULT exec_editmode(HTMLDocument *This)
if(This->nscontainer)
setup_ns_editing(This->nscontainer);
+ /*
+ * FIXME: We should load about:protocol here.
+ */
+ This->readystate = READYSTATE_LOADING;
call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE);
return S_OK;
diff --git a/dlls/mshtml/persist.c b/dlls/mshtml/persist.c
index 5b5f01c68c4..9d823018191 100644
--- a/dlls/mshtml/persist.c
+++ b/dlls/mshtml/persist.c
@@ -192,6 +192,7 @@ static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAva
}
}
+ This->readystate = READYSTATE_LOADING;
call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE);
HTMLDocument_LockContainer(This, TRUE);
diff --git a/dlls/mshtml/task.c b/dlls/mshtml/task.c
index 8f2c21e745d..87a6add3d3e 100644
--- a/dlls/mshtml/task.c
+++ b/dlls/mshtml/task.c
@@ -125,21 +125,20 @@ static void set_downloading(HTMLDocument *doc)
static void set_parsecomplete(HTMLDocument *doc)
{
- IOleCommandTarget *olecmd;
- HRESULT hres;
+ IOleCommandTarget *olecmd = NULL;
TRACE("(%p)\n", doc);
call_property_onchanged(doc->cp_propnotif, 1005);
+
+ doc->readystate = READYSTATE_INTERACTIVE;
call_property_onchanged(doc->cp_propnotif, DISPID_READYSTATE);
- if(!doc->client)
- return;
+ if(doc->client)
+ IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
- hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
- if(SUCCEEDED(hres)) {
- VARIANT state, title, progress;
- WCHAR empty[] = {0};
+ if(olecmd) {
+ VARIANT state, progress;
V_VT(&progress) = VT_I4;
V_I4(&progress) = 0;
@@ -153,7 +152,15 @@ static void set_parsecomplete(HTMLDocument *doc)
IOleCommandTarget_Exec(olecmd, &CGID_MSHTML, IDM_PARSECOMPLETE, 0, NULL, NULL);
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_HTTPEQUIV_DONE, 0, NULL, NULL);
+ }
+ doc->readystate = READYSTATE_COMPLETE;
+ call_property_onchanged(doc->cp_propnotif, DISPID_READYSTATE);
+
+ if(olecmd) {
+ VARIANT title;
+ WCHAR empty[] = {0};
+
V_VT(&title) = VT_BSTR;
V_BSTR(&title) = SysAllocString(empty);
IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETTITLE, OLECMDEXECOPT_DONTPROMPTUSER,
diff --git a/dlls/mshtml/tests/htmldoc.c b/dlls/mshtml/tests/htmldoc.c
index efa46790826..483a87471c1 100644
--- a/dlls/mshtml/tests/htmldoc.c
+++ b/dlls/mshtml/tests/htmldoc.c
@@ -113,16 +113,19 @@ DEFINE_EXPECT(Abort);
static BOOL expect_LockContainer_fLock;
static BOOL expect_SetActiveObject_active;
static BOOL set_clientsite = FALSE, container_locked = FALSE;
+static BOOL readystate_set_loading = FALSE;
static enum load_state_t {
- LD_NO = 0,
LD_DOLOAD,
LD_LOADING,
- LD_LOADED
+ LD_INTERACTIVE,
+ LD_COMPLETE,
+ LD_NO
} load_state;
static LPCOLESTR expect_status_text = NULL;
static HRESULT QueryInterface(REFIID riid, void **ppv);
+static void test_readyState(IUnknown*);
static HRESULT WINAPI HlinkFrame_QueryInterface(IHlinkFrame *iface, REFIID riid, void **ppv)
{
@@ -245,9 +248,16 @@ static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, D
switch(dispID) {
case DISPID_READYSTATE:
CHECK_EXPECT2(OnChanged_READYSTATE);
+ if(readystate_set_loading) {
+ readystate_set_loading = FALSE;
+ load_state = LD_LOADING;
+ }
+ test_readyState(NULL);
return S_OK;
case 1005:
CHECK_EXPECT(OnChanged_1005);
+ test_readyState(NULL);
+ load_state = LD_INTERACTIVE;
return S_OK;
}
@@ -494,7 +504,7 @@ static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
return E_NOTIMPL;
}
-static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
+static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
@@ -1109,7 +1119,7 @@ static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocum
SET_EXPECT(Exec_SETPROGRESSMAX);
SET_EXPECT(Exec_SETPROGRESSPOS);
SET_EXPECT(OnUIActivate);
- expect_status_text = (load_state == LD_LOADED ? (LPCOLESTR)0xdeadbeef : NULL);
+ expect_status_text = (load_state == LD_COMPLETE ? (LPCOLESTR)0xdeadbeef : NULL);
hres = IOleDocumentView_Show(view, TRUE);
ok(hres == S_OK, "Show failed: %08lx\n", hres);
@@ -1370,6 +1380,8 @@ static HRESULT WINAPI OleCommandTarget_QueryStatus(IOleCommandTarget *iface, con
static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID *pguidCmdGroup,
DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
+ test_readyState(NULL);
+
if(!pguidCmdGroup) {
switch(nCmdID) {
case OLECMDID_SETPROGRESSMAX:
@@ -1399,6 +1411,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID
ok(nCmdexecopt == 0, "nCmdexecopts=%08lx\n", nCmdexecopt);
ok(pvaOut == NULL, "pvaOut=%p\n", pvaOut);
ok(pvaIn == NULL, "pvaIn=%p\n", pvaIn);
+ load_state = LD_COMPLETE;
return S_OK;
case OLECMDID_SETDOWNLOADSTATE:
ok(nCmdexecopt == OLECMDEXECOPT_DONTPROMPTUSER, "nCmdexecopts=%08lx\n", nCmdexecopt);
@@ -1409,6 +1422,7 @@ static HRESULT WINAPI OleCommandTarget_Exec(IOleCommandTarget *iface, const GUID
switch(V_I4(pvaIn)) {
case 0:
CHECK_EXPECT(Exec_SETDOWNLOADSTATE_0);
+ load_state = LD_INTERACTIVE;
break;
case 1:
CHECK_EXPECT(Exec_SETDOWNLOADSTATE_1);
@@ -1538,6 +1552,7 @@ static HRESULT WINAPI Dispatch_Invoke(IDispatch *iface, DISPID dispIdMember, REF
ok(puArgErr != NULL, "puArgErr == NULL\n");
ok(V_VT(pVarResult) == 0, "V_VT(pVarResult)=%d, expected 0\n", V_VT(pVarResult));
ok(wFlags == DISPATCH_PROPERTYGET, "wFlags=%08x, expected DISPATCH_PROPERTYGET\n", wFlags);
+ test_readyState(NULL);
switch(dispIdMember) {
case DISPID_AMBIENT_USERMODE:
@@ -1682,6 +1697,45 @@ static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam
return DefWindowProc(hwnd, msg, wParam, lParam);
}
+static void test_readyState(IUnknown *unk)
+{
+ IHTMLDocument2 *htmldoc;
+ BSTR state;
+ HRESULT hres;
+
+ static IUnknown *_unk;
+
+ static const WCHAR wszUninitialized[] = {'u','n','i','n','i','t','i','a','l','i','z','e','d',0};
+ static const WCHAR wszLoading[] = {'l','o','a','d','i','n','g',0};
+ static const WCHAR wszInteractive[] = {'i','n','t','e','r','a','c','t','i','v','e',0};
+ static const WCHAR wszComplete[] = {'c','o','m','p','l','e','t','e',0};
+
+ static const LPCWSTR expected_state[] = {
+ wszUninitialized,
+ wszLoading,
+ wszInteractive,
+ wszComplete,
+ wszUninitialized
+ };
+
+ if(!unk) unk = _unk;
+ else _unk = unk;
+
+ hres = IUnknown_QueryInterface(unk, &IID_IHTMLDocument2, (void**)&htmldoc);
+ ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument2) failed: %08lx\n", hres);
+ if(FAILED(hres))
+ return;
+
+ hres = IHTMLDocument2_get_readyState(htmldoc, NULL);
+ ok(hres == E_POINTER, "get_readyState failed: %08lx, expected \n", hres);
+
+ hres = IHTMLDocument2_get_readyState(htmldoc, &state);
+ ok(hres == S_OK, "get_ReadyState failed: %08lx\n", hres);
+ ok(!lstrcmpW(state, expected_state[load_state]), "unexpected state, expected %d\n", load_state);
+
+ IHTMLDocument_Release(htmldoc);
+}
+
static void test_ConnectionPoint(IConnectionPointContainer *container, REFIID riid)
{
IConnectionPointContainer *tmp_container = NULL;
@@ -1742,6 +1796,8 @@ static void test_Load(IPersistMoniker *persist)
IBindCtx *bind;
HRESULT hres;
+ test_readyState((IUnknown*)persist);
+
CreateBindCtx(0, &bind);
IBindCtx_RegisterObjectParam(bind, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM,
(IUnknown*)&ClientSite);
@@ -1766,6 +1822,7 @@ static void test_Load(IPersistMoniker *persist)
SET_EXPECT(GetContainer);
SET_EXPECT(LockContainer);
expect_LockContainer_fLock = TRUE;
+ readystate_set_loading = TRUE;
hres = IPersistMoniker_Load(persist, FALSE, &Moniker, bind, 0x12);
ok(hres == S_OK, "Load failed: %08lx\n", hres);
@@ -1793,6 +1850,8 @@ static void test_Load(IPersistMoniker *persist)
set_clientsite = container_locked = TRUE;
IBindCtx_Release(bind);
+
+ test_readyState((IUnknown*)persist);
}
static void test_download(void)
@@ -1800,11 +1859,11 @@ static void test_download(void)
HWND hwnd;
MSG msg;
- load_state = LD_LOADING;
-
hwnd = FindWindowA("Internet Explorer_Hidden", NULL);
ok(hwnd != NULL, "Could not find hidden window\n");
+ test_readyState(NULL);
+
SET_EXPECT(SetStatusText);
SET_EXPECT(Exec_SETDOWNLOADSTATE_1);
SET_EXPECT(GetDropTarget);
@@ -1833,7 +1892,9 @@ static void test_download(void)
CHECK_CALLED(Exec_HTTPEQUIV_DONE);
CHECK_CALLED(Exec_SETTITLE);
- load_state = LD_LOADED;
+ load_state = LD_COMPLETE;
+
+ test_readyState(NULL);
}
static void test_Persist(IUnknown *unk)
@@ -1869,6 +1930,8 @@ static void test_Persist(IUnknown *unk)
if(load_state == LD_DOLOAD)
test_Load(persist_mon);
+ test_readyState(unk);
+
IPersistMoniker_Release(persist_mon);
}
}
@@ -2042,6 +2105,7 @@ static void test_exec_editmode(IUnknown *unk)
SET_EXPECT(Invoke_AMBIENT_OFFLINEIFNOTCONNECTED);
SET_EXPECT(OnChanged_READYSTATE);
expect_status_text = NULL;
+ readystate_set_loading = TRUE;
hres = IOleCommandTarget_Exec(cmdtrg, &CGID_MSHTML, IDM_EDITMODE,
OLECMDEXECOPT_DODEFAULT, NULL, NULL);
@@ -2502,7 +2566,7 @@ static void test_HTMLDocument(enum load_state_t ls)
return;
}
- if(load_state == LD_DOLOAD)
+ if(load_state == LD_LOADING)
test_download();
test_OleCommandTarget_fail(unk);
@@ -2605,6 +2669,7 @@ static void test_editing_mode(void)
hres = IUnknown_QueryInterface(unk, &IID_IOleObject, (void**)&oleobj);
ok(hres == S_OK, "Could not get IOleObject: %08lx\n", hres);
+ test_readyState(unk);
test_ConnectionPointContainer(unk);
test_ClientSite(oleobj, CLIENTSITE_EXPECTPATH);
test_DoVerb(oleobj);