#include "stubs_p.h"
#include "lcomp/ioctl.h"

#include <stdio.h>

#ifdef LCOMP_LINUX
   #include <dlfcn.h>
   #include <string.h>
#endif

// 0 sucess 1 error

LCOMP_EXPORT(BOOL) LFreeLibrary(HINSTANCE handle)
{
   #ifdef LCOMP_LINUX
      return dlclose(handle);
   #else
      return !FreeLibrary(handle);
   #endif
}

LCOMP_EXPORT(HINSTANCE) LLoadLibrary(const char *szLibFileName)
{
  #ifdef LCOMP_LINUX
      return dlopen(szLibFileName,RTLD_LAZY);
   #else
      return LoadLibrary(szLibFileName);
   #endif
}

LCOMP_EXPORT(void) *LGetProcAddress(HINSTANCE handle, const char *szProcName)
{
  #ifdef LCOMP_LINUX
      dlerror();
      void *ptr = dlsym(handle,szProcName);
      if(dlerror()==NULL) return ptr;
      return NULL;
   #else
      return GetProcAddress(handle,szProcName);
   #endif
}


LCOMP_EXPORT(BOOL) LCloseHandle(HANDLE hDevice)
{
   #ifdef LCOMP_LINUX
      return close(hDevice);
   #else
      return !CloseHandle(hDevice);
   #endif
}

LCOMP_EXPORT(HANDLE) LCreateFile(const char *szDrvName)
{
   #ifndef LCOMP_LINUX
      ULONG dwCreation = OPEN_EXISTING;
      ULONG dwFlags = FILE_FLAG_OVERLAPPED;
      return CreateFile(szDrvName, GENERIC_WRITE | GENERIC_READ, 0, // single use only no sharing
                        NULL, dwCreation, dwFlags, NULL);
   #else
      return open(szDrvName, O_RDWR);
   #endif

}

// in linux define handle as int
// maximum read/write size is 4096 byte
// see source for limitations...
BOOL LDeviceIoControl(HANDLE hDevice,
                       ULONG dwIoControlCode,
                       LPVOID lpInBuffer,
                       ULONG nInBufferSize,
                       LPVOID lpOutBuffer,
                       ULONG nOutBufferSize,
                       PULONG lpBytesReturned,
                       LPOVERLAPPED lpOverlapped) {
#ifdef LCOMP_LINUX
    BOOL status = FALSE;

    if ((nInBufferSize <= 4096) && (nOutBufferSize <= 4096)) {
        IOCTL_BUFFER ibuf;

        memset(&ibuf,0,sizeof(ibuf));

        if(lpOutBuffer) {
            ibuf.outSize = nOutBufferSize;
            memcpy(ibuf.outBuffer, lpOutBuffer, nOutBufferSize);
        }

        if(lpInBuffer)   {
            ibuf.inSize = nInBufferSize;
            memcpy(ibuf.inBuffer, lpInBuffer, nInBufferSize);
        }

        if (ioctl((int)hDevice, dwIoControlCode, &ibuf) >= 0) {
            if(lpOutBuffer) {
                memcpy(lpOutBuffer, ibuf.outBuffer, nOutBufferSize);
            }
            *lpBytesReturned = ibuf.outSize;
            status = TRUE;
        }
    }
    return status;
#else
   return DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize,
                          lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
#endif
}
