Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "emul.h"
4
#include "vars.h"
5
#include "init.h"
6
#include "hddio.h"
7
 
8
#include "util.h"
9
 
10
typedef int (__cdecl *GetASPI32SupportInfo_t)();
11
typedef int (__cdecl *SendASPI32Command_t)(void *SRB);
12
const int ATAPI_CDB_SIZE = 12; // sizeof(CDB) == 16
13
const int MAX_INFO_LEN = 48;
14
 
15
GetASPI32SupportInfo_t _GetASPI32SupportInfo = 0;
16
SendASPI32Command_t _SendASPI32Command = 0;
17
HMODULE hAspiDll = 0;
18
HANDLE hASPICompletionEvent;
19
 
20
 
21
DWORD ATA_PASSER::open(PHYS_DEVICE *dev)
22
{
23
   close();
24
   this->dev = dev;
25
 
26
   hDevice = CreateFile(dev->filename,
27
                GENERIC_READ | GENERIC_WRITE, // R/W required!
28
                (temp.win9x?0:FILE_SHARE_DELETE) /*Dexus*/ | FILE_SHARE_READ | FILE_SHARE_WRITE,
29
                0, OPEN_EXISTING, 0, 0);
30
 
31
   if (hDevice == INVALID_HANDLE_VALUE)
32
   {
33
       ULONG Le = GetLastError();
34
       printf("can't open: `%s', %lu\n", dev->filename, Le);
35
       return Le;
36
   }
37
 
38
   if(dev->type == ATA_NTHDD && dev->usage == ATA_OP_USE)
39
   {
40
       memset(Vols, 0, sizeof(Vols));
41
 
42
       // lock & dismount all volumes on disk
43
       char VolName[256];
44
       HANDLE VolEnum = FindFirstVolume(VolName, _countof(VolName));
45
       if(VolEnum == INVALID_HANDLE_VALUE)
46
       {
47
           ULONG Le = GetLastError();
48
           printf("can't enumerate volumes: %lu\n", Le);
49
           return Le;
50
       }
51
 
52
       BOOL NextVol = TRUE;
53
       unsigned VolIdx = 0;
54
       unsigned i;
55
       for(; NextVol; NextVol = FindNextVolume(VolEnum, VolName, _countof(VolName)))
56
       {
57
           int l = strlen(VolName);
58
           if(VolName[l-1] == '\\')
59
               VolName[l-1] = 0;
60
 
61
           HANDLE Vol = CreateFile(VolName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
62
           if(Vol == INVALID_HANDLE_VALUE)
63
           {
64
               printf("can't open volume `%s'\n", VolName);
65
               continue;
66
           }
67
 
68
           UCHAR Buf[sizeof(VOLUME_DISK_EXTENTS) + 100 * sizeof(DISK_EXTENT)];
69
           PVOLUME_DISK_EXTENTS DiskExt = PVOLUME_DISK_EXTENTS(Buf);
70
 
71
           ULONG Junk;
72
           if(!DeviceIoControl(Vol, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, 0, Buf, sizeof(Buf), &Junk, 0))
73
           {
74
               Junk = GetLastError();
75
               CloseHandle(Vol);
76
               printf("can't get volume extents: `%s', %lu\n", VolName, Junk);
77
               continue;
78
           }
79
 
80
           if(DiskExt->NumberOfDiskExtents == 0)
81
           {
82
               // bad volume
83
               CloseHandle(Vol);
84
               return ERROR_ACCESS_DENIED;
85
           }
86
 
87
           if(DiskExt->NumberOfDiskExtents > 1)
88
           {
89
               for(i = 0; i < DiskExt->NumberOfDiskExtents; i++)
90
               {
91
                   if(DiskExt->Extents[i].DiskNumber == dev->spti_id)
92
                   {
93
                       // complex volume (volume split over several disks)
94
                       CloseHandle(Vol);
95
                       return ERROR_ACCESS_DENIED;
96
                   }
97
               }
98
           }
99
 
100
           if(DiskExt->Extents[0].DiskNumber != dev->spti_id)
101
           {
102
               CloseHandle(Vol);
103
               continue;
104
           }
105
 
106
           Vols[VolIdx++] = Vol;
107
       }
108
       FindVolumeClose(VolEnum);
109
 
110
       for(i = 0; i < VolIdx; i++)
111
       {
112
           ULONG Junk;
113
           if(!DeviceIoControl(Vols[i], FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &Junk, 0))
114
           {
115
               Junk = GetLastError();
116
               printf("can't lock volume: %lu\n", Junk);
117
               return Junk;
118
           }
119
           if(!DeviceIoControl(Vols[i], FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &Junk, 0))
120
           {
121
               Junk = GetLastError();
122
               printf("can't dismount volume: %lu\n", Junk);
123
               return Junk;
124
           }
125
       }
126
   }
127
   return NO_ERROR;
128
}
129
 
130
void ATA_PASSER::close()
131
{
132
   if (hDevice != INVALID_HANDLE_VALUE)
133
   {
134
       if(dev->type == ATA_NTHDD && dev->usage == ATA_OP_USE)
135
       {
136
           // unlock all volumes on disk
137
           for(unsigned i = 0; i < _countof(Vols) && Vols[i]; i++)
138
           {
139
               ULONG Junk;
140
               DeviceIoControl(Vols[i], FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, &Junk, 0);
141
               CloseHandle(Vols[i]);
142
               Vols[i] = 0;
143
           }
144
       }
145
 
146
       CloseHandle(hDevice);
147
   }
148
   hDevice = INVALID_HANDLE_VALUE;
149
   dev = 0;
150
}
151
 
152
unsigned ATA_PASSER::identify(PHYS_DEVICE *outlist, int max)
153
{
154
   int res = 0;
155
   ATA_PASSER ata;
156
 
157
   unsigned HddCount = get_hdd_count();
158
 
159
   for (unsigned drive = 0; drive < MAX_PHYS_HD_DRIVES && res < max; drive++)
160
   {
161
 
162
      PHYS_DEVICE *dev = outlist + res;
163
      dev->type = ATA_NTHDD;
164
      dev->spti_id = drive;
165
      dev->usage = ATA_OP_ENUM_ONLY;
166
      sprintf(dev->filename, "\\\\.\\PhysicalDrive%d", dev->spti_id);
167
 
168
      if(drive >= HddCount)
169
          continue;
170
 
171
      DWORD errcode = ata.open(dev);
172
      if (errcode == ERROR_FILE_NOT_FOUND)
173
          continue;
174
 
175
      color(CONSCLR_HARDITEM);
176
      printf("hd%d: ", drive);
177
 
178
      if (errcode != NO_ERROR)
179
      {
180
          color(CONSCLR_ERROR);
181
          printf("access failed\n");
182
          err_win32(errcode);
183
          continue;
184
      }
185
 
186
      SENDCMDINPARAMS in = { 512 };
187
      in.irDriveRegs.bCommandReg = ID_CMD;
188
      struct
189
      {
190
          SENDCMDOUTPARAMS out;
191
          char xx[512];
192
      } res_buffer;
193
      res_buffer.out.cBufferSize = 512;
194
      DWORD sz;
195
 
196
      DISK_GEOMETRY geo = { 0 };
197
      int res1 = DeviceIoControl(ata.hDevice, SMART_RCV_DRIVE_DATA, &in, sizeof in, &res_buffer, sizeof res_buffer, &sz, 0);
198
      if(!res1)
199
      {
200
          printf("cant get hdd info, %lu\n", GetLastError());
201
      }
202
      int res2 = DeviceIoControl(ata.hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, &geo, sizeof geo, &sz, 0);
203
      if (geo.BytesPerSector != 512)
204
      {
205
          color(CONSCLR_ERROR);
206
          printf("unsupported sector size (%lu bytes)\n", geo.BytesPerSector);
207
          continue;
208
      }
209
 
210
      ata.close();
211
 
212
      if (!res1)
213
      {
214
          color(CONSCLR_ERROR);
215
          printf("identification failed\n");
216
          continue;
217
      }
218
 
219
      memcpy(dev->idsector, res_buffer.out.bBuffer, 512);
220
      char model[42], serial[22];
221
      swap_bytes(model, res_buffer.out.bBuffer+54, 20);
222
      swap_bytes(serial, res_buffer.out.bBuffer+20, 10);
223
 
224
      dev->hdd_size = geo.Cylinders.LowPart * geo.SectorsPerTrack * geo.TracksPerCylinder;
225
      unsigned shortsize = dev->hdd_size / 2; char mult = 'K';
226
      if (shortsize >= 100000)
227
      {
228
         shortsize /= 1024, mult = 'M';
229
         if (shortsize >= 100000)
230
             shortsize /= 1024, mult = 'G';
231
      }
232
 
233
      color(CONSCLR_HARDINFO);
234
      printf("%-40s %-20s ", model, serial);
235
      color(CONSCLR_HARDITEM);
236
      printf("%8d %cb\n", shortsize, mult);
237
      if (dev->hdd_size > 0xFFFFFFF)
238
      {
239
          color(CONSCLR_WARNING);
240
          printf("     drive %d warning! LBA48 is not supported. only first 128GB visible\n", drive); //Alone Coder 0.36.7
241
      }
242
 
243
      print_device_name(dev->viewname, dev);
244
      res++;
245
   }
246
 
247
   return res;
248
}
249
 
250
unsigned ATA_PASSER::get_hdd_count() // static
251
{
252
    HDEVINFO DeviceInfoSet;
253
    ULONG MemberIndex;
254
 
255
    // create a HDEVINFO with all present devices
256
    DeviceInfoSet = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
257
    if (DeviceInfoSet == INVALID_HANDLE_VALUE)
258
    {
259
        assert(FALSE);
260
        return 0;
261
    }
262
 
263
    // enumerate through all devices in the set
264
    MemberIndex = 0;
265
    while(true)
266
    {
267
        // get device interfaces
268
        SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
269
        DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
270
        if (!SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &GUID_DEVINTERFACE_DISK, MemberIndex, &DeviceInterfaceData))
271
        {
272
            if (GetLastError() != ERROR_NO_MORE_ITEMS)
273
            {
274
                // error
275
                assert(FALSE);
276
            }
277
 
278
            // ok, reached end of the device enumeration
279
            break;
280
        }
281
 
282
        // process the next device next time
283
        MemberIndex++;
284
    }
285
 
286
    // destroy device info list
287
    SetupDiDestroyDeviceInfoList(DeviceInfoSet);
288
 
289
    return MemberIndex;
290
}
291
 
