mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[misc] improved label and config handling
* add readout and display of extended autorun.inf label if available * use improved isolinux config parsing * also fix an issue that could leave drive unmounted on forced removal * also add Alt-F cheatmode to toggle detection of fixed USB disks
This commit is contained in:
		
							parent
							
								
									1fce90dc7c
								
							
						
					
					
						commit
						3721b0a570
					
				
					 13 changed files with 363 additions and 68 deletions
				
			
		|  | @ -165,6 +165,7 @@ | |||
|     <ClCompile Include="..\dos.c" /> | ||||
|     <ClCompile Include="..\icon.c" /> | ||||
|     <ClCompile Include="..\iso.c" /> | ||||
|     <ClCompile Include="..\parser.c" /> | ||||
|     <ClCompile Include="..\rufus.c" /> | ||||
|     <ClCompile Include="..\stdio.c" /> | ||||
|     <ClCompile Include="..\stdlg.c" /> | ||||
|  |  | |||
|  | @ -48,6 +48,9 @@ | |||
|     <ClCompile Include="..\icon.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|     <ClCompile Include="..\parser.c"> | ||||
|       <Filter>Source Files</Filter> | ||||
|     </ClCompile> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ClInclude Include="..\rufus.h"> | ||||
|  |  | |||
|  | @ -33,6 +33,7 @@ SOURCES=rufus.c          \ | |||
|         stdio.c          \ | ||||
|         stdlg.c          \ | ||||
|         icon.c           \ | ||||
|         parser.c         \ | ||||
|         iso.c            \ | ||||
|         dos.c            \ | ||||
|         dos_locale.c     \ | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ pkg_v_rc_0 = @echo "  RC     $@"; | |||
| %_rc.o: %.rc | ||||
| 	$(pkg_v_rc)$(WINDRES) $(AM_RCFLAGS) -i $< -o $@ | ||||
| 
 | ||||
| rufus_SOURCES = drive.c icon.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \ | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ CONFIG_CLEAN_FILES = | |||
| CONFIG_CLEAN_VPATH_FILES = | ||||
| PROGRAMS = $(noinst_PROGRAMS) | ||||
| am_rufus_OBJECTS = rufus-drive.$(OBJEXT) rufus-icon.$(OBJEXT) \
 | ||||
| 	rufus-iso.$(OBJEXT) rufus-dos.$(OBJEXT) \
 | ||||
| 	rufus-parser.$(OBJEXT) rufus-iso.$(OBJEXT) rufus-dos.$(OBJEXT) \
 | ||||
| 	rufus-dos_locale.$(OBJEXT) rufus-badblocks.$(OBJEXT) \
 | ||||
| 	rufus-syslinux.$(OBJEXT) rufus-format.$(OBJEXT) \
 | ||||
| 	rufus-stdio.$(OBJEXT) rufus-stdlg.$(OBJEXT) \
 | ||||
|  | @ -185,7 +185,7 @@ SUBDIRS = ms-sys syslinux/libfat syslinux/libinstaller libcdio/iso9660 libcdio/u | |||
| pkg_v_rc = $(pkg_v_rc_$(V)) | ||||
| pkg_v_rc_ = $(pkg_v_rc_$(AM_DEFAULT_VERBOSITY)) | ||||
| pkg_v_rc_0 = @echo "  RC     $@"; | ||||
| rufus_SOURCES = drive.c icon.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_SOURCES = drive.c icon.c parser.c iso.c dos.c dos_locale.c badblocks.c syslinux.c format.c stdio.c stdlg.c rufus.c | ||||
| rufus_CFLAGS = -I./ms-sys/inc -I./syslinux/libfat -I./syslinux/libinstaller -I./libcdio $(AM_CFLAGS) | ||||
| rufus_LDFLAGS = $(AM_LDFLAGS) -mwindows | ||||
| rufus_LDADD = rufus_rc.o ms-sys/libmssys.a syslinux/libfat/libfat.a syslinux/libinstaller/libinstaller.a \
 | ||||
|  | @ -262,6 +262,14 @@ rufus-icon.obj: icon.c | |||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-icon.obj `if test -f 'icon.c'; then $(CYGPATH_W) 'icon.c'; else $(CYGPATH_W) '$(srcdir)/icon.c'; fi` | ||||
| 
 | ||||
| rufus-parser.o: parser.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-parser.o `test -f 'parser.c' || echo '$(srcdir)/'`parser.c | ||||
| 
 | ||||
