Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: WinAPI и системное программирование > А-у! Помогите, не работает детская процедура


Автор: VictorBondarenko 14.2.2005, 17:51
Написал процедуру для сбора статистики работы сидюка (привожу ее ниже).
Она не работает. DeviceIoControl после правильной работы должна выдавать True, a у меня
всегда False.
Чтобы проверить можно ли так вообще что-то делать с сидюком, я поставил
константу IOCTL_DISK_PERFORMANCE=$74808; (этот код приказывает сидюку "высунь язык").
Больше ничего не менял. Все сработало сидюк высунул язык. В чем же проблема???
Перепроверил код $70020. Все правильно.
Посмотрите пожалуйста процедуру, может что-то заметите. Заранее благодарен за внимание и помощь.
И еще, работаю я очень по идиотски: залажу в DDK 2600 в его .h файлы, ищу в них нужные структуры и константы, перевожу с С++ в Delphi.
Может подскажите какой-то unit , где бы все, что может понадобиться для работы с СД уже было.

С уважением и благодарностью,
Виктор

// Эта процедура для сбора статистики работы сидюка
// не работает
Код
procedure TForm1.Button4Click(Sender: TObject);
const
IOCTL_DISK_PERFORMANCE=$70020;
type

DISK_PERFORMANCE = record
   BytesRead: Longint;
   BytesWritten:Longint;
   ReadTime:Longint;
   WriteTime:Longint;
   IdleTime:Longint;
  ReadCount:ULONG;
   WriteCount:ULONG;
   QueueDepth:ULONG;
   SplitCount:ULONG;
   QueryTime:Longint;
   StorageDeviceNumber:ULONG;
   StorageManagerName:array[0..7]of WCHAR;
end;
var
a:string;
out_size:DWORD;
out_data: DISK_PERFORMANCE;
hCDDevice : THandle;
lpBytesReturned: DWORD;
DriveLetter : char;
d:Bool;
 
begin
 DriveLetter := 'f';
hCDDevice := CreateFile(PChar('\\.\'+DriveLetter+':'),
GENERIC_READ,  
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0 );

if hCDDevice <> INVALID_HANDLE_VALUE then begin
d:=DeviceIoControl(hCDDevice,
 IOCTL_DISK_PERFORMANCE,
 nil,
 0,
@out_data,
sizeof(out_data),
 out_size,
 nil );
if  d  then
       begin
str(out_data.StorageDeviceNumber,a);
ShowMessage(a);

       end;
 CloseHandle(hCDDevice);
                                          end;

end;

Автор: Girder 15.2.2005, 14:35
1)
Код
{$A8}
procedure TForm1.Button1Click(Sender: TObject);
const IOCTL_DISK_PERFORMANCE=$70020;
type
DISK_PERFORMANCE = record
 BytesRead: LARGE_INTEGER;
 BytesWritten:LARGE_INTEGER;
 ReadTime:LARGE_INTEGER;
 WriteTime:LARGE_INTEGER;
 IdleTime:LARGE_INTEGER;
 ReadCount:DWord;
 WriteCount:DWord;
 QueueDepth:DWord;
 SplitCount:DWord;
 QueryTime:LARGE_INTEGER;
 StorageDeviceNumber:DWord;
 StorageManagerName:array[0..7]of WCHAR;
end;
...

2)Добавь вывод ошибки (если она возникнет)
Код
if d then
     begin
      str(out_data.StorageDeviceNumber,a);
      ShowMessage(a);
     end else ShowMessage('Ошибка:'+IntToStr(GetLastError));

3)открой командную строку и набери: "diskperf -y"
4)Также проверь работу данной процедуры на жестком диске, т.е. DriveLetter := 'C'; //Или какой он у тебя там

PS: Для CD... работать не будет smile (на 100% правда не уверен smile )

Автор: VictorBondarenko 16.2.2005, 11:41
Глубокоуважаемый Girder !
Большое спасибо за участие в моих проблемах,
внес все 4 твои идеи но, к сожалению,
результаты пока мрачные:

1. На diskperf -y
Система отвечает: " Счетчики производительности логических и физических дисков на этом компе включаются автоматически.
Счетчики грубой оценки также включаются для
IOCTL_DISK_PERFORMANCE".
2. Перепробовал работу со всеми устройствами:
на А: и F: (Это СД) ошибка 1
на С: Д: Е: (Это все НЖМД) ошибка 122.
Не знаю где посмотреть, что означают эти коды коды.

Я уже полностью иссяк, если у тебя еще
будут какие-либо идеи по этому поводу, приму их с большой признательностью.
С глубоким уважением
Виктор

Автор: Girder 16.2.2005, 12:11
Цитата(VictorBondarenko @ 16.2.2005, 11:41)
на А: и F: (Это СД) ошибка 1
-Команда не потдерживается

Цитата(VictorBondarenko @ 16.2.2005, 11:41)
на С: Д: Е: (Это все НЖМД) ошибка 122.
- Буфер не достаточен

PS: У меня для дисков... код работал на ура smile

Приведи свой код... а то мож что не так ты перенес!

Автор: VictorBondarenko 25.2.2005, 16:57
Дорогой Girder!
Все ра-бо-та-ет!!!!!!!
Спасибо!!!!!!!!!!!!!!!!!!!!
Но, к сожалению, головная боль осталась.
Я же все это делал чтобы добраться до СD, а
IOCTL_DISK_PERFORMANCE как выяснилось с СД не работает.

Но я видел команду IOCTL_CDROM_TOC_ATIP (пишу по памяти может не очень точно),
для чтения ATIP на CD,
а там требуется такая структура.

Цитата
typedef struct _CDROM_TOC_ATIP_DATA_BLOCK {
  UCHAR  CdrwReferenceSpeed : 3;
  UCHAR  Reserved3          : 1;
  UCHAR  WritePower        : 3;
  UCHAR  True1              : 1;
  UCHAR  Reserved4      : 6;
  UCHAR  UnrestrictedUse : 1;
  UCHAR  Reserved5      : 1;
  UCHAR  A3Valid  : 1;
  UCHAR  A2Valid  : 1;
  UCHAR  A1Valid  : 1;
  UCHAR  Reserved6 : 3;
  UCHAR  IsCdrw    : 1;
  UCHAR  True2    : 1;
  UCHAR  Reserved7;
  UCHAR  LeadInMsf[3];
  UCHAR  Reserved8;
  UCHAR  LeadOutMsf[3];
  UCHAR  Reserved9;
  UCHAR  A1Values[3];
  UCHAR  Reserved10;
  UCHAR  A2Values[3];
  UCHAR  Reserved11;
  UCHAR  A3Values[3];
  UCHAR  Reserved12;
}

Здесь, как видно, первые 13 переменных битовые. Но как задать в записи Delphi
переменную из 1 или 3 бит черт его знает, ума не приложу. Може ты или кто-то другй подскажет. Прошу прощения если вопросы покажутся уж очень детским.
С большой благодарностью и уважением,
Виктор

Автор: Soldat 26.2.2005, 10:24
Код

type struct _CDROM_TOC_ATIP_DATA_BLOCK=record
            par1:byte;// UCHAR CdrwReferenceSpeed : 3;
                             // UCHAR Reserved3 : 1;
                             // UCHAR WritePower : 3;
                             // UCHAR True1 : 1;

            par2:byte;// UCHAR Reserved4 : 6;
                             // UCHAR UnrestrictedUse : 1;
                             // UCHAR Reserved5 : 1;
           
            par3:byte;// UCHAR A3Valid : 1;
                             // UCHAR A2Valid : 1;
                             // UCHAR A1Valid : 1;
                             // UCHAR Reserved6 : 3;
                             // UCHAR IsCdrw : 1;
                             // UCHAR True2 : 1;
           //...
       end;

Дальше, при помощи логических операций и операторов сдвига считывать или записывать.
Ex:
Код

function GetCdrwReferenceSpeed(t:struct _CDROM_TOC_ATIP_DATA_BLOCK):byte;
var i:byte;
begin
i:=t.par1;
i:=i and $E0; //$E0=1110 0000b
i:=i shr 5;
result:=i;
end;

Автор: VictorBondarenko 3.3.2005, 20:28
Уважаемые Girder, Soldat и другие!
Я все пытаюсь напрямую что-нибудь прочитать с СД. Но головная боль все не проходит.
Ничерта не получается. Ниже привожу процедуру для чтения ATIP c сидюка.
Я поставил GetLastError, которая выдает ошибку 87 выполнения функции DeviceIoControl.
Заранее благодарю если кто чего заметит и подскажет.
С уважением,
Виктор

Код
{$A8}
procedure TForm1.Button3Click(Sender: TObject);
const
CDROM_READ_TOC_EX_FORMAT_ATIP= $4;  
IOCTL_CDROM_READ_TOC_EX = $24054;            
type
CDROM_TOC_ATIP_DATA_BLOCK =record
a1:  byte;
    //UCHAR  CdrwReferenceSpeed : 3;
    //UCHAR  Reserved3          : 1;
    //UCHAR  WritePower         : 3;
    //UCHAR  True1              : 1;
a2:  byte;
     //UCHAR  Reserved4       : 6;
     //UCHAR  UnrestrictedUse : 1;
     //UCHAR  Reserved5       : 1;
a3:  byte;
     //UCHAR  A3Valid   : 1;
     // UCHAR  A2Valid   : 1;
     //UCHAR  A1Valid   : 1;
     //UCHAR  Reserved6 : 3;
     //UCHAR  IsCdrw    : 1;
     //UCHAR  True2     : 1;
  Reserved7:UCHAR;
   LeadInMsf:array[0..2]of UCHAR;
   Reserved8:UCHAR;
   LeadOutMsf:array[0..2]of UCHAR;
  Reserved9:UCHAR;
   A1Values:array[0..2]of UCHAR;
  Reserved10:UCHAR;
   A2Values:array[0..2]of UCHAR;
  Reserved11:UCHAR;
   A3Values :array[0..2]of UCHAR;
   Reserved12:UCHAR;
end;


CDROM_READ_TOC_EX = record
  par1: byte;
  //Format : UCHAR:4;
 // Reserved1 : UCHAR:3;
 // Msf : UCHAR:1;
  SessionTrack:UCHAR;
  Reserved2:UCHAR;
  Reserved3:UCHAR;
end;


CDROM_TOC_ATIP_DATA =record
   Length:array [0..1] of UCHAR;
   Reserved1:UCHAR;
   Reserved2:UCHAR;
   Descriptors: array [0..0] of CDROM_TOC_ATIP_DATA_BLOCK;
                       end;


var
a:string;
hCDDevice : THandle;
DriveLetter : char;
d:Bool;
in_data: CDROM_READ_TOC_EX;
out_size:DWORD;
out_data: CDROM_TOC_ATIP_DATA;

begin
in_data.par1:=$41;
//in_data.Format  := CDROM_READ_TOC_EX_FORMAT_ATIP;
//in_data.Reserved1 := 0;
//in_data.Msf     :=1;
in_data.SessionTrack :=  0;

DriveLetter := 'F';
hCDDevice := CreateFile(PChar('\\.\'+DriveLetter+':'),
GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0 );

if hCDDevice <> INVALID_HANDLE_VALUE then
    begin
d:=DeviceIoControl(hCDDevice,
 IOCTL_CDROM_READ_TOC_EX,
 @in_data,
 sizeof(in_data),
@out_data,
sizeof(out_data),
 out_size,
 nil );

 if  d  = True then
       begin
str(out_data.Descriptors[0].LeadInMsf[0],a);
ShowMessage(a);
       end
       else ShowMessage('Ошибка:'+IntToStr(GetLastError));
 CloseHandle(hCDDevice);
   end
 else ShowMessage(' Ошибка  в Create file'+IntToStr(GetLastError));
end;


Высвечивается Ошибка 87

Автор: p0s0l 6.3.2005, 14:40
Нужно вместо строк:
Код
in_data.par1:=$41;
//in_data.Format  := CDROM_READ_TOC_EX_FORMAT_ATIP;
//in_data.Reserved1 := 0;
//in_data.Msf     :=1;
in_data.SessionTrack :=  0;

написать:
Код
 FillChar (in_data, SizeOf(in_data), 0);
 FillChar (out_data, SizeOf(out_data), 0);

 in_data.par1 := $84;
 in_data.SessionTrack :=  0;
т.к. биты идут не так, как ты думал, и зарезервированные поля должны быть нулями...
Но я сколько дисков не пробовал, всегда ATIP - пустой (out_data.Length = 2)...
Если в поле Format (in_data.par1) ставить не 4, а 0,1,2 или 5 - то возвращаются различные данные... а ATIP не получается...

Автор: VictorBondarenko 10.3.2005, 14:41
Уважаемый p0s0l и другие уважаемые люди!

Я внес рекомендованые тобой изменения, но все равно выскакивает
Ошибка 97. Не читается даже пустой ATIP.


Пробовал другой формат для чтения с СД текстовой информации
CDROM_READ_TOC_EX_FORMAT_CDTEXT=$5;
Конечно поменял и
var
out_data: CDROM_TOC_CD_TEXT_DATA;
сделал все как положено ( с моей точки зрения), но выскакивает
Ошибка 1.

Я уже думаю может что-то с операционной системой
У меня стоит ХР , а Delphi 7.0

Еще раз привожу полный текст процедуры для чтения ATIP
может кто-то что-то заметит.
С уважением,
Виктор

Код
{$A8}
procedure TForm1.Button3Click(Sender: TObject);
const
CDROM_READ_TOC_EX_FORMAT_ATIP= $4;  
IOCTL_CDROM_READ_TOC_EX = $24054;
type
CDROM_TOC_ATIP_DATA_BLOCK =record
a1:  byte ;
     //UCHAR  CdrwReferenceSpeed : 3;
     //UCHAR  Reserved3          : 1;
     //UCHAR  WritePower         : 3;
     //UCHAR  True1              : 1;
a2:  byte;
      //UCHAR  Reserved4       : 6;
      //UCHAR  UnrestrictedUse : 1;
      //UCHAR  Reserved5       : 1;
a3:  byte;
      //UCHAR  A3Valid   : 1;
      // UCHAR  A2Valid   : 1;
      //UCHAR  A1Valid   : 1;
      //UCHAR  Reserved6 : 3;
      //UCHAR  IsCdrw    : 1;
      //UCHAR  True2     : 1;
   Reserved7:UCHAR ;
    LeadInMsf:array[0..2]of UCHAR;
   Reserved8:UCHAR;
    LeadOutMsf:array[0..2]of UCHAR;
   Reserved9:UCHAR ;
    A1Values:array[0..2]of UCHAR;
   Reserved10:UCHAR ;
    A2Values:array[0..2]of UCHAR;
   Reserved11:UCHAR ;
    A3Values :array[0..2]of UCHAR;
   Reserved12:UCHAR;
end;


CDROM_READ_TOC_EX = record
   par1: byte;
   //Format : UCHAR:4 ;
  // Reserved1 : UCHAR:3;
  // Msf : UCHAR:1 ;
   SessionTrack:UCHAR;
   Reserved2:UCHAR ;
   Reserved3:UCHAR;
end;


CDROM_TOC_ATIP_DATA =record
    Length:array [0..1] of UCHAR;
    Reserved1:UCHAR;
    Reserved2:UCHAR;
   Descriptors: array [0..0] of CDROM_TOC_ATIP_DATA_BLOCK;
                        end;


var
a:string;
 hCDDevice : THandle;
 DriveLetter : char;
d:Bool;
in_data: CDROM_READ_TOC_EX;
out_size:DWORD ;
out_data: CDROM_TOC_ATIP_DATA ;

begin
FillChar( in_data,SizeOf(in_data),0);
FillChar( out_data,SizeOf(out_data),0);
in_data.par1:=$84;
//in_data.Format  := CDROM_READ_TOC_EX_FORMAT_ATIP;
//in_data.Reserved1 := 0;
//in_data.Msf     :=1;
 in_data.SessionTrack :=  0;

DriveLetter := 'F';
hCDDevice := CreateFile(PChar('\\.\'+DriveLetter+':'),
 GENERIC_READ,
 FILE_SHARE_READ or FILE_SHARE_WRITE,
 nil,
 OPEN_EXISTING,
 FILE_ATTRIBUTE_NORMAL,
 0 );

 if hCDDevice <> INVALID_HANDLE_VALUE then
     begin
 d:=DeviceIoControl(hCDDevice,
  IOCTL_CDROM_READ_TOC_EX,
  @in_data,
  sizeof(in_data),
 @out_data,
 sizeof(out_data),
  out_size,
  nil );

  if  d  = True then
        begin
str(out_data.Descriptors[0].LeadInMsf[0],a);
ShowMessage(a);
        end
        else ShowMessage(' Ошибка:'+IntToStr(GetLastError));
  CloseHandle(hCDDevice);
    end
  else ShowMessage(' Ошибка в Create file'+IntToStr(GetLastError));
end;

Автор: p0s0l 10.3.2005, 15:40
У меня работает этот код, ничего не менял...
Мож у тебя CD-диск какой глючный ? Или CDROM недоделанный ? smile
Попробуй установить виртуальный CDRom - я проверял Alcohol, Daemon и VirtualCD4 - со всеми работает...

Автор: VictorBondarenko 16.3.2005, 20:02
Уважаемый Posol и другие умные люди!
Я что-то пощелкал, код тоже не менял и РА-БО-ТА-ЕТ!!!!!!!!!!!!!!!!!!!!!!!!!!!
ATIP читается нормально, но Алкоголь120% вносит какую-то фигню. Когда он стоял, то ATIP давал все нули и Length=2 как ты писал. Я его снял и стало читаться нормально. Кроме того, я читал ATIP программой CDRIdentifier v.1.63 результаты совпадают с моей прогой. Так когда стоял Алкоголь CDRIdentifier v.1.63 перестает работать все выдает unknown.
Так что с этим Алкоголем надо быть осторожным.
Но вот, дальше пошли какие-то чудеса, какая-то фигня.
Я со своей прогой, которая у меня правильно читает ATIP, со своим проверенным СД-диском, пошел поработать на другие компы.
Два компа, как и мой, под ХР показали: первый ATIP - 0, второй - совершенно другое значение ATIP этого же диска чем читалось на моем компе????????????!!!!!!!!!
Комп под 2000 выдал Ошибку 1.
Два компа под 98 там прога даже не добралась до DeviceIoControl, была ошибка 2 в CreateFile.
Что это за фигня может каких-то dll-ок надо поставить?
Уже голова отказывется что-то понимать. Может кто что присоветует?
С уважением и благодарностью за помощь,
Виктор

Автор: p0s0l 17.3.2005, 00:04
Цитата
Два компа под 98 там прога даже не добралась до DeviceIoControl, была ошибка 2 в CreateFile.
Это и не должно работать под 98-ой...
Наверное, придётся заюзать ASPI, т.к. это универсальный метод для работы под любой виндой... Правда, придётся таскать с собой DLL-ку... (хотя возможно обойтись и без DLL, если напрямую работать с драйвером через DeviceIoControl, но этим я не занимался)...
Щас у себя попробовал - тоже якобы "читается" ATIP (т.е. Length = 2):
Код
var
  Buffer : array [0..2047] of byte;
  srbExec : SRB32_ExecSCSICmd;

begin
  LoadAspiLibrary;
  GetASPI32SupportInfo;

  FillChar (srbExec, SizeOf(srbExec), 0);
  srbExec.SRB_Cmd := SC_EXEC_SCSI_CMD;
  srbExec.SRB_HaId := 3; // Указать нужный CD-ROM!
  srbExec.SRB_Target := 0; // Указать нужный CD-ROM!
  srbExec.SRB_Flags := SRB_DIR_IN;
  srbExec.SRB_BufLen := SizeOf(Buffer);
  srbExec.SRB_BufPointer := @Buffer;
  srbExec.SRB_SenseLen := SENSE_LEN;
  srbExec.SRB_CDBLen := 10;
  srbExec.CDBByte[0] := $43;
  srbExec.CDBByte[1] := $02;
  srbExec.CDBByte[2] := $04;

  FillChar (Buffer, SizeOf(Buffer), $AA);

  SendASPI32Command (@srbExec);
end;

Добавлено @ 00:09
ЗЫ: Просьба, плиз, юзай функцию SysErrorMessage( <код ошибки> ), она возвратит текстовое описание ошибки... В форуме пиши не код ошибки, а её название...

Автор: Guest 28.3.2005, 11:45
Бью еще раз челом Послу и другим не менее уважаемым людям!
А фигня вот такая получается:
1. Я пытался получить информацию о SCSI –устройстве TargetId, Lun, Host , но получил сообщение 1-Неверная функция. Коды процедуры привожу ниже. Может быть кто-то что-то подскажет.
2. Попробовал с помощью ASPI читать ATIP, но не получилось. Я установил Adaptec ASPI, но при установке написано, что он для NT, а у меня ХР. Может быть в этом дело? Хотя было сообщение о том, что установлено сексессфул.У кого-то есть такие сведения?
3. Где ( в каких структурах) находиться название фирмы-производителя СД диска и тип материала поверхности СД ( к примеру, какой-то там Фтор….циан…)? Перерыл весь DDK 2600, но чего-то не заметил. Может кто знает?
C уважением и благодарностью за внимание,
Виктор

Код
procedure TForm1.Button6Click(Sender: TObject);
const
IOCTL_SCSISCAN_GET_INFO=$190022;
MAX_STRING=128;
type
SCSISCAN_INFO =record
    Size:DWORD;
    Flags:DWORD;
    PortNumber:UCHAR ;
    PathId:UCHAR;
    TargetId:UCHAR;
    Lun:UCHAR;
    AdapterName:array[0..MAX_STRING-1] of UCHAR;
    Reserved:DWORD;
   end;
var
a:string;
i:integer;
 hCDDevice : THandle;
 DriveLetter : char;
d:Bool;

out_size:DWORD ;
out_data:SCSISCAN_INFO ;

begin

FillChar( out_data,SizeOf(out_data),0);

  a:=edit2.text;
  DriveLetter :=a[1]; //  'f';
hCDDevice := CreateFile(PChar('\\.\'+DriveLetter+':'),
 GENERIC_READ,
 FILE_SHARE_READ or FILE_SHARE_WRITE,
 nil,
 OPEN_EXISTING,
 FILE_ATTRIBUTE_NORMAL,
 0 );

 if hCDDevice <> INVALID_HANDLE_VALUE then
     begin
    FillChar( out_data,SizeOf(out_data),0);
    out_data.Flags:=0;
 d:=DeviceIoControl(hCDDevice,
  IOCTL_SCSISCAN_GET_INFO,
  nil,
  0,
 @out_data,
 sizeof(out_data),
  out_size,
  nil );

  if  d  = True then
        begin
        memo1.Lines.Clear;
       str(out_data.PortNumber,a);
      memo1.Lines.Add('SCSI adapter number='+a);
       str(out_data.PathId,a);
        memo1.Lines.Add('Host SCSI ID='+a);
       str(out_data.TargetId,a);
        memo1.Lines.Add('Target SCSI ID='+a);
         str(out_data.Lun,a);
       memo1.Lines.Add('Target logical unit number='+a);
        end
        else ShowMessage('Ошибка:'+IntToStr(GetLastError)+
        SysErrorMessage(GetLastError));
  CloseHandle(hCDDevice);
    end
  else ShowMessage(' Ошибка в Create file'+IntToStr(GetLastError)+
  SysErrorMessage(GetLastError));
end;

Автор: ArkaNN 14.1.2006, 00:59
Здравствуйте, уважаемые!!!

Код, приведенный в сообщении от 10.3.2005, 14:41 у меня тоже работает. Только, как из out_data вытащить серийный номер диска.

Заранее спасибо, Аркадий...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)