292
 
293
bool ATA_PASSER::seek(u64 nsector)
294
{
295
   LARGE_INTEGER offset;
296
   offset.QuadPart = ((__int64)nsector) << 9;
297
   DWORD code = SetFilePointer(hDevice, offset.LowPart, &offset.HighPart, FILE_BEGIN);
298
   return (code != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR);
299
}
300
 
301
bool ATA_PASSER::read_sector(unsigned char *dst)
302
{
303
   DWORD sz = 0;
304
   if (!ReadFile(hDevice, dst, 512, &sz, 0))
305
       return false;
306
   if (sz < 512)
307
       memset(dst+sz, 0, 512-sz); // on EOF, or truncated file, read 00
308
   return true;
309
}
310
 
311
bool ATA_PASSER::write_sector(unsigned char *src)
312
{
313
   DWORD sz = 0;
314
   return (WriteFile(hDevice, src, 512, &sz, 0) && sz == 512);
315
}
316
 
317
DWORD ATAPI_PASSER::open(PHYS_DEVICE *dev)
318
{
319
   close();
320
   this->dev = dev;
321
   if (dev->type == ATA_ASPI_CD)
322
       return NO_ERROR;
323
 
324
   hDevice = CreateFile(dev->filename,
325
                GENERIC_READ | GENERIC_WRITE, // R/W required!
326
                (temp.win9x?0:FILE_SHARE_DELETE) /*Dexus*/ | FILE_SHARE_READ | FILE_SHARE_WRITE,
327
                0, OPEN_EXISTING, 0, 0);
328
 
329
   if (hDevice != INVALID_HANDLE_VALUE)
330
       return NO_ERROR;
331
   return GetLastError();
332
}
333
 
