[Scummvm-git-logs] scummvm master -> 558b07584e8310c6e607acc6fb199be5ec21a5aa

bluegr bluegr at gmail.com
Tue Jun 18 23:15:52 CEST 2019


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
558b07584e CREATE_PROJECT: Use name-based UUIDs for MSVC projects


Commit: 558b07584e8310c6e607acc6fb199be5ec21a5aa
    https://github.com/scummvm/scummvm/commit/558b07584e8310c6e607acc6fb199be5ec21a5aa
Author: SupSuper (supsuper at gmail.com)
Date: 2019-06-19T00:15:48+03:00

Commit Message:
CREATE_PROJECT: Use name-based UUIDs for MSVC projects

This keeps the project UUIDs consistent between regenerations,
avoiding excessive workspace reloads.

Changed paths:
    devtools/create_project/create_project.cpp
    devtools/create_project/create_project.h
    devtools/create_project/msvc.cpp


diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index d2216c7..82ba9b5 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 1f3e91f..19c2ba0 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 8781005..c3513ec 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)





More information about the Scummvm-git-logs mailing list