1 /*
2  * PROJECT:     ReactOS Applications
3  * LICENSE:     LGPL - See COPYING in the top level directory
4  * FILE:        base/applications/msconfig_new/xmldomparser.cpp
5  * PURPOSE:     XML DOM Parser
6  * COPYRIGHT:   Copyright 2011-2012 Hermes BELUSCA - MAITO <hermes.belusca@sfr.fr>
7  */
8 
9 #include "precomp.h"
10 #include "xmldomparser.hpp"
11 #include "utils.h"
12 #include "stringutils.h"
13 
14 // UTF8 adapted version of ConvertStringToBSTR (see lib/sdk/comsupp/comsupp.c)
15 static BSTR
ConvertUTF8StringToBSTR(const char * pSrc)16 ConvertUTF8StringToBSTR(const char *pSrc)
17 {
18     DWORD cwch;
19     BSTR wsOut(NULL);
20 
21     if (!pSrc) return NULL;
22 
23     /* Compute the needed size with the NULL terminator */
24     cwch = MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, NULL, 0);
25     if (cwch == 0) return NULL;
26 
27     /* Allocate the BSTR (without the NULL terminator) */
28     wsOut = SysAllocStringLen(NULL, cwch - 1);
29     if (!wsOut)
30     {
31         _com_issue_error(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
32         return NULL;
33     }
34 
35     /* Convert the string */
36     if (MultiByteToWideChar(CP_UTF8, 0, pSrc, -1, wsOut, cwch) == 0)
37     {
38         /* We failed, clean everything up */
39         cwch = GetLastError();
40 
41         SysFreeString(wsOut);
42         wsOut = NULL;
43 
44         _com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
45     }
46 
47     return wsOut;
48 }
49 
50 HRESULT
InitXMLDOMParser(VOID)51 InitXMLDOMParser(VOID)
52 {
53     return CoInitialize(NULL);
54 }
55 
56 VOID
UninitXMLDOMParser(VOID)57 UninitXMLDOMParser(VOID)
58 {
59     CoUninitialize();
60     return;
61 }
62 
63 HRESULT
CreateAndInitXMLDOMDocument(IXMLDOMDocument ** ppDoc)64 CreateAndInitXMLDOMDocument(IXMLDOMDocument** ppDoc)
65 {
66     HRESULT hr = CoCreateInstance(CLSID_DOMDocument30, // __uuidof(DOMDocument30), // NOTE: Do not use DOMDocument60 if you want MSConfig working by default on XP.
67                                   NULL,
68                                   CLSCTX_INPROC_SERVER,
69                                   IID_PPV_ARG(IXMLDOMDocument, ppDoc) /* IID_PPV_ARGS(ppDoc) */);
70     if (!SUCCEEDED(hr))
71         return hr;
72 
73     /* These methods should not fail so don't inspect result */
74     (*ppDoc)->put_async(VARIANT_FALSE);
75     (*ppDoc)->put_validateOnParse(VARIANT_FALSE);
76     (*ppDoc)->put_resolveExternals(VARIANT_FALSE);
77 
78     return hr;
79 }
80 
81 BOOL
LoadXMLDocumentFromResource(IXMLDOMDocument * pDoc,LPCWSTR lpszXMLResName)82 LoadXMLDocumentFromResource(IXMLDOMDocument* pDoc,
83                             LPCWSTR lpszXMLResName)
84 {
85     VARIANT_BOOL Success = VARIANT_FALSE;
86     HRSRC   hRes;
87     HGLOBAL handle;
88     LPVOID  lpXMLRes;
89     _bstr_t bstrXMLRes;
90 
91     if (!pDoc)
92         return FALSE;
93 
94     // hRes = FindResourceExW(NULL, RT_HTML, lpszXMLResName, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL));
95     hRes = FindResourceW(NULL, lpszXMLResName, RT_HTML);
96     if (hRes == NULL)
97         return FALSE;
98 
99     handle = LoadResource(NULL, hRes);
100     if (handle == NULL)
101         return FALSE;
102 
103     lpXMLRes = LockResource(handle);
104     if (lpXMLRes == NULL)
105         goto Cleanup;
106 
107     /* Convert the resource to UNICODE if needed */
108     if (!IsTextUnicode(lpXMLRes, SizeofResource(NULL, hRes), NULL))
109         bstrXMLRes.Attach(ConvertUTF8StringToBSTR((LPCSTR)lpXMLRes));
110     else
111         bstrXMLRes = (LPCWSTR)lpXMLRes;
112 
113     if (SUCCEEDED(pDoc->loadXML(bstrXMLRes, &Success)) && (Success != VARIANT_TRUE))
114     {
115         IXMLDOMParseError* pXMLErr = NULL;
116         _bstr_t            bstrErr;
117 
118         if (SUCCEEDED(pDoc->get_parseError(&pXMLErr)) &&
119             SUCCEEDED(pXMLErr->get_reason(&bstrErr.GetBSTR())))
120         {
121             LPWSTR lpszStr = NULL;
122 
123             if (IS_INTRESOURCE((ULONG_PTR)lpszXMLResName))
124                 lpszStr = FormatString(L"Failed to load DOM from resource '#%u': %wS", lpszXMLResName, (wchar_t*)bstrErr);
125             else
126                 lpszStr = FormatString(L"Failed to load DOM from resource '%wS': %wS", lpszXMLResName, (wchar_t*)bstrErr);
127 
128             MessageBoxW(NULL, lpszStr, L"Error", MB_ICONERROR | MB_OK);
129 
130             MemFree(lpszStr);
131         }
132 
133         SAFE_RELEASE(pXMLErr);
134     }
135 
136 Cleanup:
137     FreeResource(handle);
138 
139     return (Success == VARIANT_TRUE);
140 }
141 
142 BOOL
LoadXMLDocumentFromFile(IXMLDOMDocument * pDoc,LPCWSTR lpszFilename,BOOL bIgnoreErrorsIfNonExistingFile)143 LoadXMLDocumentFromFile(IXMLDOMDocument* pDoc,
144                         LPCWSTR lpszFilename,
145                         BOOL bIgnoreErrorsIfNonExistingFile)
146 {
147     VARIANT_BOOL Success = VARIANT_FALSE;
148     _variant_t varFileName(lpszFilename);
149 
150     if (!pDoc)
151         return FALSE;
152 
153     if (SUCCEEDED(pDoc->load(varFileName, &Success)) && (Success != VARIANT_TRUE))
154     {
155         IXMLDOMParseError* pXMLErr    = NULL;
156         LONG               lErrorCode = 0L;
157 
158         if (SUCCEEDED(pDoc->get_parseError(&pXMLErr)) &&
159             SUCCEEDED(pXMLErr->get_errorCode(&lErrorCode)))
160         {
161             if ( !bIgnoreErrorsIfNonExistingFile ||
162                 ((lErrorCode != _HRESULT_TYPEDEF_(0x800C0006) /* INET_E_OBJECT_NOT_FOUND */) &&
163                  (lErrorCode != HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))) )
164             {
165                 _bstr_t bstrErr;
166 
167                 if (SUCCEEDED(pXMLErr->get_reason(&bstrErr.GetBSTR())))
168                 {
169                     LPWSTR lpszStr = FormatString(L"Failed to load DOM from '%wS': %wS", lpszFilename, (wchar_t*)bstrErr);
170                     MessageBoxW(NULL, lpszStr, L"Error", MB_ICONERROR | MB_OK);
171                     MemFree(lpszStr);
172                 }
173             }
174         }
175 
176         SAFE_RELEASE(pXMLErr);
177     }
178 
179     return (Success == VARIANT_TRUE);
180 }
181