示例#1
0
static PLISTFILE_MAP ListMap_Finish(PLISTFILE_MAP pListMap)
{
    PLISTFILE_ENTRY pListEntry;
    PCASC_MAP pMap;
    LPBYTE pbEntry;

    // Sanity check
    assert(pListMap->pNameMap == NULL);
    
    // Create the map
    pListMap->pNameMap = pMap = Map_Create((DWORD)pListMap->nEntries, sizeof(ULONGLONG), 0);
    if(pListMap->pNameMap == NULL)
    {
        ListFile_FreeMap(pListMap);
        return NULL;
    }

    // Fill the map
    pbEntry = (LPBYTE)(pListMap + 1);
    for(size_t i = 0; i < pListMap->nEntries; i++)
    {
        // Get the listfile entry
        pListEntry = (PLISTFILE_ENTRY)pbEntry;
        pbEntry += pListEntry->cbEntrySize;

        // Insert the entry to the map
        Map_InsertObject(pMap, pListEntry);
    }

    return pListMap;
}
HTTP_HEADERS_HANDLE HTTPHeaders_Alloc(void)
{
    /*Codes_SRS_HTTP_HEADERS_99_002:[ This API shall produce a HTTP_HANDLE that can later be used in subsequent calls to the module.]*/
    HTTP_HEADERS_HANDLE_DATA* result;
    result = (HTTP_HEADERS_HANDLE_DATA*)malloc(sizeof(HTTP_HEADERS_HANDLE_DATA));

    if (result == NULL)
    {
        LogError("malloc failed");
    }
    else
    {
        /*Codes_SRS_HTTP_HEADERS_99_004:[ After a successful init, HTTPHeaders_GetHeaderCount shall report 0 existing headers.]*/
        result->headers = Map_Create(NULL);
        if (result->headers == NULL)
        {
            LogError("Map_Create failed");
            free(result);
            result = NULL;
        }
        else
        {
            /*all is fine*/
        }
    }

    /*Codes_SRS_HTTP_HEADERS_99_003:[ The function shall return NULL when the function cannot execute properly]*/
    return (HTTP_HEADERS_HANDLE)result;
}
示例#3
0
int RootHandler_CreateWoW6(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask)
{
    TRootHandler_WoW6 * pRootHandler;
    LPBYTE pbRootFileEnd = pbRootFile + cbRootFile;
    int nError;

    // Verify the size
    if(pbRootFile == NULL || cbRootFile <= sizeof(PFILE_LOCALE_BLOCK))
        nError = ERROR_FILE_CORRUPT;

    // Allocate the root handler object
    hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_WoW6, 1);
    if(pRootHandler == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    // Fill-in the handler functions
    memset(pRootHandler, 0, sizeof(TRootHandler_WoW6));
    pRootHandler->Insert      = (ROOT_INSERT)WowHandler_Insert;
    pRootHandler->Search      = (ROOT_SEARCH)WowHandler_Search;
    pRootHandler->EndSearch   = (ROOT_ENDSEARCH)WowHandler_EndSearch;
    pRootHandler->GetKey      = (ROOT_GETKEY)WowHandler_GetKey;
    pRootHandler->Close       = (ROOT_CLOSE)WowHandler_Close;

#ifdef _DEBUG
    pRootHandler->Dump = TRootHandlerWoW6_Dump;    // Support for ROOT file dump
#endif  // _DEBUG

    // Count the files that are going to be loaded
    ParseWowRootFile(pRootHandler, ParseRoot_CountFiles, pbRootFile, pbRootFileEnd, dwLocaleMask);
    pRootHandler->dwTotalFileCount += CASC_EXTRA_FILES;

    // Create linear table that will contain all root items
    nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, pRootHandler->dwTotalFileCount);
    if(nError != ERROR_SUCCESS)
        return nError;

    // Create sorted table that will contain all root items to lookup by FileDataId
    nError = Array_Create(&pRootHandler->FileDataIdLookupTable, PCASC_FILE_ENTRY, pRootHandler->dwTotalFileCount);
    if (nError != ERROR_SUCCESS)
        return nError;

    // Create the map of FileHash ->FileEntry
    pRootHandler->pRootMap = Map_Create(pRootHandler->dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash));
    if(pRootHandler->pRootMap == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    // Parse the root file again and insert all files to the map
    ParseWowRootFile(pRootHandler, ParseRoot_AddRootEntries, pbRootFile, pbRootFileEnd, dwLocaleMask);

    // Sort entries by FileDataId for searches
    qsort_pointer_array((void**)pRootHandler->FileDataIdLookupTable.ItemArray, pRootHandler->FileDataIdLookupTable.ItemCount, &FileDataIdCompare, NULL);
    return ERROR_SUCCESS;
}
示例#4
0
IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source)
{
    IOTHUB_MESSAGE_HANDLE_DATA* result;
    if (source == NULL)
    {
        LogError("Invalid argument - source is NULL");
        result = NULL;
    }
    else
    {
        result = (IOTHUB_MESSAGE_HANDLE_DATA*)malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
        if (result == NULL)
        {
            LogError("malloc failed");
            /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
            /*let it go through*/
        }
        else
        {
            memset(result, 0, sizeof(*result));
            /*Codes_SRS_IOTHUBMESSAGE_02_032: [The type of the new message shall be IOTHUBMESSAGE_STRING.] */
            result->contentType = IOTHUBMESSAGE_STRING;
            
            /*Codes_SRS_IOTHUBMESSAGE_02_027: [IoTHubMessage_CreateFromString shall call STRING_construct passing source as parameter.] */
            if ((result->value.string = STRING_construct(source)) == NULL)
            {
                LogError("STRING_construct failed");
                /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
                DestroyMessageData(result);
                result = NULL;
            }
            /*Codes_SRS_IOTHUBMESSAGE_02_028: [IoTHubMessage_CreateFromString shall call Map_Create to create the message properties.] */
            else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
            {
                LogError("Map_Create for properties failed");
                /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
                DestroyMessageData(result);
                result = NULL;
            }
            /*Codes_SRS_IOTHUBMESSAGE_02_031: [Otherwise, IoTHubMessage_CreateFromString shall return a non-NULL handle.] */
        }
    }
    return result;
}
示例#5
0
IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromString(const char* source)
{
    IOTHUB_MESSAGE_HANDLE_DATA* result;
    result = malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
    if (result == NULL)
    {
        LogError("malloc failed\r\n");
        /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
        /*let it go through*/
    }
    else
    {
        /*Codes_SRS_IOTHUBMESSAGE_02_027: [IoTHubMessage_CreateFromString shall call STRING_construct passing source as parameter.] */
        if ((result->value.string = STRING_construct(source)) == NULL)
        {
            LogError("STRING_construct failed\r\n");
            /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
            free(result);
            result = NULL;
        }
        /*Codes_SRS_IOTHUBMESSAGE_02_028: [IoTHubMessage_CreateFromString shall call Map_Create to create the message properties.] */
        else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
        {
            LogError("Map_Create failed\r\n");
            /*Codes_SRS_IOTHUBMESSAGE_02_029: [If there are any encountered in the execution of IoTHubMessage_CreateFromString then IoTHubMessage_CreateFromString shall return NULL.] */
            STRING_delete(result->value.string);
            free(result);
            result = NULL;
        }
        else
        {
            /*Codes_SRS_IOTHUBMESSAGE_02_031: [Otherwise, IoTHubMessage_CreateFromString shall return a non-NULL handle.] */
            /*Codes_SRS_IOTHUBMESSAGE_02_032: [The type of the new message shall be IOTHUBMESSAGE_STRING.] */
            result->contentType = IOTHUBMESSAGE_STRING;
            result->messageId = NULL;
            result->correlationId = NULL;
        }
    }
    return result;
}
// Creates a map of String -> Pointer
static PCASC_MAP CreatePackageMap(
    LPBYTE pbPackagesDat,
    LPBYTE pbPackagesEnd)
{
    PDIABLO3_PACKAGES_DAT_HEADER pDatHeader = (PDIABLO3_PACKAGES_DAT_HEADER)pbPackagesDat;
    PCASC_MAP pPackageMap;

    // Get the header
    if((pbPackagesDat + sizeof(DIABLO3_PACKAGES_DAT_HEADER)) >= pbPackagesEnd)
        return NULL;
    pbPackagesDat += sizeof(DIABLO3_PACKAGES_DAT_HEADER);

    // Check the signature and name count
    if(pDatHeader->Signature != DIABLO3_PACKAGES_SIGNATURE)
        return NULL;

    // Create the map for fast search of the file name
    pPackageMap = Map_Create(pDatHeader->NumberOfNames, KEY_LENGTH_STRING, 0);
    if(pPackageMap != NULL)
    {
        char * szFileName = (char *)pbPackagesDat;

        // Go as long as there is something
        for(DWORD i = 0; i < pDatHeader->NumberOfNames; i++)
        {
            // Get the file extension
            if((LPBYTE)szFileName >= pbPackagesEnd)
                break;

            // Insert the file name to the map. The file extension is not included
            Map_InsertString(pPackageMap, szFileName, true);
            szFileName = szFileName + strlen(szFileName) + 1;
        }
    }

    return pPackageMap;
}
示例#7
0
IOTHUB_MESSAGE_HANDLE IoTHubMessage_CreateFromByteArray(const unsigned char* byteArray, size_t size)
{
    IOTHUB_MESSAGE_HANDLE_DATA* result;
    result = malloc(sizeof(IOTHUB_MESSAGE_HANDLE_DATA));
    if (result == NULL)
    {
        LogError("unable to malloc\r\n");
        /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
        /*let it go through*/
    }
    else
    {
        const unsigned char* source;
        unsigned char temp = 0x00;
        if (size != 0)
        {
            /*Codes_SRS_IOTHUBMESSAGE_06_002: [If size is NOT zero then byteArray MUST NOT be NULL*/
            if (byteArray == NULL)
            {
                LogError("Attempted to create a Hub Message from a NULL pointer!\r\n");
                free(result);
                result = NULL;
                source = NULL;
            }
            else
            {
                source = byteArray;
            }
        }
        else
        {
            /*Codes_SRS_IOTHUBMESSAGE_06_001: [If size is zero then byteArray may be NULL.]*/
            source = &temp;
        }
        if (result != NULL)
        {
            /*Codes_SRS_IOTHUBMESSAGE_02_022: [IoTHubMessage_CreateFromByteArray shall call BUFFER_create passing byteArray and size as parameters.] */
            if ((result->value.byteArray = BUFFER_create(source, size)) == NULL)
            {
                LogError("BUFFER_create failed\r\n");
                /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
                free(result);
                result = NULL;
            }
            /*Codes_SRS_IOTHUBMESSAGE_02_023: [IoTHubMessage_CreateFromByteArray shall call Map_Create to create the message properties.] */
            else if ((result->properties = Map_Create(ValidateAsciiCharactersFilter)) == NULL)
            {
                LogError("Map_Create failed\r\n");
                /*Codes_SRS_IOTHUBMESSAGE_02_024: [If there are any errors then IoTHubMessage_CreateFromByteArray shall return NULL.] */
                BUFFER_delete(result->value.byteArray);
                free(result);
                result = NULL;
            }
            else
            {
                /*Codes_SRS_IOTHUBMESSAGE_02_025: [Otherwise, IoTHubMessage_CreateFromByteArray shall return a non-NULL handle.] */
                /*Codes_SRS_IOTHUBMESSAGE_02_026: [The type of the new message shall be IOTHUBMESSAGE_BYTEARRAY.] */
                result->contentType = IOTHUBMESSAGE_BYTEARRAY;
                result->messageId = NULL;
                result->correlationId = NULL;
                /*all is fine, return result*/
            }
        }
    }
    return result;
}
示例#8
0
static int SimulatorModule_create_message(SIMULATOR_MODULE_HANDLE * module, MESSAGE_CONFIG* message)
{
    int thread_result;
    MAP_HANDLE property_map = Map_Create(NULL);
    if (property_map == NULL)
    {
        LogError("Allocation of properties map failed.");
        thread_result = -__LINE__;
    }
    else
    {
        std::string property_string(module->psuedo_random_buffer, module->properties_size);
        std::string property_count_string = std::to_string(module->properties_count);

        if (property_string.empty() || property_count_string.empty())
        {
            LogError("Allocation of properties string failed.");
            Map_Destroy(property_map);
            thread_result = -__LINE__;
        }
        else
        {
            if (Map_Add(property_map, "deviceId", module->device_id) != MAP_OK)
            {
                Map_Destroy(property_map);
                thread_result = -__LINE__;
            }
            else if (Map_Add(property_map, "property count", property_count_string.c_str()) != MAP_OK)
            {
                Map_Destroy(property_map);
                thread_result = -__LINE__;
            }
            else
            {
                thread_result = 0;
                for (size_t p = 0; p < module->properties_count; p++)
                {
                    std::ostringstream property_n;
                    property_n << "property" << p;
                    if (Map_Add(property_map, property_n.str().c_str(), property_string.c_str()))
                    {
                        thread_result = -__LINE__;
                        break;
                    }
                }
                if (thread_result != 0)
                {
                    Map_Destroy(property_map);
                    thread_result = -__LINE__;
                }
                else
                {
                    message->source = (const unsigned char*)malloc(module->message_size);
                    if (message->source == NULL)
                    {
                        LogError("unable to allocate message buffer");
                        Map_Destroy(property_map);
                        thread_result = -__LINE__;
                    }
                    else
                    {
                        message->sourceProperties = property_map;
                        message->size = module->message_size;
                        if (module->message_size == 0)
                        {
                            message->source = NULL;
                        }
                        else
                        {
                            memcpy((void*)message->source, module->psuedo_random_buffer, message->size - 1);
                            ((char*)(message->source))[message->size - 1] = '\0';
                        }
                        thread_result = 0;
                    }

                }
            }
        }
    }
    return thread_result;
}
/* Codes_SRS_CONNECTIONSTRINGPARSER_01_001: [connectionstringparser_parse shall parse all key value pairs from the connection_string passed in as argument and return a new map that holds the key/value pairs.] */
MAP_HANDLE connectionstringparser_parse(STRING_HANDLE connection_string)
{
    MAP_HANDLE result;

    if (connection_string == NULL)
    {
        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_002: [If connection_string is NULL then connectionstringparser_parse shall fail and return NULL.] */
        result = NULL;
        LogError("NULL connection string passed to tokenizer.");
    }
    else
    {
        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_003: [connectionstringparser_parse shall create a STRING tokenizer to be used for parsing the connection string, by calling STRING_TOKENIZER_create.] */
        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_004: [connectionstringparser_parse shall start scanning at the beginning of the connection string.] */
        STRING_TOKENIZER_HANDLE tokenizer = STRING_TOKENIZER_create(connection_string);
        if (tokenizer == NULL)
        {
            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_015: [If STRING_TOKENIZER_create fails, connectionstringparser_parse shall fail and return NULL.] */
            result = NULL;
            LogError("Error creating STRING tokenizer.");
        }
        else
        {
            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_016: [2 STRINGs shall be allocated in order to hold the to be parsed key and value tokens.] */
            STRING_HANDLE token_key_string = STRING_new();
            if (token_key_string == NULL)
            {
                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
                result = NULL;
                LogError("Error creating key token STRING.");
            }
            else
            {
                STRING_HANDLE token_value_string = STRING_new();
                if (token_value_string == NULL)
                {
                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_017: [If allocating the STRINGs fails connectionstringparser_parse shall fail and return NULL.] */
                    result = NULL;
                    LogError("Error creating value token STRING.");
                }
                else
                {
                    result = Map_Create(NULL);
                    if (result == NULL)
                    {
                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_018: [If creating the result map fails, then connectionstringparser_parse shall return NULL.] */
                        LogError("Error creating Map.");
                    }
                    else
                    {
                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_005: [The following actions shall be repeated until parsing is complete:] */
                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_006: [connectionstringparser_parse shall find a token (the key of the key/value pair) delimited by the `=` character, by calling STRING_TOKENIZER_get_next_token.] */
                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_007: [If STRING_TOKENIZER_get_next_token fails, parsing shall be considered complete.] */
                        while (STRING_TOKENIZER_get_next_token(tokenizer, token_key_string, "=") == 0)
                        {
                            bool is_error = false;

                            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_008: [connectionstringparser_parse shall find a token (the value of the key/value pair) delimited by the `;` character, by calling STRING_TOKENIZER_get_next_token.] */
                            if (STRING_TOKENIZER_get_next_token(tokenizer, token_value_string, ";") != 0)
                            {
                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_009: [If STRING_TOKENIZER_get_next_token fails, connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
                                is_error = true;
                                LogError("Error reading value token from the connection string.");
                            }
                            else
                            {
                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
                                const char* token = STRING_c_str(token_key_string);
                                /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
                                if ((token == NULL) ||
                                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_019: [If the key length is zero then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
                                    (strlen(token) == 0))
                                {
                                    is_error = true;
                                    LogError("The key token is NULL or empty.");
                                }
                                else
                                {
                                    /* Codes_SRS_CONNECTIONSTRINGPARSER_01_011: [The C strings for the key and value shall be extracted from the previously parsed STRINGs by using STRING_c_str.] */
                                    const char* value = STRING_c_str(token_value_string);
                                    if (value == NULL)
                                    {
                                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_013: [If STRING_c_str fails then connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
                                        is_error = true;
                                        LogError("Could not get C string for value token.");
                                    }
                                    else
                                    {
                                        /* Codes_SRS_CONNECTIONSTRINGPARSER_01_010: [The key and value shall be added to the result map by using Map_Add.] */
                                        if (Map_Add(result, token, value) != 0)
                                        {
                                            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_012: [If Map_Add fails connectionstringparser_parse shall fail and return NULL (freeing the allocated result map).] */
                                            is_error = true;
                                            LogError("Could not add the key/value pair to the result map.");
                                        }
                                    }
                                }
                            }

                            if (is_error)
                            {
                                LogError("Error parsing connection string.");
                                Map_Destroy(result);
                                result = NULL;
                                break;
                            }
                        }
                    }

                    STRING_delete(token_value_string);
                }

                STRING_delete(token_key_string);
            }

            /* Codes_SRS_CONNECTIONSTRINGPARSER_01_014: [After the parsing is complete the previously allocated STRINGs and STRING tokenizer shall be freed by calling STRING_TOKENIZER_destroy.] */
            STRING_TOKENIZER_destroy(tokenizer);
        }
    }

    return result;
}
MAP_HANDLE Map_Clone(MAP_HANDLE handle)
{
    (void)handle;
	return Map_Create(mockFilterFunc);
}
示例#11
0
int RootHandler_CreateDiablo3(TCascStorage * hs, LPBYTE pbRootFile, DWORD cbRootFile)
{
    TRootHandler_Diablo3 * pRootHandler;
    PCASC_MAP pPackageMap = NULL;
    LPBYTE pbRootFileEnd = pbRootFile + cbRootFile;
    LPBYTE pbPackagesDat = NULL;
    DWORD dwTotalFileCount;
    DWORD cbPackagesDat = 0;
    int nError;

    // Allocate the root handler object
    hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_Diablo3, 1);
    if(pRootHandler == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    // Fill-in the handler functions
    memset(pRootHandler, 0, sizeof(TRootHandler_Diablo3));
    pRootHandler->Insert      = (ROOT_INSERT)D3Handler_Insert;
    pRootHandler->Search      = (ROOT_SEARCH)D3Handler_Search;
    pRootHandler->EndSearch   = (ROOT_ENDSEARCH)D3Handler_EndSearch;
    pRootHandler->GetKey      = (ROOT_GETKEY)D3Handler_GetKey;
    pRootHandler->Close       = (ROOT_CLOSE)D3Handler_Close;
    pRootHandler->GetFileId   = (ROOT_GETFILEID)D3Handler_GetFileId;

    // Fill-in the flags
    pRootHandler->dwRootFlags |= ROOT_FLAG_HAS_NAMES;

    // Scan the total number of files in the root directories
    // Reserve space for extra files
    dwTotalFileCount = ScanDirectoryFile(hs, pbRootFile, pbRootFileEnd);
    if(dwTotalFileCount == 0)
        return ERROR_FILE_CORRUPT;
    dwTotalFileCount += CASC_EXTRA_FILES;

    // Allocate the global linear file table
    // Note: This is about 18 MB of memory for Diablo III PTR build 30013
    nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, dwTotalFileCount);
    if(nError != ERROR_SUCCESS)
        return nError;

    // Allocate global buffer for file names.
    // The size of the buffer was taken from Diablo III build 30013
    nError = Array_Create(&pRootHandler->FileNames, char, 0x01000000);
    if(nError != ERROR_SUCCESS)
        return nError;

    // Create map of ROOT_ENTRY -> FileEntry
    pRootHandler->pRootMap = Map_Create(dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash));
    if(pRootHandler->pRootMap == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    // Parse the ROOT file and insert all entries in the file table
    nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFileEnd, DIABLO3_INVALID_INDEX);
    if(nError == ERROR_SUCCESS)
    {
        size_t dwRootEntries = pRootHandler->FileTable.ItemCount;

        // We expect the number of level-0 to be less than maximum
        assert(dwRootEntries < DIABLO3_MAX_SUBDIRS);

        // Now parse the all root items and load them
        for(DWORD i = 0; i < dwRootEntries; i++)
        {
            PCASC_FILE_ENTRY pRootEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, i);

            // Load the entire file to memory
            pbRootFile = LoadFileToMemory(hs, pRootEntry->EncodingKey.Value, &cbRootFile);
            if(pbRootFile != NULL)
            {
                nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFile + cbRootFile, i);
                CASC_FREE(pbRootFile);
            }
        }
    }

    // Note: The file "Base\Data_D3\PC\Misc\Packages.dat" contains the names
    // of the files (without level-0 and level-1 directory). We can use these
    // names for supplying the missing extensions
    if(nError == ERROR_SUCCESS)
    {
        // Load the entire file to memory
        pbPackagesDat = LoadFileToMemory(hs, "Base\\Data_D3\\PC\\Misc\\Packages.dat", &cbPackagesDat);
        if(pbPackagesDat != NULL)
        {
            pPackageMap = CreatePackageMap(pbPackagesDat, pbPackagesDat + cbPackagesDat);
        }
    }

    // Vast majorify of files at this moment don't have names.
    // We can load the Base\CoreTOC.dat file in order
    // to get directory asset indexes, file names and extensions
    if(nError == ERROR_SUCCESS)
    {
        LPBYTE pbCoreTOC;
        DWORD cbCoreTOC = 0;

        // Load the entire file to memory
        pbCoreTOC = LoadFileToMemory(hs, "Base\\CoreTOC.dat", &cbCoreTOC);
        if(pbCoreTOC != NULL)
        {
            ParseCoreTOC(pRootHandler, pPackageMap, pbCoreTOC, pbCoreTOC + cbCoreTOC);
            CASC_FREE(pbCoreTOC);
        }
    }

    // Free the packages map
    if(pPackageMap != NULL)
        Map_Free(pPackageMap);
    if(pbPackagesDat != NULL)
        CASC_FREE(pbPackagesDat);
    return nError;
}