Beispiel #1
0
// From smartmontools os_win32.cpp
void GetWindowsVersion(void)
{
	OSVERSIONINFOEXA vi, vi2;
	const char* w = 0;
	const char* w64 = "32 bit";
	char* vptr;
	size_t vlen;
	unsigned major, minor;
	ULONGLONG major_equal, minor_equal;
	BOOL ws;

	nWindowsVersion = WINDOWS_UNDEFINED;
	safe_strcpy(WindowsVersionStr, sizeof(WindowsVersionStr), "Windows Undefined");

	memset(&vi, 0, sizeof(vi));
	vi.dwOSVersionInfoSize = sizeof(vi);
	if (!GetVersionExA((OSVERSIONINFOA *)&vi)) {
		memset(&vi, 0, sizeof(vi));
		vi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
		if (!GetVersionExA((OSVERSIONINFOA *)&vi))
			return;
	}

	if (vi.dwPlatformId == VER_PLATFORM_WIN32_NT) {

		if (vi.dwMajorVersion > 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion >= 2)) {
			// Starting with Windows 8.1 Preview, GetVersionEx() does no longer report the actual OS version
			// See: http://msdn.microsoft.com/en-us/library/windows/desktop/dn302074.aspx

			major_equal = VerSetConditionMask(0, VER_MAJORVERSION, VER_EQUAL);
			for (major = vi.dwMajorVersion; major <= 9; major++) {
				memset(&vi2, 0, sizeof(vi2));
				vi2.dwOSVersionInfoSize = sizeof(vi2); vi2.dwMajorVersion = major;
				if (!VerifyVersionInfoA(&vi2, VER_MAJORVERSION, major_equal))
					continue;
				if (vi.dwMajorVersion < major) {
					vi.dwMajorVersion = major; vi.dwMinorVersion = 0;
				}

				minor_equal = VerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL);
				for (minor = vi.dwMinorVersion; minor <= 9; minor++) {
					memset(&vi2, 0, sizeof(vi2)); vi2.dwOSVersionInfoSize = sizeof(vi2);
					vi2.dwMinorVersion = minor;
					if (!VerifyVersionInfoA(&vi2, VER_MINORVERSION, minor_equal))
						continue;
					vi.dwMinorVersion = minor;
					break;
				}

				break;
			}
		}

		if (vi.dwMajorVersion <= 0xf && vi.dwMinorVersion <= 0xf) {
			ws = (vi.wProductType <= VER_NT_WORKSTATION);
			nWindowsVersion = vi.dwMajorVersion << 4 | vi.dwMinorVersion;
			switch (nWindowsVersion) {
			case 0x50: w = "2000";
				break;
			case 0x51: w = "XP";
				break;
			case 0x52: w = (!GetSystemMetrics(89)?"2003":"2003_R2");
				break;
			case 0x60: w = (ws?"Vista":"2008");
				break;
			case 0x61: w = (ws?"7":"2008_R2");
				break;
			case 0x62: w = (ws?"8":"2012");
				break;
			case 0x63: w = (ws?"8.1":"2012_R2");
				break;
			case 0x64: w = (ws?"8.2":"2012_R3");
				break;
			default:
				if (nWindowsVersion < 0x50)
					nWindowsVersion = WINDOWS_UNSUPPORTED;
				else
					w = "9 or later";
				break;
			}
		}
	}

	if (is_x64())
		w64 = "64-bit";

	vptr = &WindowsVersionStr[sizeof("Windows ") - 1];
	vlen = sizeof(WindowsVersionStr) - sizeof("Windows ") - 1;
	if (!w)
		safe_sprintf(vptr, vlen, "%s %u.%u %s", (vi.dwPlatformId==VER_PLATFORM_WIN32_NT?"NT":"??"),
			(unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
	else if (vi.wServicePackMinor)
		safe_sprintf(vptr, vlen, "%s SP%u.%u %s", w, vi.wServicePackMajor, vi.wServicePackMinor, w64);
	else if (vi.wServicePackMajor)
		safe_sprintf(vptr, vlen, "%s SP%u %s", w, vi.wServicePackMajor, w64);
	else
		safe_sprintf(vptr, vlen, "%s %s", w, w64);
}
Beispiel #2
0
Datei: iso.c Projekt: hanji/rufus
// Returns 0 on success, nonzero on error
static int iso_extract_files(iso9660_t* p_iso, const char *psz_path)
{
	HANDLE file_handle = NULL;
	DWORD buf_size, wr_size;
	BOOL s, is_syslinux_cfg, is_old_vesamenu;
	int i_length, r = 1;
	char psz_fullpath[1024], *psz_basename;
	const char *psz_iso_name = &psz_fullpath[strlen(psz_extract_dir)];
	unsigned char buf[ISO_BLOCKSIZE];
	CdioListNode_t* p_entnode;
	iso9660_stat_t *p_statbuf;
	CdioList_t* p_entlist;
	size_t i, nul_pos;
	lsn_t lsn;
	int64_t i_file_length;

	if ((p_iso == NULL) || (psz_path == NULL))
		return 1;

	i_length = safe_sprintf(psz_fullpath, sizeof(psz_fullpath), "%s%s/", psz_extract_dir, psz_path);
	if (i_length < 0)
		return 1;
	psz_basename = &psz_fullpath[i_length];

	p_entlist = iso9660_ifs_readdir(p_iso, psz_path);
	if (!p_entlist) {
		uprintf("Could not access directory %s\n", psz_path);
		return 1;
	}

	_CDIO_LIST_FOREACH(p_entnode, p_entlist) {
		if (FormatStatus) goto out;
		p_statbuf = (iso9660_stat_t*) _cdio_list_node_data(p_entnode);
		/* Eliminate . and .. entries */
		if ( (strcmp(p_statbuf->filename, ".") == 0)
			|| (strcmp(p_statbuf->filename, "..") == 0) )
			continue;
		iso9660_name_translate_ext(p_statbuf->filename, psz_basename, i_joliet_level);
		if (p_statbuf->type == _STAT_DIR) {
			if (!scan_only) _mkdirU(psz_fullpath);
			if (iso_extract_files(p_iso, psz_iso_name))
				goto out;
		} else {
			i_file_length = p_statbuf->size;
			if (check_iso_props(psz_path, &is_syslinux_cfg, &is_old_vesamenu, i_file_length, psz_basename, psz_fullpath)) {
				continue;
			}
			// Replace slashes with backslashes and append the size to the path for UI display
			nul_pos = safe_strlen(psz_fullpath);
			for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '/') psz_fullpath[i] = '\\';
			safe_strcpy(&psz_fullpath[nul_pos], 24, size_to_hr(i_file_length));
			uprintf("Extracting: %s\n", psz_fullpath);
			SetWindowTextU(hISOFileName, psz_fullpath);
			// ISO9660 cannot handle backslashes
			for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '\\') psz_fullpath[i] = '/';
			psz_fullpath[nul_pos] = 0;
			if (is_old_vesamenu && use_own_vesamenu) {
				if (CopyFileA("vesamenu.c32", psz_fullpath, FALSE)) {
					uprintf("  Replaced with local version\n");
					continue;
				}
				uprintf("  Could not replace file: %s\n", WindowsErrorString());
			}
			file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if (file_handle == INVALID_HANDLE_VALUE) {
				uprintf("  Unable to create file: %s\n", WindowsErrorString());
				goto out;
			}
			for (i = 0; i_file_length > 0; i++) {
				if (FormatStatus) goto out;
				memset(buf, 0, ISO_BLOCKSIZE);
				lsn = p_statbuf->lsn + (lsn_t)i;
				if (iso9660_iso_seek_read(p_iso, buf, lsn, 1) != ISO_BLOCKSIZE) {
					uprintf("  Error reading ISO9660 file %s at LSN %lu\n",
						psz_iso_name, (long unsigned int)lsn);
					goto out;
				}
				buf_size = (DWORD)MIN(i_file_length, ISO_BLOCKSIZE);
				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());
					goto out;
				}
				i_file_length -= ISO_BLOCKSIZE;
				if (nb_blocks++ % PROGRESS_THRESHOLD == 0) {
					SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
					UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
				}
			}
			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, TRUE) != NULL)
					uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label);
			}
		}
	}
	r = 0;

out:
	ISO_BLOCKING(safe_closehandle(file_handle));
	_cdio_list_free(p_entlist, true);
	return r;
}
Beispiel #3
0
/*
 * Open a drive or volume with optional write and lock access
 * Returns INVALID_HANDLE_VALUE (/!\ which is DIFFERENT from NULL /!\) on failure.
 * This call is quite risky (left unchecked, inadvertently passing 0 as index would
 * return a handle to C:, which we might then proceed to unknowingly repartition!),
 * so we apply the following mitigation factors:
 * - Valid indexes must belong to a specific range [DRIVE_INDEX_MIN; DRIVE_INDEX_MAX]
 * - When opening for write access, we lock the volume. If that fails, which would
 *   typically be the case on C:\ or any other drive in use, we report failure
 * - We report the full path of any drive that was successfully opened for write acces
 */
HANDLE GetDriveHandle(DWORD DriveIndex, char* DriveLetter, BOOL bWriteAccess, BOOL bLockDrive)
{
	BOOL r;
	DWORD size;
	HANDLE hDrive = INVALID_HANDLE_VALUE;
	STORAGE_DEVICE_NUMBER_REDEF device_number = {0};
	UINT drive_type;
	char drives[26*4];	/* "D:\", "E:\", etc. */
	char *drive = drives;
	char logical_drive[] = "\\\\.\\#:";
	char physical_drive[24];

	if ((DriveIndex < DRIVE_INDEX_MIN) || (DriveIndex > DRIVE_INDEX_MAX)) {
		uprintf("WARNING: Bad index value. Please check the code!\n");
	}
	DriveIndex -= DRIVE_INDEX_MIN;

	// If no drive letter is requested, open a physical drive
	if (DriveLetter == NULL) {
		safe_sprintf(physical_drive, sizeof(physical_drive), "\\\\.\\PHYSICALDRIVE%d", DriveIndex);
		hDrive = CreateFileA(physical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
			FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
		if (hDrive == INVALID_HANDLE_VALUE) {
			uprintf("Could not open drive %s: %s\n", physical_drive, WindowsErrorString());
			goto out;
		}
		if (bWriteAccess) {
			uprintf("Caution: Opened %s drive for write access\n", physical_drive);
		}
	} else {
		*DriveLetter = ' ';
		size = GetLogicalDriveStringsA(sizeof(drives), drives);
		if (size == 0) {
			uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
			goto out;
		}
		if (size > sizeof(drives)) {
			uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
			goto out;
		}

		hDrive = INVALID_HANDLE_VALUE;
		for ( ;*drive; drive += safe_strlen(drive)+1) {
			if (!isalpha(*drive))
				continue;
			*drive = (char)toupper((int)*drive);
			if (*drive < 'C') {
				continue;
			}

			/* IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
			   not unique! An HDD, a DVD and probably other drives can have the same
			   value there => Use GetDriveType() to filter out unwanted devices.
			   See https://github.com/pbatard/rufus/issues/32 for details. */
			drive_type = GetDriveTypeA(drive);
			// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't allow by default
			// Using Alt-F in Rufus does enable listing, but this mode is unsupported.
			if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED)))
				continue;

			safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
			hDrive = CreateFileA(logical_drive, GENERIC_READ|(bWriteAccess?GENERIC_WRITE:0),
				FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
			if (hDrive == INVALID_HANDLE_VALUE) {
				uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
				continue;
			}

			r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
				0, &device_number, sizeof(device_number), &size, NULL);
			if ((!r) || (size <= 0)) {
				uprintf("IOCTL_STORAGE_GET_DEVICE_NUMBER failed for device %s: %s\n",
					logical_drive, WindowsErrorString());
			} else if (device_number.DeviceNumber == DriveIndex) {
				break;
			}
			safe_closehandle(hDrive);
		}
		if (hDrive == INVALID_HANDLE_VALUE) {
			goto out;
		}
		if (bWriteAccess) {
			uprintf("Caution: Opened %s drive for write access\n", logical_drive);
		}
		*DriveLetter = *drive?*drive:' ';
	}

	if ((bLockDrive) && (!DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &size, NULL))) {
		uprintf("Could not get exclusive access to %s %s\n", logical_drive, WindowsErrorString());
		safe_closehandle(hDrive);
		goto out;
	}

out:
	return hDrive;
}
Beispiel #4
0
/*
 * FormatMessage does not handle internet errors
 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa385465.aspx
 */
const char* WinInetErrorString(void)
{
	static char error_string[256];
	DWORD size = sizeof(error_string);

	error_code = HRESULT_CODE(GetLastError());

	if ((error_code < INTERNET_ERROR_BASE) || (error_code > INTERNET_ERROR_LAST))
		return WindowsErrorString();

	// TODO: These should be localized on an ad-hoc basis
	switch(error_code) {
	case ERROR_INTERNET_OUT_OF_HANDLES:
		return "No more handles could be generated at this time.";
	case ERROR_INTERNET_TIMEOUT:
		return "The request has timed out.";
	case ERROR_INTERNET_INTERNAL_ERROR:
		return "An internal error has occurred.";
	case ERROR_INTERNET_INVALID_URL:
		return "The URL is invalid.";
	case ERROR_INTERNET_UNRECOGNIZED_SCHEME:
		return "The URL scheme could not be recognized or is not supported.";
	case ERROR_INTERNET_NAME_NOT_RESOLVED:
		return "The server name could not be resolved.";
	case ERROR_INTERNET_PROTOCOL_NOT_FOUND:
		return "The requested protocol could not be located.";
	case ERROR_INTERNET_INVALID_OPTION:
		return "A request specified an invalid option value.";
	case ERROR_INTERNET_BAD_OPTION_LENGTH:
		return "The length of an option supplied is incorrect for the type of option specified.";
	case ERROR_INTERNET_OPTION_NOT_SETTABLE:
		return "The request option cannot be set, only queried.";
	case ERROR_INTERNET_SHUTDOWN:
		return "The Win32 Internet function support is being shut down or unloaded.";
	case ERROR_INTERNET_INCORRECT_USER_NAME:
		return "The request to connect and log on to an FTP server could not be completed because the supplied user name is incorrect.";
	case ERROR_INTERNET_INCORRECT_PASSWORD:
		return "The request to connect and log on to an FTP server could not be completed because the supplied password is incorrect.";
	case ERROR_INTERNET_LOGIN_FAILURE:
		return "The request to connect to and log on to an FTP server failed.";
	case ERROR_INTERNET_INVALID_OPERATION:
		return "The requested operation is invalid.";
	case ERROR_INTERNET_OPERATION_CANCELLED:
		return "The operation was cancelled, usually because the handle on which the request was operating was closed before the operation completed.";
	case ERROR_INTERNET_INCORRECT_HANDLE_TYPE:
		return "The type of handle supplied is incorrect for this operation.";
	case ERROR_INTERNET_INCORRECT_HANDLE_STATE:
		return "The requested operation cannot be carried out because the handle supplied is not in the correct state.";
	case ERROR_INTERNET_NOT_PROXY_REQUEST:
		return "The request cannot be made via a proxy.";
	case ERROR_INTERNET_REGISTRY_VALUE_NOT_FOUND:
		return "A required registry value could not be located.";
	case ERROR_INTERNET_BAD_REGISTRY_PARAMETER:
		return "A required registry value was located but is an incorrect type or has an invalid value.";
	case ERROR_INTERNET_NO_DIRECT_ACCESS:
		return "Direct network access cannot be made at this time.";
	case ERROR_INTERNET_NO_CONTEXT:
		return "An asynchronous request could not be made because a zero context value was supplied.";
	case ERROR_INTERNET_NO_CALLBACK:
		return "An asynchronous request could not be made because a callback function has not been set.";
	case ERROR_INTERNET_REQUEST_PENDING:
		return "The required operation could not be completed because one or more requests are pending.";
	case ERROR_INTERNET_INCORRECT_FORMAT:
		return "The format of the request is invalid.";
	case ERROR_INTERNET_ITEM_NOT_FOUND:
		return "The requested item could not be located.";
	case ERROR_INTERNET_CANNOT_CONNECT:
		return "The attempt to connect to the server failed.";
	case ERROR_INTERNET_CONNECTION_ABORTED:
		return "The connection with the server has been terminated.";
	case ERROR_INTERNET_CONNECTION_RESET:
		return "The connection with the server has been reset.";
	case ERROR_INTERNET_FORCE_RETRY:
		return "Calls for the Win32 Internet function to redo the request.";
	case ERROR_INTERNET_INVALID_PROXY_REQUEST:
		return "The request to the proxy was invalid.";
	case ERROR_INTERNET_HANDLE_EXISTS:
		return "The request failed because the handle already exists.";
	case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
		return "SSL certificate date that was received from the server is bad. The certificate is expired.";
	case ERROR_INTERNET_SEC_CERT_CN_INVALID:
		return "SSL certificate common name (host name field) is incorrect.";
	case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
		return "The application is moving from a non-SSL to an SSL connection because of a redirect.";
	case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
		return "The application is moving from an SSL to an non-SSL connection because of a redirect.";
	case ERROR_INTERNET_MIXED_SECURITY:
		return "Some of the content being viewed may have come from unsecured servers.";
	case ERROR_INTERNET_CHG_POST_IS_NON_SECURE:
		return "The application is posting and attempting to change multiple lines of text on a server that is not secure.";
	case ERROR_INTERNET_POST_IS_NON_SECURE:
		return "The application is posting data to a server that is not secure.";
	case ERROR_FTP_TRANSFER_IN_PROGRESS:
		return "The requested operation cannot be made on the FTP session handle because an operation is already in progress.";
	case ERROR_FTP_DROPPED:
		return "The FTP operation was not completed because the session was aborted.";
	case ERROR_GOPHER_PROTOCOL_ERROR:
	case ERROR_GOPHER_NOT_FILE:
	case ERROR_GOPHER_DATA_ERROR:
	case ERROR_GOPHER_END_OF_DATA:
	case ERROR_GOPHER_INVALID_LOCATOR:
	case ERROR_GOPHER_INCORRECT_LOCATOR_TYPE:
	case ERROR_GOPHER_NOT_GOPHER_PLUS:
	case ERROR_GOPHER_ATTRIBUTE_NOT_FOUND:
	case ERROR_GOPHER_UNKNOWN_LOCATOR:
		return "Gopher? Really??? What is this, 1994?";
	case ERROR_HTTP_HEADER_NOT_FOUND:
		return "The requested header could not be located.";
	case ERROR_HTTP_DOWNLEVEL_SERVER:
		return "The server did not return any headers.";
	case ERROR_HTTP_INVALID_SERVER_RESPONSE:
		return "The server response could not be parsed.";
	case ERROR_HTTP_INVALID_HEADER:
		return "The supplied header is invalid.";
	case ERROR_HTTP_INVALID_QUERY_REQUEST:
		return "The request made to HttpQueryInfo is invalid.";
	case ERROR_HTTP_HEADER_ALREADY_EXISTS:
		return "The header could not be added because it already exists.";
	case ERROR_HTTP_REDIRECT_FAILED:
		return "The redirection failed because either the scheme changed or all attempts made to redirect failed.";
	case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
		return "Client Authentication certificate needed";
	case ERROR_INTERNET_BAD_AUTO_PROXY_SCRIPT:
		return "Bad auto proxy script.";
	case ERROR_INTERNET_UNABLE_TO_DOWNLOAD_SCRIPT:
		return "Unable to download script.";
	case ERROR_INTERNET_NOT_INITIALIZED:
		return "Internet has not be initialized.";
	case ERROR_INTERNET_UNABLE_TO_CACHE_FILE:
		return "Unable to cache the file.";
	case ERROR_INTERNET_TCPIP_NOT_INSTALLED:
		return "TPC/IP not installed.";
	case ERROR_INTERNET_DISCONNECTED:
		return "Internet is disconnected.";
	case ERROR_INTERNET_SERVER_UNREACHABLE:
		return "Server could not be reached.";
	case ERROR_INTERNET_PROXY_SERVER_UNREACHABLE:
		return "Proxy server could not be reached.";
	case ERROR_INTERNET_FAILED_DUETOSECURITYCHECK:
		return "A security check prevented internet connection.";
	case ERROR_INTERNET_NEED_MSN_SSPI_PKG:
		return "This connection requires an MSN Security Support Provider Interface package.";
	case ERROR_INTERNET_LOGIN_FAILURE_DISPLAY_ENTITY_BODY:
		return "Please ask Microsoft about that one!";
	case ERROR_INTERNET_EXTENDED_ERROR:
		InternetGetLastResponseInfoA(&error_code, error_string, &size);
		return error_string;
	default:
		safe_sprintf(error_string, sizeof(error_string), "Unknown internet error 0x%08X", error_code);
		return error_string;
	}
}
Beispiel #5
0
BOOL ExtractISO(const char* src_iso, const char* dest_dir, BOOL scan)
{
	size_t i, size;
	int j;
	uint16_t sl_version;
	FILE* fd;
	int r = 1;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL;
	udf_dirent_t* p_udf_root;
	char *tmp, *buf, *ext;
	char path[MAX_PATH], path2[16];
	const char* basedir[] = { "i386", "minint" };
	const char* tmp_sif = ".\\txtsetup.sif~";
	iso_extension_mask_t iso_extension_mask = ISO_EXTENSION_ALL;
	char* spacing = "  ";

	if ((!enable_iso) || (src_iso == NULL) || (dest_dir == NULL))
		return FALSE;

	scan_only = scan;
	if (!scan_only)
		spacing = "";
	cdio_log_set_handler(log_handler);
	psz_extract_dir = dest_dir;
	// Change progress style to marquee for scanning
	if (scan_only) {
		uprintf("ISO analysis:");
		SendMessage(hMainDialog, UM_PROGRESS_INIT, PBS_MARQUEE, 0);
		total_blocks = 0;
		memset(&img_report, 0, sizeof(img_report));
		has_ldlinux_c32 = FALSE;
		// String array of all isolinux/syslinux locations
		StrArrayCreate(&config_path, 8);
		StrArrayCreate(&isolinux_path, 8);
		PrintInfo(0, MSG_202);
	} else {
		uprintf("Extracting files...\n");
		IGNORE_RETVAL(_chdirU(app_dir));
		PrintInfo(0, MSG_231);
		if (total_blocks == 0) {
			uprintf("Error: ISO has not been properly scanned.\n");
			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
			goto out;
		}
		nb_blocks = 0;
		iso_blocking_status = 0;
	}

	// First try to open as UDF - fallback to ISO if it failed
	p_udf = udf_open(src_iso);
	if (p_udf == NULL)
		goto try_iso;
	uprintf("%sImage is an UDF image", spacing);

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("%sCould not locate UDF root directory", spacing);
		goto out;
	}
	if (scan_only) {
		if (udf_get_logical_volume_id(p_udf, img_report.label, sizeof(img_report.label)) <= 0)
			img_report.label[0] = 0;
	}
	r = udf_extract_files(p_udf, p_udf_root, "");
	goto out;

