diff --git a/src/checksum.c b/src/checksum.c index c9db99cb..e831cc54 100644 --- a/src/checksum.c +++ b/src/checksum.c @@ -63,9 +63,9 @@ #define WAIT_TIME 5000 /* Globals */ -char sum_str[NUM_CHECKSUMS][65]; -uint32_t bufnum, sum_count[NUM_CHECKSUMS] = { 16, 20, 32 }; -HANDLE data_ready[NUM_CHECKSUMS], thread_ready[NUM_CHECKSUMS]; +char sum_str[CHECKSUM_MAX][65]; +uint32_t bufnum, sum_count[CHECKSUM_MAX] = { 16, 20, 32 }; +HANDLE data_ready[CHECKSUM_MAX], thread_ready[CHECKSUM_MAX]; DWORD read_size[2]; char ALIGNED(64) buffer[2][BUFFER_SIZE]; @@ -709,9 +709,52 @@ static void null_final(SUM_CONTEXT *ctx) { } typedef void sum_init_t(SUM_CONTEXT *ctx); typedef void sum_write_t(SUM_CONTEXT *ctx, const unsigned char *buf, size_t len); typedef void sum_final_t(SUM_CONTEXT *ctx); -sum_init_t *sum_init[NUM_CHECKSUMS] = { md5_init, sha1_init , sha256_init }; -sum_write_t *sum_write[NUM_CHECKSUMS] = { md5_write, sha1_write , sha256_write }; -sum_final_t *sum_final[NUM_CHECKSUMS] = { md5_final, sha1_final , sha256_final }; +sum_init_t *sum_init[CHECKSUM_MAX] = { md5_init, sha1_init , sha256_init }; +sum_write_t *sum_write[CHECKSUM_MAX] = { md5_write, sha1_write , sha256_write }; +sum_final_t *sum_final[CHECKSUM_MAX] = { md5_final, sha1_final , sha256_final }; + +// Compute an individual checksum without threading or buffering, for a single file +BOOL Checksum(const unsigned type, const char* path, uint8_t* sum) +{ + BOOL r = FALSE; + SUM_CONTEXT sum_ctx = { 0 }; + HANDLE h = INVALID_HANDLE_VALUE; + DWORD read_size = 0; + uint64_t rb; + char buffer[4096]; + + if ((type >= CHECKSUM_MAX) || (path == NULL) || (sum == NULL)) + goto out; + + uprintf("\r\nComputing checksum for '%s'...", path); + h = CreateFileU(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); + if (h == INVALID_HANDLE_VALUE) { + uprintf("Could not open file: %s", WindowsErrorString()); + FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_OPEN_FAILED; + goto out; + } + + sum_init[type](&sum_ctx); + for (rb = 0; ; rb += read_size) { + CHECK_FOR_USER_CANCEL; + if (!ReadFile(h, buffer, sizeof(buffer), &read_size, NULL)) { + FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_READ_FAULT; + uprintf(" Read error: %s", WindowsErrorString()); + goto out; + } + if (read_size == 0) + break; + sum_write[type](&sum_ctx, buffer, (size_t)read_size); + } + sum_final[type](&sum_ctx); + + memcpy(sum, sum_ctx.buf, sum_count[type]); + r = TRUE; + +out: + safe_closehandle(h); + return r; +} /* * Checksum dialog callback @@ -817,7 +860,7 @@ error: DWORD WINAPI SumThread(void* param) { DWORD_PTR* thread_affinity = (DWORD_PTR*)param; - HANDLE sum_thread[NUM_CHECKSUMS] = { NULL, NULL, NULL }; + HANDLE sum_thread[CHECKSUM_MAX] = { NULL, NULL, NULL }; HANDLE h = INVALID_HANDLE_VALUE; uint64_t rb, LastRefresh = 0; int i, _bufnum, r = -1; @@ -835,7 +878,7 @@ DWORD WINAPI SumThread(void* param) // is usually in this first mask, for other tasks. SetThreadAffinityMask(GetCurrentThread(), thread_affinity[0]); - for (i = 0; i < NUM_CHECKSUMS; i++) { + for (i = 0; i < CHECKSUM_MAX; i++) { // NB: Can't use a single manual-reset event for data_ready as we // wouldn't be able to ensure the event is reset before the thread // gets into its next wait loop @@ -882,7 +925,7 @@ DWORD WINAPI SumThread(void* param) // Toggle the read buffer _bufnum = (bufnum + 1) % 2; // Signal the waiting threads - for (i = 0; i < NUM_CHECKSUMS; i++) { + for (i = 0; i < CHECKSUM_MAX; i++) { if (!SetEvent(data_ready[i])) { uprintf("Could not signal checksum thread %d: %s", i, WindowsErrorString()); goto out; @@ -902,14 +945,14 @@ DWORD WINAPI SumThread(void* param) } // Wait for the thread to signal they are ready to process data - if (WaitForMultipleObjects(NUM_CHECKSUMS, thread_ready, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { + if (WaitForMultipleObjects(CHECKSUM_MAX, thread_ready, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { uprintf("Checksum threads failed to signal: %s", WindowsErrorString()); goto out; } } // Our last event with read_size=0 signaled the threads to exit - wait for that to happen - if (WaitForMultipleObjects(NUM_CHECKSUMS, sum_thread, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { + if (WaitForMultipleObjects(CHECKSUM_MAX, sum_thread, TRUE, WAIT_TIME) != WAIT_OBJECT_0) { uprintf("Checksum threads did not finalize: %s", WindowsErrorString()); goto out; } @@ -920,7 +963,7 @@ DWORD WINAPI SumThread(void* param) r = 0; out: - for (i = 0; i < NUM_CHECKSUMS; i++) { + for (i = 0; i < CHECKSUM_MAX; i++) { if (sum_thread[i] != NULL) TerminateThread(sum_thread[i], 1); CloseHandle(data_ready[i]); diff --git a/src/rufus.c b/src/rufus.c index 4ce21356..e6fbf847 100644 --- a/src/rufus.c +++ b/src/rufus.c @@ -2270,7 +2270,16 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA break; #ifdef RUFUS_TEST case IDC_TEST: + { + int j; + char str[65]; + uint8_t sum[32]; + Checksum(CHECKSUM_SHA256, "C:\\rufus\\src\\.msvc\\rufus_files\\syslinux-6.03\\ldlinux.sys", sum); + for (j = 0; j < sizeof(sum); j++) + safe_sprintf(&str[2 * j], ARRAYSIZE(str) - 2 * j, "%02x", sum[j]); + uprintf(" Checksum: %s", str); break; + } #endif case IDC_ADVANCED: advanced_mode = !advanced_mode; @@ -2540,7 +2549,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA // Disable all controls except cancel EnableControls(FALSE); InitProgress(FALSE); - SetThreadAffinity(thread_affinity, NUM_CHECKSUMS + 1); + SetThreadAffinity(thread_affinity, CHECKSUM_MAX + 1); format_thid = CreateThread(NULL, 0, SumThread, (LPVOID)thread_affinity, 0, NULL); if (format_thid != NULL) { PrintInfo(0, -1); diff --git a/src/rufus.h b/src/rufus.h index 186e1980..182abd20 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -42,7 +42,7 @@ #define APPLICATION_NAME "Rufus" #define COMPANY_NAME "Akeo Consulting" #define STR_NO_LABEL "NO_LABEL" -// Yes, there is a character between these seemingly empty quotes! +// Yes, there exist characters between these seemingly empty quotes! #define LEFT_TO_RIGHT_MARK "‎" #define RIGHT_TO_LEFT_MARK "‏" #define LEFT_TO_RIGHT_EMBEDDING "‪" @@ -68,7 +68,6 @@ #define MBR_UEFI_MARKER 0x49464555 // 'U', 'E', 'F', 'I', as a 32 bit little endian longword #define STATUS_MSG_TIMEOUT 3500 // How long should cheat mode messages appear for on the status bar #define WRITE_RETRIES 3 -#define NUM_CHECKSUMS 3 // Number of checksum algorithms we support (MD5, SHA1, SHA256) #define FS_DEFAULT FS_FAT32 #define SINGLE_CLUSTERSIZE_DEFAULT 0x00000100 #define BADBLOCK_PATTERNS {0xaa, 0x55, 0xff, 0x00} @@ -232,6 +231,13 @@ enum target_type { #define GETTARGETTYPE(x) (((x)>0)?(((x) >> 16) & 0xFFFF):0) #define GETPARTTYPE(x) (((x)>0)?((x) & 0xFFFF):0); +enum checksum_type { + CHECKSUM_MD5 = 0, + CHECKSUM_SHA1, + CHECKSUM_SHA256, + CHECKSUM_MAX +}; + /* Special handling for old .c32 files we need to replace */ #define NB_OLD_C32 2 #define OLD_C32_NAMES { "menu.c32", "vesamenu.c32" } @@ -450,6 +456,7 @@ extern BOOL IsFontAvailable(const char* font_name); extern BOOL WriteFileWithRetry(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, DWORD nNumRetries); extern BOOL SetThreadAffinity(DWORD_PTR* thread_affinity, size_t num_threads); +extern BOOL Checksum(const unsigned type, const char* path, uint8_t* sum); #define printbits(x) _printbits(sizeof(x), &x, 0) #define printbitslz(x) _printbits(sizeof(x), &x, 1) extern char* _printbits(size_t const size, void const * const ptr, int leading_zeroes); diff --git a/src/rufus.rc b/src/rufus.rc index 06151ebe..fa55f8a8 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 242, 376 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 2.10.938" +CAPTION "Rufus 2.10.939" FONT 8, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Device",IDS_DEVICE_TXT,9,6,200,8 @@ -320,8 +320,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,10,938,0 - PRODUCTVERSION 2,10,938,0 + FILEVERSION 2,10,939,0 + PRODUCTVERSION 2,10,939,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -338,13 +338,13 @@ BEGIN BEGIN VALUE "CompanyName", "Akeo Consulting (http://akeo.ie)" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "2.10.938" + VALUE "FileVersion", "2.10.939" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", " 2011-2016 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "2.10.938" + VALUE "ProductVersion", "2.10.939" END END BLOCK "VarFileInfo" diff --git a/src/smart.c b/src/smart.c index a07de632..a12b1f32 100644 --- a/src/smart.c +++ b/src/smart.c @@ -181,7 +181,7 @@ static int SatAtaPassthrough(HANDLE hPhysical, ATA_PASSTHROUGH_CMD* Command, voi int t_length = 0; /* 0 -> no data transferred */ uint8_t Direction; - if (BufLen % SelectedDrive.Geometry.BytesPerSector != 0) { + if (BufLen % SelectedDrive.SectorSize != 0) { uprintf("SatAtaPassthrough: BufLen must be a multiple of \n"); return SPT_ERROR_BUFFER; }