From 3b0b08726257a2fe8dd87ef79ba2d7d228c24c99 Mon Sep 17 00:00:00 2001 From: Kearwood Kip Gilbert Date: Sat, 17 Aug 2019 21:57:55 -0700 Subject: [PATCH] Fix KRDataBlock crashes on Win32 --- kraken/KRContext.cpp | 34 +++++++++++++++---------------- kraken/KRDataBlock.cpp | 45 +++++++++++++++++++++++++++++++++++++++--- kraken/KRResource.cpp | 4 ++++ tools/convert/main.cpp | 2 +- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/kraken/KRContext.cpp b/kraken/KRContext.cpp index 29b1541..255584c 100755 --- a/kraken/KRContext.cpp +++ b/kraken/KRContext.cpp @@ -321,34 +321,34 @@ void KRContext::loadResource(std::string path) { } } -KrResult KRContext::unloadResource(const KrUnloadResourceInfo* unloadResourceInfo) -{ - if (unloadResourceInfo->resourceHandle < 0 || unloadResourceInfo->resourceHandle >= m_resourceMapSize) { - return KR_ERROR_OUT_OF_BOUNDS; - } - KRResource* resource = m_resourceMap[unloadResourceInfo->resourceHandle]; - if (resource == nullptr) { - return KR_ERROR_NOT_MAPPED; - } - // TODO - Need to implement unloading logic +KrResult KRContext::unloadResource(const KrUnloadResourceInfo* unloadResourceInfo) +{ + if (unloadResourceInfo->resourceHandle < 0 || unloadResourceInfo->resourceHandle >= m_resourceMapSize) { + return KR_ERROR_OUT_OF_BOUNDS; + } + KRResource* resource = m_resourceMap[unloadResourceInfo->resourceHandle]; + if (resource == nullptr) { + return KR_ERROR_NOT_MAPPED; + } + // TODO - Need to implement unloading logic return KR_ERROR_NOT_IMPLEMENTED; } KrResult KRContext::createBundle(const KrCreateBundleInfo* createBundleInfo) { - if (createBundleInfo->resourceHandle < 0 || createBundleInfo->resourceHandle >= m_resourceMapSize) { - return KR_ERROR_OUT_OF_BOUNDS; + if (createBundleInfo->resourceHandle < 0 || createBundleInfo->resourceHandle >= m_resourceMapSize) { + return KR_ERROR_OUT_OF_BOUNDS; } - KRResource* bundle = m_pBundleManager->createBundle(createBundleInfo->pBundleName); - m_resourceMap[createBundleInfo->resourceHandle] = bundle; - + KRResource* bundle = m_pBundleManager->createBundle(createBundleInfo->pBundleName); + m_resourceMap[createBundleInfo->resourceHandle] = bundle; + return KR_SUCCESS; } KrResult KRContext::saveResource(const KrSaveResourceInfo* saveResourceInfo) { - if (saveResourceInfo->resourceHandle < 0 || saveResourceInfo->resourceHandle >= m_resourceMapSize) { - return KR_ERROR_OUT_OF_BOUNDS; + if (saveResourceInfo->resourceHandle < 0 || saveResourceInfo->resourceHandle >= m_resourceMapSize) { + return KR_ERROR_OUT_OF_BOUNDS; } KRResource* resource = m_resourceMap[saveResourceInfo->resourceHandle]; if (resource == nullptr) { diff --git a/kraken/KRDataBlock.cpp b/kraken/KRDataBlock.cpp index 5ec81a5..60d13ee 100755 --- a/kraken/KRDataBlock.cpp +++ b/kraken/KRDataBlock.cpp @@ -95,7 +95,10 @@ void KRDataBlock::unload() #if defined(_WIN32) || defined(_WIN64) if (m_hPackFile != INVALID_HANDLE_VALUE) { - CloseHandle(m_hPackFile); + // Memory mapped file + if (m_fileOwnerDataBlock == this) { + CloseHandle(m_hPackFile); + } m_hPackFile = INVALID_HANDLE_VALUE; } #elif defined(__APPLE__) @@ -414,6 +417,36 @@ std::string KRDataBlock::getString() return ret; } +#if defined(_WIN32) || defined(_WIN64) +void ReportWindowsLastError(LPCTSTR lpszFunction) +{ + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, + 0, NULL); + + // Display the error message and exit the process + + lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); + fprintf(stderr, + TEXT("%s failed with error %d: %s\n"), + lpszFunction, dw, lpMsgBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); +} +#endif + // Lock the memory, forcing it to be loaded into a contiguous block of address space void KRDataBlock::lock() { @@ -421,7 +454,7 @@ void KRDataBlock::lock() // Memory mapped file; ensure data is mapped to ram #if defined(_WIN32) || defined(_WIN64) - if(m_hFileMapping) { + if(m_hPackFile != INVALID_HANDLE_VALUE) { #elif defined(__APPLE__) || defined(ANDROID) if(m_fdPackFile) { #else @@ -436,9 +469,15 @@ void KRDataBlock::lock() assert(m_mmapData == NULL); #if defined(_WIN32) || defined(_WIN64) m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_data_size, NULL); + if(m_hFileMapping == NULL) { + ReportWindowsLastError("CreateFileMappingFromApp"); + } assert(m_hFileMapping != NULL); - m_mmapData = MapViewOfFileFromApp(m_hPackFile, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset); + m_mmapData = MapViewOfFileFromApp(m_hFileMapping, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset); + if(m_mmapData == NULL) { + ReportWindowsLastError("MapViewOfFileFromApp"); + } assert(m_mmapData != NULL); #elif defined(__APPLE__) || defined(ANDROID) //fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount); diff --git a/kraken/KRResource.cpp b/kraken/KRResource.cpp index b72db4e..fbd0ada 100755 --- a/kraken/KRResource.cpp +++ b/kraken/KRResource.cpp @@ -33,6 +33,10 @@ std::string KRResource::GetFileExtension(const std::string& name) std::string KRResource::GetFileBase(const std::string& name) { std::string f = name; + + // Normalize Windows Paths + std::replace(f.begin(), f.end(), '\\', '/'); + // Strip off directory if(f.find_last_of("/") != std::string::npos) { f = f.substr(f.find_last_of("/") + 1); diff --git a/tools/convert/main.cpp b/tools/convert/main.cpp index 52f10e4..d642b0c 100644 --- a/tools/convert/main.cpp +++ b/tools/convert/main.cpp @@ -37,7 +37,7 @@ int main( int argc, char *argv[] ) move_to_bundle_info.sType = KR_STRUCTURE_TYPE_MOVE_TO_BUNDLE; move_to_bundle_info.bundleHandle = 0; - for (int i = 0; i < argc; i++) { + for (int i = 1; i < argc; i++) { char *arg = argv[i]; if (arg[0] != '-') { load_resource_info.pResourcePath = arg;