try_iso:
	// Perform our first scan with Joliet disabled (if Rock Ridge is enabled), so that we can find if
	// there exists a Rock Ridge file with a name > 64 chars or if there are symlinks. If that is the
	// case then we also disable Joliet during the extract phase.
	if ((!enable_joliet) || (enable_rockridge && (scan_only || img_report.has_long_filename || img_report.has_symlinks))) {
		iso_extension_mask &= ~ISO_EXTENSION_JOLIET;
	}
	if (!enable_rockridge) {
		iso_extension_mask &= ~ISO_EXTENSION_ROCK_RIDGE;
	}

	p_iso = iso9660_open_ext(src_iso, iso_extension_mask);
	if (p_iso == NULL) {
		uprintf("%s'%s' doesn't look like an ISO image", spacing, src_iso);
		r = 1;
		goto out;
	}
	uprintf("%sImage is an ISO9660 image", spacing);
	i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
	if (scan_only) {
		if (iso9660_ifs_get_volume_id(p_iso, &tmp)) {
			safe_strcpy(img_report.label, sizeof(img_report.label), tmp);
			safe_free(tmp);
		} else
			img_report.label[0] = 0;
	} else {
		if (iso_extension_mask & (ISO_EXTENSION_JOLIET|ISO_EXTENSION_ROCK_RIDGE))
			uprintf("%sThis image will be extracted using %s extensions (if present)", spacing,
				(iso_extension_mask & ISO_EXTENSION_JOLIET)?"Joliet":"Rock Ridge");
		else
			uprintf("%sThis image will not be extracted using any ISO extensions", spacing);
	}
	r = iso_extract_files(p_iso, "");