334
void ATAPI_PASSER::close()
335
{
336
   if (!dev || dev->type == ATA_ASPI_CD)
337
       return;
338
   if (hDevice != INVALID_HANDLE_VALUE)
339
       CloseHandle(hDevice);
340
   hDevice = INVALID_HANDLE_VALUE;
341
   dev = 0;
342
}
343
 
344
unsigned ATAPI_PASSER::identify(PHYS_DEVICE *outlist, int max)
345
{
346
   int res = 0;
347
   ATAPI_PASSER atapi;
348
 
349
   if (conf.cd_aspi)
350
   {
351
 
352
      init_aspi();
353
 
354
 
355
      for (int adapterid = 0; ; adapterid++)
356
      {
357
 
358
         SRB_HAInquiry SRB = { 0 };
359
         SRB.SRB_Cmd        = SC_HA_INQUIRY;
360
         SRB.SRB_HaId       = (unsigned char)adapterid;
361
         DWORD ASPIStatus = _SendASPI32Command(&SRB);
362
 
363
         if (ASPIStatus != SS_COMP) break;
364
 
365
         char b1[20], b2[20];
366
         memcpy(b1, SRB.HA_ManagerId, 16); b1[16] = 0;
367
         memcpy(b2, SRB.HA_Identifier, 16); b2[16] = 0;
368
 
369
         if (adapterid == 0) {
370
            color(CONSCLR_HARDITEM); printf("using ");
371
            color(CONSCLR_WARNING); printf("%s", b1);
372
            color(CONSCLR_HARDITEM); printf(" %s\n", b2);
373
         }
374
         if (adapterid >= (int)SRB.HA_Count) break;
375
         // int maxTargets = (int)SRB.HA_Unique[3]; // always 8 (?)
376
 
377
         for (int targetid = 0; targetid < 8; targetid++) {
378
 
379
            PHYS_DEVICE *dev = outlist + res;
380
            dev->type = ATA_ASPI_CD;
381
            dev->adapterid = adapterid; // (int)SRB.HA_SCSI_ID; // does not work with Nero ASPI
382
            dev->targetid = targetid;
383
 
384
            DWORD errcode = atapi.open(dev);
385
            if (errcode != NO_ERROR) continue;
386
 
387
            int ok = atapi.read_atapi_id(dev->idsector, 1);
388
            atapi.close();
389
            if (ok != 2) continue; // not a CD-ROM
390
 
391
            print_device_name(dev->viewname, dev);
392
            res++;
393
         }
394
      }
395
 
396
 
397
       return res;
398
   }
399
 
400
   // spti
401
   for (int drive = 0; drive < MAX_PHYS_CD_DRIVES && res < max; drive++)
402
   {
403
 
404
      PHYS_DEVICE *dev = outlist + res;
405
      dev->type = ATA_SPTI_CD;
406
      dev->spti_id = drive;
407
      dev->usage = ATA_OP_ENUM_ONLY;
408
      sprintf(dev->filename, "\\\\.\\CdRom%d", dev->spti_id);
409
 
410
      DWORD errcode = atapi.open(dev);
411
      if (errcode == ERROR_FILE_NOT_FOUND)
412
          continue;
413
 
414
      color(CONSCLR_HARDITEM);
415
      printf("cd%d: ", drive);
416
      if (errcode != NO_ERROR)
417
      {
418
          color(CONSCLR_ERROR);
419
          printf("access failed\n");
420
          err_win32(errcode);
421
          continue;
422
      }
423
 
424
 
425
      int ok = atapi.read_atapi_id(dev->idsector, 0);
426
      atapi.close();
427
      if (!ok)
428
      {
429
          color(CONSCLR_ERROR);
430
          printf("identification failed\n");
431
          continue;
432
      }
433
      if (ok < 2)
434
          continue; // not a CD-ROM
435
 
436
      print_device_name(dev->viewname, dev);
437
      res++;
438
   }
439
 
440
   return res;
441
}
442
 
