|
|
1.1 root 1: #include <windows.h>
2: #include <devioctl.h>
3: #include <ntdddisk.h>
4: #include <ntddscsi.h>
5: #include <stdio.h>
6: #include <stddef.h>
7: #include <stdlib.h>
8: #include "spti.h"
9:
10: VOID
11: main(
12: int argc,
13: char *argv[]
14: )
15:
16: {
17: BOOLEAN status;
18: DWORD accessMode,
19: shareMode;
20: HANDLE fileHandle;
21: IO_SCSI_CAPABILITIES capabilities;
22: PUCHAR dataBuffer;
23: SCSI_PASS_THROUGH_WITH_BUFFERS sptwb;
24: SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sptdwb;
25: UCHAR buffer[2048];
26: UCHAR string[25];
27: ULONG length,
28: errorCode,
29: returned,
30: sectorSize = 512;
31:
32: if ((argc < 2) || (argc > 3)) {
33: printf("Usage: %s <port-name> [-mode]\n", argv[0] );
34: printf("Examples:\n");
35: printf(" spti g: (open the SCSI disk class driver in SHARED READ/WRITE mode)\n");
36: printf(" spti Scsi2: (open the SCSI miniport driver for the 3rd host adapter)\n");
37: printf(" spti Tape0 w (open the SCSI tape class driver in SHARED WRITE mode)\n");
38: printf(" spti i: c (open the SCSI CD-ROM class driver in SHARED READ mode)\n");
39: return;
40: }
41:
42: strcpy(string,"\\\\.\\");
43: strcat(string,argv[1]);
44:
45: shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; // default
46: accessMode = GENERIC_WRITE | GENERIC_READ; // default
47:
48: if (argc == 3) {
49: if (!stricmp("r", argv[2])) {
50: shareMode = FILE_SHARE_READ;
51: accessMode = GENERIC_READ;
52: }
53: if (!stricmp("w", argv[2])) {
54: shareMode = FILE_SHARE_WRITE;
55: accessMode = GENERIC_WRITE;
56: }
57: if (!stricmp("c",argv[2])) {
58: shareMode = FILE_SHARE_READ;
59: accessMode = GENERIC_READ;
60: sectorSize = 2048;
61: }
62: }
63:
64: fileHandle = CreateFile(string,
65: accessMode,
66: shareMode,
67: NULL,
68: OPEN_EXISTING,
69: 0,
70: NULL);
71:
72: if (fileHandle == INVALID_HANDLE_VALUE) {
73: printf("Error opening %s. Error: %d\n",
74: argv[1], errorCode = GetLastError());
75: PrintError(errorCode);
76: return;
77: }
78:
79: //
80: // Get the inquiry data.
81: //
82:
83: status = DeviceIoControl(fileHandle,
84: IOCTL_SCSI_GET_INQUIRY_DATA,
85: NULL,
86: 0,
87: buffer,
88: sizeof(buffer),
89: &returned,
90: FALSE);
91:
92: if (!status) {
93: printf( "Error reading inquiry data information; error was %d\n",
94: errorCode = GetLastError());
95: PrintError(errorCode);
96: return;
97: }
98:
99: printf("Read %Xh bytes of inquiry data Information.\n\n",returned);
100:
101: PrintInquiryData(buffer);
102:
103: //
104: // Get the capabilities structure.
105: //
106:
107: status = DeviceIoControl(fileHandle,
108: IOCTL_SCSI_GET_CAPABILITIES,
109: NULL,
110: 0,
111: &capabilities,
112: sizeof(IO_SCSI_CAPABILITIES),
113: &returned,
114: FALSE);
115:
116: if (!status ) {
117: printf( "Error in io control; error was %d\n",
118: errorCode = GetLastError() );
119: PrintError(errorCode);
120: return;
121: }
122: printf(" ***** MODE SENSE -- return all pages *****\n");
123: printf(" ***** with SenseInfo buffer *****\n\n");
124:
125: ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
126:
127: sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
128: sptwb.spt.PathId = 0;
129: sptwb.spt.TargetId = 1;
130: sptwb.spt.Lun = 0;
131: sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
132: sptwb.spt.SenseInfoLength = 24;
133: sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
134: sptwb.spt.DataTransferLength = 192;
135: sptwb.spt.TimeOutValue = 2;
136: sptwb.spt.DataBufferOffset =
137: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
138: sptwb.spt.SenseInfoOffset =
139: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
140: sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
141: sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
142: sptwb.spt.Cdb[4] = 192;
143: length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
144: sptwb.spt.DataTransferLength;
145:
146: status = DeviceIoControl(fileHandle,
147: IOCTL_SCSI_PASS_THROUGH,
148: &sptwb,
149: sizeof(SCSI_PASS_THROUGH),
150: &sptwb,
151: length,
152: &returned,
153: FALSE);
154:
155: PrintStatusResults(status,returned,&sptwb,length);
156:
157: printf(" ***** MODE SENSE -- return all pages *****\n");
158: printf(" ***** without SenseInfo buffer *****\n\n");
159:
160: ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
161:
162: sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
163: sptwb.spt.PathId = 0;
164: sptwb.spt.TargetId = 1;
165: sptwb.spt.Lun = 0;
166: sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
167: sptwb.spt.SenseInfoLength = 0;
168: sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
169: sptwb.spt.DataTransferLength = 192;
170: sptwb.spt.TimeOutValue = 2;
171: sptwb.spt.DataBufferOffset =
172: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
173: sptwb.spt.SenseInfoOffset =
174: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
175: sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
176: sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
177: sptwb.spt.Cdb[4] = 192;
178: length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
179: sptwb.spt.DataTransferLength;
180:
181: status = DeviceIoControl(fileHandle,
182: IOCTL_SCSI_PASS_THROUGH,
183: &sptwb,
184: sizeof(SCSI_PASS_THROUGH),
185: &sptwb,
186: length,
187: &returned,
188: FALSE);
189:
190: PrintStatusResults(status,returned,&sptwb,length);
191:
192: printf(" ***** TEST UNIT READY *****\n");
193: printf(" ***** DataBufferLength = 0 *****\n\n");
194:
195:
196: ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
197:
198: sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
199: sptwb.spt.PathId = 0;
200: sptwb.spt.TargetId = 1;
201: sptwb.spt.Lun = 0;
202: sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
203: sptwb.spt.SenseInfoLength = 24;
204: sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
205: sptwb.spt.DataTransferLength = 0;
206: sptwb.spt.TimeOutValue = 2;
207: sptwb.spt.DataBufferOffset =
208: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
209: sptwb.spt.SenseInfoOffset =
210: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
211: sptwb.spt.Cdb[0] = SCSIOP_TEST_UNIT_READY;
212: length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
213:
214: status = DeviceIoControl(fileHandle,
215: IOCTL_SCSI_PASS_THROUGH,
216: &sptwb,
217: sizeof(SCSI_PASS_THROUGH),
218: &sptwb,
219: length,
220: &returned,
221: FALSE);
222:
223: PrintStatusResults(status,returned,&sptwb,length);
224:
225: //
226: // Do a mode sense with a bad data buffer offset. This should fail.
227: //
228: printf(" ***** MODE SENSE -- return all pages *****\n");
229: printf(" ***** bad DataBufferOffset -- should fail *****\n\n");
230:
231: ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
232:
233: sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
234: sptwb.spt.PathId = 0;
235: sptwb.spt.TargetId = 1;
236: sptwb.spt.Lun = 0;
237: sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
238: sptwb.spt.SenseInfoLength = 0;
239: sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
240: sptwb.spt.DataTransferLength = 192;
241: sptwb.spt.TimeOutValue = 2;
242: sptwb.spt.DataBufferOffset = 0;
243: sptwb.spt.SenseInfoOffset =
244: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
245: sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
246: sptwb.spt.Cdb[2] = MODE_SENSE_RETURN_ALL;
247: sptwb.spt.Cdb[4] = 192;
248: length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
249: sptwb.spt.DataTransferLength;
250: status = DeviceIoControl(fileHandle,
251: IOCTL_SCSI_PASS_THROUGH,
252: &sptwb,
253: sizeof(SCSI_PASS_THROUGH),
254: &sptwb,
255: length,
256: &returned,
257: FALSE);
258:
259: PrintStatusResults(status,returned,&sptwb,length);
260:
261:
262: //
263: // Get caching mode sense page.
264: //
265: printf(" ***** MODE SENSE *****\n");
266: printf(" ***** return caching mode sense page *****\n\n");
267:
268: ZeroMemory(&sptwb,sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS));
269:
270: sptwb.spt.Length = sizeof(SCSI_PASS_THROUGH);
271: sptwb.spt.PathId = 0;
272: sptwb.spt.TargetId = 1;
273: sptwb.spt.Lun = 0;
274: sptwb.spt.CdbLength = CDB6GENERIC_LENGTH;
275: sptwb.spt.SenseInfoLength = 24;
276: sptwb.spt.DataIn = SCSI_IOCTL_DATA_IN;
277: sptwb.spt.DataTransferLength = 192;
278: sptwb.spt.TimeOutValue = 2;
279: sptwb.spt.DataBufferOffset =
280: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
281: sptwb.spt.SenseInfoOffset =
282: offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
283: sptwb.spt.Cdb[0] = SCSIOP_MODE_SENSE;
284: sptwb.spt.Cdb[1] = 0x08; // target shall not return any block descriptors
285: sptwb.spt.Cdb[2] = MODE_PAGE_CACHING;
286: sptwb.spt.Cdb[4] = 192;
287: length = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf) +
288: sptwb.spt.DataTransferLength;
289: status = DeviceIoControl(fileHandle,
290: IOCTL_SCSI_PASS_THROUGH,
291: &sptwb,
292: sizeof(SCSI_PASS_THROUGH),
293: &sptwb,
294: length,
295: &returned,
296: FALSE);
297:
298: PrintStatusResults(status,returned,&sptwb,length);
299:
300: printf(" ***** WRITE DATA BUFFER operation *****\n");
301:
302: ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
303: dataBuffer = AllocateAlignedBuffer(sectorSize,capabilities.AlignmentMask);
304: FillMemory(dataBuffer,sectorSize/2,'N');
305: FillMemory(dataBuffer + sectorSize/2,sectorSize/2,'T');
306:
307: sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
308: sptdwb.sptd.PathId = 0;
309: sptdwb.sptd.TargetId = 1;
310: sptdwb.sptd.Lun = 0;
311: sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
312: sptdwb.sptd.SenseInfoLength = 24;
313: sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_OUT;
314: sptdwb.sptd.DataTransferLength = sectorSize;
315: sptdwb.sptd.TimeOutValue = 2;
316: sptdwb.sptd.DataBuffer = dataBuffer;
317: sptdwb.sptd.SenseInfoOffset =
318: offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
319: sptdwb.sptd.Cdb[0] = SCSIOP_WRITE_DATA_BUFF;
320: sptdwb.sptd.Cdb[1] = 2; // Data mode
321: sptdwb.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
322: sptdwb.sptd.Cdb[8] = 0;
323: length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
324: status = DeviceIoControl(fileHandle,
325: IOCTL_SCSI_PASS_THROUGH_DIRECT,
326: &sptdwb,
327: length,
328: &sptdwb,
329: length,
330: &returned,
331: FALSE);
332:
333: PrintStatusResults(status,returned,
334: (PSCSI_PASS_THROUGH_WITH_BUFFERS)&sptdwb,length);
335: if ((sptdwb.sptd.ScsiStatus == 0) && (status != 0)) {
336: PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
337: }
338:
339: printf(" ***** READ DATA BUFFER operation *****\n");
340:
341: ZeroMemory(&sptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER));
342: ZeroMemory(dataBuffer,sectorSize);
343:
344: sptdwb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
345: sptdwb.sptd.PathId = 0;
346: sptdwb.sptd.TargetId = 1;
347: sptdwb.sptd.Lun = 0;
348: sptdwb.sptd.CdbLength = CDB10GENERIC_LENGTH;
349: sptdwb.sptd.DataIn = SCSI_IOCTL_DATA_IN;
350: sptdwb.sptd.SenseInfoLength = 24;
351: sptdwb.sptd.DataTransferLength = sectorSize;
352: sptdwb.sptd.TimeOutValue = 2;
353: sptdwb.sptd.DataBuffer = dataBuffer;
354: sptdwb.sptd.SenseInfoOffset =
355: offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
356: sptdwb.sptd.Cdb[0] = SCSIOP_READ_DATA_BUFF;
357: sptdwb.sptd.Cdb[1] = 2; // Data mode
358: sptdwb.sptd.Cdb[7] = (UCHAR)(sectorSize >> 8); // Parameter List length
359: sptdwb.sptd.Cdb[8] = 0;
360: length = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);
361: status = DeviceIoControl(fileHandle,
362: IOCTL_SCSI_PASS_THROUGH_DIRECT,
363: &sptdwb,
364: length,
365: &sptdwb,
366: length,
367: &returned,
368: FALSE);
369:
370: PrintStatusResults(status,returned,
371: (PSCSI_PASS_THROUGH_WITH_BUFFERS)&sptdwb,length);
372: if ((sptdwb.sptd.ScsiStatus == 0) && (status != 0)) {
373: PrintDataBuffer(dataBuffer,sptdwb.sptd.DataTransferLength);
374: }
375: }
376:
377: VOID
378: PrintError(ULONG ErrorCode)
379: {
380: UCHAR errorBuffer[80];
381: ULONG count;
382:
383: count = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
384: NULL,
385: ErrorCode,
386: 0,
387: errorBuffer,
388: sizeof(errorBuffer),
389: NULL
390: );
391:
392: if (count != 0) {
393: printf("%s\n", errorBuffer);
394: } else {
395: printf("Format message failed. Error: %d\n", GetLastError());
396: }
397: }
398:
399: VOID
400: PrintDataBuffer(PUCHAR DataBuffer, ULONG BufferLength)
401: {
402: ULONG Cnt;
403:
404: printf(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n");
405: printf(" ---------------------------------------------------------------\n");
406: for (Cnt = 0; Cnt < BufferLength; Cnt++) {
407: if ((Cnt) % 16 == 0) {
408: printf(" %03X ",Cnt);
409: }
410: printf("%02X ", DataBuffer[Cnt]);
411: if ((Cnt+1) % 8 == 0) {
412: printf(" ");
413: }
414: if ((Cnt+1) % 16 == 0) {
415: printf("\n");
416: }
417: }
418: printf("\n\n");
419: }
420:
421: VOID
422: PrintInquiryData(PCHAR DataBuffer)
423: {
424: PSCSI_ADAPTER_BUS_INFO adapterInfo;
425: PSCSI_INQUIRY_DATA inquiryData;
426: ULONG i,
427: j;
428:
429: adapterInfo = (PSCSI_ADAPTER_BUS_INFO) DataBuffer;
430:
431: printf("Bus\n");
432: printf("Num TID LUN Claimed String Inquiry Header\n");
433: printf("--- --- --- ------- ---------------------------- -----------------------\n");
434:
435: for (i = 0; i < adapterInfo->NumberOfBuses; i++) {
436: inquiryData = (PSCSI_INQUIRY_DATA) (DataBuffer +
437: adapterInfo->BusData[i].InquiryDataOffset);
438: while (adapterInfo->BusData[i].InquiryDataOffset) {
439: printf(" %d %d %3d %s %.28s ",
440: i,
441: inquiryData->TargetId,
442: inquiryData->Lun,
443: (inquiryData->DeviceClaimed) ? "Y" : "N",
444: &inquiryData->InquiryData[8]);
445: for (j = 0; j < 8; j++) {
446: printf("%02X ", inquiryData->InquiryData[j]);
447: }
448: printf("\n");
449: if (inquiryData->NextInquiryDataOffset == 0) {
450: break;
451: }
452: inquiryData = (PSCSI_INQUIRY_DATA) (DataBuffer +
453: inquiryData->NextInquiryDataOffset);
454: }
455: }
456:
457: printf("\n\n");
458: }
459:
460: PUCHAR
461: AllocateAlignedBuffer(ULONG size, ULONG Align)
462: {
463: PUCHAR ptr;
464:
465: if (!Align) {
466: ptr = malloc(size);
467: }
468: else {
469: ptr = malloc(size + Align);
470: ptr = (PUCHAR)(((ULONG)ptr + Align) & ~Align);
471: }
472: if (ptr == NULL) {
473: printf("Memory allocation error. Terminating program\n");
474: exit(1);
475: }
476: else {
477: return ptr;
478: }
479: }
480:
481: VOID
482: PrintStatusResults(
483: BOOLEAN status,DWORD returned,PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb,
484: ULONG length)
485: {
486: ULONG errorCode;
487:
488: if (!status ) {
489: printf( "Error: %d ",
490: errorCode = GetLastError() );
491: PrintError(errorCode);
492: return;
493: }
494: if (psptwb->spt.ScsiStatus) {
495: PrintSenseInfo(psptwb);
496: return;
497: }
498: else {
499: printf("Scsi status: %02Xh, Bytes returned: %Xh, ",
500: psptwb->spt.ScsiStatus,returned);
501: printf("Data buffer length: %Xh\n\n\n",
502: psptwb->spt.DataTransferLength);
503: PrintDataBuffer((PUCHAR)psptwb,length);
504: }
505: }
506:
507: VOID
508: PrintSenseInfo(PSCSI_PASS_THROUGH_WITH_BUFFERS psptwb)
509: {
510: int i;
511:
512: printf("Scsi status: %02Xh\n\n",psptwb->spt.ScsiStatus);
513: if (psptwb->spt.SenseInfoLength == 0) {
514: return;
515: }
516: printf("Sense Info -- consult SCSI spec for details\n");
517: printf("-------------------------------------------------------------\n");
518: for (i=0; i < psptwb->spt.SenseInfoLength; i++) {
519: printf("%02X ",psptwb->ucSenseBuf[i]);
520: }
521: printf("\n\n");
522: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.