/* FIXME: urlmon should handle it */ static BOOL try_application_url(LPCWSTR url) { SHELLEXECUTEINFOW exec_info; WCHAR app[64]; HKEY hkey; DWORD res, type; HRESULT hres; static const WCHAR wszURLProtocol[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0}; hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, app, sizeof(app)/sizeof(WCHAR), NULL, 0); if(FAILED(hres)) return FALSE; res = RegOpenKeyW(HKEY_CLASSES_ROOT, app, &hkey); if(res != ERROR_SUCCESS) return FALSE; res = RegQueryValueExW(hkey, wszURLProtocol, NULL, &type, NULL, NULL); RegCloseKey(hkey); if(res != ERROR_SUCCESS || type != REG_SZ) return FALSE; TRACE("openning application %s\n", debugstr_w(app)); memset(&exec_info, 0, sizeof(exec_info)); exec_info.cbSize = sizeof(exec_info); exec_info.lpFile = url; exec_info.nShow = SW_SHOW; return ShellExecuteExW(&exec_info); }
/****************************************************************************** * URLMoniker_Construct (local function) *******************************************************************************/ static HRESULT URLMonikerImpl_Construct(URLMonikerImpl* This, LPCOLESTR lpszLeftURLName, LPCOLESTR lpszURLName) { HRESULT hres; DWORD sizeStr = 0; TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszLeftURLName),debugstr_w(lpszURLName)); This->lpvtbl = &VT_URLMonikerImpl; This->ref = 0; This->URLName = heap_alloc(INTERNET_MAX_URL_LENGTH*sizeof(WCHAR)); if(lpszLeftURLName) hres = CoInternetCombineUrl(lpszLeftURLName, lpszURLName, URL_FILE_USE_PATHURL, This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0); else hres = CoInternetParseUrl(lpszURLName, PARSE_CANONICALIZE, URL_FILE_USE_PATHURL, This->URLName, INTERNET_MAX_URL_LENGTH, &sizeStr, 0); if(FAILED(hres)) { heap_free(This->URLName); return hres; } URLMON_LockModule(); if(sizeStr != INTERNET_MAX_URL_LENGTH) This->URLName = heap_realloc(This->URLName, (sizeStr+1)*sizeof(WCHAR)); TRACE("URLName = %s\n", debugstr_w(This->URLName)); return S_OK; }
BOOL is_registered_protocol(LPCWSTR url) { DWORD schema_len; WCHAR schema[64]; HRESULT hres; hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), &schema_len, 0); if(FAILED(hres)) return FALSE; return get_protocol_cf(schema, schema_len, NULL, NULL) == S_OK; }
static HRESULT bind_to_object(DocHost *This, IMoniker *mon, LPCWSTR url, IBindCtx *bindctx, IBindStatusCallback *callback) { WCHAR schema[30]; DWORD schema_len; HRESULT hres; static const WCHAR httpW[] = {'h','t','t','p',0}; static const WCHAR httpsW[] = {'h','t','t','p','s',0}; static const WCHAR ftpW[]= {'f','t','p',0}; if(mon) { IMoniker_AddRef(mon); }else { hres = create_moniker(url, &mon); if(FAILED(hres)) return hres; } CoTaskMemFree(This->url); hres = IMoniker_GetDisplayName(mon, 0, NULL, &This->url); if(FAILED(hres)) FIXME("GetDisplayName failed: %08x\n", hres); IBindCtx_RegisterObjectParam(bindctx, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, (IUnknown*)CLIENTSITE(This)); hres = CoInternetParseUrl(This->url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), &schema_len, 0); if(SUCCEEDED(hres) && (!strcmpW(schema, httpW) || !strcmpW(schema, httpsW) || !strcmpW(schema, ftpW))) { hres = http_load_hack(This, mon, callback, bindctx); }else { IUnknown *unk = NULL; hres = IMoniker_BindToObject(mon, bindctx, NULL, &IID_IUnknown, (void**)&unk); if(SUCCEEDED(hres)) { hres = S_OK; if(unk) IUnknown_Release(unk); }else if(try_application_url(url)) { hres = S_OK; }else { FIXME("BindToObject failed: %08x\n", hres); } } IMoniker_Release(mon); return S_OK; }
static HRESULT WINAPI UniformResourceLocatorW_InvokeCommand(IUniformResourceLocatorW *url, PURLINVOKECOMMANDINFOW pCommandInfo) { InternetShortcut *This = impl_from_IUniformResourceLocatorW(url); WCHAR app[64]; HKEY hkey; static const WCHAR wszURLProtocol[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0}; SHELLEXECUTEINFOW sei; DWORD res, type; HRESULT hres; TRACE("%p %p\n", This, pCommandInfo ); if (pCommandInfo->dwcbSize < sizeof (URLINVOKECOMMANDINFOW)) return E_INVALIDARG; if (pCommandInfo->dwFlags != IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB) { FIXME("(%p, %p): non-default verbs not implemented\n", url, pCommandInfo); return E_NOTIMPL; } hres = CoInternetParseUrl(This->url, PARSE_SCHEMA, 0, app, sizeof(app)/sizeof(WCHAR), NULL, 0); if(FAILED(hres)) return E_FAIL; res = RegOpenKeyW(HKEY_CLASSES_ROOT, app, &hkey); if(res != ERROR_SUCCESS) return E_FAIL; res = RegQueryValueExW(hkey, wszURLProtocol, NULL, &type, NULL, NULL); RegCloseKey(hkey); if(res != ERROR_SUCCESS || type != REG_SZ) return E_FAIL; memset(&sei, 0, sizeof(sei)); sei.cbSize = sizeof(sei); sei.lpFile = This->url; sei.nShow = SW_SHOW; if( ShellExecuteExW(&sei) ) return S_OK; else return E_FAIL; }
IInternetProtocolInfo *get_protocol_info(LPCWSTR url) { IInternetProtocolInfo *ret = NULL; IClassFactory *cf; name_space *ns; WCHAR schema[64]; DWORD schema_len; HRESULT hres; hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(schema[0]), &schema_len, 0); if(FAILED(hres) || !schema_len) return NULL; EnterCriticalSection(&session_cs); ns = find_name_space(schema); if(ns && !ns->urlmon) { hres = IClassFactory_QueryInterface(ns->cf, &IID_IInternetProtocolInfo, (void**)&ret); if(FAILED(hres)) hres = IClassFactory_CreateInstance(ns->cf, NULL, &IID_IInternetProtocolInfo, (void**)&ret); } LeaveCriticalSection(&session_cs); if(ns && SUCCEEDED(hres)) return ret; hres = get_protocol_cf(schema, schema_len, NULL, &cf); if(FAILED(hres)) return NULL; hres = IClassFactory_QueryInterface(cf, &IID_IInternetProtocolInfo, (void**)&ret); if(FAILED(hres)) IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocolInfo, (void**)&ret); IClassFactory_Release(cf); return ret; }
HRESULT OpenURL(HWND hWnd) { HRESULT hr = S_OK; INT_PTR ret = DialogBox(hInst, MAKEINTRESOURCE(IDD_OPENURL), hWnd, OpenURLDlgProc); if (LOWORD(ret) == IDCANCEL) { return E_FAIL; } InvalidateRect(hWnd, NULL, TRUE); WCHAR wcDomain[MAX_URL_LENGTH] = {0}; DWORD cchDecodeUrl = 0; CoInternetParseUrl(g_wcURL, PARSE_DOMAIN, 0, wcDomain, MAX_URL_LENGTH, &cchDecodeUrl, 0); //int nbytes = WideCharToMultiByte(0, 0, g_szURL, nLength, NULL, 0, NULL, NULL); ZeroMemory(g_acURL, MAX_URL_LENGTH); WideCharToMultiByte(0, 0, g_wcURL, wcslen(g_wcURL), g_acURL, wcslen(g_wcURL), NULL, NULL); ZeroMemory(g_acDomain, MAX_URL_LENGTH); //nbytes = WideCharToMultiByte(0, 0, szDomain, wcslen(szDomain), NULL, 0, NULL, NULL); WideCharToMultiByte(0, 0, wcDomain, wcslen(wcDomain), g_acDomain, wcslen(wcDomain), NULL, NULL); char sendBuff[DEFAULT_BUFFER_LENGTH] = {0}; sprintf_s(sendBuff, DEFAULT_BUFFER_LENGTH, "HEAD %s HTTP/1.1\r\n" \ "Host: %s\r\n" \ "Proxy-Connection: keep-alive\r\n" \ "Proxy-Authorization: Basic ***********\r\n" \ "Accept: */*\r\n" \ "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36\r\n\r\n", strstr(g_acURL, g_acDomain)+strlen(g_acDomain), g_acDomain); int iResult = 0; ADDRINFOW* result = NULL; ADDRINFOW* ptr = NULL; ADDRINFOW hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; WCHAR* strProxyURL = L"test.proxy.com"; WCHAR* strProxyPort = L"8080"; iResult = GetAddrInfo(strProxyURL, strProxyPort, &hints, &result); if (iResult != 0) { ICSE_OUTPUTDEBUGSTRING_W(L"getaddrinfo failed: %d", iResult); return E_FAIL; } SOCKET connectSocket = INVALID_SOCKET; ptr = result; connectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (connectSocket == INVALID_SOCKET) { ICSE_OUTPUTDEBUGSTRING_W(L"socket failed: %ld\n", WSAGetLastError()); FreeAddrInfo(result); return E_FAIL; } int value = 0; int size = sizeof(value); iResult = getsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&value, &size); iResult = connect(connectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); FreeAddrInfo(result); if (iResult == SOCKET_ERROR) { ICSE_OUTPUTDEBUGSTRING_W(L"connect failed: %d", iResult); closesocket(connectSocket); return E_FAIL; } char recvBuff[DEFAULT_BUFFER_LENGTH] = {0}; iResult = send(connectSocket, sendBuff, (int)strlen(sendBuff), 0); if (iResult == SOCKET_ERROR) { ICSE_OUTPUTDEBUGSTRING_W(L"send failed: %d", WSAGetLastError()); closesocket(connectSocket); return E_FAIL; } iResult = shutdown(connectSocket, SD_SEND); if (iResult == SOCKET_ERROR) { ICSE_OUTPUTDEBUGSTRING_W(L"shutdown failed %d", WSAGetLastError()); closesocket(connectSocket); return E_FAIL; } CStringA strHeader(""); do { iResult = recv(connectSocket, recvBuff, DEFAULT_BUFFER_LENGTH, 0); if (iResult > 0) { strHeader += recvBuff; } else if (iResult == 0) { ICSE_OUTPUTDEBUGSTRING_W(L"Connection closed"); } else { ICSE_OUTPUTDEBUGSTRING_W(L"recv failed %d", WSAGetLastError()); } } while (iResult > 0); if (strHeader.GetLength() > 0) { int begin = strHeader.Find("Content-Length: "); int end = strHeader.Find("\r\n", begin); CStringA strLength = strHeader.Mid(begin + 16, end - begin - 16); __int64 length = _atoi64(strLength); ICSE_OUTPUTDEBUGSTRING_W(L"content length: %I64d", length); HANDLE hFile = ::CreateFile(g_wcFile, GENERIC_READ|GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); DWORD dwTemp = 0; ::DeviceIoControl(hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL); CloseHandle(hFile); __int64 segmentLength = length / g_factor; for (int i = 0; i < g_factor; i++) { g_segmentMatrix[i][0] = i * segmentLength; g_segmentMatrix[i][1] = g_segmentMatrix[i][0] + segmentLength - 1; length -= segmentLength; } g_segmentMatrix[g_factor-1][1] += length; for (int i = 0; i < g_factor; i++) { _beginthread(ThreadProc, 0, (void*)i); } } closesocket(connectSocket); return hr; }
void ThreadProc(void* param) { int index = (int)param; ICSE_OUTPUTDEBUGSTRING_W(L"[%d][%I64d:%I64d]", index, g_segmentMatrix[index][0], g_segmentMatrix[index][1]); __int64 begin = 0; __int64 end = g_segmentMatrix[index][0] - 1; __int64 backup = end; __int64 writeSize = 0LL; LOOP: int iResult = 0; ADDRINFOW* result = NULL; ADDRINFOW* ptr = NULL; ADDRINFOW hints; ZeroMemory(&hints, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; WCHAR szDomain[MAX_URL_LENGTH] = {0}; DWORD cchDecodeUrl = 0; CoInternetParseUrl(g_wcURL, PARSE_DOMAIN, 0, szDomain, MAX_URL_LENGTH, &cchDecodeUrl, 0); WCHAR* strProxyURL = L"test.proxy.com"; WCHAR* strProxyPort = L"8080"; iResult = GetAddrInfo(strProxyURL, strProxyPort, &hints, &result); if (iResult != 0) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]getaddrinfo failed: %d", index, iResult); } SOCKET connectSocket = INVALID_SOCKET; ptr = result; connectSocket = socket(ptr->ai_family, ptr->ai_socktype, ptr->ai_protocol); if (connectSocket == INVALID_SOCKET) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]socket failed: %ld\n", index, WSAGetLastError()); FreeAddrInfo(result); } int value = 0; int size = sizeof(value); iResult = getsockopt(connectSocket, SOL_SOCKET, SO_RCVBUF, (char*)&value, &size); iResult = connect(connectSocket, ptr->ai_addr, (int)ptr->ai_addrlen); FreeAddrInfo(result); if (iResult == SOCKET_ERROR) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]connect failed: %d", index, iResult); closesocket(connectSocket); } do { begin = end + 1; end = ((begin + 32767) > g_segmentMatrix[index][1] ? g_segmentMatrix[index][1] : (begin + 32767)); char sendBuff[DEFAULT_BUFFER_LENGTH] = {0}; sprintf_s(sendBuff, DEFAULT_BUFFER_LENGTH, "GET %s HTTP/1.1\r\n" \ "Host: %s\r\n" \ "Proxy-Connection: keep-alive\r\n" \ "Proxy-Authorization: Basic ***********\r\n" \ "Accept: */*\r\n" \ "Range: bytes=%I64d-%I64d\r\n" "User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36\r\n\r\n", strstr(g_acURL, g_acDomain)+strlen(g_acDomain), g_acDomain, begin, end); iResult = send(connectSocket, sendBuff, (int)strlen(sendBuff), 0); if (iResult == SOCKET_ERROR) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]send failed: %d", index, WSAGetLastError()); closesocket(connectSocket); } char recvBuff[DEFAULT_BUFFER_LENGTH * 33] = {0}; int recvLength = 0; char* dataAddress = NULL; bool bRecvSucess = false; do { iResult = recv(connectSocket, recvBuff + recvLength, DEFAULT_BUFFER_LENGTH * 33 - recvLength, 0); if (iResult > 0) { recvLength += iResult; ICSE_OUTPUTDEBUGSTRING_W(L"[%d]recv length %d", index, iResult); dataAddress = StrStrA(recvBuff, "\r\n\r\n") + 4; if ((recvLength - (dataAddress - recvBuff)) == (int)(end - begin + 1)) { bRecvSucess = true; break; } } else if (iResult == 0) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]Connection closed", index); } else { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]recv failed %d", index, WSAGetLastError()); } } while (iResult > 0); if (bRecvSucess) { HANDLE hFile = CreateFile(g_wcFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == NULL) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]file open failed %d", index, GetLastError()); break; } LONG llow = (LONG)(begin & 0x0FFFFFFFF); LONG lhigh = (LONG)((begin & 0xFFFFFFFF00000000)>>32); DWORD dwPrt = SetFilePointer(hFile, llow, &lhigh, FILE_BEGIN); if (dwPrt == INVALID_SET_FILE_POINTER) { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]move pointer failed %d", index, GetLastError()); break; } DWORD dwSize = 0; WriteFile(hFile, dataAddress, (int)(end - begin + 1), &dwSize, NULL); CloseHandle(hFile); backup = end; writeSize += (__int64)dwSize; g_segmentMatrix[index][2] =writeSize; InvalidateRect(g_hWndMain, NULL, TRUE); } else { ICSE_OUTPUTDEBUGSTRING_W(L"[%d]recv error! %d", index, recvLength); closesocket(connectSocket); end = backup; goto LOOP; } } while (end < g_segmentMatrix[index][1]);
static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url) { LPWSTR secur_url; WCHAR schema[64]; DWORD size=0; HRESULT hres; *zone = URLZONE_INVALID; hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0); if(hres != S_OK) { size = strlenW(url)*sizeof(WCHAR); secur_url = heap_alloc(size); if(!secur_url) return E_OUTOFMEMORY; memcpy(secur_url, url, size); } hres = CoInternetParseUrl(secur_url, PARSE_SCHEMA, 0, schema, sizeof(schema)/sizeof(WCHAR), &size, 0); if(FAILED(hres) || !*schema) { heap_free(secur_url); return E_INVALIDARG; } /* file protocol is a special case */ if(!strcmpW(schema, fileW)) { WCHAR path[MAX_PATH], root[20]; WCHAR *ptr; hres = CoInternetParseUrl(secur_url, PARSE_PATH_FROM_URL, 0, path, sizeof(path)/sizeof(WCHAR), &size, 0); if(SUCCEEDED(hres) && (ptr = strchrW(path, '\\')) && ptr-path < sizeof(root)/sizeof(WCHAR)) { UINT type; memcpy(root, path, (ptr-path)*sizeof(WCHAR)); root[ptr-path] = 0; type = GetDriveTypeW(root); switch(type) { case DRIVE_UNKNOWN: case DRIVE_NO_ROOT_DIR: break; case DRIVE_REMOVABLE: case DRIVE_FIXED: case DRIVE_CDROM: case DRIVE_RAMDISK: *zone = URLZONE_LOCAL_MACHINE; hres = S_OK; break; case DRIVE_REMOTE: *zone = URLZONE_INTERNET; hres = S_OK; break; default: FIXME("unsupported drive type %d\n", type); } } } if(*zone == URLZONE_INVALID) { WARN("domains are not yet implemented\n"); hres = get_zone_from_reg(schema, zone); } if(FAILED(hres) || !ret_url) heap_free(secur_url); else *ret_url = secur_url; return hres; }
static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { FileProtocol *This = PROTOCOL_THIS(iface); BINDINFO bindinfo; DWORD grfBINDF = 0; LARGE_INTEGER size; DWORD len; LPWSTR url, mime = NULL, file_name; WCHAR null_char = 0; BOOL first_call = FALSE; HRESULT hres; static const WCHAR wszFile[] = {'f','i','l','e',':'}; TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); if(!szUrl || strlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR) || memcmp(szUrl, wszFile, sizeof(wszFile))) return E_INVALIDARG; memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); if(FAILED(hres)) { WARN("GetBindInfo failed: %08x\n", hres); return hres; } ReleaseBindInfo(&bindinfo); len = lstrlenW(szUrl)+16; url = heap_alloc(len*sizeof(WCHAR)); hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0); if(FAILED(hres)) { heap_free(url); return hres; } if(!(grfBINDF & BINDF_FROMURLMON)) IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL); if(!This->file) { WCHAR *ptr; first_call = TRUE; IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char); file_name = url+sizeof(wszFile)/sizeof(WCHAR); /* Strip both forward and back slashes */ if( (file_name[0] == '/' && file_name[1] == '/') || (file_name[0] == '\\' && file_name[1] == '\\')) file_name += 2; if(*file_name == '/') file_name++; for(ptr = file_name; *ptr; ptr++) { if(*ptr == '?' || *ptr == '#') { *ptr = 0; break; } } if(file_name[1] == '|') file_name[1] = ':'; This->file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(This->file == INVALID_HANDLE_VALUE) { This->file = NULL; IInternetProtocolSink_ReportResult(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError(), NULL); heap_free(url); return INET_E_RESOURCE_NOT_FOUND; } IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_CACHEFILENAMEAVAILABLE, file_name); hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, (grfBINDF & BINDF_FROMURLMON) ? BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } } heap_free(url); if(GetFileSizeEx(This->file, &size)) IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION, size.u.LowPart, size.u.LowPart); if(first_call) IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); return S_OK; }
static HRESULT WINAPI ResProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, IInternetProtocolSink* pOIProtSink, IInternetBindInfo* pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) { ResProtocol *This = ResProtocol_from_IInternetProtocol(iface); WCHAR *url_dll, *url_file, *url, *mime, *res_type = (LPWSTR)RT_HTML, *ptr; DWORD grfBINDF = 0, len; BINDINFO bindinfo; HMODULE hdll; HRSRC src; HRESULT hres; static const WCHAR wszRes[] = {'r','e','s',':','/','/'}; TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); memset(&bindinfo, 0, sizeof(bindinfo)); bindinfo.cbSize = sizeof(BINDINFO); hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &grfBINDF, &bindinfo); if(FAILED(hres)) return hres; ReleaseBindInfo(&bindinfo); len = strlenW(szUrl)+16; url = heap_alloc(len*sizeof(WCHAR)); hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0); if(FAILED(hres)) { WARN("CoInternetParseUrl failed: %08x\n", hres); heap_free(url); IInternetProtocolSink_ReportResult(pOIProtSink, hres, 0, NULL); return hres; } if(len < sizeof(wszRes)/sizeof(wszRes[0]) || memcmp(url, wszRes, sizeof(wszRes))) { WARN("Wrong protocol of url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, E_INVALIDARG, 0, NULL); heap_free(url); return E_INVALIDARG; } url_dll = url + sizeof(wszRes)/sizeof(wszRes[0]); if(!(res_type = strchrW(url_dll, '/'))) { WARN("wrong url: %s\n", debugstr_w(url)); IInternetProtocolSink_ReportResult(pOIProtSink, MK_E_SYNTAX, 0, NULL); heap_free(url); return MK_E_SYNTAX; } *res_type++ = 0; if ((url_file = strchrW(res_type, '/'))) { *url_file++ = 0; }else { url_file = res_type; res_type = MAKEINTRESOURCEW(RT_HTML); } /* Ignore query and hash parts. */ if((ptr = strchrW(url_file, '?'))) *ptr = 0; if((ptr = strchrW(url_file, '#'))) *ptr = 0; hdll = LoadLibraryExW(url_dll, NULL, LOAD_LIBRARY_AS_DATAFILE); if(!hdll) { WARN("Could not open dll: %s\n", debugstr_w(url_dll)); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } TRACE("trying to find resource type %s, name %s\n", debugstr_w(res_type), debugstr_w(url_file)); src = FindResourceW(hdll, url_file, res_type); if(!src) { LPWSTR endpoint = NULL; DWORD file_id = strtolW(url_file, &endpoint, 10); if(endpoint == url_file+strlenW(url_file)) src = FindResourceW(hdll, MAKEINTRESOURCEW(file_id), res_type); if(!src) { WARN("Could not find resource\n"); IInternetProtocolSink_ReportResult(pOIProtSink, HRESULT_FROM_WIN32(GetLastError()), 0, NULL); heap_free(url); return HRESULT_FROM_WIN32(GetLastError()); } } if(This->data) { WARN("data already loaded\n"); heap_free(This->data); } This->data_len = SizeofResource(hdll, src); This->data = heap_alloc(This->data_len); memcpy(This->data, LoadResource(hdll, src), This->data_len); This->cur = 0; FreeLibrary(hdll); hres = FindMimeFromData(NULL, url_file, This->data, This->data_len, NULL, 0, &mime, 0); heap_free(url); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION | BSCF_DATAFULLYAVAILABLE, This->data_len, This->data_len); IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL); return S_OK; }
static NPError _OpenURL(NPP npp, const char *szURL, const char *szTarget, void *pNotifyData, const char *pData, uint32 len, NPBool isFile) { if (!npp) { return NPERR_INVALID_INSTANCE_ERROR; } void *postData = NULL; uint32 postDataLen = 0; if (pData) { if (!isFile) { postData = (void *) pData; postDataLen = len; } else { // TODO read the file specified in the postdata param into memory } } nsPluginHostWnd *pWnd = (nsPluginHostWnd *) npp->ndata; ATLASSERT(pWnd); // Other window targets if (szTarget) { CComPtr<IWebBrowserApp> cpBrowser; pWnd->GetWebBrowserApp(&cpBrowser); if (!cpBrowser) { return NPERR_GENERIC_ERROR; } CComBSTR url(szURL); HRESULT hr; // Test if the input URL has a schema which means it's relative, // otherwise consider it to be relative to the current URL WCHAR szSchema[10]; const DWORD cbSchema = sizeof(szSchema) / sizeof(szSchema[0]); DWORD cbSchemaUsed = 0; memset(szSchema, 0, cbSchema); hr = CoInternetParseUrl(url.m_str, PARSE_SCHEMA, 0, szSchema, cbSchema, &cbSchemaUsed, 0); if (hr != S_OK || cbSchemaUsed == 0) { // Convert relative URLs to absolute, so that they can be loaded // by the Browser CComBSTR bstrCurrentURL; cpBrowser->get_LocationURL(&bstrCurrentURL); if (bstrCurrentURL.Length()) { USES_CONVERSION; DWORD cbNewURL = (url.Length() + bstrCurrentURL.Length() + 1) * sizeof(WCHAR); DWORD cbNewURLUsed = 0; WCHAR *pszNewURL = (WCHAR *) calloc(cbNewURL, 1); ATLASSERT(pszNewURL); CoInternetCombineUrl( bstrCurrentURL.m_str, url.m_str, 0, pszNewURL, cbNewURL, &cbNewURLUsed, 0); ATLASSERT(cbNewURLUsed < cbNewURL); url = pszNewURL; free(pszNewURL); } } CComVariant vFlags; CComVariant vTarget(szTarget); CComVariant vPostData; CComVariant vHeaders; // Initialise postdata if (postData) { // According to the documentation. // The post data specified by PostData is passed as a SAFEARRAY // structure. The variant should be of type VT_ARRAY and point to // a SAFEARRAY. The SAFEARRAY should be of element type VT_UI1, // dimension one, and have an element count equal to the number of // bytes of post data. SAFEARRAYBOUND saBound[1]; saBound[0].lLbound = 0; saBound[0].cElements = len; vPostData.vt = VT_ARRAY | VT_UI1; vPostData.parray = SafeArrayCreate(VT_UI1, 1, saBound); SafeArrayLock(vPostData.parray); memcpy(vPostData.parray->pvData, postData, postDataLen); SafeArrayUnlock(vPostData.parray); } cpBrowser->Navigate(url, &vFlags, &vTarget, &vPostData, &vHeaders); // TODO listen to navigation & send a URL notify to plugin when completed return NPERR_NO_ERROR; } USES_CONVERSION; HRESULT hr = pWnd->OpenURLStream(A2CT(szURL), pNotifyData, postData, postDataLen); return SUCCEEDED(hr) ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR; }