443
int ATAPI_PASSER::pass_through(void *databuf, int bufsize)
444
{
445
   int res = (conf.cd_aspi)? SEND_ASPI_CMD(databuf, bufsize) : SEND_SPTI_CMD(databuf, bufsize);
446
   return res;
447
}
448
 
449
int ATAPI_PASSER::SEND_SPTI_CMD(void *databuf, int bufsize)
450
{
451
   memset(databuf, 0, bufsize);
452
 
453
   struct {
454
      SCSI_PASS_THROUGH_DIRECT p;
455
      unsigned char sense[MAX_SENSE_LEN];
456
   } srb = { 0 }, dst;
457
 
458
   srb.p.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
459
   *(CDB*)&srb.p.Cdb = cdb;
460
   srb.p.CdbLength = sizeof(CDB);
461
   srb.p.DataIn = SCSI_IOCTL_DATA_IN;
462
   srb.p.TimeOutValue = 10;
463
   srb.p.DataBuffer = databuf;
464
   srb.p.DataTransferLength = bufsize;
465
   srb.p.SenseInfoLength = sizeof(srb.sense);
466
   srb.p.SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT);
467
 
468
   DWORD outsize;
469
   int r = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT,
470
                           &srb.p, sizeof(srb.p),
471
                           &dst, sizeof(dst),
472
                           &outsize, 0);
473
 
474
   if (!r) { return 0; }
475
 
476
   passed_length = dst.p.DataTransferLength;
477
   if ((senselen = dst.p.SenseInfoLength)) memcpy(sense, dst.sense, senselen);
478
 