out:
	iso_blocking_status = -1;
	if (scan_only) {
		// Remove trailing spaces from the label
		for (j=(int)safe_strlen(img_report.label)-1; ((j>=0)&&(isspaceU(img_report.label[j]))); j--)
			img_report.label[j] = 0;
		// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
		img_report.projected_size = total_blocks * ISO_BLOCKSIZE;
		// We will link the existing isolinux.cfg from a syslinux.cfg we create
		// If multiple config files exist, choose the one with the shortest path
		// (so that a '/syslinux.cfg' is preferred over a '/isolinux/isolinux.cfg')
		if (!IsStrArrayEmpty(config_path)) {
			// Set the img_report.cfg_path string to maximum length, so that we don't have to
			// do a special case for StrArray entry 0.
			memset(img_report.cfg_path, '_', sizeof(img_report.cfg_path)-1);
			img_report.cfg_path[sizeof(img_report.cfg_path)-1] = 0;
			for (i=0; i<config_path.Index; i++) {
				// OpenSuse based Live image have a /syslinux.cfg that doesn't work, so we enforce
				// the use of the one in '/boot/[i386|x86_64]/loader/isolinux.cfg' if present.
				// Note that, because the openSuse live script are not designed to handle anything but
				// an ISO9660 filesystem for the live device, this still won't allow for proper boot.
				// See https://github.com/openSUSE/kiwi/issues/354
				if ( (_stricmp(config_path.String[i], "/boot/i386/loader/isolinux.cfg") == 0) ||
					 (_stricmp(config_path.String[i], "/boot/x86_64/loader/isolinux.cfg") == 0)) {
					safe_strcpy(img_report.cfg_path, sizeof(img_report.cfg_path), config_path.String[i]);
					img_report.needs_syslinux_overwrite = TRUE;
					break;
				}
				// Tails uses an '/EFI/BOOT/isolinux.cfg' along with a '/isolinux/isolinux.cfg'
				// which are the exact same length. However, only the /isolinux one will work,
				// so for now, at equal length, always pick the latest.
				// We may have to revisit this and prefer a path that contains '/isolinux' if
				// this hack is not enough for other images.
				if (safe_strlen(img_report.cfg_path) >= safe_strlen(config_path.String[i]))
					safe_strcpy(img_report.cfg_path, sizeof(img_report.cfg_path), config_path.String[i]);
			}
			uprintf("  Will use '%s' for Syslinux", img_report.cfg_path);
			// Extract all of the isolinux.bin files we found to identify their versions
			for (i=0; i<isolinux_path.Index; i++) {
				size = (size_t)ExtractISOFile(src_iso, isolinux_path.String[i], dot_isolinux_bin, FILE_ATTRIBUTE_NORMAL);
				if (size == 0) {
					uprintf("  Could not access %s", isolinux_path.String[i]);
				} else {
					buf = (char*)calloc(size, 1);
					if (buf == NULL) break;
					fd = fopen(dot_isolinux_bin, "rb");
					if (fd == NULL) {
						free(buf);
						continue;
					}
					fread(buf, 1, size, fd);
					fclose(fd);
					sl_version = GetSyslinuxVersion(buf, size, &ext);
					if (img_report.sl_version == 0) {
						safe_strcpy(img_report.sl_version_ext, sizeof(img_report.sl_version_ext), ext);
						img_report.sl_version = sl_version;
						j = (int)i;
					} else if ((img_report.sl_version != sl_version) || (safe_strcmp(img_report.sl_version_ext, ext) != 0)) {
						uprintf("  Found conflicting %s versions:\n  '%s' (%d.%02d%s) vs '%s' (%d.%02d%s)", isolinux_bin,
							isolinux_path.String[j], SL_MAJOR(img_report.sl_version), SL_MINOR(img_report.sl_version),
							img_report.sl_version_ext, isolinux_path.String[i], SL_MAJOR(sl_version), SL_MINOR(sl_version), ext);
					}
					free(buf);
					_unlink(dot_isolinux_bin);
				}
			}
			if (img_report.sl_version != 0) {
				static_sprintf(img_report.sl_version_str, "%d.%02d",
					SL_MAJOR(img_report.sl_version), SL_MINOR(img_report.sl_version));
				uprintf("  Detected Syslinux version: %s%s (from '%s')",
					img_report.sl_version_str, img_report.sl_version_ext, isolinux_path.String[j]);
				if ( (has_ldlinux_c32 && (SL_MAJOR(img_report.sl_version) < 5))
				  || (!has_ldlinux_c32 && (SL_MAJOR(img_report.sl_version) >= 5)) )
					uprintf("  Warning: Conflict between Isolinux version and the presence of ldlinux.c32...");
			} else {
				// Couldn't find a version from isolinux.bin. Force set to the versions we embed
				img_report.sl_version = embedded_sl_version[has_ldlinux_c32?1:0];
				static_sprintf(img_report.sl_version_str, "%d.%02d",
					SL_MAJOR(img_report.sl_version), SL_MINOR(img_report.sl_version));
				uprintf("  Warning: Could not detect Isolinux version - Forcing to %s (embedded)",
					img_report.sl_version_str);
			}
		}
		if (IS_WINPE(img_report.winpe)) {
			// In case we have a WinPE 1.x based iso, we extract and parse txtsetup.sif
			// during scan, to see if /minint was provided for OsLoadOptions, as it decides
			// whether we should use 0x80 or 0x81 as the disk ID in the MBR
			safe_sprintf(path, sizeof(path), "/%s/txtsetup.sif",
				basedir[((img_report.winpe&WINPE_I386) == WINPE_I386)?0:1]);
			ExtractISOFile(src_iso, path, tmp_sif, FILE_ATTRIBUTE_NORMAL);
			tmp = get_token_data_file("OsLoadOptions", tmp_sif);
			if (tmp != NULL) {
				for (i=0; i<strlen(tmp); i++)
					tmp[i] = (char)tolower(tmp[i]);
				uprintf("  Checking txtsetup.sif:\n  OsLoadOptions = %s", tmp);
				img_report.uses_minint = (strstr(tmp, "/minint") != NULL);
			}
			_unlink(tmp_sif);
			safe_free(tmp);
		}
		if (HAS_INSTALL_WIM(img_report)) {
			img_report.install_wim_version = GetInstallWimVersion(src_iso);
		}
		if (img_report.has_grub2) {
			// In case we have a GRUB2 based iso, we extract boot/grub/i386-pc/normal.mod to parse its version
			img_report.grub2_version[0] = 0;
			if ((GetTempPathU(sizeof(path), path) != 0) && (GetTempFileNameU(path, APPLICATION_NAME, 0, path) != 0)) {
				size = (size_t)ExtractISOFile(src_iso, "boot/grub/i386-pc/normal.mod", path, FILE_ATTRIBUTE_NORMAL);
				buf = (char*)calloc(size, 1);
				fd = fopen(path, "rb");
				if ((size == 0) || (buf == NULL) || (fd == NULL)) {
					uprintf("  Could not read Grub version from 'boot/grub/i386-pc/normal.mod'");
				} else {
					fread(buf, 1, size, fd);
					fclose(fd);
					GetGrubVersion(buf, size);
				}
				free(buf);
				_unlink(path);
			}
			if (img_report.grub2_version[0] != 0)
				uprintf("  Detected Grub version: %s", img_report.grub2_version);
			else {
				uprintf("  Could not detect Grub version");
				img_report.has_grub2 = FALSE;
			}
		}
		StrArrayDestroy(&config_path);
		StrArrayDestroy(&isolinux_path);
		SendMessage(hMainDialog, UM_PROGRESS_EXIT, 0, 0);
	} else if (HAS_SYSLINUX(img_report)) {
		safe_sprintf(path, sizeof(path), "%s\\syslinux.cfg", dest_dir);
		// Create a /syslinux.cfg (if none exists) that points to the existing isolinux cfg
		fd = fopen(path, "r");
		if (fd != NULL && img_report.needs_syslinux_overwrite) {
			fclose(fd);
			fd = NULL;
			safe_sprintf(path2, sizeof(path2), "%s\\syslinux.org", dest_dir);
			uprintf("Renaming: %s ⇨ %s", path, path2);
			IGNORE_RETVAL(rename(path, path2));
		}
		if (fd == NULL) {
			fd = fopen(path, "w");	// No "/syslinux.cfg" => create a new one
			if (fd == NULL) {
				uprintf("Unable to create %s - booting from USB will not work", path);
				r = 1;
			} else {
				fprintf(fd, "DEFAULT loadconfig\n\nLABEL loadconfig\n  CONFIG %s\n", img_report.cfg_path);
				for (i=safe_strlen(img_report.cfg_path); (i>0)&&(img_report.cfg_path[i]!='/'); i--);
				if (i>0) {
					img_report.cfg_path[i] = 0;
					fprintf(fd, "  APPEND %s/\n", img_report.cfg_path);
					img_report.cfg_path[i] = '/';
				}
				uprintf("Created: %s", path);
			}
		}
		if (fd != NULL)
			fclose(fd);
	}
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	if ((r != 0) && (FormatStatus == 0))
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
	return (r == 0);
}
Beispiel #6
0
BOOL CALLBACK dialog_proc_2(HWND dialog, UINT message,
							WPARAM wParam, LPARAM lParam)
{
	static device_context_t *device = NULL;
	static HWND hToolTip;
	char tmp[MAX_TEXT_LENGTH];
	int val;

	switch (message)
	{

	case WM_INITDIALOG:
		SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
		SendMessage(dialog,WM_SETICON,ICON_BIG,   (LPARAM)mIcon);

		device = (device_context_t *)lParam;

		if (device)
		{
			wdi_is_driver_supported(WDI_LIBUSB0, &device->driver_info);

			//g_hwndTrackingTT = CreateTrackingToolTip(dialog,TEXT(" "));
			hToolTip = create_tooltip(dialog, g_hInst, 300, tooltips_dlg2);

			memset(tmp, 0, sizeof(tmp));
			safe_sprintf(tmp,sizeof(tmp) - 1, "0x%04X", device->wdi->vid);
			SetWindowText(GetDlgItem(dialog, ID_TEXT_VID), tmp);

			memset(tmp, 0, sizeof(tmp));
			safe_sprintf(tmp,sizeof(tmp) - 1, "0x%04X", device->wdi->pid);
			SetWindowText(GetDlgItem(dialog, ID_TEXT_PID), tmp);


			memset(tmp, 0, sizeof(tmp));
			if (device->wdi->is_composite)
				safe_sprintf(tmp,sizeof(tmp) - 1, "0x%02X", device->wdi->mi);
			SetWindowText(GetDlgItem(dialog, ID_TEXT_MI), tmp);

			SetWindowTextU(GetDlgItem(dialog, ID_TEXT_MANUFACTURER),
				device->manufacturer);

			SetWindowTextU(GetDlgItem(dialog, ID_TEXT_DEV_NAME),
				device->description);
		}
		return TRUE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID_BUTTON_NEXT:
			//memset(device, 0, sizeof(*device));
			device->wdi->is_composite=false;

			GetWindowTextU(GetDlgItem(dialog, ID_TEXT_MANUFACTURER),
				device->manufacturer, sizeof(tmp));

			GetWindowTextU(GetDlgItem(dialog, ID_TEXT_DEV_NAME),
				device->description, sizeof(tmp));

			GetWindowText(GetDlgItem(dialog, ID_TEXT_VID), tmp, sizeof(tmp));
			if(sscanf(tmp, "0x%04x", &val) == 1)
				device->wdi->vid = (WORD)val;

			GetWindowText(GetDlgItem(dialog, ID_TEXT_PID), tmp, sizeof(tmp));
			if(sscanf(tmp, "0x%04x", &val) == 1)
				device->wdi->pid = (WORD)val;

			GetWindowText(GetDlgItem(dialog, ID_TEXT_MI), tmp, sizeof(tmp));

			if (sscanf(tmp, "0x%02x", &val) == 1)
			{
				device->wdi->mi = (BYTE)val;
				device->wdi->is_composite=true;
			}
			if (save_file(dialog, device))
				EndDialog(dialog, ID_DIALOG_3);
			return TRUE ;
		case ID_BUTTON_BACK:
			EndDialog(dialog, ID_DIALOG_1);
			return TRUE ;
		case ID_BUTTON_CANCEL:
		case IDCANCEL:
			EndDialog(dialog, 0);
			return TRUE ;
		}
	}

	return FALSE;
}
int es_interface(int s, const void *data, size_t size) {
	int idx = 0 , retval = 0;

	char input_buf[RECV_BUF_SIZE+1];

	// Copy the data into 'input_buf'
	memset( input_buf , 0 , RECV_BUF_SIZE+1 );
	strncpy( input_buf , data , size );

	char *commands[NTELNETCOMMANDS] = { "esinit" , "esread" , "esdone" , "esdisable" , "mwr" , "mrd" , "debug" , \
			"dbgeyescan" , "initclk" , "readclk" , "printupod" , "iicr" , "iicw" , "printtemp" , "globalinit"
	};

	if( !strncmp( input_buf , "h" , 1 ) || !strncmp( input_buf , "H" , 1 ) ) {
		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		safe_sprintf( input_buf , "commands :" );
		for( idx = 0 ; idx < NTELNETCOMMANDS ; idx++ ) {
			safe_sprintf( input_buf , "%s %s" , input_buf , commands[idx] );
		}
		safe_sprintf( input_buf , "%s\r\n" , input_buf );
		return safe_send(s, input_buf);
	}

	char * temp_str , ** pEnd = NULL;
	typedef enum { ESINIT = 0 , ESREAD = 1 , ESDONE = 2 , ESDISABLE = 3 , MWR = 4 , MRD = 5 , DEBUG = 6 , \
		DBGEYESCAN = 7 , INITCLK = 8 , READCLK = 9 , PRINTUPOD = 10 , IICR = 11 , IICW = 12 , PRINTTEMP = 13 , GLOBALINIT = 14
	} command_type_t;
	command_type_t command_type = MWR;

	char tokens[NTELNETTOKENS][20] = {};
	for( idx = 0 ; idx < NTELNETTOKENS ; idx++ ) {
		memset( tokens[idx] , 0 , 20 );
	}

	// tokenize (strtok) the input and store in tokens[]
	temp_str = strtok( input_buf , " " );
	int number_tokens = 0;
	while( temp_str != NULL ) {
		strncpy( tokens[number_tokens] , temp_str , strlen( temp_str ) );
		++number_tokens;
		temp_str = strtok( NULL , " {},\r\n");
	}

	// identify the command
	for( idx = 0 ; idx < NTELNETCOMMANDS ; ++idx ) {
		if( !strncmp( commands[idx] , tokens[0] , strlen(commands[idx]) ) )
			command_type = idx;
	}

	if( command_type == ESINIT ) {
		if( number_tokens == 2 ) {
			if( !strncmp( "run" , tokens[1] , 3 ) ) {
				global_run_eye_scan();
				return safe_send( s , "1\r\n" );
			}
		}
		if( number_tokens != 8 ) {
			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			safe_sprintf( input_buf , "Syntax: esinit <lane> <max_prescale> <horz_step> <data_width> <vert_step> <lpm_mode> <rate>\r\n");
			return safe_send( s , input_buf );
		}

		int curr_lane = strtoul( tokens[1] , pEnd , 0);
		xaxi_eyescan_enable_channel(curr_lane);
		eyescan_lock();
		eye_scan * curr_eyescan = get_eye_scan_lane( curr_lane );
		if( curr_eyescan == NULL ) {
			return safe_send( s , "error, no lane found\r\n" );
		}
		curr_eyescan->pixel_count = 0;
		curr_eyescan->state = WAIT_STATE;
		curr_eyescan->p_upload_rdy = 0;

		// Read values in
		curr_eyescan->max_prescale = strtoul( tokens[2] , pEnd , 0);
		curr_eyescan->horz_step_size = strtoul( tokens[3] , pEnd , 0);
		curr_eyescan->data_width = strtoul( tokens[4] , pEnd , 0);
		curr_eyescan->vert_step_size = strtoul( tokens[5] , pEnd , 0);
		curr_eyescan->lpm_mode = strtoul( tokens[6] , pEnd , 0);
		curr_eyescan->max_horz_offset = strtoul( tokens[7] , pEnd , 0); // same as rate?

		//retval = configure_eye_scan( curr_eyescan , curr_lane );

		curr_eyescan->enable = TRUE; // enable the lane
		curr_eyescan->initialized = FALSE; // need to reinitialize lane

		eyescan_unlock();
		return 0;
	}

	if( command_type == ESREAD ) {
		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		if( number_tokens != 3 && number_tokens != 2 ) {
			safe_sprintf( input_buf , "Syntax: esread <lane> <pixel>\r\n");
			return safe_send( s , input_buf );
		}
		if( !strncmp( "all" , tokens[1] , 3 ) ) {
			if( !global_upload_ready() )
				return 0;
			int curr_lane = 0;
			for( curr_lane = 0 ; curr_lane < MAX_NUMBER_OF_LANES ; curr_lane++ ) {
				eye_scan * curr_eyescan = get_eye_scan_lane( curr_lane );
				if( curr_eyescan == NULL || curr_eyescan->enable == FALSE || curr_eyescan->p_upload_rdy == FALSE )
					continue;
				for( idx = 0 ; idx < curr_eyescan->pixel_count ; idx++ ) {
					eye_scan_pixel * current_pixel = ( curr_eyescan->pixels + idx );
					safe_sprintf( input_buf , "%s%d %d %d %d: %d %d %d %d %ld\r\n" , input_buf, curr_lane , idx , \
							current_pixel->h_offset , current_pixel->v_offset , \
							current_pixel->error_count , current_pixel->sample_count , \
							current_pixel->prescale & 0x001F , current_pixel->ut_sign , current_pixel->center_error );
					if( strlen(input_buf) > 1900 ) {
						retval = safe_send(s, input_buf);
						memset( input_buf , 0 , RECV_BUF_SIZE+1 );
					}
				}
			}
			if( strlen(input_buf) > 0 ) {
				retval = safe_send(s, input_buf);
			}
			return retval;
		}
		int curr_lane = strtoul( tokens[1] , pEnd , 0 );
		eye_scan * curr_eyescan = get_eye_scan_lane( curr_lane );
		if( curr_eyescan == NULL ) {
			return safe_send( s , "error, no lane found\r\n" );
		}
		if( number_tokens == 2 ) {
			safe_sprintf( input_buf , "%d\r\n" , curr_eyescan->pixel_count );
			retval = safe_send(s, input_buf);
			return retval;
		}
		else {
			int curr_pixel = strtoul( tokens[2] , pEnd , 0 );

			int begin_pixel = curr_pixel;
			int end_pixel = curr_pixel + 1;

			if( curr_pixel == curr_eyescan->pixel_count ) {
				begin_pixel = 0;
				end_pixel = curr_eyescan->pixel_count;
			}
			else if( curr_pixel > curr_eyescan->pixel_count ) {
				return 0;
			}

			for( idx = begin_pixel ; idx <= end_pixel ; idx++ ) {
				eye_scan_pixel * current_pixel = ( curr_eyescan->pixels + idx );
				safe_sprintf( input_buf , "%s%d %d %d %d: %d %d %d %d %ld\r\n" , input_buf, curr_lane , idx , \
						current_pixel->h_offset , current_pixel->v_offset , \
						current_pixel->error_count , current_pixel->sample_count , \
						current_pixel->prescale & 0x001F , current_pixel->ut_sign , current_pixel->center_error );
				if( strlen(input_buf) > 1900 ) {
					retval = safe_send(s, input_buf);
					memset( input_buf , 0 , RECV_BUF_SIZE+1 );
				}
			}
			if( strlen(input_buf) > 0 ) {
				retval = safe_send(s, input_buf);
			}
			return retval;
		}
	}

	if( command_type == ESDONE ) {
		if( number_tokens != 2 ) {
			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			safe_sprintf( input_buf , "Syntax: esdone <lane> \r\n");
			return safe_send( s , input_buf );
		}
		if( !strncmp( "all" , tokens[1] , 3 ) ) {
			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			safe_sprintf( input_buf , "%d\r\n" , global_upload_ready() );
			return safe_send(s, input_buf);
		}
		int curr_lane = strtoul( tokens[1] , pEnd , 0);
		int is_ready = FALSE;
		eye_scan * curr_eyescan = get_eye_scan_lane( curr_lane );
		if( curr_eyescan == NULL ) {
			return safe_send( s , "error, no lane found\r\n" );
		}
		is_ready = curr_eyescan->p_upload_rdy;

		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		safe_sprintf( input_buf , "%d: %d\r\n" , curr_lane , is_ready );
		return safe_send(s, input_buf);
	}

	if( command_type == ESDISABLE ) {
		if( number_tokens != 2 ) {
			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			safe_sprintf( input_buf , "Syntax: esdisable <lane> \r\n");
			return safe_send( s , input_buf );
		}
		if( !strncmp( "all" , tokens[1] , 3 ) ) {
			global_stop_eye_scan();
			global_upload_unrdy();
			return 0;
		}

		// Disable the eyescan
		int curr_lane = strtoul( tokens[1] , pEnd , 0);
		eye_scan * curr_eyescan = get_eye_scan_lane( curr_lane );
		curr_eyescan->enable = FALSE;

		// Turn off the GTX for this channel
		xaxi_eyescan_disable_channel(curr_lane);

		return 0;
	}

	typedef enum { N=-1 , W = 0 , H = 1 , B = 2 } wtype_t;
	wtype_t wtype = N;
	char *wtypes[3] = { "w" , "h" , "b" };
	uint wtype_sizes[3] = { 8 , 4 , 2 };
	if( command_type == MWR || command_type == MRD ) {
		for( idx = 0 ; idx < 3 ; idx++ ){
			if( !strncmp( wtypes[idx] , tokens[number_tokens-1] , 1 ) )
				wtype = idx;
		}
	}

	u16_t number_of_words = 1;
	if( command_type == MRD ) {
		if( number_tokens == 2 )
			number_of_words = 0;
		else if( number_tokens > 2 ) {
			if( wtype == N ) {
				number_of_words = strtoul( tokens[number_tokens-1] , pEnd , 0 );
			}
			else {
				number_of_words = strtoul( tokens[number_tokens-2] , pEnd , 0 );
			}
		}
	}
	else if( command_type == MWR ) {
		if( number_tokens == 3 )
			number_of_words = 1;
		else if( number_tokens > 3 ) {
			if( wtype == N ) {
				number_of_words = strtoul( tokens[number_tokens-1] , pEnd , 0 );
			}
			else {
				number_of_words = strtoul( tokens[number_tokens-2] , pEnd , 0 );
			}
		}
	}

	if( command_type == MRD && number_tokens == 2 )
		number_of_words = 1;

	u32_t address = 0;
	u32_t addresses[NTELNETTOKENS] = {0};
	u32_t values[NTELNETTOKENS] = {0};

	if( command_type == MWR || command_type == MRD ) {
		if( number_tokens > 1 ) {
			address = strtoul( tokens[1] , pEnd , 0 );
		}
	}

	if( command_type == MWR ) {
		for( idx = 0 ; idx < number_of_words ; idx++ ) {
			values[idx] = strtoul( tokens[idx+2] , pEnd , 0 );
			if( wtype == N || wtype == W ) { /* WORD, u32_t */
				u32_t * tval = NULL;
			tval = ( (u32_t*)address + idx );
			*tval = (u32_t)values[idx];
			}
			else if( wtype == H ) { /* HALF, u16_t */
				u16_t * tval = NULL;
			tval = ( (u16_t*)address + idx );
			*tval = (u16_t)values[idx];
			}
			else if( wtype == B ) { /* BYTE, u8_t */
				u8_t * tval = NULL;
				tval = ( (u8_t*)address + idx );
				*tval = (u8_t)values[idx];
			}
		}
	}

	if( command_type == MRD ) {
		for( idx = 0 ; idx < number_of_words ; idx++ ) {
			if( wtype == N || wtype == W ) { /* WORD, u32_t */
				u32_t * tval = NULL;
				tval = ( (u32_t*)address + idx );
				addresses[idx] = (u32_t)tval;
				values[idx] = *tval;
			}
			else if( wtype == H ) { /* HALF, u16_t */
				u16_t * tval = NULL;
				tval = ( (u16_t*)address + idx );
				addresses[idx] = (u32_t)tval;
				values[idx] = *tval;
			}
			else if( wtype == B ) { /* BYTE, u8_t */
				u8_t * tval = NULL;
				tval = ( (u8_t*)address + idx );
				addresses[idx] = (u32_t)tval;
				values[idx] = *tval;
			}
		}
		return retval;
	}

	if( command_type == MRD ) {
		char format_string[20];
		memset( format_string , 0 , 20 );
		if( wtype >= 0 )
			sprintf( format_string , "%%p: 0x%%0%dlx\r\n" , wtype_sizes[wtype] );
		else
			sprintf( format_string , "%%p: 0x%%0%dlx\r\n" , wtype_sizes[0] );
		for( idx = 0 ; idx < number_of_words ; idx++ ) {
			memset( input_buf , 0 , RECV_BUF_SIZE+1);
			safe_sprintf( input_buf , format_string , addresses[idx] , values[idx] );
			retval = safe_send(s, input_buf);
		}
		return retval;
	}

	if( command_type == DEBUG ) {
		srand( time(NULL) );

		safe_sprintf( input_buf , "echo mrd %p 4 b | nc 192.168.1.99 7\r\n" , u8_test_array );
		retval = safe_send(s, input_buf);


		safe_sprintf( input_buf , "echo mwr %p {0x%02x 0x%02x 0x%02x 0x%02x} 4 b | nc 192.168.1.99 7\r\n" ,
				u8_test_array , (u8_t)rand() , (u8_t)rand() , (u8_t)rand() , (u8_t)rand() );
		retval = safe_send(s, input_buf);


		safe_sprintf( input_buf , "echo mrd %p 4 b | nc 192.168.1.99 7\r\n" , u8_test_array );
		retval = safe_send(s, input_buf);


		safe_sprintf( input_buf , "echo mrd %p 4 h | nc 192.168.1.99 7\r\n" , u16_test_array );
		retval = safe_send(s, input_buf);


		safe_sprintf( input_buf , "echo mwr %p {0x%04x 0x%04x 0x%04x 0x%04x} 4 h | nc 192.168.1.99 7\r\n" ,
				u16_test_array , (u16_t)rand() , (u16_t)rand() , (u16_t)rand() , (u16_t)rand() );
		retval = safe_send(s, input_buf);


		safe_sprintf( input_buf , "echo mrd %p 4 h | nc 192.168.1.99 7\r\n" , u16_test_array );
		retval = safe_send(s, input_buf);

		safe_sprintf( input_buf , "echo mrd %p 4 w | nc 192.168.1.99 7\r\n" , u32_test_array );
		retval = safe_send(s, input_buf);

		safe_sprintf( input_buf , "echo mwr %p {0x%08lx 0x%08lx 0x%08lx 0x%08lx} 4 w | nc 192.168.1.99 7\r\n" ,
				u32_test_array , (u32_t)rand() , (u32_t)rand() , (u32_t)rand() , (u32_t)rand() );
		retval = safe_send(s, input_buf);

		safe_sprintf( input_buf , "echo mrd %p 4 w | nc 192.168.1.99 7\r\n" , u32_test_array );
		retval = safe_send(s, input_buf);

		return retval;
	}

	if( command_type == DBGEYESCAN ) {
		int curr_lane = -1;

		memset( input_buf , 0 , RECV_BUF_SIZE+1 );

		if( number_tokens == 2 ) {
			curr_lane = strtoul( tokens[1] , pEnd , 0 );
		}

		eyescan_debugging( curr_lane , input_buf );
		if( curr_lane == -1 ) {
			retval = safe_send( s , input_buf );
			return retval;
		}

		u32 drp_addresses[146] = { \
				0x000, 0x00D, 0x00E, 0x00F, 0x011, 0x012, 0x013, 0x014, 0x015, 0x016, 0x018, 0x019, 0x01A, 0x01B, 0x01C, 0x01D, 0x01E, 0x01F, 0x020, \
				0x021, 0x022, 0x023, 0x024, 0x025, 0x026, 0x027, 0x028, 0x029, 0x02A, 0x02B, 0x02C, 0x02D, 0x02E, 0x02F, 0x030, 0x031, 0x032, 0x033, \
				0x034, 0x035, 0x036, 0x037, 0x038, 0x039, 0x03A, 0x03B, 0x03C, 0x03D, 0x03E, 0x03F, 0x040, 0x041, 0x044, 0x045, 0x046, 0x047, 0x048, \
				0x049, 0x04A, 0x04B, 0x04C, 0x04D, 0x04E, 0x04F, 0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x059, 0x05B, 0x05C, 0x05D, \
				0x05E, 0x05F, 0x060, 0x061, 0x062, 0x063, 0x064, 0x065, 0x066, 0x068, 0x069, 0x06A, 0x06B, 0x06F, 0x070, 0x071, 0x074, 0x075, 0x076, \
				0x077, 0x078, 0x079, 0x07A, 0x07C, 0x07D, 0x07F, 0x082, 0x083, 0x086, 0x087, 0x088, 0x08C, 0x091, 0x092, 0x097, 0x098, 0x099, 0x09A, \
				0x09B, 0x09C, 0x09D, 0x09F, 0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9, 0x0AA, 0x0AB, 0x0AC ,\
				0x14F, 0x150, 0x151, 0x152, 0x153, 0x154, 0x155, 0x156, 0x157, 0x158, 0x159, 0x15A, 0x15B , 0x15C, 0x15D \
		};

		for( idx = 0 ; idx < 146 ; idx++ ) {
			eyescan_debug_addr( curr_lane , drp_addresses[idx] , input_buf );
			if( strlen(input_buf) > 1900 ) {
				retval = safe_send( s , input_buf );
				memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			}
		}
		if( strlen(input_buf) > 0 ) {
			retval = safe_send( s , input_buf );
			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		}

		return retval;
	}

	if( command_type == INITCLK ) {
#ifdef IS_OTC_BOARD
		SetClockDevID(0);
		retval = 0;
		if( number_tokens == 1 ) {
			retval = InitClockRegisters();
			return retval;
		}
		else if( number_tokens == 2 ) {
			char * freqs[4] = { "125.000 MHz" , "148.778 MHz" , "200.395 MHz" , "299.000 MHz" };
			u16 regvals[4][21] = {
					{ 0x01b9,  0x24c4,  0x74fa,  0x04fa,  0x306f,  0x0023,  0x0003,  0x0023,  0x0003,  0x00c3,  0x0030,  0x0000,  0x00c3,  0x0030,  0x0000,  0x00c3,  0x0030,  0x0000,  0x00c3,  0x0030,  0x0000 } ,
					{ 0x01b9,  0x11e9,  0x5c3c,  0x04f0,  0x306f,  0x0023,  0x0004,  0x0023,  0x0004,  0x00c3,  0x0040,  0x0000,  0x00c3,  0x0040,  0x0000,  0x00c3,  0x0040,  0x0000,  0x00c3,  0x0040,  0x0000 } ,
					{ 0x01b9,  0x000c,  0x003b,  0x04f5,  0x306f,  0x0023,  0x0002,  0x0023,  0x0002,  0x00c3,  0x0020,  0x0000,  0x00c3,  0x0020,  0x0000,  0x00c3,  0x0020,  0x0000,  0x00c3,  0x0020,  0x0000 } ,
					{ 0x01b1,  0x21f5,  0xc846,  0x04f5,  0x306f,  0x0023,  0x0001,  0x0023,  0x0001,  0x00c3,  0x0010,  0x0000,  0x00c3,  0x0010,  0x0000,  0x00c3,  0x0010,  0x0000,  0x00c3,  0x0010,  0x0000 }
			};
			int fidx = strtoul( tokens[1] , pEnd , 0);
			if( fidx >= 0 && fidx < 4 ) {
				u16 regval[21];
				for( idx = 0 ; idx<21 ; idx++ ) {
					regval[idx] = regvals[fidx][idx];
				}
				memset( input_buf , 0 , RECV_BUF_SIZE+1 );
				safe_sprintf( input_buf , "Using clock frequency of %s\n" , freqs[fidx] );
				retval = safe_send( s , input_buf );
				retval = InitClockRegisters( regval );
				return retval;
			}
			else {
				safe_printf( "Can't init clock\n");
				return 0;
			}
		}
		else if( number_tokens == 22 ) {
			u16 regval[21];
			for( idx = 1 ; idx<22 ; idx++ ) {
				regval[idx-1] = strtoul( tokens[idx] , pEnd , 0);
			}
			retval = InitClockRegisters( regval );
			return retval;
		}
		else {
			safe_printf( "Can't init clock\n");
			return 0;
		}
#endif
return retval;
	}

	if( command_type == READCLK ) {
#ifdef IS_OTC_BOARD
		u16 *cfgdata = GetClockConfig();

		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		for( idx = 0 ; idx < 21 ; idx++ ) {
			safe_sprintf( input_buf , "%s  %04d " , input_buf , idx );
		}
		safe_sprintf( input_buf , "%s\r\n" , input_buf );
		retval = safe_send(s, input_buf);
		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		for( idx = 0 ; idx < 21 ; idx++ ) {
			safe_sprintf( input_buf , "%s0x%04x " , input_buf , cfgdata[idx] );
		}
		safe_sprintf( input_buf , "%s\r\n" , input_buf );
		retval = safe_send(s, input_buf);
		free(cfgdata);
#endif
		return retval;
	}

	if( command_type == PRINTUPOD ) {
#ifdef IS_OTC_BOARD
		u8_t i2c_addresses[8];
		for( idx=0 ; idx<8; idx++ )
			i2c_addresses[idx] = idx;
		for( idx=1 ; idx < number_tokens ; idx++ )
			i2c_addresses[idx-1] = strtoul( tokens[idx] , pEnd , 0 );
		for( idx=0;idx<8;idx++ ) {
			if( number_tokens > 1 && idx>=(number_tokens-1) )
				continue;
			u8_t i2c_addr = i2c_addresses[idx];
			if( i2c_addr < 8 ) {
				i2c_addr = upod_address(i2c_addr);
			}
			SetUPodI2CAddress( i2c_addr );
			uPodMonitorData *mondata = GetUPodStatus();

			memset( input_buf , 0 , RECV_BUF_SIZE+1 );
			char * temp_format_string = "Addr %p , status 0x%02x , temp %d.%03dC , 3.3V %duV , 2.5V %duV\n";
			safe_sprintf( input_buf , temp_format_string , i2c_addr , mondata->status, \
					mondata->tempWhole, mondata->tempFrac, \
					100*mondata->v33, 100*mondata->v25);
			free(mondata);
			retval = safe_send(s, input_buf);
		}
#endif
		return retval;
	}

	if( command_type == IICR ) {
#ifdef IS_OTC_BOARD
		int devid = 0;
		u8_t i2c_addr;
		u8_t regaddr;
		u8_t * data;
		u16_t nbytes = 1;

		devid = strtoul( tokens[1] , pEnd , 0 );
		i2c_addr = strtoul( tokens[2] , pEnd , 0 );
		regaddr = strtoul( tokens[3] , pEnd , 0 );

		if( number_tokens == 5 )
			nbytes = strtoul( tokens[4] , pEnd , 0 );

		data = malloc( sizeof(u8_t) * nbytes );

		/* Set the register address */
		retval = IICMasterWrite(devid,i2c_addr,1,&regaddr);
		if( retval != XST_SUCCESS ) return retval;

		/* and do the read */
		retval = IICMasterRead(devid,i2c_addr,nbytes,data);

		memset( input_buf , 0 , RECV_BUF_SIZE+1 );
		for( idx = 0 ; idx < nbytes ; idx++ ) {
			safe_sprintf( input_buf , "%s 0x%02x" , input_buf , data[idx] );
		}
		safe_sprintf( input_buf , "%s\r\n" , input_buf );
		retval = safe_send(s, input_buf);
		free(data);
#endif
		return retval;
	}

	if( command_type == IICW ) {
#ifdef IS_OTC_BOARD
		int devid = 0;
		u8_t i2c_addr;
		u8_t regaddr;
		u8_t * buffer;
		u16_t nbytes = ( number_tokens - 4 );

		devid = strtoul( tokens[1] , pEnd , 0 );
		i2c_addr = strtoul( tokens[2] , pEnd , 0 );
		regaddr = strtoul( tokens[3] , pEnd , 0 );

		buffer = malloc( sizeof(u8_t) * ( nbytes + 1 ) );

		buffer[0] = regaddr;
		for( idx = 4 ; idx < number_tokens ; idx++ ) {
			buffer[idx-3] = strtoul( tokens[idx] , pEnd , 0 );
		}

		retval = IICMasterWrite(devid,i2c_addr,nbytes+1,buffer);
		free(buffer);
#endif
return retval;
	}

	if( command_type == PRINTTEMP ) { // We now update this in monitor, don't bother doing it twice...
		/* now write the web page data in two steps.  FIrst the Xilinx temp/voltages */
		char *pagefmt = "uptime %d , temp %0.1fC , intv %0.1fV , auxv %0.1fV , bramv %0.1fV\r\n";
		safe_sprintf(input_buf,pagefmt,procStatus.uptime,procStatus.v7temp,procStatus.v7vCCINT,procStatus.v7vCCAUX,procStatus.v7vBRAM);
		int n=strlen(input_buf);
		int w;
		if ((w = safe_send(s, input_buf)) < 0 ) {
			safe_printf("error writing web page data (part 1) to socket\r\n");
			safe_printf("attempted to lwip_write %d bytes, actual bytes written = %d\r\n", n, w);
			return -2;
		}
		return w;
	}

	if( command_type == GLOBALINIT ) {
		global_reset_eye_scan();
	}

	return retval;

}
	void VertexDeclarationGL::init(bvertex_format fmt)
	{
		bformat = fmt;
		int i = 0;
		int offset = 0;
		Element *dest = elements;
		if (fmt & VERTEX_POSITION)
		{
			strcpy(dest->name, "position");
			dest->elemType = GL_FLOAT;
			dest->size = 3;
			dest->offset = offset;
			dest->index = i;
			dest->normalized = false;

			offset += sizeof(float) * 3;
			++i;
			++dest;
		}

		if (fmt & VERTEX_COLOR)
		{
			strcpy(dest->name, "color");
			dest->elemType = GL_UNSIGNED_BYTE;
			dest->size = 4;
			dest->offset = offset;
			dest->index = i;
			dest->normalized = true;

			offset += 4;
			++i;
			++dest;
		}

		int numTexCoords = numTextureCoordinates(fmt);
		for (int j = 0; j < numTexCoords; ++j )
		{
			int coordSize = texCoordSize(j, fmt);
			if (j == 0)
				strcpy(dest->name, "uv");
			else
				safe_sprintf(dest->name, "uv%d", j + 1);

			dest->elemType = GL_FLOAT;
			dest->size = coordSize;
			dest->offset = offset;
			dest->index = i;
			dest->normalized = true;

			offset += sizeof(float) * coordSize;
			++i;
			++dest;
		}

		int userSize = userDataSize(fmt);
		if (userSize > 0)
		{
			dest->elemType = GL_FLOAT;
			dest->size = userSize;
			dest->offset = offset;
			dest->index = i;
			dest->normalized = false;

			offset += sizeof(float) * userSize;
			++i;
			++dest;
		}

		numElements = i;
		size = offset;
	}
