aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSupSuper2019-06-16 00:19:38 +0100
committerFilippos Karapetis2019-06-19 00:15:48 +0300
commit558b07584e8310c6e607acc6fb199be5ec21a5aa (patch)
tree3d5a190b46fc4fc0c630fd8870ac9e7cb1fc366b
parentf7110bffd1b56139f7fbeff3fa3f4ca92370f648 (diff)
downloadscummvm-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.cpp79
-rw-r--r--devtools/create_project/create_project.h17
-rw-r--r--devtools/create_project/msvc.cpp2
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)