1
- // Copyright (c) Microsoft Corporation and Contributors.
1
+ // Copyright (c) Microsoft Corporation and Contributors.
2
2
// Licensed under the MIT License.
3
3
4
4
#include < pch.h>
5
5
6
6
#include " catalog.h"
7
+ #include " Microsoft.Utf8.h"
7
8
#include " TypeResolution.h"
8
9
9
10
#include < activation.h>
@@ -125,11 +126,26 @@ HRESULT LoadFromEmbeddedManifest(PCWSTR path)
125
126
126
127
HRESULT WinRTLoadComponentFromFilePath (PCWSTR manifestPath)
127
128
{
128
- ComPtr<IStream> fileStream;
129
- RETURN_IF_FAILED (SHCreateStreamOnFileEx (manifestPath, STGM_READ, FILE_ATTRIBUTE_NORMAL, FALSE , nullptr , &fileStream));
130
129
try
131
130
{
132
- return ParseRootManifestFromXmlReaderInput (fileStream.Get ());
131
+ wil::unique_hfile file{ ::CreateFileW (manifestPath, GENERIC_READ, FILE_SHARE_READ, nullptr , OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, nullptr ) };
132
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (GetLastError ()), !file);
133
+
134
+ LARGE_INTEGER fileSize{};
135
+ RETURN_IF_WIN32_BOOL_FALSE (::GetFileSizeEx (file.get (), &fileSize));
136
+ const auto dataSize{ fileSize.QuadPart };
137
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (ERROR_INVALID_DATA), dataSize > INT32_MAX);
138
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (ERROR_SXS_XML_E_UNEXPECTEDEOF), dataSize == 0 );
139
+
140
+ const auto bufferSize{ static_cast <DWORD>(dataSize) + 1 };
141
+ std::unique_ptr<char []> buffer{ std::make_unique<char []>(bufferSize) };
142
+
143
+ DWORD bytesRead{};
144
+ RETURN_IF_WIN32_BOOL_FALSE (::ReadFile (file.get (), buffer.get (), bufferSize, &bytesRead, nullptr ));
145
+ file.reset ();
146
+ buffer[bytesRead] = ' \0 ' ;
147
+
148
+ return WinRTLoadComponentFromString (std::string_view (buffer.get (), bytesRead));
133
149
}
134
150
catch (...)
135
151
{
@@ -140,16 +156,23 @@ HRESULT WinRTLoadComponentFromFilePath(PCWSTR manifestPath)
140
156
141
157
HRESULT WinRTLoadComponentFromString (std::string_view xmlStringValue)
142
158
{
143
- ComPtr<IStream> xmlStream;
144
- auto xmlStringValueData{ xmlStringValue.data () };
145
- auto xmlStringValueDataLength{ strlen (xmlStringValueData) };
146
- auto xmlStringValueDataSize{ xmlStringValueDataLength * sizeof (*xmlStringValueData) };
147
- xmlStream.Attach (SHCreateMemStream (reinterpret_cast <const BYTE*>(xmlStringValue.data ()), static_cast <UINT>(xmlStringValueDataSize)));
148
- RETURN_HR_IF_NULL (E_OUTOFMEMORY, xmlStream);
149
- ComPtr<IXmlReaderInput> xmlReaderInput;
150
- RETURN_IF_FAILED (CreateXmlReaderInputWithEncodingName (xmlStream.Get (), nullptr , L" utf-8" , FALSE , nullptr , &xmlReaderInput));
151
159
try
152
160
{
161
+ auto wideXmlString = ::Microsoft::Utf8::ToUtf16 (xmlStringValue.data ());
162
+
163
+ // Expand any env vars, such as %MICROSOFT_WINDOWSAPPRUNTIME_BASE_DIRECTORY% in asmv3:file.loadFrom
164
+ auto expandedSize = ExpandEnvironmentStringsW (wideXmlString.data (), nullptr , 0 );
165
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (GetLastError ()), expandedSize == 0 );
166
+ std::unique_ptr<WCHAR[]> expanded{ std::make_unique<WCHAR[]>(expandedSize) };
167
+ expandedSize = ExpandEnvironmentStringsW (wideXmlString.data (), expanded.get (), expandedSize);
168
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (GetLastError ()), expandedSize == 0 );
169
+
170
+ ComPtr<IStream> xmlStream;
171
+ xmlStream.Attach (SHCreateMemStream (reinterpret_cast <const BYTE*>(expanded.get ()), static_cast <UINT>(expandedSize * sizeof (WCHAR))));
172
+ RETURN_HR_IF_NULL (E_OUTOFMEMORY, xmlStream);
173
+ ComPtr<IXmlReaderInput> xmlReaderInput;
174
+ RETURN_IF_FAILED (CreateXmlReaderInputWithEncodingName (xmlStream.Get (), nullptr , L" UCS-2" , FALSE , nullptr , &xmlReaderInput));
175
+
153
176
return ParseRootManifestFromXmlReaderInput (xmlReaderInput.Get ());
154
177
}
155
178
catch (...)
@@ -185,16 +208,47 @@ HRESULT ParseRootManifestFromXmlReaderInput(IUnknown* input)
185
208
186
209
HRESULT ParseFileTag (IXmlReader* xmlReader)
187
210
{
188
- HRESULT hr = S_OK;
189
- XmlNodeType nodeType;
190
211
PCWSTR localName = nullptr ;
191
212
PCWSTR value = nullptr ;
192
- hr = xmlReader->MoveToAttributeByName (L" name" , nullptr );
193
- RETURN_HR_IF (HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR), hr != S_OK);
194
- RETURN_IF_FAILED (xmlReader->GetValue (&value, nullptr ));
195
- std::wstring fileName{ !value ? L" " : value };
196
- RETURN_HR_IF (HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR), fileName.empty ());
213
+ std::wstring fileName;
197
214
auto locale = _create_locale (LC_ALL, " C" );
215
+ HRESULT hr = xmlReader->MoveToFirstAttribute ();
216
+ if (S_FALSE == hr)
217
+ {
218
+ return HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR);
219
+ }
220
+ else
221
+ {
222
+ while (TRUE )
223
+ {
224
+ if (FAILED_LOG (xmlReader->GetLocalName (&localName, NULL )))
225
+ {
226
+ return HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR);
227
+ }
228
+ if (FAILED_LOG (xmlReader->GetValue (&value, NULL )))
229
+ {
230
+ return HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR);
231
+ }
232
+ if (localName != nullptr )
233
+ {
234
+ if ((_wcsicmp_l (L" name" , localName, locale) == 0 ) && fileName.empty ())
235
+ {
236
+ fileName = value;
237
+ }
238
+ else if (_wcsicmp_l (L" loadFrom" , localName, locale) == 0 )
239
+ {
240
+ // override bare filename with fully qualified loadFrom path if supplied
241
+ fileName = value;
242
+ }
243
+ }
244
+ if (xmlReader->MoveToNextAttribute () != S_OK)
245
+ {
246
+ break ;
247
+ }
248
+ }
249
+ }
250
+ RETURN_HR_IF (HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR), fileName.empty ());
251
+ XmlNodeType nodeType;
198
252
while (S_OK == xmlReader->Read (&nodeType))
199
253
{
200
254
if (nodeType == XmlNodeType_Element)
@@ -220,10 +274,8 @@ HRESULT ParseActivatableClassTag(IXmlReader* xmlReader, PCWSTR fileName)
220
274
auto this_component = make_shared<component>();
221
275
this_component->module_name = fileName;
222
276
HRESULT hr = xmlReader->MoveToFirstAttribute ();
223
- // Using this pattern intead of calling multiple MoveToAttributeByName improves performance
224
277
const WCHAR* activatableClass = nullptr ;
225
278
const WCHAR* threadingModel = nullptr ;
226
- const WCHAR* xmlns = nullptr ;
227
279
if (S_FALSE == hr)
228
280
{
229
281
return HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR);
@@ -252,10 +304,6 @@ HRESULT ParseActivatableClassTag(IXmlReader* xmlReader, PCWSTR fileName)
252
304
{
253
305
activatableClass = pwszValue;
254
306
}
255
- else if (_wcsicmp_l (L" xmlns" , pwszLocalName, locale) == 0 )
256
- {
257
- xmlns = pwszValue;
258
- }
259
307
}
260
308
if (xmlReader->MoveToNextAttribute () != S_OK)
261
309
{
@@ -288,7 +336,6 @@ HRESULT ParseActivatableClassTag(IXmlReader* xmlReader, PCWSTR fileName)
288
336
{
289
337
return HRESULT_FROM_WIN32 (ERROR_SXS_MANIFEST_PARSE_ERROR);
290
338
}
291
- this_component->xmlns = xmlns; // Should we care if this value is blank or missing?
292
339
// Check for duplicate activatable classes
293
340
auto component_iter = g_types.find (activatableClass);
294
341
if (component_iter != g_types.end ())
0 commit comments