// - ------------------------------------------------------------------------------------------ - //
pNetAdapterInfo* new_pNetAdapterInfo() {
	// http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058%28v=vs.85%29.aspx
	ULONG IPASize = 16384;
	IP_ADAPTER_ADDRESSES* IPA = (IP_ADAPTER_ADDRESSES*)new char[IPASize];
	
	// http://msdn.microsoft.com/en-us/library/windows/desktop/aa365915%28v=vs.85%29.aspx
	GetAdaptersAddresses( /*AF_UNSPEC*/AF_INET, 0, NULL, IPA, &IPASize );

	// IP_ADAPTER_UNICAST_ADDRESS -- http://msdn.microsoft.com/en-us/library/windows/desktop/aa366066%28v=vs.85%29.aspx
	// SOCKET_ADDRESS -- http://msdn.microsoft.com/en-us/library/windows/desktop/ms740507%28v=vs.85%29.aspx
	// sockaddr/sockaddr_in -- http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496%28v=vs.85%29.aspx
	// Alternatively -- http://www.beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html
	
	// Count the number Interfaces with IPv4 addresses //
	size_t IPv4Count = 0;
	for ( IP_ADAPTER_ADDRESSES* Current = IPA; Current != 0; Current = Current->Next ) {
		for ( IP_ADAPTER_UNICAST_ADDRESS* Cur = Current->FirstUnicastAddress; Cur != 0; Cur = Cur->Next ) {
			if ( Cur->Address.lpSockaddr->sa_family == AF_INET ) {
				// Found one! //
				IPv4Count++;
				break;
			}
		}
	}
	
	// Allocate the pNetAdapterInfo's //
	pNetAdapterInfo* Adapters = new pNetAdapterInfo[IPv4Count+1];

	// Allocate NetAdapterInfos per IP //	
	for ( size_t idx = 0; idx < IPv4Count; idx++ ) {
		Adapters[idx] = new_NetAdapterInfo();	// Internal Function //
	}
	
	Adapters[IPv4Count] = 0; // Last one a null pointer //

	
	// Iterate though and populate data //
	size_t Index = 0;
	for ( IP_ADAPTER_ADDRESSES* Current = IPA; Current != 0; Current = Current->Next ) {
		bool HasIPv4 = false;
		for ( IP_ADAPTER_UNICAST_ADDRESS* Cur = Current->FirstUnicastAddress; Cur != 0; Cur = Cur->Next ) {
			if ( Cur->Address.lpSockaddr->sa_family == AF_INET ) {
				sockaddr_in* SAI = (sockaddr_in*)Cur->Address.lpSockaddr;
				const unsigned char* DataAddr = (const unsigned char*)&(SAI->sin_addr.s_addr);

				int* IPv4 = (int*)Adapters[Index]->Data.IPv4;
				*IPv4 = *(int*)DataAddr;
								
				safe_sprintf( Adapters[Index]->IP, sizeof(Adapters[Index]->IP), "%s", inet_ntoa( SAI->sin_addr ) );
				
				HasIPv4 = true;
				break;
			}
		}
		
		// If an IP address wasn't found, then don't waste this NetAdapterInfo //
		if ( !HasIPv4 )
			continue;

		// Extract MAC //
		if ( Current->PhysicalAddressLength > 0 ) {
			memcpy( Adapters[Index]->Data.MAC, Current->PhysicalAddress, sizeof(Adapters[Index]->Data.MAC) );
			sprintf( Adapters[Index]->MAC, "%02x:%02x:%02x:%02x:%02x:%02x",
				Current->PhysicalAddress[0],
				Current->PhysicalAddress[1],
				Current->PhysicalAddress[2],
				Current->PhysicalAddress[3],
				Current->PhysicalAddress[4],
				Current->PhysicalAddress[5]
				);
		}
		
		// Extract DNS //
		for ( IP_ADAPTER_DNS_SERVER_ADDRESS* Cur = Current->FirstDnsServerAddress; Cur != 0; Cur = Cur->Next ) {
			if ( Cur->Address.lpSockaddr->sa_family == AF_INET ) {
				sockaddr_in* SAI = (sockaddr_in*)Cur->Address.lpSockaddr;								
				safe_sprintf( Adapters[Index]->DNS, sizeof(Adapters[Index]->DNS), "%s", inet_ntoa( SAI->sin_addr ) );
				break;
			}
		}

		// Anycast and Multicast address code, in case I ever decide to use them //
		
//		for ( IP_ADAPTER_ANYCAST_ADDRESS* Cur = Current->FirstAnycastAddress; Cur != 0; Cur = Cur->Next ) {
//			//printf("** %i\n", Cur->Address.lpSockaddr->sa_family);
//			if ( Cur->Address.lpSockaddr->sa_family == AF_INET ) {
//				sockaddr_in* SAI = (sockaddr_in*)Cur->Address.lpSockaddr;
//				printf( "Anycast: %s\n", inet_ntoa( SAI->sin_addr ) );
//			}
//		}
		
//		for ( IP_ADAPTER_MULTICAST_ADDRESS* Cur = Current->FirstMulticastAddress; Cur != 0; Cur = Cur->Next ) {
//			//printf("*** %i\n", Cur->Address.lpSockaddr->sa_family);
//			if ( Cur->Address.lpSockaddr->sa_family == AF_INET ) {
//				sockaddr_in* SAI = (sockaddr_in*)Cur->Address.lpSockaddr;
//				printf( "Multicast: %s\n", inet_ntoa( SAI->sin_addr ) );
//			}
//		}		
		
		// Copy Name //
		{
			// The strings are stored in wchar_t's, so we copy it to our char[] //
			size_t Length = wcstombs( Adapters[Index]->Name, Current->FriendlyName, sizeof(Adapters[Index]->Name) );
		}
		
		// Copy Description //
		{
			// The strings are stored in wchar_t's, so we copy it to our char[] //
			size_t Length = wcstombs( Adapters[Index]->Description, Current->Description, sizeof(Adapters[Index]->Description) );
		}
				
		Index++;
	}	
	
	delete IPA;

	return Adapters;
}
Beispiel #10
0
/*
 * Download a file from an URL
 * Mostly taken from http://support.microsoft.com/kb/234913
 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages
 * to the dialog in question, with WPARAM being set to nonzero for EXIT on success
 * and also attempt to indicate progress using an IDC_PROGRESS control
 */
BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog)
{
	HWND hProgressBar = NULL;
	BOOL r = FALSE;
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	FILE* fd = NULL;
	LONG progress_style;
	unsigned char buf[DOWNLOAD_BUFFER_SIZE];
	char agent[64], hostname[64], urlpath[128];
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	int i;
	char msg[MAX_PATH];

	if (hProgressDialog != NULL) {
		// Use the progress control provided, if any
		hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS);
		if (hProgressBar != NULL) {
			progress_style = GetWindowLong(hProgressBar, GWL_STYLE);
			SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
			SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
		}
		SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0);
	}

	safe_sprintf(msg, sizeof(msg), "Downloading %s: Connecting...", file);
	print_status(0, FALSE, msg);
	dprintf("Downloading %s from %s\n", file, url);

	if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts))
	  || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) {
		dprintf("Unable to decode URL: %s\n", WindowsErrorString());
		goto out;
	}
	hostname[sizeof(hostname)-1] = 0;

	// Open an Internet session
	for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) {
		Sleep(1000);
	}
	if (i <= 0) {
		// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
		SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
		dprintf("Network is unavailable: %s\n", WinInetErrorString());
		goto out;
	}
	safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d  (Windows NT %d.%d%s)",
		application_version[0], application_version[1], application_version[2],
		nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : "");
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL) {
		dprintf("Could not open internet session: %s\n", WinInetErrorString());
		goto out;
	}

	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL) {
		dprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
		goto out;
	}

	hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, (const char**)"*/*\0",
		INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
		INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
	if (hRequest == NULL) {
		dprintf("Could not open url %s: %s\n", url, WindowsErrorString());
		goto out;
	}

	if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
		dprintf("Unable to send request: %s\n", WinInetErrorString());
		goto out;
	}

	// Get the file size
	dwSize = sizeof(dwStatus);
	dwStatus = 404;
	HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
	if (dwStatus != 200) {
		download_error = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND;
		dprintf("Unable to access file: Server status %d\n", dwStatus);
		goto out;
	}
	dwSize = sizeof(dwTotalSize);
	if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) {
		dprintf("Unable to retrieve file length: %s\n", WinInetErrorString());
		goto out;
	}
	dprintf("File length: %d bytes\n", dwTotalSize);

	fd = fopenU(file, "wb");
	if (fd == NULL) {
		dprintf("Unable to create file '%s': %s\n", file, WinInetErrorString());
		goto out;
	}

	// Keep checking for data until there is nothing left.
	dwSize = 0;
	while (1) {
		if (download_error)
			goto out;

		if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
			break;
		dwSize += dwDownloaded;
		SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
		safe_sprintf(msg, sizeof(msg), "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize));
		print_status(0, FALSE, msg);
		if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) {
			dprintf("Error writing file '%s': %s\n", file, WinInetErrorString());
			goto out;
		}
	}

	if (dwSize != dwTotalSize) {
		dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize);
		download_error = ERROR_WRITE_FAULT;
		goto out;
	} else {
		r = TRUE;
		dprintf("Successfully downloaded '%s'\n", file);
	}

out:
	if (hProgressDialog != NULL)
		SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0);
	if (fd != NULL) fclose(fd);
	if (!r) {
		_unlink(file);
		print_status(0, FALSE, "Failed to download file.");
		SetLastError(download_error);
		MessageBoxU(hMain, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR);
	}
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);

	return r;
}
    TexturesInspector::TexturesInspector(const Vector2& size)
    {
        setSize(size);

        spSlidingActor slide = new SlidingActor;
        slide->setSize(size);
        addChild(slide);


        float offsetY = 0;

        std::vector<spNativeTexture> textures = NativeTexture::getCreatedTextures();


        spTextField text = initActor(new TextField,
                                     arg_color = Color::White,
                                     arg_pos = Vector2(1, 1),
                                     arg_w = itemSize.x * 3.0f,
                                     arg_h = 30.0f,
                                     arg_vAlign = TextStyle::VALIGN_TOP,
                                     arg_hAlign = TextStyle::HALIGN_LEFT,
                                     arg_multiline = true,
                                     arg_attachTo = slide
                                    );


        offsetY += text->getTextRect().getBottom() + 5;

        spActor content = new Actor;
        content->setX(2);


        int numX = (int)(size.x / itemSize.x);

        int n = 0;
        int mem = 0;
        for (std::vector<spNativeTexture>::reverse_iterator i = textures.rbegin(); i != textures.rend(); ++i)
        {
            spNativeTexture t = *i;
            TextureLine* line = new TextureLine(t);

            float x = (n % numX) * (itemSize.x + 5.0f);
            float y = (n / numX) * (itemSize.y + 5.0f);
            line->setX(x);
            line->setY(y + offsetY);
            content->addChild(line);
            ++n;

            if (t->getHandle())
            {
                TextureFormat fmt = t->getFormat();
                int ram = t->getWidth() * t->getHeight();
                if (isCompressedFormat(fmt))
                {
                    switch (fmt)
                    {
                        case TF_PVRTC_4RGBA:
                            ram /= 2;
                            break;
                        case TF_ETC1:
                            ram /= 2;
                            break;
                        default:
                            break;
                    }
                }
                else
                    ram *= getBytesPerPixel(fmt);

                mem += ram;
            }
        }

        char txt[255];
        safe_sprintf(txt, "created textures: %d, vram: %d kb", textures.size(), mem / 1024);

        text->setText(txt);
        if (numX > n)
            numX = n;

        content->setSize(
            (itemSize.x + 5.0f) * numX,
            (itemSize.y + 5.0f) * (n + numX - 1.0f) / numX + offsetY);

        setWidth(content->getWidth());
        slide->setWidth(content->getWidth());

        //slide->setSize()
        slide->setContent(content);
    }
