#include <windows.h>
#include <process.h>
#include <io.h>
#include <conio.h>

#include "..\common.src\bastypes.h"
#include "..\common.src\os.h"

#define IS_NT     (BOOL)(GetVersion() < 0x80000000)
#define IS_WIN32S (BOOL)(!(IS_NT) && (LOBYTE(LOWORD(GetVersion()))<4))
#define IS_WIN95  (BOOL)(!(IS_NT) && !(IS_WIN32S))

DWORD glb_affinity=1;

void OsSleep (unsigned long msec)
{
  Sleep (msec);
}

static BOOL EnableBootPriv( void )
{
  BOOL             rc = FALSE;
  HANDLE           hToken;
  TOKEN_PRIVILEGES tp;
  LUID             luid;

  if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) )
  {
    if( LookupPrivilegeValue( NULL, SE_SHUTDOWN_NAME, &luid ) )
    {
      tp.PrivilegeCount = 1;
      tp.Privileges[0].Luid = luid;
      tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

      if( AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL) )
        rc = TRUE;
    }
  }

  return rc;
}

void OsBoot (void)
{
  if (IS_NT) {
    if (EnableBootPriv()) ExitWindowsEx( EWX_REBOOT, 0);
  } else {
    ExitWindowsEx( EWX_REBOOT, 0);
  }
}

Thread_Id_Typ OsStartThread (void(*startaddr)(void *))
{
  unsigned long id;
  unsigned long parm;
  Thread_Id_Typ thread_handle;

  thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)startaddr,&parm,0,&id);
//  if (IS_NT) SetThreadAffinityMask(thread_handle,glb_affinity);
  return (thread_handle);
}

void          OsStopThread  (Thread_Id_Typ thread_id)
{
  TerminateThread (thread_id,0);
  CloseHandle (thread_id);
}


short OsFindFirst (FileInfoTyp *FileInfo, char *searchmask)
{
  FileInfo->hfile = _findfirst(searchmask, &FileInfo->FindBuffer);

  if (FileInfo->hfile == -1L) {
    strcpy (FileInfo->FileName,"");
    FileInfo->FileSize = 0;
    return (1);
  } else {
    strcpy (FileInfo->FileName,FileInfo->FindBuffer.name);
    FileInfo->FileSize = FileInfo->FindBuffer.size;
    return (0);
  }
}

short OsFindNext  (FileInfoTyp *FileInfo)
{
  long rc;

  rc = _findnext (FileInfo->hfile,&FileInfo->FindBuffer);

  if (!rc) {
    strcpy (FileInfo->FileName,FileInfo->FindBuffer.name);
    FileInfo->FileSize = FileInfo->FindBuffer.size;
  } else {
    strcpy (FileInfo->FileName,"");
    FileInfo->FileSize = 0;
  }
  return ((short)rc);

}

short OsFindClose (FileInfoTyp *FileInfo)
{
  return((short)_findclose(FileInfo->hfile));
}

void  OSCreateMutexSem  (char *v1, HMTX *sem, unsigned long d2, unsigned long d3)
{
  InitializeCriticalSection (sem);
}

void  OSCloseMutexSem   (HMTX *sem)
{
  DeleteCriticalSection (sem);
}

void  OSRequestMutexSem (HMTX *sem, long d1)
{
  EnterCriticalSection (sem);
}

void  OSReleaseMutexSem (HMTX *sem)
{
  LeaveCriticalSection (sem);
}

void  OSBeep (unsigned long frequency, unsigned long duration)
{
  Beep (frequency, duration);
}

void OSSetPriority (unsigned long class)
{
  HANDLE hProcess;

  hProcess = GetCurrentProcess();

  switch (class) {
    case 1 : class = IDLE_PRIORITY_CLASS    ; break;
    case 2 : class = NORMAL_PRIORITY_CLASS  ; break;
    case 3 : class = HIGH_PRIORITY_CLASS    ; break;
    case 4 : class = REALTIME_PRIORITY_CLASS; break;
    default: class = NORMAL_PRIORITY_CLASS  ; break;
  }

  SetPriorityClass(hProcess, class);
}

void  OSProcessAffinity (unsigned long affinity)
{
  glb_affinity = affinity;
//  if (IS_NT) SetProcessAffinityMask(GetCurrentProcess(),glb_affinity);
}


char  Os_kbhit  (void)
{
  return (_kbhit());
}

char  Os_getch  (void)
{
  return (_getch());
}

tU32  OsGetTickCount (void)
{
  return (GetTickCount());
}


void OsMkDir (char *dirpath)
{
  CreateDirectory (dirpath,0);
}


