//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2015 by PDSoft (Attila Padar)                *
//*                http://mpxplay.sourceforge.net                          *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  This program is distributed in the hope that it will be useful,       *
//*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
//*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function: mixed functions

#include <stdlib.h>
#include <dos.h>
#include "mpxplay.h"

#ifdef MPXPLAY_WIN32
 #define WIN32_LEAN_AND_MEAN 1
 #include <windows.h>
 #include <wincon.h>
#endif
#ifdef MPXPLAY_GUI_QT_disable
 #include <DISP_QT/disp_qt.h>
#elif defined(MPXPLAY_WIN32)
 #include <shellapi.h>
#endif

#ifdef __DOS__
extern unsigned int iswin9x,id3textconv;
extern dosmem_t dm_int2x_1;
#endif

static unsigned int firstrand;

unsigned long pds_rand(int maxnum)
{
#ifdef __DOS__
 unsigned int i;
 char *biosmem;
#endif
 unsigned int r;

 if(maxnum<1)
  return 0;
 if(!firstrand){
  srand(pds_gettime());
  firstrand=1;
 }
#ifdef __DOS__
 r=0;
 biosmem=(char *)0;
 for(i=(biosmem[0x46c]&127);i;i--)
  r+=(biosmem[0x046c]);
 r+=rand();
#else
 r=rand()*rand()*rand();
#endif
 return (r%maxnum);
}

//--------------------------------------------------------------------------
#ifdef __DOS__
static int mswin_version=-1;
#endif

#ifdef __DOS__
unsigned int pds_mswin_getver(void)
{
//#ifdef __DOS__
 union REGPACK regp;
 if(mswin_version<0){
  pds_newfunc_regp_clear(&regp);
  regp.w.ax=0x160A;
  intr(0x2f,&regp);
  mswin_version=(unsigned int)(regp.w.bx);
 }
 return mswin_version;
/*#else
 #ifdef MPXPLAY_WIN32
 OSVERSIONINFO	osVersion;
 pds_memset(&osVersion,0,sizeof(osVersion));
 osVersion.dwOSVersionInfoSize = sizeof( osVersion );
 GetVersionEx(&osVersion);
 if(osVersion.dwPlatformId!=VER_PLATFORM_WIN32_NT)
  return 1024;
 #endif
 return 0;
#endif*/
}
#endif

void pds_mswin_setapplicationtitle_utf8(char *title)
{
#if defined(MPXPLAY_WIN32) && !defined(MPXPLAY_GUI_QT)
#ifdef MPXPLAY_UTF8
 mpxp_wchar_t u16buf[MAX_PATHNAMEU16];
 pds_str_UTF8_to_UTF16LE(u16buf,title,sizeof(u16buf));
 SetConsoleTitleW(u16buf);
#else
 SetConsoleTitleA(title);
#endif
#elif defined(__DOS__)
 if(iswin9x && !pds_filehand_check_infilehand()){
  struct rminfo RMI;
  pds_dpmi_rmi_clear(&RMI);
  RMI.EAX=0x0000168E;
  RMI.ECX=80;
  RMI.ES =dm_int2x_1.segment;
  pds_strcpy(dm_int2x_1.linearptr,title);
  pds_dpmi_realmodeint_call(0x2f,&RMI);
 }
#endif
}

//--------------------------------------------------------------------------
//shutdown routine
#if defined(__DOS__)
void asm_disk_reset(void);
void asm_apm_shutdown(void);
#endif

#ifdef MPXPLAY_WIN32
 #ifndef EWX_FORCEIFHUNG
  #define EWX_FORCEIFHUNG  0x00000010
 #endif
#endif

void pds_shutdown_atx(void)
{
#ifdef MPXPLAY_WIN32
 if(!(GetVersion()&0x80000000)){
  HANDLE h;
  if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&h)){
   LUID luid;
   if(LookupPrivilegeValueA(NULL,"SeShutdownPrivilege",&luid)){
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount=1;
    tp.Privileges[0].Luid=luid;
    tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(h,FALSE,&tp,0,NULL,NULL);
   }
   CloseHandle(h);
  }
 }
 ExitWindowsEx(EWX_SHUTDOWN|EWX_POWEROFF|EWX_FORCEIFHUNG, 0);
#elif defined(__DOS__)
 if(iswin9x){
  system("rundll32.exe shell32.dll,SHExitWindowsEx 5"); // faster
  //system("rundll32.exe User,ExitWindows"); // more safe
 }else{
  //1.disks reset
  //2.reset disk system
 #ifdef __WATCOMC__
  #pragma aux asm_disk_reset=\
  "mov ax,0x0d00"\
  "int 0x21"\
  "xor eax,eax"\
  "mov dx,128"\
  "int 0x13"\
  modify[eax edx];
  asm_disk_reset(); // flush caches and reset disks

  //1.RealMode Interface connect
  //2.Engage power management
  //3.Enable APM for all devices
  //4.Force version 1.1 compatibility
  //5 First attempt: using APM 1.1 or later
  //  Shutdown all the devices supported by APM
  //6.Second attempt: using APM 1.0
  //  Shutdown only the system BIOS
  #pragma aux asm_apm_shutdown=\
  "mov ax,0x5301"\
  "mov bx,0"\
  "int 0x15"\
  "mov ax,0x530f"\
  "mov bx,1"\
  "mov cx,1"\
  "int 0x15"\
  "mov ax,0x5308"\
  "mov bx,1"\
  "mov cx,1"\
  "int 0x15"\
  "mov ax,0x530e"\
  "mov bx,0"\
  "mov cx,0x0101"\
  "int 0x15"\
  "mov ax,0x5307"\
  "mov bx,1"\
  "mov cx,3"\
  "int 0x15"\
  "mov ax,0x5307"\
  "mov bx,0"\
  "mov cx,3"\
  "int 0x15"\
  modify[eax ebx ecx];
  asm_apm_shutdown(); // shutdown by advanced power managment (BIOS)
 #endif // __WATCOMC__
 }
#endif // __DOS__
}

#ifndef __DOS__
void mpxplay_system_opendefaultapplication(char *filename)
{
#ifdef MPXPLAY_GUI_QT_disable
 mpxplay_dispqt_system_opendefaultapplication(filename);
#elif defined(MPXPLAY_UTF8)
 mpxp_wchar_t u16buf[MAX_STRLEN/2];
 pds_str_UTF8_to_UTF16LE(u16buf,filename,sizeof(u16buf));
 ShellExecuteW(NULL, L"open", u16buf, NULL, NULL, SW_SHOW);
#else
 ShellExecuteA(NULL, "open", filename, NULL, NULL, SW_SHOW);
#endif
}
#endif
