content: package org.flashtool.jna.win32;
  
  import java.io.IOException;
  
  import org.flashtool.flashsystem.io.USBFlashLinux;
  import org.flashtool.jna.linux.JUsb;
  import org.flashtool.system.Devices;
  import org.flashtool.util.BytesUtil;
  import org.flashtool.util.HexDump;
  
  import com.sun.jna.Native;
  import com.sun.jna.platform.win32.Kernel32;
  import com.sun.jna.platform.win32.Kernel32Util;
  import com.sun.jna.platform.win32.WinBase;
  import com.sun.jna.platform.win32.WinNT;
  import com.sun.jna.ptr.IntByReference;
  import com.sun.jna.ptr.PointerByReference;
  import com.sun.jna.win32.W32APIOptions;
  
  import lombok.extern.slf4j.Slf4j;
  
  @Slf4j
  public class JKernel32 {
  
  
  	public static Kernel32RW kernel32 = (Kernel32RW) Native.loadLibrary("kernel32", Kernel32RW.class, W32APIOptions.UNICODE_OPTIONS);
  	static WinNT.HANDLE HandleToDevice = WinBase.INVALID_HANDLE_VALUE;
  	static WinBase.OVERLAPPED ovwrite = new WinBase.OVERLAPPED();
  
  	public static boolean openDevice() throws IOException {
          /* Kernel32RW.GENERIC_READ | Kernel32RW.GENERIC_WRITE not used in dwDesiredAccess field for system devices such a keyboard or mouse */
          int shareMode = WinNT.FILE_SHARE_READ | WinNT.FILE_SHARE_WRITE;
          int Access = WinNT.GENERIC_WRITE | WinNT.GENERIC_READ;
  		HandleToDevice = Kernel32.INSTANCE.CreateFile(
                  Devices.getConnectedDeviceWin32().getDevPath(), 
                  Access, 
                  shareMode, 
                  null, 
                  WinNT.OPEN_EXISTING, 
                  0,//WinNT.FILE_FLAG_OVERLAPPED, 
                  (WinNT.HANDLE)null);
  		if (HandleToDevice == WinBase.INVALID_HANDLE_VALUE) throw new IOException(getLastError());
  		return true;
  	}
  
  	public static boolean openDeviceAsync() throws IOException {
          /* Kernel32RW.GENERIC_READ | Kernel32RW.GENERIC_WRITE not used in dwDesiredAccess field for system devices such a keyboard or mouse */
          int shareMode = WinNT.FILE_SHARE_READ | WinNT.FILE_SHARE_WRITE;
          int Access = WinNT.GENERIC_WRITE | WinNT.GENERIC_READ;
  		HandleToDevice = Kernel32.INSTANCE.CreateFile(
                  Devices.getConnectedDeviceWin32().getDevPath(), 
                  Access, 
                  shareMode, 
                  null, 
                  WinNT.OPEN_EXISTING, 
                  WinNT.FILE_FLAG_OVERLAPPED, 
                  (WinNT.HANDLE)null);
  		if (HandleToDevice == WinBase.INVALID_HANDLE_VALUE) throw new IOException(getLastError());
  		return true;
  	}
  
  	public static byte[] readBytes(int length) throws IOException {
  		IntByReference nbread = new IntByReference();
  		byte[] b = new byte[length];
  		boolean result = kernel32.ReadFile(HandleToDevice, b, length, nbread, null);
  		if (!result) throw new IOException("Read error :"+getLastError());
  		return BytesUtil.getReply(b,nbread.getValue());
  	}
  
  	public static WinNT.HANDLE createEvent() throws IOException {
  		WinNT.HANDLE hevent = kernel32.CreateEvent(null, false, false, null);
  		int res = kernel32.GetLastError();
  		if (hevent == WinBase.INVALID_HANDLE_VALUE || res!=0)
  				throw new IOException(JKernel32.getLastError());
  		return hevent;
  	}
  	
  	
  	public static void sleep(int ms) {
  		try {
  			Thread.sleep(ms);
  		} catch (Exception e) {}
  	}
  	
  	public static boolean writeBytes(byte bytes[]) throws IOException {
  		IntByReference nbwritten = new IntByReference();
  		boolean result = kernel32.WriteFile(HandleToDevice, bytes, bytes.length, nbwritten, null);
  		if (!result) throw new IOException(getLastError());
  		if (nbwritten.getValue()!=bytes.length) throw new IOException("Did not write all data");
  		bytes = null;
  		return result;
  	}
  
  	public static boolean closeDevice() {
  		boolean result = true;
  		
  		if (HandleToDevice != WinBase.INVALID_HANDLE_VALUE) {
  			result = kernel32.CloseHandle(HandleToDevice);
  		}
  		HandleToDevice = WinBase.INVALID_HANDLE_VALUE;
  		return result;
  	}
  	
  	public static int getLastErrorCode() {
  		return Kernel32.INSTANCE.GetLastError();
  	}
  	
  	public static String getLastError() {
  		return Kernel32Util.getLastErrorMessage();
  	}
  
  }