Solution0.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #include "def.hpp"
  2. // Solution0 is for navicat premium of which the version < 12.0.25
  3. namespace patcher::Solution0 {
  4. static std::Tstring InstallationPath;
  5. static const CHAR Keyword[] =
  6. "-----BEGIN PUBLIC KEY-----\r\n"
  7. "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw1dqF3SkCaAAmMzs889I\r\n"
  8. "qdW9M2dIdh3jG9yPcmLnmJiGpBF4E9VHSMGe8oPAy2kJDmdNt4BcEygvssEfginv\r\n"
  9. "a5t5jm352UAoDosUJkTXGQhpAWMF4fBmBpO3EedG62rOsqMBgmSdAyxCSPBRJIOF\r\n"
  10. "R0QgZFbRnU0frj34fiVmgYiLuZSAmIbs8ZxiHPdp1oD4tUpvsFci4QJtYNjNnGU2\r\n"
  11. "WPH6rvChGl1IRKrxMtqLielsvajUjyrgOC6NmymYMvZNER3htFEtL1eQbCyTfDmt\r\n"
  12. "YyQ1Wt4Ot12lxf0wVIR5mcGN7XCXJRHOFHSf1gzXWabRSvmt1nrl7sW6cjxljuuQ\r\n"
  13. "awIDAQAB\r\n"
  14. "-----END PUBLIC KEY-----\r\n";
  15. static const DWORD KeywordLength = sizeof(Keyword) - 1;
  16. static LPCTSTR PossibleName[3] = {
  17. TEXT("Navicat.exe"), // for Linux compatible, main program name is "Navicat.exe" in Linux, case sensitive
  18. TEXT("Modeler.exe"), // for Linux compatible
  19. TEXT("Rviewer.exe") // for Linux compatible
  20. };
  21. static LPCTSTR TargetName = NULL;
  22. static HMODULE hTarget = NULL;
  23. BOOL Init(const std::Tstring& Path) {
  24. BOOL bSuccess = FALSE;
  25. DWORD dwLastError = ERROR_SUCCESS;
  26. DWORD attr = INVALID_FILE_ATTRIBUTES;
  27. attr = GetFileAttributes(Path.c_str());
  28. if (attr == INVALID_FILE_ATTRIBUTES) {
  29. dwLastError = GetLastError();
  30. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  31. _tprintf_s(TEXT("Failed @ GetFileAttributes. CODE: 0x%08X\n"), dwLastError);
  32. goto ON_Init_ERROR;
  33. }
  34. if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
  35. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  36. _tprintf_s(TEXT("Error: Path is not a directory.\n"));
  37. goto ON_Init_ERROR;
  38. }
  39. InstallationPath = Path;
  40. if (InstallationPath.back() != TEXT('\\') && InstallationPath.back() != TEXT('/'))
  41. InstallationPath.push_back(TEXT('/')); // for Linux compatible
  42. bSuccess = TRUE;
  43. ON_Init_ERROR:
  44. return bSuccess;
  45. }
  46. BOOL CheckKey(RSACipher* cipher) {
  47. return TRUE;
  48. }
  49. BOOL FindTargetFile() {
  50. BOOL bSuccess = FALSE;
  51. DWORD dwLastError = ERROR_SUCCESS;
  52. for (size_t i = 0; i < _countof(PossibleName); ++i) {
  53. std::Tstring&& PossibleFileName = InstallationPath + PossibleName[i];
  54. hTarget = LoadLibrary(PossibleFileName.c_str());
  55. if (hTarget == NULL && (dwLastError = GetLastError()) != ERROR_MOD_NOT_FOUND) {
  56. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  57. _tprintf_s(TEXT("Unexpected Error @ LoadLibrary. CODE: 0x%08X\n"), dwLastError);
  58. goto ON_FindTargetFile_ERROR;
  59. }
  60. if (hTarget) {
  61. _tprintf_s(TEXT("Target has been found: %s\n"), PossibleName[i]);
  62. TargetName = PossibleName[i];
  63. bSuccess = TRUE;
  64. goto ON_FindTargetFile_ERROR;
  65. }
  66. }
  67. ON_FindTargetFile_ERROR:
  68. return bSuccess;
  69. }
  70. BOOL CheckFile() {
  71. BOOL bFound = FALSE;
  72. DWORD dwLastError = ERROR_SUCCESS;
  73. HRSRC hRes = NULL;
  74. HGLOBAL hGLobal = NULL;
  75. PVOID lpData = NULL;
  76. DWORD dwSize = 0;
  77. if (hTarget == NULL) {
  78. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  79. _tprintf_s(TEXT("Error: Target has not been set yet.\n"));
  80. goto ON_CheckFile_ERROR;
  81. }
  82. hRes = FindResource(hTarget, TEXT("ACTIVATIONPUBKEY"), RT_RCDATA);
  83. if (hRes == NULL) {
  84. dwLastError = GetLastError();
  85. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  86. _tprintf_s(TEXT("Failed @ FindResource. CODE: 0x%08X\n"), dwLastError);
  87. goto ON_CheckFile_ERROR;
  88. }
  89. hGLobal = LoadResource(hTarget, hRes);
  90. if (hGLobal == NULL) {
  91. dwLastError = GetLastError();
  92. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  93. _tprintf_s(TEXT("Failed @ LoadResource. CODE: 0x%08X\n"), dwLastError);
  94. goto ON_CheckFile_ERROR;
  95. }
  96. lpData = LockResource(hGLobal);
  97. if (lpData == NULL) {
  98. dwLastError = GetLastError();
  99. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  100. _tprintf_s(TEXT("Failed @ LockResource. CODE: 0x%08X\n"), dwLastError);
  101. goto ON_CheckFile_ERROR;
  102. }
  103. dwSize = SizeofResource(hTarget, hRes);
  104. if (dwSize == 0) {
  105. dwLastError = GetLastError();
  106. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  107. _tprintf_s(TEXT("Failed @ SizeofResource. CODE: 0x%08X\n"), dwLastError);
  108. goto ON_CheckFile_ERROR;
  109. }
  110. if (dwSize == KeywordLength && memcmp(lpData, Keyword, KeywordLength) == 0) {
  111. FreeLibrary(hTarget);
  112. hTarget = NULL;
  113. bFound = TRUE;
  114. } else {
  115. FreeLibrary(hTarget);
  116. hTarget = NULL;
  117. TargetName = NULL;
  118. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  119. _tprintf_s(TEXT("ERROR: Resource doest not match.\n"));
  120. goto ON_CheckFile_ERROR;
  121. }
  122. ON_CheckFile_ERROR:
  123. return bFound;
  124. }
  125. BOOL BackupFile() {
  126. BOOL bSuccess = FALSE;
  127. DWORD dwLastError = ERROR_SUCCESS;
  128. std::Tstring&& TargetFileName = InstallationPath + TargetName;
  129. std::Tstring&& BackupFileName = InstallationPath + TargetName + TEXT(".backup");
  130. if (!CopyFile(TargetFileName.c_str(), BackupFileName.c_str(), TRUE)) {
  131. dwLastError = GetLastError();
  132. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  133. _tprintf_s(TEXT("Failed @ CopyFile. CODE: 0x%08X\n"), dwLastError);
  134. goto ON_BackupFile_ERROR;
  135. }
  136. bSuccess = TRUE;
  137. ON_BackupFile_ERROR:
  138. return bSuccess;
  139. }
  140. BOOL Do(RSACipher* cipher) {
  141. BOOL bSuccess = FALSE;
  142. DWORD dwLastError = ERROR_SUCCESS;
  143. std::string RSAPublicKeyPEM;
  144. std::Tstring&& TargetFileName = InstallationPath + TargetName;
  145. HANDLE hUpdater = NULL;
  146. RSAPublicKeyPEM = cipher->ExportKeyString<RSACipher::KeyType::PublicKey, RSACipher::KeyFormat::PEM>();
  147. if (RSAPublicKeyPEM.empty()) {
  148. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  149. _tprintf_s(TEXT("ERROR: cipher->ExportKeyString failed.\n"));
  150. goto ON_Do_ERROR;
  151. }
  152. [](std::string& str, const std::string& OldSub, const std::string& NewSub) {
  153. std::string::size_type pos = 0;
  154. std::string::size_type srclen = OldSub.size();
  155. std::string::size_type dstlen = NewSub.size();
  156. while ((pos = str.find(OldSub, pos)) != std::string::npos) {
  157. str.replace(pos, srclen, NewSub);
  158. pos += dstlen;
  159. }
  160. } (RSAPublicKeyPEM, "\n", "\r\n"); // replace '\n' to '\r\n'
  161. if (RSAPublicKeyPEM.length() != KeywordLength) {
  162. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  163. _tprintf_s(TEXT("ERROR: Public key length does not match.\n"));
  164. goto ON_Do_ERROR;
  165. }
  166. hUpdater = BeginUpdateResource(TargetFileName.c_str(), FALSE);
  167. if (hUpdater == NULL) {
  168. dwLastError = GetLastError();
  169. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  170. _tprintf_s(TEXT("Failed @ BeginUpdateResource. CODE: 0x%08X\n"), dwLastError);
  171. goto ON_Do_ERROR;
  172. }
  173. if (!UpdateResource(hUpdater,
  174. RT_RCDATA,
  175. TEXT("ACTIVATIONPUBKEY"),
  176. MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
  177. (LPVOID)RSAPublicKeyPEM.c_str(),
  178. KeywordLength)) {
  179. dwLastError = GetLastError();
  180. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  181. _tprintf_s(TEXT("Failed @ UpdateResource. CODE: 0x%08X\n"), dwLastError);
  182. goto ON_Do_ERROR;
  183. }
  184. bSuccess = TRUE;
  185. ON_Do_ERROR:
  186. EndUpdateResource(hUpdater, !bSuccess);
  187. return bSuccess;
  188. }
  189. BOOL GetVersion(LPDWORD lpMajorVer, LPDWORD lpMinorVer) {
  190. BOOL bSuccess = FALSE;
  191. DWORD dwLastError = ERROR_SUCCESS;
  192. std::Tstring&& TargetFileName = InstallationPath + TargetName;
  193. DWORD dwSize = 0;
  194. PVOID lpData = NULL;
  195. VS_FIXEDFILEINFO* lpVersionInfo = NULL;
  196. UINT VersionInfoSize = 0;
  197. dwSize = GetFileVersionInfoSize(TargetFileName.c_str(),
  198. &dwSize); // MSDN doesn't say it can be NULL.
  199. // so I use dwSize to receive this deprecated value
  200. if (dwSize == 0) {
  201. dwLastError = GetLastError();
  202. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  203. _tprintf_s(TEXT("Failed @ GetFileVersionInfoSize. CODE: 0x%08X\n"), dwLastError);
  204. goto ON_GetVersion_ERROR;
  205. }
  206. lpData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
  207. if (lpData == NULL) {
  208. dwLastError = GetLastError();
  209. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  210. _tprintf_s(TEXT("Failed @ HeapAlloc. CODE: 0x%08X\n"), dwLastError);
  211. goto ON_GetVersion_ERROR;
  212. }
  213. if (!GetFileVersionInfo(TargetFileName.c_str(), NULL, dwSize, lpData)) {
  214. dwLastError = GetLastError();
  215. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  216. _tprintf_s(TEXT("Failed @ GetFileVersionInfo. CODE: 0x%08X\n"), dwLastError);
  217. goto ON_GetVersion_ERROR;
  218. }
  219. if (!VerQueryValue(lpData, TEXT("\\"), (LPVOID*)&lpVersionInfo, &VersionInfoSize)) {
  220. dwLastError = GetLastError();
  221. _tprintf_s(TEXT("@%s LINE: %u\n"), TEXT(__FUNCTION__), __LINE__);
  222. _tprintf_s(TEXT("Failed @ VerQueryValue. CODE: 0x%08X\n"), dwLastError);
  223. goto ON_GetVersion_ERROR;
  224. }
  225. *lpMajorVer = lpVersionInfo->dwProductVersionMS;
  226. *lpMinorVer = lpVersionInfo->dwProductVersionLS;
  227. bSuccess = TRUE;
  228. ON_GetVersion_ERROR:
  229. if (lpData)
  230. HeapFree(GetProcessHeap(), NULL, lpData);
  231. return bSuccess;
  232. }
  233. VOID Finalize() {
  234. if (hTarget) {
  235. FreeLibrary(hTarget);
  236. hTarget = NULL;
  237. }
  238. }
  239. }