using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;

namespace RAPIDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            #if DEBUG
                MinimizeBox = false;
            #else
                MinimizeBox = true;
            #endif
        }
        [DllImport("rapi.dll")]
        public static extern void CeRapiInitEx(ref RAPIINIT pRapiInit);

        [StructLayout(LayoutKind.Sequential)]
        public struct RAPIINIT
        {
            public int cbsize;
            public IntPtr heRapiInit;
            public UInt32 hrRapiInit;
        };




        [DllImport("rapi.dll")]
        public static extern int CeRapiInit();

        [DllImport("rapi.dll")]
        static extern int CeRapiUninit();

        [DllImport("rapi.dll")]
        static extern int CeCloseHandle(IntPtr hObject);



        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        static extern IntPtr CeCreateFile(
          string lpFileName,
          uint dwDesiredAccess,
          int dwShareMode,
          int lpSecurityAttributes,
          int dwCreationDisposition,
          int dwFlagsAndAttributes,
          int hTemplateFile);

        [DllImport("rapi.dll", CharSet = CharSet.Unicode)]
        static extern int CeReadFile(
          IntPtr hFile,
          byte[] lpBuffer,
          int nNumberOfbytesToRead,
          ref int lpNumberOfbytesRead,
          int lpOverlapped);

        const int ERROR_SUCCESS = 0;
        const int OPEN_EXISTING = 3;
        const int INVALID_HANDLE_VALUE = -1;
        const int FILE_ATTRIBUTE_NORMAL = 0x80;
        const uint GENERIC_READ = 0x80000000;

        public static void CopyFromDevice(string remote_file, string local_file)
        {
            bool rapi = CeRapiInit() == ERROR_SUCCESS;
            if (!rapi)
            {
                return;
            }

            IntPtr remote_file_ptr = CeCreateFile(
              remote_file,
              GENERIC_READ,
              0,
              0,
              OPEN_EXISTING,
              FILE_ATTRIBUTE_NORMAL,
              0);

            if (remote_file_ptr.ToInt32() == INVALID_HANDLE_VALUE)
            {
                return;
            }

            FileStream local_file_stream = new FileStream(
              local_file,
              FileMode.Create,
              FileAccess.Write);

            int read = 0;
            int size = 1024 * 4;
            byte[] data = new byte[size];

            CeReadFile(remote_file_ptr, data, size, ref read, 0);

            while (read > 0)
            {
                local_file_stream.Write(data, 0, read);
                if (CeReadFile(remote_file_ptr, data, size, ref read, 0) == 0)
                {
                    CeCloseHandle(remote_file_ptr);
                    local_file_stream.Close();
                    return;
                }
            }

            CeCloseHandle(remote_file_ptr);
            local_file_stream.Flush();
            local_file_stream.Close();

            if (rapi)
            {
                CeRapiUninit();
            }

            if (!File.Exists(local_file))
            {
                throw new FileNotFoundException("The file was not copied to the desktop");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CopyFromDevice(@"\windows\alarm1.wma", @"c:\alarm.wma");
        }

        private void button2_Click(object sender, EventArgs e)
        {
            RAPIINIT r = new RAPIINIT();
            r.cbsize = Marshal.SizeOf(r);
            CeRapiInitEx(ref r);
            //r.hrRapiInit==0 indicates succes
        }

    }
}