Beispiel #12
0
int
main(int argc, char **argv){
	int fd, i, j, m, n, op, off, arg, c, d;
	struct slice all;
	struct pt *ptp;
	enum action what = LIST;
	char *type, *diskdevice, *device, *progname;
	int verbose = 0;
	char partname[PARTNAME_SIZE], params[PARTNAME_SIZE + 16];
	char * loopdev = NULL;
	char * delim = NULL;
	char *uuid = NULL;
	char *mapname = NULL;
	int loopro = 0;
	int hotplug = 0;
	int loopcreated = 0;
	int sync = 0;
	struct stat buf;
	uint32_t cookie = 0;

	initpts();
	init_crc32();

	type = device = diskdevice = NULL;
	memset(&all, 0, sizeof(all));
	memset(&partname, 0, sizeof(partname));

	/* Check whether hotplug mode. */
	progname = strrchr(argv[0], '/');

	if (!progname)
		progname = argv[0];
	else
		progname++;

	if (!strcmp(progname, "kpartx.dev")) { /* Hotplug mode */
		hotplug = 1;

		/* Setup for original kpartx variables */
		if (!(device = get_hotplug_device()))
			exit(1);

		diskdevice = device;
		what = ADD;
	} else if (argc < 2) {
		usage();
		exit(1);
	}

	while ((arg = getopt(argc, argv, short_opts)) != EOF) switch(arg) {
		case 'g':
			force_gpt=1;
			break;
		case 't':
			type = optarg;
			break;
		case 'v':
			verbose = 1;
			break;
		case 'p':
			delim = optarg;
			break;
		case 'l':
			what = LIST;
			break;
		case 'a':
			what = ADD;
			break;
		case 'd':
			what = DELETE;
			break;
		case 's':
			sync = 1;
			break;
		default:
			usage();
			exit(1);
	}

	if (!sync)
		dm_udev_set_sync_support(0);

	if (dm_prereq(DM_TARGET, 0, 0, 0) && (what == ADD || what == DELETE)) {
		fprintf(stderr, "device mapper prerequisites not met\n");
		exit(1);
	}

	if (hotplug) {
		/* already got [disk]device */
	} else if (optind == argc-2) {
		device = argv[optind];
		diskdevice = argv[optind+1];
	} else if (optind == argc-1) {
		diskdevice = device = argv[optind];
	} else {
		usage();
		exit(1);
	}

	if (stat(device, &buf)) {
		printf("failed to stat() %s\n", device);
		exit (1);
	}

	if (S_ISREG (buf.st_mode)) {
		/* already looped file ? */
		loopdev = find_loop_by_file(device);

		if (!loopdev && what == DELETE)
			exit (0);

		if (!loopdev) {
			loopdev = find_unused_loop_device();

			if (set_loop(loopdev, device, 0, &loopro)) {
				fprintf(stderr, "can't set up loop\n");
				exit (1);
			}
			loopcreated = 1;
		}
		device = loopdev;
	}

	if (delim == NULL) {
		delim = malloc(DELIM_SIZE);
		memset(delim, 0, DELIM_SIZE);
		set_delimiter(device, delim);
	}

	off = find_devname_offset(device);

	if (!loopdev) {
		uuid = dm_mapuuid((unsigned int)MAJOR(buf.st_rdev),
				  (unsigned int)MINOR(buf.st_rdev));
		mapname = dm_mapname((unsigned int)MAJOR(buf.st_rdev),
				     (unsigned int)MINOR(buf.st_rdev));
	}

	if (!uuid)
		uuid = device + off;

	if (!mapname)
		mapname = device + off;

	fd = open(device, O_RDONLY);

	if (fd == -1) {
		perror(device);
		exit(1);
	}

	/* add/remove partitions to the kernel devmapper tables */
	int r = 0;
	for (i = 0; i < ptct; i++) {
		ptp = &pts[i];

		if (type && strcmp(type, ptp->type))
			continue;

		/* here we get partitions */
		n = ptp->fn(fd, all, slices, SIZE(slices));

#ifdef DEBUG
		if (n >= 0)
			printf("%s: %d slices\n", ptp->type, n);
#endif

		if (n > 0)
			close(fd);
		else
			continue;

		switch(what) {
		case LIST:
			for (j = 0, c = 0, m = 0; j < n; j++) {
				if (slices[j].size == 0)
					continue;
				if (slices[j].container > 0) {
					c++;
					continue;
				}

				slices[j].minor = m++;

				printf("%s%s%d : 0 %" PRIu64 " %s %" PRIu64"\n",
				       mapname, delim, j+1,
				       slices[j].size, device,
				       slices[j].start);
			}
			/* Loop to resolve contained slices */
			d = c;
			while (c) {
				for (j = 0; j < n; j++) {
					uint64_t start;
					int k = slices[j].container - 1;

					if (slices[j].size == 0)
						continue;
					if (slices[j].minor > 0)
						continue;
					if (slices[j].container == 0)
						continue;
					slices[j].minor = m++;

					start = slices[j].start - slices[k].start;
					printf("%s%s%d : 0 %" PRIu64 " /dev/dm-%d %" PRIu64 "\n",
					       mapname, delim, j+1,
					       slices[j].size,
					       slices[k].minor, start);
					c--;
				}
				/* Terminate loop if nothing more to resolve */
				if (d == c)
					break;
			}

			if (loopcreated && S_ISREG (buf.st_mode)) {
				if (del_loop(device)) {
					if (verbose)
						printf("can't del loop : %s\n",
							device);
					exit(1);
				}
				printf("loop deleted : %s\n", device);
			}
			break;

		case DELETE:
			for (j = n-1; j >= 0; j--) {
				if (safe_sprintf(partname, "%s%s%d",
					     mapname, delim, j+1)) {
					fprintf(stderr, "partname too small\n");
					exit(1);
				}
				strip_slash(partname);

				if (!slices[j].size || !dm_map_present(partname))
					continue;

				if (!dm_simplecmd(DM_DEVICE_REMOVE, partname,
						  0, &cookie)) {
					r++;
					continue;
				}
				if (verbose)
					printf("del devmap : %s\n", partname);
			}

			if (S_ISREG (buf.st_mode)) {
				if (del_loop(device)) {
					if (verbose)
						printf("can't del loop : %s\n",
							device);
					exit(1);
				}
				printf("loop deleted : %s\n", device);
			}
			break;

		case ADD:
			for (j = 0, c = 0; j < n; j++) {
				if (slices[j].size == 0)
					continue;

				/* Skip all contained slices */
				if (slices[j].container > 0) {
					c++;
					continue;
				}

				if (safe_sprintf(partname, "%s%s%d",
					     mapname, delim, j+1)) {
					fprintf(stderr, "partname too small\n");
					exit(1);
				}
				strip_slash(partname);

				if (safe_sprintf(params, "%s %" PRIu64 ,
						 device, slices[j].start)) {
					fprintf(stderr, "params too small\n");
					exit(1);
				}

				op = (dm_map_present(partname) ?
					DM_DEVICE_RELOAD : DM_DEVICE_CREATE);

				if (!dm_addmap(op, partname, DM_TARGET, params,
					       slices[j].size, uuid, j+1,
					       buf.st_mode & 0777, buf.st_uid,
					       buf.st_gid, &cookie)) {
					fprintf(stderr, "create/reload failed on %s\n",
						partname);
					r++;
				}
				if (op == DM_DEVICE_RELOAD &&
				    !dm_simplecmd(DM_DEVICE_RESUME, partname,
						  1, &cookie)) {
					fprintf(stderr, "resume failed on %s\n",
						partname);
					r++;
				}
				dm_devn(partname, &slices[j].major,
					&slices[j].minor);

				if (verbose)
					printf("add map %s (%d:%d): 0 %" PRIu64 " %s %s\n",
					       partname, slices[j].major,
					       slices[j].minor, slices[j].size,
					       DM_TARGET, params);
			}
			/* Loop to resolve contained slices */
			d = c;
			while (c) {
				for (j = 0; j < n; j++) {
					uint64_t start;
					int k = slices[j].container - 1;

					if (slices[j].size == 0)
						continue;

					/* Skip all existing slices */
					if (slices[j].minor > 0)
						continue;

					/* Skip all simple slices */
					if (slices[j].container == 0)
						continue;

					/* Check container slice */
					if (slices[k].size == 0)
						fprintf(stderr, "Invalid slice %d\n",
							k);

					if (safe_sprintf(partname, "%s%s%d",
							 mapname, delim, j+1)) {
						fprintf(stderr, "partname too small\n");
						exit(1);
					}
					strip_slash(partname);

					start = slices[j].start - slices[k].start;
					if (safe_sprintf(params, "%d:%d %" PRIu64,
							 slices[k].major,
							 slices[k].minor,
							 start)) {
						fprintf(stderr, "params too small\n");
						exit(1);
					}

					op = (dm_map_present(partname) ?
					      DM_DEVICE_RELOAD : DM_DEVICE_CREATE);

					dm_addmap(op, partname, DM_TARGET, params,
						  slices[j].size, uuid, j+1,
						  buf.st_mode & 0777,
						  buf.st_uid, buf.st_gid,
						  &cookie);

					if (op == DM_DEVICE_RELOAD)
						dm_simplecmd(DM_DEVICE_RESUME,
							     partname, 1,
							     &cookie);

					dm_devn(partname, &slices[j].major,
						&slices[j].minor);

					if (verbose)
						printf("add map %s : 0 %" PRIu64 " %s %s\n",
						       partname, slices[j].size,
						       DM_TARGET, params);
					c--;
				}
				/* Terminate loop */
				if (d == c)
					break;
			}
			break;

		default:
			break;

		}
		if (n > 0)
			break;
	}
	dm_udev_wait(cookie);
	dm_lib_release();
	dm_lib_exit();

	return r;
}
Beispiel #13
0
/*
 * Background thread to check for updates
 */
static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
{
	BOOL releases_only, found_new_version = FALSE;
	int status = 0;
	const char* server_url = RUFUS_URL "/";
	int i, j, k, verbose = 0, verpos[4];
	static const char* archname[] = {"win_x86", "win_x64"};
	static const char* channel[] = {"release", "beta"};		// release channel
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	char* buf = NULL;
	char agent[64], hostname[64], urlpath[128], mime[32];
	OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""};
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	SYSTEMTIME ServerTime, LocalTime;
	FILETIME FileTime;
	int64_t local_time = 0, reg_time, server_time, update_interval;
	BOOL is_x64 = FALSE, (__stdcall *pIsWow64Process)(HANDLE, PBOOL) = NULL;

	update_check_in_progress = TRUE;
	verbose = ReadRegistryKey32(REGKEY_HKCU, REGKEY_VERBOSE_UPDATES);
	// Unless the update was forced, wait a while before performing the update check
	if (!force_update_check) {
		// TODO: Also check on inactivity
		// It would of course be a lot nicer to use a timer and wake the thread, but my
		// development time is limited and this is FASTER to implement.
		do {
			for (i=0; (i<30) && (!force_update_check); i++)
				Sleep(500);
		} while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0))));
		if (!force_update_check) {
			if ((ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == -1)) {
				vuprintf("Check for updates disabled, as per registry settings.\n");
				goto out;
			}
			reg_time = ReadRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE);
			update_interval = (int64_t)ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL);
			if (update_interval == 0) {
				WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL);
				update_interval = DEFAULT_UPDATE_INTERVAL;
			}
			GetSystemTime(&LocalTime);
			if (!SystemTimeToFileTime(&LocalTime, &FileTime))
				goto out;
			local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
			vvuprintf("Local time: %" PRId64 "\n", local_time);
			if (local_time < reg_time + update_interval) {
				vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time);
				goto out;
			}
		}
	}

	PrintStatus(3000, TRUE, "Checking for " APPLICATION_NAME " updates...\n");
	status++;	// 1

	if (!GetVersionExA(&os_version)) {
		uprintf("Could not read Windows version - Check for updates cancelled.\n");
		goto out;
	}

	// Detect if the OS is 64 bit, without relying on external libs
	if (sizeof(uintptr_t) < 8) {
		// This application is not 64 bit, but it might be 32 bit running in WOW64
		pIsWow64Process = (BOOL (__stdcall *)(HANDLE, PBOOL))
			GetProcAddress(GetModuleHandleA("KERNEL32"), "IsWow64Process");
		if (pIsWow64Process != NULL) {
			(*pIsWow64Process)(GetCurrentProcess(), &is_x64);
		}
	} else {
		is_x64 = TRUE;
	}

	if ((!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!InternetGetConnectedState(&dwFlags, 0)))
		goto out;
	hostname[sizeof(hostname)-1] = 0;

	safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL)
		goto out;
	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL)
		goto out;

	status++;	// 2
	releases_only = !GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS);

	for (k=0; (k<(releases_only?1:(int)ARRAYSIZE(channel))) && (!found_new_version); k++) {
		uprintf("Checking %s channel...\n", channel[k]);
		// At this stage we can query the server for various update version files.
		// We first try to lookup for "<appname>_<os_arch>_<os_version_major>_<os_version_minor>.ver"
		// and then remove each each of the <os_> components until we find our match. For instance, we may first
		// look for rufus_win_x64_6.2.ver (Win8 x64) but only get a match for rufus_win_x64_6.ver (Vista x64 or later)
		// This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups.
		safe_sprintf(urlpath, sizeof(urlpath), "%s%s%s_%s_%d.%d.ver", APPLICATION_NAME, (k==0)?"":"_",
			(k==0)?"":channel[k], archname[is_x64?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion);
		vuprintf("Base update check: %s\n", urlpath);
		for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) {
			if ((urlpath[j] == '.') || (urlpath[j] == '_')) {
				verpos[i++] = j;
			}
		}
		if (i != ARRAYSIZE(verpos)) {
			uprintf("Broken code in CheckForUpdatesThread()!\n");
			goto out;
		}

		UrlParts.lpszUrlPath = urlpath;
		UrlParts.dwUrlPathLength = sizeof(urlpath);
		for (i=0; i<ARRAYSIZE(verpos); i++) {
			vvuprintf("Trying %s\n", UrlParts.lpszUrlPath);
			hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, (const char**)"*/*\0",
				INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
				INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
			if ((hRequest == NULL) || (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)))
				goto out;

			// Ensure that we get a text file
			dwSize = sizeof(dwStatus);
			dwStatus = 404;
			HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
			if (dwStatus == 200) 
				break;
			InternetCloseHandle(hRequest);
			hRequest = NULL;
			safe_strcpy(&urlpath[verpos[i]], 5, ".ver");
		}
		if (dwStatus != 200) {
			vuprintf("Could not find a %s version file on server %s", channel[k], server_url);
			if ((releases_only) || (k+1 >= ARRAYSIZE(channel)))
				goto out;
			continue;
		}
		vuprintf("Found match for %s on server %s.", urlpath, server_url);

		dwSize = sizeof(mime);
		HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_TYPE, (LPVOID)&mime, &dwSize, NULL);
		if (strcmp(mime, "text/plain") != 0)
			goto out;

		// We also get a date from Apache, which we'll use to avoid out of sync check,
		// in case some set their clock way into the future and back.
		// On the other hand, if local clock is set way back in the past, we will never check.
		dwSize = sizeof(ServerTime);
		// If we can't get a date we can trust, don't bother...
		if ( (!HttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL))
			|| (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
			goto out;
		server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
		vvuprintf("Server time: %" PRId64 "\n", server_time);
		// Always store the server response time - the only clock we trust!
		WriteRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE, server_time);
		// Might as well let the user know
		if (!force_update_check) {
			if (local_time > server_time + 600) {
				uprintf("Your local clock appears more than 10 minutes early - You ought to fix that...\n");
			}
			if (local_time < server_time - 600) {
				uprintf("Your local clock appears more than 10 minutes late - you ought to fix that...\n");
			}
		}

		dwSize = sizeof(dwTotalSize);
		if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL))
			goto out;

		safe_free(buf);
		// Make sure the file is NUL terminated
		buf = (char*)calloc(dwTotalSize+1, 1);
		if (buf == NULL) goto out;
		// This is a version file - we should be able to gulp it down in one go
		if (!InternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize))
			goto out;

		status++;
		vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize);

		parse_update(buf, dwTotalSize+1);

		vuprintf("UPDATE DATA:\n");
		vuprintf("  version: %d.%d.%d.%d (%s)\n", update.version[0], update.version[1], 
			update.version[2], update.version[3], channel[k]);
		vuprintf("  platform_min: %d.%d\n", update.platform_min[0], update.platform_min[1]);
		vuprintf("  url: %s\n", update.download_url);

		found_new_version = (to_uint64_t(update.version) > to_uint64_t(rufus_version))
			&& ( (os_version.dwMajorVersion > update.platform_min[0])
			  || ( (os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) );
		uprintf("N%sew %s version found%c\n", found_new_version?"":"o n", channel[k], found_new_version?'!':'.');
	}

