Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennavigate.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2006-2007 Jacek Caban for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #define NONAMELESSUNION 00020 #define NONAMELESSSTRUCT 00021 00022 #include "wine/debug.h" 00023 00024 #include "shdocvw.h" 00025 #include "exdispid.h" 00026 #include "shellapi.h" 00027 #include "winreg.h" 00028 #include "shlwapi.h" 00029 #include "wininet.h" 00030 #include "mshtml.h" 00031 00032 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); 00033 00034 static const WCHAR emptyW[] = {0}; 00035 00036 typedef struct { 00037 const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; 00038 const IHttpNegotiateVtbl *lpHttpNegotiateVtbl; 00039 00040 LONG ref; 00041 00042 DocHost *doc_host; 00043 00044 LPWSTR url; 00045 HGLOBAL post_data; 00046 BSTR headers; 00047 ULONG post_data_len; 00048 } BindStatusCallback; 00049 00050 #define BINDSC(x) ((IBindStatusCallback*) &(x)->lpBindStatusCallbackVtbl) 00051 #define HTTPNEG(x) ((IHttpNegotiate*) &(x)->lpHttpNegotiateVtbl) 00052 00053 static void dump_BINDINFO(BINDINFO *bi) 00054 { 00055 static const char * const BINDINFOF_str[] = { 00056 "#0", 00057 "BINDINFOF_URLENCODESTGMEDDATA", 00058 "BINDINFOF_URLENCODEDEXTRAINFO" 00059 }; 00060 00061 static const char * const BINDVERB_str[] = { 00062 "BINDVERB_GET", 00063 "BINDVERB_POST", 00064 "BINDVERB_PUT", 00065 "BINDVERB_CUSTOM" 00066 }; 00067 00068 TRACE("\n" 00069 "BINDINFO = {\n" 00070 " %d, %s,\n" 00071 " {%d, %p, %p},\n" 00072 " %s,\n" 00073 " %s,\n" 00074 " %s,\n" 00075 " %d, %08x, %d, %d\n" 00076 " {%d %p %x},\n" 00077 " %s\n" 00078 " %p, %d\n" 00079 "}\n", 00080 00081 bi->cbSize, debugstr_w(bi->szExtraInfo), 00082 bi->stgmedData.tymed, bi->stgmedData.u.hGlobal, bi->stgmedData.pUnkForRelease, 00083 bi->grfBindInfoF > BINDINFOF_URLENCODEDEXTRAINFO 00084 ? "unknown" : BINDINFOF_str[bi->grfBindInfoF], 00085 bi->dwBindVerb > BINDVERB_CUSTOM 00086 ? "unknown" : BINDVERB_str[bi->dwBindVerb], 00087 debugstr_w(bi->szCustomVerb), 00088 bi->cbstgmedData, bi->dwOptions, bi->dwOptionsFlags, bi->dwCodePage, 00089 bi->securityAttributes.nLength, 00090 bi->securityAttributes.lpSecurityDescriptor, 00091 bi->securityAttributes.bInheritHandle, 00092 debugstr_guid(&bi->iid), 00093 bi->pUnk, bi->dwReserved 00094 ); 00095 } 00096 00097 static void set_status_text(BindStatusCallback *This, LPCWSTR str) 00098 { 00099 VARIANTARG arg; 00100 DISPPARAMS dispparams = {&arg, NULL, 1, 0}; 00101 00102 if(!This->doc_host) 00103 return; 00104 00105 V_VT(&arg) = VT_BSTR; 00106 V_BSTR(&arg) = str ? SysAllocString(str) : NULL; 00107 call_sink(This->doc_host->cps.wbe2, DISPID_STATUSTEXTCHANGE, &dispparams); 00108 VariantClear(&arg); 00109 00110 if(This->doc_host->frame) 00111 IOleInPlaceFrame_SetStatusText(This->doc_host->frame, str); 00112 } 00113 00114 static HRESULT set_dochost_url(DocHost *This, const WCHAR *url) 00115 { 00116 WCHAR *new_url; 00117 00118 if(url) { 00119 new_url = heap_strdupW(url); 00120 if(!new_url) 00121 return E_OUTOFMEMORY; 00122 }else { 00123 new_url = NULL; 00124 } 00125 00126 heap_free(This->url); 00127 This->url = new_url; 00128 00129 This->container_vtbl->SetURL(This, This->url); 00130 return S_OK; 00131 } 00132 00133 #define BINDSC_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface) 00134 00135 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, 00136 REFIID riid, void **ppv) 00137 { 00138 BindStatusCallback *This = BINDSC_THIS(iface); 00139 00140 *ppv = NULL; 00141 00142 if(IsEqualGUID(&IID_IUnknown, riid)) { 00143 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 00144 *ppv = BINDSC(This); 00145 }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { 00146 TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv); 00147 *ppv = BINDSC(This); 00148 }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { 00149 TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv); 00150 *ppv = HTTPNEG(This); 00151 } 00152 00153 if(*ppv) { 00154 IBindStatusCallback_AddRef(BINDSC(This)); 00155 return S_OK; 00156 } 00157 00158 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 00159 return E_NOINTERFACE; 00160 } 00161 00162 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) 00163 { 00164 BindStatusCallback *This = BINDSC_THIS(iface); 00165 LONG ref = InterlockedIncrement(&This->ref); 00166 00167 TRACE("(%p) ref=%d\n", This, ref); 00168 00169 return ref; 00170 } 00171 00172 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) 00173 { 00174 BindStatusCallback *This = BINDSC_THIS(iface); 00175 LONG ref = InterlockedDecrement(&This->ref); 00176 00177 TRACE("(%p) ref=%d\n", This, ref); 00178 00179 if(!ref) { 00180 if(This->doc_host) 00181 IOleClientSite_Release(CLIENTSITE(This->doc_host)); 00182 if(This->post_data) 00183 GlobalFree(This->post_data); 00184 SysFreeString(This->headers); 00185 heap_free(This->url); 00186 heap_free(This); 00187 } 00188 00189 return ref; 00190 } 00191 00192 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, 00193 DWORD dwReserved, IBinding *pbind) 00194 { 00195 BindStatusCallback *This = BINDSC_THIS(iface); 00196 00197 TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind); 00198 00199 return S_OK; 00200 } 00201 00202 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, 00203 LONG *pnPriority) 00204 { 00205 BindStatusCallback *This = BINDSC_THIS(iface); 00206 FIXME("(%p)->(%p)\n", This, pnPriority); 00207 return E_NOTIMPL; 00208 } 00209 00210 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, 00211 DWORD reserved) 00212 { 00213 BindStatusCallback *This = BINDSC_THIS(iface); 00214 FIXME("(%p)->(%d)\n", This, reserved); 00215 return E_NOTIMPL; 00216 } 00217 00218 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, 00219 ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 00220 { 00221 BindStatusCallback *This = BINDSC_THIS(iface); 00222 00223 TRACE("(%p)->(%d %d %d %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, 00224 debugstr_w(szStatusText)); 00225 00226 switch(ulStatusCode) { 00227 case BINDSTATUS_REDIRECTING: 00228 return set_dochost_url(This->doc_host, szStatusText); 00229 case BINDSTATUS_BEGINDOWNLOADDATA: 00230 set_status_text(This, szStatusText); /* FIXME: "Start downloading from site: %s" */ 00231 return S_OK; 00232 case BINDSTATUS_ENDDOWNLOADDATA: 00233 set_status_text(This, szStatusText); /* FIXME: "Downloading from site: %s" */ 00234 return S_OK; 00235 case BINDSTATUS_CLASSIDAVAILABLE: 00236 case BINDSTATUS_MIMETYPEAVAILABLE: 00237 case BINDSTATUS_BEGINSYNCOPERATION: 00238 case BINDSTATUS_ENDSYNCOPERATION: 00239 return S_OK; 00240 default: 00241 FIXME("status code %u\n", ulStatusCode); 00242 } 00243 00244 return S_OK; 00245 } 00246 00247 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, 00248 HRESULT hresult, LPCWSTR szError) 00249 { 00250 BindStatusCallback *This = BINDSC_THIS(iface); 00251 00252 TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError)); 00253 00254 set_status_text(This, emptyW); 00255 00256 if(This->doc_host) { 00257 IOleClientSite_Release(CLIENTSITE(This->doc_host)); 00258 This->doc_host = NULL; 00259 } 00260 00261 return S_OK; 00262 } 00263 00264 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, 00265 DWORD *grfBINDF, BINDINFO *pbindinfo) 00266 { 00267 BindStatusCallback *This = BINDSC_THIS(iface); 00268 00269 TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); 00270 00271 *grfBINDF = BINDF_ASYNCHRONOUS; 00272 00273 if(This->post_data) { 00274 pbindinfo->dwBindVerb = BINDVERB_POST; 00275 00276 pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; 00277 pbindinfo->stgmedData.u.hGlobal = This->post_data; 00278 pbindinfo->cbstgmedData = This->post_data_len; 00279 pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)BINDSC(This); 00280 IBindStatusCallback_AddRef(BINDSC(This)); 00281 } 00282 00283 return S_OK; 00284 } 00285 00286 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, 00287 DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) 00288 { 00289 BindStatusCallback *This = BINDSC_THIS(iface); 00290 FIXME("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); 00291 return E_NOTIMPL; 00292 } 00293 00294 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, 00295 REFIID riid, IUnknown *punk) 00296 { 00297 BindStatusCallback *This = BINDSC_THIS(iface); 00298 00299 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); 00300 00301 return dochost_object_available(This->doc_host, punk); 00302 } 00303 00304 #undef BSC_THIS 00305 00306 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { 00307 BindStatusCallback_QueryInterface, 00308 BindStatusCallback_AddRef, 00309 BindStatusCallback_Release, 00310 BindStatusCallback_OnStartBinding, 00311 BindStatusCallback_GetPriority, 00312 BindStatusCallback_OnLowResource, 00313 BindStatusCallback_OnProgress, 00314 BindStatusCallback_OnStopBinding, 00315 BindStatusCallback_GetBindInfo, 00316 BindStatusCallback_OnDataAvailable, 00317 BindStatusCallback_OnObjectAvailable 00318 }; 00319 00320 #define HTTPNEG_THIS(iface) DEFINE_THIS(BindStatusCallback, HttpNegotiate, iface) 00321 00322 static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate *iface, 00323 REFIID riid, void **ppv) 00324 { 00325 BindStatusCallback *This = HTTPNEG_THIS(iface); 00326 return IBindStatusCallback_QueryInterface(BINDSC(This), riid, ppv); 00327 } 00328 00329 static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate *iface) 00330 { 00331 BindStatusCallback *This = HTTPNEG_THIS(iface); 00332 return IBindStatusCallback_AddRef(BINDSC(This)); 00333 } 00334 00335 static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate *iface) 00336 { 00337 BindStatusCallback *This = HTTPNEG_THIS(iface); 00338 return IBindStatusCallback_Release(BINDSC(This)); 00339 } 00340 00341 static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate *iface, 00342 LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) 00343 { 00344 BindStatusCallback *This = HTTPNEG_THIS(iface); 00345 00346 TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), 00347 dwReserved, pszAdditionalHeaders); 00348 00349 if(This->headers) { 00350 int size = (strlenW(This->headers)+1)*sizeof(WCHAR); 00351 *pszAdditionalHeaders = CoTaskMemAlloc(size); 00352 memcpy(*pszAdditionalHeaders, This->headers, size); 00353 } 00354 00355 return S_OK; 00356 } 00357 00358 static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate *iface, 00359 DWORD dwResponseCode, LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, 00360 LPWSTR *pszAdditionalRequestHeaders) 00361 { 00362 BindStatusCallback *This = HTTPNEG_THIS(iface); 00363 TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), 00364 debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); 00365 return S_OK; 00366 } 00367 00368 #undef HTTPNEG_THIS 00369 00370 static const IHttpNegotiateVtbl HttpNegotiateVtbl = { 00371 HttpNegotiate_QueryInterface, 00372 HttpNegotiate_AddRef, 00373 HttpNegotiate_Release, 00374 HttpNegotiate_BeginningTransaction, 00375 HttpNegotiate_OnResponse 00376 }; 00377 00378 static BindStatusCallback *create_callback(DocHost *doc_host, LPCWSTR url, PBYTE post_data, 00379 ULONG post_data_len, LPCWSTR headers) 00380 { 00381 BindStatusCallback *ret = heap_alloc(sizeof(BindStatusCallback)); 00382 00383 ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; 00384 ret->lpHttpNegotiateVtbl = &HttpNegotiateVtbl; 00385 00386 ret->ref = 1; 00387 ret->url = heap_strdupW(url); 00388 ret->post_data = NULL; 00389 ret->post_data_len = post_data_len; 00390 ret->headers = headers ? SysAllocString(headers) : NULL; 00391 00392 ret->doc_host = doc_host; 00393 IOleClientSite_AddRef(CLIENTSITE(doc_host)); 00394 00395 if(post_data) { 00396 ret->post_data = GlobalAlloc(0, post_data_len); 00397 memcpy(ret->post_data, post_data, post_data_len); 00398 } 00399 00400 return ret; 00401 } 00402 00403 static void on_before_navigate2(DocHost *This, LPCWSTR url, SAFEARRAY *post_data, LPWSTR headers, VARIANT_BOOL *cancel) 00404 { 00405 VARIANT var_url, var_flags, var_frame_name, var_post_data, var_post_data2, var_headers; 00406 DISPPARAMS dispparams; 00407 VARIANTARG params[7]; 00408 00409 dispparams.cArgs = 7; 00410 dispparams.cNamedArgs = 0; 00411 dispparams.rgdispidNamedArgs = NULL; 00412 dispparams.rgvarg = params; 00413 00414 This->busy = VARIANT_TRUE; 00415 00416 V_VT(params) = VT_BOOL|VT_BYREF; 00417 V_BOOLREF(params) = cancel; 00418 00419 V_VT(params+1) = (VT_BYREF|VT_VARIANT); 00420 V_VARIANTREF(params+1) = &var_headers; 00421 V_VT(&var_headers) = VT_BSTR; 00422 V_BSTR(&var_headers) = headers; 00423 00424 V_VT(params+2) = (VT_BYREF|VT_VARIANT); 00425 V_VARIANTREF(params+2) = &var_post_data2; 00426 V_VT(&var_post_data2) = (VT_BYREF|VT_VARIANT); 00427 V_VARIANTREF(&var_post_data2) = &var_post_data; 00428 00429 if(post_data) { 00430 V_VT(&var_post_data) = VT_UI1|VT_ARRAY; 00431 V_ARRAY(&var_post_data) = post_data; 00432 }else { 00433 V_VT(&var_post_data) = VT_EMPTY; 00434 } 00435 00436 V_VT(params+3) = (VT_BYREF|VT_VARIANT); 00437 V_VARIANTREF(params+3) = &var_frame_name; 00438 V_VT(&var_frame_name) = VT_BSTR; 00439 V_BSTR(&var_frame_name) = NULL; 00440 00441 V_VT(params+4) = (VT_BYREF|VT_VARIANT); 00442 V_VARIANTREF(params+4) = &var_flags; 00443 V_VT(&var_flags) = VT_I4; 00444 V_I4(&var_flags) = 0; 00445 00446 V_VT(params+5) = (VT_BYREF|VT_VARIANT); 00447 V_VARIANTREF(params+5) = &var_url; 00448 V_VT(&var_url) = VT_BSTR; 00449 V_BSTR(&var_url) = SysAllocString(url); 00450 00451 V_VT(params+6) = (VT_DISPATCH); 00452 V_DISPATCH(params+6) = This->disp; 00453 00454 call_sink(This->cps.wbe2, DISPID_BEFORENAVIGATE2, &dispparams); 00455 00456 SysFreeString(V_BSTR(&var_url)); 00457 } 00458 00459 /* FIXME: urlmon should handle it */ 00460 static BOOL try_application_url(LPCWSTR url) 00461 { 00462 SHELLEXECUTEINFOW exec_info; 00463 WCHAR app[64]; 00464 HKEY hkey; 00465 DWORD res, type; 00466 HRESULT hres; 00467 00468 static const WCHAR wszURLProtocol[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0}; 00469 00470 hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, app, sizeof(app)/sizeof(WCHAR), NULL, 0); 00471 if(FAILED(hres)) 00472 return FALSE; 00473 00474 res = RegOpenKeyW(HKEY_CLASSES_ROOT, app, &hkey); 00475 if(res != ERROR_SUCCESS) 00476 return FALSE; 00477 00478 res = RegQueryValueExW(hkey, wszURLProtocol, NULL, &type, NULL, NULL); 00479 RegCloseKey(hkey); 00480 if(res != ERROR_SUCCESS || type != REG_SZ) 00481 return FALSE; 00482 00483 TRACE("openning application %s\n", debugstr_w(app)); 00484 00485 memset(&exec_info, 0, sizeof(exec_info)); 00486 exec_info.cbSize = sizeof(exec_info); 00487 exec_info.lpFile = url; 00488 exec_info.nShow = SW_SHOW; 00489 00490 return ShellExecuteExW(&exec_info); 00491 } 00492 00493 static HRESULT create_moniker(LPCWSTR url, IMoniker **mon) 00494 { 00495 WCHAR new_url[INTERNET_MAX_URL_LENGTH]; 00496 DWORD size; 00497 HRESULT hres; 00498 00499 if(PathIsURLW(url)) 00500 return CreateURLMoniker(NULL, url, mon); 00501 00502 if(url[1] == ':') { 00503 size = sizeof(new_url); 00504 hres = UrlCreateFromPathW(url, new_url, &size, 0); 00505 if(FAILED(hres)) { 00506 WARN("UrlCreateFromPathW failed: %08x\n", hres); 00507 return hres; 00508 } 00509 }else { 00510 size = sizeof(new_url)/sizeof(WCHAR); 00511 hres = UrlApplySchemeW(url, new_url, &size, URL_APPLY_GUESSSCHEME); 00512 TRACE("got %s\n", debugstr_w(new_url)); 00513 if(FAILED(hres)) { 00514 WARN("UrlApplyScheme failed: %08x\n", hres); 00515 return hres; 00516 } 00517 } 00518 00519 return CreateURLMoniker(NULL, new_url, mon); 00520 } 00521 00522 static HRESULT bind_to_object(DocHost *This, IMoniker *mon, LPCWSTR url, IBindCtx *bindctx, 00523 IBindStatusCallback *callback) 00524 { 00525 IUnknown *unk = NULL; 00526 WCHAR *display_name; 00527 HRESULT hres; 00528 00529 if(mon) { 00530 IMoniker_AddRef(mon); 00531 }else { 00532 hres = create_moniker(url, &mon); 00533 if(FAILED(hres)) 00534 return hres; 00535 } 00536 00537 hres = IMoniker_GetDisplayName(mon, 0, NULL, &display_name); 00538 if(FAILED(hres)) { 00539 FIXME("GetDisplayName failed: %08x\n", hres); 00540 return hres; 00541 } 00542 00543 hres = set_dochost_url(This, display_name); 00544 CoTaskMemFree(display_name); 00545 if(FAILED(hres)) 00546 return hres; 00547 00548 IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, 00549 (IUnknown*)CLIENTSITE(This)); 00550 00551 hres = IMoniker_BindToObject(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk); 00552 if(SUCCEEDED(hres)) { 00553 hres = S_OK; 00554 if(unk) 00555 IUnknown_Release(unk); 00556 }else if(try_application_url(url)) { 00557 hres = S_OK; 00558 }else { 00559 FIXME("BindToObject failed: %08x\n", hres); 00560 } 00561 00562 IMoniker_Release(mon); 00563 return S_OK; 00564 } 00565 00566 static void html_window_navigate(DocHost *This, IHTMLPrivateWindow *window, BSTR url, BSTR headers, SAFEARRAY *post_data) 00567 { 00568 VARIANT headers_var, post_data_var; 00569 BSTR empty_str; 00570 HRESULT hres; 00571 00572 hres = set_dochost_url(This, url); 00573 if(FAILED(hres)) 00574 return; 00575 00576 empty_str = SysAllocStringLen(NULL, 0); 00577 00578 if(headers) { 00579 V_VT(&headers_var) = VT_BSTR; 00580 V_BSTR(&headers_var) = headers; 00581 }else { 00582 V_VT(&headers_var) = VT_EMPTY; 00583 } 00584 00585 if(post_data) { 00586 V_VT(&post_data_var) = VT_UI1|VT_ARRAY; 00587 V_ARRAY(&post_data_var) = post_data; 00588 }else { 00589 V_VT(&post_data_var) = VT_EMPTY; 00590 } 00591 00592 set_doc_state(This, READYSTATE_LOADING); 00593 hres = IHTMLPrivateWindow_SuperNavigate(window, url, empty_str, NULL, NULL, &post_data_var, &headers_var, 0); 00594 SysFreeString(empty_str); 00595 if(FAILED(hres)) 00596 WARN("SuprtNavigate failed: %08x\n", hres); 00597 } 00598 00599 typedef struct { 00600 task_header_t header; 00601 BSTR url; 00602 BSTR headers; 00603 SAFEARRAY *post_data; 00604 BOOL async_notif; 00605 } task_doc_navigate_t; 00606 00607 static HRESULT free_doc_navigate_task(task_doc_navigate_t *task, BOOL free_task) 00608 { 00609 SysFreeString(task->url); 00610 SysFreeString(task->headers); 00611 if(task->post_data) 00612 SafeArrayDestroy(task->post_data); 00613 if(free_task) 00614 heap_free(task); 00615 return E_OUTOFMEMORY; 00616 } 00617 00618 static void doc_navigate_proc(DocHost *This, task_header_t *t) 00619 { 00620 task_doc_navigate_t *task = (task_doc_navigate_t*)t; 00621 IHTMLPrivateWindow *priv_window; 00622 HRESULT hres; 00623 00624 if(!This->doc_navigate) 00625 return; 00626 00627 if(task->async_notif) { 00628 VARIANT_BOOL cancel = VARIANT_FALSE; 00629 on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel); 00630 if(cancel) { 00631 TRACE("Navigation calnceled\n"); 00632 free_doc_navigate_task(task, FALSE); 00633 return; 00634 } 00635 } 00636 00637 hres = IUnknown_QueryInterface(This->doc_navigate, &IID_IHTMLPrivateWindow, (void**)&priv_window); 00638 if(SUCCEEDED(hres)) { 00639 html_window_navigate(This, priv_window, task->url, task->headers, task->post_data); 00640 IHTMLPrivateWindow_Release(priv_window); 00641 }else { 00642 WARN("Could not get IHTMLPrivateWindow iface: %08x\n", hres); 00643 } 00644 00645 free_doc_navigate_task(task, FALSE); 00646 } 00647 00648 static HRESULT async_doc_navigate(DocHost *This, LPCWSTR url, LPCWSTR headers, PBYTE post_data, ULONG post_data_size, 00649 BOOL async_notif) 00650 { 00651 task_doc_navigate_t *task; 00652 00653 task = heap_alloc_zero(sizeof(*task)); 00654 if(!task) 00655 return E_OUTOFMEMORY; 00656 00657 task->url = SysAllocString(url); 00658 if(!task->url) 00659 return free_doc_navigate_task(task, TRUE); 00660 00661 if(headers) { 00662 task->headers = SysAllocString(headers); 00663 if(!task->headers) 00664 return free_doc_navigate_task(task, TRUE); 00665 } 00666 00667 if(post_data) { 00668 task->post_data = SafeArrayCreateVector(VT_UI1, 0, post_data_size); 00669 if(!task->post_data) 00670 return free_doc_navigate_task(task, TRUE); 00671 memcpy(task->post_data->pvData, post_data, post_data_size); 00672 } 00673 00674 if(!async_notif) { 00675 VARIANT_BOOL cancel = VARIANT_FALSE; 00676 00677 on_before_navigate2(This, task->url, task->post_data, task->headers, &cancel); 00678 if(cancel) { 00679 TRACE("Navigation calnceled\n"); 00680 free_doc_navigate_task(task, TRUE); 00681 return S_OK; 00682 } 00683 } 00684 00685 task->async_notif = async_notif; 00686 push_dochost_task(This, &task->header, doc_navigate_proc, FALSE); 00687 return S_OK; 00688 } 00689 00690 static HRESULT navigate_bsc(DocHost *This, BindStatusCallback *bsc, IMoniker *mon) 00691 { 00692 VARIANT_BOOL cancel = VARIANT_FALSE; 00693 SAFEARRAY *post_data = NULL; 00694 IBindCtx *bindctx; 00695 HRESULT hres; 00696 00697 set_doc_state(This, READYSTATE_LOADING); 00698 00699 if(bsc->post_data) { 00700 post_data = SafeArrayCreateVector(VT_UI1, 0, bsc->post_data_len); 00701 memcpy(post_data->pvData, post_data, bsc->post_data_len); 00702 } 00703 00704 on_before_navigate2(This, bsc->url, post_data, bsc->headers, &cancel); 00705 if(post_data) 00706 SafeArrayDestroy(post_data); 00707 if(cancel) { 00708 FIXME("Navigation canceled\n"); 00709 return S_OK; 00710 } 00711 00712 if(This->document) 00713 deactivate_document(This); 00714 00715 CreateAsyncBindCtx(0, BINDSC(bsc), 0, &bindctx); 00716 00717 if(This->frame) 00718 IOleInPlaceFrame_EnableModeless(This->frame, FALSE); 00719 00720 hres = bind_to_object(This, mon, bsc->url, bindctx, BINDSC(bsc)); 00721 00722 if(This->frame) 00723 IOleInPlaceFrame_EnableModeless(This->frame, TRUE); 00724 00725 IBindCtx_Release(bindctx); 00726 00727 return hres; 00728 } 00729 00730 typedef struct { 00731 task_header_t header; 00732 BindStatusCallback *bsc; 00733 } task_navigate_bsc_t; 00734 00735 static void navigate_bsc_proc(DocHost *This, task_header_t *t) 00736 { 00737 task_navigate_bsc_t *task = (task_navigate_bsc_t*)t; 00738 00739 if(!This->hwnd) 00740 create_doc_view_hwnd(This); 00741 00742 navigate_bsc(This, task->bsc, NULL); 00743 00744 IBindStatusCallback_Release(BINDSC(task->bsc)); 00745 } 00746 00747 00748 HRESULT navigate_url(DocHost *This, LPCWSTR url, const VARIANT *Flags, 00749 const VARIANT *TargetFrameName, VARIANT *PostData, VARIANT *Headers) 00750 { 00751 PBYTE post_data = NULL; 00752 ULONG post_data_len = 0; 00753 LPWSTR headers = NULL; 00754 HRESULT hres = S_OK; 00755 00756 TRACE("navigating to %s\n", debugstr_w(url)); 00757 00758 if((Flags && V_VT(Flags) != VT_EMPTY) 00759 || (TargetFrameName && V_VT(TargetFrameName) != VT_EMPTY)) 00760 FIXME("Unsupported args (Flags %p:%d; TargetFrameName %p:%d)\n", 00761 Flags, Flags ? V_VT(Flags) : -1, TargetFrameName, 00762 TargetFrameName ? V_VT(TargetFrameName) : -1); 00763 00764 if(PostData && V_VT(PostData) == (VT_ARRAY | VT_UI1) && V_ARRAY(PostData)) { 00765 SafeArrayAccessData(V_ARRAY(PostData), (void**)&post_data); 00766 post_data_len = V_ARRAY(PostData)->rgsabound[0].cElements; 00767 } 00768 00769 if(Headers && V_VT(Headers) == VT_BSTR) { 00770 headers = V_BSTR(Headers); 00771 TRACE("Headers: %s\n", debugstr_w(headers)); 00772 } 00773 00774 set_doc_state(This, READYSTATE_LOADING); 00775 This->ready_state = READYSTATE_LOADING; 00776 00777 if(This->doc_navigate) { 00778 WCHAR new_url[INTERNET_MAX_URL_LENGTH]; 00779 00780 if(PathIsURLW(url)) { 00781 new_url[0] = 0; 00782 }else { 00783 DWORD size; 00784 00785 size = sizeof(new_url)/sizeof(WCHAR); 00786 hres = UrlApplySchemeW(url, new_url, &size, 00787 URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT); 00788 if(FAILED(hres)) { 00789 WARN("UrlApplyScheme failed: %08x\n", hres); 00790 new_url[0] = 0; 00791 } 00792 } 00793 00794 hres = async_doc_navigate(This, *new_url ? new_url : url, headers, post_data, 00795 post_data_len, TRUE); 00796 }else { 00797 task_navigate_bsc_t *task; 00798 00799 task = heap_alloc(sizeof(*task)); 00800 task->bsc = create_callback(This, url, post_data, post_data_len, headers); 00801 push_dochost_task(This, &task->header, navigate_bsc_proc, This->url == NULL); 00802 } 00803 00804 if(post_data) 00805 SafeArrayUnaccessData(V_ARRAY(PostData)); 00806 00807 return hres; 00808 } 00809 00810 static HRESULT navigate_hlink(DocHost *This, IMoniker *mon, IBindCtx *bindctx, 00811 IBindStatusCallback *callback) 00812 { 00813 IHttpNegotiate *http_negotiate; 00814 BindStatusCallback *bsc; 00815 PBYTE post_data = NULL; 00816 ULONG post_data_len = 0; 00817 LPWSTR headers = NULL, url; 00818 BINDINFO bindinfo; 00819 DWORD bindf = 0; 00820 HRESULT hres; 00821 00822 hres = IMoniker_GetDisplayName(mon, 0, NULL, &url); 00823 if(FAILED(hres)) 00824 FIXME("GetDisplayName failed: %08x\n", hres); 00825 00826 hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate, 00827 (void**)&http_negotiate); 00828 if(SUCCEEDED(hres)) { 00829 static const WCHAR null_string[] = {0}; 00830 00831 IHttpNegotiate_BeginningTransaction(http_negotiate, null_string, null_string, 0, 00832 &headers); 00833 IHttpNegotiate_Release(http_negotiate); 00834 } 00835 00836 memset(&bindinfo, 0, sizeof(bindinfo)); 00837 bindinfo.cbSize = sizeof(bindinfo); 00838 00839 hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo); 00840 dump_BINDINFO(&bindinfo); 00841 if(bindinfo.dwBindVerb == BINDVERB_POST) { 00842 post_data_len = bindinfo.cbstgmedData; 00843 if(post_data_len) 00844 post_data = bindinfo.stgmedData.u.hGlobal; 00845 } 00846 00847 if(This->doc_navigate) { 00848 hres = async_doc_navigate(This, url, headers, post_data, post_data_len, FALSE); 00849 }else { 00850 bsc = create_callback(This, url, post_data, post_data_len, headers); 00851 hres = navigate_bsc(This, bsc, mon); 00852 IBindStatusCallback_Release(BINDSC(bsc)); 00853 } 00854 00855 CoTaskMemFree(url); 00856 CoTaskMemFree(headers); 00857 ReleaseBindInfo(&bindinfo); 00858 00859 return hres; 00860 } 00861 00862 HRESULT go_home(DocHost *This) 00863 { 00864 HKEY hkey; 00865 DWORD res, type, size; 00866 WCHAR wszPageName[MAX_PATH]; 00867 static const WCHAR wszAboutBlank[] = {'a','b','o','u','t',':','b','l','a','n','k',0}; 00868 static const WCHAR wszStartPage[] = {'S','t','a','r','t',' ','P','a','g','e',0}; 00869 static const WCHAR wszSubKey[] = {'S','o','f','t','w','a','r','e','\\', 00870 'M','i','c','r','o','s','o','f','t','\\', 00871 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\', 00872 'M','a','i','n',0}; 00873 00874 res = RegOpenKeyW(HKEY_CURRENT_USER, wszSubKey, &hkey); 00875 if (res != ERROR_SUCCESS) 00876 return navigate_url(This, wszAboutBlank, NULL, NULL, NULL, NULL); 00877 00878 size = sizeof(wszPageName); 00879 res = RegQueryValueExW(hkey, wszStartPage, NULL, &type, (LPBYTE)wszPageName, &size); 00880 RegCloseKey(hkey); 00881 if (res != ERROR_SUCCESS || type != REG_SZ) 00882 return navigate_url(This, wszAboutBlank, NULL, NULL, NULL, NULL); 00883 00884 return navigate_url(This, wszPageName, NULL, NULL, NULL, NULL); 00885 } 00886 00887 #define HLINKFRAME_THIS(iface) DEFINE_THIS(HlinkFrame, IHlinkFrame, iface) 00888 00889 static HRESULT WINAPI HlinkFrame_QueryInterface(IHlinkFrame *iface, REFIID riid, void **ppv) 00890 { 00891 HlinkFrame *This = HLINKFRAME_THIS(iface); 00892 return IUnknown_QueryInterface(This->outer, riid, ppv); 00893 } 00894 00895 static ULONG WINAPI HlinkFrame_AddRef(IHlinkFrame *iface) 00896 { 00897 HlinkFrame *This = HLINKFRAME_THIS(iface); 00898 return IUnknown_AddRef(This->outer); 00899 } 00900 00901 static ULONG WINAPI HlinkFrame_Release(IHlinkFrame *iface) 00902 { 00903 HlinkFrame *This = HLINKFRAME_THIS(iface); 00904 return IUnknown_Release(This->outer); 00905 } 00906 00907 static HRESULT WINAPI HlinkFrame_SetBrowseContext(IHlinkFrame *iface, 00908 IHlinkBrowseContext *pihlbc) 00909 { 00910 HlinkFrame *This = HLINKFRAME_THIS(iface); 00911 FIXME("(%p)->(%p)\n", This, pihlbc); 00912 return E_NOTIMPL; 00913 } 00914 00915 static HRESULT WINAPI HlinkFrame_GetBrowseContext(IHlinkFrame *iface, 00916 IHlinkBrowseContext **ppihlbc) 00917 { 00918 HlinkFrame *This = HLINKFRAME_THIS(iface); 00919 FIXME("(%p)->(%p)\n", This, ppihlbc); 00920 return E_NOTIMPL; 00921 } 00922 00923 static HRESULT WINAPI HlinkFrame_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPBC pbc, 00924 IBindStatusCallback *pibsc, IHlink *pihlNavigate) 00925 { 00926 HlinkFrame *This = HLINKFRAME_THIS(iface); 00927 IMoniker *mon; 00928 LPWSTR location = NULL; 00929 00930 TRACE("(%p)->(%08x %p %p %p)\n", This, grfHLNF, pbc, pibsc, pihlNavigate); 00931 00932 if(grfHLNF) 00933 FIXME("unsupported grfHLNF=%08x\n", grfHLNF); 00934 00935 /* Windows calls GetTargetFrameName here. */ 00936 00937 IHlink_GetMonikerReference(pihlNavigate, 1, &mon, &location); 00938 00939 if(location) { 00940 FIXME("location = %s\n", debugstr_w(location)); 00941 CoTaskMemFree(location); 00942 } 00943 00944 /* Windows calls GetHlinkSite here */ 00945 00946 if(grfHLNF & HLNF_OPENINNEWWINDOW) { 00947 FIXME("Not supported HLNF_OPENINNEWWINDOW\n"); 00948 return E_NOTIMPL; 00949 } 00950 00951 return navigate_hlink(This->doc_host, mon, pbc, pibsc); 00952 } 00953 00954 static HRESULT WINAPI HlinkFrame_OnNavigate(IHlinkFrame *iface, DWORD grfHLNF, 00955 IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, DWORD dwreserved) 00956 { 00957 HlinkFrame *This = HLINKFRAME_THIS(iface); 00958 FIXME("(%p)->(%08x %p %s %s %d)\n", This, grfHLNF, pimkTarget, debugstr_w(pwzLocation), 00959 debugstr_w(pwzFriendlyName), dwreserved); 00960 return E_NOTIMPL; 00961 } 00962 00963 static HRESULT WINAPI HlinkFrame_UpdateHlink(IHlinkFrame *iface, ULONG uHLID, 00964 IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName) 00965 { 00966 HlinkFrame *This = HLINKFRAME_THIS(iface); 00967 FIXME("(%p)->(%u %p %s %s)\n", This, uHLID, pimkTarget, debugstr_w(pwzLocation), 00968 debugstr_w(pwzFriendlyName)); 00969 return E_NOTIMPL; 00970 } 00971 00972 #undef HLINKFRAME_THIS 00973 00974 static const IHlinkFrameVtbl HlinkFrameVtbl = { 00975 HlinkFrame_QueryInterface, 00976 HlinkFrame_AddRef, 00977 HlinkFrame_Release, 00978 HlinkFrame_SetBrowseContext, 00979 HlinkFrame_GetBrowseContext, 00980 HlinkFrame_Navigate, 00981 HlinkFrame_OnNavigate, 00982 HlinkFrame_UpdateHlink 00983 }; 00984 00985 #define TARGETFRAME2_THIS(iface) DEFINE_THIS(HlinkFrame, ITargetFrame2, iface) 00986 00987 static HRESULT WINAPI TargetFrame2_QueryInterface(ITargetFrame2 *iface, REFIID riid, void **ppv) 00988 { 00989 HlinkFrame *This = TARGETFRAME2_THIS(iface); 00990 return IUnknown_QueryInterface(This->outer, riid, ppv); 00991 } 00992 00993 static ULONG WINAPI TargetFrame2_AddRef(ITargetFrame2 *iface) 00994 { 00995 HlinkFrame *This = TARGETFRAME2_THIS(iface); 00996 return IUnknown_AddRef(This->outer); 00997 } 00998 00999 static ULONG WINAPI TargetFrame2_Release(ITargetFrame2 *iface) 01000 { 01001 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01002 return IUnknown_Release(This->outer); 01003 } 01004 01005 static HRESULT WINAPI TargetFrame2_SetFrameName(ITargetFrame2 *iface, LPCWSTR pszFrameName) 01006 { 01007 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01008 FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameName)); 01009 return E_NOTIMPL; 01010 } 01011 01012 static HRESULT WINAPI TargetFrame2_GetFrameName(ITargetFrame2 *iface, LPWSTR *ppszFrameName) 01013 { 01014 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01015 FIXME("(%p)->(%p)\n", This, ppszFrameName); 01016 return E_NOTIMPL; 01017 } 01018 01019 static HRESULT WINAPI TargetFrame2_GetParentFrame(ITargetFrame2 *iface, IUnknown **ppunkParent) 01020 { 01021 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01022 FIXME("(%p)->(%p)\n", This, ppunkParent); 01023 return E_NOTIMPL; 01024 } 01025 01026 static HRESULT WINAPI TargetFrame2_SetFrameSrc(ITargetFrame2 *iface, LPCWSTR pszFrameSrc) 01027 { 01028 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01029 FIXME("(%p)->(%s)\n", This, debugstr_w(pszFrameSrc)); 01030 return E_NOTIMPL; 01031 } 01032 01033 static HRESULT WINAPI TargetFrame2_GetFrameSrc(ITargetFrame2 *iface, LPWSTR *ppszFrameSrc) 01034 { 01035 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01036 FIXME("(%p)->()\n", This); 01037 return E_NOTIMPL; 01038 } 01039 01040 static HRESULT WINAPI TargetFrame2_GetFramesContainer(ITargetFrame2 *iface, IOleContainer **ppContainer) 01041 { 01042 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01043 FIXME("(%p)->(%p)\n", This, ppContainer); 01044 return E_NOTIMPL; 01045 } 01046 01047 static HRESULT WINAPI TargetFrame2_SetFrameOptions(ITargetFrame2 *iface, DWORD dwFlags) 01048 { 01049 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01050 FIXME("(%p)->(%x)\n", This, dwFlags); 01051 return E_NOTIMPL; 01052 } 01053 01054 static HRESULT WINAPI TargetFrame2_GetFrameOptions(ITargetFrame2 *iface, DWORD *pdwFlags) 01055 { 01056 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01057 FIXME("(%p)->(%p)\n", This, pdwFlags); 01058 return E_NOTIMPL; 01059 } 01060 01061 static HRESULT WINAPI TargetFrame2_SetFrameMargins(ITargetFrame2 *iface, DWORD dwWidth, DWORD dwHeight) 01062 { 01063 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01064 FIXME("(%p)->(%d %d)\n", This, dwWidth, dwHeight); 01065 return E_NOTIMPL; 01066 } 01067 01068 static HRESULT WINAPI TargetFrame2_GetFrameMargins(ITargetFrame2 *iface, DWORD *pdwWidth, DWORD *pdwHeight) 01069 { 01070 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01071 FIXME("(%p)->(%p %p)\n", This, pdwWidth, pdwHeight); 01072 return E_NOTIMPL; 01073 } 01074 01075 static HRESULT WINAPI TargetFrame2_FindFrame(ITargetFrame2 *iface, LPCWSTR pszTargetName, DWORD dwFlags, IUnknown **ppunkTargetFrame) 01076 { 01077 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01078 FIXME("(%p)->(%s %x %p)\n", This, debugstr_w(pszTargetName), dwFlags, ppunkTargetFrame); 01079 return E_NOTIMPL; 01080 } 01081 01082 static HRESULT WINAPI TargetFrame2_GetTargetAlias(ITargetFrame2 *iface, LPCWSTR pszTargetName, LPWSTR *ppszTargetAlias) 01083 { 01084 HlinkFrame *This = TARGETFRAME2_THIS(iface); 01085 FIXME("(%p)->(%s %p)\n", This, debugstr_w(pszTargetName), ppszTargetAlias); 01086 return E_NOTIMPL; 01087 } 01088 01089 #undef TARGETFRAME2_THIS 01090 01091 static const ITargetFrame2Vtbl TargetFrame2Vtbl = { 01092 TargetFrame2_QueryInterface, 01093 TargetFrame2_AddRef, 01094 TargetFrame2_Release, 01095 TargetFrame2_SetFrameName, 01096 TargetFrame2_GetFrameName, 01097 TargetFrame2_GetParentFrame, 01098 TargetFrame2_SetFrameSrc, 01099 TargetFrame2_GetFrameSrc, 01100 TargetFrame2_GetFramesContainer, 01101 TargetFrame2_SetFrameOptions, 01102 TargetFrame2_GetFrameOptions, 01103 TargetFrame2_SetFrameMargins, 01104 TargetFrame2_GetFrameMargins, 01105 TargetFrame2_FindFrame, 01106 TargetFrame2_GetTargetAlias 01107 }; 01108 01109 BOOL HlinkFrame_QI(HlinkFrame *This, REFIID riid, void **ppv) 01110 { 01111 if(IsEqualGUID(&IID_IHlinkFrame, riid)) { 01112 TRACE("(%p)->(IID_IHlinkFrame %p)\n", This, ppv); 01113 *ppv = HLINKFRAME(This); 01114 }else if(IsEqualGUID(&IID_ITargetFrame2, riid)) { 01115 TRACE("(%p)->(IID_ITargetFrame2 %p)\n", This, ppv); 01116 *ppv = TARGETFRAME2(This); 01117 }else { 01118 return FALSE; 01119 } 01120 01121 IUnknown_AddRef((IUnknown*)*ppv); 01122 return TRUE; 01123 } 01124 01125 void HlinkFrame_Init(HlinkFrame *This, IUnknown *outer, DocHost *doc_host) 01126 { 01127 This->lpIHlinkFrameVtbl = &HlinkFrameVtbl; 01128 This->lpITargetFrame2Vtbl = &TargetFrame2Vtbl; 01129 01130 This->outer = outer; 01131 This->doc_host = doc_host; 01132 } Generated on Sat May 26 2012 04:23:38 for ReactOS by
1.7.6.1
|