Общение с USB-накопителем как с файлом!
От: aconite Беларусь  
Дата: 18.11.09 20:58
Оценка:
Необходимо реализовать общение с USB-накопителем (USB 2.0) как с файлом. Точнее скопировать всё содержимое флешки (ввод/вывод). Данный код выдран из MSDN, а функция чтения (ReadFile()) заимствована из книги Агурова "USB.Практика". Имя доступа USB верное (\\?\...).
ReadFile() = 0 GetLastError() = 87 (ERROR_INVALID_PARAMETER/The parameter is incorrect.)
Помогите, чем можете!!!

class FileReader
{
    const uint GENERIC_READ = 0x80000000;
    const uint OPEN_EXISTING = 3;
    System.IntPtr handle;

    [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
    static extern unsafe System.IntPtr CreateFile
    (
        string FileName,          // file name
        uint DesiredAccess,       // access mode
        uint ShareMode,           // share mode
        uint SecurityAttributes,  // Security Attributes
        uint CreationDisposition, // how to create
        uint FlagsAndAttributes,  // file attributes
        int hTemplateFile         // handle to template file
    );

    [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
    static extern unsafe bool ReadFile
    (
        System.IntPtr hFile,      // handle to file
        void* pBuffer,            // data buffer
        int NumberOfBytesToRead,  // number of bytes to read
        int* pNumberOfBytesRead,  // number of bytes read
        int Overlapped            // overlapped buffer
    );
    [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
    static extern unsafe int GetLastError();


    [System.Runtime.InteropServices.DllImport("kernel32", SetLastError = true)]
    static extern unsafe bool CloseHandle
    (
        System.IntPtr hObject // handle to object
    );

    public bool Open(string FileName)
    {
        // open the existing file for reading       
        handle = CreateFile
        (
            FileName,
            GENERIC_READ,
            0,
            0,
            OPEN_EXISTING,
            0,
            0
        );
        System.Console.WriteLine("handle: {0}", handle);// получает 

        if (handle != System.IntPtr.Zero)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public unsafe int Read(byte[] buffer, int index, int count)
    {
        int n = 0;
        bool s;
        fixed (byte* p = buffer)
        {
            s = ReadFile(handle, p + index, count, &n, 0);
            System.Console.WriteLine("ReadFile(): {0} Error: {1}", s, GetLastError()); // ReadFile()=FALSE  Error=87
            if (!s)
            {
                return 0;
            }
        }
        return n;
    }

    public bool Close()
    {
        return CloseHandle(handle);
    }
}

class Test
{
    static int Main(string[] args)
    {

        byte[] buffer = new byte[128];
        FileReader fr = new FileReader();
        // string name = @"g:\1.txt";
        string name = @"\\?\USB#vid_0951&pid_1625#0019e06b07aeb980d0000097#{a5dcbf10-6530-11d2-901f-00c04fb951ed}";

        if (fr.Open(name))
        {
            // Assume that an ASCII file is being read.
            System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding();

            int bytesRead;
            do
            {
                bytesRead = fr.Read(buffer, 0, buffer.Length);
                string content = Encoding.GetString(buffer, 0, bytesRead);
                System.Console.Write("{0}", content);
                System.Console.Read();
            }
            while (bytesRead > 0);

            fr.Close();
            return 0;
        }
        else
        {
            System.Console.WriteLine("Failed to open requested file");
            return 1;
        }
    }
}
Re: Общение с USB-накопителем как с файлом!
От: Мизантроп  
Дата: 19.11.09 04:08
Оценка:
Здравствуйте, aconite, Вы писали:

Начать, вероятно, надо с этого:

A> if (handle != System.IntPtr.Zero)

A> {
A> return true;
A> }
A> else
A> {
A> return false;
A> }

CreateFile в случае ошибки возвращает не ноль, а INVALID_HANDLE_VALUE, которая равна -1 в знаковом представлении. А вообще стоило бы завернуть это дело в FileStream, оно как-бы более идеалогически выдержано


    [DllImport("kernel32.dll", SetLastError = true)]
    static extern IntPtr CreateFile(String lpFileName,
            uint dwDesiredAccess, uint dwShareMode,
            IntPtr lpSecurityAttributes, uint dwCreationDisposition,
            uint dwFlagsAndAttributes, IntPtr hTemplateFile);

    public FileStream Open(string FileName)
    {
            IntPtr H = CreateFile(FileName, 0x80000000, 0,
                IntPtr.Zero, 3, 0x40000080, IntPtr.Zero);
            SafeFileHandle SF = new SafeFileHandle(H, true);
            if (SF.IsInvalid)
            {
                int hr = Marshal.GetHRForLastWin32Error();
                Marshal.ThrowExceptionForHR(hr);
            }
            return new FileStream(SF, FileAccess.Read, 0x10000, true);
    }
"Нормальные герои всегда идут в обход!"
Re[2]: Общение с USB-накопителем как с файлом!
От: _d_m_  
Дата: 19.11.09 04:49
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>CreateFile в случае ошибки возвращает не ноль, а INVALID_HANDLE_VALUE, которая равна -1 в знаковом представлении. А вообще стоило бы завернуть это дело в FileStream, оно как-бы более идеалогически выдержано


FileStream с негодованием отвергает имена "\\?\...", а также COMx, LPTx и прочее.
Re[3]: Общение с USB-накопителем как с файлом!
От: Мизантроп  
Дата: 19.11.09 05:04
Оценка:
Здравствуйте, _d_m_, Вы писали:

___>FileStream с негодованием отвергает имена "\\?\...", а также COMx, LPTx и прочее.


С прискорбием должен констатировать, что Вы невнимательны Файл открывается с помощью CreateFile, для которой такие имена проблемой не являются. А уже полученный хёндл используется для создания FileStream. Я такой подход использовал для MailSlots, работает.
"Нормальные герои всегда идут в обход!"
Re[4]: Общение с USB-накопителем как с файлом!
От: _d_m_  
Дата: 19.11.09 06:09
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Здравствуйте, _d_m_, Вы писали:


___>>FileStream с негодованием отвергает имена "\\?\...", а также COMx, LPTx и прочее.


М>С прискорбием должен констатировать, что Вы невнимательны Файл открывается с помощью CreateFile, для которой такие имена проблемой не являются. А уже полученный хёндл используется для создания FileStream. Я такой подход использовал для MailSlots, работает.


Таким образом получается, что ограничение на открытие файлов с неугодными именами выглядит вопиюще странно.
Re[5]: Общение с USB-накопителем как с файлом!
От: Мизантроп  
Дата: 19.11.09 07:05
Оценка:
Здравствуйте, _d_m_, Вы писали:

___>Таким образом получается, что ограничение на открытие файлов с неугодными именами выглядит вопиюще странно.


Что же делать, такова Microsoft, данная нам в ощущениях Если поднапрячься, то вероятно можно придумать объяснение и для этой станности. Например, реферанс в сторону кроссплатформенности, в расчёте на платформы, на которых аналог CreateFile не принимает имена формата UNC. Это первое, что пришло мне в голову, когда я столкнулся с такой реакцией FileStream. И способ обойти это ограничение тоже, кстати, первый пришедший в голову
Но честно говоря, мне такое объяснение представляется сильно притянутым за уши.
"Нормальные герои всегда идут в обход!"
Re: Общение с USB-накопителем как с файлом!
От: Pavel_Agurov Россия  
Дата: 19.11.09 07:14
Оценка:
Здравствуйте, aconite, Вы писали:

A>Необходимо реализовать общение с USB-накопителем (USB 2.0) как с файлом. Точнее скопировать всё содержимое флешки (ввод/вывод). Данный код выдран из MSDN, а функция чтения (ReadFile()) заимствована из книги Агурова "USB.Практика". Имя доступа USB верное (\\?\...).

A>ReadFile() = 0 GetLastError() = 87 (ERROR_INVALID_PARAMETER/The parameter is incorrect.)
A>Помогите, чем можете!!!

Задача описана не понятно. Если вы откроете USB порт по имени что-то вроде
\\?\hid#hpq0006&col01#3&563a312&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
то и данные будете читать с порта. Только тогда надо общаться с флешкой как с HID-устройством.
Никакого отношения к файловой системе и файлам это иметь не будет. Например, можно будет узнать
протокол обмена с флешкой (репорты), число конечных точек USB и т.д.

А вы что хотите? Прочитать всю флешку на низком уровне, не зависимо от файловой системы?
Тогда надо рыть в сторону протокола USB MASS STORAGE:
http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
Re[2]: Общение с USB-накопителем как с файлом!
От: Аноним  
Дата: 19.11.09 07:43
Оценка:
Здравствуйте, Pavel_Agurov, Вы писали:

P_A>Задача описана не понятно. Если вы откроете USB порт по имени что-то вроде

P_A> \\?\hid#hpq0006&col01#3&563a312&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
P_A>то и данные будете читать с порта. Только тогда надо общаться с флешкой как с HID-устройством.
P_A>Никакого отношения к файловой системе и файлам это иметь не будет. Например, можно будет узнать
P_A>протокол обмена с флешкой (репорты), число конечных точек USB и т.д.

P_A>А вы что хотите? Прочитать всю флешку на низком уровне, не зависимо от файловой системы?

P_A>Тогда надо рыть в сторону протокола USB MASS STORAGE:
P_A>http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
Вопрос как открыть порт USB mass storage через HID .... задача интересная!
Если можно и не напрягаю, про протокол USB MASS STORAGE хоть что напишите. Только вот как тупо скопировать с флешки всё!!!
Pavel_Agurov, большое спасибо за значимый ответ!!!
Re[6]: Общение с USB-накопителем как с файлом!
От: _d_m_  
Дата: 19.11.09 08:00
Оценка:
Здравствуйте, Мизантроп, Вы писали:

М>Здравствуйте, _d_m_, Вы писали:


___>>Таким образом получается, что ограничение на открытие файлов с неугодными именами выглядит вопиюще странно.


М>Что же делать, такова Microsoft, данная нам в ощущениях Если поднапрячься, то вероятно можно придумать объяснение и для этой станности. Например, реферанс в сторону кроссплатформенности, в расчёте на платформы, на которых аналог CreateFile не принимает имена формата UNC. Это первое, что пришло мне в голову, когда я столкнулся с такой реакцией FileStream. И способ обойти это ограничение тоже, кстати, первый пришедший в голову


Сомнительно это все. Выбрасывать исключения на различных платформах нет препятствий. Да и Microsoft кроссплатформенность заботила мало всегда. Лишь для XBox или компактных платформ ее же разве.

М>Но честно говоря, мне такое объяснение представляется сильно притянутым за уши.


Да... Другая тайна кроется в факте этом вероятно.
Re: Общение с USB-накопителем как с файлом!
От: Мизантроп  
Дата: 19.11.09 09:23
Оценка:
Здравствуйте, aconite, Вы писали:

Действительно, не очень понятно, что значит "содержимое флешки (ввод/вывод)". Если Вам нужен образ диска, то может стоит попробовать открыть как обычный логический диск:

        private void button2_Click(object sender, EventArgs e)
        {
            IntPtr H = CreateFile(@"\\.\F:", 
                0x80000000, 3,IntPtr.Zero, 3, 0, IntPtr.Zero);
            SafeFileHandle SF = new SafeFileHandle(H, true);
            MessageBox.Show(H.ToString());
            if (SF.IsInvalid)
            {
                int hr = Marshal.GetHRForLastWin32Error();
                Marshal.ThrowExceptionForHR(hr);
            }
            using (FileStream src = new FileStream(SF, FileAccess.Read, 0x10000, false))
            {
                using (FileStream dst = new FileStream("Dump.bin", FileMode.Create, 
                    FileAccess.Write, FileShare.None, 0x10000))
                {
                    byte[] buf = new byte[0x10000];
                    int i;
                    do
                    {
                        i = src.Read(buf, 0, buf.Length);
                        if (i == 0) break;
                        dst.Write(buf, 0, i);
                    } 
                    while (true);
                }
            }
        }


С флэшкой не проверял, но с жесткими дисками и CD вроде справляется.
"Нормальные герои всегда идут в обход!"
Re[3]: Общение с USB-накопителем как с файлом!
От: Pavel_Agurov Россия  
Дата: 19.11.09 09:35
Оценка:
P_A>>А вы что хотите? Прочитать всю флешку на низком уровне, не зависимо от файловой системы?
P_A>>Тогда надо рыть в сторону протокола USB MASS STORAGE:
P_A>>http://www.usb.org/developers/devclass_docs/usb_msc_overview_1.2.pdf
А>Вопрос как открыть порт USB mass storage через HID .... задача интересная!
А>Если можно и не напрягаю, про протокол USB MASS STORAGE хоть что напишите. Только вот как тупо скопировать с флешки всё!!!

Все таки — что значит "скопировать с флешки все"?
1. Если надо скопировать все файлы, то получите DirectoryInfo, переберите рекурсивно все файлы и копируйте.

2. Куда надо это "все" скопировать? На другую флешку или в backup какой-то?

3. На протокол я ссылку дал, там же можно найти и другие документы. Собственно нужно открыть устройство как HID (в книге это есть — через CreateFile), а дальше общаться с устройством через репорты (т.е. пакеты специального вида). Какие именно пакеты и нужно прочитать в спецификации.

4. Еще есть тут:
http://www.lvr.com/mass_storage.htm

5. Может вот тут еще пример пригодится http://www.codeproject.com/KB/system/usb_lock.aspx
Re: Общение с USB-накопителем как с файлом!
От: Pavel Dvorkin Россия  
Дата: 19.11.09 10:15
Оценка: 1 (1)
Здравствуйте, aconite, Вы писали:

A> s = ReadFile(handle, p + index, count, &n, 0);

A> System.Console.WriteLine("ReadFile(): {0} Error: {1}", s, GetLastError()); // ReadFile()=FALSE Error=87
A> if (!s)
A> {
A> return 0;
A> }

Никакого права вызывать GetLastError тут у тебя нет.

Из описания ReadFile

If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero (0). To get extended error information, call GetLastError

Поэтому до проверки результата ReadFile вызывать ее нельзя. А надо так


            s = ReadFile(handle, p + index, count, &n, 0);
            if (!s)
            {
                System.Console.WriteLine("ReadFile(): {0} Error: {1}", s, GetLastError()); // ReadFile()=FALSE  Error=87
                return 0;
            }


Это во-первых. А во-вторых, проверь в отладке значение handle. Чему оно равно ?
With best regards
Pavel Dvorkin
Re[2]: Общение с USB-накопителем как с файлом!
От: Мизантроп  
Дата: 19.11.09 10:25
Оценка: 10 (1)
Здравствуйте, Pavel Dvorkin, Вы писали:

А в NET документация вообще не велит использовать апишную GetLastError, там может оказаться ошибка от какого-нибудь внутреннего вызова рантаймом. Нужно использовать DllImportAttribute.SetLastError и Marshal.GetLastWin32Error
"Нормальные герои всегда идут в обход!"
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.