out:
	safe_free(buf);
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);
	switch(status) {
	case 1:
		PrintStatus(3000, TRUE, "Updates: Unable to connect to the internet.\n");
		break;
	case 2:
		PrintStatus(3000, TRUE, "Updates: Unable to access version data.\n");
		break;
	case 3:
	case 4:
		PrintStatus(3000, FALSE, "%s new version of " APPLICATION_NAME " %s\n",
		found_new_version?"A":"No", found_new_version?"is available!":"was found.");
	default:
		break;
	}
	// Start the new download after cleanup
	if (found_new_version) {
		// User may have started an operation while we were checking
		while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing>0))) {
			Sleep(15000);
		}
		DownloadNewVersion();
	}
	force_update_check = FALSE;
	update_check_in_progress = FALSE;
	ExitThread(0);
}
Beispiel #14
0
Datei: iso.c Projekt: hanji/rufus
BOOL ExtractISO(const char* src_iso, const char* dest_dir, bool scan)
{
	size_t i;
	int j;
	FILE* fd;
	BOOL r = FALSE;
	iso9660_t* p_iso = NULL;
	udf_t* p_udf = NULL; 
	udf_dirent_t* p_udf_root;
	LONG progress_style;
	char* tmp;
	char path[64];
	const char* scan_text = "Scanning ISO image...";
	const char* basedir[] = { "i386", "minint" };
	const char* tmp_sif = ".\\txtsetup.sif~";

	if ((src_iso == NULL) || (dest_dir == NULL))
		return FALSE;

	scan_only = scan;
	cdio_log_set_handler(log_handler);
	psz_extract_dir = dest_dir;
	progress_style = GetWindowLong(hISOProgressBar, GWL_STYLE);
	if (scan_only) {
		total_blocks = 0;
		memset(&iso_report, 0, sizeof(iso_report));
		// String array of all isolinux/syslinux locations
		StrArrayCreate(&config_path, 8);
		// Change the Window title and static text
		SetWindowTextU(hISOProgressDlg, scan_text);
		SetWindowTextU(hISOFileName, scan_text);
		// Change progress style to marquee for scanning
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style | PBS_MARQUEE);
		SendMessage(hISOProgressBar, PBM_SETMARQUEE, TRUE, 0);
	} else {
		uprintf("Extracting files...\n");
		if (total_blocks == 0) {
			uprintf("Error: ISO has not been properly scanned.\n");
			FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR(ERROR_ISO_SCAN);
			goto out;
		}
		nb_blocks = 0;
		iso_blocking_status = 0;
		SetWindowLong(hISOProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
		SendMessage(hISOProgressBar, PBM_SETPOS, 0, 0);
	}
	ShowWindow(hISOProgressDlg, SW_SHOW);
	UpdateWindow(hISOProgressDlg);

	/* First try to open as UDF - fallback to ISO if it failed */
	p_udf = udf_open(src_iso);
	if (p_udf == NULL)
		goto try_iso;
	uprintf("Disc image is an UDF image\n");

	p_udf_root = udf_get_root(p_udf, true, 0);
	if (p_udf_root == NULL) {
		uprintf("Couldn't locate UDF root directory\n");
		goto out;
	}
	if (scan_only) {
		if (udf_get_logical_volume_id(p_udf, iso_report.label, sizeof(iso_report.label)) <= 0)
			iso_report.label[0] = 0;
	}
	r = udf_extract_files(p_udf, p_udf_root, "");
	goto out;

try_iso:
	p_iso = iso9660_open_ext(src_iso, ISO_EXTENSION_ALL);
	if (p_iso == NULL) {
		uprintf("Unable to open image '%s'.\n", src_iso);
		goto out;
	}
	i_joliet_level = iso9660_ifs_get_joliet_level(p_iso);
	uprintf("Disc image is an ISO9660 image\n");
	if (scan_only) {
		if (iso9660_ifs_get_volume_id(p_iso, &tmp)) {
			safe_strcpy(iso_report.label, sizeof(iso_report.label), tmp);
			safe_free(tmp);
		} else
			iso_report.label[0] = 0;
	}
	r = iso_extract_files(p_iso, "");

out:
	iso_blocking_status = -1;
	if (scan_only) {
		// Remove trailing spaces from the label
		for (j=safe_strlen(iso_report.label)-1; ((j>=0)&&(isspace(iso_report.label[j]))); j--)
			iso_report.label[j] = 0;
		// We use the fact that UDF_BLOCKSIZE and ISO_BLOCKSIZE are the same here
		iso_report.projected_size = total_blocks * ISO_BLOCKSIZE;
		// We will link the existing isolinux.cfg from a syslinux.cfg we create
		// If multiple config file exist, choose the one with the shortest path
		if (iso_report.has_isolinux) {
			safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.Table[0]);
			for (i=1; i<config_path.Index; i++) {
				if (safe_strlen(iso_report.cfg_path) > safe_strlen(config_path.Table[i]))
					safe_strcpy(iso_report.cfg_path, sizeof(iso_report.cfg_path), config_path.Table[i]);
			}
			uprintf("Will use %s for Syslinux\n", iso_report.cfg_path);
		}
		if (IS_WINPE(iso_report.winpe)) {
			// In case we have a WinPE 1.x based iso, we extract and parse txtsetup.sif
			// during scan, to see if /minint was provided for OsLoadOptions, as it decides
			// whether we should use 0x80 or 0x81 as the disk ID in the MBR
			safe_sprintf(path, sizeof(path), "/%s/txtsetup.sif", 
				basedir[((iso_report.winpe&WINPE_I386) == WINPE_I386)?0:1]);
			ExtractISOFile(src_iso, path, tmp_sif);
			tmp = get_token_data(tmp_sif, "OsLoadOptions");
			if (tmp != NULL) {
				for (i=0; i<strlen(tmp); i++)
					tmp[i] = (char)tolower(tmp[i]);
				uprintf("Checking txtsetup.sif:\n  OsLoadOptions = %s\n", tmp);
				iso_report.uses_minint = (strstr(tmp, "/minint") != NULL);
			}
			_unlink(tmp_sif);
			safe_free(tmp);
		}
		StrArrayDestroy(&config_path);
	} else if (iso_report.has_isolinux) {
		safe_sprintf(path, sizeof(path), "%s\\syslinux.cfg", dest_dir);
		// Create a /syslinux.cfg (if none exists) that points to the existing isolinux cfg
		fd = fopen(path, "r");
		if (fd == NULL) {
			fd = fopen(path, "w");	// No "/syslinux.cfg" => create a new one
			if (fd == NULL) {
				uprintf("Unable to create %s - booting from USB will not work\n", path);
				r = 1;
			} else {
				fprintf(fd, "DEFAULT loadconfig\n\nLABEL loadconfig\n  CONFIG %s\n", iso_report.cfg_path);
				for (i=safe_strlen(iso_report.cfg_path); (i>0)&&(iso_report.cfg_path[i]!='/'); i--);
				if (i>0) {
					iso_report.cfg_path[i] = 0;
					fprintf(fd, "  APPEND %s/\n", iso_report.cfg_path);
					iso_report.cfg_path[i] = '/';
				}
				uprintf("Created: %s\n", path);
			}
		}
		if (fd != NULL)
			fclose(fd);
	}
	ShowWindow(hISOProgressDlg, SW_HIDE);
	if (p_iso != NULL)
		iso9660_close(p_iso);
	if (p_udf != NULL)
		udf_close(p_udf);
	if ((r != 0) && (FormatStatus == 0))
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|APPERR((scan_only?ERROR_ISO_SCAN:ERROR_ISO_EXTRACT));
	return (r == 0);
}
Beispiel #15
0
static DWORD WINAPI SearchProcessThread(LPVOID param)
{
	const char *access_rights_str[8] = { "n", "r", "w", "rw", "x", "rx", "wx", "rwx" };
	char tmp[MAX_PATH];
	NTSTATUS status = STATUS_SUCCESS;
	PSYSTEM_HANDLE_INFORMATION_EX handles = NULL;
	POBJECT_NAME_INFORMATION buffer = NULL;
	ULONG_PTR i;
	ULONG_PTR pid[2];
	ULONG_PTR last_access_denied_pid = 0;
	ULONG bufferSize;
	USHORT wHandleNameLen;
	WCHAR *wHandleName = NULL;
	HANDLE dupHandle = NULL;
	HANDLE processHandle = NULL;
	BOOLEAN bFound = FALSE, bGotExePath, verbose = !_bQuiet;
	ULONG access_rights = 0;
	DWORD size;
	char exe_path[MAX_PATH] = { 0 };
	wchar_t wexe_path[MAX_PATH];
	int cur_pid;

	PF_INIT_OR_SET_STATUS(NtQueryObject, Ntdll);
	PF_INIT_OR_SET_STATUS(NtDuplicateObject, NtDll);
	PF_INIT_OR_SET_STATUS(NtClose, NtDll);

	StrArrayClear(&BlockingProcess);

	if (NT_SUCCESS(status))
		status = PhCreateHeap();

	if (NT_SUCCESS(status))
		status = PhEnumHandlesEx(&handles);

	if (!NT_SUCCESS(status)) {
		uprintf("Warning: Could not enumerate process handles: %s", NtStatusError(status));
		goto out;
	}

	pid[0] = (ULONG_PTR)0;
	cur_pid = 1;

	wHandleName = utf8_to_wchar(_HandleName);
	wHandleNameLen = (USHORT)wcslen(wHandleName);

	bufferSize = 0x200;
	buffer = PhAllocate(bufferSize);
	if (buffer == NULL)
		goto out;

	for (i = 0; ; i++) {
		ULONG attempts = 8;
		PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX handleInfo =
			(i < handles->NumberOfHandles) ? &handles->Handles[i] : NULL;

		if ((dupHandle != NULL) && (processHandle != NtCurrentProcess())) {
			pfNtClose(dupHandle);
			dupHandle = NULL;
		}

		// Update the current handle's process PID and compare against last
		// Note: Be careful about not trying to overflow our list!
		pid[cur_pid] = (handleInfo != NULL) ? handleInfo->UniqueProcessId : -1;

		if (pid[0] != pid[1]) {
			cur_pid = (cur_pid + 1) % 2;

			// If we're switching process and found a match, print it
			if (bFound) {
				vuprintf("● '%s' (pid: %ld, access: %s)", exe_path, pid[cur_pid], access_rights_str[access_rights & 0x7]);
				static_sprintf(tmp, "● %s (%s)", exe_path, access_rights_str[access_rights & 0x7]);
				StrArrayAdd(&BlockingProcess, tmp, TRUE);
				bFound = FALSE;
				access_rights = 0;
			}

			// Close the previous handle
			if (processHandle != NULL) {
				if (processHandle != NtCurrentProcess())
					pfNtClose(processHandle);
				processHandle = NULL;
			}
		}

		CHECK_FOR_USER_CANCEL;

		// Exit loop condition
		if (i >= handles->NumberOfHandles)
			break;

		// Don't bother with processes we can't access
		if (handleInfo->UniqueProcessId == last_access_denied_pid)
			continue;

		// Filter out handles that aren't opened with Read (bit 0), Write (bit 1) or Execute (bit 5) access
		if ((handleInfo->GrantedAccess & 0x23) == 0)
			continue;

		// Open the process to which the handle we are after belongs, if not already opened
		if (pid[0] != pid[1]) {
			status = PhOpenProcess(&processHandle, PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION,
				(HANDLE)handleInfo->UniqueProcessId);
			// There exists some processes we can't access
			if (!NT_SUCCESS(status)) {
				uuprintf("SearchProcess: Could not open process %ld: %s",
					handleInfo->UniqueProcessId, NtStatusError(status));
				processHandle = NULL;
				if (status == STATUS_ACCESS_DENIED) {
					last_access_denied_pid = handleInfo->UniqueProcessId;
				}
				continue;
			}
		}

		// Now duplicate this handle onto our own process, so that we can access its properties
		if (processHandle == NtCurrentProcess()) {
			if (_bIgnoreSelf)
				continue;
			dupHandle = (HANDLE)handleInfo->HandleValue;
		} else {
			status = pfNtDuplicateObject(processHandle, (HANDLE)handleInfo->HandleValue,
				NtCurrentProcess(), &dupHandle, 0, 0, 0);
			if (!NT_SUCCESS(status))
				continue;
		}

		// Filter non-storage handles. We're not interested in them and they make NtQueryObject() freeze
		if (GetFileType(dupHandle) != FILE_TYPE_DISK)
			continue;

		// A loop is needed because the I/O subsystem likes to give us the wrong return lengths...
		do {
			ULONG returnSize;
			// TODO: We might potentially still need a timeout on ObjectName queries, as PH does...
			status = pfNtQueryObject(dupHandle, ObjectNameInformation, buffer, bufferSize, &returnSize);
			if (status == STATUS_BUFFER_OVERFLOW || status == STATUS_INFO_LENGTH_MISMATCH ||
				status == STATUS_BUFFER_TOO_SMALL) {
				uuprintf("SearchProcess: Realloc from %d to %d", bufferSize, returnSize);
				bufferSize = returnSize;
				PhFree(buffer);
				buffer = PhAllocate(bufferSize);
			} else {
				break;
			}
		} while (--attempts);
		if (!NT_SUCCESS(status)) {
			uuprintf("SearchProcess: NtQueryObject failed for handle %X of process %ld: %s",
				handleInfo->HandleValue, handleInfo->UniqueProcessId, NtStatusError(status));
			continue;
		}

		// Don't bother comparing if we are looking for full match and the length is different
		if ((!_bPartialMatch) && (wHandleNameLen != buffer->Name.Length))
			continue;

		// Likewise, if we are looking for a partial match and the current length is smaller
		if ((_bPartialMatch) && (wHandleNameLen > buffer->Name.Length))
			continue;

		// Match against our target string
		if (wcsncmp(wHandleName, buffer->Name.Buffer, wHandleNameLen) != 0)
			continue;

		// If we are here, we have a process accessing our target!
		bFound = TRUE;

		// Keep a mask of all the access rights being used
		access_rights |= handleInfo->GrantedAccess;
		// The Executable bit is in a place we don't like => reposition it
		if (access_rights & 0x20)
			access_rights = (access_rights & 0x03) | 0x04;
		access_mask |= (BYTE) (access_rights & 0x7) + 0x80;	// Bit 7 is always set if a process was found

		// If this is the very first process we find, print a header
		if (exe_path[0] == 0)
			vuprintf("WARNING: The following process(es) or service(s) are accessing %s:", _HandleName);

		// First, we try to get the executable path using GetModuleFileNameEx
		bGotExePath = (GetModuleFileNameExU(processHandle, 0, exe_path, MAX_PATH - 1) != 0);

		// The above may not work on Windows 7, so try QueryFullProcessImageName (Vista or later)
		if (!bGotExePath) {
			size = MAX_PATH;
			PF_INIT(QueryFullProcessImageNameW, kernel32);
			if ( (pfQueryFullProcessImageNameW != NULL) &&
				 (bGotExePath = pfQueryFullProcessImageNameW(processHandle, 0, wexe_path, &size)) )
				wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path));
		}

		// Still nothing? Try GetProcessImageFileName. Note that GetProcessImageFileName uses
		// '\Device\Harddisk#\Partition#\' instead drive letters
		if (!bGotExePath) {
			bGotExePath = (GetProcessImageFileNameW(processHandle, wexe_path, MAX_PATH) != 0);
			if (bGotExePath)
				wchar_to_utf8_no_alloc(wexe_path, exe_path, sizeof(exe_path));
		}

		// Complete failure => Just craft a default process name that includes the PID
		if (!bGotExePath) {
			safe_sprintf(exe_path, MAX_PATH, "Unknown_Process_%" PRIu64,
				(ULONGLONG)handleInfo->UniqueProcessId);
		}
	}

out:
	if (exe_path[0] != 0)
		vuprintf("You should close these applications before attempting to reformat the drive.");
	else
		vuprintf("NOTE: Could not identify the process(es) or service(s) accessing %s", _HandleName);

	free(wHandleName);
	PhFree(buffer);
	PhFree(handles);
	PhDestroyHeap();
	ExitThread(0);
}
    TexturesInspector::TexturesInspector(const Vector2& size)
    {
        setSize(size);

        spSlidingActor slide = new SlidingActor;
        slide->setSize(size);
        addChild(slide);


        float offsetY = 0;

        std::vector<spNativeTexture> textures = NativeTexture::getCreatedTextures();


        spTextField text = initActor(new TextField,
                                     arg_color = Color::White,
                                     arg_pos = Vector2(1, 1),
                                     arg_w = itemSize.x * 3.0f,
                                     arg_h = 30.0f,
                                     arg_vAlign = TextStyle::VALIGN_TOP,
                                     arg_hAlign = TextStyle::HALIGN_LEFT,
                                     arg_multiline = true,
                                     arg_attachTo = slide
                                    );


        offsetY += text->getTextRect().getBottom() + 5;

        spActor content = new Actor;
        content->setX(2);


        int numX = (int)(size.x / itemSize.x);

        int n = 0;
        int mem = 0;
        for (std::vector<spNativeTexture>::iterator i = textures.begin(); i != textures.end(); ++i)
        {
            spNativeTexture t = *i;
            TextureLine* line = new TextureLine(t);

            float x = (n % numX) * (itemSize.x + 5.0f);
            float y = (n / numX) * (itemSize.y + 5.0f);
            line->setX(x);
            line->setY(y + offsetY);
            content->addChild(line);
            ++n;

            mem += t->getSizeVRAM();
        }

        char txt[255];
        safe_sprintf(txt, "created textures: %d, vram: %d kb", textures.size(), mem / 1024);

        text->setText(txt);
        if (numX > n)
            numX = n;

        content->setSize(
            (itemSize.x + 5.0f) * numX,
            (itemSize.y + 5.0f) * (n + numX - 1.0f) / numX + offsetY);

        setWidth(content->getWidth());
        slide->setWidth(content->getWidth());

        //slide->setSize()
        slide->setContent(content);
    }
Beispiel #17
0
INT_PTR CALLBACK device_list_wndproc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	TCHAR tipText[80];
	POINT pt;
	static int oldX, oldY;
	int newX, newY;
	LVHITTESTINFO hitTestInfo;
	LVITEM lvitem;
	device_context_t* dev_context;
	BOOL ignored;

	switch(message)
	{
	case WM_MOUSELEAVE:
		// The mouse pointer has left our window.
		// Deactivate the tooltip.
		SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&g_toolItem);
		g_TrackingMouse = FALSE;
		return FALSE;

	case WM_MOUSEMOVE:

		if (!g_TrackingMouse)
		{
			// The mouse has just entered the window.

			// Request notification when the mouse leaves.
			TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
			tme.hwndTrack = hDlg;
			tme.dwFlags = TME_LEAVE;
			TrackMouseEvent(&tme);

			// Activate the tooltip.
			SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,
				(WPARAM)TRUE, (LPARAM)&g_toolItem);
			g_TrackingMouse = TRUE;
		}

		newX = LOWORD(lParam);
		newY = HIWORD(lParam);

		// Make sure the mouse has actually moved. The presence of the tooltip
		// causes Windows to send the message continuously.
		if ((newX != oldX) || (newY != oldY))
		{
			oldX = newX;
			oldY = newY;

			memset(&hitTestInfo,0,sizeof(hitTestInfo));
			hitTestInfo.pt.x = newX;
			hitTestInfo.pt.y = newY;

			if ((ListView_HitTest(hDlg, &hitTestInfo) == -1) || newX > ListView_GetColumnWidth(hDlg, 0))
			{
				safe_sprintf(tipText, sizeof(tipText) - 1, TEXT("%s"), TEXT(""));
				SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,FALSE, (LPARAM)&g_toolItem);
			}
			else
			{
				SendMessage(g_hwndTrackingTT, TTM_SETDELAYTIME,TTDT_INITIAL, 1000);

				memset(&lvitem, 0 , sizeof(lvitem));

				lvitem.iItem = hitTestInfo.iItem;
				lvitem.mask =  LVIF_PARAM;
				ignored = ListView_GetItem(hDlg,&lvitem);

				dev_context = (device_context_t*)lvitem.lParam;
				// Update the text.
				safe_sprintf(tipText, sizeof(tipText)-1 , TEXT("%s"), wdi_get_vendor_name(dev_context->wdi->vid));
				SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE,TRUE, (LPARAM)&g_toolItem);

			}
			g_toolItem.lpszText = tipText;
			SendMessage(g_hwndTrackingTT, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);

			// Position the tooltip.
			// The coordinates are adjusted so that the tooltip does not
			// overlap the mouse pointer.
			pt.x = newX;
			pt.y = newY;

			ClientToScreen(hDlg, &pt);
			SendMessage(g_hwndTrackingTT, TTM_TRACKPOSITION,
				0, (LPARAM)MAKELONG(pt.x + 10, pt.y - 20));
		}
		break;
	}
	return CallWindowProc(device_list_wndproc_orig, hDlg, message, wParam, lParam);
}
	string	color2hex(const Color &c)
	{
		char str[255];
		safe_sprintf(str, "%02x%02x%02x%02x", c.r, c.g, c.b, c.a);
		return string(str);
	}
