From 89c92bee630b9a1e9e98223dc4f5094e67cb411d Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Mon, 10 Aug 2009 22:30:51 +1000 Subject: [PATCH] msxml3: Support loading windows file paths. --- dlls/msxml3/main.c | 73 ++++++++++++++++++++++ dlls/msxml3/tests/domdoc.c | 124 +++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) diff --git a/dlls/msxml3/main.c b/dlls/msxml3/main.c index 358a5cb3af1..c31a53a8873 100644 --- a/dlls/msxml3/main.c +++ b/dlls/msxml3/main.c @@ -32,6 +32,7 @@ #include "msxml.h" #include "msxml2.h" +#include "wine/unicode.h" #include "wine/debug.h" #include "wine/library.h" @@ -39,6 +40,68 @@ WINE_DEFAULT_DEBUG_CHANNEL(msxml); +#ifdef HAVE_LIBXML2 + +/* Support for loading xml files from a Wine Windows drive */ +static int wineXmlMatchCallback (char const * filename) +{ + int nRet = 0; + + TRACE("%s\n", filename); + + /* + * We will deal with loading XML files from the file system + * We only care about files that linux cannot find. + * e.g. C:,D: etc + */ + if(isalpha(filename[0]) && filename[1] == ':') + nRet = 1; + + return nRet; +} + +static void *wineXmlOpenCallback (char const * filename) +{ + BSTR sFilename = bstr_from_xmlChar( (xmlChar*)filename); + HANDLE hFile; + + TRACE("%s\n", debugstr_w(sFilename)); + + hFile = CreateFileW(sFilename, GENERIC_READ,FILE_SHARE_READ, NULL, + OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL); + if(hFile == INVALID_HANDLE_VALUE) hFile = 0; + SysFreeString(sFilename); + return hFile; +} + +static int wineXmlReadCallback(void * context, char * buffer, int len) +{ + DWORD dwBytesRead; + + TRACE("%p %s %d\n", context, buffer, len); + + if ((context == NULL) || (buffer == NULL)) + return(-1); + + if(!ReadFile( context, buffer,len, &dwBytesRead, NULL)) + { + ERR("Failed to read file\n"); + return -1; + } + + TRACE("Read %d\n", dwBytesRead); + + return dwBytesRead; +} + +static int wineXmlFileCloseCallback (void * context) +{ + return CloseHandle(context) ? 0 : -1; +} + +#endif + + HRESULT WINAPI DllCanUnloadNow(void) { FIXME("\n"); @@ -96,6 +159,12 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) for this thread and as default for new threads */ xmlTreeIndentString = "\t"; xmlThrDefTreeIndentString("\t"); + + /* Register callbacks for loading XML files */ + if(xmlRegisterInputCallbacks(wineXmlMatchCallback, wineXmlOpenCallback, + wineXmlReadCallback, wineXmlFileCloseCallback) == -1) + WARN("Failed to register callbacks\n"); + #endif init_libxslt(); DisableThreadLibraryCalls(hInstDLL); @@ -110,6 +179,10 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) } #endif #ifdef HAVE_LIBXML2 + /* Restore default Callbacks */ + xmlCleanupInputCallbacks(); + xmlRegisterDefaultInputCallbacks(); + xmlCleanupParser(); #endif release_typelib(); diff --git a/dlls/msxml3/tests/domdoc.c b/dlls/msxml3/tests/domdoc.c index 0eddb38a223..2d831dd7fbd 100644 --- a/dlls/msxml3/tests/domdoc.c +++ b/dlls/msxml3/tests/domdoc.c @@ -150,6 +150,37 @@ static const CHAR szTypeValueXML[] = "" "Wine"; +static const CHAR szBasicTransformSSXMLPart1[] = +"" +"" +"\n" +"" +"" +" " +" " +" " +"
" +"
" +"" +" " +"" +"" +" " +"" +"" +" " +"" +"
"; + +static const CHAR szBasicTransformXML[] = +"Wine$25.00"; + +static const CHAR szBasicTransformOutput[] = +"
Wine$25.00
"; + static const WCHAR szNonExistentFile[] = { 'c', ':', '\\', 'N', 'o', 'n', 'e', 'x', 'i', 's', 't', 'e', 'n', 't', '.', 'x', 'm', 'l', 0 }; @@ -3952,6 +3983,98 @@ static void test_NodeTypeValue(void) free_bstrs(); } +static void test_TransformWithLoadingLocalFile(void) +{ + IXMLDOMDocument2 *doc = NULL; + IXMLDOMDocument2 *xsl = NULL; + IXMLDOMNode *pNode; + VARIANT_BOOL bSucc; + HRESULT hr; + HANDLE file; + DWORD dwWritten; + char lpPathBuffer[MAX_PATH]; + int i; + + /* Create a Temp File. */ + GetTempPathA(MAX_PATH, lpPathBuffer); + strcat(lpPathBuffer, "customers.xml" ); + + file = CreateFile(lpPathBuffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); + ok(file != INVALID_HANDLE_VALUE, "Could not create file: %u\n", GetLastError()); + if(file == INVALID_HANDLE_VALUE) + return; + + WriteFile(file, szBasicTransformXML, strlen(szBasicTransformXML), &dwWritten, NULL); + CloseHandle(file); + + /* Correct path to not include a escape character. */ + for(i=0; i < strlen(lpPathBuffer); i++) + { + if(lpPathBuffer[i] == '\\') + lpPathBuffer[i] = '/'; + } + + hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&doc ); + if( hr != S_OK ) + return; + + hr = CoCreateInstance( &CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (LPVOID*)&xsl ); + if( hr != S_OK ) + { + IXMLDOMDocument2_Release(doc); + return; + } + + hr = IXMLDOMDocument2_loadXML(doc, _bstr_(szTypeValueXML), &bSucc); + ok(hr == S_OK, "ret %08x\n", hr ); + ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n"); + if(bSucc == VARIANT_TRUE) + { + BSTR sXSL; + BSTR sPart1 = _bstr_(szBasicTransformSSXMLPart1); + BSTR sPart2 = _bstr_(szBasicTransformSSXMLPart2); + BSTR sFileName = _bstr_(lpPathBuffer); + int nLegnth = lstrlenW(sPart1) + lstrlenW(sPart2) + lstrlenW(sFileName) + 1; + + sXSL = SysAllocStringLen(NULL, nLegnth); + lstrcpyW(sXSL, sPart1); + lstrcatW(sXSL, sFileName); + lstrcatW(sXSL, sPart2); + + hr = IXMLDOMDocument2_loadXML(xsl, sXSL, &bSucc); + ok(hr == S_OK, "ret %08x\n", hr ); + ok(bSucc == VARIANT_TRUE, "Expected VARIANT_TRUE got VARIANT_FALSE\n"); + if(bSucc == VARIANT_TRUE) + { + BSTR sResult; + + hr = IXMLDOMDocument_QueryInterface(xsl, &IID_IXMLDOMNode, (LPVOID*)&pNode ); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + /* This will load the temp file via the XSL */ + hr = IXMLDOMDocument2_transformNode(doc, pNode, &sResult); + ok(hr == S_OK, "ret %08x\n", hr ); + if(hr == S_OK) + { + ok( compareIgnoreReturns( sResult, _bstr_(szBasicTransformOutput)), "Stylesheet output not correct\n"); + SysFreeString(sResult); + } + + IXMLDOMNode_Release(pNode); + } + } + + SysFreeString(sXSL); + } + + IXMLDOMDocument2_Release(doc); + IXMLDOMDocument2_Release(xsl); + + DeleteFile(lpPathBuffer); + free_bstrs(); +} + START_TEST(domdoc) { HRESULT r; @@ -3981,6 +4104,7 @@ START_TEST(domdoc) test_Namespaces(); test_FormattingXML(); test_NodeTypeValue(); + test_TransformWithLoadingLocalFile(); CoUninitialize(); }