479
#ifdef DUMP_HDD_IO
480
printf("sense=%d, data=%d, srbsz=%d/%d, dir=%d. ok%d\n", senselen, passed_length, outsize, sizeof(srb.p), dst.p.DataIn, res);
481
printf("srb:"); dump1((BYTE*)&dst, outsize);
482
printf("data:"); dump1((BYTE*)databuf, 0x40);
483
#endif
484
 
485
   return 1;
486
}
487
 
488
int ATAPI_PASSER::read_atapi_id(unsigned char *idsector, char prefix)
489
{
490
   memset(&cdb, 0, sizeof(CDB));
491
   memset(idsector, 0, 512);
492
 
493
   INQUIRYDATA inq;
494
   cdb.CDB6INQUIRY.OperationCode = 0x12; // INQUIRY
495
   cdb.CDB6INQUIRY.AllocationLength = sizeof(inq);
496
   if (!pass_through(&inq, sizeof(inq))) return 0;
497
 
498
   char vendor[10], product[18], revision[6], id[22], ata_name[26];
499
 
500
   memcpy(vendor, inq.VendorId, sizeof(inq.VendorId)); vendor[sizeof(inq.VendorId)] = 0;
501
   memcpy(product, inq.ProductId, sizeof(inq.ProductId)); product[sizeof(inq.ProductId)] = 0;
502
   memcpy(revision, inq.ProductRevisionLevel, sizeof(inq.ProductRevisionLevel)); revision[sizeof(inq.ProductRevisionLevel)] = 0;
503
   memcpy(id, inq.VendorSpecific, sizeof(inq.VendorSpecific)); id[sizeof(inq.VendorSpecific)] = 0;
504
 
505
   if (prefix) {
506
      color(CONSCLR_HARDITEM);
507
      if (dev->type == ATA_ASPI_CD) printf("%d.%d: ", dev->adapterid, dev->targetid);
508
      if (dev->type == ATA_SPTI_CD) printf("cd%d: ", dev->spti_id);
509
   }
510
 
511
   trim(vendor); trim(product); trim(revision); trim(id);
512
   sprintf(ata_name, "%s %s", vendor, product);
513
 
514
   idsector[0] = 0xC0; // removable, accelerated DRQ, 12-byte packet
515
   idsector[1] = 0x85; // protocol: ATAPI, device type: CD-ROM
516
 
517
   make_ata_string(idsector+54, 20, ata_name);
518
   make_ata_string(idsector+20, 10, id);
519
   make_ata_string(idsector+46,  4, revision);
520
 
521
   idsector[0x63] = 0x0B; // caps: IORDY,LBA,DMA
522
   idsector[0x67] = 4; // PIO timing
523
   idsector[0x69] = 2; // DMA timing
524
 
525
   if (inq.DeviceType == 5) color(CONSCLR_HARDINFO);
526
   printf("%-40s %-20s  ", ata_name, id);
527
   color(CONSCLR_HARDITEM);
528
   printf("rev.%-4s\n", revision);
529
 
530
   return 1 + (inq.DeviceType == 5);
531
}
532
 
533
bool ATAPI_PASSER::read_sector(unsigned char *dst)
534
{
535
   DWORD sz = 0;
536
   if (!ReadFile(hDevice, dst, 2048, &sz, 0))
537
       return false;
538
   if (sz < 2048)
539
       memset(dst+sz, 0, 2048-sz); // on EOF, or truncated file, read 00
540
   return true;
541
}
542
 
543
bool ATAPI_PASSER::seek(unsigned nsector)
544
{
545
   LARGE_INTEGER offset;
546
   offset.QuadPart = i64(nsector) * 2048;
547
   DWORD code = SetFilePointer(hDevice, offset.LowPart, &offset.HighPart, FILE_BEGIN);
548
   return (code != INVALID_SET_FILE_POINTER || GetLastError() == NO_ERROR);
549
}
550
 
551
void make_ata_string(unsigned char *dst, unsigned n_words, const char *src)
552
{
553
   unsigned i; //Alone Coder 0.36.7
554
   for (/*unsigned*/ i = 0; i < n_words*2 && src[i]; i++) dst[i] = src[i];
555
   while (i < n_words*2) dst[i++] = ' ';
556
   unsigned char tmp;
557
   for (i = 0; i < n_words*2; i += 2)
558
      tmp = dst[i], dst[i] = dst[i+1], dst[i+1] = tmp;
559
}
560
 