Beispiel #19
0
BOOL CALLBACK dialog_proc_3(HWND dialog, UINT message,
							WPARAM wParam, LPARAM lParam)
{
	static device_context_t *device = NULL;
	char* bufferLabel = NULL;
	char* bufferText = NULL;
	int ret;
	UINT x,y;
	UINT TXT_WIDTH = 200;
	UINT LBL_WIDTH = 150;
	UINT LBL_HEIGHT = 15;
	UINT LBL_SEP = 5;
	HWND hwnd;
	static HBRUSH hBrushStatic = NULL;

	RECT rect;

	switch (message)
	{
	case WM_INITDIALOG:
		SendMessage(dialog,WM_SETICON,ICON_SMALL, (LPARAM)mIcon);
		SendMessage(dialog,WM_SETICON,ICON_BIG,   (LPARAM)mIcon);

		device = (device_context_t *)lParam;

		create_tooltip(dialog, g_hInst, 300, tooltips_dlg3);

		bufferLabel  = malloc(MAX_TEXT_LENGTH*2);
		bufferText   = bufferLabel+MAX_TEXT_LENGTH;
		if (bufferLabel)
		{
			GetWindowRect(GetDlgItem(dialog,IDG_MAIN),&rect);
			TXT_WIDTH = rect.right-rect.left-30-LBL_WIDTH;

			y = 40;
			x = 30;
			safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, "%s", info_text_1);
			create_labeled_text(bufferLabel,NULL, dialog, g_hInst, x, y, LBL_HEIGHT * 2,LBL_WIDTH+TXT_WIDTH,0, ID_TEXT_HIGHLIGHT_INFO, ID_TEXT_HIGHLIGHT_INFO);

			y += LBL_HEIGHT*2+LBL_SEP*2;
			safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Vendor ID:");
			safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%04X", device->wdi->vid);
			create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);

			y += LBL_HEIGHT+LBL_SEP;
			safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Product ID:");
			safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%04X", device->wdi->pid);
			create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);

			if (device->wdi->is_composite)
			{
				y += LBL_HEIGHT+LBL_SEP;
				safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Interface # (MI):");
				safe_sprintf(bufferText, MAX_TEXT_LENGTH, "0x%02X", device->wdi->mi);
				create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);
			}

			y += LBL_HEIGHT+LBL_SEP;
			safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Device description:");
			safe_sprintf(bufferText, MAX_TEXT_LENGTH, "%s", device->description);
			create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);

			y += LBL_HEIGHT+LBL_SEP;
			safe_strcpy(bufferLabel, MAX_TEXT_LENGTH, "Manufacturer:");
			safe_sprintf(bufferText, MAX_TEXT_LENGTH, "%s", device->manufacturer);
			create_labeled_text(bufferLabel,bufferText,dialog,g_hInst,x,y,LBL_HEIGHT,LBL_WIDTH,TXT_WIDTH, ID_INFO_TEXT, ID_INFO_TEXT);

			y += LBL_HEIGHT+LBL_SEP*2;
			if (device->driver_info.dwSignature)
			{
				safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, package_contents_fmt_0, "libusb-win32",
					(int)device->driver_info.dwFileVersionMS>>16, (int)device->driver_info.dwFileVersionMS&0xFFFF,
					(int)device->driver_info.dwFileVersionLS>>16, (int)device->driver_info.dwFileVersionLS&0xFFFF,
					"x86, x64, ia64");

			}
			else
			{
				safe_sprintf(bufferLabel, MAX_TEXT_LENGTH, "%s", package_contents_fmt_1);
			}
			hwnd = create_labeled_text(NULL,bufferLabel,dialog,g_hInst,x,y,LBL_HEIGHT*2, 0, LBL_WIDTH+TXT_WIDTH, ID_TEXT_HIGHLIGHT_INFO, ID_TEXT_HIGHLIGHT_INFO);

			free(bufferLabel);

		}
Beispiel #20
0
 void error_va(const char* format, va_list args)
 {
     char tm[32];
     safe_sprintf(tm, "%03d error: ", getTime());
     out_line_prefix(_eh, tm, format, args);
 }
Beispiel #21
0
/*
 * Background thread to check for updates
 */
static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
{
	BOOL releases_only, found_new_version = FALSE;
	int status = 0;
	const char* server_url = RUFUS_URL "/";
	int i, j, k, max_channel, verbose = 0, verpos[4];
	static const char* archname[] = {"win_x86", "win_x64"};
	static const char* channel[] = {"release", "beta", "test"};		// release channel
	const char* accept_types[] = {"*/*\0", NULL};
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	char* buf = NULL;
	char agent[64], hostname[64], urlpath[128], mime[32];
	OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""};
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	SYSTEMTIME ServerTime, LocalTime;
	FILETIME FileTime;
	int64_t local_time = 0, reg_time, server_time, update_interval;

	update_check_in_progress = TRUE;
	verbose = ReadSetting32(SETTING_VERBOSE_UPDATES);
	// Without this the FileDialog will produce error 0x8001010E when compiled for Vista or later
	IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
	// Unless the update was forced, wait a while before performing the update check
	if (!force_update_check) {
		// It would of course be a lot nicer to use a timer and wake the thread, but my
		// development time is limited and this is FASTER to implement.
		do {
			for (i=0; (i<30) && (!force_update_check); i++)
				Sleep(500);
		} while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0))));
		if (!force_update_check) {
			if ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1)) {
				vuprintf("Check for updates disabled, as per settings.\n");
				goto out;
			}
			reg_time = ReadSetting64(SETTING_LAST_UPDATE);
			update_interval = (int64_t)ReadSetting32(SETTING_UPDATE_INTERVAL);
			if (update_interval == 0) {
				WriteSetting32(SETTING_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL);
				update_interval = DEFAULT_UPDATE_INTERVAL;
			}
			GetSystemTime(&LocalTime);
			if (!SystemTimeToFileTime(&LocalTime, &FileTime))
				goto out;
			local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
			vvuprintf("Local time: %" PRId64 "\n", local_time);
			if (local_time < reg_time + update_interval) {
				vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time);
				goto out;
			}
		}
	}

	PrintInfoDebug(3000, MSG_243);
	status++;	// 1

	if (!GetVersionExA(&os_version)) {
		uprintf("Could not read Windows version - Check for updates cancelled.\n");
		goto out;
	}

	if ((!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!InternetGetConnectedState(&dwFlags, 0)))
		goto out;
	hostname[sizeof(hostname)-1] = 0;

	safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)",
		rufus_version[0], rufus_version[1], rufus_version[2],
		nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : "");
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL)
		goto out;
	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL)
		goto out;

	status++;	// 2
	releases_only = !ReadSettingBool(SETTING_INCLUDE_BETAS);

	// Test releases get their own distribution channel (and also force beta checks)
#if defined(TEST)
	max_channel = (int)ARRAYSIZE(channel);
#else
	max_channel = releases_only ? 1 : (int)ARRAYSIZE(channel) - 1;
#endif
	for (k=0; (k<max_channel) && (!found_new_version); k++) {
		uprintf("Checking %s channel...\n", channel[k]);
		// At this stage we can query the server for various update version files.
		// We first try to lookup for "<appname>_<os_arch>_<os_version_major>_<os_version_minor>.ver"
		// and then remove each each of the <os_> components until we find our match. For instance, we may first
		// look for rufus_win_x64_6.2.ver (Win8 x64) but only get a match for rufus_win_x64_6.ver (Vista x64 or later)
		// This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups.
		safe_sprintf(urlpath, sizeof(urlpath), "%s%s%s_%s_%d.%d.ver", APPLICATION_NAME, (k==0)?"":"_",
			(k==0)?"":channel[k], archname[is_x64()?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion);
		vuprintf("Base update check: %s\n", urlpath);
		for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) {
			if ((urlpath[j] == '.') || (urlpath[j] == '_')) {
				verpos[i++] = j;
			}
		}
		if (i != ARRAYSIZE(verpos)) {
			uprintf("Broken code in CheckForUpdatesThread()!\n");
			goto out;
		}

		UrlParts.lpszUrlPath = urlpath;
		UrlParts.dwUrlPathLength = sizeof(urlpath);
		for (i=0; i<ARRAYSIZE(verpos); i++) {
			vvuprintf("Trying %s\n", UrlParts.lpszUrlPath);
			hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types,
				INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
				INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
			if ((hRequest == NULL) || (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)))
				goto out;

			// Ensure that we get a text file
			dwSize = sizeof(dwStatus);
			dwStatus = 404;
			HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
			if (dwStatus == 200)
				break;
			InternetCloseHandle(hRequest);
			hRequest = NULL;
			safe_strcpy(&urlpath[verpos[i]], 5, ".ver");
		}
		if (dwStatus != 200) {
			vuprintf("Could not find a %s version file on server %s", channel[k], server_url);
			if ((releases_only) || (k+1 >= ARRAYSIZE(channel)))
				goto out;
			continue;
		}
		vuprintf("Found match for %s on server %s", urlpath, server_url);

		dwSize = sizeof(mime);
		HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_TYPE, (LPVOID)&mime, &dwSize, NULL);
		if (strncmp(mime, "text/plain", sizeof("text/plain")-1) != 0)
			goto out;

		// We also get a date from Apache, which we'll use to avoid out of sync check,
		// in case some set their clock way into the future and back.
		// On the other hand, if local clock is set way back in the past, we will never check.
		dwSize = sizeof(ServerTime);
		// If we can't get a date we can trust, don't bother...
		if ( (!HttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL))
			|| (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
			goto out;
		server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
		vvuprintf("Server time: %" PRId64 "\n", server_time);
		// Always store the server response time - the only clock we trust!
		WriteSetting64(SETTING_LAST_UPDATE, server_time);
		// Might as well let the user know
		if (!force_update_check) {
			if ((local_time > server_time + 600) || (local_time < server_time - 600)) {
				uprintf("IMPORTANT: Your local clock is more than 10 minutes in the %s. Unless you fix this, " APPLICATION_NAME " may not be able to check for updates...",
					(local_time > server_time + 600)?"future":"past");
			}
		}

		dwSize = sizeof(dwTotalSize);
		if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL))
			goto out;

		safe_free(buf);
		// Make sure the file is NUL terminated
		buf = (char*)calloc(dwTotalSize+1, 1);
		if (buf == NULL) goto out;
		// This is a version file - we should be able to gulp it down in one go
		if (!InternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize))
			goto out;

		status++;
		vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize);

		parse_update(buf, dwTotalSize+1);

		vuprintf("UPDATE DATA:\n");
		vuprintf("  version: %d.%d.%d (%s)\n", update.version[0], update.version[1], update.version[2], channel[k]);
		vuprintf("  platform_min: %d.%d\n", update.platform_min[0], update.platform_min[1]);
		vuprintf("  url: %s\n", update.download_url);

		found_new_version = ((to_uint64_t(update.version) > to_uint64_t(rufus_version)) || (force_update))
			&& ( (os_version.dwMajorVersion > update.platform_min[0])
			  || ( (os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) );
		uprintf("N%sew %s version found%c\n", found_new_version?"":"o n", channel[k], found_new_version?'!':'.');
	}

out:
	safe_free(buf);
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);
	switch(status) {
	case 1:
		PrintInfoDebug(3000, MSG_244);
		break;
	case 2:
		PrintInfoDebug(3000, MSG_245);
		break;
	case 3:
	case 4:
		PrintInfo(3000, found_new_version?MSG_246:MSG_247);
	default:
		break;
	}
	// Start the new download after cleanup
	if (found_new_version) {
		// User may have started an operation while we were checking
		while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing>0))) {
			Sleep(15000);
		}
		DownloadNewVersion();
	} else if (force_update_check) {
		PostMessage(hMainDialog, UM_NO_UPDATE, 0, 0);
	}
	force_update_check = FALSE;
	update_check_in_progress = FALSE;
	ExitThread(0);
}
Beispiel #22
0
 void messageln_va(const char* format, va_list args)
 {
     char tm[16];
     safe_sprintf(tm, "%03d ", getTime());
     out_line_prefix(0, tm, format, args);
 }
Beispiel #23
0
/*
 * Refresh the list of USB devices
 */
BOOL GetUSBDevices(DWORD devnum)
{
	// The first two are standard Microsoft drivers (including the Windows 8 UASP one).
	// The rest are the vendor UASP drivers I know of so far - list may be incomplete!
	const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" };
	const char* scsi_name = "SCSI";
	const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" };
	// Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path
	htab_table htab_devid = HTAB_EMPTY;
	StrArray dev_if_path;
	char letter_name[] = " (?:)";
	char uefi_togo_check[] = "?:\\EFI\\Rufus\\ntfs_x64.efi";
	BOOL r = FALSE, found = FALSE, is_SCSI;
	HDEVINFO dev_info = NULL;
	SP_DEVINFO_DATA dev_info_data;
	SP_DEVICE_INTERFACE_DATA devint_data;
	PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data;
	DEVINST parent_inst, grandparent_inst, device_inst;
	DWORD size, i, j, k, l, datatype, drive_index;
	ULONG list_size[ARRAYSIZE(storage_name)] = { 0 }, list_start[ARRAYSIZE(storage_name)] = { 0 }, full_list_size, ulFlags;
	HANDLE hDrive;
	LONG maxwidth = 0;
	int s, score, drive_number, remove_drive;
	char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128];
	char *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str;
	usb_device_props props;

	IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList));
	StrArrayClear(&DriveID);
	StrArrayClear(&DriveLabel);
	StrArrayCreate(&dev_if_path, 128);
	// Add a dummy for string index zero, as this is what non matching hashes will point to
	StrArrayAdd(&dev_if_path, "");

	device_id = (char*)malloc(MAX_PATH);
	if (device_id == NULL)
		goto out;

	// Build a hash table associating a CM Device ID of an USB device with the SetupDI Device Interface Path
	// of its parent hub - this is needed to retrieve the device speed
	dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_USB_HUB, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
	if (dev_info != INVALID_HANDLE_VALUE) {
		if (htab_create(DEVID_HTAB_SIZE, &htab_devid)) {
			dev_info_data.cbSize = sizeof(dev_info_data);
			for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
				if (usb_debug)
					uprintf("Processing Hub %d:", i + 1);
				devint_detail_data = NULL;
				devint_data.cbSize = sizeof(devint_data);
				// Only care about the first interface (MemberIndex 0)
				if ( (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_USB_HUB, 0, &devint_data))
				  && (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) 
				  && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
				  && ((devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size)) != NULL) ) {
					devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
					if (SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) {

						// Find the Device IDs for all the children of this hub
						if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) {
							device_id[0] = 0;
							s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath);
							if (usb_debug)
								uprintf("  Hub[%d] = '%s'", s, devint_detail_data->DevicePath);
							if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) {
								if ((k = htab_hash(device_id, &htab_devid)) != 0) {
									htab_devid.table[k].data = (void*)(uintptr_t)s;
								}
								if (usb_debug)
									uprintf("  Found ID[%03d]: %s", k, device_id);
								while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) {
									device_id[0] = 0;
									if (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS) {
										if ((k = htab_hash(device_id, &htab_devid)) != 0) {
											htab_devid.table[k].data = (void*)(uintptr_t)s;
										}
										if (usb_debug)
											uprintf("  Found ID[%03d]: %s", k, device_id);
									}
								}
							}
						}
					}
					free(devint_detail_data);
				}
			}
		}
		SetupDiDestroyDeviceInfoList(dev_info);
	}
	free(device_id);

	// Build a single list of Device IDs from all the storage enumerators we know of
	full_list_size = 0;
	ulFlags = CM_GETIDLIST_FILTER_SERVICE;
	if (nWindowsVersion >= WINDOWS_7)
		ulFlags |= CM_GETIDLIST_FILTER_PRESENT;
	for (s=0; s<ARRAYSIZE(storage_name); s++) {
		// Get a list of device IDs for all USB storage devices
		// This will be used to find if a device is UASP
		if (CM_Get_Device_ID_List_SizeA(&list_size[s], storage_name[s], ulFlags) != CR_SUCCESS)
			list_size[s] = 0;
		if (list_size[s] != 0)
			full_list_size += list_size[s]-1;	// remove extra NUL terminator
	}
	devid_list = NULL;
	if (full_list_size != 0) {
		full_list_size += 1;	// add extra NUL terminator
		devid_list = (char*)malloc(full_list_size);
		if (devid_list == NULL) {
			uprintf("Could not allocate Device ID list\n");
			return FALSE;
		}
		for (s=0, i=0; s<ARRAYSIZE(storage_name); s++) {
			list_start[s] = i;
			if (list_size[s] > 1) {
				if (CM_Get_Device_ID_ListA(storage_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS)
					continue;
				if (usb_debug) {
					uprintf("Processing IDs belonging to %s:", storage_name[s]);
					for (device_id = &devid_list[i]; *device_id != 0; device_id += strlen(device_id) + 1)
						uprintf("  %s", device_id);
				}
				// The list_size is sometimes larger than required thus we need to find the real end
				for (i += list_size[s]; i > 2; i--) {
					if ((devid_list[i-2] != '\0') && (devid_list[i-1] == '\0') && (devid_list[i] == '\0'))
						break;
				}
			}
		}
	}

	// Now use SetupDi to enumerate all our storage devices
	dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
	if (dev_info == INVALID_HANDLE_VALUE) {
		uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString());
		goto out;
	}
	dev_info_data.cbSize = sizeof(dev_info_data);
	for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
		memset(buffer, 0, sizeof(buffer));
		method_str = "";
		if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME,
				&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
			uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString());
			continue;
		}
		// UASP drives are listed under SCSI (along with regular SYSTEM drives => "DANGER, WILL ROBINSON!!!")
		is_SCSI = (safe_stricmp(buffer, scsi_name) == 0);
		if ((safe_stricmp(buffer, storage_name[0]) != 0) && (!is_SCSI))
			continue;

		// We can't use the friendly name to find if a drive is a VHD, as friendly name string gets translated
		// according to your locale, so we poke the Hardware ID
		memset(&props, 0, sizeof(props));
		memset(buffer, 0, sizeof(buffer));
		props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID,
			&datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsVHD(buffer);
		if (usb_debug)
			uprintf("Processing Device: '%s'", buffer);

		memset(buffer, 0, sizeof(buffer));
		if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME,
				&datatype, (LPBYTE)buffer, sizeof(buffer), &size)) {
			uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString());
			// We can afford a failure on this call - just replace the name with "USB Storage Device (Generic)"
			safe_strcpy(buffer, sizeof(buffer), lmprintf(MSG_045));
		} else if ((!props.is_VHD) && (devid_list != NULL)) {
			// Get the properties of the device. We could avoid doing this lookup every time by keeping
			// a lookup table, but there shouldn't be that many USB storage devices connected...
			// NB: Each of these Device IDs have an _only_ child, from which we get the Device Instance match.
			for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) {
				if ( (CM_Locate_DevNodeA(&parent_inst, device_id, 0) == CR_SUCCESS)
				  && (CM_Get_Child(&device_inst, parent_inst, 0) == CR_SUCCESS)
				  && (device_inst == dev_info_data.DevInst) ) {
					// If we're not dealing with the USBSTOR part of our list, then this is an UASP device
					props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[1]);
					// Now get the properties of the device, and its Device ID, which we need to populate the properties
					j = htab_hash(device_id, &htab_devid);
					if (usb_debug)
						uprintf("  Matched with ID[%03d]: %s", j, device_id);
					// If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0),
					// we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver"
					// for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods)
					// so try to see if we can match the grandparent.
					if ( ((uintptr_t)htab_devid.table[j].data == 0)
					  && (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS)
					  && (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) {
						device_id = str;
						method_str = "[GP]";
						j = htab_hash(device_id, &htab_devid);
						if (usb_debug)
							uprintf("  Matched with (GP) ID[%03d]: %s", j, device_id);
					}
					if ((uintptr_t)htab_devid.table[j].data > 0) {
						if (usb_debug)
							uprintf("  Matched with Hub[%d]: '%s'", (uintptr_t)htab_devid.table[j].data,
								dev_if_path.String[(uintptr_t)htab_devid.table[j].data]);
						GetUSBProperties(dev_if_path.String[(uintptr_t)htab_devid.table[j].data], device_id, &props);
					}
					if (usb_debug)
						uprintf("  Props VID:PID = %04X:%04X", props.vid, props.pid);

					// If previous calls still didn't succeed, try reading the VID:PID from the device_id
					if ((props.vid == 0) && (props.pid == 0)) {
						BOOL post_backslash = FALSE;
						method_str = "[ID]";
						for (j=0, k=0; (j<strlen(device_id))&&(k<2); j++) {
							// The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\...
							if (device_id[j] == '\\')
								post_backslash = TRUE;
							if (!post_backslash)
								continue;
							if (device_id[j] == '_') {
								props.pid = (uint16_t)strtoul(&device_id[j+1], NULL, 16);
								if (k++==0)
									props.vid = props.pid;
							}
						}
					}
					break;
				}
			}
		}
		if (props.is_VHD) {
			uprintf("Found VHD device '%s'", buffer);
		} else {
			if ((props.vid == 0) && (props.pid == 0)) {
				if (is_SCSI) {
					// If we have an SCSI drive and couldn't get a VID:PID, we are most likely
					// dealing with a system drive => eliminate it!
					if (usb_debug)
						uprintf("  Non USB => Eliminated");
					continue;
				}
				safe_strcpy(str, sizeof(str), "????:????");	// Couldn't figure VID:PID
			} else {
				static_sprintf(str, "%04X:%04X", props.vid, props.pid);
			}
			if (props.speed >= USB_SPEED_MAX)
				props.speed = 0;
			uprintf("Found %s%s%s device '%s' (%s) %s\n", props.is_UASP?"UAS (":"", 
				usb_speed_name[props.speed], props.is_UASP?")":"", buffer, str, method_str);
			if (props.is_LowerSpeed)
				uprintf("NOTE: This device is an USB 3.0 device operating at lower speed...");
		}
		devint_data.cbSize = sizeof(devint_data);
		hDrive = INVALID_HANDLE_VALUE;
		devint_detail_data = NULL;
		for (j=0; ;j++) {
			safe_closehandle(hDrive);
			safe_free(devint_detail_data);

			if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) {
				if(GetLastError() != ERROR_NO_MORE_ITEMS) {
					uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString());
				} else {
					uprintf("A device was eliminated because it didn't report itself as a disk\n");
				}
				break;
			}

			if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) {
				if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
					devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size);
					if (devint_detail_data == NULL) {
						uprintf("Unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n");
						continue;
					}
					devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
				} else {
					uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString());
					continue;
				}
			}
			if (devint_detail_data == NULL) {
				uprintf("SetupDiGetDeviceInterfaceDetail (dummy) - no data was allocated\n");
				continue;
			}
			if(!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) {
				uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString());
				continue;
			}

			hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ,
				NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
			if(hDrive == INVALID_HANDLE_VALUE) {
				uprintf("Could not open '%s': %s\n", devint_detail_data->DevicePath, WindowsErrorString());
				continue;
			}

			drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath);
			if (drive_number < 0)
				continue;

			drive_index = drive_number + DRIVE_INDEX_MIN;
			if (!IsMediaPresent(drive_index)) {
				uprintf("Device eliminated because it appears to contain no media\n");
				safe_closehandle(hDrive);
				safe_free(devint_detail_data);
				break;
			}

			if (GetDriveLabel(drive_index, drive_letters, &label)) {
				if ((!enable_HDDs) && (!props.is_VHD) &&
					((score = IsHDD(drive_index, (uint16_t)props.vid, (uint16_t)props.pid, buffer)) > 0)) {
					uprintf("Device eliminated because it was detected as an USB Hard Drive (score %d > 0)\n", score);
					uprintf("If this device is not an USB Hard Drive, please e-mail the author of this application\n");
					uprintf("NOTE: You can enable the listing of USB Hard Drives in 'Advanced Options' (after clicking the white triangle)");
					safe_closehandle(hDrive);
					safe_free(devint_detail_data);
					break;
				}

				// The empty string is returned for drives that don't have any volumes assigned
				if (drive_letters[0] == 0) {
					entry = lmprintf(MSG_046, label, drive_number,
						SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units));
				} else {
					// Find the UEFI:TOGO partition(s) (and eliminate them form our listing)
					for (k=0; drive_letters[k]; k++) {
						uefi_togo_check[0] = drive_letters[k];
						if (PathFileExistsA(uefi_togo_check)) {
							for (l=k; drive_letters[l]; l++)
								drive_letters[l] = drive_letters[l+1];
							k--;
						}
					}
					// We have multiple volumes assigned to the same device (multiple partitions)
					// If that is the case, use "Multiple Volumes" instead of the label
					safe_strcpy(entry_msg, sizeof(entry_msg), (((drive_letters[0] != 0) && (drive_letters[1] != 0))?
						lmprintf(MSG_047):label));
					for (k=0, remove_drive=0; drive_letters[k] && (!remove_drive); k++) {
						// Append all the drive letters we detected
						letter_name[2] = drive_letters[k];
						if (right_to_left_mode)
							safe_strcat(entry_msg, sizeof(entry_msg), RIGHT_TO_LEFT_MARK);
						safe_strcat(entry_msg, sizeof(entry_msg), letter_name);
						if (drive_letters[k] == (PathGetDriveNumberU(app_dir) + 'A'))
							remove_drive = 1;
						if (drive_letters[k] == (PathGetDriveNumberU(system_dir) + 'A'))
							remove_drive = 2;
					}
					// Make sure that we don't list any drive that should not be listed
					if (remove_drive) {
						uprintf("Removing %C: from the list: This is the %s!", drive_letters[--k],
							(remove_drive==1)?"disk from which " APPLICATION_NAME " is running":"system disk");
						safe_closehandle(hDrive);
						safe_free(devint_detail_data);
						break;
					}
					safe_sprintf(&entry_msg[strlen(entry_msg)], sizeof(entry_msg) - strlen(entry_msg),
						"%s [%s]", (right_to_left_mode)?RIGHT_TO_LEFT_MARK:"", SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units));
					entry = entry_msg;
				}

				// Must ensure that the combo box is UNSORTED for indexes to be the same
				StrArrayAdd(&DriveID, buffer);
				StrArrayAdd(&DriveLabel, label);

				IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index));
				maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry));
				safe_closehandle(hDrive);
				safe_free(devint_detail_data);
				break;
			}
		}
	}
	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) {
				found = TRUE;
				break;
			}
		}
	}
	if (!found)
		i = 0;
	IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, i));
	SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0);
	SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM,
		ComboBox_GetCurSel(hFileSystem));
	r = TRUE;

out:
	// Set 'Start' as the selected button, so that tab selection works
	SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDC_START), TRUE);
	safe_free(devid_list);
	StrArrayDestroy(&dev_if_path);
	htab_destroy(&htab_devid);
	return r;
}
Beispiel #24
0
/*
 * Returns the first drive letter for a volume located on the drive identified by DriveIndex
 */
char GetDriveLetter(DWORD DriveIndex)
{
	DWORD size;
	BOOL r;
	STORAGE_DEVICE_NUMBER_REDEF device_number = {0};
	UINT drive_type;
	HANDLE hDrive = INVALID_HANDLE_VALUE;
	char *drive, drives[26*4];	/* "D:\", "E:\", etc. */
	char logical_drive[] = "\\\\.\\#:";
	char drive_letter = ' ';
	CheckDriveIndex(DriveIndex);

	size = GetLogicalDriveStringsA(sizeof(drives), drives);
	if (size == 0) {
		uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
		goto out;
	}
	if (size > sizeof(drives)) {
		uprintf("GetLogicalDriveStrings: buffer too small (required %d vs %d)\n", size, sizeof(drives));
		goto out;
	}

	for (drive = drives ;*drive; drive += safe_strlen(drive)+1) {
		if (!isalpha(*drive))
			continue;
		*drive = (char)toupper((int)*drive);
		if (*drive < 'C') {
			continue;
		}

		/* IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
			not unique! An HDD, a DVD and probably other drives can have the same
			value there => Use GetDriveType() to filter out unwanted devices.
			See https://github.com/pbatard/rufus/issues/32 for details. */
		drive_type = GetDriveTypeA(drive);
		// NB: the HP utility allows drive_type == DRIVE_FIXED, which we don't allow by default
		// Using Alt-F in Rufus does enable listing, but this mode is unsupported.
		if ((drive_type != DRIVE_REMOVABLE) && ((!enable_fixed_disks) || (drive_type != DRIVE_FIXED)))
			continue;

		safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
		hDrive = CreateFileA(logical_drive, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
		if (hDrive == INVALID_HANDLE_VALUE) {
			uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
			continue;
		}

		r = DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL,
			0, &device_number, sizeof(device_number), &size, NULL);
		safe_closehandle(hDrive);
		if ((!r) || (size <= 0)) {
			uprintf("Could not get device number for device %s: %s\n",
				logical_drive, WindowsErrorString());
		} else if (device_number.DeviceNumber == DriveIndex) {
			drive_letter = *drive;
			break;
		}
	}

out:
	return drive_letter;
}
Beispiel #25
0
/*
 * Returns the drive letters for all volumes located on the drive identified by DriveIndex,
 * as well as the drive type. This is used as base for the 2 function calls that follow.
 */
static BOOL _GetDriveLettersAndType(DWORD DriveIndex, char* drive_letters, UINT* drive_type)
{
	DWORD size;
	BOOL r = FALSE;
	HANDLE hDrive = INVALID_HANDLE_VALUE;
	UINT _drive_type;
	int i = 0, drive_number;
	char *drive, drives[26*4 + 1];	/* "D:\", "E:\", etc., plus one NUL */
	char logical_drive[] = "\\\\.\\#:";

	if (drive_letters != NULL)
		drive_letters[0] = 0;
	if (drive_type != NULL)
		*drive_type = DRIVE_UNKNOWN;
	CheckDriveIndex(DriveIndex);

	// This call is weird... The buffer needs to have an extra NUL, but you're
	// supposed to provide the size without the extra NUL. And the returned size
	// does not include the NUL either *EXCEPT* if your buffer is too small...
	// But then again, this doesn't hold true if you have a 105 byte buffer and
	// pass a 4*26=104 size, as the the call will return 105 (i.e. *FAILURE*)
	// instead of 104 as it should => screw Microsoft: We'll include the NUL
	// always, as each drive string is at least 4 chars long anyway.
	size = GetLogicalDriveStringsA(sizeof(drives), drives);
	if (size == 0) {
		uprintf("GetLogicalDriveStrings failed: %s\n", WindowsErrorString());
		goto out;
	}
	if (size > sizeof(drives)) {
		uprintf("GetLogicalDriveStrings: Buffer too small (required %d vs. %d)\n", size, sizeof(drives));
		goto out;
	}

	r = TRUE;	// Required to detect drives that don't have volumes assigned
	for (drive = drives ;*drive; drive += safe_strlen(drive)+1) {
		if (!isalpha(*drive))
			continue;
		*drive = (char)toupper((int)*drive);
		if (*drive < 'C') {
			continue;
		}

		// IOCTL_STORAGE_GET_DEVICE_NUMBER's STORAGE_DEVICE_NUMBER.DeviceNumber is
		// not unique! An HDD, a DVD and probably other drives can have the same
		// value there => Use GetDriveType() to filter out unwanted devices.
		// See https://github.com/pbatard/rufus/issues/32#issuecomment-3785956
		_drive_type = GetDriveTypeA(drive);

		if ((_drive_type != DRIVE_REMOVABLE) && (_drive_type != DRIVE_FIXED))
			continue;

		safe_sprintf(logical_drive, sizeof(logical_drive), "\\\\.\\%c:", drive[0]);
		hDrive = CreateFileA(logical_drive, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
			NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
		if (hDrive == INVALID_HANDLE_VALUE) {
//			uprintf("Warning: could not open drive %c: %s\n", drive[0], WindowsErrorString());
			continue;
		}

		drive_number = GetDriveNumber(hDrive, logical_drive);
		safe_closehandle(hDrive);
		if (drive_number == DriveIndex) {
			r = TRUE;
			if (drive_letters != NULL)
				drive_letters[i++] = *drive;
			// The drive type should be the same for all volumes, so we can overwrite
			if (drive_type != NULL)
				*drive_type = _drive_type;
		}
	}

out:
	if (drive_letters != NULL)
		drive_letters[i] = 0;
	return r;
}
Beispiel #26
0
Datei: iso.c Projekt: hanji/rufus
// Returns 0 on success, nonzero on error
static int udf_extract_files(udf_t *p_udf, udf_dirent_t *p_udf_dirent, const char *psz_path)
{
	HANDLE file_handle = NULL;
	DWORD buf_size, wr_size;
	BOOL r, is_syslinux_cfg, is_old_vesamenu;
	int i_length;
	size_t i, nul_pos;
	char* psz_fullpath = NULL;
	const char* psz_basename;
	udf_dirent_t *p_udf_dirent2;
	uint8_t buf[UDF_BLOCKSIZE];
	int64_t i_read, i_file_length;

	if ((p_udf_dirent == NULL) || (psz_path == NULL))
		return 1;

	while ((p_udf_dirent = udf_readdir(p_udf_dirent)) != NULL) {
		if (FormatStatus) goto out;
		psz_basename = udf_get_filename(p_udf_dirent);
		i_length = (int)(3 + strlen(psz_path) + strlen(psz_basename) + strlen(psz_extract_dir) + 24);
		psz_fullpath = (char*)calloc(sizeof(char), i_length);
		if (psz_fullpath == NULL) {
			uprintf("Error allocating file name\n");
			goto out;
		}
		i_length = safe_sprintf(psz_fullpath, i_length, "%s%s/%s", psz_extract_dir, psz_path, psz_basename);
		if (i_length < 0) {
			goto out;
		}
		if (udf_is_dir(p_udf_dirent)) {
			if (!scan_only) _mkdirU(psz_fullpath);
			p_udf_dirent2 = udf_opendir(p_udf_dirent);
			if (p_udf_dirent2 != NULL) {
				if (udf_extract_files(p_udf, p_udf_dirent2, &psz_fullpath[strlen(psz_extract_dir)]))
					goto out;
			}
		} else {
			i_file_length = udf_get_file_length(p_udf_dirent);
			if (check_iso_props(psz_path, &is_syslinux_cfg, &is_old_vesamenu, i_file_length, psz_basename, psz_fullpath)) {
				safe_free(psz_fullpath);
				continue;
			}
			// Replace slashes with backslashes and append the size to the path for UI display
			nul_pos = safe_strlen(psz_fullpath);
			for (i=0; i<nul_pos; i++) if (psz_fullpath[i] == '/') psz_fullpath[i] = '\\';
			safe_strcpy(&psz_fullpath[nul_pos], 24, size_to_hr(i_file_length));
			uprintf("Extracting: %s\n", psz_fullpath);
			SetWindowTextU(hISOFileName, psz_fullpath);
			// Remove the appended size for extraction
			psz_fullpath[nul_pos] = 0;
			if (is_old_vesamenu && use_own_vesamenu) {
				if (CopyFileA("vesamenu.c32", psz_fullpath, FALSE)) {
					uprintf("  Replaced with local version\n");
					continue;
				}
				uprintf("  Could not replace file: %s\n", WindowsErrorString());
			}
			file_handle = CreateFileU(psz_fullpath, GENERIC_READ | GENERIC_WRITE,
				FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
			if (file_handle == INVALID_HANDLE_VALUE) {
				uprintf("  Unable to create file: %s\n", WindowsErrorString());
				goto out;
			}
			while (i_file_length > 0) {
				if (FormatStatus) goto out;
				memset(buf, 0, UDF_BLOCKSIZE);
				i_read = udf_read_block(p_udf_dirent, buf, 1);
				if (i_read < 0) {
					uprintf("  Error reading UDF file %s\n", &psz_fullpath[strlen(psz_extract_dir)]);
					goto out;
				}
				buf_size = (DWORD)MIN(i_file_length, i_read);
				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());
					goto out;
				}
				i_file_length -= i_read;
				if (nb_blocks++ % PROGRESS_THRESHOLD == 0) {
					SendMessage(hISOProgressBar, PBM_SETPOS, (WPARAM)((MAX_PROGRESS*nb_blocks)/total_blocks), 0);
					UpdateProgress(OP_DOS, 100.0f*nb_blocks/total_blocks);
				}
			}
			// If you have a fast USB 3.0 device, the default Windows buffering does an
			// excellent job at compensating for our small blocks read/writes to max out the
			// device's bandwidth.
			// 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, TRUE) != NULL)
					uprintf("Patched %s: '%s' -> '%s'\n", psz_fullpath, iso_report.label, iso_report.usb_label);
			}
		}
		safe_free(psz_fullpath);
	}
	return 0;

out:
	if (p_udf_dirent != NULL)
		udf_dirent_free(p_udf_dirent);
	ISO_BLOCKING(safe_closehandle(file_handle));
	safe_free(psz_fullpath);
	return 1;
}