static HRESULT find_mime_from_url(const WCHAR *url, WCHAR **ret) { const WCHAR *ptr, *end_ptr; WCHAR *ext = NULL; HRESULT hres; for(end_ptr = url; *end_ptr; end_ptr++) { if(*end_ptr == '?' || *end_ptr == '#') break; } for(ptr = end_ptr; ptr >= url; ptr--) { if(*ptr == '.') break; } if(ptr < url) return E_FAIL; if(*end_ptr) { unsigned len = end_ptr-ptr; ext = heap_alloc((len+1)*sizeof(WCHAR)); if(!ext) return E_OUTOFMEMORY; memcpy(ext, ptr, len*sizeof(WCHAR)); ext[len] = 0; } hres = find_mime_from_ext(ext ? ext : ptr, ret); heap_free(ext); return hres; }
static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE *dwReserved) { FileProtocol *This = impl_from_IInternetProtocolEx(iface); WCHAR path[MAX_PATH], *ptr; LARGE_INTEGER file_size; HANDLE file_handle; BINDINFO bindinfo; DWORD grfBINDF = 0; DWORD scheme, size; LPWSTR mime = NULL; WCHAR null_char = 0; BSTR ext; HRESULT hres; TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink, pOIBindInfo, grfPI, dwReserved); if(!pUri) return E_INVALIDARG; scheme = 0; hres = IUri_GetScheme(pUri, &scheme); if(FAILED(hres)) return hres; if(scheme != URL_SCHEME_FILE) 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); if(!(grfBINDF & BINDF_FROMURLMON)) IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL); if(This->file != INVALID_HANDLE_VALUE) { IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION, This->size, This->size); return S_OK; } IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char); size = 0; hres = CoInternetParseIUri(pUri, PARSE_PATH_FROM_URL, 0, path, sizeof(path)/sizeof(WCHAR), &size, 0); if(FAILED(hres)) { WARN("CoInternetParseIUri failed: %08x\n", hres); return report_result(pOIProtSink, hres, 0); } file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(file_handle == INVALID_HANDLE_VALUE && (ptr = strrchrW(path, '#'))) { /* If path contains fragment part, try without it. */ *ptr = 0; file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } if(file_handle == INVALID_HANDLE_VALUE) return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError()); if(!GetFileSizeEx(file_handle, &file_size)) { CloseHandle(file_handle); return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, GetLastError()); } This->file = file_handle; This->size = file_size.u.LowPart; IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_CACHEFILENAMEAVAILABLE, path); hres = IUri_GetExtension(pUri, &ext); if(SUCCEEDED(hres)) { if(hres == S_OK && *ext) { if((ptr = strchrW(ext, '#'))) *ptr = 0; hres = find_mime_from_ext(ext, &mime); if(SUCCEEDED(hres)) { IInternetProtocolSink_ReportProgress(pOIProtSink, (grfBINDF & BINDF_FROMURLMON) ? BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE, mime); CoTaskMemFree(mime); } } SysFreeString(ext); } IInternetProtocolSink_ReportData(pOIProtSink, BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION, This->size, This->size); return report_result(pOIProtSink, S_OK, 0); }