diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-29 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2024-11-30 15:27:15 +0500 |
| commit | e5431fa6f5505e385c6f9367260717e9c47dc2ee (patch) | |
| tree | 4cd2c2c3b225b48c8e7053432c41d7b6b6a3d5f8 /CPP/Windows | |
| parent | e008ce3976c087bfd21344af8f00a23cf69d4174 (diff) | |
| download | 7zip-24.09.tar.gz 7zip-24.09.tar.bz2 7zip-24.09.zip | |
24.0924.09
Diffstat (limited to 'CPP/Windows')
| -rw-r--r-- | CPP/Windows/FileDir.cpp | 138 | ||||
| -rw-r--r-- | CPP/Windows/FileDir.h | 23 | ||||
| -rw-r--r-- | CPP/Windows/FileName.cpp | 8 | ||||
| -rw-r--r-- | CPP/Windows/Registry.cpp | 295 | ||||
| -rw-r--r-- | CPP/Windows/Registry.h | 48 | ||||
| -rw-r--r-- | CPP/Windows/System.cpp | 41 | ||||
| -rw-r--r-- | CPP/Windows/System.h | 2 | ||||
| -rw-r--r-- | CPP/Windows/SystemInfo.cpp | 125 | ||||
| -rw-r--r-- | CPP/Windows/SystemInfo.h | 2 |
9 files changed, 484 insertions, 198 deletions
diff --git a/CPP/Windows/FileDir.cpp b/CPP/Windows/FileDir.cpp index dfeed82..2cb83b2 100644 --- a/CPP/Windows/FileDir.cpp +++ b/CPP/Windows/FileDir.cpp | |||
| @@ -15,8 +15,9 @@ | |||
| 15 | #include <sys/stat.h> | 15 | #include <sys/stat.h> |
| 16 | #include <sys/types.h> | 16 | #include <sys/types.h> |
| 17 | 17 | ||
| 18 | #include "../Common/StringConvert.h" | ||
| 19 | #include "../Common/C_FileIO.h" | 18 | #include "../Common/C_FileIO.h" |
| 19 | #include "../Common/MyBuffer2.h" | ||
| 20 | #include "../Common/StringConvert.h" | ||
| 20 | #endif | 21 | #endif |
| 21 | 22 | ||
| 22 | #include "FileDir.h" | 23 | #include "FileDir.h" |
| @@ -222,6 +223,8 @@ bool RemoveDir(CFSTR path) | |||
| 222 | } | 223 | } |
| 223 | 224 | ||
| 224 | 225 | ||
| 226 | // When moving a directory, oldFile and newFile must be on the same drive. | ||
| 227 | |||
| 225 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 228 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) |
| 226 | { | 229 | { |
| 227 | #ifndef _UNICODE | 230 | #ifndef _UNICODE |
| @@ -250,6 +253,59 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
| 250 | return false; | 253 | return false; |
| 251 | } | 254 | } |
| 252 | 255 | ||
| 256 | #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 | ||
| 257 | static DWORD WINAPI CopyProgressRoutine_to_ICopyFileProgress( | ||
| 258 | LARGE_INTEGER TotalFileSize, // file size | ||
| 259 | LARGE_INTEGER TotalBytesTransferred, // bytes transferred | ||
| 260 | LARGE_INTEGER /* StreamSize */, // bytes in stream | ||
| 261 | LARGE_INTEGER /* StreamBytesTransferred */, // bytes transferred for stream | ||
| 262 | DWORD /* dwStreamNumber */, // current stream | ||
| 263 | DWORD /* dwCallbackReason */, // callback reason | ||
| 264 | HANDLE /* hSourceFile */, // handle to source file | ||
| 265 | HANDLE /* hDestinationFile */, // handle to destination file | ||
| 266 | LPVOID lpData // from CopyFileEx | ||
| 267 | ) | ||
| 268 | { | ||
| 269 | return ((ICopyFileProgress *)lpData)->CopyFileProgress( | ||
| 270 | (UInt64)TotalFileSize.QuadPart, | ||
| 271 | (UInt64)TotalBytesTransferred.QuadPart); | ||
| 272 | } | ||
| 273 | #endif | ||
| 274 | |||
| 275 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, | ||
| 276 | ICopyFileProgress *progress) | ||
| 277 | { | ||
| 278 | #if defined(Z7_WIN32_WINNT_MIN) && Z7_WIN32_WINNT_MIN >= 0x0500 | ||
| 279 | #ifndef _UNICODE | ||
| 280 | if (g_IsNT) | ||
| 281 | #endif | ||
| 282 | if (progress) | ||
| 283 | { | ||
| 284 | IF_USE_MAIN_PATH_2(oldFile, newFile) | ||
| 285 | { | ||
| 286 | if (::MoveFileWithProgressW(fs2us(oldFile), fs2us(newFile), | ||
| 287 | CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)) | ||
| 288 | return true; | ||
| 289 | if (::GetLastError() == ERROR_REQUEST_ABORTED) | ||
| 290 | return false; | ||
| 291 | } | ||
| 292 | #ifdef Z7_LONG_PATH | ||
| 293 | if (USE_SUPER_PATH_2) | ||
| 294 | { | ||
| 295 | UString d1, d2; | ||
| 296 | if (GetSuperPaths(oldFile, newFile, d1, d2, USE_MAIN_PATH_2)) | ||
| 297 | return BOOLToBool(::MoveFileWithProgressW(d1, d2, | ||
| 298 | CopyProgressRoutine_to_ICopyFileProgress, progress, MOVEFILE_COPY_ALLOWED)); | ||
| 299 | } | ||
| 300 | #endif | ||
| 301 | return false; | ||
| 302 | } | ||
| 303 | #else | ||
| 304 | UNUSED_VAR(progress) | ||
| 305 | #endif | ||
| 306 | return MyMoveFile(oldFile, newFile); | ||
| 307 | } | ||
| 308 | |||
| 253 | #ifndef UNDER_CE | 309 | #ifndef UNDER_CE |
| 254 | #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 | 310 | #if !defined(Z7_WIN32_WINNT_MIN) || Z7_WIN32_WINNT_MIN < 0x0500 // Win2000 |
| 255 | #define Z7_USE_DYN_CreateHardLink | 311 | #define Z7_USE_DYN_CreateHardLink |
| @@ -878,9 +934,9 @@ bool CTempFile::Remove() | |||
| 878 | return !_mustBeDeleted; | 934 | return !_mustBeDeleted; |
| 879 | } | 935 | } |
| 880 | 936 | ||
| 881 | bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) | 937 | bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore, |
| 938 | ICopyFileProgress *progress) | ||
| 882 | { | 939 | { |
| 883 | // DWORD attrib = 0; | ||
| 884 | if (deleteDestBefore) | 940 | if (deleteDestBefore) |
| 885 | { | 941 | { |
| 886 | if (NFind::DoesFileExist_Raw(name)) | 942 | if (NFind::DoesFileExist_Raw(name)) |
| @@ -891,8 +947,8 @@ bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) | |||
| 891 | } | 947 | } |
| 892 | } | 948 | } |
| 893 | DisableDeleting(); | 949 | DisableDeleting(); |
| 894 | return MyMoveFile(_path, name); | 950 | // if (!progress) return MyMoveFile(_path, name); |
| 895 | 951 | return MyMoveFile_with_Progress(_path, name, progress); | |
| 896 | /* | 952 | /* |
| 897 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) | 953 | if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_READONLY)) |
| 898 | { | 954 | { |
| @@ -941,34 +997,59 @@ bool RemoveDir(CFSTR path) | |||
| 941 | } | 997 | } |
| 942 | 998 | ||
| 943 | 999 | ||
| 944 | static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile) | 1000 | static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile, ICopyFileProgress *progress) |
| 945 | { | 1001 | { |
| 946 | NWindows::NFile::NIO::COutFile outFile; | ||
| 947 | if (!outFile.Create_NEW(newFile)) | ||
| 948 | return FALSE; | ||
| 949 | |||
| 950 | NWindows::NFile::NIO::CInFile inFile; | ||
| 951 | if (!inFile.Open(oldFile)) | ||
| 952 | return FALSE; | ||
| 953 | |||
| 954 | char buf[1 << 14]; | ||
| 955 | |||
| 956 | for (;;) | ||
| 957 | { | 1002 | { |
| 958 | const ssize_t num = inFile.read_part(buf, sizeof(buf)); | 1003 | NIO::COutFile outFile; |
| 959 | if (num == 0) | 1004 | if (!outFile.Create_NEW(newFile)) |
| 960 | return TRUE; | ||
| 961 | if (num < 0) | ||
| 962 | return FALSE; | 1005 | return FALSE; |
| 963 | size_t processed; | 1006 | NIO::CInFile inFile; |
| 964 | const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); | 1007 | if (!inFile.Open(oldFile)) |
| 965 | if (num2 != num || processed != (size_t)num) | ||
| 966 | return FALSE; | 1008 | return FALSE; |
| 1009 | |||
| 1010 | const size_t k_BufSize = 1 << 16; | ||
| 1011 | CAlignedBuffer1 buf(k_BufSize); | ||
| 1012 | |||
| 1013 | UInt64 length = 0; | ||
| 1014 | if (progress && !inFile.GetLength(length)) | ||
| 1015 | length = 0; | ||
| 1016 | UInt64 prev = 0; | ||
| 1017 | UInt64 cur = 0; | ||
| 1018 | for (;;) | ||
| 1019 | { | ||
| 1020 | const ssize_t num = inFile.read_part(buf, k_BufSize); | ||
| 1021 | if (num == 0) | ||
| 1022 | return TRUE; | ||
| 1023 | if (num < 0) | ||
| 1024 | break; | ||
| 1025 | size_t processed; | ||
| 1026 | const ssize_t num2 = outFile.write_full(buf, (size_t)num, processed); | ||
| 1027 | if (num2 != num || processed != (size_t)num) | ||
| 1028 | break; | ||
| 1029 | cur += (size_t)num2; | ||
| 1030 | if (progress && cur - prev >= (1u << 20)) | ||
| 1031 | { | ||
| 1032 | prev = cur; | ||
| 1033 | if (progress->CopyFileProgress(length, cur) != PROGRESS_CONTINUE) | ||
| 1034 | { | ||
| 1035 | errno = EINTR; // instead of WIN32::ERROR_REQUEST_ABORTED | ||
| 1036 | break; | ||
| 1037 | } | ||
| 1038 | } | ||
| 1039 | } | ||
| 967 | } | 1040 | } |
| 1041 | // There is file IO error or process was interrupted by user. | ||
| 1042 | // We close output file and delete it. | ||
| 1043 | // DeleteFileAlways doesn't change errno (if successed), but we restore errno. | ||
| 1044 | const int errno_save = errno; | ||
| 1045 | DeleteFileAlways(newFile); | ||
| 1046 | errno = errno_save; | ||
| 1047 | return FALSE; | ||
| 968 | } | 1048 | } |
| 969 | 1049 | ||
| 970 | 1050 | ||
| 971 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | 1051 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, |
| 1052 | ICopyFileProgress *progress) | ||
| 972 | { | 1053 | { |
| 973 | int res = rename(oldFile, newFile); | 1054 | int res = rename(oldFile, newFile); |
| 974 | if (res == 0) | 1055 | if (res == 0) |
| @@ -976,7 +1057,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
| 976 | if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) | 1057 | if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem) |
| 977 | return false; | 1058 | return false; |
| 978 | 1059 | ||
| 979 | if (My_CopyFile(oldFile, newFile) == FALSE) | 1060 | if (My_CopyFile(oldFile, newFile, progress) == FALSE) |
| 980 | return false; | 1061 | return false; |
| 981 | 1062 | ||
| 982 | struct stat info_file; | 1063 | struct stat info_file; |
| @@ -990,6 +1071,11 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | |||
| 990 | return (unlink(oldFile) == 0); | 1071 | return (unlink(oldFile) == 0); |
| 991 | } | 1072 | } |
| 992 | 1073 | ||
| 1074 | bool MyMoveFile(CFSTR oldFile, CFSTR newFile) | ||
| 1075 | { | ||
| 1076 | return MyMoveFile_with_Progress(oldFile, newFile, NULL); | ||
| 1077 | } | ||
| 1078 | |||
| 993 | 1079 | ||
| 994 | bool CreateDir(CFSTR path) | 1080 | bool CreateDir(CFSTR path) |
| 995 | { | 1081 | { |
diff --git a/CPP/Windows/FileDir.h b/CPP/Windows/FileDir.h index 573ffa2..74675ee 100644 --- a/CPP/Windows/FileDir.h +++ b/CPP/Windows/FileDir.h | |||
| @@ -41,7 +41,26 @@ int my_chown(CFSTR path, uid_t owner, gid_t group); | |||
| 41 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); | 41 | bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib); |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | #ifndef _WIN32 | ||
| 45 | #define PROGRESS_CONTINUE 0 | ||
| 46 | #define PROGRESS_CANCEL 1 | ||
| 47 | // #define PROGRESS_STOP 2 | ||
| 48 | // #define PROGRESS_QUIET 3 | ||
| 49 | #endif | ||
| 50 | Z7_PURE_INTERFACES_BEGIN | ||
| 51 | DECLARE_INTERFACE(ICopyFileProgress) | ||
| 52 | { | ||
| 53 | // in: total, current: include all/processed alt streams. | ||
| 54 | // it returns PROGRESS_CONTINUE or PROGRESS_CANCEL. | ||
| 55 | virtual DWORD CopyFileProgress(UInt64 total, UInt64 current) = 0; | ||
| 56 | }; | ||
| 57 | Z7_PURE_INTERFACES_END | ||
| 58 | |||
| 44 | bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); | 59 | bool MyMoveFile(CFSTR existFileName, CFSTR newFileName); |
| 60 | // (progress == NULL) is allowed | ||
| 61 | bool MyMoveFile_with_Progress(CFSTR oldFile, CFSTR newFile, | ||
| 62 | ICopyFileProgress *progress); | ||
| 63 | |||
| 45 | 64 | ||
| 46 | #ifndef UNDER_CE | 65 | #ifndef UNDER_CE |
| 47 | bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); | 66 | bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName); |
| @@ -87,7 +106,9 @@ public: | |||
| 87 | bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix | 106 | bool Create(CFSTR pathPrefix, NIO::COutFile *outFile); // pathPrefix is not folder prefix |
| 88 | bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); | 107 | bool CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile); |
| 89 | bool Remove(); | 108 | bool Remove(); |
| 90 | bool MoveTo(CFSTR name, bool deleteDestBefore); | 109 | // bool MoveTo(CFSTR name, bool deleteDestBefore); |
| 110 | bool MoveTo(CFSTR name, bool deleteDestBefore, | ||
| 111 | ICopyFileProgress *progress); | ||
| 91 | }; | 112 | }; |
| 92 | 113 | ||
| 93 | 114 | ||
diff --git a/CPP/Windows/FileName.cpp b/CPP/Windows/FileName.cpp index c16b3d4..1f4a6da 100644 --- a/CPP/Windows/FileName.cpp +++ b/CPP/Windows/FileName.cpp | |||
| @@ -278,12 +278,14 @@ bool IsAbsolutePath(const wchar_t *s) throw() | |||
| 278 | int FindAltStreamColon(CFSTR path) throw() | 278 | int FindAltStreamColon(CFSTR path) throw() |
| 279 | { | 279 | { |
| 280 | unsigned i = 0; | 280 | unsigned i = 0; |
| 281 | if (IsDrivePath2(path)) | 281 | if (IsSuperPath(path)) |
| 282 | i = 2; | 282 | i = kSuperPathPrefixSize; |
| 283 | if (IsDrivePath2(path + i)) | ||
| 284 | i += 2; | ||
| 283 | int colonPos = -1; | 285 | int colonPos = -1; |
| 284 | for (;; i++) | 286 | for (;; i++) |
| 285 | { | 287 | { |
| 286 | FChar c = path[i]; | 288 | const FChar c = path[i]; |
| 287 | if (c == 0) | 289 | if (c == 0) |
| 288 | return colonPos; | 290 | return colonPos; |
| 289 | if (c == ':') | 291 | if (c == ':') |
diff --git a/CPP/Windows/Registry.cpp b/CPP/Windows/Registry.cpp index c8b1709..a94a50f 100644 --- a/CPP/Windows/Registry.cpp +++ b/CPP/Windows/Registry.cpp | |||
| @@ -78,7 +78,7 @@ LONG CKey::Close() throw() | |||
| 78 | return res; | 78 | return res; |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | // win95, win98: deletes sunkey and all its subkeys | 81 | // win95, win98: deletes subkey and all its subkeys |
| 82 | // winNT to be deleted must not have subkeys | 82 | // winNT to be deleted must not have subkeys |
| 83 | LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() | 83 | LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() |
| 84 | { | 84 | { |
| @@ -88,22 +88,36 @@ LONG CKey::DeleteSubKey(LPCTSTR subKeyName) throw() | |||
| 88 | 88 | ||
| 89 | LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() | 89 | LONG CKey::RecurseDeleteKey(LPCTSTR subKeyName) throw() |
| 90 | { | 90 | { |
| 91 | CKey key; | ||
| 92 | LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); | ||
| 93 | if (res != ERROR_SUCCESS) | ||
| 94 | return res; | ||
| 95 | FILETIME fileTime; | ||
| 96 | const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL | ||
| 97 | DWORD size = kBufSize; | ||
| 98 | TCHAR buffer[kBufSize]; | ||
| 99 | while (RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime) == ERROR_SUCCESS) | ||
| 100 | { | 91 | { |
| 101 | res = key.RecurseDeleteKey(buffer); | 92 | CKey key; |
| 93 | LONG res = key.Open(_object, subKeyName, KEY_READ | KEY_WRITE); | ||
| 102 | if (res != ERROR_SUCCESS) | 94 | if (res != ERROR_SUCCESS) |
| 103 | return res; | 95 | return res; |
| 104 | size = kBufSize; | 96 | FILETIME fileTime; |
| 97 | const UInt32 kBufSize = MAX_PATH + 1; // 256 in ATL | ||
| 98 | TCHAR buffer[kBufSize]; | ||
| 99 | // we use loop limit here for some unexpected code failure | ||
| 100 | for (unsigned loop_cnt = 0; loop_cnt < (1u << 26); loop_cnt++) | ||
| 101 | { | ||
| 102 | DWORD size = kBufSize; | ||
| 103 | // we always request starting item (index==0) in each iteration, | ||
| 104 | // because we remove starting item (index==0) in each loop iteration. | ||
| 105 | res = RegEnumKeyEx(key._object, 0, buffer, &size, NULL, NULL, NULL, &fileTime); | ||
| 106 | if (res != ERROR_SUCCESS) | ||
| 107 | { | ||
| 108 | // possible return codes: | ||
| 109 | // ERROR_NO_MORE_ITEMS : are no more subkeys available | ||
| 110 | // ERROR_MORE_DATA : name buffer is too small | ||
| 111 | // we can try to remove (subKeyName), even if there is non ERROR_NO_MORE_ITEMS error. | ||
| 112 | // if (res != ERROR_NO_MORE_ITEMS) return res; | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | res = key.RecurseDeleteKey(buffer); | ||
| 116 | if (res != ERROR_SUCCESS) | ||
| 117 | return res; | ||
| 118 | } | ||
| 119 | // key.Close(); | ||
| 105 | } | 120 | } |
| 106 | key.Close(); | ||
| 107 | return DeleteSubKey(subKeyName); | 121 | return DeleteSubKey(subKeyName); |
| 108 | } | 122 | } |
| 109 | 123 | ||
| @@ -127,7 +141,7 @@ LONG CKey::DeleteValue(LPCWSTR name) | |||
| 127 | MY_ASSUME(_object != NULL); | 141 | MY_ASSUME(_object != NULL); |
| 128 | if (g_IsNT) | 142 | if (g_IsNT) |
| 129 | return ::RegDeleteValueW(_object, name); | 143 | return ::RegDeleteValueW(_object, name); |
| 130 | return DeleteValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name)); | 144 | return DeleteValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name)); |
| 131 | } | 145 | } |
| 132 | #endif | 146 | #endif |
| 133 | 147 | ||
| @@ -143,12 +157,15 @@ LONG CKey::SetValue(LPCTSTR name, bool value) throw() | |||
| 143 | return SetValue(name, BoolToUINT32(value)); | 157 | return SetValue(name, BoolToUINT32(value)); |
| 144 | } | 158 | } |
| 145 | 159 | ||
| 160 | |||
| 161 | // value must be string that is NULL terminated | ||
| 146 | LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() | 162 | LONG CKey::SetValue(LPCTSTR name, LPCTSTR value) throw() |
| 147 | { | 163 | { |
| 148 | MYASSERT(value != NULL); | 164 | MYASSERT(value != NULL); |
| 149 | MY_ASSUME(_object != NULL); | 165 | MY_ASSUME(_object != NULL); |
| 166 | // note: RegSetValueEx supports (value == NULL), if (cbData == 0) | ||
| 150 | return RegSetValueEx(_object, name, 0, REG_SZ, | 167 | return RegSetValueEx(_object, name, 0, REG_SZ, |
| 151 | (const BYTE *)value, ((DWORD)lstrlen(value) + 1) * sizeof(TCHAR)); | 168 | (const BYTE *)value, (DWORD)(((DWORD)lstrlen(value) + 1) * sizeof(TCHAR))); |
| 152 | } | 169 | } |
| 153 | 170 | ||
| 154 | /* | 171 | /* |
| @@ -156,7 +173,7 @@ LONG CKey::SetValue(LPCTSTR name, const CSysString &value) | |||
| 156 | { | 173 | { |
| 157 | MYASSERT(value != NULL); | 174 | MYASSERT(value != NULL); |
| 158 | MY_ASSUME(_object != NULL); | 175 | MY_ASSUME(_object != NULL); |
| 159 | return RegSetValueEx(_object, name, NULL, REG_SZ, | 176 | return RegSetValueEx(_object, name, 0, REG_SZ, |
| 160 | (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); | 177 | (const BYTE *)(const TCHAR *)value, (value.Len() + 1) * sizeof(TCHAR)); |
| 161 | } | 178 | } |
| 162 | */ | 179 | */ |
| @@ -169,9 +186,10 @@ LONG CKey::SetValue(LPCWSTR name, LPCWSTR value) | |||
| 169 | MY_ASSUME(_object != NULL); | 186 | MY_ASSUME(_object != NULL); |
| 170 | if (g_IsNT) | 187 | if (g_IsNT) |
| 171 | return RegSetValueExW(_object, name, 0, REG_SZ, | 188 | return RegSetValueExW(_object, name, 0, REG_SZ, |
| 172 | (const BYTE * )value, (DWORD)((wcslen(value) + 1) * sizeof(wchar_t))); | 189 | (const BYTE *)value, (DWORD)(((DWORD)wcslen(value) + 1) * sizeof(wchar_t))); |
| 173 | return SetValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), | 190 | return SetValue(name == NULL ? NULL : |
| 174 | value == 0 ? 0 : (LPCSTR)GetSystemString(value)); | 191 | (LPCSTR)GetSystemString(name), |
| 192 | (LPCSTR)GetSystemString(value)); | ||
| 175 | } | 193 | } |
| 176 | 194 | ||
| 177 | #endif | 195 | #endif |
| @@ -205,99 +223,137 @@ LONG CKey::SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw( | |||
| 205 | return res; | 223 | return res; |
| 206 | } | 224 | } |
| 207 | 225 | ||
| 208 | LONG CKey::QueryValue(LPCTSTR name, UInt32 &value) throw() | ||
| 209 | { | ||
| 210 | DWORD type = 0; | ||
| 211 | DWORD count = sizeof(DWORD); | ||
| 212 | LONG res = RegQueryValueEx(_object, name, NULL, &type, | ||
| 213 | (LPBYTE)&value, &count); | ||
| 214 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_DWORD)); | ||
| 215 | MYASSERT((res != ERROR_SUCCESS) || (count == sizeof(UInt32))); | ||
| 216 | return res; | ||
| 217 | } | ||
| 218 | 226 | ||
| 219 | LONG CKey::QueryValue(LPCTSTR name, bool &value) throw() | 227 | LONG CKey::GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw() |
| 220 | { | 228 | { |
| 221 | UInt32 uintValue = BoolToUINT32(value); | 229 | DWORD type = 0; |
| 222 | LONG res = QueryValue(name, uintValue); | 230 | DWORD count = sizeof(value); |
| 223 | value = UINT32ToBool(uintValue); | 231 | UInt32 value2; // = value; |
| 232 | const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count); | ||
| 233 | if (res == ERROR_SUCCESS) | ||
| 234 | { | ||
| 235 | // ERROR_UNSUPPORTED_TYPE | ||
| 236 | if (count != sizeof(value) || type != REG_DWORD) | ||
| 237 | return ERROR_UNSUPPORTED_TYPE; // ERROR_INVALID_DATA; | ||
| 238 | value = value2; | ||
| 239 | } | ||
| 224 | return res; | 240 | return res; |
| 225 | } | 241 | } |
| 226 | 242 | ||
| 227 | LONG CKey::GetValue_IfOk(LPCTSTR name, UInt32 &value) throw() | 243 | LONG CKey::GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw() |
| 228 | { | 244 | { |
| 229 | UInt32 newVal; | 245 | DWORD type = 0; |
| 230 | LONG res = QueryValue(name, newVal); | 246 | DWORD count = sizeof(value); |
| 247 | UInt64 value2; // = value; | ||
| 248 | const LONG res = QueryValueEx(name, &type, (LPBYTE)&value2, &count); | ||
| 231 | if (res == ERROR_SUCCESS) | 249 | if (res == ERROR_SUCCESS) |
| 232 | value = newVal; | 250 | { |
| 251 | if (count != sizeof(value) || type != REG_QWORD) | ||
| 252 | return ERROR_UNSUPPORTED_TYPE; | ||
| 253 | value = value2; | ||
| 254 | } | ||
| 233 | return res; | 255 | return res; |
| 234 | } | 256 | } |
| 235 | 257 | ||
| 236 | LONG CKey::GetValue_IfOk(LPCTSTR name, bool &value) throw() | 258 | LONG CKey::GetValue_bool_IfOk(LPCTSTR name, bool &value) throw() |
| 237 | { | 259 | { |
| 238 | bool newVal = false; | 260 | UInt32 uintValue; |
| 239 | LONG res = QueryValue(name, newVal); | 261 | const LONG res = GetValue_UInt32_IfOk(name, uintValue); |
| 240 | if (res == ERROR_SUCCESS) | 262 | if (res == ERROR_SUCCESS) |
| 241 | value = newVal; | 263 | value = UINT32ToBool(uintValue); |
| 242 | return res; | 264 | return res; |
| 243 | } | 265 | } |
| 244 | 266 | ||
| 245 | LONG CKey::QueryValue(LPCTSTR name, LPTSTR value, UInt32 &count) throw() | 267 | |
| 246 | { | ||
| 247 | DWORD type = 0; | ||
| 248 | LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | ||
| 249 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | ||
| 250 | return res; | ||
| 251 | } | ||
| 252 | 268 | ||
| 253 | LONG CKey::QueryValue(LPCTSTR name, CSysString &value) | 269 | LONG CKey::QueryValue(LPCTSTR name, CSysString &value) |
| 254 | { | 270 | { |
| 255 | value.Empty(); | 271 | value.Empty(); |
| 256 | DWORD type = 0; | 272 | LONG res = ERROR_SUCCESS; |
| 257 | DWORD curSize = 0; | 273 | { |
| 258 | LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, &curSize); | 274 | // if we don't want multiple calls here, |
| 259 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | 275 | // we can use big value (264) here. |
| 260 | return res; | 276 | // 3 is default available length in new string. |
| 261 | UInt32 curSize2 = curSize; | 277 | DWORD size_prev = 3 * sizeof(TCHAR); |
| 262 | res = QueryValue(name, value.GetBuf(curSize), curSize2); | 278 | // at least 2 attempts are required. But we use more attempts for cases, |
| 263 | if (curSize > curSize2) | 279 | // where string can be changed by anothner process |
| 264 | curSize = curSize2; | 280 | for (unsigned i = 0; i < 2 + 2; i++) |
| 265 | value.ReleaseBuf_CalcLen(curSize / sizeof(TCHAR)); | 281 | { |
| 282 | DWORD type = 0; | ||
| 283 | DWORD size = size_prev; | ||
| 284 | { | ||
| 285 | LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(TCHAR)); | ||
| 286 | res = QueryValueEx(name, &type, size == 0 ? NULL : buf, &size); | ||
| 287 | // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size. | ||
| 288 | } | ||
| 289 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
| 290 | { | ||
| 291 | if (type != REG_SZ && type != REG_EXPAND_SZ) | ||
| 292 | { | ||
| 293 | res = ERROR_UNSUPPORTED_TYPE; | ||
| 294 | size = 0; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | else | ||
| 298 | size = 0; | ||
| 299 | if (size > size_prev) | ||
| 300 | { | ||
| 301 | size_prev = size; | ||
| 302 | size = 0; | ||
| 303 | res = ERROR_MORE_DATA; | ||
| 304 | } | ||
| 305 | value.ReleaseBuf_CalcLen(size / sizeof(TCHAR)); | ||
| 306 | if (res != ERROR_MORE_DATA) | ||
| 307 | return res; | ||
| 308 | } | ||
| 309 | } | ||
| 266 | return res; | 310 | return res; |
| 267 | } | 311 | } |
| 268 | 312 | ||
| 269 | 313 | ||
| 270 | #ifndef _UNICODE | 314 | #ifndef _UNICODE |
| 271 | 315 | ||
| 272 | LONG CKey::QueryValue(LPCWSTR name, LPWSTR value, UInt32 &count) | ||
| 273 | { | ||
| 274 | DWORD type = 0; | ||
| 275 | LONG res = RegQueryValueExW(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | ||
| 276 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_SZ) || (type == REG_MULTI_SZ) || (type == REG_EXPAND_SZ)); | ||
| 277 | return res; | ||
| 278 | } | ||
| 279 | |||
| 280 | LONG CKey::QueryValue(LPCWSTR name, UString &value) | 316 | LONG CKey::QueryValue(LPCWSTR name, UString &value) |
| 281 | { | 317 | { |
| 282 | value.Empty(); | 318 | value.Empty(); |
| 283 | DWORD type = 0; | 319 | LONG res = ERROR_SUCCESS; |
| 284 | DWORD curSize = 0; | ||
| 285 | LONG res; | ||
| 286 | if (g_IsNT) | 320 | if (g_IsNT) |
| 287 | { | 321 | { |
| 288 | res = RegQueryValueExW(_object, name, NULL, &type, NULL, &curSize); | 322 | DWORD size_prev = 3 * sizeof(wchar_t); |
| 289 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | 323 | for (unsigned i = 0; i < 2 + 2; i++) |
| 290 | return res; | 324 | { |
| 291 | UInt32 curSize2 = curSize; | 325 | DWORD type = 0; |
| 292 | res = QueryValue(name, value.GetBuf(curSize), curSize2); | 326 | DWORD size = size_prev; |
| 293 | if (curSize > curSize2) | 327 | { |
| 294 | curSize = curSize2; | 328 | LPBYTE buf = (LPBYTE)value.GetBuf(size / sizeof(wchar_t)); |
| 295 | value.ReleaseBuf_CalcLen(curSize / sizeof(wchar_t)); | 329 | res = RegQueryValueExW(_object, name, NULL, &type, |
| 330 | size == 0 ? NULL : buf, &size); | ||
| 331 | } | ||
| 332 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
| 333 | { | ||
| 334 | if (type != REG_SZ && type != REG_EXPAND_SZ) | ||
| 335 | { | ||
| 336 | res = ERROR_UNSUPPORTED_TYPE; | ||
| 337 | size = 0; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | else | ||
| 341 | size = 0; | ||
| 342 | if (size > size_prev) | ||
| 343 | { | ||
| 344 | size_prev = size; | ||
| 345 | size = 0; | ||
| 346 | res = ERROR_MORE_DATA; | ||
| 347 | } | ||
| 348 | value.ReleaseBuf_CalcLen(size / sizeof(wchar_t)); | ||
| 349 | if (res != ERROR_MORE_DATA) | ||
| 350 | return res; | ||
| 351 | } | ||
| 296 | } | 352 | } |
| 297 | else | 353 | else |
| 298 | { | 354 | { |
| 299 | AString vTemp; | 355 | AString vTemp; |
| 300 | res = QueryValue(name == 0 ? 0 : (LPCSTR)GetSystemString(name), vTemp); | 356 | res = QueryValue(name == NULL ? NULL : (LPCSTR)GetSystemString(name), vTemp); |
| 301 | value = GetUnicodeString(vTemp); | 357 | value = GetUnicodeString(vTemp); |
| 302 | } | 358 | } |
| 303 | return res; | 359 | return res; |
| @@ -306,26 +362,43 @@ LONG CKey::QueryValue(LPCWSTR name, UString &value) | |||
| 306 | #endif | 362 | #endif |
| 307 | 363 | ||
| 308 | 364 | ||
| 309 | LONG CKey::QueryValue(LPCTSTR name, void *value, UInt32 &count) throw() | 365 | LONG CKey::QueryValue_Binary(LPCTSTR name, CByteBuffer &value) |
| 310 | { | 366 | { |
| 311 | DWORD type = 0; | 367 | // value.Free(); |
| 312 | LONG res = RegQueryValueEx(_object, name, NULL, &type, (LPBYTE)value, (DWORD *)&count); | 368 | DWORD size_prev = 0; |
| 313 | MYASSERT((res != ERROR_SUCCESS) || (type == REG_BINARY)); | 369 | LONG res = ERROR_SUCCESS; |
| 370 | for (unsigned i = 0; i < 2 + 2; i++) | ||
| 371 | { | ||
| 372 | DWORD type = 0; | ||
| 373 | DWORD size = size_prev; | ||
| 374 | value.Alloc(size_prev); | ||
| 375 | res = QueryValueEx(name, &type, value.NonConstData(), &size); | ||
| 376 | // if (size_prev == 0), then (res == ERROR_SUCCESS) is expected here, because we requested only size. | ||
| 377 | if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) | ||
| 378 | { | ||
| 379 | if (type != REG_BINARY) | ||
| 380 | { | ||
| 381 | res = ERROR_UNSUPPORTED_TYPE; | ||
| 382 | size = 0; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | else | ||
| 386 | size = 0; | ||
| 387 | if (size > size_prev) | ||
| 388 | { | ||
| 389 | size_prev = size; | ||
| 390 | size = 0; | ||
| 391 | res = ERROR_MORE_DATA; | ||
| 392 | } | ||
| 393 | if (size < value.Size()) | ||
| 394 | value.ChangeSize_KeepData(size, size); | ||
| 395 | if (res != ERROR_MORE_DATA) | ||
| 396 | return res; | ||
| 397 | } | ||
| 314 | return res; | 398 | return res; |
| 315 | } | 399 | } |
| 316 | 400 | ||
| 317 | 401 | ||
| 318 | LONG CKey::QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize) | ||
| 319 | { | ||
| 320 | DWORD type = 0; | ||
| 321 | dataSize = 0; | ||
| 322 | LONG res = RegQueryValueEx(_object, name, NULL, &type, NULL, (DWORD *)&dataSize); | ||
| 323 | if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) | ||
| 324 | return res; | ||
| 325 | value.Alloc(dataSize); | ||
| 326 | return QueryValue(name, (BYTE *)value, dataSize); | ||
| 327 | } | ||
| 328 | |||
| 329 | LONG CKey::EnumKeys(CSysStringVector &keyNames) | 402 | LONG CKey::EnumKeys(CSysStringVector &keyNames) |
| 330 | { | 403 | { |
| 331 | keyNames.Clear(); | 404 | keyNames.Clear(); |
| @@ -334,23 +407,23 @@ LONG CKey::EnumKeys(CSysStringVector &keyNames) | |||
| 334 | { | 407 | { |
| 335 | const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL | 408 | const unsigned kBufSize = MAX_PATH + 1; // 256 in ATL |
| 336 | FILETIME lastWriteTime; | 409 | FILETIME lastWriteTime; |
| 337 | UInt32 nameSize = kBufSize; | 410 | DWORD nameSize = kBufSize; |
| 338 | LONG result = ::RegEnumKeyEx(_object, index, keyName.GetBuf(kBufSize), | 411 | const LONG res = ::RegEnumKeyEx(_object, index, |
| 339 | (DWORD *)&nameSize, NULL, NULL, NULL, &lastWriteTime); | 412 | keyName.GetBuf(kBufSize), &nameSize, |
| 413 | NULL, NULL, NULL, &lastWriteTime); | ||
| 340 | keyName.ReleaseBuf_CalcLen(kBufSize); | 414 | keyName.ReleaseBuf_CalcLen(kBufSize); |
| 341 | if (result == ERROR_NO_MORE_ITEMS) | 415 | if (res == ERROR_NO_MORE_ITEMS) |
| 342 | break; | 416 | return ERROR_SUCCESS; |
| 343 | if (result != ERROR_SUCCESS) | 417 | if (res != ERROR_SUCCESS) |
| 344 | return result; | 418 | return res; |
| 345 | keyNames.Add(keyName); | 419 | keyNames.Add(keyName); |
| 346 | } | 420 | } |
| 347 | return ERROR_SUCCESS; | ||
| 348 | } | 421 | } |
| 349 | 422 | ||
| 423 | |||
| 350 | LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) | 424 | LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) |
| 351 | { | 425 | { |
| 352 | size_t numChars = 0; | 426 | size_t numChars = 0; |
| 353 | |||
| 354 | unsigned i; | 427 | unsigned i; |
| 355 | 428 | ||
| 356 | for (i = 0; i < strings.Size(); i++) | 429 | for (i = 0; i < strings.Size(); i++) |
| @@ -362,10 +435,11 @@ LONG CKey::SetValue_Strings(LPCTSTR valueName, const UStringVector &strings) | |||
| 362 | for (i = 0; i < strings.Size(); i++) | 435 | for (i = 0; i < strings.Size(); i++) |
| 363 | { | 436 | { |
| 364 | const UString &s = strings[i]; | 437 | const UString &s = strings[i]; |
| 365 | size_t size = s.Len() + 1; | 438 | const size_t size = s.Len() + 1; |
| 366 | wmemcpy(buffer + pos, s, size); | 439 | wmemcpy(buffer + pos, s, size); |
| 367 | pos += size; | 440 | pos += size; |
| 368 | } | 441 | } |
| 442 | // if (pos != numChars) return E_FAIL; | ||
| 369 | return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); | 443 | return SetValue(valueName, buffer, (UInt32)numChars * sizeof(wchar_t)); |
| 370 | } | 444 | } |
| 371 | 445 | ||
| @@ -373,20 +447,18 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) | |||
| 373 | { | 447 | { |
| 374 | strings.Clear(); | 448 | strings.Clear(); |
| 375 | CByteBuffer buffer; | 449 | CByteBuffer buffer; |
| 376 | UInt32 dataSize = 0; | 450 | const LONG res = QueryValue_Binary(valueName, buffer); |
| 377 | const LONG res = QueryValue(valueName, buffer, dataSize); | ||
| 378 | if (res != ERROR_SUCCESS) | 451 | if (res != ERROR_SUCCESS) |
| 379 | return res; | 452 | return res; |
| 380 | if (dataSize > buffer.Size()) | 453 | const size_t dataSize = buffer.Size(); |
| 381 | return E_FAIL; | 454 | if (dataSize % sizeof(wchar_t)) |
| 382 | if (dataSize % sizeof(wchar_t) != 0) | 455 | return ERROR_INVALID_DATA; |
| 383 | return E_FAIL; | ||
| 384 | |||
| 385 | const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; | 456 | const wchar_t *data = (const wchar_t *)(const void *)(const Byte *)buffer; |
| 386 | const size_t numChars = dataSize / sizeof(wchar_t); | 457 | const size_t numChars = dataSize / sizeof(wchar_t); |
| 458 | // we can check that all names are finished | ||
| 459 | // if (numChars != 0 && data[numChars - 1] != 0) return ERROR_INVALID_DATA; | ||
| 387 | size_t prev = 0; | 460 | size_t prev = 0; |
| 388 | UString s; | 461 | UString s; |
| 389 | |||
| 390 | for (size_t i = 0; i < numChars; i++) | 462 | for (size_t i = 0; i < numChars; i++) |
| 391 | { | 463 | { |
| 392 | if (data[i] == 0) | 464 | if (data[i] == 0) |
| @@ -396,7 +468,6 @@ LONG CKey::GetValue_Strings(LPCTSTR valueName, UStringVector &strings) | |||
| 396 | prev = i + 1; | 468 | prev = i + 1; |
| 397 | } | 469 | } |
| 398 | } | 470 | } |
| 399 | |||
| 400 | return res; | 471 | return res; |
| 401 | } | 472 | } |
| 402 | 473 | ||
diff --git a/CPP/Windows/Registry.h b/CPP/Windows/Registry.h index 0d3b4fc..74ee919 100644 --- a/CPP/Windows/Registry.h +++ b/CPP/Windows/Registry.h | |||
| @@ -14,6 +14,13 @@ LONG SetValue(HKEY parentKey, LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) | |||
| 14 | class CKey | 14 | class CKey |
| 15 | { | 15 | { |
| 16 | HKEY _object; | 16 | HKEY _object; |
| 17 | |||
| 18 | LONG QueryValueEx(LPCTSTR lpValueName, LPDWORD lpType, | ||
| 19 | LPBYTE lpData, LPDWORD lpcbData) | ||
| 20 | { | ||
| 21 | return RegQueryValueEx(_object, lpValueName, NULL, lpType, lpData, lpcbData); | ||
| 22 | } | ||
| 23 | |||
| 17 | public: | 24 | public: |
| 18 | CKey(): _object(NULL) {} | 25 | CKey(): _object(NULL) {} |
| 19 | ~CKey() { Close(); } | 26 | ~CKey() { Close(); } |
| @@ -22,13 +29,14 @@ public: | |||
| 22 | void Attach(HKEY key) { _object = key; } | 29 | void Attach(HKEY key) { _object = key; } |
| 23 | HKEY Detach() | 30 | HKEY Detach() |
| 24 | { | 31 | { |
| 25 | HKEY key = _object; | 32 | const HKEY key = _object; |
| 26 | _object = NULL; | 33 | _object = NULL; |
| 27 | return key; | 34 | return key; |
| 28 | } | 35 | } |
| 29 | 36 | ||
| 30 | LONG Create(HKEY parentKey, LPCTSTR keyName, | 37 | LONG Create(HKEY parentKey, LPCTSTR keyName, |
| 31 | LPTSTR keyClass = REG_NONE, DWORD options = REG_OPTION_NON_VOLATILE, | 38 | LPTSTR keyClass = REG_NONE, |
| 39 | DWORD options = REG_OPTION_NON_VOLATILE, | ||
| 32 | REGSAM accessMask = KEY_ALL_ACCESS, | 40 | REGSAM accessMask = KEY_ALL_ACCESS, |
| 33 | LPSECURITY_ATTRIBUTES securityAttributes = NULL, | 41 | LPSECURITY_ATTRIBUTES securityAttributes = NULL, |
| 34 | LPDWORD disposition = NULL) throw(); | 42 | LPDWORD disposition = NULL) throw(); |
| @@ -40,18 +48,18 @@ public: | |||
| 40 | LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); | 48 | LONG RecurseDeleteKey(LPCTSTR subKeyName) throw(); |
| 41 | 49 | ||
| 42 | LONG DeleteValue(LPCTSTR name) throw(); | 50 | LONG DeleteValue(LPCTSTR name) throw(); |
| 43 | #ifndef _UNICODE | 51 | #ifndef _UNICODE |
| 44 | LONG DeleteValue(LPCWSTR name); | 52 | LONG DeleteValue(LPCWSTR name); |
| 45 | #endif | 53 | #endif |
| 46 | 54 | ||
| 47 | LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); | 55 | LONG SetValue(LPCTSTR valueName, UInt32 value) throw(); |
| 48 | LONG SetValue(LPCTSTR valueName, bool value) throw(); | 56 | LONG SetValue(LPCTSTR valueName, bool value) throw(); |
| 49 | LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); | 57 | LONG SetValue(LPCTSTR valueName, LPCTSTR value) throw(); |
| 50 | // LONG SetValue(LPCTSTR valueName, const CSysString &value); | 58 | // LONG SetValue(LPCTSTR valueName, const CSysString &value); |
| 51 | #ifndef _UNICODE | 59 | #ifndef _UNICODE |
| 52 | LONG SetValue(LPCWSTR name, LPCWSTR value); | 60 | LONG SetValue(LPCWSTR name, LPCWSTR value); |
| 53 | // LONG SetValue(LPCWSTR name, const UString &value); | 61 | // LONG SetValue(LPCWSTR name, const UString &value); |
| 54 | #endif | 62 | #endif |
| 55 | 63 | ||
| 56 | LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); | 64 | LONG SetValue(LPCTSTR name, const void *value, UInt32 size) throw(); |
| 57 | 65 | ||
| @@ -60,21 +68,25 @@ public: | |||
| 60 | 68 | ||
| 61 | LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); | 69 | LONG SetKeyValue(LPCTSTR keyName, LPCTSTR valueName, LPCTSTR value) throw(); |
| 62 | 70 | ||
| 63 | LONG QueryValue(LPCTSTR name, UInt32 &value) throw(); | 71 | // GetValue_[type]_IfOk(): |
| 64 | LONG QueryValue(LPCTSTR name, bool &value) throw(); | 72 | // if (return_result == ERROR_SUCCESS), (value) variable was read from registry |
| 65 | LONG QueryValue(LPCTSTR name, LPTSTR value, UInt32 &dataSize) throw(); | 73 | // if (return_result != ERROR_SUCCESS), (value) variable was not changed |
| 66 | LONG QueryValue(LPCTSTR name, CSysString &value); | 74 | LONG GetValue_UInt32_IfOk(LPCTSTR name, UInt32 &value) throw(); |
| 67 | 75 | LONG GetValue_UInt64_IfOk(LPCTSTR name, UInt64 &value) throw(); | |
| 68 | LONG GetValue_IfOk(LPCTSTR name, UInt32 &value) throw(); | 76 | LONG GetValue_bool_IfOk(LPCTSTR name, bool &value) throw(); |
| 69 | LONG GetValue_IfOk(LPCTSTR name, bool &value) throw(); | ||
| 70 | 77 | ||
| 71 | #ifndef _UNICODE | 78 | // QueryValue(): |
| 72 | LONG QueryValue(LPCWSTR name, LPWSTR value, UInt32 &dataSize); | 79 | // if (return_result == ERROR_SUCCESS), (value) string was read from registry |
| 80 | // if (return_result != ERROR_SUCCESS), (value) string was cleared | ||
| 81 | LONG QueryValue(LPCTSTR name, CSysString &value); | ||
| 82 | #ifndef _UNICODE | ||
| 73 | LONG QueryValue(LPCWSTR name, UString &value); | 83 | LONG QueryValue(LPCWSTR name, UString &value); |
| 74 | #endif | 84 | #endif |
| 75 | 85 | ||
| 76 | LONG QueryValue(LPCTSTR name, void *value, UInt32 &dataSize) throw(); | 86 | // QueryValue_Binary(): |
| 77 | LONG QueryValue(LPCTSTR name, CByteBuffer &value, UInt32 &dataSize); | 87 | // if (return_result == ERROR_SUCCESS), (value) buffer was read from registry (BINARY data) |
| 88 | // if (return_result != ERROR_SUCCESS), (value) buffer was cleared | ||
| 89 | LONG QueryValue_Binary(LPCTSTR name, CByteBuffer &value); | ||
| 78 | 90 | ||
| 79 | LONG EnumKeys(CSysStringVector &keyNames); | 91 | LONG EnumKeys(CSysStringVector &keyNames); |
| 80 | }; | 92 | }; |
diff --git a/CPP/Windows/System.cpp b/CPP/Windows/System.cpp index 03c8988..5fa87f3 100644 --- a/CPP/Windows/System.cpp +++ b/CPP/Windows/System.cpp | |||
| @@ -142,9 +142,9 @@ typedef BOOL (WINAPI *Func_GlobalMemoryStatusEx)(MY_LPMEMORYSTATUSEX lpBuffer); | |||
| 142 | #endif // !UNDER_CE | 142 | #endif // !UNDER_CE |
| 143 | 143 | ||
| 144 | 144 | ||
| 145 | bool GetRamSize(UInt64 &size) | 145 | bool GetRamSize(size_t &size) |
| 146 | { | 146 | { |
| 147 | size = (UInt64)(sizeof(size_t)) << 29; | 147 | size = (size_t)sizeof(size_t) << 29; |
| 148 | 148 | ||
| 149 | #ifndef UNDER_CE | 149 | #ifndef UNDER_CE |
| 150 | MY_MEMORYSTATUSEX stat; | 150 | MY_MEMORYSTATUSEX stat; |
| @@ -167,11 +167,23 @@ bool GetRamSize(UInt64 &size) | |||
| 167 | "GlobalMemoryStatusEx"); | 167 | "GlobalMemoryStatusEx"); |
| 168 | if (fn && fn(&stat)) | 168 | if (fn && fn(&stat)) |
| 169 | { | 169 | { |
| 170 | size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys); | 170 | // (MY_MEMORYSTATUSEX::ullTotalVirtual) < 4 GiB in 32-bit mode |
| 171 | size_t size2 = (size_t)0 - 1; | ||
| 172 | if (size2 > stat.ullTotalPhys) | ||
| 173 | size2 = (size_t)stat.ullTotalPhys; | ||
| 174 | if (size2 > stat.ullTotalVirtual) | ||
| 175 | size2 = (size_t)stat.ullTotalVirtual; | ||
| 176 | size = size2; | ||
| 171 | return true; | 177 | return true; |
| 172 | } | 178 | } |
| 173 | #endif | 179 | #endif |
| 174 | 180 | ||
| 181 | // On computers with more than 4 GB of memory: | ||
| 182 | // new docs : GlobalMemoryStatus can report (-1) value to indicate an overflow. | ||
| 183 | // some old docs : GlobalMemoryStatus can report (modulo 4 GiB) value. | ||
| 184 | // (for example, if 5 GB total memory, it could report 1 GB). | ||
| 185 | // We don't want to get (modulo 4 GiB) value. | ||
| 186 | // So we use GlobalMemoryStatusEx() instead. | ||
| 175 | { | 187 | { |
| 176 | MEMORYSTATUS stat2; | 188 | MEMORYSTATUS stat2; |
| 177 | stat2.dwLength = sizeof(stat2); | 189 | stat2.dwLength = sizeof(stat2); |
| @@ -187,9 +199,11 @@ bool GetRamSize(UInt64 &size) | |||
| 187 | // POSIX | 199 | // POSIX |
| 188 | // #include <stdio.h> | 200 | // #include <stdio.h> |
| 189 | 201 | ||
| 190 | bool GetRamSize(UInt64 &size) | 202 | bool GetRamSize(size_t &size) |
| 191 | { | 203 | { |
| 192 | size = (UInt64)(sizeof(size_t)) << 29; | 204 | UInt64 size64; |
| 205 | size = (size_t)sizeof(size_t) << 29; | ||
| 206 | size64 = size; | ||
| 193 | 207 | ||
| 194 | #if defined(__APPLE__) || defined(__DragonFly__) || \ | 208 | #if defined(__APPLE__) || defined(__DragonFly__) || \ |
| 195 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) | 209 | defined(BSD) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) |
| @@ -215,7 +229,7 @@ bool GetRamSize(UInt64 &size) | |||
| 215 | // we use strict check (size_sys == sizeof(val)) for returned value | 229 | // we use strict check (size_sys == sizeof(val)) for returned value |
| 216 | // because big-endian encoding is possible: | 230 | // because big-endian encoding is possible: |
| 217 | if (res == 0 && size_sys == sizeof(val) && val) | 231 | if (res == 0 && size_sys == sizeof(val) && val) |
| 218 | size = val; | 232 | size64 = val; |
| 219 | else | 233 | else |
| 220 | { | 234 | { |
| 221 | uint32_t val32 = 0; | 235 | uint32_t val32 = 0; |
| @@ -223,12 +237,12 @@ bool GetRamSize(UInt64 &size) | |||
| 223 | res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); | 237 | res = sysctl(mib, 2, &val32, &size_sys, NULL, 0); |
| 224 | // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); | 238 | // printf("\n sysctl res=%d val=%llx size_sys = %d, %d\n", res, (long long int)val32, (int)size_sys, errno); |
| 225 | if (res == 0 && size_sys == sizeof(val32) && val32) | 239 | if (res == 0 && size_sys == sizeof(val32) && val32) |
| 226 | size = val32; | 240 | size64 = val32; |
| 227 | } | 241 | } |
| 228 | 242 | ||
| 229 | #elif defined(_AIX) | 243 | #elif defined(_AIX) |
| 230 | #if defined(_SC_AIX_REALMEM) // AIX | 244 | #if defined(_SC_AIX_REALMEM) // AIX |
| 231 | size = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; | 245 | size64 = (UInt64)sysconf(_SC_AIX_REALMEM) * 1024; |
| 232 | #endif | 246 | #endif |
| 233 | #elif 0 || defined(__sun) | 247 | #elif 0 || defined(__sun) |
| 234 | #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) | 248 | #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) |
| @@ -240,7 +254,7 @@ bool GetRamSize(UInt64 &size) | |||
| 240 | // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); | 254 | // printf("\n_SC_PHYS_PAGES (hex) = %lx", (unsigned long)phys_pages); |
| 241 | // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); | 255 | // printf("\n_SC_PAGESIZE = %lu\n", (unsigned long)page_size); |
| 242 | if (phys_pages != -1 && page_size != -1) | 256 | if (phys_pages != -1 && page_size != -1) |
| 243 | size = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; | 257 | size64 = (UInt64)(Int64)phys_pages * (UInt64)(Int64)page_size; |
| 244 | } | 258 | } |
| 245 | #endif | 259 | #endif |
| 246 | #elif defined(__gnu_hurd__) | 260 | #elif defined(__gnu_hurd__) |
| @@ -253,7 +267,7 @@ bool GetRamSize(UInt64 &size) | |||
| 253 | struct sysinfo info; | 267 | struct sysinfo info; |
| 254 | if (::sysinfo(&info) != 0) | 268 | if (::sysinfo(&info) != 0) |
| 255 | return false; | 269 | return false; |
| 256 | size = (UInt64)info.mem_unit * info.totalram; | 270 | size64 = (UInt64)info.mem_unit * info.totalram; |
| 257 | /* | 271 | /* |
| 258 | printf("\n mem_unit = %lld", (UInt64)info.mem_unit); | 272 | printf("\n mem_unit = %lld", (UInt64)info.mem_unit); |
| 259 | printf("\n totalram = %lld", (UInt64)info.totalram); | 273 | printf("\n totalram = %lld", (UInt64)info.totalram); |
| @@ -262,10 +276,9 @@ bool GetRamSize(UInt64 &size) | |||
| 262 | 276 | ||
| 263 | #endif | 277 | #endif |
| 264 | 278 | ||
| 265 | const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1); | 279 | size = (size_t)1 << (sizeof(size_t) * 8 - 1); |
| 266 | if (size > kLimit) | 280 | if (size > size64) |
| 267 | size = kLimit; | 281 | size = (size_t)size64; |
| 268 | |||
| 269 | return true; | 282 | return true; |
| 270 | } | 283 | } |
| 271 | 284 | ||
diff --git a/CPP/Windows/System.h b/CPP/Windows/System.h index b17111c..9951b8b 100644 --- a/CPP/Windows/System.h +++ b/CPP/Windows/System.h | |||
| @@ -122,7 +122,7 @@ struct CProcessAffinity | |||
| 122 | 122 | ||
| 123 | UInt32 GetNumberOfProcessors(); | 123 | UInt32 GetNumberOfProcessors(); |
| 124 | 124 | ||
| 125 | bool GetRamSize(UInt64 &size); // returns false, if unknown ram size | 125 | bool GetRamSize(size_t &size); // returns false, if unknown ram size |
| 126 | 126 | ||
| 127 | unsigned long Get_File_OPEN_MAX(); | 127 | unsigned long Get_File_OPEN_MAX(); |
| 128 | unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks(); | 128 | unsigned Get_File_OPEN_MAX_Reduced_for_3_tasks(); |
diff --git a/CPP/Windows/SystemInfo.cpp b/CPP/Windows/SystemInfo.cpp index cfc6a90..35846e0 100644 --- a/CPP/Windows/SystemInfo.cpp +++ b/CPP/Windows/SystemInfo.cpp | |||
| @@ -530,6 +530,28 @@ struct CCpuName | |||
| 530 | AString Microcode; | 530 | AString Microcode; |
| 531 | AString LargePages; | 531 | AString LargePages; |
| 532 | 532 | ||
| 533 | #ifdef _WIN32 | ||
| 534 | UInt32 MHz; | ||
| 535 | |||
| 536 | #ifdef MY_CPU_ARM64 | ||
| 537 | #define Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 538 | #endif | ||
| 539 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 540 | bool Arm64_ISAR0_EL1_Defined; | ||
| 541 | UInt64 Arm64_ISAR0_EL1; | ||
| 542 | #endif | ||
| 543 | #endif | ||
| 544 | |||
| 545 | #ifdef _WIN32 | ||
| 546 | CCpuName(): | ||
| 547 | MHz(0) | ||
| 548 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 549 | , Arm64_ISAR0_EL1_Defined(false) | ||
| 550 | , Arm64_ISAR0_EL1(0) | ||
| 551 | #endif | ||
| 552 | {} | ||
| 553 | #endif | ||
| 554 | |||
| 533 | void Fill(); | 555 | void Fill(); |
| 534 | 556 | ||
| 535 | void Get_Revision_Microcode_LargePages(AString &s) | 557 | void Get_Revision_Microcode_LargePages(AString &s) |
| @@ -537,16 +559,46 @@ struct CCpuName | |||
| 537 | s.Empty(); | 559 | s.Empty(); |
| 538 | AddBracedString(s, Revision); | 560 | AddBracedString(s, Revision); |
| 539 | AddBracedString(s, Microcode); | 561 | AddBracedString(s, Microcode); |
| 540 | s.Add_OptSpaced(LargePages); | 562 | #ifdef _WIN32 |
| 563 | if (MHz != 0) | ||
| 564 | { | ||
| 565 | s.Add_Space_if_NotEmpty(); | ||
| 566 | s.Add_UInt32(MHz); | ||
| 567 | s += " MHz"; | ||
| 568 | } | ||
| 569 | #endif | ||
| 570 | if (!LargePages.IsEmpty()) | ||
| 571 | s.Add_OptSpaced(LargePages); | ||
| 572 | } | ||
| 573 | |||
| 574 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 575 | void Get_Registers(AString &s) | ||
| 576 | { | ||
| 577 | if (Arm64_ISAR0_EL1_Defined) | ||
| 578 | { | ||
| 579 | // ID_AA64ISAR0_EL1 | ||
| 580 | s.Add_OptSpaced("cp4030:"); | ||
| 581 | PrintHex(s, Arm64_ISAR0_EL1); | ||
| 582 | { | ||
| 583 | const unsigned sha2 = ((unsigned)(Arm64_ISAR0_EL1 >> 12) & 0xf) - 1; | ||
| 584 | if (sha2 < 2) | ||
| 585 | { | ||
| 586 | s += ":SHA256"; | ||
| 587 | if (sha2) | ||
| 588 | s += ":SHA512"; | ||
| 589 | } | ||
| 590 | } | ||
| 591 | } | ||
| 541 | } | 592 | } |
| 593 | #endif | ||
| 542 | }; | 594 | }; |
| 543 | 595 | ||
| 544 | void CCpuName::Fill() | 596 | void CCpuName::Fill() |
| 545 | { | 597 | { |
| 546 | CpuName.Empty(); | 598 | // CpuName.Empty(); |
| 547 | Revision.Empty(); | 599 | // Revision.Empty(); |
| 548 | Microcode.Empty(); | 600 | // Microcode.Empty(); |
| 549 | LargePages.Empty(); | 601 | // LargePages.Empty(); |
| 550 | 602 | ||
| 551 | AString &s = CpuName; | 603 | AString &s = CpuName; |
| 552 | 604 | ||
| @@ -600,21 +652,32 @@ void CCpuName::Fill() | |||
| 600 | Revision += GetAnsiString(name); | 652 | Revision += GetAnsiString(name); |
| 601 | } | 653 | } |
| 602 | } | 654 | } |
| 655 | #ifdef _WIN32 | ||
| 656 | key.GetValue_UInt32_IfOk(TEXT("~MHz"), MHz); | ||
| 657 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 658 | /* | ||
| 659 | mapping arm64 registers to Windows registry: | ||
| 660 | CP 4000: MIDR_EL1 | ||
| 661 | CP 4020: ID_AA64PFR0_EL1 | ||
| 662 | CP 4021: ID_AA64PFR1_EL1 | ||
| 663 | CP 4028: ID_AA64DFR0_EL1 | ||
| 664 | CP 4029: ID_AA64DFR1_EL1 | ||
| 665 | CP 402C: ID_AA64AFR0_EL1 | ||
| 666 | CP 402D: ID_AA64AFR1_EL1 | ||
| 667 | CP 4030: ID_AA64ISAR0_EL1 | ||
| 668 | CP 4031: ID_AA64ISAR1_EL1 | ||
| 669 | CP 4038: ID_AA64MMFR0_EL1 | ||
| 670 | CP 4039: ID_AA64MMFR1_EL1 | ||
| 671 | CP 403A: ID_AA64MMFR2_EL1 | ||
| 672 | */ | ||
| 673 | if (key.GetValue_UInt64_IfOk(TEXT("CP 4030"), Arm64_ISAR0_EL1) == ERROR_SUCCESS) | ||
| 674 | Arm64_ISAR0_EL1_Defined = true; | ||
| 675 | #endif | ||
| 676 | #endif | ||
| 603 | LONG res[2]; | 677 | LONG res[2]; |
| 604 | CByteBuffer bufs[2]; | 678 | CByteBuffer bufs[2]; |
| 605 | { | 679 | res[0] = key.QueryValue_Binary(TEXT("Previous Update Revision"), bufs[0]); |
| 606 | for (unsigned i = 0; i < 2; i++) | 680 | res[1] = key.QueryValue_Binary(TEXT("Update Revision"), bufs[1]); |
| 607 | { | ||
| 608 | UInt32 size = 0; | ||
| 609 | res[i] = key.QueryValue(i == 0 ? | ||
| 610 | TEXT("Previous Update Revision") : | ||
| 611 | TEXT("Update Revision"), | ||
| 612 | bufs[i], size); | ||
| 613 | if (res[i] == ERROR_SUCCESS) | ||
| 614 | if (size != bufs[i].Size()) | ||
| 615 | res[i] = ERROR_SUCCESS + 1; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) | 681 | if (res[0] == ERROR_SUCCESS || res[1] == ERROR_SUCCESS) |
| 619 | { | 682 | { |
| 620 | for (unsigned i = 0; i < 2; i++) | 683 | for (unsigned i = 0; i < 2; i++) |
| @@ -747,9 +810,18 @@ void AddCpuFeatures(AString &s) | |||
| 747 | unsigned long h = MY_getauxval(AT_HWCAP); | 810 | unsigned long h = MY_getauxval(AT_HWCAP); |
| 748 | PrintHex(s, h); | 811 | PrintHex(s, h); |
| 749 | #ifdef MY_CPU_ARM64 | 812 | #ifdef MY_CPU_ARM64 |
| 813 | #ifndef HWCAP_SHA3 | ||
| 814 | #define HWCAP_SHA3 (1 << 17) | ||
| 815 | #endif | ||
| 816 | #ifndef HWCAP_SHA512 | ||
| 817 | #define HWCAP_SHA512 (1 << 21) | ||
| 818 | // #pragma message("=== HWCAP_SHA512 define === ") | ||
| 819 | #endif | ||
| 750 | if (h & HWCAP_CRC32) s += ":CRC32"; | 820 | if (h & HWCAP_CRC32) s += ":CRC32"; |
| 751 | if (h & HWCAP_SHA1) s += ":SHA1"; | 821 | if (h & HWCAP_SHA1) s += ":SHA1"; |
| 752 | if (h & HWCAP_SHA2) s += ":SHA2"; | 822 | if (h & HWCAP_SHA2) s += ":SHA2"; |
| 823 | if (h & HWCAP_SHA3) s += ":SHA3"; | ||
| 824 | if (h & HWCAP_SHA512) s += ":SHA512"; | ||
| 753 | if (h & HWCAP_AES) s += ":AES"; | 825 | if (h & HWCAP_AES) s += ":AES"; |
| 754 | if (h & HWCAP_ASIMD) s += ":ASIMD"; | 826 | if (h & HWCAP_ASIMD) s += ":ASIMD"; |
| 755 | #elif defined(MY_CPU_ARM) | 827 | #elif defined(MY_CPU_ARM) |
| @@ -908,13 +980,18 @@ void GetSystemInfoText(AString &sRes) | |||
| 908 | } | 980 | } |
| 909 | } | 981 | } |
| 910 | { | 982 | { |
| 911 | AString s; | 983 | AString s, registers; |
| 912 | GetCpuName_MultiLine(s); | 984 | GetCpuName_MultiLine(s, registers); |
| 913 | if (!s.IsEmpty()) | 985 | if (!s.IsEmpty()) |
| 914 | { | 986 | { |
| 915 | sRes += s; | 987 | sRes += s; |
| 916 | sRes.Add_LF(); | 988 | sRes.Add_LF(); |
| 917 | } | 989 | } |
| 990 | if (!registers.IsEmpty()) | ||
| 991 | { | ||
| 992 | sRes += registers; | ||
| 993 | sRes.Add_LF(); | ||
| 994 | } | ||
| 918 | } | 995 | } |
| 919 | /* | 996 | /* |
| 920 | #ifdef MY_CPU_X86_OR_AMD64 | 997 | #ifdef MY_CPU_X86_OR_AMD64 |
| @@ -932,8 +1009,8 @@ void GetSystemInfoText(AString &sRes) | |||
| 932 | } | 1009 | } |
| 933 | 1010 | ||
| 934 | 1011 | ||
| 935 | void GetCpuName_MultiLine(AString &s); | 1012 | void GetCpuName_MultiLine(AString &s, AString ®isters); |
| 936 | void GetCpuName_MultiLine(AString &s) | 1013 | void GetCpuName_MultiLine(AString &s, AString ®isters) |
| 937 | { | 1014 | { |
| 938 | CCpuName cpuName; | 1015 | CCpuName cpuName; |
| 939 | cpuName.Fill(); | 1016 | cpuName.Fill(); |
| @@ -945,6 +1022,10 @@ void GetCpuName_MultiLine(AString &s) | |||
| 945 | s.Add_LF(); | 1022 | s.Add_LF(); |
| 946 | s += s2; | 1023 | s += s2; |
| 947 | } | 1024 | } |
| 1025 | registers.Empty(); | ||
| 1026 | #ifdef Z7_SYS_INFO_SHOW_ARM64_REGS | ||
| 1027 | cpuName.Get_Registers(registers); | ||
| 1028 | #endif | ||
| 948 | } | 1029 | } |
| 949 | 1030 | ||
| 950 | 1031 | ||
diff --git a/CPP/Windows/SystemInfo.h b/CPP/Windows/SystemInfo.h index c2e2e3b..4601685 100644 --- a/CPP/Windows/SystemInfo.h +++ b/CPP/Windows/SystemInfo.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "../Common/MyString.h" | 6 | #include "../Common/MyString.h" |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | void GetCpuName_MultiLine(AString &s); | 9 | void GetCpuName_MultiLine(AString &s, AString ®isters); |
| 10 | 10 | ||
| 11 | void GetOsInfoText(AString &sRes); | 11 | void GetOsInfoText(AString &sRes); |
| 12 | void GetSystemInfoText(AString &s); | 12 | void GetSystemInfoText(AString &s); |