561
void swap_bytes(char *dst, BYTE *src, unsigned n_words)
562
{
563
   unsigned i; //Alone Coder 0.36.7
564
   for (/*unsigned*/ i = 0; i < n_words; i++)
565
   {
566
      char c1 = src[2*i], c2 = src[2*i+1];
567
      dst[2*i] = c2, dst[2*i+1] = c1;
568
   }
569
   dst[2*i] = 0;
570
   trim(dst);
571
}
572
 
573
void print_device_name(char *dst, PHYS_DEVICE *dev)
574
{
575
   char model[42], serial[22];
576
   swap_bytes(model, dev->idsector + 54, 20);
577
   swap_bytes(serial, dev->idsector + 20, 10);
578
   sprintf(dst, "<%s,%s>", model, serial);
579
}
580
 
581
void init_aspi()
582
{
583
   if (_SendASPI32Command)
584
       return;
585
   hAspiDll = LoadLibrary("WNASPI32.DLL");
586
   if (!hAspiDll)
587
   {
588
       errmsg("failed to load WNASPI32.DLL");
589
       err_win32();
590
       exit();
591
   }
592
   _GetASPI32SupportInfo = (GetASPI32SupportInfo_t)GetProcAddress(hAspiDll, "GetASPI32SupportInfo");
593
   _SendASPI32Command = (SendASPI32Command_t)GetProcAddress(hAspiDll, "SendASPI32Command");
594
   if (!_GetASPI32SupportInfo || !_SendASPI32Command) errexit("invalid ASPI32 library");
595
   DWORD init = _GetASPI32SupportInfo();
596
   if (((init >> 8) & 0xFF) != SS_COMP)
597
       errexit("error in ASPI32 initialization");
598
   hASPICompletionEvent = CreateEvent(0,0,0,0);
599
}
600
 
601
int ATAPI_PASSER::SEND_ASPI_CMD(void *buf, int buf_sz)
602
{
603
   SRB_ExecSCSICmd SRB = { 0 };
604
   SRB.SRB_Cmd        = SC_EXEC_SCSI_CMD;
605
   SRB.SRB_HaId       = (unsigned char)dev->adapterid;
606
   SRB.SRB_Flags      = SRB_DIR_IN | SRB_EVENT_NOTIFY | SRB_ENABLE_RESIDUAL_COUNT;
607
   SRB.SRB_Target     = (unsigned char)dev->targetid;
608
   SRB.SRB_BufPointer = (unsigned char*)buf;
609
   SRB.SRB_BufLen     = buf_sz;
610
   SRB.SRB_SenseLen   = sizeof(SRB.SenseArea);
611
   SRB.SRB_CDBLen     = ATAPI_CDB_SIZE;
612
   SRB.SRB_PostProc   = hASPICompletionEvent;
613
   memcpy(SRB.CDBByte, &cdb, ATAPI_CDB_SIZE);
614
 
615
   /* DWORD ASPIStatus = */ _SendASPI32Command(&SRB);
616
   passed_length = SRB.SRB_BufLen;
617
 
618
   if (SRB.SRB_Status == SS_PENDING)
619
   {
620
      DWORD ASPIEventStatus = WaitForSingleObject(hASPICompletionEvent, 10000); // timeout 10sec
621
      if (ASPIEventStatus == WAIT_OBJECT_0)
622
          ResetEvent(hASPICompletionEvent);
623
   }
624
   if (senselen = SRB.SRB_SenseLen)
625
       memcpy(sense, SRB.SenseArea, senselen);
626
   if (temp.win9x)
627
       senselen = 0; //Alone Coder //makes possible to read one CD sector in win9x
628
   if (/*(temp.win9x)&&*/(passed_length >= 0xffff))
629
       passed_length = 2048; //Alone Coder //was >=65535 in win9x //makes possible to work in win9x (HDDoct, WDC, Time Gal) //XP fails too
630
 
631
#ifdef DUMP_HDD_IO
632
printf("sense=%d, data=%d/%d, ok%d\n", senselen, passed_length, buf_sz, SRB.SRB_Status);
633
printf("srb:"); dump1((BYTE*)&SRB, sizeof(SRB));
634
printf("data:"); dump1((BYTE*)buf, 0x40);
635
#endif
636
 
637
   return (SRB.SRB_Status == SS_COMP);
638
}
639
 
640
void done_aspi()
641
{
642
   if (!hAspiDll)
643
       return;
644
   FreeLibrary(hAspiDll);
645
   CloseHandle(hASPICompletionEvent);
646
}