DeviceIOControl call with Android Device always return no output length even when success = true


Completely new area of tech for me. Trying to communicate with Android device to eventually do read/write of files back and forth. Special requirement, can NOT use ADB.exe which I originally had and worked perfect, but too many security risks/concerns. Can't use 3rd party tools we don't have source control to for static code analysis (such as Fortify).

I have tried to get rid of all the otherwise C/C++ #defines so no guessing at values, and also included the few DLLImports needed.

I found the string for my Android device and get a successful handle via CreateFile(). However, when I try calling the operation code to GetDeviceInfo (0x1001), I get a success = true, but nothing is returned in the buffer. I even tried overpreparing the size to 1k just for grins. This is a complete class self-contained.

So, aside from testing on anybody's own Android device where you would have to find the symbolic name references from the registry, a call to TestConnectToAndroid() is all I am doing. I suspect I will have more questions once I start getting data coming back.

public class IOAndroidTest
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr CreateFile(
        [MarshalAs(UnmanagedType.LPTStr)] string lpFileName,
        [MarshalAs(UnmanagedType.U4)] uint dwDesiredAccess,     // File Access
        [MarshalAs(UnmanagedType.U4)] uint dwShareMode,         // File Share
        IntPtr lpSecurityAttributes,
        [MarshalAs(UnmanagedType.U4)] uint dwCreationDisposition,   // File Mode
        [MarshalAs(UnmanagedType.U4)] uint dwFlagsAndAttributes,    // File Attributes
        IntPtr hTemplateFile);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall,
        SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle( IntPtr hObject );

    [DllImport("kernel32.dll", CharSet = CharSet.Auto,
        CallingConvention = CallingConvention.StdCall,
        SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool DeviceIoControl(
        IntPtr hDevice,
        // Control code that tells the device what function to do... and method, access, etc via CTL_CODE() 
        uint dwIoControlCode,       // the I/O Control code
        IntPtr lpInBuffer,          // pointer to input buffer
        uint nInBufferSize,         // size of input buffer
        IntPtr lpOutBuffer,         // pointer to output buffer
        uint nOutBufferSize,        // size of output buffer
        ref uint lpBytesReturned,   // ref for return of bytes returned from request
        IntPtr lpOverlapped);       // pointer if using overlapped

    private static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
        return (uint)((DeviceType << 16)
                        | (Access << 14)
                        | (Function << 2)
                        | Method);

    public void TestConnectToAndroid()
        var myAndroid = @"\??\USB#VID_05C6&PID_9091#[and rest of device ID and guid from registry]";

        uint DesiredAccess = 0x80000000;    // generic read
        uint ShareMode = 0x1 | 0x2;         // Read OR Write share mode
        uint BufferedMethod = 0;            // for the CTL_CODE building overall op code

        uint OpenExisting = 3;
        uint InvalidFileHandle = 0xFFFFFFFF;
        IntPtr deviceHandle = CreateFile(

        if (deviceHandle != (IntPtr)InvalidFileHandle)
            uint outBufferSize = 1024;
            uint requiredLength = 0;

            IntPtr readIntoThisBuffer = Marshal.AllocHGlobal((int)outBufferSize);

            uint GetDeviceInfo = 0x1001;

            uint FILE_DEVICE_UNKNOWN = 0x00000022;

            uint opCode = CTL_CODE(FILE_DEVICE_UNKNOWN, GetDeviceInfo, BufferedMethod, DesiredAccess);

            var success = DeviceIoControl(deviceHandle,
                                            opCode,             // GetDeviceInfo built with CTL_CODE above,
                                            IntPtr.Zero,        // No input being sent TO the device
                                            0,                  // input buffer is 0 bytes
                                            readIntoThisBuffer, // IF we are expecting output BACK
                                            outBufferSize,      // output buffer size we are PROVIDING
                                            ref requiredLength, // Actual bytes returned IF successful are written to the buffer
                                            IntPtr.Zero );

            if (success)
                if (requiredLength > 0)
                    Console.WriteLine("There SHOULD be something in the buffer required length");
                    Console.WriteLine("It is always coming here");

            // Now, free the allocated memory buffer

        }   // end - if good device handle connection
asked on Stack Overflow Apr 16, 2021 by DRapp

0 Answers

Nobody has answered this question yet.

User contributions licensed under CC BY-SA 3.0