static PyObject * Package_extract(PackageObject *self, PyObject *args) { hlUInt i; hlUInt uiExtractItems = 0; hlChar *lpExtractItems[MAX_ITEMS]; hlChar *lpDestination = 0;; HLDirectoryItem *pItem = 0; pUpdateFunc = Py_None; if (!PyArg_ParseTuple(args, "ss|O", &lpExtractItems[0], &lpDestination, &pUpdateFunc)) { return NULL; } uiExtractItems = 1; // Just before extracting set these globals hlSetBoolean(HL_OVERWRITE_FILES, self->bOverwriteFiles); hlSetBoolean(HL_FORCE_DEFRAGMENT, self->bForceDefragment); bSilent = self->bSilent; // Extract the requested items. for(i = 0; i < uiExtractItems; i++) { // Find the item. pItem = hlFolderGetItemByPath(hlPackageGetRoot(), lpExtractItems[i], HL_FIND_ALL); if(pItem == 0) { PySys_WriteStdout("%s not found in package.\n", lpExtractItems[i]); continue; } if(!self->bSilent) { PySys_WriteStdout("Extracting %s...\n\n", hlItemGetName(pItem)); } // Extract the item. // Item is extracted to cDestination\Item->GetName(). g_extract_save = PyEval_SaveThread(); g_bytesExtracted = 0; hlItemExtract(pItem, lpDestination); PyEval_RestoreThread(g_extract_save); if(!self->bSilent) { PySys_WriteStdout("\nDone.\n"); } } Py_INCREF(Py_None); return Py_None; }
int main(hlInt argc, hlChar* argv[]) { hlUInt i; // Arguments. hlUInt uiArgumentCount = (hlUInt)argc; hlChar *lpPackage = 0; hlUInt uiExtractItems = 0; hlChar *lpExtractItems[MAX_ITEMS]; hlUInt uiValidateItems = 0; hlChar *lpValidateItems[MAX_ITEMS]; hlChar *lpList = 0; hlBool bDefragment = hlFalse; hlChar *lpNCFRootPath = 0; hlBool bList = hlFalse; hlBool bListFolders = hlFalse; hlBool bListFiles = hlFalse; FILE *pFile = 0; hlBool bConsoleMode = hlFalse; hlUInt uiConsoleCommands = 0; hlChar *lpConsoleCommands[MAX_ITEMS]; hlBool bFileMapping = hlFalse; hlBool bQuickFileMapping = hlFalse; hlBool bVolatileAccess = hlFalse; hlBool bOverwriteFiles = hlTrue; hlBool bForceDefragment = hlFalse; // Package stuff. HLPackageType ePackageType = HL_PACKAGE_NONE; hlUInt uiPackage = HL_ID_INVALID, uiMode = HL_MODE_INVALID; HLDirectoryItem *pItem = 0; if(hlGetUnsignedInteger(HL_VERSION) < HL_VERSION_NUMBER) { printf("Wrong HLLib version: v%s.\n", hlGetString(HL_VERSION)); return 1; } // Process switches. if(uiArgumentCount == 2) { // The user just specified a file, drop into console mode. lpPackage = argv[1]; bConsoleMode = hlTrue; bVolatileAccess = hlTrue; } else { for(i = 1; i < uiArgumentCount; i++) { if(stricmp(argv[i], "-p") == 0 || stricmp(argv[i], "--package") == 0) { if(lpPackage == 0 && i + 1 < uiArgumentCount) { lpPackage = argv[++i]; } else { PrintUsage(); return 2; } } else if(stricmp(argv[i], "-d") == 0 || stricmp(argv[i], "--dest") == 0) { if(*lpDestination == 0 && i + 1 < uiArgumentCount) { strcpy(lpDestination, argv[++i]); } else { PrintUsage(); return 2; } } else if(stricmp(argv[i], "-e") == 0 || stricmp(argv[i], "--extract") == 0) { if(i + 1 < uiArgumentCount) { if(uiExtractItems == MAX_ITEMS) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading package:\nMAX_ITEMS\n"); return 2; } lpExtractItems[uiExtractItems++] = argv[++i]; } else { PrintUsage(); return 2; } } else if(stricmp(argv[i], "-t") == 0 || stricmp(argv[i], "--validate") == 0) { if(i + 1 < uiArgumentCount) { if(uiValidateItems == MAX_ITEMS) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading package:\nMAX_ITEMS\n"); return 2; } lpValidateItems[uiValidateItems++] = argv[++i]; } else { PrintUsage(); return 2; } } else if(strnicmp(argv[i], "-l", 2) == 0 || stricmp(argv[i], "--list") == 0) { if(bList) { PrintUsage(); return 2; } bList = hlTrue; if(stricmp(argv[i], "-l") == 0 || stricmp(argv[i], "--list") == 0) { // By default list everything. bListFolders = hlTrue; bListFiles = hlTrue; } else { // List folders and files if specified. bListFolders = strcspn(argv[i], "dD") != strlen(argv[i]); bListFiles = strcspn(argv[i], "fF") != strlen(argv[i]); } // Check to see if we need to dump our list to a file. if(i + 1 < uiArgumentCount && *argv[i + 1] != '-') { lpList = argv[++i]; } } else if(stricmp(argv[i], "-f") == 0 || stricmp(argv[i], "--defragment") == 0) { bDefragment = hlTrue; } else if(stricmp(argv[i], "-n") == 0 || stricmp(argv[i], "--ncfroot") == 0) { if(lpNCFRootPath == 0 && i + 1 < uiArgumentCount) { lpNCFRootPath = argv[++i]; } else { PrintUsage(); return 2; } } else if(stricmp(argv[i], "-s") == 0 || stricmp(argv[i], "--silent") == 0) { bSilent = hlTrue; } else if(stricmp(argv[i], "-c") == 0 || stricmp(argv[i], "--console") == 0) { bConsoleMode = hlTrue; } else if(stricmp(argv[i], "-x") == 0 || stricmp(argv[i], "--execute") == 0) { if(i + 1 < uiArgumentCount) { if(uiConsoleCommands == MAX_ITEMS) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading package:\nMAX_ITEMS\n"); return 2; } lpConsoleCommands[uiConsoleCommands++] = argv[++i]; } else { PrintUsage(); return 2; } } else if(stricmp(argv[i], "-m") == 0 || stricmp(argv[i], "--filemapping") == 0) { bFileMapping = hlTrue; } else if(stricmp(argv[i], "-q") == 0 || stricmp(argv[i], "--quick-filemapping") == 0) { bFileMapping = hlTrue; bQuickFileMapping = hlTrue; } else if(stricmp(argv[i], "-v") == 0 || stricmp(argv[i], "--volatile") == 0) { bVolatileAccess = hlTrue; } else if(stricmp(argv[i], "-o") == 0 || stricmp(argv[i], "--overwrite") == 0) { bOverwriteFiles = hlFalse; } else if(stricmp(argv[i], "-r") == 0 || stricmp(argv[i], "--force-defragment") == 0) { bDefragment = hlTrue; bForceDefragment = hlTrue; } else { PrintUsage(); return 2; } } } // Make sure we have something to do. if(lpPackage == 0 || (uiExtractItems == 0 && uiValidateItems == 0 && !bList && !bDefragment && !bConsoleMode)) { PrintUsage(); return 2; } // If the destination directory is not specified, make it the input directory. if(*lpDestination == 0) { const hlChar *pForward = strrchr(lpPackage, '\\'); const hlChar *pBackward = strrchr(lpPackage, '/'); const hlChar *pEnd = pForward > pBackward ? pForward : pBackward; if(pEnd != 0) { strncpy(lpDestination, lpPackage, pEnd - lpPackage); lpDestination[pEnd - lpPackage] = '\0'; } } hlInitialize(); hlSetBoolean(HL_OVERWRITE_FILES, bOverwriteFiles); hlSetBoolean(HL_FORCE_DEFRAGMENT, bForceDefragment); hlSetVoid(HL_PROC_EXTRACT_ITEM_START, ExtractItemStartCallback); hlSetVoid(HL_PROC_EXTRACT_ITEM_END, ExtractItemEndCallback); hlSetVoid(HL_PROC_EXTRACT_FILE_PROGRESS, FileProgressCallback); hlSetVoid(HL_PROC_VALIDATE_FILE_PROGRESS, FileProgressCallback); hlSetVoid(HL_PROC_DEFRAGMENT_PROGRESS_EX, DefragmentProgressCallback); // Get the package type from the filename extension. ePackageType = hlGetPackageTypeFromName(lpPackage); // If the above fails, try getting the package type from the data at the start of the file. if(ePackageType == HL_PACKAGE_NONE) { pFile = fopen(lpPackage, "rb"); if(pFile != 0) { hlByte lpBuffer[HL_DEFAULT_PACKAGE_TEST_BUFFER_SIZE]; hlUInt uiBufferSize = (hlUInt)fread(lpBuffer, 1, HL_DEFAULT_PACKAGE_TEST_BUFFER_SIZE, pFile); ePackageType = hlGetPackageTypeFromMemory(lpBuffer, uiBufferSize); fclose(pFile); pFile = 0; } } if(ePackageType == HL_PACKAGE_NONE) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading %s:\nUnsupported package type.\n", lpPackage); hlShutdown(); return 3; } // Create a package element, the element is allocated by the library and cleaned // up by the library. An ID is generated which must be bound to apply operations // to the package. if(!hlCreatePackage(ePackageType, &uiPackage)) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading %s:\n%s\n", lpPackage, hlGetString(HL_ERROR_SHORT_FORMATED)); hlShutdown(); return 3; } hlBindPackage(uiPackage); uiMode = HL_MODE_READ | (bDefragment ? HL_MODE_WRITE : 0); uiMode |= !bFileMapping ? HL_MODE_NO_FILEMAPPING : 0; uiMode |= bQuickFileMapping ? HL_MODE_QUICK_FILEMAPPING : 0; uiMode |= bVolatileAccess ? HL_MODE_VOLATILE : 0; // Open the package. // Of the above modes, only HL_MODE_READ is required. HL_MODE_WRITE is present // only for future use. File mapping is recommended as an efficient way to load // packages. Quick file mapping maps the entire file (instead of bits as they are // needed) and thus should only be used in Windows 2000 and up (older versions of // Windows have poor virtual memory management which means large files won't be able // to find a continues block and will fail to load). Volatile access allows HLLib // to share files with other applications that have those file open for writing. // This is useful for, say, loading .gcf files while Steam is running. if(!hlPackageOpenFile(lpPackage, uiMode)) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error loading %s:\n%s\n", lpPackage, hlGetString(HL_ERROR_SHORT_FORMATED)); hlShutdown(); return 3; } // If we have a .ncf file, the package file data is stored externally. In order to // validate the file data etc., HLLib needs to know where to look. Tell it where. if(ePackageType == HL_PACKAGE_NCF) { hlNCFFileSetRootPath(lpNCFRootPath); } if(!bSilent) Print(FOREGROUND_GREEN | FOREGROUND_INTENSITY, "%s opened.\n", lpPackage); // Extract the requested items. for(i = 0; i < uiExtractItems; i++) { // Find the item. pItem = hlFolderGetItemByPath(hlPackageGetRoot(), lpExtractItems[i], HL_FIND_ALL); if(pItem == 0) { printf("%s not found in package.\n", lpExtractItems[i]); continue; } if(!bSilent) { Print(FOREGROUND_GREEN | FOREGROUND_INTENSITY, "Extracting %s...\n", hlItemGetName(pItem)); printf("\n"); } // Extract the item. // Item is extracted to cDestination\Item->GetName(). hlItemExtract(pItem, lpDestination); if(!bSilent) { printf("\n"); printf("Done.\n"); } } // Validate the requested items. for(i = 0; i < uiValidateItems; i++) { // Find the item. pItem = hlFolderGetItemByPath(hlPackageGetRoot(), lpValidateItems[i], HL_FIND_ALL); if(pItem == 0) { printf("%s not found in package.\n", lpValidateItems[i]); continue; } if(!bSilent) { Print(FOREGROUND_GREEN | FOREGROUND_INTENSITY, "Validating %s...\n", hlItemGetName(pItem)); printf("\n"); } // Validate the item. Validate(pItem); if(!bSilent) { printf("\n"); printf("Done.\n"); } } // List items in package. if(bList) { if(!bSilent) { printf("Listing...\n"); printf("\n"); } pFile = stdout; if(lpList != 0) { pFile = fopen(lpList, "wt"); if(pFile == 0) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, "Error opening %s:\n%s\n", lpList, "fopen() failed."); pFile = stdout; } } List(pFile, hlPackageGetRoot(), bListFolders, bListFiles); if(lpList != 0) { fclose(pFile); pFile = 0; } if(!bSilent) { printf("\n"); printf("Done.\n"); } } if(bDefragment) { if(!bSilent) { printf("Defragmenting...\n"); printf("\n"); ProgressStart(); printf(" Progress: "); } if(!hlPackageDefragment()) { Print(FOREGROUND_RED | FOREGROUND_INTENSITY, " %s", hlGetString(HL_ERROR_SHORT_FORMATED)); } if(!bSilent) { printf("\n"); printf("\n"); printf("Done.\n"); } } // Interactive console mode. // Commands: dir, cd, root, info, extract, find, type, cls, help, exit. if(bConsoleMode) { EnterConsole(uiPackage, uiConsoleCommands, lpConsoleCommands); } // Close the package. hlPackageClose(); if(!bSilent) Print(FOREGROUND_GREEN | FOREGROUND_INTENSITY, "%s closed.\n", lpPackage); // Free up the allocated memory. hlDeletePackage(uiPackage); hlShutdown(); return 0; }