1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "resource_append.h"
17 #include <algorithm>
18 #include <iomanip>
19 #include <iostream>
20 #include <regex>
21 #include "config_parser.h"
22 #include "header.h"
23 #include "id_worker.h"
24 #include "key_parser.h"
25 #include "reference_parser.h"
26 #include "resource_table.h"
27 #include "resource_util.h"
28 #include "select_compile_parse.h"
29 #ifdef __WIN32
30 #include "windows.h"
31 #endif
32 #include "securec.h"
33
34 namespace OHOS {
35 namespace Global {
36 namespace Restool {
37 using namespace std;
38
ResourceAppend(const PackageParser & packageParser)39 ResourceAppend::ResourceAppend(const PackageParser &packageParser) : packageParser_(packageParser)
40 {
41 }
42
Append()43 uint32_t ResourceAppend::Append()
44 {
45 string outputPath = packageParser_.GetOutput();
46 for (const auto &iter : packageParser_.GetAppend()) {
47 if (!ScanResources(iter, outputPath)) {
48 return RESTOOL_ERROR;
49 }
50 }
51 return RESTOOL_SUCCESS;
52 }
53
Combine()54 uint32_t ResourceAppend::Combine()
55 {
56 for (const auto &iter : packageParser_.GetInputs()) {
57 if (!Combine(iter)) {
58 return RESTOOL_ERROR;
59 }
60 }
61
62 if (!ParseRef()) {
63 return false;
64 }
65
66 ResourceTable resourceTable;
67 if (resourceTable.CreateResourceTable(items_) != RESTOOL_SUCCESS) {
68 return RESTOOL_ERROR;
69 }
70 return RESTOOL_SUCCESS;
71 }
72
73 // private
Combine(const string & folderPath)74 bool ResourceAppend::Combine(const string &folderPath)
75 {
76 FileEntry entry(folderPath);
77 if (!entry.Init()) {
78 return false;
79 }
80
81 itemsForModule_.clear();
82 for (const auto &child : entry.GetChilds()) {
83 if (!child->IsFile()) {
84 cerr << "Error:" << child->GetFilePath().GetPath() << " not file" << endl;
85 return false;
86 }
87 if (child->GetFilePath().GetFilename() == ID_DEFINED_FILE) {
88 continue;
89 }
90 if (!LoadResourceItem(child->GetFilePath().GetPath())) {
91 return false;
92 }
93 }
94 return true;
95 }
96
ParseRef()97 bool ResourceAppend::ParseRef()
98 {
99 for (auto &iter : refs_) {
100 ReferenceParser ref;
101 if (iter->GetResType() == ResType::PROF || iter->GetResType() == ResType::MEDIA) {
102 if (ref.ParseRefInJsonFile(*iter, packageParser_.GetOutput(), true) != RESTOOL_SUCCESS) {
103 return false;
104 }
105 } else if (ref.ParseRefInResourceItem(*iter) != RESTOOL_SUCCESS) {
106 return false;
107 }
108 }
109 return true;
110 }
111
ScanResources(const string & resourcePath,const string & outputPath)112 bool ResourceAppend::ScanResources(const string &resourcePath, const string &outputPath)
113 {
114 if (!ResourceUtil::FileExist(resourcePath)) {
115 string filePath = FileEntry::FilePath(outputPath).Append(ResourceUtil::GenerateHash(resourcePath)).GetPath();
116 if (remove(filePath.c_str()) != 0) {
117 cerr << "Error: remove failed '" << filePath << "', reason: " << strerror(errno) << endl;
118 return false;
119 }
120 return true;
121 }
122
123 FileEntry entry(resourcePath);
124 if (!entry.Init()) {
125 return false;
126 }
127
128 if (entry.IsFile()) {
129 return ScanSingleFile(resourcePath, outputPath);
130 }
131
132 return ScanSubResources(entry, resourcePath, outputPath);
133 }
134
ScanSubResources(const FileEntry entry,const string & resourcePath,const string & outputPath)135 bool ResourceAppend::ScanSubResources(const FileEntry entry, const string &resourcePath, const string &outputPath)
136 {
137 vector<KeyParam> keyParams;
138 if (KeyParser::Parse(entry.GetFilePath().GetFilename(), keyParams)) {
139 for (const auto &child : entry.GetChilds()) {
140 if (!ResourceUtil::IslegalPath(child->GetFilePath().GetFilename())) {
141 continue;
142 }
143 if (!ScanIegalResources(child->GetFilePath().GetPath(), outputPath)) {
144 return false;
145 }
146 }
147 return true;
148 }
149
150 if (ResourceUtil::IslegalPath(entry.GetFilePath().GetFilename())) {
151 return ScanIegalResources(resourcePath, outputPath);
152 }
153
154 return ScanSubLimitkeyResources(entry, resourcePath, outputPath);
155 }
156
ScanSubLimitkeyResources(const FileEntry entry,const string & resourcePath,const string & outputPath)157 bool ResourceAppend::ScanSubLimitkeyResources(const FileEntry entry, const string &resourcePath,
158 const string &outputPath)
159 {
160 for (const auto &child : entry.GetChilds()) {
161 string limitKey = child->GetFilePath().GetFilename();
162 if (ResourceUtil::IsIgnoreFile(limitKey, child->IsFile())) {
163 continue;
164 }
165
166 if (limitKey == RAW_FILE_DIR || limitKey == RES_FILE_DIR) {
167 if (!ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limitKey)) {
168 return false;
169 }
170 continue;
171 }
172
173 if (child->IsFile()) {
174 cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl;
175 return false;
176 }
177
178 if (!ScanLimitKey(child, limitKey, outputPath)) {
179 return false;
180 }
181 }
182 return true;
183 }
184
ScanIegalResources(const string & resourcePath,const string & outputPath)185 bool ResourceAppend::ScanIegalResources(const string &resourcePath, const string &outputPath)
186 {
187 FileEntry entry(resourcePath);
188 if (!entry.Init()) {
189 return false;
190 }
191 for (const auto &child : entry.GetChilds()) {
192 if (!ScanSingleFile(child->GetFilePath().GetPath(), outputPath)) {
193 return false;
194 }
195 }
196 return true;
197 }
ScanLimitKey(const unique_ptr<FileEntry> & entry,const string & limitKey,const string outputPath)198 bool ResourceAppend::ScanLimitKey(const unique_ptr<FileEntry> &entry,
199 const string &limitKey, const string outputPath)
200 {
201 vector<KeyParam> keyParams;
202 if (!KeyParser::Parse(limitKey, keyParams)) {
203 cerr << "Error: invalid limit key '" << limitKey << "'.";
204 cerr << NEW_LINE_PATH << entry->GetFilePath().GetPath() << endl;
205 return false;
206 }
207
208 for (const auto &child : entry->GetChilds()) {
209 string fileCuster = child->GetFilePath().GetFilename();
210 if (ResourceUtil::IsIgnoreFile(fileCuster, child->IsFile())) {
211 continue;
212 }
213
214 if (child->IsFile()) {
215 cerr << "Error: " << child->GetFilePath().GetPath() << " not directory" << endl;
216 return false;
217 }
218
219 ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
220 if (resType == ResType::INVALID_RES_TYPE) {
221 cerr << "Error: invalid resType." << NEW_LINE_PATH << child->GetFilePath().GetPath() << endl;
222 return false;
223 }
224
225 DirectoryInfo directoryInfo = { limitKey, fileCuster, child->GetFilePath().GetPath(), keyParams, resType};
226 if (!ScanFiles(child, directoryInfo, outputPath)) {
227 return false;
228 }
229 }
230 return true;
231 }
232
233
ScanFiles(const unique_ptr<FileEntry> & entry,const DirectoryInfo & directoryInfo,const string & outputPath)234 bool ResourceAppend::ScanFiles(const unique_ptr<FileEntry> &entry,
235 const DirectoryInfo &directoryInfo, const string &outputPath)
236 {
237 for (const auto &child : entry->GetChilds()) {
238 string filename = child->GetFilePath().GetFilename();
239 if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
240 continue;
241 }
242
243 if (!child->IsFile()) {
244 cerr << "Error: '" << child->GetFilePath().GetPath() << "' not file." << endl;
245 return false;
246 }
247
248 FileInfo fileInfo = {directoryInfo, child->GetFilePath().GetPath(), filename};
249 if (!ScanFile(fileInfo, outputPath)) {
250 return false;
251 }
252 }
253 return true;
254 }
255
ScanFile(const FileInfo & fileInfo,const string & outputPath)256 bool ResourceAppend::ScanFile(const FileInfo &fileInfo, const string &outputPath)
257 {
258 if (ResourceAppend::IsBaseIdDefined(fileInfo)) {
259 cout << "Warning: id_defined.json does not compile to generate intermediate files" << endl;
260 FileEntry::FilePath outPath(outputPath);
261 return ResourceUtil::CopyFleInner(fileInfo.filePath, outPath.Append(ID_DEFINED_FILE).GetPath());
262 }
263
264 unique_ptr<IResourceCompiler> resourceCompiler =
265 FactoryResourceCompiler::CreateCompilerForAppend(fileInfo.dirType, outputPath);
266 if (resourceCompiler == nullptr) {
267 return true;
268 }
269
270 if (resourceCompiler->CompileForAppend(fileInfo) != RESTOOL_SUCCESS) {
271 return false;
272 }
273
274 ostringstream outStream;
275 const auto &items = resourceCompiler->GetResourceItems();
276 for (const auto &item : items) {
277 for (const auto &resourceItem : item.second) {
278 if (!WriteResourceItem(resourceItem, outStream)) {
279 return false;
280 }
281 }
282 }
283
284 string hash = ResourceUtil::GenerateHash(fileInfo.filePath);
285 FileEntry::FilePath output(outputPath);
286 if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
287 return false;
288 }
289 return true;
290 }
291
ScanSingleFile(const string & filePath,const string & outputPath)292 bool ResourceAppend::ScanSingleFile(const string &filePath, const string &outputPath)
293 {
294 if (filePath.find(RAW_FILE_DIR) != string::npos) {
295 return WriteRawFilesOrResFiles(filePath, outputPath, RAW_FILE_DIR);
296 }
297
298 if (filePath.find(RES_FILE_DIR) != string::npos) {
299 return WriteRawFilesOrResFiles(filePath, outputPath, RES_FILE_DIR);
300 }
301
302 FileEntry::FilePath path(filePath);
303 string fileCuster = path.GetParent().GetFilename();
304 ResType resType = ResourceUtil::GetResTypeByDir(fileCuster);
305 if (resType == ResType::INVALID_RES_TYPE) {
306 cerr << "Error: invalid resType." << NEW_LINE_PATH << filePath << endl;
307 return false;
308 }
309
310 string limitKey = path.GetParent().GetParent().GetFilename();
311 vector<KeyParam> keyParams;
312 if (!KeyParser::Parse(limitKey, keyParams)) {
313 cerr << "Error: invalid limit key." << NEW_LINE_PATH << filePath << endl;
314 return false;
315 }
316
317 DirectoryInfo directoryInfo = {limitKey, fileCuster, path.GetParent().GetPath(), keyParams, resType};
318 FileInfo fileInfo = {directoryInfo, filePath, path.GetFilename() };
319 if (!ScanFile(fileInfo, outputPath)) {
320 return false;
321 }
322 return true;
323 }
324
WriteFileInner(ostringstream & outStream,const string & outputPath) const325 bool ResourceAppend::WriteFileInner(ostringstream &outStream, const string &outputPath) const
326 {
327 #ifdef __WIN32
328 HANDLE hWriteFile = CreateFile(outputPath.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE,
329 nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
330 if (hWriteFile == INVALID_HANDLE_VALUE) {
331 cerr << "Error: '" << outputPath << "' " << GetLastError() << endl;
332 return false;
333 }
334
335 DWORD writeBytes;
336 if (!WriteFile(hWriteFile, outStream.str().c_str(), outStream.tellp(), &writeBytes, nullptr)) {
337 cerr << "Error: write '" << outputPath << "' " << GetLastError() << endl;
338 CloseHandle(hWriteFile);
339 return false;
340 }
341 CloseHandle(hWriteFile);
342 #else
343 ofstream out(outputPath, ofstream::out | ofstream::binary);
344 if (!out.is_open()) {
345 cerr << "Error: open failed '" << outputPath << "', reason: " << strerror(errno) << endl;
346 return false;
347 }
348 out << outStream.str();
349 #endif
350 return true;
351 }
352
WriteResourceItem(const ResourceItem & resourceItem,ostringstream & out)353 bool ResourceAppend::WriteResourceItem(const ResourceItem &resourceItem, ostringstream &out)
354 {
355 int32_t size = resourceItem.GetName().length();
356 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
357 out.write(reinterpret_cast<const char *>(resourceItem.GetName().c_str()), size);
358
359 size = resourceItem.GetLimitKey().length();
360 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
361 out.write(reinterpret_cast<const char *>(resourceItem.GetLimitKey().c_str()), size);
362
363 size = resourceItem.GetFilePath().length();
364 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
365 out.write(reinterpret_cast<const char *>(resourceItem.GetFilePath().c_str()), size);
366
367 int32_t type = static_cast<int32_t>(resourceItem.GetResType());
368 out.write(reinterpret_cast<const char *>(&type), sizeof(int32_t));
369
370 size = resourceItem.GetKeyParam().size();
371 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
372 for (const auto &keyParam : resourceItem.GetKeyParam()) {
373 out.write(reinterpret_cast<const char *>(&keyParam.keyType), sizeof(int32_t));
374 out.write(reinterpret_cast<const char *>(&keyParam.value), sizeof(int32_t));
375 }
376
377 size = resourceItem.GetDataLength();
378 out.write(reinterpret_cast<const char *>(&size), sizeof(int32_t));
379 out.write(reinterpret_cast<const char *>(resourceItem.GetData()), size);
380 return true;
381 }
382
LoadResourceItem(const string & filePath)383 bool ResourceAppend::LoadResourceItem(const string &filePath)
384 {
385 #ifdef __WIN32
386 return LoadResourceItemWin(filePath);
387 #else
388 ifstream in(filePath, ifstream::in | ifstream::binary);
389 if (!in.is_open()) {
390 cerr << "Error: open failed '" << filePath << "', reason: " << strerror(errno) << endl;
391 return false;
392 }
393
394 in.seekg(0, in.end);
395 int32_t length = in.tellg();
396 in.seekg(0, in.beg);
397 if (length <= 0) {
398 cerr << "Error: invalid file size = " << length << NEW_LINE_PATH << filePath << endl;
399 return false;
400 }
401 char buffer[length];
402 in.read(buffer, length);
403 return LoadResourceItemFromMem(buffer, length);
404 #endif
405 }
406
ScanRawFilesOrResFiles(const string & path,const string & outputPath,const string & limit)407 bool ResourceAppend::ScanRawFilesOrResFiles(const string &path, const string &outputPath, const string &limit)
408 {
409 FileEntry entry(path);
410 if (!entry.Init()) {
411 return false;
412 }
413
414 for (const auto &child : entry.GetChilds()) {
415 string filename = child->GetFilePath().GetFilename();
416 if (ResourceUtil::IsIgnoreFile(filename, child->IsFile())) {
417 continue;
418 }
419
420 bool ret = false;
421 if (child->IsFile()) {
422 ret = WriteRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
423 } else {
424 ret = ScanRawFilesOrResFiles(child->GetFilePath().GetPath(), outputPath, limit);
425 }
426
427 if (!ret) {
428 return false;
429 }
430 }
431 return true;
432 }
433
WriteRawFilesOrResFiles(const string & filePath,const string & outputPath,const string & limit)434 bool ResourceAppend::WriteRawFilesOrResFiles(const string &filePath, const string &outputPath, const string &limit)
435 {
436 string::size_type pos = filePath.find(limit);
437 if (pos == string::npos) {
438 cerr << "Error: invalid file path." << NEW_LINE_PATH << filePath << endl;
439 return false;
440 }
441
442 string sub = filePath.substr(pos);
443 sub = FileEntry::FilePath(RESOURCES_DIR).Append(sub).GetPath();
444 vector<KeyParam> keyParams;
445 auto iter = g_copyFileMap.find(limit);
446 ResourceItem resourceItem("", keyParams, iter->second);
447 resourceItem.SetData(sub);
448 resourceItem.SetFilePath(filePath);
449 resourceItem.SetLimitKey("");
450
451 ostringstream outStream;
452 if (!WriteResourceItem(resourceItem, outStream)) {
453 return false;
454 }
455
456 string hash = ResourceUtil::GenerateHash(filePath);
457 FileEntry::FilePath output(outputPath);
458 if (!WriteFileInner(outStream, output.Append(hash).GetPath())) {
459 return false;
460 }
461 return true;
462 }
463
Push(const shared_ptr<ResourceItem> & resourceItem)464 bool ResourceAppend::Push(const shared_ptr<ResourceItem> &resourceItem)
465 {
466 string idName = ResourceUtil::GetIdName(resourceItem->GetName(), resourceItem->GetResType());
467 int32_t id = IdWorker::GetInstance().GenerateId(resourceItem->GetResType(), idName);
468 if (id < 0) {
469 return false;
470 }
471
472 if (!CheckModuleResourceItem(resourceItem, id)) {
473 return false;
474 }
475
476 const auto &result = items_.find(id);
477 if (result == items_.end()) {
478 items_[id].push_back(resourceItem);
479 AddRef(resourceItem);
480 return true;
481 }
482
483 if (find_if(result->second.begin(), result->second.end(), [resourceItem](auto &iter) {
484 return resourceItem->GetLimitKey() == iter->GetLimitKey();
485 }) != result->second.end()) {
486 return true;
487 }
488
489 items_[id].push_back(resourceItem);
490 AddRef(resourceItem);
491 return true;
492 }
493
AddRef(const shared_ptr<ResourceItem> & resourceItem)494 void ResourceAppend::AddRef(const shared_ptr<ResourceItem> &resourceItem)
495 {
496 string data(reinterpret_cast<const char *>(resourceItem->GetData()), resourceItem->GetDataLength());
497 ResType resType = resourceItem->GetResType();
498 if (resType == ResType::MEDIA) {
499 if (FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() == JSON_EXTENSION) {
500 refs_.push_back(resourceItem);
501 }
502 return;
503 }
504
505 if (resType == ResType::PROF) {
506 if (resourceItem->GetLimitKey() != "base" ||
507 FileEntry::FilePath(resourceItem->GetFilePath()).GetExtension() != JSON_EXTENSION) {
508 return;
509 }
510 refs_.push_back(resourceItem);
511 return;
512 }
513
514 if (regex_match(data, regex(".*\\$.+:.*"))) {
515 refs_.push_back(resourceItem);
516 }
517 }
518
LoadResourceItemFromMem(const char buffer[],int32_t length)519 bool ResourceAppend::LoadResourceItemFromMem(const char buffer[], int32_t length)
520 {
521 int32_t offset = 0;
522 do {
523 // name
524 string nameStr = ParseString(buffer, length, offset);
525 // limit key
526 string limitKeyStr = ParseString(buffer, length, offset);
527 // file path
528 string filePathStr = ParseString(buffer, length, offset);
529 // ResType
530 int32_t type = ParseInt32(buffer, length, offset);
531 ResType resType = static_cast<ResType>(type);
532 // keyParam
533 int32_t keyParamSize = ParseInt32(buffer, length, offset);
534 vector<KeyParam> keyParams;
535 for (int i = 0; i < keyParamSize; i++) {
536 KeyParam keyParam;
537 keyParam.keyType = static_cast<KeyType>(ParseInt32(buffer, length, offset));
538 keyParam.value = ParseInt32(buffer, length, offset);
539 keyParams.push_back(keyParam);
540 }
541 if (limitKeyStr != "base" && !limitKeyStr.empty() && !SelectCompileParse::IsSelectCompile(keyParams)) {
542 return true;
543 }
544 // data
545 string data = ParseString(buffer, length, offset);
546 if (resType == ResType::RAW || resType == ResType::RES) {
547 FileEntry::FilePath outPath(packageParser_.GetOutput());
548 if (ResourceUtil::FileExist(outPath.Append(data).GetPath())) {
549 continue;
550 }
551 if (!ResourceUtil::CreateDirs(outPath.Append(data).GetParent().GetPath())) {
552 return false;
553 }
554
555 if (!ResourceUtil::FileExist(filePathStr)) {
556 continue;
557 }
558
559 if (!ResourceUtil::CopyFleInner(filePathStr, outPath.Append(data).GetPath())) {
560 return false;
561 }
562 continue;
563 }
564
565 shared_ptr<ResourceItem> resourceItem = make_shared<ResourceItem>(nameStr, keyParams, resType);
566 resourceItem->SetData(reinterpret_cast<const int8_t *>(data.c_str()), data.length());
567 resourceItem->SetLimitKey(limitKeyStr);
568 resourceItem->SetFilePath(filePathStr);
569 if (!Push(resourceItem)) {
570 return false;
571 }
572 } while (offset < length);
573 return true;
574 }
575
ParseString(const char buffer[],int32_t length,int32_t & offset) const576 string ResourceAppend::ParseString(const char buffer[], int32_t length, int32_t &offset) const
577 {
578 int32_t size = ParseInt32(buffer, length, offset);
579 if (size < 0 || offset + size > length) {
580 offset = length;
581 return "";
582 }
583
584 if (size == 0) {
585 return "";
586 }
587
588 string value(buffer + offset, size);
589 offset += size;
590 return value;
591 }
592
ParseInt32(const char buffer[],int32_t length,int32_t & offset) const593 int32_t ResourceAppend::ParseInt32(const char buffer[], int32_t length, int32_t &offset) const
594 {
595 if (offset + static_cast<int32_t>(sizeof(int32_t)) > length) {
596 offset = length;
597 return -1;
598 }
599
600 int32_t size = 0;
601 if (memcpy_s(&size, sizeof(int32_t), buffer + offset, sizeof(int32_t)) != EOK) {
602 offset = length;
603 return -1;
604 }
605 offset += sizeof(int32_t);
606 return size;
607 }
608
CheckModuleResourceItem(const shared_ptr<ResourceItem> & resourceItem,int32_t id)609 bool ResourceAppend::CheckModuleResourceItem(const shared_ptr<ResourceItem> &resourceItem, int32_t id)
610 {
611 const auto &result = itemsForModule_.find(id);
612 if (result == itemsForModule_.end()) {
613 itemsForModule_[id].push_back(resourceItem);
614 return true;
615 }
616
617 const auto &ret = find_if(result->second.begin(), result->second.end(), [resourceItem](auto iter) {
618 return resourceItem->GetLimitKey() == iter->GetLimitKey();
619 });
620
621 if (ret != result->second.end()) {
622 cerr << "Error: '" << resourceItem->GetName() << "' conflict, first declared.";
623 cerr << NEW_LINE_PATH << (*ret)->GetFilePath() << endl;
624 cerr << "but declared again." << NEW_LINE_PATH << resourceItem->GetFilePath() << endl;
625 return false;
626 }
627
628 itemsForModule_[id].push_back(resourceItem);
629 return true;
630 }
631
632 #ifdef __WIN32
LoadResourceItemWin(const string & filePath)633 bool ResourceAppend::LoadResourceItemWin(const string &filePath)
634 {
635 bool result = false;
636 HANDLE hReadFile = CreateFile(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING,
637 FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS, nullptr);
638 if (hReadFile == INVALID_HANDLE_VALUE) {
639 cerr << "Error: "<< GetLastError() << NEW_LINE_PATH << filePath << endl;
640 return result;
641 }
642
643 DWORD fileSize = GetFileSize(hReadFile, nullptr);
644 HANDLE hFileMap = CreateFileMapping(hReadFile, nullptr, PAGE_READONLY, 0, fileSize, nullptr);
645 if (hFileMap == INVALID_HANDLE_VALUE) {
646 cerr << "Error: create file mapping " << GetLastError() << endl;
647 CloseHandle(hReadFile);
648 return result;
649 }
650
651 void* pBuffer = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0);
652 if (pBuffer == nullptr) {
653 cerr << "Error: map view of file " << GetLastError() << endl;
654 CloseHandle(hReadFile);
655 return result;
656 }
657
658 char* buffer = reinterpret_cast<char *>(pBuffer);
659 result = LoadResourceItemFromMem(buffer, fileSize);
660 UnmapViewOfFile(hFileMap);
661 CloseHandle(hReadFile);
662 return result;
663 }
664 #endif
665
IsBaseIdDefined(const FileInfo & fileInfo)666 bool ResourceAppend::IsBaseIdDefined(const FileInfo &fileInfo)
667 {
668 FileEntry::FilePath filePath(fileInfo.filePath);
669 return filePath.GetParent().GetParent().GetFilename() == "base" &&
670 filePath.GetParent().GetFilename() == "element" &&
671 fileInfo.filename == ID_DEFINED_FILE;
672 }
673 }
674 }
675 }