SysInfoXML.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include <windows.h>
  2. #include <stddef.h> // for offsetof
  3. #include <winioctl.h>
  4. #include <strsafe.h>
  5. typedef struct {
  6. USHORT Length;
  7. UCHAR ScsiStatus;
  8. UCHAR PathId;
  9. UCHAR TargetId;
  10. UCHAR Lun;
  11. UCHAR CdbLength;
  12. UCHAR SenseInfoLength;
  13. UCHAR DataIn;
  14. ULONG DataTransferLength;
  15. ULONG TimeOutValue;
  16. PVOID DataBuffer;
  17. ULONG SenseInfoOffset;
  18. UCHAR Cdb[16];
  19. } SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
  20. typedef struct {
  21. SCSI_PASS_THROUGH_DIRECT spt;
  22. ULONG Filler;
  23. UCHAR ucSenseBuf[32];
  24. } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
  25. #define IOCTL_SCSI_BASE 0x00000004
  26. /*
  27. * constants for DataIn member of SCSI_PASS_THROUGH* structures
  28. */
  29. #define SCSI_IOCTL_DATA_OUT 0
  30. #define SCSI_IOCTL_DATA_IN 1
  31. #define SCSI_IOCTL_DATA_UNSPECIFIED 2
  32. /*
  33. * Standard IOCTL define
  34. */
  35. #define CTL_CODE( DevType, Function, Method, Access ) ( \
  36. ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
  37. )
  38. #define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
  39. #define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
  40. #define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
  41. #define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
  42. #define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
  43. #define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS
  44. static bool scsi_inquiry(HANDLE deviceHandle, UCHAR page, UCHAR *inqbuf, size_t &buf_len)
  45. {
  46. char buf[2048] = {0};
  47. BOOL status;
  48. PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER pswb;
  49. DWORD length=0, returned=0;
  50. /*
  51. * Get the drive inquiry data
  52. */
  53. ZeroMemory( &buf, 2048 );
  54. ZeroMemory( inqbuf, buf_len );
  55. pswb = (PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)buf;
  56. pswb->spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
  57. pswb->spt.CdbLength = 6;
  58. pswb->spt.SenseInfoLength = 32;
  59. pswb->spt.DataIn = SCSI_IOCTL_DATA_IN;
  60. pswb->spt.DataTransferLength = buf_len;
  61. pswb->spt.TimeOutValue = 2;
  62. pswb->spt.DataBuffer = inqbuf;
  63. pswb->spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
  64. pswb->spt.Cdb[0] = 0x12;
  65. pswb->spt.Cdb[1] = 0x1;
  66. pswb->spt.Cdb[2] = page;
  67. pswb->spt.Cdb[4] = (UCHAR)buf_len;
  68. length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
  69. status = DeviceIoControl( deviceHandle,
  70. IOCTL_SCSI_PASS_THROUGH_DIRECT,
  71. pswb,
  72. length,
  73. pswb,
  74. length,
  75. &returned,
  76. NULL );
  77. if (status && returned >3)
  78. {
  79. buf_len=returned;
  80. return true;
  81. }
  82. else
  83. {
  84. buf_len=0;
  85. return false;
  86. }
  87. }
  88. static bool AddPagetoXML(HANDLE dev, char *&dest, size_t &destlen, UCHAR page)
  89. {
  90. UCHAR buf[256] = {0};
  91. size_t buflen=255;
  92. if (scsi_inquiry(dev, page, buf, buflen))
  93. {
  94. size_t len = buf[3];
  95. StringCchCopyNExA(dest, destlen, (char *)buf+4, len, &dest, &destlen, 0);
  96. return true;
  97. }
  98. return false;
  99. }
  100. static bool BuildXML(HANDLE dev, char *xml, size_t xmllen)
  101. {
  102. *xml=0;
  103. UCHAR pages[255] = {0};
  104. size_t pageslen=255;
  105. if (scsi_inquiry(dev, 0xc0, pages, pageslen) && pageslen>3)
  106. {
  107. unsigned char numPages=pages[3];
  108. if (numPages+4 <= 255)
  109. {
  110. for (int i=0;i<numPages;i++)
  111. {
  112. if (!AddPagetoXML(dev, xml, xmllen, pages[i+4]))
  113. return false;
  114. }
  115. }
  116. }
  117. return true;
  118. }
  119. bool ParseSysInfoXML(wchar_t drive_letter, char * xml, int xmllen)
  120. {
  121. wchar_t fn[MAX_PATH] = {0};
  122. StringCchPrintf(fn, MAX_PATH, L"\\\\.\\%c:", drive_letter);
  123. HANDLE hfile = CreateFileW(fn, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
  124. if (hfile != INVALID_HANDLE_VALUE)
  125. {
  126. bool ret = BuildXML(hfile, xml, xmllen);
  127. CloseHandle(hfile);
  128. return ret;
  129. }
  130. return false;
  131. }