Example #1
0
PyMODINIT_FUNC
	initpyhlextract(void)
{
	PyObject* m;

	if (PyType_Ready(&PackageType) < 0)
		return;

	m = Py_InitModule3("pyhlextract", hlextractMethods, "");

	if (m == NULL)
		return;

    if (all_ins(m))
        return;

	Py_INCREF(&PackageType);
	PyModule_AddObject(m, "Package", (PyObject *)&PackageType);

	// Initialize hllib
	hlInitialize();

	// Callbacks
	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);
}
Example #2
0
File: Main.c Project: Rupan/HLLib
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;
}