1 /*
2  * HLLib
3  * Copyright (C) 2006-2012 Ryan Gregg
4 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later
9  * version.
10  */
11 
12 #include "DirectoryFile.h"
13 #include "DirectoryFolder.h"
14 #include "HLLib.h"
15 #include "Utility.h"
16 
17 #include <algorithm>
18 
19 using namespace HLLib;
20 
CDirectoryFolder(CPackage * pPackage)21 CDirectoryFolder::CDirectoryFolder(CPackage *pPackage) : CDirectoryItem("root", HL_ID_INVALID, 0, pPackage, 0), pDirectoryItemVector(new CDirectoryItemVector())
22 {
23 
24 }
25 
CDirectoryFolder(const hlChar * lpName,hlUInt uiID,hlVoid * pData,CPackage * pPackage,CDirectoryFolder * pParent)26 CDirectoryFolder::CDirectoryFolder(const hlChar *lpName, hlUInt uiID, hlVoid *pData, CPackage *pPackage, CDirectoryFolder *pParent) : CDirectoryItem(lpName, uiID, pData, pPackage, pParent), pDirectoryItemVector(new CDirectoryItemVector())
27 {
28 
29 }
30 
~CDirectoryFolder()31 CDirectoryFolder::~CDirectoryFolder()
32 {
33 	// Delete children.
34 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
35 	{
36 		delete (*this->pDirectoryItemVector)[i];
37 	}
38 
39 	delete this->pDirectoryItemVector;
40 }
41 
GetType() const42 HLDirectoryItemType CDirectoryFolder::GetType() const
43 {
44 	return HL_ITEM_FOLDER;
45 }
46 
AddFolder(const hlChar * lpName,hlUInt uiID,hlVoid * lpData)47 CDirectoryFolder *CDirectoryFolder::AddFolder(const hlChar *lpName, hlUInt uiID, hlVoid *lpData)
48 {
49 	CDirectoryFolder *pFolder = new CDirectoryFolder(lpName, uiID, lpData, this->GetPackage(), this);
50 
51 	this->pDirectoryItemVector->push_back(pFolder);
52 
53 	return pFolder;
54 }
55 
AddFile(const hlChar * lpName,hlUInt uiID,hlVoid * lpData)56 CDirectoryFile *CDirectoryFolder::AddFile(const hlChar *lpName, hlUInt uiID, hlVoid *lpData)
57 {
58 	CDirectoryFile *pFile = new CDirectoryFile(lpName, uiID, lpData, this->GetPackage(), this);
59 
60 	this->pDirectoryItemVector->push_back(pFile);
61 
62 	return pFile;
63 }
64 
65 //
66 // GetCount()
67 // Returns the number of directory items in this folder.
68 //
GetCount() const69 hlUInt CDirectoryFolder::GetCount() const
70 {
71 	return (hlUInt)this->pDirectoryItemVector->size();
72 }
73 
74 //
75 // GetItem()
76 // Returns the directory item at index uiIndex.
77 //
GetItem(hlUInt uiIndex)78 CDirectoryItem *CDirectoryFolder::GetItem(hlUInt uiIndex)
79 {
80 	if(uiIndex >= (hlUInt)this->pDirectoryItemVector->size())
81 	{
82 		return 0;
83 	}
84 
85 	return (*this->pDirectoryItemVector)[uiIndex];
86 }
87 
GetItem(hlUInt uiIndex) const88 const CDirectoryItem *CDirectoryFolder::GetItem(hlUInt uiIndex) const
89 {
90 	if(uiIndex >= (hlUInt)this->pDirectoryItemVector->size())
91 	{
92 		return 0;
93 	}
94 
95 	return (*this->pDirectoryItemVector)[uiIndex];
96 }
97 
98 //
99 // GetItem()
100 // Returns the directory item lpName.  If the directory item
101 // does not exist null is returned.
102 //
GetItem(const hlChar * lpName,HLFindType eFind)103 CDirectoryItem *CDirectoryFolder::GetItem(const hlChar *lpName, HLFindType eFind)
104 {
105 	return const_cast<CDirectoryItem *>(const_cast<const CDirectoryFolder*>(this)->GetItem(lpName, eFind));
106 }
107 
GetItem(const hlChar * lpName,HLFindType eFind) const108 const CDirectoryItem *CDirectoryFolder::GetItem(const hlChar *lpName, HLFindType eFind) const
109 {
110 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
111 	{
112 		CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
113 		if((pItem->GetType() == HL_ITEM_FILE && (eFind & HL_FIND_FILES)) || (pItem->GetType() == HL_ITEM_FOLDER && (eFind & HL_FIND_FOLDERS)))
114 		{
115 			if(this->Compare(lpName, pItem->GetName(), eFind) == 0)
116 			{
117 				return pItem;
118 			}
119 		}
120 	}
121 
122 	return 0;
123 }
124 
125 //
126 // GetRelativeItem()
127 // Returns the directory item lpPath.  If the directory item
128 // does not exist null is returned.  Transverses sub-folders too.
129 //
GetRelativeItem(const hlChar * lpPath,HLFindType eFind)130 CDirectoryItem *CDirectoryFolder::GetRelativeItem(const hlChar *lpPath, HLFindType eFind)
131 {
132 	return const_cast<CDirectoryItem *>(const_cast<const CDirectoryFolder*>(this)->GetRelativeItem(lpPath, eFind));
133 }
134 
GetRelativeItem(const hlChar * lpPath,HLFindType eFind) const135 const CDirectoryItem *CDirectoryFolder::GetRelativeItem(const hlChar *lpPath, HLFindType eFind) const
136 {
137 	const CDirectoryFolder *pFolder = this;
138 
139 	hlChar *lpTemp = new hlChar[strlen(lpPath) + 1];
140 	strcpy(lpTemp, lpPath);
141 
142 	hlChar *lpToken = strtok(lpTemp, "\\/");
143 	if(lpToken != 0 && this->Compare(pFolder->GetName(), lpToken, eFind) == 0)
144 	{
145 		lpToken = strtok(0, "\\/");
146 	}
147 
148 	while(lpToken != 0)
149 	{
150 		if(*lpToken == '\0' || strcmp(lpToken, ".") == 0)
151 		{
152 			lpToken = strtok(0, "\\/");
153 		}
154 		else if(strcmp(lpToken, "..") == 0)
155 		{
156 			if(pFolder->GetParent())
157 			{
158 				pFolder = pFolder->GetParent();
159 			}
160 			else
161 			{
162 				delete []lpTemp;
163 				return 0;
164 			}
165 
166 			lpToken = strtok(0, "\\/");
167 		}
168 		else
169 		{
170 			hlChar *lpNext = strtok(0, "\\/");
171 
172 			const CDirectoryItem *pItem = 0;
173 
174 			for(hlUInt i = 0; i < pFolder->GetCount(); i++)
175 			{
176 				const CDirectoryItem *pTemp = pFolder->GetItem(i);
177 				if(lpNext == 0 && pTemp->GetType() == HL_ITEM_FILE && (eFind & HL_FIND_FILES) && this->Compare(lpToken, pTemp->GetName(), eFind) == 0)
178 				{
179 					pItem = pTemp;
180 					break;
181 				}
182 				else if(pTemp->GetType() == HL_ITEM_FOLDER && this->Compare(lpToken, pTemp->GetName(), eFind) == 0)
183 				{
184 					pItem = pTemp;
185 					break;
186 				}
187 			}
188 
189 			if(pItem == 0)
190 			{
191 				delete []lpTemp;
192 				return 0;
193 			}
194 
195 			if(pItem->GetType() == HL_ITEM_FOLDER)
196 			{
197 				pFolder = static_cast<const CDirectoryFolder *>(pItem);
198 			}
199 			else
200 			{
201 				delete []lpTemp;
202 				return pItem;
203 			}
204 
205 			lpToken = lpNext;
206 		}
207 	}
208 
209 	delete []lpTemp;
210 	if(eFind & HL_FIND_FOLDERS)
211 	{
212 		return pFolder;
213 	}
214 	else
215 	{
216 		return 0;
217 	}
218 }
219 
220 class CCompareDirectoryItems
221 {
222 private:
223 	HLSortField eField;
224 	HLSortOrder eOrder;
225 
226 public:
CCompareDirectoryItems(HLSortField eField,HLSortOrder eOrder)227 	CCompareDirectoryItems(HLSortField eField, HLSortOrder eOrder) : eField(eField), eOrder(eOrder)
228 	{
229 
230 	}
231 
operator ()(const CDirectoryItem * const & pItem0,const CDirectoryItem * const & pItem1)232 	bool operator()(const CDirectoryItem * const &pItem0, const CDirectoryItem * const &pItem1)
233 	{
234 		HLDirectoryItemType eType0 = pItem0->GetType();
235 		HLDirectoryItemType eType1 = pItem1->GetType();
236 
237 		if(eType0 == HL_ITEM_FOLDER && eType1 == HL_ITEM_FILE)
238 		{
239 			return true;
240 		}
241 		else if(eType0 == HL_ITEM_FILE && eType1 == HL_ITEM_FOLDER)
242 		{
243 			return false;
244 		}
245 
246 		hlInt iResult;
247 
248 		switch(eField)
249 		{
250 			case HL_FIELD_SIZE:
251 			{
252 				hlUInt uiSize0 = eType0 == HL_ITEM_FILE ? static_cast<const CDirectoryFile *>(pItem0)->GetSize() : static_cast<const CDirectoryFolder *>(pItem0)->GetCount();
253 				hlUInt uiSize1 = eType1 == HL_ITEM_FILE ? static_cast<const CDirectoryFile *>(pItem1)->GetSize() : static_cast<const CDirectoryFolder *>(pItem1)->GetCount();
254 
255 				iResult = (hlInt)uiSize0 - (hlInt)uiSize1;
256 
257 				if(iResult != 0)
258 				{
259 					break;
260 				}
261 			}
262 			//case HL_FIELD_NAME:
263 			default:
264 			{
265 				iResult = stricmp(pItem0->GetName(), pItem1->GetName());
266 				break;
267 			}
268 		}
269 
270 		if(eOrder == HL_ORDER_DESCENDING)
271 		{
272 			iResult *= -1;
273 		}
274 
275 		return iResult < 0;
276 	}
277 };
278 
Sort(HLSortField eField,HLSortOrder eOrder,hlBool bRecurse)279 hlVoid CDirectoryFolder::Sort(HLSortField eField, HLSortOrder eOrder, hlBool bRecurse)
280 {
281 	std::sort(this->pDirectoryItemVector->begin(), this->pDirectoryItemVector->end(), CCompareDirectoryItems(eField, eOrder));
282 
283 	if(bRecurse)
284 	{
285 		for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
286 		{
287 			CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
288 			if(pItem->GetType() == HL_ITEM_FOLDER)
289 			{
290 				static_cast<CDirectoryFolder *>(pItem)->Sort(eField, eOrder, bRecurse);
291 			}
292 		}
293 	}
294 }
295 
FindFirst(const hlChar * lpSearch,HLFindType eFind)296 CDirectoryItem *CDirectoryFolder::FindFirst(const hlChar *lpSearch, HLFindType eFind)
297 {
298 	return const_cast<CDirectoryItem *>(const_cast<const CDirectoryFolder*>(this)->FindFirst(lpSearch, eFind));
299 }
300 
FindFirst(const hlChar * lpSearch,HLFindType eFind) const301 const CDirectoryItem *CDirectoryFolder::FindFirst(const hlChar *lpSearch, HLFindType eFind) const
302 {
303 	return this->FindNext(this, 0, lpSearch, eFind);
304 }
305 
FindNext(const CDirectoryItem * pItem,const hlChar * lpSearch,HLFindType eFind)306 CDirectoryItem *CDirectoryFolder::FindNext(const CDirectoryItem *pItem, const hlChar *lpSearch, HLFindType eFind)
307 {
308 	return const_cast<CDirectoryItem *>(const_cast<const CDirectoryFolder*>(this)->FindNext(pItem, lpSearch, eFind));
309 }
310 
FindNext(const CDirectoryItem * pItem,const hlChar * lpSearch,HLFindType eFind) const311 const CDirectoryItem *CDirectoryFolder::FindNext(const CDirectoryItem *pItem, const hlChar *lpSearch, HLFindType eFind) const
312 {
313 	if(pItem == 0)
314 	{
315 		return 0;
316 	}
317 
318 	if(pItem->GetType() == HL_ITEM_FOLDER && !(eFind & HL_FIND_NO_RECURSE))
319 	{
320 		return this->FindNext(static_cast<const CDirectoryFolder *>(pItem), 0, lpSearch, eFind);
321 	}
322 	else
323 	{
324 		return this->FindNext(pItem->GetParent(), pItem, lpSearch, eFind);
325 	}
326 }
327 
FindNext(const CDirectoryFolder * pFolder,const CDirectoryItem * pRelative,const hlChar * lpSearch,HLFindType eFind) const328 const CDirectoryItem *CDirectoryFolder::FindNext(const CDirectoryFolder *pFolder, const CDirectoryItem *pRelative, const hlChar *lpSearch, HLFindType eFind) const
329 {
330 	hlUInt uiFirst = 0;
331 
332 	if(pRelative)
333 	{
334 		for(hlUInt i = 0; i < pFolder->GetCount(); i++)
335 		{
336 			if(pFolder->GetItem(i) == pRelative)
337 			{
338 				uiFirst = i + 1;
339 				break;
340 			}
341 		}
342 	}
343 
344 	for(hlUInt i = uiFirst; i < pFolder->GetCount(); i++)
345 	{
346 		const CDirectoryItem *pTest = pFolder->GetItem(i);
347 		if((pTest->GetType() == HL_ITEM_FILE && (eFind & HL_FIND_FILES)) || (pTest->GetType() == HL_ITEM_FOLDER && (eFind & HL_FIND_FOLDERS)))
348 		{
349 			if(this->Match(pTest->GetName(), lpSearch, eFind))
350 			{
351 				return pTest;
352 			}
353 		}
354 
355 		if(pTest->GetType() == HL_ITEM_FOLDER && !(eFind & HL_FIND_NO_RECURSE))
356 		{
357 			pTest = this->FindNext(static_cast<const CDirectoryFolder *>(pTest), 0, lpSearch, eFind);
358 
359 			if(pTest != 0)
360 			{
361 				return pTest;
362 			}
363 		}
364 	}
365 
366 	if(this == pFolder || pRelative == 0 || pFolder->GetParent() == 0)
367 	{
368 		return 0;
369 	}
370 
371 	return this->FindNext(pFolder->GetParent(), pFolder, lpSearch, eFind);
372 }
373 
Compare(const hlChar * lpString0,const hlChar * lpString1,HLFindType eFind) const374 hlInt CDirectoryFolder::Compare(const hlChar *lpString0, const hlChar *lpString1, HLFindType eFind) const
375 {
376 	if(eFind & HL_FIND_CASE_SENSITIVE)
377 	{
378 		return strcmp(lpString0, lpString1);
379 	}
380 	else
381 	{
382 		return stricmp(lpString0, lpString1);
383 	}
384 }
385 
386 //
387 // Match a string to a seach string.  Search string can contain wild cards like * (to match
388 // a substring) and ? (to match a letter).
389 //
Match(const hlChar * lpString,const hlChar * lpSearch,HLFindType eFind) const390 hlBool CDirectoryFolder::Match(const hlChar *lpString, const hlChar *lpSearch, HLFindType eFind) const
391 {
392 	if(eFind & HL_FIND_MODE_STRING)
393 	{
394 		return this->Compare(lpString, lpSearch, eFind);
395 	}
396 	else if(eFind & HL_FIND_MODE_SUBSTRING)
397 	{
398 		hlInt iStringLength = (hlInt)strlen(lpString);
399 		hlInt iSearchLength = (hlInt)strlen(lpSearch);
400 		hlInt iTests = iStringLength - iSearchLength;
401 
402 		if(eFind & HL_FIND_CASE_SENSITIVE)
403 		{
404 			for(hlInt i = 0; i <= iTests; i++)
405 			{
406 				if(strncmp(lpString + i, lpSearch, iSearchLength) == 0)
407 				{
408 					return hlTrue;
409 				}
410 			}
411 		}
412 		else
413 		{
414 			for(hlInt i = 0; i <= iTests; i++)
415 			{
416 				if(_strnicmp(lpString + i, lpSearch, iSearchLength) == 0)
417 				{
418 					return hlTrue;
419 				}
420 			}
421 		}
422 
423 		return hlFalse;
424 	}
425 	else /*if(eFind & HL_FIND_MODE_WILDCARD)*/
426 	{
427 		while(*lpSearch)
428 		{
429 			if(*lpSearch == '*')
430 			{
431 				if(lpSearch[1] == '*')
432 				{
433 					lpSearch++;
434 					continue;
435 				}
436 				else if(lpSearch[1] == '\0')
437 				{
438 					return hlTrue;
439 				}
440 				else
441 				{
442 					lpSearch++;
443 					while(*lpString)
444 					{
445 						if(this->Match(lpString, lpSearch, eFind))
446 						{
447 							return hlTrue;
448 						}
449 						lpString++;
450 					}
451 
452 					return hlFalse;
453 				}
454 			}
455 			else if(*lpSearch == '?')
456 			{
457 				if(*lpString == '\0')
458 				{
459 					return hlFalse;
460 				}
461 				lpSearch++;
462 				lpString++;
463 			}
464 			else
465 			{
466 				if(*lpString == '\0')
467 				{
468 					return hlFalse;
469 				}
470 				else
471 				{
472 					hlChar iA = *lpSearch;
473 					hlChar iB = *lpString;
474 
475 					if((eFind & HL_FIND_CASE_SENSITIVE) == 0)
476 					{
477 						if(iA >= 'a' && iA <= 'z')
478 						{
479 							iA -= 'a' - 'A';
480 						}
481 
482 						if(iB >= 'a' && iB <= 'z')
483 						{
484 							iB -= 'a' - 'A';
485 						}
486 					}
487 
488 					if(iA != iB)
489 					{
490 						return hlFalse;
491 					}
492 				}
493 				lpSearch++;
494 				lpString++;
495 			}
496 		}
497 
498 		return *lpString == '\0';
499 	}
500 }
501 
GetSize(hlBool bRecurse) const502 hlUInt CDirectoryFolder::GetSize(hlBool bRecurse) const
503 {
504 	hlUInt uiSize = 0;
505 
506 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
507 	{
508 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
509 		switch(pItem->GetType())
510 		{
511 		case HL_ITEM_FOLDER:
512 			if(bRecurse)
513 			{
514 				uiSize += static_cast<const CDirectoryFolder *>(pItem)->GetSize(bRecurse);
515 			}
516 			break;
517 		case HL_ITEM_FILE:
518 			uiSize += static_cast<const CDirectoryFile *>(pItem)->GetSize();
519 			break;
520 		}
521 	}
522 
523 	return uiSize;
524 }
525 
GetSizeEx(hlBool bRecurse) const526 hlULongLong CDirectoryFolder::GetSizeEx(hlBool bRecurse) const
527 {
528 	hlULongLong uiSize = 0;
529 
530 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
531 	{
532 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
533 		switch(pItem->GetType())
534 		{
535 		case HL_ITEM_FOLDER:
536 			if(bRecurse)
537 			{
538 				uiSize += static_cast<const CDirectoryFolder *>(pItem)->GetSizeEx(bRecurse);
539 			}
540 			break;
541 		case HL_ITEM_FILE:
542 			uiSize += static_cast<hlULongLong>(static_cast<const CDirectoryFile *>(pItem)->GetSize());
543 			break;
544 		}
545 	}
546 
547 	return uiSize;
548 }
549 
GetSizeOnDisk(hlBool bRecurse) const550 hlUInt CDirectoryFolder::GetSizeOnDisk(hlBool bRecurse) const
551 {
552 	hlUInt uiSize = 0;
553 
554 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
555 	{
556 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
557 		switch(pItem->GetType())
558 		{
559 		case HL_ITEM_FOLDER:
560 			if(bRecurse)
561 			{
562 				uiSize += static_cast<const CDirectoryFolder *>(pItem)->GetSizeOnDisk(bRecurse);
563 			}
564 			break;
565 		case HL_ITEM_FILE:
566 			uiSize += static_cast<const CDirectoryFile *>(pItem)->GetSizeOnDisk();
567 			break;
568 		}
569 	}
570 
571 	return uiSize;
572 }
573 
GetSizeOnDiskEx(hlBool bRecurse) const574 hlULongLong CDirectoryFolder::GetSizeOnDiskEx(hlBool bRecurse) const
575 {
576 	hlULongLong uiSize = 0;
577 
578 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
579 	{
580 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
581 		switch(pItem->GetType())
582 		{
583 		case HL_ITEM_FOLDER:
584 			if(bRecurse)
585 			{
586 				uiSize += static_cast<const CDirectoryFolder *>(pItem)->GetSizeOnDiskEx(bRecurse);
587 			}
588 			break;
589 		case HL_ITEM_FILE:
590 			uiSize += static_cast<hlULongLong>(static_cast<const CDirectoryFile *>(pItem)->GetSizeOnDisk());
591 			break;
592 		}
593 	}
594 
595 	return uiSize;
596 }
597 
GetFolderCount(hlBool bRecurse) const598 hlUInt CDirectoryFolder::GetFolderCount(hlBool bRecurse) const
599 {
600 	hlUInt uiCount = 0;
601 
602 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
603 	{
604 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
605 		switch(pItem->GetType())
606 		{
607 		case HL_ITEM_FOLDER:
608 			uiCount++;
609 			if(bRecurse)
610 			{
611 				uiCount += static_cast<const CDirectoryFolder *>(pItem)->GetFolderCount(bRecurse);
612 			}
613 			break;
614 		}
615 	}
616 
617 	return uiCount;
618 }
619 
GetFileCount(hlBool bRecurse) const620 hlUInt CDirectoryFolder::GetFileCount(hlBool bRecurse) const
621 {
622 	hlUInt uiCount = 0;
623 
624 	for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
625 	{
626 		const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
627 		switch(pItem->GetType())
628 		{
629 		case HL_ITEM_FOLDER:
630 			if(bRecurse)
631 			{
632 				uiCount += static_cast<const CDirectoryFolder *>(pItem)->GetFileCount(bRecurse);
633 			}
634 			break;
635 		case HL_ITEM_FILE:
636 			uiCount++;
637 			break;
638 		}
639 	}
640 
641 	return uiCount;
642 }
643 
Extract(const hlChar * lpPath) const644 hlBool CDirectoryFolder::Extract(const hlChar *lpPath) const
645 {
646 	hlExtractItemStart(this);
647 
648 	hlChar *lpName = new hlChar[strlen(this->GetName()) + 1];
649 	strcpy(lpName, this->GetName());
650 	RemoveIllegalCharacters(lpName);
651 
652 	hlChar *lpFolderName;
653 	if(lpPath == 0 || *lpPath == '\0')
654 	{
655 		lpFolderName = new hlChar[strlen(lpName) + 1];
656 		strcpy(lpFolderName, lpName);
657 	}
658 	else
659 	{
660 		lpFolderName = new hlChar[strlen(lpPath) + 1 + strlen(lpName) + 1];
661 		strcpy(lpFolderName, lpPath);
662 		strcat(lpFolderName, PATH_SEPARATOR_STRING);
663 		strcat(lpFolderName, lpName);
664 	}
665 
666 	FixupIllegalCharacters(lpFolderName);
667 
668 	hlBool bResult;
669 	if(!CreateFolder(lpFolderName))
670 	{
671 		LastError.SetSystemErrorMessage("CreateDirectory() failed.");
672 
673 		bResult = hlFalse;
674 	}
675 	else
676 	{
677 		bResult = hlTrue;
678 
679 		for(hlUInt i = 0; i < this->pDirectoryItemVector->size(); i++)
680 		{
681 			const CDirectoryItem *pItem = (*this->pDirectoryItemVector)[i];
682 			if(pItem->GetType() != HL_ITEM_FILE || static_cast<const CDirectoryFile *>(pItem)->GetExtractable())
683 			{
684 				bResult &= pItem->Extract(lpFolderName);
685 			}
686 		}
687 	}
688 
689 	delete []lpFolderName;
690 	delete []lpName;
691 
692 	hlExtractItemEnd(this, bResult);
693 
694 	return bResult;
695 }
696