diff options
author | SupSuper | 2019-06-16 00:19:38 +0100 |
---|---|---|
committer | Filippos Karapetis | 2019-06-19 00:15:48 +0300 |
commit | 558b07584e8310c6e607acc6fb199be5ec21a5aa (patch) | |
tree | 3d5a190b46fc4fc0c630fd8870ac9e7cb1fc366b | |
parent | f7110bffd1b56139f7fbeff3fa3f4ca92370f648 (diff) | |
download | scummvm-rg350-558b07584e8310c6e607acc6fb199be5ec21a5aa.tar.gz scummvm-rg350-558b07584e8310c6e607acc6fb199be5ec21a5aa.tar.bz2 scummvm-rg350-558b07584e8310c6e607acc6fb199be5ec21a5aa.zip |
CREATE_PROJECT: Use name-based UUIDs for MSVC projects
This keeps the project UUIDs consistent between regenerations,
avoiding excessive workspace reloads.
-rw-r--r-- | devtools/create_project/create_project.cpp | 79 | ||||
-rw-r--r-- | devtools/create_project/create_project.h | 17 | ||||
-rw-r--r-- | devtools/create_project/msvc.cpp | 2 |
3 files changed, 87 insertions, 11 deletions
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp index d2216c7324..82ba9b5252 100644 --- a/devtools/create_project/create_project.cpp +++ b/devtools/create_project/create_project.cpp @@ -1496,7 +1496,7 @@ void ProjectProvider::createProject(BuildSetup &setup) { } // We also need to add the UUID of the main project file. - const std::string svmUUID = _uuidMap[setup.projectName] = createUUID(); + const std::string svmUUID = _uuidMap[setup.projectName] = createUUID(setup.projectName); createWorkspace(setup); @@ -1581,7 +1581,7 @@ ProjectProvider::UUIDMap ProjectProvider::createUUIDMap(const BuildSetup &setup) if (!i->enable || isSubEngine(i->name, setup.engines)) continue; - result[i->name] = createUUID(); + result[i->name] = createUUID(i->name); } return result; @@ -1595,17 +1595,20 @@ ProjectProvider::UUIDMap ProjectProvider::createToolsUUIDMap() const { if (!i->enable) continue; - result[i->name] = createUUID(); + result[i->name] = createUUID(i->name); } return result; } +const int kUUIDLen = 16; + std::string ProjectProvider::createUUID() const { #ifdef USE_WIN32_API UUID uuid; - if (UuidCreate(&uuid) != RPC_S_OK) - error("UuidCreate failed"); + RPC_STATUS status = UuidCreateSequential(&uuid); + if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) + error("UuidCreateSequential failed"); unsigned char *string = 0; if (UuidToStringA(&uuid, &string) != RPC_S_OK) @@ -1616,25 +1619,81 @@ std::string ProjectProvider::createUUID() const { RpcStringFreeA(&string); return result; #else - unsigned char uuid[16]; + unsigned char uuid[kUUIDLen]; - for (int i = 0; i < 16; ++i) + for (int i = 0; i < kUUIDLen; ++i) uuid[i] = (unsigned char)((std::rand() / (double)(RAND_MAX)) * 0xFF); uuid[8] &= 0xBF; uuid[8] |= 0x80; uuid[6] &= 0x4F; uuid[6] |= 0x40; + return UUIDToString(uuid); +#endif +} + +std::string ProjectProvider::createUUID(const std::string &name) const { +#ifdef USE_WIN32_API + HCRYPTPROV hProv = NULL; + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + error("CryptAcquireContext failed"); + } + + // Use MD5 hashing algorithm + HCRYPTHASH hHash = NULL; + if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)) { + CryptReleaseContext(hProv, 0); + error("CryptCreateHash failed"); + } + + // Hash unique ScummVM namespace {5f5b43e8-35ff-4f1e-ad7e-a2a87e9b5254} + const BYTE uuidNs[kUUIDLen] = + { 0x5f, 0x5b, 0x43, 0xe8, 0x35, 0xff, 0x4f, 0x1e, 0xad, 0x7e, 0xa2, 0xa8, 0x7e, 0x9b, 0x52, 0x54 }; + if (!CryptHashData(hHash, uuidNs, kUUIDLen, 0)) { + CryptDestroyHash(hHash); + CryptReleaseContext(hProv, 0); + error("CryptHashData failed"); + } + + // Hash project name + if (!CryptHashData(hHash, (const BYTE *)name.c_str(), name.length(), 0)) { + CryptDestroyHash(hHash); + CryptReleaseContext(hProv, 0); + error("CryptHashData failed"); + } + + // Get resulting UUID + BYTE uuid[kUUIDLen]; + DWORD len = kUUIDLen; + if (!CryptGetHashParam(hHash, HP_HASHVAL, uuid, &len, 0)) { + CryptDestroyHash(hHash); + CryptReleaseContext(hProv, 0); + error("CryptGetHashParam failed"); + } + + // Add version and variant + uuid[6] &= 0x0F; uuid[6] |= 0x30; + uuid[8] &= 0x3F; uuid[8] |= 0x80; + + CryptDestroyHash(hHash); + CryptReleaseContext(hProv, 0); + + return UUIDToString(uuid); +#else + // Fallback to random UUID + return createUUID(); +#endif +} + +std::string ProjectProvider::UUIDToString(unsigned char *uuid) const { std::stringstream uuidString; uuidString << std::hex << std::uppercase << std::setfill('0'); - for (int i = 0; i < 16; ++i) { + for (int i = 0; i < kUUIDLen; ++i) { uuidString << std::setw(2) << (int)uuid[i]; if (i == 3 || i == 5 || i == 7 || i == 9) { uuidString << std::setw(0) << '-'; } } - return uuidString.str(); -#endif } std::string ProjectProvider::getLastPathComponent(const std::string &path) { diff --git a/devtools/create_project/create_project.h b/devtools/create_project/create_project.h index 1f3e91f7b4..19c2ba094b 100644 --- a/devtools/create_project/create_project.h +++ b/devtools/create_project/create_project.h @@ -581,7 +581,24 @@ protected: */ std::string createUUID() const; + /** + * Creates a name-based UUID and returns it in string representation. + * + * @param name Unique name to hash. + * @return A new UUID as string. + */ + std::string createUUID(const std::string &name) const; + private: + + /** + * Returns the string representation of an existing UUID. + * + * @param uuid 128-bit array. + * @return Existing UUID as string. + */ + std::string UUIDToString(unsigned char *uuid) const; + /** * This creates the engines/plugins_table.h file required for building * ScummVM. diff --git a/devtools/create_project/msvc.cpp b/devtools/create_project/msvc.cpp index 8781005d56..c3513ec4e6 100644 --- a/devtools/create_project/msvc.cpp +++ b/devtools/create_project/msvc.cpp @@ -46,7 +46,7 @@ void MSVCProvider::createWorkspace(const BuildSetup &setup) { const std::string svmProjectUUID = svmUUID->second; assert(!svmProjectUUID.empty()); - std::string solutionUUID = createUUID(); + std::string solutionUUID = createUUID(setup.projectName + ".sln"); std::ofstream solution((setup.outputDir + '/' + setup.projectName + ".sln").c_str()); if (!solution) |