| rufus-parser.obj: parser.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-parser.obj `if test -f 'parser.c'; then $(CYGPATH_W) 'parser.c'; else $(CYGPATH_W) '$(srcdir)/parser.c'; fi` | ||||
| 
 | ||||
| rufus-iso.o: iso.c | ||||
| 	$(AM_V_CC) @AM_BACKSLASH@ | ||||
| 	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(rufus_CFLAGS) $(CFLAGS) -c -o rufus-iso.o `test -f 'iso.c' || echo '$(srcdir)/'`iso.c | ||||
|  |  | |||
							
								
								
									
										15
									
								
								src/drive.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/drive.c
									
										
									
									
									
								
							|  | @ -34,6 +34,8 @@ | |||
|  * Globals | ||||
|  */ | ||||
| RUFUS_DRIVE_INFO SelectedDrive; | ||||
| extern BOOL enable_fixed_disks; | ||||
| extern char* get_token_data(const char* filename, const char* token); | ||||
| 
 | ||||
| /*
 | ||||
|  * Open a drive or volume with optional write and lock access | ||||
|  | @ -103,7 +105,7 @@ HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BO | |||
| 			drive_type = GetDriveTypeA(drive); | ||||
| 			// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't really really want for now
 | ||||
| 			// TODO: allow fixed drives after partitioning/preserving of existing partitions has been sorted out
 | ||||
| 			if (drive_type != DRIVE_REMOVABLE) | ||||
| 			if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED))) | ||||
| 				continue; | ||||
| 
 | ||||
| 			safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]); | ||||
|  | @ -149,6 +151,7 @@ out: | |||
| BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | ||||
| { | ||||
| 	HANDLE hDrive; | ||||
| 	char AutorunPath[] = "#:\\autorun.inf", *AutorunLabel; | ||||
| 	wchar_t wDrivePath[] = L"#:\\"; | ||||
| 	wchar_t wVolumeLabel[MAX_PATH+1]; | ||||
| 	static char VolumeLabel[MAX_PATH+1]; | ||||
|  | @ -159,9 +162,17 @@ BOOL GetDriveLabel(DWORD DriveIndex, char* letter, char** label) | |||
| 	if (hDrive == INVALID_HANDLE_VALUE) | ||||
| 		return FALSE; | ||||
| 	safe_closehandle(hDrive); | ||||
| 	AutorunPath[0] = *letter; | ||||
| 	wDrivePath[0] = *letter; | ||||
| 
 | ||||
| 	if (GetVolumeInformationW(wDrivePath, wVolumeLabel, sizeof(wVolumeLabel), | ||||
| 	// Try to read an extended label from autorun first. Fallback to regular label if not found.
 | ||||
| 	AutorunLabel = get_token_data(AutorunPath, "label"); | ||||
| 	if (AutorunLabel != NULL) { | ||||
| 		uprintf("Using autorun.inf label for device %c:\n", *letter); | ||||
| 		strncpy(VolumeLabel, AutorunLabel, sizeof(VolumeLabel)); | ||||
| 		safe_free(AutorunLabel); | ||||
| 		*label = VolumeLabel; | ||||
| 	} else if (GetVolumeInformationW(wDrivePath, wVolumeLabel, sizeof(wVolumeLabel), | ||||
| 		NULL, NULL, NULL, NULL, 0) && *wVolumeLabel) { | ||||
| 		wchar_to_utf8_no_alloc(wVolumeLabel, VolumeLabel, sizeof(VolumeLabel)); | ||||
| 		*label = VolumeLabel; | ||||
|  |  | |||
|  | @ -656,8 +656,9 @@ DWORD WINAPI FormatThread(LPVOID param) | |||
| 			if (iso_path != NULL) { | ||||
| 				PrintStatus(0, TRUE, "Copying ISO files..."); | ||||
| 				drive_name[2] = 0; | ||||
| 				if ( (!ExtractISO(iso_path, drive_name, FALSE)) && (!FormatStatus)) { | ||||
| 					FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | ||||
| 				if (!ExtractISO(iso_path, drive_name, FALSE)) { | ||||
| 					if (!FormatStatus) | ||||
| 						FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_CANNOT_COPY; | ||||
| 					goto out; | ||||
| 				} | ||||
| 			} | ||||
|  |  | |||
							
								
								
									
										68
									
								
								src/iso.c
									
										
									
									
									
								
							
							
						
						
									
										68
									
								
								src/iso.c
									
										
									
									
									
								
							|  | @ -71,6 +71,8 @@ static uint64_t total_blocks, nb_blocks; | |||
| static BOOL scan_only = FALSE; | ||||
| static StrArray config_path; | ||||
| 
 | ||||
| extern char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep); | ||||
| 
 | ||||
| // TODO: Timestamp & permissions preservation
 | ||||
| 
 | ||||
| // Convert a file size to human readable
 | ||||
|  | @ -102,55 +104,6 @@ static void log_handler (cdio_log_level_t level, const char *message) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Workaround for isolinux config files requiring an ISO label for kernel | ||||
|  * append that may be different from our USB label. | ||||
|  * NB: this is intended as a quick-and-dirty workaround, because it is the | ||||
|  * distro creator's job to make their config and labels also work with USB. | ||||
|  * As such, this process may fail if: | ||||
|  * - the label is on the block size limit, for cfg files of more than 2KB | ||||
|  * - the user changed the label to one that is larger than the one from the cfg | ||||
|  * - the cfg is weird (more than one label on the same line, etc.) | ||||
|  */ | ||||
| static void process_config(char* buf, size_t buf_size, const char* cfg_name) | ||||
| { | ||||
| 	char last_char, eol_char, *label; | ||||
| 	size_t i, j, k; | ||||
| 
 | ||||
| 	// Don't apply workaround if USB label is the same or longer than ISO
 | ||||
| 	if ( (strcmp(iso_report.label, iso_report.usb_label) == 0) | ||||
| 	  || (strlen(iso_report.label) < strlen(iso_report.usb_label)) ) | ||||
| 		return; | ||||
| 
 | ||||
| 	// Make sure our buffer is NUL terminated
 | ||||
| 	if (buf_size >= UDF_BLOCKSIZE)	// UDF_BLOCKSIZE = ISO_BLOCKSIZE = 2048
 | ||||
| 		buf_size = UDF_BLOCKSIZE-1; | ||||
| 	last_char = buf[buf_size]; | ||||
| 	buf[buf_size] = 0; | ||||
| 
 | ||||
| 	for (i=0; i<buf_size; i++) { | ||||
| 		// Check if there is a line starting with "append" (case insensitive)
 | ||||
| 		if (_strnicmp(&buf[i], "append", sizeof("append")-1) == 0) { | ||||
| 			for (j=i; (buf[j]!=0x00)&&(buf[j]!=0x0A)&&(buf[j]!=0x0D); j++);	// EOL
 | ||||
| 			eol_char = buf[j];	// Make sure the line is NUL terminated
 | ||||
| 			buf[j] = 0; | ||||
| 			label = strstr(&buf[i], iso_report.label); | ||||
| 			if (label != NULL) { | ||||
| 				// Since label is longer than usb_label we can replace it
 | ||||
| 				for (k=0; k<strlen(iso_report.label); k++) | ||||
| 					label[k] = (k<strlen(iso_report.usb_label))?iso_report.usb_label[k]:' '; | ||||
| 				uprintf("  Patched config file to use USB label '%s'\n", iso_report.usb_label); | ||||
| //				uprintf("  Patched line: '%s'\n", &buf[i]);
 | ||||
| 			} | ||||
| 			// Revert EOL
 | ||||
| 			buf[j] = eol_char; | ||||
| 			i = j; | ||||
| 		} | ||||
| 	} | ||||
| 	// Revert NUL terminator
 | ||||
| 	buf[buf_size] = last_char; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Scan and set ISO properties | ||||
|  * Returns true if the the current file does not need to be processed further | ||||
|  | @ -259,8 +212,6 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha | |||
| 					goto out; | ||||
| 				} | ||||
| 				buf_size = (DWORD)MIN(i_file_length, i_read); | ||||
| 				if (is_syslinux_cfg) | ||||
| 					process_config((char*)buf, (size_t)buf_size, psz_fullpath); | ||||
| 				ISO_BLOCKING(r = WriteFile(file_handle, buf, buf_size, &wr_size, NULL)); | ||||
| 				if ((!r) || (buf_size != wr_size)) { | ||||
| 					uprintf("  Error writing file: %s\n", WindowsErrorString()); | ||||
|  | @ -277,6 +228,12 @@ static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const cha | |||
| 			// The drawback however is with cancellation. With a large file, CloseHandle()
 | ||||
| 			// may take forever to complete and is not interruptible. We try to detect this.
 | ||||
| 			ISO_BLOCKING(safe_closehandle(file_handle)); | ||||
| 			if (is_syslinux_cfg) { | ||||
| 				// Workaround for isolinux config files requiring an ISO label for kernel
 | ||||
| 				// append that may be different from our USB label.
 | ||||
| 				if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label) != NULL) | ||||
| 					uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); | ||||
| 			} | ||||
| 		} | ||||
| 		safe_free(psz_fullpath); | ||||
| 	} | ||||
|  | @ -363,8 +320,6 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) | |||
| 					goto out; | ||||
| 				} | ||||
| 				buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE); | ||||
| 				if (is_syslinux_cfg) | ||||
| 					process_config((char*)buf, (size_t)buf_size, psz_fullpath); | ||||
| 				ISO_BLOCKING(s = WriteFile(file_handle, buf, buf_size, &wr_size, NULL)); | ||||
| 				if ((!s) || (buf_size != wr_size)) { | ||||
| 					uprintf("  Error writing file: %s\n", WindowsErrorString()); | ||||
|  | @ -376,6 +331,10 @@ static int iso_extract_files(iso9660_t* p_iso, const char *psz_path) | |||
| 				} | ||||
| 			} | ||||
| 			ISO_BLOCKING(safe_closehandle(file_handle)); | ||||
| 			if (is_syslinux_cfg) { | ||||
| 				if (replace_in_token_data(psz_fullpath, "append", iso_report.label, iso_report.usb_label) != NULL) | ||||
| 					uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	r = 0; | ||||
|  | @ -506,7 +465,8 @@ out: | |||
| 				uprintf("Created: %s\n", syslinux_path); | ||||
| 			} | ||||
| 		} | ||||
| 		fclose(fd); | ||||
| 		if (fd != NULL) | ||||
| 			fclose(fd); | ||||
| 	} | ||||
| 	SendMessage(hISOProgressDlg, UM_ISO_EXIT, 0, 0); | ||||
| 	if (p_iso != NULL) | ||||
|  |  | |||
							
								
								
									
										268
									
								
								src/parser.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								src/parser.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,268 @@ | |||
