📄 pm.c
字号:
/****************************************************************************** SciTech OS Portability Manager Library** ========================================================================** The contents of this file are subject to the SciTech MGL Public* License Version 1.0 (the "License"); you may not use this file* except in compliance with the License. You may obtain a copy of* the License at http://www.scitechsoft.com/mgl-license.txt** Software distributed under the License is distributed on an* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or* implied. See the License for the specific language governing* rights and limitations under the License.** The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.** The Initial Developer of the Original Code is SciTech Software, Inc.* All Rights Reserved.** ========================================================================** Language: ANSI C* Environment: Win32** Description: Implementation for the OS Portability Manager Library, which* contains functions to implement OS specific services in a* generic, cross platform API. Porting the OS Portability* Manager library is the first step to porting any SciTech* products to a new platform.*****************************************************************************/#define WIN32_LEAN_AND_MEAN#define STRICT#include <windows.h>#include <mmsystem.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <direct.h>#include "pmapi.h"#include "drvlib/os/os.h"#include "pm_help.h"/*--------------------------- Global variables ----------------------------*/ibool _PM_haveWinNT; /* True if we are running on NT */static uint VESABuf_len = 1024; /* Length of the VESABuf buffer */static void *VESABuf_ptr = NULL;/* Near pointer to VESABuf */static uint VESABuf_rseg; /* Real mode segment of VESABuf */static uint VESABuf_roff; /* Real mode offset of VESABuf */HANDLE _PM_hDevice = NULL; /* Handle to Win32 VxD */static ibool inited = false; /* Flags if we are initialised */static void (PMAPIP fatalErrorCleanup)(void) = NULL;static char *szMachineNameKey = "System\\CurrentControlSet\\control\\ComputerName\\ComputerName";static char *szMachineNameKeyNT = "System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName";static char *szMachineName = "ComputerName";/*----------------------------- Implementation ----------------------------*//* Macro to check for a valid, loaded version of PMHELP. We check this * on demand when we need these services rather than when PM_init() is * called because if we are running on DirectDraw we don't need PMHELP.VXD. */#define CHECK_FOR_PMHELP() \{ \ if (_PM_hDevice == INVALID_HANDLE_VALUE) \ if (_PM_haveWinNT) \ PM_fatalError("Unable to connect to PMHELP.SYS or SDDHELP.SYS!"); \ else \ PM_fatalError("Unable to connect to PMHELP.VXD or SDDHELP.VXD!"); \}/****************************************************************************REMARKS:Initialise the PM library and connect to our helper device driver. If wecannot connect to our helper device driver, we bail out with an errormessage. Our Windows 9x VxD is dynamically loadable, so it can be loadedafter the system has started.****************************************************************************/void PMAPI PM_init(void){ DWORD inBuf[1]; /* Buffer to receive data from VxD */ DWORD outBuf[1]; /* Buffer to receive data from VxD */ DWORD count; /* Count of bytes returned from VxD */ char cntPath[PM_MAX_PATH]; char *env; /* Create a file handle for the static VxD if possible, otherwise * dynamically load the PMHELP helper VxD. Note that if an old version * of SDD is loaded, we use the PMHELP VxD instead. */ if (!inited) { /* Determine if we are running under Windows NT or not and * set the global OS type variable. */ _PM_haveWinNT = false; if ((GetVersion() & 0x80000000UL) == 0) _PM_haveWinNT = true; ___drv_os_type = (_PM_haveWinNT) ? _OS_WINNT : _OS_WIN95; /* Now try to connect to SDDHELP.VXD or SDDHELP.SYS */ _PM_hDevice = CreateFile(SDDHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0); if (_PM_hDevice != INVALID_HANDLE_VALUE) { if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, NULL, 0, outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) { /* Old version of SDDHELP loaded, so use PMHELP instead */ CloseHandle(_PM_hDevice); _PM_hDevice = INVALID_HANDLE_VALUE; } } if (_PM_hDevice == INVALID_HANDLE_VALUE) { /* First try to see if there is a currently loaded PMHELP driver. * This is usually the case when we are running under Windows NT/2K. */ _PM_hDevice = CreateFile(PMHELP_MODULE_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0); if (_PM_hDevice == INVALID_HANDLE_VALUE) { /* The driver was not staticly loaded, so try creating a file handle * to a dynamic version of the VxD if possible. Note that on WinNT/2K we * cannot support dynamically loading the drivers. */ _PM_hDevice = CreateFile(PMHELP_VXD_PATH, 0,0,0, CREATE_NEW, FILE_FLAG_DELETE_ON_CLOSE, 0); } } if (_PM_hDevice != INVALID_HANDLE_VALUE) { /* Call the driver to determine the version number */ if (!DeviceIoControl(_PM_hDevice, PMHELP_GETVER32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL) || outBuf[0] < PMHELP_VERSION) { if (_PM_haveWinNT) PM_fatalError("Older version of PMHELP.SYS found!"); else PM_fatalError("Older version of PMHELP.VXD found!"); } /* Now set the current path inside the VxD so it knows what the * current directory is for loading Nucleus drivers. */ inBuf[0] = (ulong)PM_getCurrentPath(cntPath,sizeof(cntPath)); if (!DeviceIoControl(_PM_hDevice, PMHELP_SETCNTPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL)) PM_fatalError("Unable to set VxD current path!"); /* Now pass down the NUCLEUS_PATH environment variable to the device * driver so it can use this value if it is found. */ if ((env = getenv("NUCLEUS_PATH")) != NULL) { inBuf[0] = (ulong)env; if (!DeviceIoControl(_PM_hDevice, PMHELP_SETNUCLEUSPATH32, inBuf, sizeof(inBuf), outBuf, sizeof(outBuf), &count, NULL)) PM_fatalError("Unable to set VxD Nucleus path!"); } /* Enable IOPL for ring-3 code by default if driver is present */ if (_PM_haveWinNT) PM_setIOPL(3); } /* Indicate that we have been initialised */ inited = true; }}/****************************************************************************REMARKS:We do have BIOS access under Windows 9x, but not under Windows NT.****************************************************************************/int PMAPI PM_setIOPL( int iopl){ DWORD inBuf[1]; /* Buffer to receive data from VxD */ DWORD outBuf[1]; /* Buffer to receive data from VxD */ DWORD count; /* Count of bytes returned from VxD */ static int cntIOPL = 0; int oldIOPL = cntIOPL; /* Enable I/O by adjusting the I/O permissions map on Windows NT */ if (_PM_haveWinNT) { CHECK_FOR_PMHELP(); if (iopl == 3) DeviceIoControl(_PM_hDevice, PMHELP_ENABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL); else DeviceIoControl(_PM_hDevice, PMHELP_DISABLERING3IOPL, inBuf, sizeof(inBuf),outBuf, sizeof(outBuf), &count, NULL); cntIOPL = iopl; return oldIOPL; } /* We always have IOPL on Windows 9x */ return 3;}/****************************************************************************REMARKS:We do have BIOS access under Windows 9x, but not under Windows NT.****************************************************************************/ibool PMAPI PM_haveBIOSAccess(void){ if (PM_getOSType() == _OS_WINNT) return false; else return _PM_hDevice != INVALID_HANDLE_VALUE;}/****************************************************************************REMARKS:Return the operating system type identifier.****************************************************************************/long PMAPI PM_getOSType(void){ if ((GetVersion() & 0x80000000UL) == 0) return ___drv_os_type = _OS_WINNT; else return ___drv_os_type = _OS_WIN95;}/****************************************************************************REMARKS:Return the runtime type identifier.****************************************************************************/int PMAPI PM_getModeType(void){ return PM_386;}/****************************************************************************REMARKS:Add a file directory separator to the end of the filename.****************************************************************************/void PMAPI PM_backslash( char *s){ uint pos = strlen(s); if (s[pos-1] != '\\') { s[pos] = '\\'; s[pos+1] = '\0'; }}/****************************************************************************REMARKS:Add a user defined PM_fatalError cleanup function.****************************************************************************/void PMAPI PM_setFatalErrorCleanup( void (PMAPIP cleanup)(void)){ fatalErrorCleanup = cleanup;}/****************************************************************************REMARKS:Report a fatal error condition and halt the program.****************************************************************************/void PMAPI PM_fatalError( const char *msg){ if (fatalErrorCleanup) fatalErrorCleanup(); MessageBox(NULL,msg,"Fatal Error!", MB_ICONEXCLAMATION); exit(1);}/****************************************************************************REMARKS:Allocate the real mode VESA transfer buffer for communicating with the BIOS.****************************************************************************/void * PMAPI PM_getVESABuf( uint *len, uint *rseg, uint *roff){ DWORD outBuf[4]; /* Buffer to receive data from VxD */ DWORD count; /* Count of bytes returned from VxD */ /* We require the helper VxD to be loaded staticly in order to support * the VESA transfer buffer. We do not support dynamically allocating * real mode memory buffers from Win32 programs (we need a 16-bit DLL * for this, and Windows 9x becomes very unstable if you free the * memory blocks out of order). */ if (!inited) PM_init(); if (!VESABuf_ptr) { CHECK_FOR_PMHELP(); if (DeviceIoControl(_PM_hDevice, PMHELP_GETVESABUF32, NULL, 0, outBuf, sizeof(outBuf), &count, NULL)) { if (!outBuf[0]) return NULL; VESABuf_ptr = (void*)outBuf[0]; VESABuf_len = outBuf[1]; VESABuf_rseg = outBuf[2]; VESABuf_roff = outBuf[3]; } } *len = VESABuf_len; *rseg = VESABuf_rseg; *roff = VESABuf_roff; return VESABuf_ptr;}/****************************************************************************REMARKS:Check if a key has been pressed.****************************************************************************/int PMAPI PM_kbhit(void){ /* Not used in Windows */ return true;}/****************************************************************************REMARKS:Wait for and return the next keypress.****************************************************************************/int PMAPI PM_getch(void){ /* Not used in Windows */ return 0xD;}/****************************************************************************REMARKS:Set the location of the OS console cursor.****************************************************************************/void PM_setOSCursorLocation( int x, int y){ /* Nothing to do for Windows */ (void)x; (void)y;}/****************************************************************************REMARKS:Set the width of the OS console.****************************************************************************/void PM_setOSScreenWidth( int width, int height){ /* Nothing to do for Windows */ (void)width; (void)height;}/****************************************************************************REMARKS:Set the real time clock handler (used for software stereo modes).****************************************************************************/ibool PMAPI PM_setRealTimeClockHandler( PM_intHandler ih, int frequency){ /* We do not support this from Win32 programs. Rather the VxD handles * this stuff it will take care of hooking the stereo flip functions at * the VxD level. */ (void)ih; (void)frequency; return false;}/****************************************************************************REMARKS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -