📄 os_win32.cpp
字号:
sb.regs = *regs; sb.regs.bReserved = port; DWORD num_out; if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT, &sb, sizeof(sb), &sb, sizeof(sb), &num_out, NULL)) { long err = GetLastError(); if (con->reportataioctl) { pout(" ATA via IOCTL_SCSI_MINIPORT failed, Error=%ld\n", err); print_ide_regs_io(regs, NULL); } errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO); return -1; } if (sb.srbc.ReturnCode) { if (con->reportataioctl) { pout(" ATA via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08lx\n", sb.srbc.ReturnCode); print_ide_regs_io(regs, NULL); } errno = EIO; return -1; } // Copy data if (datasize > 0) memcpy(data, sb.buffer, datasize); if (con->reportataioctl > 1) { pout(" ATA via IOCTL_SCSI_MINIPORT suceeded, bytes returned: %lu\n", num_out); print_ide_regs_io(regs, &sb.regs); } *regs = sb.regs; return 0;}/////////////////////////////////////////////////////////////////////////////// 3ware specific call to update the devicemap returned by SMART_GET_VERSION.// 3DM/CLI "Rescan Controller" function does not to always update it.static int update_3ware_devicemap_ioctl(HANDLE hdevice){ SRB_IO_CONTROL srbc; memset(&srbc, 0, sizeof(srbc)); strcpy((char *)srbc.Signature, "<3ware>"); srbc.HeaderLength = sizeof(SRB_IO_CONTROL); srbc.Timeout = 60; // seconds srbc.ControlCode = 0xCC010014; srbc.ReturnCode = 0; srbc.Length = 0; DWORD num_out; if (!DeviceIoControl(hdevice, IOCTL_SCSI_MINIPORT, &srbc, sizeof(srbc), &srbc, sizeof(srbc), &num_out, NULL)) { long err = GetLastError(); if (con->reportataioctl) pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, Error=%ld\n", err); errno = (err == ERROR_INVALID_FUNCTION ? ENOSYS : EIO); return -1; } if (srbc.ReturnCode) { if (con->reportataioctl) pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08lx\n", srbc.ReturnCode); errno = EIO; return -1; } if (con->reportataioctl > 1) pout(" UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT suceeded\n"); return 0;}/////////////////////////////////////////////////////////////////////////////// Routines for pseudo device /dev/tw_cli/*// Parses output of 3ware "tw_cli /cx/py show all" or 3DM SMART data window// Get clipboard datastatic int get_clipboard(char * data, int datasize){ if (!OpenClipboard(NULL)) return -1; HANDLE h = GetClipboardData(CF_TEXT); if (!h) { CloseClipboard(); return 0; } const void * p = GlobalLock(h); int n = GlobalSize(h); if (n > datasize) n = datasize; memcpy(data, p, n); GlobalFree(h); CloseClipboard(); return n;}// Run a command, write stdout to dataout// TODO: Combine with daemon_win32.cpp:daemon_spawn()static int run_cmd(const char * cmd, char * dataout, int outsize){ // Create stdout pipe SECURITY_ATTRIBUTES sa = {sizeof(sa), 0, TRUE}; HANDLE pipe_out_w, h; if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) return -1; HANDLE self = GetCurrentProcess(); HANDLE pipe_out_r; if (!DuplicateHandle(self, h, self, &pipe_out_r, GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) { CloseHandle(pipe_out_w); return -1; } HANDLE pipe_err_w; if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w, 0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) { CloseHandle(pipe_out_r); CloseHandle(pipe_out_w); return -1; } // Create process STARTUPINFO si; memset(&si, 0, sizeof(si)); si.cb = sizeof(si); si.hStdInput = INVALID_HANDLE_VALUE; si.hStdOutput = pipe_out_w; si.hStdError = pipe_err_w; si.dwFlags = STARTF_USESTDHANDLES; PROCESS_INFORMATION pi; if (!CreateProcess( NULL, const_cast<char *>(cmd), NULL, NULL, TRUE/*inherit*/, CREATE_NO_WINDOW/*do not create a new console window*/, NULL, NULL, &si, &pi)) { CloseHandle(pipe_err_w); CloseHandle(pipe_out_r); CloseHandle(pipe_out_w); return -1; } CloseHandle(pi.hThread); CloseHandle(pipe_err_w); CloseHandle(pipe_out_w); // Copy stdout to output buffer int i = 0; while (i < outsize) { DWORD num_read; if (!ReadFile(pipe_out_r, dataout+i, outsize-i, &num_read, NULL) || num_read == 0) break; i += num_read; } CloseHandle(pipe_out_r); // Wait for process WaitForSingleObject(pi.hProcess, INFINITE); CloseHandle(pi.hProcess); return i;}static const char * findstr(const char * str, const char * sub){ const char * s = strstr(str, sub); return (s ? s+strlen(sub) : "");}static void copy_swapped(unsigned char * dest, const char * src, int destsize){ int srclen = strcspn(src, "\r\n"); int i; for (i = 0; i < destsize-1 && i < srclen-1; i+=2) { dest[i] = src[i+1]; dest[i+1] = src[i]; } if (i < destsize-1 && i < srclen) dest[i+1] = src[i];}static ata_identify_device * tw_cli_identbuf = 0;static ata_smart_values * tw_cli_smartbuf = 0;static int tw_cli_open(const char * name){ // Read tw_cli or 3DM browser output into buffer char buffer[4096]; int size = -1, n1 = -1; if (!strcmp(name, "clip")) { // tw_cli/clip => read clipboard size = get_clipboard(buffer, sizeof(buffer)); } else if (!strcmp(name, "stdin")) { // tw_cli/stdin => read stdin size = fread(buffer, 1, sizeof(buffer), stdin); } else if (sscanf(name, "c%*u/p%*u%n", &n1) >= 0 && n1 == (int)strlen(name)) { // tw_cli/cx/py => read output from "tw_cli /cx/py show all" char cmd[100]; snprintf(cmd, sizeof(cmd), "tw_cli /%s show all", name); if (con->reportataioctl > 1) pout("tw_cli/%s: Run: \"%s\"\n", name, cmd); size = run_cmd(cmd, buffer, sizeof(buffer)); } else { errno = EINVAL; return -1; } if (con->reportataioctl > 1) pout("tw_cli/%s: Read %d bytes\n", name, size); if (size <= 0) { errno = ENOENT; return -1; } if (size >= (int)sizeof(buffer)) { errno = EIO; return -1; } buffer[size] = 0; if (con->reportataioctl > 1) pout("[\n%.100s%s\n]\n", buffer, (size>100?"...":"")); // Fake identify sector ASSERT_SIZEOF(ata_identify_device, 512); ata_identify_device * id = (ata_identify_device *)malloc(sizeof(ata_identify_device)); memset(id, 0, sizeof(*id)); copy_swapped(id->model , findstr(buffer, " Model = " ), sizeof(id->model)); copy_swapped(id->fw_rev , findstr(buffer, " Firmware Version = "), sizeof(id->fw_rev)); copy_swapped(id->serial_no, findstr(buffer, " Serial = " ), sizeof(id->serial_no)); unsigned long nblocks = 0; // "Capacity = N.N GB (N Blocks)" sscanf(findstr(buffer, "Capacity = "), "%*[^(\r\n](%lu", &nblocks); if (nblocks) { id->words047_079[49-47] = 0x0200; // size valid id->words047_079[60-47] = (unsigned short)(nblocks ); // secs_16 id->words047_079[61-47] = (unsigned short)(nblocks>>16); // secs_32 } id->major_rev_num = 0x1<<3; // ATA-3 id->command_set_1 = 0x0001; id->command_set_2 = 0x4000; // SMART supported, words 82,83 valid id->cfs_enable_1 = 0x0001; id->csf_default = 0x4000; // SMART enabled, words 85,87 valid // Parse smart data hex dump const char * s = findstr(buffer, "Drive Smart Data:"); if (!*s) { s = findstr(buffer, "S.M.A.R.T. (Controller"); // from 3DM browser window if (*s) { const char * s1 = findstr(s, "<td class"); // html version if (*s1) s = s1; s += strcspn(s, "\r\n"); } else s = buffer; // try raw hex dump without header } unsigned char * sd = (unsigned char *)malloc(512); int i = 0; for (;;) { unsigned x = ~0; int n = -1; if (!(sscanf(s, "%x %n", &x, &n) == 1 && !(x & ~0xff))) break; sd[i] = (unsigned char)x; if (!(++i < 512 && n > 0)) break; s += n; if (*s == '<') // "<br>" s += strcspn(s, "\r\n"); } if (i < 512) { free(sd); if (!id->model[1]) { // No useful data found free(id); char * err = strstr(buffer, "Error:"); if (!err) err = strstr(buffer, "error :"); if (err) { // Print tw_cli error message err[strcspn(err, "\r\n")] = 0; pout("%s\n", err); } errno = EIO; return -1; } sd = 0; } tw_cli_identbuf = id; tw_cli_smartbuf = (ata_smart_values *)sd; return TW_CLI_FDOFFSET;}static void tw_cli_close(){ if (tw_cli_identbuf) { free(tw_cli_identbuf); tw_cli_identbuf = 0; } if (tw_cli_smartbuf) { free(tw_cli_smartbuf); tw_cli_smartbuf = 0; }}static int tw_cli_command_interface(smart_command_set command, int /*select*/, char * data){ switch (command) { case IDENTIFY: if (!tw_cli_identbuf) break; memcpy(data, tw_cli_identbuf, 512); return 0; case READ_VALUES: if (!tw_cli_smartbuf) break; memcpy(data, tw_cli_smartbuf, 512); return 0; case READ_THRESHOLDS: if (!tw_cli_smartbuf) break; // Fake zero thresholds { const ata_smart_values * sv = tw_cli_smartbuf; ata_smart_thresholds_pvt * tr = (ata_smart_thresholds_pvt *)data; memset(tr, 0, 512); // TODO: Indicate missing thresholds in ataprint.cpp:PrintSmartAttribWithThres() // (ATA_SMART_READ_THRESHOLDS is marked obsolete since ATA-5) for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) tr->chksum -= tr->thres_entries[i].id = sv->vendor_attributes[i].id; } return 0; case ENABLE: case STATUS: case STATUS_CHECK: // Fake "good" SMART status return 0; default: break; } // Arrive here for all unsupported commands errno = ENOSYS; return -1;}/////////////////////////////////////////////////////////////////////////////// IOCTL_STORAGE_QUERY_PROPERTY#define FILE_DEVICE_MASS_STORAGE 0x0000002d#define IOCTL_STORAGE_BASE FILE_DEVICE_MASS_STORAGE#define FILE_ANY_ACCESS 0#define IOCTL_STORAGE_QUERY_PROPERTY \ CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)typedef enum _STORAGE_BUS_TYPE { BusTypeUnknown = 0x00, BusTypeScsi = 0x01, BusTypeAtapi = 0x02, BusTypeAta = 0x03, BusType1394 = 0x04, BusTypeSsa = 0x05, BusTypeFibre = 0x06, BusTypeUsb = 0x07, BusTypeRAID = 0x08, BusTypeiScsi = 0x09, BusTypeSas = 0x0A, BusTypeSata = 0x0B, BusTypeSd = 0x0C, BusTypeMmc = 0x0D, BusTypeMax = 0x0E, BusTypeMaxReserved = 0x7F} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;typedef struct _STORAGE_DEVICE_DESCRIPTOR { ULONG Version; ULONG Size; UCHAR DeviceType; UCHAR DeviceTypeModifier; BOOLEAN RemovableMedia; BOOLEAN CommandQueueing; ULONG VendorIdOffset; ULONG ProductIdOffset; ULONG ProductRevisionOffset; ULONG SerialNumberOffset; STORAGE_BUS_TYPE BusType; ULONG RawPropertiesLength; UCHAR RawDeviceProperties[1];} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;typedef enum _STORAGE_QUERY_TYPE { PropertyStandardQuery = 0, PropertyExistsQuery, PropertyMaskQuery, PropertyQueryMaxDefined} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;typedef enum _STORAGE_PROPERTY_ID { StorageDeviceProperty = 0, StorageAdapterProperty, StorageDeviceIdProperty, StorageDeviceUniqueIdProperty, StorageDeviceWriteCacheProperty, StorageMiniportProperty, StorageAccessAlignmentProperty} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;typedef struct _STORAGE_PROPERTY_QUERY { STORAGE_PROPERTY_ID PropertyId; STORAGE_QUERY_TYPE QueryType; UCHAR AdditionalParameters[1];} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;/////////////////////////////////////////////////////////////////////////////union STORAGE_DEVICE_DESCRIPTOR_DATA { STORAGE_DEVICE_DESCRIPTOR desc; char raw[256];};// Get STORAGE_DEVICE_DESCRIPTOR_DATA for device.// (This works without admin rights)static int storage_query_property_ioctl(HANDLE hdevice, STORAGE_DEVICE_DESCRIPTOR_DATA * data){ STORAGE_PROPERTY_QUERY query = {StorageDeviceProperty, PropertyStandardQuery, 0}; memset(data, 0, sizeof(*data)); DWORD num_out; if (!DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -