BVG Group
 
Имя:  
Пароль:    
 
 
• Регистрация
• Забыли пароль? 
  РУС     ENG   на главную карта сайта написать письмо
 ооо "Смарт"
+7 (925), (495) 772-45-95
Москва, ул. Космонавта Волкова, дом 10, стр. 1, "CHALLENGER", оф.101.
Skype: ooo_smart   ICQ: 164937826    Написать в Whatsapp            контакты


ВОССТАНОВЛЕНИЕ ДАННЫХ
ВОССТАНОВЛЕНИЕ ДАННЫХ  
 
оборудование
для диагностики
и ремонта
 

 
 
 
 
?iaaen.Iao?eea
 
Top.Mail.Ru
 
 

Скачать учебный фильм как получить доступ к диску из среды .NET

Скачать полный проект получитения доступа к диску из среды .NET


Доступ к диску из среды .NET 

© Олег Васильев, BVG Group, 10.12.2012

Часть I 

Введение 

Всё больше и больше моих знакомых, начинают пользоваться языком C#. Я с удивлением узнаю, что молодые люди, изучив этот язык, начинают пользоваться только им, не углубляясь в дебри более "низкоуровневых" языков вроде Си или С++. Хотя, для моего поколения, сама идея того, что Си является низкоуровневым языком, звучит крайне кощунственно. А какого же уровня тогда ассемблер, спрошу я? "А что это вообще такое?" ответит мне молодое поколение.

Но ладно бы, речь шла только о молодёжи. Это было бы благодатной почвой для написания статьи о том, какие сейчас все лентяи, как все расслабились, не хотят учить правильные языки, тянутся на халяву. Дальше можно было бы повспоминать, как "в наши дни" шли войны за каждый байт памяти СМ1420. Нет, лучше СМ-4... А нет, ещё лучше ЮТ-88, там её вообще мало было. Но не тут-то было. Дело в том, что ряд моих знакомых, относящихся к поколению "старой закалки" тоже переходят под программирования в среде .NET, выбирая или управляемый С++ или С#. Среди них есть вполне уважаемые мною программисты, которые явно знают, что делают. Некоторые из них с пеной у рта доказывают, что необходимость думать об освобождении памяти, сковывает полёт фантазии программиста. Другие высказываются более осторожно, но всё равно не ругают среду .NET, а вполне даже хвалят.

Мне известен даже большой проект по восстановлению данных со стриммеров, реализованный именно на языке С#. Я поговорил с теми, кто его делал. Для связи с аппаратурой, они написали DLLки на обычном С++, а затем подключают их из программы на С#. Всю логическую обработку файловой системы, они выполняют уже на этом языке.

Наш ответ Чембрлену
 

Глядя на всё это безобразие, мы тоже решили попробовать, что же это за такая среда .NET. И чем же её код лучше обычного. И, чтобы "набить руку", мы сделали простенький проектик по доступу к SSD. Получилось очень даже симпатично. Сам проектик был внутренним, причём, прямо скажем, неудачным, так что описывать в статье его не будем (может, потом, когда удастся достичь каких-либо успехов, разве что), но его составной частью был компонент для доступа к любому SATA диску, подключённому через контроллер SIL3132. И возможно, тем, кто пишет свои программы для восстановления данных, он будет полезным.

Наверняка искушённые читатели подмут плечами и скажут: "Эка невидаль, не проще ли просто подключить стандартный запрос IOCTL_ATA_PASS_THROUGH_DIRECT и начать считывать сектора диска через него?". И будут в корне неправы. Берём диск с BADами, подключаем к системе. Если BADы находятся в районе MFT или прочей области метаданных, что будет? правильно, система будет долго грузиться. Иногда настолько долго, что лучше бы она не грузилась вообще (несколько дней). Или, скажем, если файловая система красиво так испорчена (вирусы или ещё какие пакости), что у операционной системы "мозги сносит", что прикажете делать?

Нет, можно испортить сигнатуру 55 АА в Partition Table, тогда по крайней мере, файловая система не будет лазать к диску, но как это сделать? Подключить к другому контроллеру? Очень хорошо, подключить к другому, запустить софт для него, испортить, подключить к системному, запустить софт, написанный на C#. Не многовато ли действий? И всё равно, BAD блоки могут подвесить всю подсистему ввода-вывода, так что даже системный диск перестанет работать. Такое на дисках, подключённых через Windows, встречается сплошь и рядом.

В общем, как ни крути, а использование IOCTL_ATA_PASS_THROUGH_DIRECT - не самый лучший выход. Всё-таки лучше подключить диск к контроллеру, который обслуживается специализированным драйвером, не участвующим в дисковой подсистеме Windows. И к таким драйверам относится разработанный нами драйвер HRTe.sys. Вот через него наш .NET компонент и будет работать. Причём нам показалось неправильным делать "плюсовую" DLL, а затем уже подключать её неуправляемые функции. Это какая-то лишняя работа. Гораздо проще написать смешанный код на языке С++, который одной стороной будет сам стыковаться с WIN32 API, а другой - предоставлять управляемые интерфейсы. И именно такой компонент у нас и получился.

Начинаем работу
 

В первую очередь, стоит сказать, что из-за особенностей драйвера, компонент получился не один, а сразу два. Один следует подключать для исполнения в 32-битной среде, другой - в 64 битной. Да, код на C# будет один и тот же, но так уж устроен драйвер, что в 64 битной среде к нему не может обращаться 32 битное приложение. Потому что если драйвер может дать 64 битный указатель на память, от чего 32 битному EXEшнику немножко поплохеет. Так что, если Вы хотите делать программы под обе среды исполнения - делайте две сборки. Одна будет привязана к 32 битному компоненту SIL3232_Connector, другая - к 64 битному. Подробнее о привязке Вы можете посмотреть в учебном фильме.

Но вот мы создали свой проект и даже подключили к нему компонент для доступа к диску, что делаем дальше? А дальше надо прописать запуск в режиме администратора. Честно говоря, в документе описать процесс получится очень занудно. Будет много букв, много картинок и мало понимания. В учебном фильме же это занимает несколько секунд. поэтому мы вновь отправляем читателя к нему. А тем, кто не хочет смотреть фильм - кратко скажем, что к проекту надо добавить файл манифеста, и уже в этом файле выставить значение флага requestedExecutionLevel равным requireAdministrator. Вот так:

      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
      </requestedPrivileges>
 

Уффф. Подготовка завершена. Теперь заведём глобальную переменную, через которую будем достукиваться до накопителя

 Sil3132_connector.Class1 m_hdd = new Sil3132_connector.Class1();

Перво-наперво, надо выбрать накопитель, ведь в системе может находиться несколько контроллеров, а у каждого контроллера, к тому же, может быть несколько каналов. Делаем это так:

private void OnConnectToDrive(object sender, EventArgs e)
        {
            m_hdd.ConnectToDisk();
 
        }
 

Вообще-то, у функции ConnectToDisk есть результаты. Так что при желании, их можно обрабатывать. Просто программка демонстрационная, и мы не стали этого делать. В серьёзной программе, Вы, само собой, будете более аккуратны. Так что приводим перечень возможных возвращаемых значений. Вот так выглядит прототип функции:

public: errorCodes ConnectToDisk ()

А вот возможные коды ошибок:

	public enum errorCodes
	{
		hddErrNoError = 0,
		hddErrFunctionNotImplemented,
		hddErrCanceledByUser,
		hddErrCanNotOpenDrive,
		hddErrDriveError,
		hddErrWrongAnswerFormat,
		hddErrInvalidParameter,
		hddErrNotEnoughBuffer,
		hddErrFileNotFound,
		hddErrChannelError,
		hddErrTimeout,
		hddErrHasErrors,
		hddErrMiscompared,
		hddErrDriveNotSelected,
		hddErrWriteBackError
	};
 

Запомните этот список. Он же будет использоваться в качестве результата всех остальных функций.

Стоит кратенько упомянуть, что столь страшный вид диалога выбора накопителя, как показан ниже, является следствием нашего слабого опыта работы с библиотекой .NET FrameWork. Мы постарались взять компонент, максимально близкий к MFC-шному CListCtrlDlg (а именно System::Windows::Forms::ListView), но почему-то попытки выставить GridView и прочие вкусности, ни к чему не привели. Мы будем рады, если нам покажут, как это правильно делается под .NET, и исправим проблему в следующих версиях компонента.

А был ли мальчик?
 

Ну всё. компонент подключен, и даже диск выбран, пора подавать ему команды? А вот и нет! Пока что мы выбрали только порт. Есть ли на нём диск - мы ещё не знаем. Мало того, даже если он есть - вполне может статься, что он не "зацепился" с нашим контроллером. Это в IDE всё было просто - есть провода, большую часть времени по ним ничего не передаётся, а периодически проскакивают команды. Ну, или широким потоком льются данные. В SATA же всё иначе. В SATA данные по проводам бегают всё время. Если обмена нет - всё равно по проводам в обе стороны бегут шумовые данные, цель которых - удержать канал в работоспособном виде. А для приведения канала в этот самый работоспособный вид, используется целая ритуальная последовательность, во время которой устройства сначала взаимно сбрасывают друг друга, затем - определяют максимально возможную скорость (а вдруг контроллер трёхгигабитный, а накопитель - шести? Максимально возможной будет скорость три гигабита), после чего каждый из приёмников калибруется, настраивает эквалайзеры, затем устройства сбрасывают свои FIFO буфера, посылая специальный примитив, и лишь после этого канал начинает забиваться специально подобранными шумовыми данными, периодически прерываемыми на передачу примитива ALIGN, который нужен на тот случай, если у устройств немного рассинхронизированы тактовые генераторы.

Вы что-нибудь поняли? Если нет, но хотите - читайте стандарт SATA. Один, два, три, десять раз... Пока не станет понятно. А здесь этот ужас был приведён чисто для того, чтобы показать всю важность начальной инициализации канала. Если эту инициализацию не сделать - даже подключённый накопитель работать не будет. Какие-то контроллеры выполняют эти действия сами, контроллер же SIL3132 необходимо принудительно перевести в режим инициализации канала. И именно для этого существуют две функции в нашем компоненте.

Первая позволяет узнать текущее состояние канала

public: System::UInt32 GetChannelState()

Данные, которые она возвращает, документация описывает следующим образом:

Собственно, мы можем смотреть на биты 3-0, выясняя, есть или нет диск на канале.

public: errorCodes SetChannelState(System::UInt32 andMask,System::UInt32 orMask)

Она производит запись вот в такой порт:

по странному стечению обстоятельств, наиболее ценным являются биты 3-0. Их состояние "0001" как раз заставляет контроллер вновь и вновь пытаться установить соединение. Поэтому, на наш взгляд, установка соединения должна выглядеть следующим образом:

private void OnConnectToDrive(object sender, EventArgs e)
{
    System.Windows.Forms.Cursor oldCursor = Cursor;
    Cursor = System.Windows.Forms.Cursors.WaitCursor;
    m_hdd.ConnectToDisk();
    System.DateTime timeout = System.DateTime.Now.AddSeconds(10);
    m_hdd.SetChannelState(0xfffffff0, 0x1);
    System.UInt32 temp = m_hdd.GetChannelState();
    while ((m_hdd.GetChannelState() & 0x0f) == 0)
    {
        if (System.DateTime.Now > timeout)
        {
            System.Windows.Forms.MessageBox.Show(
			"Drive is not detected on channel", "",
                   System.Windows.Forms.MessageBoxButtons.OK,
			 System.Windows.Forms.MessageBoxIcon.Stop);
            Cursor = oldCursor;
            return;
        }
   }
   m_hdd.SetChannelState(0xfffffff0, 0x0);
   Cursor = oldCursor;
}
 

Возможно, в будущем, время внесёт изменения в этот код.

Примечание: когда снимался учебный фильм, эти две функции ещё отсутствовали, поэтому там про них ничего не сказано.

Наконец-то настоящее дело
 

Жуть, сколько подготовительных работ пришлось выполнить! Но наконец-то мы "зацепились" с диском и убедились, что он имеется на канале. Теперь-то можно начинать реальную работу! Как же мы будем передавать порты в наш накопитель? А давайте сделаем это через такую структуру:

	public ref struct ideTaskFile
	{
		System::Byte port171_prev;
		System::Byte port172_prev;
		System::Byte port173_prev;
		System::Byte port174_prev;
		System::Byte port175_prev;
		System::Byte port171_cur;
		System::Byte port172_cur;
		System::Byte port173_cur;
		System::Byte port174_cur;
		System::Byte port175_cur;
		System::Byte port176_cur;
		System::Byte port177_cur;
		ideTaskFile():port171_prev(0),port172_prev(0),port173_prev(0),port174_prev(0),port175_prev(0),
			port171_cur(0),port172_cur(0),port173_cur(0),port174_cur(0),port175_cur(0),port176_cur(0),port177_cur(0){}
	};
 

Из кода видно, что структура самозануляется при создании. Если какие-то порты равны нулю, специально занулять их не требуется. Хорошо, с портами ясно. А как с данными? Для этого предназначена следующая структура:

public ref struct dataTransferStruct
{
	array <System::Byte>^ buf;
	int dwLen;
	BOOL bSendToDrive;
	BOOL bUseDMA;
	DWORD dwTimeout;
	dataTransferStruct():dwLen (0), bSendToDrive (FALSE),bUseDMA(FALSE),dwTimeout(1000){}
};
 

Если длина (параметр dwLen) равен нулю, значит данные не передаются. Но обратите внимание, что в этой же структуре живёт и значение таймаута (в миллисекундах).

Теперь рассмотрим пару примеров. Вот так выглядит обращение к накопителю, которое принимает из него данные (команда ECh):

private void OnDetectDrive(object sender, EventArgs e)
{
    System.Windows.Forms.Cursor oldCursor = Cursor;
    Cursor = System.Windows.Forms.Cursors.WaitCursor;
    Sil3132_connector.ideTaskFile tf = new Sil3132_connector.ideTaskFile();
    tf.port176_cur = 0xa0;
    tf.port177_cur = 0xec;
 
    Sil3132_connector.dataTransferStruct ts = new Sil3132_connector.dataTransferStruct();
    ts.buf = new byte[0x200];
    ts.dwLen = 0x200;
    ts.dwTimeout = 3000;
 
    if (m_hdd.SendIdeTaskFile(tf, ts) != 0)
    {
        System.Windows.Forms.MessageBox.Show("Error on sending Command", "",
        System.Windows.Forms.MessageBoxButtons.OK,
	  System.Windows.Forms.MessageBoxIcon.Stop);
    }
    else
    {
        Be.Windows.Forms.DynamicByteProvider data = new Be.Windows.Forms.DynamicByteProvider(ts.buf);
        hexBox1.ByteProvider = data;
    }
    Cursor = oldCursor;
}
 

Если же мы пишем данные в накопитель, отличие невелики:

private void OnSetPassword(object sender, EventArgs e)
{
    Sil3132_connector.dataTransferStruct ts = new Sil3132_connector.dataTransferStruct();
    ts.bSendToDrive = 1;
    ts.buf = new byte[0x200];
    int i;
    for (i = 0; i < 0x200; i++)
    {
        ts.buf[i] = 0;
    }
    if (radioButton2.Checked)
    {
        ts.buf[1] = 1;
    }
    for (i = 0; i < 32; i++)
    {
        ts.buf[i + 2] = hexBox2.ByteProvider.ReadByte(i);
    }
    ts.dwLen = 0x200;
    ts.dwTimeout = 0x5000;
    Sil3132_connector.ideTaskFile tf = new Sil3132_connector.ideTaskFile();
    tf.port176_cur = 0xe0;
    tf.port177_cur = 0xf1;
 
    System.Windows.Forms.Cursor oldCursor = Cursor;
    Cursor = System.Windows.Forms.Cursors.WaitCursor;
    if (m_hdd.SendIdeTaskFile(tf, ts) != 0)
    {
        System.Windows.Forms.MessageBox.Show("Error on sending Command", "",
                System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Stop);
    }
    Cursor = oldCursor;
}
 

Более красочно это всё показано в учебном фильме, к которому Вас и отсылаем

Кошка сдохла, хвост облез
 

А что делать, если накопитель "завис"? Ведь при работе с неисправными накопителями, это самое обыденное явление. Для этого в компоненте имеется функция:

errorCodes ResetDrive (int timeOut)

Она будет пытаться "развесить" накопитель, но если пройдёт более, чем timeOut миллисекунд - вернёт ошибку.

А где порты на чтение?
 

Это - самый больной вопрос при работе с SATA накопителем. В IDE протоколе, можно было в любой момент обратиться к любому порту на чтение. Некоторые производители даже строили на этом протоколы обмена, в которых не учсаствовало обращение к регистру команд, а шевелились только определённые порты, после чего считывались отклики. Затем эти протоколы как-то сами собой отошли в небытие. А знаете почему? Потому что стандарт SATA не предусматривает таких вольностей. Там всё построено на пакетах. Послали пакет с портами в накопитель, он отработал, прислал пакет с откликами. И всё. Вот что он сразу прислал, то и придёт. И не более того. чтобы запросить отклик, имеется функция:

void  GetIdeTaskFile (ideTaskFile^ tf)

Она вернёт не текущее состояние портов. Нет, нет и ещё раз нет! И не надейтесь! Она вернёт последний набор портов, который был зафиксирован от накопителя. Если Вы посылали команду полчаса назад - вот тогда он и пришёл. Увы и ах. пока что иного способа не найдено. Если Вы подскажете его - мы будем рады. Но пока, прогнав сотни транзакций через шинный анализатор, мы ничего подобного не заметили. Либо мы слепые, либо это - единственная возможность принять порты (послав команду в накопитель).

Заключение
 

Мы рассмотрели простенький компонент, позволяющий программам, написанных для среды .NET (управляемый C++, C#, Cisual Basic и т.п) обращаться к накопителям через контроллер Silicon Image SIL3132. Для полноценной работы также необходим драйвер HRTe. Так как драйверы для ОС x86 и x64 несовместимы, имеются две версии компонента под эти типы ОС. Ваша задача делать ссылку из своего кода на один из них.

Компоненты достаточно "сырые", но всё-таки позволяют разрабатывать полноценное ПО для восстановления данных или ремонта накопителей. При обнаружении ошибок, мы с удовольствием рассмотрим хорошие описания, позволяющие чётко воспроизвести проблему. Нечёткие описания, увы, рассматриваться не будут.

Также к статье прилагается учебный фильм, в котором все методики рассмотрены в "живом" режиме. В качестве демонстрационного приложения к статье разработана программка, позволяющая устанавливать и снимать пароль на ATA накопителях.

Часть II
 

Введение
 

В предыдущей стате мы рассказали, как получить доступ к накопителю через адаптер SIL3121 фирмы Silicon Image при помощи классических языков, к которым относятся C++ или, скажем, Delphi. Однако, всё большую популярность набирают языки, компилирующие код не в штатный двоичный файл, а в файлы, исполняемые на платформе .NET. К этим языкам относятся Visual Basic, C#, в конце концов, C++ с опцией CLR.

Можно много спорить о достоинствах и недостатках платформы .NET (автор слышал доводы очень уважаемых им программистов, доказывающих как то, что все старые языки достойны забвения, потому что не содержат сборки мусора, так и то, что все эти новомодные языки не годятся для системных задач, потому что .NET - это интерпретатор, а сборщик мусора - медленный бульдозер), но уже есть реальные программы для восстановления данных, написанные под .NET, и они реально работают. Следовательно, было бы неправильно обойти вниманием тех, кто использует данную платформу.

Для того, чтобы помочь программистам, привыкшим к C# или, скажем, Visual Basic, мы разработали простенький .NET компонент, который позволяет получить доступ к адаптеру SIL3132 и совместимым с ним. Может возникнуть вопрос: "Зачем такие сложности? Есть же прекрасный запрос IOCTL_ATA_PASS_THROUGH_DIRECT, необходимо и достаточно импортировать его штатными средствами в свою программу, и дело в шляпе, можно достукиваться до любого системного накопителя". Но дело в том, что если накопитель частично исправен, то включение его в систему может наделать массу бед. Во-первых, система может тупо не загрузиться, так как BAD блоки накопителя "введут её в ступор". Далее, система может "зависнуть" во время работы при "зависании" накопителя. И, наконец, система может попытаться что-то записать на накопитель (особенно этим славится Winwdows XP, которая даже при осмотре каталога обновит время доступа ко всем файлам, имена которых она невзначай разглядела). В общем, как при ремонте накопителя, так и при восстановлении данных, желательно, чтобы накопитель был подключён не к системному, а к автономному каналу, к которому может "достучаться" только ремонтное программное обеспечение. И давайте рассмотрим, как превратить штатный канал на базе SILа в автономный.

Установка драйвера
 

Перво-наперво, необходимо установить специализированный драйвер (тот самый "наш" драйвер, о котором шла речь в предыдущей статье). Адаптер может сиротливо болтаться, как неопознанное устройство, либо "подхватить" стандартный драйвер из набора драйверов Windows. И в том и в другом случае, надо действовать совершенно одинаково. Во-первых, следует сказать Windows, что Вы собираетесь обновить драйвер. Ну, а во-вторых, в-третьих и т.д - действовать, как показано на рисунках ниже.

Далее, надо несколько раз согласиться с предложениями Windows, в результате чего, устройство станет таким:

Теперь плата обслуживается не штатными драйверами из поставки Windows, а драйвером, разработанным в нашей компании. И именно через этот драйвер будет работать .NET компонент.

Разные сборки компонента
 

Компонент существует в виде двух сборок. Одна - для среды x86, вторая - для среды x64. Сборки несовместимы между собой. Однако, код, который ими пользуется, может быть собран в универсальном формате. Следует просто связывать его с той из сборок, которая будет использована Вами. Интерфейсная часть у обоих вариантов ничем не различается.

Константы
 

При разработке компонента, было решено отказаться от результатов функции TRUE и FALSE. Вместо этого, был введён целый перечень ошибок, которые закодированы следующим образом:

	public enum errorCodes
	{
		hddErrNoError = 0,
		hddErrFunctionNotImplemented,
		hddErrCanceledByUser,
		hddErrCanNotOpenDrive,
		hddErrDriveError,
		hddErrWrongAnswerFormat,
		hddErrInvalidParameter,
		hddErrNotEnoughBuffer,
		hddErrFileNotFound,
		hddErrChannelError,
		hddErrTimeout,
		hddErrHasErrors,
		hddErrMiscompared,
		hddErrDriveNotSelected,
		hddErrWriteBackError
	};
 

Других типизированных констант текущая версия компонента не содержит

Структуры
 

Для передачи таскфайла в накопитель, используется классический набор IDE портов, закодированный в следующей структуре:

	public ref struct ideTaskFile
	{
		System::Byte port171_prev; // Features_Prev
		System::Byte port172_prev; // Sector_count_Prev
		System::Byte port173_prev; // Sector_prev
		System::Byte port174_prev; // Cyl_Lo_PRev
		System::Byte port175_prev; // Cyl_Hi_Prev
		// Head_prev и Command_prev - не существует
		System::Byte port171_cur;  // Feature
		System::Byte port172_cur;  // Sector_count
		System::Byte port173_cur;  // Sector
		System::Byte port174_cur;  // Cyl_lo
		System::Byte port175_cur;  // Cyl_Hi
		System::Byte port176_cur;  //Dev/Head
		System::Byte port177_cur;  // Command
	};
 

Имена полям структуры даны в соответствии с IDE портами, что связано с тем, что некоторые программисты больше привыкли именно к этому формату.

Конструктор структуры сделан так, что она автоматически зануляется, поэтому специального зануления в программе пользователя не требуется. Достаточно только заполнить те поля, которые планируется использовать (это показано в учебном фильме, который прилагается к статье).
Для передачи данных, используется следующая структура:

	public ref struct dataTransferStruct
	{
		array <System::Byte>^ buf;
		int dwLen;
		BOOL bSendToDrive;
		BOOL bUseDMA;
		DWORD dwTimeout;
		dataTransferStruct():dwLen (0), bSendToDrive (FALSE),bUseDMA(FALSE),dwTimeout(1000){}
	};
 

buf - массив передаваемых или принимаемых данных (выделяется пользователем)

dwLen - длина в байтах, которую планируется передать или принять

bSendToDrive - TRUE - данные передаются в накопитель, FALSE - принимаются (конструктор по умолчанию, как видно, устанавливает значение в FALSE)

bUseDMA - TRUE - передавать данные в режиме Ultra DMA, FALSE - в режиме PIO. Как уже отмечалось в предыдущей статье, эти два режима отличаются друг от друга только максимальным размером передаваемого пакета FIS46, но тем не менее, контроллер SIL3132 следует настроить на тот или иной режим, для чего и введена переменная

dwTimeout - величина таймаута в миллисекундах

Функции
 

Текущая версия компонента предоставляет следующие функции:

public: errorCodes ConnectToDisk ()

Открывает список всех плат, установленных в данном компьютере, позволяя выбрать одну из них. Также позволяет выбрать один из двух портов платы. Внешний вид списка далёк от идеала, однако, наш опыт работы с .NET компонентами весьма невелик. попытки взводить те или иные флажки в компоненте System::Windows::Forms::ListView не позволили получить красивых линий между строками, как это бывает в MFC-классе CListCtrl. Мы с удовольствием примем предложения по доработке компонента от специалистов по .NET.

errorCodes ResetDrive (int timeOut)

Сборс накопителя (посылка примитива COMRESET с последующей инициализацией канала, что эквивалентно сбросу через линию 1 интерфейса IDE).

timeOut - величина таймаута ожидания выхода накопителя в готовность

errorCodes SendIdeTaskFile (ideTaskFile^ tf,dataTransferStruct^ ts)

Подача таскфайла в накопитель с возможной передачей данных (если поле dwLen транспортной структуры не равно нулю). Направление и способ передачи задаются в транспортной структуре

void  GetIdeTaskFile (ideTaskFile^ tf)

"Получение таскфайла". На самом деле, стандарт SATA не предусматривает полноценного запроса таскфайла. Данная функция передаст содержимое портов, пришедших в ответ на последнюю АТА команду. При этом, если это была PIO операция - не удивляйтесь, что в портах может быть взведён бит DRQ. Дело в том, что таков протокол - кадр FIS5F приходит до передачи данных, а после - нет. Поэтому бит DRQ останется "болтаться" в теневых регистрах, запомненных компонентами.

Возможно, в будущем перечень функций будет дополнен, но это произойдёт только в том случае, если компонент окажется реально востребованным программистами, поэтому мы ждём конструктивной обратной связи.

Заключение
 

Практический опыт работы с компонентом, Вы сможете получить, просмотрев учебный фильм, который реализует функции определения типа накопителя, а также - установки и снятия пароля.

Мы будем рады опубликовать любые программы, разработанные с использованием нашего компонента. Кроме того, мы готовы дорабатывать его с учётом реальных потребностей .NWT программистов. Само собой разумеется, предложения должны быть конкретными и реальными. А учитывая, что на момент написания статьи, общий стаж разработки программ под C# у автора составлял две недели (и это с перерывами до трёх месяцев), желательно все предложения иллюстрировать конкретными фрагментами кода, поясняющего, как это сделать.

Желаем успехов!

eng 
рус
на главную |  наши цены |  наши дилеры |  новости | 
информация по восстановлению данных |  карта сайта 
© 2006-2022 BVG Group
e-mail: office@bvg-group.ru 
   Компания BVG Group - профессиональное восстановление данных с различных цифровых носителей.