| /*
 | ||||
|  * Rufus: The Reliable USB Formatting Utility | ||||
|  * Elementary Unicode compliant find/replace parser | ||||
|  * Copyright (c) 2012 Pete Batard <pete@akeo.ie> | ||||
|  * | ||||
|  * This program is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * This program is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
|  */ | ||||
| 
 | ||||
| /* Memory leaks detection - define _CRTDBG_MAP_ALLOC as preprocessor macro */ | ||||
| #ifdef _CRTDBG_MAP_ALLOC | ||||
| #include <stdlib.h> | ||||
| #include <crtdbg.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <windows.h> | ||||
| #include <stdio.h> | ||||
| #include <wchar.h> | ||||
| #include <string.h> | ||||
| #include <malloc.h> | ||||
| #include <io.h> | ||||
| #include <fcntl.h> | ||||
| 
 | ||||
| #include "rufus.h" | ||||
| #include "msapi_utf8.h" | ||||
| 
 | ||||
| // Parse a file (ANSI or UTF-8 or UTF-16) and return the data for the first occurence of 'token'
 | ||||
| // The parsed line is of the form: [ ]token[ ]=[ ]["]data["]
 | ||||
| // The returned string is UTF-8 and MUST be freed by the caller
 | ||||
| char* get_token_data(const char* filename, const char* token) | ||||
| { | ||||
| 	wchar_t *wtoken = NULL, *wfilename = NULL; | ||||
| 	wchar_t wspace[] = L" \t"; | ||||
| 	wchar_t weol[] = L"\r\n"; | ||||
| 	wchar_t buf[1024]; | ||||
| 	FILE* fd = NULL; | ||||
| 	size_t i, r; | ||||
| 	char *ret = NULL; | ||||
| 
 | ||||
| 	if ((filename == NULL) || (token == NULL)) | ||||
| 		return NULL; | ||||
| 	if ((filename[0] == 0) || (token[0] == 0)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	wfilename = utf8_to_wchar(filename); | ||||
| 	if (wfilename == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wtoken = utf8_to_wchar(token); | ||||
| 	if (wfilename == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", token); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	fd = _wfopen(wfilename, L"r, ccs=UNICODE"); | ||||
| 	if (fd == NULL) { | ||||
| 		uprintf("Could not open file '%s'\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	// Process individual lines. NUL is always appended.
 | ||||
| 	// Ideally, we'd check that our buffer fits the line
 | ||||
| 	while (fgetws(buf, ARRAYSIZE(buf), fd) != NULL) { | ||||
| 
 | ||||
| 		// Eliminate trailing EOL characters
 | ||||
| 		buf[wcscspn(buf, weol)] = 0; | ||||
| 
 | ||||
| 		i = 0; | ||||
| 
 | ||||
| 		// Skip leading spaces
 | ||||
| 		i += wcsspn(&buf[i], wspace); | ||||
| 
 | ||||
| 		// Our token should begin a line
 | ||||
| 		if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		// Token was found, move past token
 | ||||
| 		i += wcslen(wtoken); | ||||
| 
 | ||||
| 		// Skip spaces
 | ||||
| 		i += wcsspn(&buf[i], wspace); | ||||
| 
 | ||||
| 		// Check for an equal sign
 | ||||
| 		if (buf[i] != L'=')  | ||||
| 			continue; | ||||
| 		i++; | ||||
| 
 | ||||
| 		// Skip spaces after equal sign
 | ||||
| 		i += wcsspn(&buf[i], wspace); | ||||
| 
 | ||||
| 		// eliminate leading quote, if it exists
 | ||||
| 		if (buf[i] == L'"') | ||||
| 			i++; | ||||
| 
 | ||||
| 		// Keep the starting pos of our data
 | ||||
| 		r = i; | ||||
| 
 | ||||
| 		// locate end of string or quote
 | ||||
| 		while ((buf[i] != 0) && (buf[i] != L'"')) | ||||
| 			i++; | ||||
| 		buf[i] = 0; | ||||
| 		ret = wchar_to_utf8(&buf[r]); | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	if (fd != NULL) | ||||
| 		fclose(fd); | ||||
| 	safe_free(wfilename); | ||||
| 	safe_free(wtoken); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| // Search for a specific 'src' substring the data for all occurences of 'token', and replace
 | ||||
| // if with 'rep'. File can be ANSI or UNICODE and is overwritten. Parameters are UTF-8.
 | ||||
| // The parsed line is of the form: [ ]token[ ]data
 | ||||
| // Returns a pointer to rep if replacement occured, NULL otherwise
 | ||||
| char* replace_in_token_data(const char* filename, const char* token, const char* src, const char* rep) | ||||
| { | ||||
| 	const wchar_t* outmode[] = { L"w", L"w, ccs=UTF-8", L"w, ccs=UTF-16LE" }; | ||||
| 	wchar_t *wtoken = NULL, *wfilename = NULL, *wtmpname = NULL, *wsrc = NULL, *wrep = NULL, bom = 0; | ||||
| 	wchar_t wspace[] = L" \t"; | ||||
| 	wchar_t buf[1024], *torep; | ||||
| 	FILE *fd_in = NULL, *fd_out = NULL; | ||||
| 	size_t i, size; | ||||
| 	int mode; | ||||
| 	char *ret = NULL, tmp[2]; | ||||
| 
 | ||||
| 	if ((filename == NULL) || (token == NULL) || (src == NULL) || (rep == NULL)) | ||||
| 		return NULL; | ||||
| 	if ((filename[0] == 0) || (token[0] == 0) || (src[0] == 0) || (rep[0] == 0)) | ||||
| 		return NULL; | ||||
| 	if (strcmp(src, rep) == 0)	// No need for processing is source is same as replacement
 | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	wfilename = utf8_to_wchar(filename); | ||||
| 	if (wfilename == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wtoken = utf8_to_wchar(token); | ||||
| 	if (wfilename == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", token); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wsrc = utf8_to_wchar(src); | ||||
| 	if (wsrc == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", src); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wrep = utf8_to_wchar(rep); | ||||
| 	if (wsrc == NULL) { | ||||
| 		uprintf("Could not convert '%s' to UTF-16\n", rep); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	fd_in = _wfopen(wfilename, L"r, ccs=UNICODE"); | ||||
| 	if (fd_in == NULL) { | ||||
| 		uprintf("Could not open file '%s'\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	// Check the input file's BOM and create an output file with the same
 | ||||
| 	fread(&bom, sizeof(bom), 1, fd_in); | ||||
| 	switch(bom) { | ||||
| 	case 0xFEFF: | ||||
| 		mode = 2;	// UTF-16 (LE)
 | ||||
| 		break; | ||||
| 	case 0xBBEF:	// Yeah, the UTF-8 BOM is really 0xEF,0xBB,0xBF, but
 | ||||
| 		mode = 1;	// find me a non UTF-8 file that actually begins with "ï»"
 | ||||
| 		break; | ||||
| 	default: | ||||
| 		mode = 0;	// ANSI
 | ||||
| 		break; | ||||
| 	} | ||||
| 	fseek(fd_in, 0, SEEK_SET); | ||||
| //	uprintf("'%s' was detected as %s\n", filename, 
 | ||||
| //		(mode==0)?"ANSI/UTF8 (no BOM)":((mode==1)?"UTF8 (with BOM)":"UTF16 (with BOM"));
 | ||||
| 
 | ||||
| 
 | ||||
| 	wtmpname = (wchar_t*)calloc(wcslen(wfilename)+2, sizeof(wchar_t)); | ||||
| 	if (wtmpname == NULL) { | ||||
| 		uprintf("Could not allocate space for temporary output name\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	wcscpy(wtmpname, wfilename); | ||||
| 	wtmpname[wcslen(wtmpname)] = '~'; | ||||
| 
 | ||||
| 	fd_out = _wfopen(wtmpname, outmode[mode]); | ||||
| 	if (fd_out == NULL) { | ||||
| 		uprintf("Could not open temporary output file %s~\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	// Process individual lines. NUL is always appended.
 | ||||
| 	while (fgetws(buf, ARRAYSIZE(buf), fd_in) != NULL) { | ||||
| 
 | ||||
| 		i = 0; | ||||
| 
 | ||||
| 		// Skip leading spaces
 | ||||
| 		i += wcsspn(&buf[i], wspace); | ||||
| 
 | ||||
| 		// Our token should begin a line
 | ||||
| 		if (_wcsnicmp(&buf[i], wtoken, wcslen(wtoken)) != 0) { | ||||
| 			fputws(buf, fd_out); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		// Token was found, move past token
 | ||||
| 		i += strlen(token); | ||||
| 
 | ||||
| 		// Skip spaces
 | ||||
| 		i += wcsspn(&buf[i], wspace); | ||||
| 
 | ||||
| 		torep = wcsstr(&buf[i], wsrc); | ||||
| 		if (torep == NULL) { | ||||
| 			fputws(buf, fd_out); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		i = (torep-buf) + wcslen(wsrc); | ||||
| 		*torep = 0; | ||||
| 		fwprintf(fd_out, L"%s%s%s", buf, wrep, &buf[i]); | ||||
| 		ret = (char*)rep; | ||||
| 	} | ||||
| 
 | ||||
| out: | ||||
| 	if (fd_in != NULL) fclose(fd_in); | ||||
| 	if (fd_out != NULL) fclose(fd_out); | ||||
| 
 | ||||
| 	// If a replacement occured, delete existing file and use the new one
 | ||||
| 	if (ret != NULL) { | ||||
| 		// We're in Windows text mode => Remove CRs
 | ||||
| 		fd_in = _wfopen(wtmpname, L"rb"); | ||||
| 		fd_out = _wfopen(wfilename, L"wb"); | ||||
| 		// Don't check fds
 | ||||
| 		if ((fd_in != NULL) && (fd_out != NULL)) { | ||||
| 			size = (mode==2)?2:1; | ||||
| 			while(fread(tmp, size, 1, fd_in) == 1) { | ||||
| 				if (tmp[0] != 0x0D) | ||||
| 					fwrite(tmp, size, 1, fd_out); | ||||
| 			} | ||||
| 			fclose(fd_in); | ||||
| 			fclose(fd_out); | ||||
| 		} else { | ||||
| 			uprintf("Dos2Unix conversion failed for %s - file will be unusable!\n", filename); | ||||
| 			if (fd_in != NULL) fclose(fd_in); | ||||
| 			if (fd_out != NULL) fclose(fd_out); | ||||
| 		} | ||||
| 	}  | ||||
| 	_wunlink(wtmpname); | ||||
| 	safe_free(wfilename); | ||||
| 	safe_free(wtmpname); | ||||
| 	safe_free(wtoken); | ||||
| 	safe_free(wsrc); | ||||
| 	safe_free(wrep); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										15
									
								
								src/rufus.c
									
										
									
									
									
								
							
							
						
						
									
										15
									
								
								src/rufus.c
									
										
									
									
									
								
							|  | @ -46,6 +46,7 @@ static const char* ClusterSizeLabel[] = { "512 bytes", "1024 bytes","2048 bytes" | |||
| 	"1024 kilobytes","2048 kilobytes","4096 kilobytes","8192 kilobytes","16 megabytes","32 megabytes" }; | ||||
| static BOOL existing_key = FALSE;	// For LGP set/restore
 | ||||
| static BOOL iso_size_check = TRUE; | ||||
| BOOL enable_fixed_disks = FALSE; | ||||
| 
 | ||||
| /*
 | ||||
|  * Globals | ||||
|  | @ -535,6 +536,8 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 	STORAGE_DEVICE_NUMBER_REDEF device_number; | ||||
| 	DWORD size, i, j, datatype; | ||||
| 	HANDLE hDrive; | ||||
| 	LONG maxwidth = 0; | ||||
| 	RECT rect; | ||||
| 	char drive_letter; | ||||
| 	char *label, entry[MAX_PATH], buffer[MAX_PATH]; | ||||
| 	const char* usbstor_name = "USBSTOR"; | ||||
|  | @ -544,6 +547,7 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 	IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList)); | ||||
| 	StrArrayClear(&DriveID); | ||||
| 	StrArrayClear(&DriveLabel); | ||||
| 	GetClientRect(hDeviceList, &rect); | ||||
| 
 | ||||
| 	dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); | ||||
| 	if (dev_info == INVALID_HANDLE_VALUE) { | ||||
|  | @ -623,6 +627,7 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 				safe_sprintf(entry, sizeof(entry), "%s (%c:)", label, drive_letter); | ||||
| 				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), | ||||
| 					device_number.DeviceNumber + DRIVE_INDEX_MIN)); | ||||
| 				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); | ||||
| 				safe_closehandle(hDrive); | ||||
| 				safe_free(devint_detail_data); | ||||
| 				break; | ||||
|  | @ -631,6 +636,9 @@ static BOOL GetUSBDevices(DWORD devnum) | |||
| 	} | ||||
| 	SetupDiDestroyDeviceInfoList(dev_info); | ||||
| 
 | ||||
| 	// Adjust the Dropdown width to the maximum text size
 | ||||
| 	SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0); | ||||
| 
 | ||||
| 	if (devnum >= DRIVE_INDEX_MIN) { | ||||
| 		for (i=0; i<ComboBox_GetCount(hDeviceList); i++) { | ||||
| 			if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) { | ||||
|  | @ -1505,6 +1513,13 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine | |||
| 				PrintStatus(0, FALSE, "ISO size check %s", iso_size_check?"enabled":"disabled"); | ||||
| 				continue; | ||||
| 			} | ||||
| 			// Alt-F => toggle detection of fixed disks
 | ||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'F')) { | ||||
| 				enable_fixed_disks = !enable_fixed_disks; | ||||
| 				PrintStatus(0, FALSE, "Fixed disks detection %s", enable_fixed_disks?"enabled":"disabled"); | ||||
| 				GetUSBDevices(0); | ||||
| 				continue; | ||||
| 			} | ||||
| #ifdef DISABLE_AUTORUN | ||||
| 			// Alt-D => Delete the NoDriveTypeAutorun key on exit (useful if the app crashed)
 | ||||
| 			if ((msg.message == WM_SYSKEYDOWN) && (msg.wParam == 'D')) { | ||||
|  |  | |||
|  | @ -196,6 +196,7 @@ extern BOOL UnmountDrive(HANDLE hDrive); | |||
| extern BOOL CreateProgress(void); | ||||
| extern BOOL SetAutorun(const char* path); | ||||
| extern char* FileDialog(BOOL save, char* path, char* filename, char* ext, char* ext_desc); | ||||
| extern LONG GetEntryWidth(HWND hDropDown, const char *entry); | ||||
| 
 | ||||
| __inline static BOOL UnlockDrive(HANDLE hDrive) | ||||
| { | ||||
|  |  | |||
							
								
								
									
										14
									
								
								src/rufus.rc
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								src/rufus.rc
									
										
									
									
									
								
							|  | @ -33,12 +33,12 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL | |||
| IDD_DIALOG DIALOGEX 12, 12, 206, 289 | ||||
| STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU | ||||
| EXSTYLE WS_EX_APPWINDOW | ||||
| CAPTION "Rufus v1.1.4.147" | ||||
| CAPTION "Rufus v1.1.4.148" | ||||
| FONT 8, "MS Shell Dlg", 400, 0, 0x1 | ||||
| BEGIN | ||||
|     DEFPUSHBUTTON   "Start",IDC_START,94,248,50,14 | ||||
|     PUSHBUTTON      "Close",IDCANCEL,148,248,50,14 | ||||
|     COMBOBOX        IDC_DEVICE,8,17,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | ||||
|     COMBOBOX        IDC_DEVICE,8,17,190,33,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | ||||
|     CONTROL         "Device",IDC_STATIC,"Static",SS_LEFTNOWORDWRAP | WS_GROUP,9,6,22,8 | ||||
|     COMBOBOX        IDC_FILESYSTEM,8,75,190,30,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP | ||||
|     LTEXT           "File system",IDC_STATIC,9,64,51,10 | ||||
|  | @ -73,7 +73,7 @@ BEGIN | |||
|     DEFPUSHBUTTON   "OK",IDOK,231,175,50,14,WS_GROUP | ||||
|     CONTROL         "<a href=""http://rufus.akeo.ie"">http://rufus.akeo.ie</a>",IDC_ABOUT_RUFUS_URL, | ||||
|                     "SysLink",WS_TABSTOP,46,47,114,9 | ||||
|     LTEXT           "Version 1.1.4 (Build 147)",IDC_STATIC,46,19,78,8 | ||||
|     LTEXT           "Version 1.1.4 (Build 148)",IDC_STATIC,46,19,78,8 | ||||
|     PUSHBUTTON      "License...",IDC_ABOUT_LICENSE,46,175,50,14,WS_GROUP | ||||
|     EDITTEXT        IDC_ABOUT_COPYRIGHTS,46,107,235,63,ES_MULTILINE | ES_READONLY | WS_VSCROLL | ||||
|     LTEXT           "Report bugs or request enhancements at:",IDC_STATIC,46,66,187,8 | ||||
|  | @ -223,8 +223,8 @@ END | |||
| // | ||||
| 
 | ||||
| VS_VERSION_INFO VERSIONINFO | ||||
|  FILEVERSION 1,1,4,147 | ||||
|  PRODUCTVERSION 1,1,4,147 | ||||
|  FILEVERSION 1,1,4,148 | ||||
|  PRODUCTVERSION 1,1,4,148 | ||||
|  FILEFLAGSMASK 0x3fL | ||||
| #ifdef _DEBUG | ||||
|  FILEFLAGS 0x1L | ||||
|  | @ -241,13 +241,13 @@ BEGIN | |||
|         BEGIN | ||||
|             VALUE "CompanyName", "akeo.ie" | ||||
|             VALUE "FileDescription", "Rufus" | ||||
|             VALUE "FileVersion", "1.1.4.147" | ||||
|             VALUE "FileVersion", "1.1.4.148" | ||||
|             VALUE "InternalName", "Rufus" | ||||
|             VALUE "LegalCopyright", "© 2011 Pete Batard (GPL v3)" | ||||
|             VALUE "LegalTrademarks", "http://www.gnu.org/copyleft/gpl.html" | ||||
|             VALUE "OriginalFilename", "rufus.exe" | ||||
|             VALUE "ProductName", "Rufus" | ||||
|             VALUE "ProductVersion", "1.1.4.147" | ||||
|             VALUE "ProductVersion", "1.1.4.148" | ||||
|         END | ||||
|     END | ||||
|     BLOCK "VarFileInfo" | ||||
|  |  | |||
							
								
								
									
										26
									
								
								src/stdlg.c
									
										
									
									
									
								
							
							
						
						
									
										26
									
								
								src/stdlg.c
									
										
									
									
									
								
							|  | @ -806,3 +806,29 @@ void DestroyAllTooltips(void) | |||
| 		safe_free(ttlist[i].wstring); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Compute the width of a device list entry */ | ||||
| LONG GetEntryWidth(HWND hDropDown, const char *entry) | ||||
| {  | ||||
| 	HDC hDC; | ||||
| 	HFONT hFont, hDefFont; | ||||
| 	SIZE size; | ||||
| 	WCHAR* wentry = NULL; | ||||
| 	int len; | ||||
| 
 | ||||
| 	hDC = GetDC(hDropDown); | ||||
| 	hFont = (HFONT)SendMessage(hDropDown, WM_GETFONT, 0, 0); | ||||
| 	if (hFont != NULL) | ||||
| 		hDefFont = (HFONT)SelectObject(hDC, hFont); | ||||
| 	 | ||||
| 	wentry = utf8_to_wchar(entry); | ||||
| 	len = (int)wcslen(wentry)+1; | ||||
| 	GetTextExtentPoint32W(hDC, wentry, len, &size); | ||||
| 
 | ||||
| 	if (hFont != NULL) | ||||
| 		SelectObject(hDC, hDefFont); | ||||
| 
 | ||||
| 	ReleaseDC(hDropDown, hDC); | ||||
| 	free(wentry); | ||||
| 	return size.cx; | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue