/* $Id: HandleManager.cpp,v 1.104 2003-06-02 16:25:15 sandervl Exp $ */ /* * Win32 Unified Handle Manager for OS/2 * * 1998/02/11 PH Patrick Haller (haller@zebra.fh-weingarten.de) * * @(#) HandleManager.Cpp 1.0.0 1998/02/11 PH start * * Project Odin Software License can be found in LICENSE.TXT * */ //#undef DEBUG_LOCAL //#define DEBUG_LOCAL /***************************************************************************** * Remark * ***************************************************************************** 1998/02/11 PH Even overlapped I/O could be simulated by another subsystem thread with a request queue. We'll see if required ... Flush (flush handle buffer) WaitForSingleObject WaitForMultipleObjects (?) 1998/02/12 PH IBM and Microsoft disagree about the definition of FILE_TYPE_xxx Interesting, Open32 returns Microsoft's values ... 1998/02/12 PH Handles should be equipped with a locking mechanism, in particular as we publish a pointer into the handle table via HMHandleQueryHandleData */ /***************************************************************************** * Includes * *****************************************************************************/ #include #include #include #include #include #include #include "handlenames.h" #include "HMDevice.h" #include "HMDisk.h" #include "HMOpen32.h" #include "HMEvent.h" #include "HMFile.h" #include "HMMutex.h" #include "HMSemaphore.h" #include "HMMMap.h" #include "HMComm.h" #include "HMParPort.h" #include "HMNul.h" #include "HMToken.h" #include "HMThread.h" #include "HMNPipe.h" #include "HMStd.h" #include "HMMailslot.h" #include "hmhandle.h" #include "oslibdos.h" #include #include #include #include <_ras.h> #define DBG_LOCALLOG DBG_handlemanager #include "dbglocal.h" /***************************************************************************** * Defines * *****************************************************************************/ // this is the size of our currently static handle table #define MAX_OS2_HMHANDLES (16*1024) #define ERROR_SYS_INTERNAL 328 /***************************************************************************** * Structures * *****************************************************************************/ typedef struct _HMDEVICE { struct _HMDEVICE *pNext; /* pointer to next device in chain */ LPSTR pszDeviceName; /* name or alias of the pseudo-device */ HMDeviceHandler *pDeviceHandler; /* handler for this pseudo-device */ VOID *pDevData; /* Pointer To Device data */ } HMDEVICE, *PHMDEVICE; /***************************************************************************** * This pseudo-device logs all device requests to the logfile and returns * * ERROR_INVALID_FUNCTION to virtually all requests -> debugging * *****************************************************************************/ class HMDeviceDebugClass : public HMDeviceHandler { public: HMDeviceDebugClass(LPCSTR lpDeviceName) : HMDeviceHandler(lpDeviceName) {} }; /***************************************************************************** * Process Global Structures * *****************************************************************************/ /* the device name is repeated here to enable device alias names */ static PHMDEVICE TabWin32Devices = NULL; static int lastIndex = 1; static HMHANDLE *TabWin32Handles = NULL; /* static handle table */ VMutex handleMutex; struct _HMGlobals { HANDLE hStandardIn; /* stdin handle to CONIN$ */ HANDLE hStandardOut; /* stdout handle to CONOUT$ */ HANDLE hStandardError; /* stderr handle to CONOUT$ */ BOOL fIsInitialized; /* if HM is initialized already ? */ /* this MUST !!! be false initially */ HMDeviceHandler *pHMStandard; /* default handle manager instance */ HMDeviceHandler *pHMOpen32; /* default handle manager instance */ HMDeviceHandler *pHMEvent; /* static instances of subsystems */ HMDeviceHandler *pHMFile; HMDeviceHandler *pHMInfoFile; HMDeviceHandler *pHMDisk; HMDeviceHandler *pHMMutex; HMDeviceHandler *pHMSemaphore; HMDeviceHandler *pHMFileMapping; /* static instances of subsystems */ HMDeviceHandler *pHMComm; /* serial communication */ HMDeviceHandler *pHMToken; /* security tokens */ HMDeviceHandler *pHMThread; HMDeviceHandler *pHMNamedPipe; HMDeviceHandler *pHMMailslot; HMDeviceHandler *pHMParPort; /* parallel communication */ HMDeviceHandler *pHMNul; /* nul device */ ULONG ulHandleLast; /* index of last used handle */ } HMGlobals; #ifdef RAS RAS_TRACK_HANDLE rthHandles = 0; ULONG WIN32API LogObjectContent_Handle (ULONG objident, ULONG objhandle, void *objdata, ULONG cbobjdata, FNRASLOG_EXTERNAL *pRasLog) { pRasLog (" %8.8x: data=%p, type=%x, internal type=%x", objhandle, TabWin32Handles[objhandle].hmHandleData.hHMHandle, GetFileType(objhandle), TabWin32Handles[objhandle].hmHandleData.dwInternalType); return 0; } #endif #define FREEHANDLE(a) do { \ TabWin32Handles[a].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; \ RasRemoveObject(rthHandles, a); \ } while (0) extern "C" { /***************************************************************************** * Local Prototypes * *****************************************************************************/ /* get appropriate device handler by the device name */ static HMDeviceHandler* _Optlink _HMDeviceFind(LPSTR pszDeviceName); /* get next free handle from the handle table */ static ULONG _Optlink _HMHandleGetFree(void); /* get handle table entry from handle */ static ULONG _Optlink _HMHandleQuery(HANDLE hHandle); // Get GlobalDeviceData static VOID *_HMDeviceGetData (LPSTR pszDeviceName); /***************************************************************************** * Name : static HMDeviceHandler * _HMDeviceFind * Purpose : obtain appropriate device handler from the table by searching * for a device name or alias * Parameters: PSZ pszDeviceName * Variables : * Result : HMDeviceHandler * - pointer to the handler object * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:42] *****************************************************************************/ static HMDeviceHandler *_HMDeviceFind (LPSTR pszDeviceName) { PHMDEVICE pHMDevice; /* iterator over the device table */ int namelength = strlen(pszDeviceName); if (pszDeviceName != NULL) { for (pHMDevice = TabWin32Devices; /* loop over all devices in the table */ pHMDevice != NULL; pHMDevice = pHMDevice->pNext) { if(pHMDevice->pDeviceHandler->FindDevice(pHMDevice->pszDeviceName, pszDeviceName, namelength) == TRUE) { return pHMDevice->pDeviceHandler; } } } return (HMGlobals.pHMOpen32); /* haven't found anything, return default */ } /***************************************************************************** * Name : static VOID *_HMDeviceGetData * Purpose : obtain pointer to device data from the table by searching * for a device name or alias * Parameters: PSZ pszDeviceName * Variables : * Result : VOID * - pointer to the handlers device data * Remark : * Status : * * Author : Markus Montkowski *****************************************************************************/ static VOID *_HMDeviceGetData (LPSTR pszDeviceName) { PHMDEVICE pHMDevice; /* iterator over the device table */ int namelength = strlen(pszDeviceName); if (pszDeviceName != NULL) { for (pHMDevice = TabWin32Devices; /* loop over all devices in the table */ pHMDevice != NULL; pHMDevice = pHMDevice->pNext) { if(pHMDevice->pDeviceHandler->FindDevice(pHMDevice->pszDeviceName, pszDeviceName, namelength) == TRUE) { return (pHMDevice->pDevData); /* OK, we've found our device */ } } } return (NULL); /* haven't found anything, return NULL */ } /***************************************************************************** * Name : static int _HMHandleGetFree * Purpose : get index to first free handle in the handle table * Parameters: * Variables : * Result : int iIndex - index to the table or -1 in case of error * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:43] *****************************************************************************/ static ULONG _HMHandleGetFree(void) { register ULONG ulLoop; handleMutex.enter(); //find next free handle; do not reuse handles until we have no choice if(lastIndex >= MAX_OS2_HMHANDLES) { lastIndex = 1; } for (ulLoop = lastIndex;ulLoop < MAX_OS2_HMHANDLES; ulLoop++) { /* free handle found ? */ if (INVALID_HANDLE_VALUE == TabWin32Handles[ulLoop].hmHandleData.hHMHandle) { //Mark handle as allocated here. memset(&TabWin32Handles[ulLoop].hmHandleData, 0, sizeof(TabWin32Handles[ulLoop].hmHandleData)); TabWin32Handles[ulLoop].hmHandleData.hHMHandle = ulLoop; TabWin32Handles[ulLoop].hmHandleData.dwInternalType = HMTYPE_UNKNOWN; TabWin32Handles[ulLoop].hmHandleData.hWin32Handle = (HANDLE)ulLoop; lastIndex = ulLoop+1; handleMutex.leave(); RasAddObject (rthHandles, ulLoop, NULL, 0); return (ulLoop); /* OK, then return it to the caller */ } } handleMutex.leave(); dprintf(("KERNEL32:HandleManager:_HMHandleGetFree() no free handle (%d already allocated)\n", ulLoop)); #ifdef RAS RasLog ("KERNEL32:HandleManager:_HMHandleGetFree() no free handle"); RasLogObjects (rthHandles, RAS_FLAG_LOG_OBJECTS); #endif return (INVALID_HANDLE_VALUE); /* haven't found any free handle */ } /***************************************************************************** * Name : static int _HMHandleGetFree * Purpose : get pointer to first free handle in the handle table * Parameters: * Variables : * Result : pointer to the table or NULL in case of error * Remark : * Status : * * Author : SvL *****************************************************************************/ PHMHANDLE HMHandleGetFreePtr(ULONG dwType) { ULONG handle; PHMHANDLE pHandle; handle = _HMHandleGetFree(); if(handle == INVALID_HANDLE_VALUE) { return NULL; } pHandle = &TabWin32Handles[handle]; switch(dwType) { case HMTYPE_MEMMAP: pHandle->pDeviceHandler = HMGlobals.pHMFileMapping; break; case HMTYPE_DEVICE: pHandle->pDeviceHandler = HMGlobals.pHMFile; break; case HMTYPE_PROCESSTOKEN: case HMTYPE_THREADTOKEN: pHandle->pDeviceHandler = HMGlobals.pHMToken; break; case HMTYPE_THREAD: pHandle->pDeviceHandler = HMGlobals.pHMThread; break; case HMTYPE_PIPE: pHandle->pDeviceHandler = HMGlobals.pHMNamedPipe; break; case HMTYPE_EVENTSEM: pHandle->pDeviceHandler = HMGlobals.pHMEvent; break; case HMTYPE_MUTEXSEM: pHandle->pDeviceHandler = HMGlobals.pHMMutex; break; case HMTYPE_SEMAPHORE: pHandle->pDeviceHandler = HMGlobals.pHMSemaphore; break; case HMTYPE_COMPORT: pHandle->pDeviceHandler = HMGlobals.pHMComm; break; case HMTYPE_PARPORT: pHandle->pDeviceHandler = HMGlobals.pHMParPort; break; case HMTYPE_MAILSLOT: pHandle->pDeviceHandler = HMGlobals.pHMMailslot; break; case HMTYPE_UNKNOWN: default: DebugInt3(); HMHandleFree(handle); return NULL; } pHandle->hmHandleData.dwInternalType = dwType; return pHandle; } /***************************************************************************** * Name : HMHandleGetUserData * Purpose : Get the dwUserData dword for a specific handle * Parameters: HANDLE hHandle * Variables : * Result : -1 or dwUserData * Remark : * Status : * * Author : SvL *****************************************************************************/ DWORD HMHandleGetUserData(ULONG hHandle) { if (hHandle >= MAX_OS2_HMHANDLES) /* check the table range */ { /* Standard handle? */ switch (hHandle) { case STD_INPUT_HANDLE: hHandle = HMGlobals.hStandardIn; break; case STD_OUTPUT_HANDLE: hHandle = HMGlobals.hStandardOut; break; case STD_ERROR_HANDLE: hHandle = HMGlobals.hStandardError; break; default: return(-1); } if (hHandle >= MAX_OS2_HMHANDLES) return(-1); } /* Oops, invalid handle ! */ if (INVALID_HANDLE_VALUE == TabWin32Handles[hHandle].hmHandleData.hHMHandle) return(-1); /* nope, ERROR_INVALID_HANDLE */ return TabWin32Handles[hHandle].hmHandleData.dwUserData; } /***************************************************************************** * Name : HMHandleGetUserData * Purpose : Get the dwUserData dword for a specific handle * Parameters: HANDLE hHandle * Variables : * Result : -1 or dwUserData * Remark : * Status : * * Author : SvL *****************************************************************************/ DWORD HMHandleSetUserData(ULONG hHandle, ULONG dwUserData) { if (hHandle >= MAX_OS2_HMHANDLES) /* check the table range */ { /* Standard handle? */ switch (hHandle) { case STD_INPUT_HANDLE: hHandle = HMGlobals.hStandardIn; break; case STD_OUTPUT_HANDLE: hHandle = HMGlobals.hStandardOut; break; case STD_ERROR_HANDLE: hHandle = HMGlobals.hStandardError; break; default: return(-1); } if (hHandle >= MAX_OS2_HMHANDLES) return(-1); } /* Oops, invalid handle ! */ if (INVALID_HANDLE_VALUE == TabWin32Handles[hHandle].hmHandleData.hHMHandle) return(-1); /* nope, ERROR_INVALID_HANDLE */ TabWin32Handles[hHandle].hmHandleData.dwUserData = dwUserData; return NO_ERROR; } /***************************************************************************** * Name : static int _HMHandleQuery * Purpose : gets the index of handle table entry as fast as possible from * the specified handle * Parameters: HANDLE hHandle * Variables : * Result : index or -1 in case of error * Remark : Should fail for standard handles (in/out/err)!!!!!!!!!! * HMGetFileType depends on this!!! * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ INLINE ULONG _HMHandleQuery(HANDLE hHandle) { if (hHandle >= MAX_OS2_HMHANDLES) /* check the table range */ { /* Standard handle? */ switch (hHandle) { case STD_INPUT_HANDLE: hHandle = HMGlobals.hStandardIn; break; case STD_OUTPUT_HANDLE: hHandle = HMGlobals.hStandardOut; break; case STD_ERROR_HANDLE: hHandle = HMGlobals.hStandardError; break; default: return(INVALID_HANDLE_VALUE); /* nope, ERROR_INVALID_HANDLE */ } if (hHandle >= MAX_OS2_HMHANDLES) /* check the table range */ return(INVALID_HANDLE_VALUE); /* nope, ERROR_INVALID_HANDLE */ } /* Oops, invalid handle ! */ if (INVALID_HANDLE_VALUE == TabWin32Handles[hHandle].hmHandleData.hHMHandle) return(INVALID_HANDLE_VALUE); /* nope, ERROR_INVALID_HANDLE */ return( hHandle); /* OK, we've got our handle index */ } /***************************************************************************** * Name : HMHandleQueryPtr * Purpose : gets the pointer of handle table entry as fast as possible from * the specified handle * Parameters: HANDLE hHandle * Variables : * Result : pointer or NULL in case of error * Remark : * Status : * * Author : SvL *****************************************************************************/ PHMHANDLE HMHandleQueryPtr(HANDLE hHandle) { if (hHandle >= MAX_OS2_HMHANDLES) { /* Standard handle? */ switch (hHandle) { case STD_INPUT_HANDLE: hHandle = HMGlobals.hStandardIn; break; case STD_OUTPUT_HANDLE: hHandle = HMGlobals.hStandardOut; break; case STD_ERROR_HANDLE: hHandle = HMGlobals.hStandardError; break; default: SetLastError(ERROR_INVALID_HANDLE); return(NULL); } if (hHandle >= MAX_OS2_HMHANDLES) { SetLastError(ERROR_INVALID_HANDLE); return(NULL); } } if (INVALID_HANDLE_VALUE == TabWin32Handles[hHandle].hmHandleData.hHMHandle) { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return(NULL); /* nope, ERROR_INVALID_HANDLE */ } return( &TabWin32Handles[hHandle]); /* OK, we've got our handle index */ } /***************************************************************************** * Name : DWORD HMDeviceRegister * Purpose : register a device with the handle manager * Parameters: PSZ pszDeviceName * HMDeviceHandler *pDeviceHandler * Variables : * Result : API returncode * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/12 20:44] *****************************************************************************/ DWORD HMDeviceRegisterEx(LPCSTR pszDeviceName, HMDeviceHandler *pDeviceHandler, VOID *pDevData) { PHMDEVICE pHMDevice; /* our new device to be allocated */ if ( (pszDeviceName == NULL) || /* check parameters */ (pDeviceHandler == NULL) ) return (ERROR_INVALID_PARAMETER); /* raise error conditon */ pHMDevice = (PHMDEVICE) malloc (sizeof (HMDEVICE) ); /* allocate memory */ if (pHMDevice == NULL) /* check proper allocation */ return (ERROR_NOT_ENOUGH_MEMORY); /* signal error */ pHMDevice->pszDeviceName = strdup(pszDeviceName); /* copy name */ if (pHMDevice->pszDeviceName == NULL) /* check proper allocation */ { free (pHMDevice); /* free previously allocated memory */ return (ERROR_NOT_ENOUGH_MEMORY); /* signal error */ } pHMDevice->pDeviceHandler = pDeviceHandler; /* store pointer to device */ pHMDevice->pNext = TabWin32Devices; /* establish linkage */ pHMDevice->pDevData = pDevData; TabWin32Devices = pHMDevice; /* insert new node as root in the list */ return (NO_ERROR); } DWORD HMDeviceRegister(LPCSTR pszDeviceName, HMDeviceHandler *pDeviceHandler) { return HMDeviceRegisterEx(pszDeviceName, pDeviceHandler, NULL); } /***************************************************************************** * Name : DWORD HMInitialize * Purpose : Initialize the handlemanager * Parameters: - * Variables : - * Result : always NO_ERROR * Remark : this routine just stores the standard handles in the * internal table within the HandleManager * Status : * * Author : Patrick Haller [Wed, 1998/02/12 20:44] *****************************************************************************/ DWORD HMInitialize(void) { ULONG ulIndex; if (HMGlobals.fIsInitialized != TRUE) { #ifdef RAS RasRegisterObjectTracking(&rthHandles, "KERNEL32 handles", 0, RAS_TRACK_FLAG_LOGOBJECTCONTENT, LogObjectContent_Handle, NULL); #endif handleMutex.enter(); TabWin32Handles = (HMHANDLE *)VirtualAlloc(NULL, MAX_OS2_HMHANDLES*sizeof(HMHANDLE), MEM_COMMIT, PAGE_READWRITE); if(TabWin32Handles == NULL) { DebugInt3(); return ERROR_NOT_ENOUGH_MEMORY; } // fill handle table for(ulIndex = 0; ulIndex < MAX_OS2_HMHANDLES; ulIndex++) { TabWin32Handles[ulIndex].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; } handleMutex.leave(); dprintf(("KERNEL32:HandleManager:HMInitialize() storing handles.\n")); memset(&HMGlobals, /* zero out the structure first */ 0, sizeof(HMGlobals)); HMGlobals.fIsInitialized = TRUE; /* OK, done */ #if 1 //This is a very bad idea. \\\\.\\NTICE -> NTICE, if the file exits, then //it will open the file instead of the device driver /* add standard symbolic links first, so local symbolic links in the * device handlers get precedence over the default here. * * Device handlers are supposed to place the appropriate * symbolic links such as "\\.\\COM1", "COM1" * * - "\\.\f:\temp\readme.txt" is a valid file * - "com1" is a valid device in case serial port 1 exists, * otherwise it'd be a valid file. * - "\\.\filename" is the only misleading case (to be verified) * * Note: * the Open32 "device" definately MUST be the last device to be * asked to accept the specified name. */ { // strings are placed in read-only segment PSZ pszDrive = strdup("\\\\.\\x:"); PSZ pszDrive2 = strdup("\\\\.\\x:"); for (char ch = 'A'; ch <= 'Z'; ch++) { pszDrive[4] = ch; pszDrive2[4] = ch; HandleNamesAddSymbolicLink(pszDrive, pszDrive+4); HandleNamesAddSymbolicLink(pszDrive2, pszDrive2+4); } free(pszDrive); free(pszDrive2); HandleNamesAddSymbolicLink("\\\\?\\UNC\\", "\\\\"); //SvL: Can be used in Windows 2000 to open device drivers HandleNamesAddSymbolicLink("\\\\.\\Global", "\\\\."); } #endif /* create handle manager instance for Open32 handles */ HMGlobals.pHMStandard = new HMDeviceStandardClass("\\\\STANDARD_HANDLE\\"); HMGlobals.pHMOpen32 = new HMDeviceOpen32Class("\\\\.\\"); HMGlobals.pHMEvent = new HMDeviceEventClass("\\\\EVENT\\"); HMGlobals.pHMFile = new HMDeviceFileClass("\\\\FILE\\"); HMGlobals.pHMInfoFile = new HMDeviceInfoFileClass("\\\\INFOFILE\\"); HMGlobals.pHMDisk = new HMDeviceDiskClass("\\\\DISK\\"); HMGlobals.pHMMutex = new HMDeviceMutexClass("\\\\MUTEX\\"); HMGlobals.pHMSemaphore = new HMDeviceSemaphoreClass("\\\\SEM\\"); HMGlobals.pHMFileMapping= new HMDeviceMemMapClass("\\\\MEMMAP\\"); HMGlobals.pHMComm = new HMDeviceCommClass("\\\\COM\\"); HMGlobals.pHMToken = new HMDeviceTokenClass("\\\\TOKEN\\"); HMGlobals.pHMThread = new HMDeviceThreadClass("\\\\THREAD\\"); HMGlobals.pHMNamedPipe = new HMDeviceNamedPipeClass("\\\\PIPE\\"); HMGlobals.pHMMailslot = new HMMailslotClass("\\MAILSLOT\\"); HMGlobals.pHMParPort = new HMDeviceParPortClass("\\\\LPT\\"); HMGlobals.pHMNul = new HMDeviceNulClass("\\\\NUL\\"); HMSetupStdHandle(STD_INPUT_HANDLE); HMSetupStdHandle(STD_OUTPUT_HANDLE); HMSetupStdHandle(STD_ERROR_HANDLE); } return (NO_ERROR); } /***************************************************************************** * Name : DWORD HMTerminate * Purpose : Terminate the handlemanager * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/12 20:44] *****************************************************************************/ DWORD HMTerminate(void) { /* @@@PH we could deallocate the device list here */ #ifdef DEBUG dprintf(("List of leaked handles")); for(int i = 0; i < MAX_OS2_HMHANDLES; i++) { /* check if handle is free */ if (TabWin32Handles[i].hmHandleData.hHMHandle != INVALID_HANDLE_VALUE) { dprintf(("Handle %x(%p) type %x internal type %x", i, TabWin32Handles[i].hmHandleData.hHMHandle, GetFileType(i), TabWin32Handles[i].hmHandleData.dwInternalType)); } } #endif RasLogObjects (rthHandles, RAS_FLAG_LOG_OBJECTS); if(HMGlobals.pHMOpen32) delete HMGlobals.pHMOpen32; if(HMGlobals.pHMEvent) delete HMGlobals.pHMEvent; if(HMGlobals.pHMFile) delete HMGlobals.pHMFile; if(HMGlobals.pHMInfoFile) delete HMGlobals.pHMInfoFile; if(HMGlobals.pHMMutex) delete HMGlobals.pHMMutex; if(HMGlobals.pHMSemaphore) delete HMGlobals.pHMSemaphore; if(HMGlobals.pHMFileMapping) delete HMGlobals.pHMFileMapping; if(HMGlobals.pHMComm) delete HMGlobals.pHMComm; if(HMGlobals.pHMToken) delete HMGlobals.pHMToken; if(HMGlobals.pHMThread) delete HMGlobals.pHMThread; if(HMGlobals.pHMNamedPipe) delete HMGlobals.pHMNamedPipe; if(HMGlobals.pHMMailslot) delete HMGlobals.pHMMailslot; if(HMGlobals.pHMDisk) delete HMGlobals.pHMDisk; if(HMGlobals.pHMStandard); delete HMGlobals.pHMStandard; if(HMGlobals.pHMParPort) delete HMGlobals.pHMParPort; if(HMGlobals.pHMNul) delete HMGlobals.pHMNul; return (NO_ERROR); } /*****************************************************************************/ /* handle translation buffer management */ /* */ /* Since some Win32 applications rely (!) on 16-bit handles, we've got to do */ /* 32-bit to 16-bit and vs vsa translation here. */ /* Filehandle-based functions should be routed via the handlemanager instead */ /* of going to Open32 directly. */ /*****************************************************************************/ /***************************************************************************** * Name : DWORD HMHandleAllocate * Purpose : allocate a handle in the translation table * Parameters: PULONG pHandle16 - to return the allocated handle * ULONG hHandle32 - the associated OS/2 handle * Variables : * Result : API returncode * Remark : no parameter checking is done, phHandle may not be invalid * hHandle32 shouldn't be 0 * Should be protected with a HM-Mutex ! * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleAllocate (PULONG phHandle16, ULONG hHandleOS2) { register ULONG ulHandle; #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleAllocate (%08xh,%08xh)\n", phHandle16, hHandleOS2)); #endif if (!phHandle16) return (ERROR_TOO_MANY_OPEN_FILES); // @@@PH 2001-09-27 // prevent too quick re-use of last handle ulHandle = HMGlobals.ulHandleLast + 1; /* get free handle */ handleMutex.enter(); if(ulHandle == 0 || ulHandle >= MAX_OS2_HMHANDLES) { ulHandle = 1; //SvL: Start searching from index 1 } do { /* check if handle is free */ if (TabWin32Handles[ulHandle].hmHandleData.hHMHandle == INVALID_HANDLE_VALUE) { *phHandle16 = ulHandle; TabWin32Handles[ulHandle].hmHandleData.hHMHandle = hHandleOS2; TabWin32Handles[ulHandle].hmHandleData.lpDeviceData = NULL; HMGlobals.ulHandleLast = ulHandle; /* to shorten search times */ handleMutex.leave(); RasAddObject (rthHandles, ulHandle, NULL, 0); return (NO_ERROR); /* OK */ } ulHandle++; /* skip to next entry */ if (ulHandle >= MAX_OS2_HMHANDLES) /* check boundary */ ulHandle = 1; } while (ulHandle != HMGlobals.ulHandleLast); handleMutex.leave(); #ifdef DEBUG dprintf(("ERROR: Out of handles!!!!")); for (int i = 0; i < MAX_OS2_HMHANDLES; i++) { /* check if handle is free */ if (TabWin32Handles[i].hmHandleData.hHMHandle != INVALID_HANDLE_VALUE) { dprintf(("Handle %d type %d internal type %d", i, GetFileType(i), TabWin32Handles[i].hmHandleData.dwInternalType)); } } #endif #ifdef RAS RasLog ("KERNEL32:HandleManager:HMHandleAllocate() no free handle"); RasLogObjects (rthHandles, RAS_FLAG_LOG_OBJECTS); #endif return (ERROR_TOO_MANY_OPEN_FILES); /* OK, we're done */ } /***************************************************************************** * Name : DWORD HMHandleFree * Purpose : free a handle from the translation table * Parameters: ULONG hHandle16 - the handle to be freed * Variables : * Result : API returncode * Remark : no parameter checking is done, hHandle16 MAY NEVER exceed * the MAX_TRANSLATION_HANDLES boundary * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleFree (ULONG hHandle16) { ULONG rc; /* API returncode */ #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleFree (%08xh)\n", hHandle16)); #endif rc = HMHandleValidate(hHandle16); /* verify handle */ if (rc != NO_ERROR) /* check errors */ return (rc); /* raise error condition */ FREEHANDLE(hHandle16); // TabWin32Handles[hHandle16].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; // RasRemoveObjects(rthHandles, hHandle16); /* OK, done */ return (NO_ERROR); } /***************************************************************************** * Name : DWORD HMHandleValidate * Purpose : validate a handle through the translation table * Parameters: ULONG hHandle - the handle to be verified * Variables : * Result : API returncode * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleValidate (ULONG hHandle) { #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleValidate (%08xh)\n", hHandle)); #endif if (hHandle >= MAX_OS2_HMHANDLES) /* check boundary */ { /* Standard handle? */ switch (hHandle) { case STD_INPUT_HANDLE: hHandle = HMGlobals.hStandardIn; break; case STD_OUTPUT_HANDLE: hHandle = HMGlobals.hStandardOut; break; case STD_ERROR_HANDLE: hHandle = HMGlobals.hStandardError; break; default: return(ERROR_INVALID_HANDLE); } if (hHandle >= MAX_OS2_HMHANDLES) return(ERROR_INVALID_HANDLE); } if (TabWin32Handles[hHandle].hmHandleData.hHMHandle == INVALID_HANDLE_VALUE) /* valid ? */ return(ERROR_INVALID_HANDLE); /* raise error condition */ return(NO_ERROR); } //***************************************************************************** //***************************************************************************** PHMHANDLEDATA HMQueryHandleData(HANDLE handle) { int iIndex; iIndex = _HMHandleQuery(handle); /* get the index */ if (-1 == iIndex) /* error ? */ { return NULL; } return &TabWin32Handles[iIndex].hmHandleData; /* call device handler */ } /***************************************************************************** * Name : DWORD HMHandleTranslateToWin * Purpose : translate a 32-bit OS/2 handle to the associated windows handle * Parameters: ULONG hHandle32 - the OS/2 handle * PULONG phHandle16 - the associated windows handle * Variables : * Result : API returncode * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleTranslateToWin (ULONG hHandleOS2, PULONG phHandle16) { ULONG rc; /* API returncode */ register ULONG ulIndex; /* index counter over the table */ #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleTranslateToWin (%08xh, %08xh)\n", hHandleOS2, phHandle16)); #endif for (ulIndex = 1; ulIndex < MAX_OS2_HMHANDLES; ulIndex++) { /* look for the handle */ if (TabWin32Handles[ulIndex].hmHandleData.hHMHandle == hHandleOS2) { *phHandle16 = ulIndex; /* deliver result */ return (NO_ERROR); /* OK */ } } return (ERROR_INVALID_HANDLE); /* raise error condition */ } /***************************************************************************** * Name : DWORD HMHandleTranslateToOS2 * Purpose : translate a 16-bit Win32 handle to the associated OS/2 handle * Parameters: ULONG hHandle16 - the windows handle * PULONG phHandle32 - the associated OS/2 handle * Variables : * Result : API returncode * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleTranslateToOS2 (ULONG hHandle16, PULONG phHandleOS2) { #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleTranslateToOS2 (%08xh, %08xh)\n", hHandle16, phHandleOS2)); #endif if (HMHandleValidate(hHandle16) == NO_ERROR) /* verify handle */ { *phHandleOS2 = TabWin32Handles[hHandle16].hmHandleData.hHMHandle; return (NO_ERROR); } return (ERROR_INVALID_HANDLE); /* raise error condition */ } /***************************************************************************** * Name : DWORD HMHandleTranslateToOS2i * Purpose : translate a 16-bit Win32 handle to the associated OS/2 handle * Parameters: ULONG hHandle16 - the windows handle * Variables : * Result : OS/2 handle * Remark : no checkinf * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMHandleTranslateToOS2i (ULONG hHandle16) { #ifdef DEBUG_LOCAL dprintf(("KERNEL32: HMHandleTranslateToOS2i (%08xh)\n", hHandle16)); #endif return(TabWin32Handles[hHandle16].hmHandleData.hHMHandle); } /***************************************************************************** * Name : HANDLE _HMGetStdHandle * Purpose : replacement for Open32's GetStdHandle function * Parameters: DWORD nStdHandle * Variables : * Result : HANDLE to standard device * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/12 20:44] *****************************************************************************/ HANDLE HMGetStdHandle(DWORD nStdHandle) { switch (nStdHandle) { case STD_INPUT_HANDLE: return (HMGlobals.hStandardIn); case STD_OUTPUT_HANDLE: return (HMGlobals.hStandardOut); case STD_ERROR_HANDLE: return (HMGlobals.hStandardError); default: { SetLastError(ERROR_INVALID_PARAMETER); /* set error information */ return (INVALID_HANDLE_VALUE); /* raise error condition */ } } } /***************************************************************************** * Name : HANDLE _HMSetupStdHandle * Purpose : initialization of standard handles * Parameters: DWORD nStdHandle * HANDLE hHandle * Variables : * Result : BOOL fSuccess * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/12 20:44] *****************************************************************************/ BOOL HMSetupStdHandle(DWORD nStdHandle) { PHMHANDLEDATA pHMHandleData; HANDLE hHandle; hHandle = _HMHandleGetFree(); /* get free handle */ if (hHandle == -1) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; } ULONG handle; switch (nStdHandle) { case STD_INPUT_HANDLE: { handle = 0; HMGlobals.hStandardIn = hHandle; break; } case STD_OUTPUT_HANDLE: { handle = 1; HMGlobals.hStandardOut = hHandle; break; } case STD_ERROR_HANDLE: { handle = 2; HMGlobals.hStandardError = hHandle; break; } default: { SetLastError(ERROR_INVALID_PARAMETER); /* set error information */ return (FALSE); /* raise error condition */ } } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[hHandle].hmHandleData; pHMHandleData->dwAccess = 0; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->dwUserData = 0; pHMHandleData->lpHandlerData = NULL; DWORD type = OSLibDosQueryHType(handle, NULL); switch (type & 0x7) { case 0: /* disk file */ { pHMHandleData->hHMHandle = handle; TabWin32Handles[hHandle].pDeviceHandler = HMGlobals.pHMFile; break; } case 1: /* character device */ { // Note: we use a simple read/write device by default; // if this is a console application, iConsoleInit() will set up // proper devices with extended functionality pHMHandleData->hHMHandle = O32_GetStdHandle(nStdHandle); TabWin32Handles[hHandle].pDeviceHandler = HMGlobals.pHMStandard; break; } case 2: /* pipe */ { pHMHandleData->hHMHandle = handle; TabWin32Handles[hHandle].pDeviceHandler = HMGlobals.pHMNamedPipe; break; } default: { SetLastError(ERROR_SYS_INTERNAL); /* set error information */ return (FALSE); /* raise error condition */ } } return TRUE; } /***************************************************************************** * Name : HANDLE _HMSetStdHandle * Purpose : replacement for Open32's SetStdHandle function * Parameters: DWORD nStdHandle * HANDLE hHandle * Variables : * Result : BOOL fSuccess * Remark : * Status : * * Author : Dmitry Froloff [Thu, 2003/03/03 17:44] *****************************************************************************/ BOOL HMSetStdHandle(DWORD nStdHandle, HANDLE hHandle) { switch (nStdHandle) { case STD_INPUT_HANDLE: HMGlobals.hStandardIn = hHandle; return TRUE; case STD_OUTPUT_HANDLE: HMGlobals.hStandardOut = hHandle; return TRUE; case STD_ERROR_HANDLE: HMGlobals.hStandardError = hHandle; return TRUE; default: { SetLastError(ERROR_INVALID_PARAMETER); /* set error information */ return (FALSE); /* raise error condition */ } } } /***************************************************************************** * Name : HANDLE HMDuplicateHandle * Purpose : replacement for Open32's HMDuplicateHandle function * Parameters: * * Variables : * Result : BOOL fSuccess * Remark : * Status : * * Author : Sander van Leeuwen [Wed, 1999/08/25 15:44] *****************************************************************************/ BOOL HMDuplicateHandle(HANDLE srcprocess, HANDLE srchandle, HANDLE destprocess, PHANDLE desthandle, DWORD fdwAccess, BOOL fInherit, DWORD fdwOptions) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; BOOL rc; /* API return code */ if(HMHandleValidate(srchandle) != NO_ERROR) { dprintf(("KERNEL32: HMDuplicateHandle: invalid handle %x", srchandle)); SetLastError(ERROR_INVALID_HANDLE); /* use this as error message */ return FALSE; } pDeviceHandler = TabWin32Handles[srchandle].pDeviceHandler; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return FALSE; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; if (fdwOptions & DUPLICATE_SAME_ACCESS) pHMHandleData->dwAccess = TabWin32Handles[srchandle].hmHandleData.dwAccess; else pHMHandleData->dwAccess = fdwAccess; pHMHandleData->dwShare = TabWin32Handles[srchandle].hmHandleData.dwShare; pHMHandleData->dwCreation = TabWin32Handles[srchandle].hmHandleData.dwCreation; pHMHandleData->dwFlags = TabWin32Handles[srchandle].hmHandleData.dwFlags; pHMHandleData->lpHandlerData = TabWin32Handles[srchandle].hmHandleData.lpHandlerData; pHMHandleData->dwInternalType = TabWin32Handles[srchandle].hmHandleData.dwInternalType; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->DuplicateHandle(srchandle, &TabWin32Handles[iIndexNew].hmHandleData, srcprocess, &TabWin32Handles[srchandle].hmHandleData, destprocess, fdwAccess, fInherit, fdwOptions & ~DUPLICATE_CLOSE_SOURCE, 0); //Don't let Open32 close it for us, but do it manually (regardless of error; see SDK docs)) if (fdwOptions & DUPLICATE_CLOSE_SOURCE) HMCloseHandle(srchandle); if(rc == FALSE) /* oops, creation failed within the device handler */ { // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; FREEHANDLE(iIndexNew); return FALSE; /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? *desthandle = iIndexNew; return TRUE; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMCreateFile * Purpose : Wrapper for the CreateFile() API * Parameters: * Variables : * Result : * Remark : Fix parameters passed to the HMDeviceManager::CreateFile * Supply access mode and share mode validation routines * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE HMCreateFile(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ HANDLE hResult; DWORD rc; /* API return code */ PHMHANDLEDATA pHMHandleData; HMHANDLEDATA HMHandleTemp; /* temporary buffer for handle data */ VOID *pDevData; /* create new handle by either lpFileName or hTemplateFile */ if (lpFileName == NULL) /* this indicates creation from template */ { iIndex = _HMHandleQuery(hTemplateFile); /* query table for template */ if (-1 == iIndex) /* this device is unknown to us */ { SetLastError (ERROR_INVALID_HANDLE); return INVALID_HANDLE_VALUE; } else { /* to pass to handler */ pHMHandleData = &TabWin32Handles[iIndex].hmHandleData; pDeviceHandler = TabWin32Handles[iIndex].pDeviceHandler; } } else { // name resolving CHAR szFilename[260]; if (TRUE == HandleNamesResolveName((PSZ)lpFileName, szFilename, sizeof(szFilename), TRUE)) { // use the resolved name lpFileName = szFilename; } pDeviceHandler = _HMDeviceFind((LPSTR)lpFileName); /* find device */ if (NULL == pDeviceHandler) /* this name is unknown to us */ { SetLastError(ERROR_FILE_NOT_FOUND); return (INVALID_HANDLE_VALUE); /* signal error */ } else pHMHandleData = NULL; pDevData = _HMDeviceGetData((LPSTR)lpFileName); if(pDeviceHandler == HMGlobals.pHMOpen32) { /* PF When create flag is set we do not care about zero in desired access verified in Win2k */ if(dwDesiredAccess == 0 && dwCreationDisposition != CREATE_NEW) { dprintf(("File information access!")); pDeviceHandler = HMGlobals.pHMInfoFile; } else pDeviceHandler = HMGlobals.pHMFile; } } iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return (INVALID_HANDLE_VALUE); /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ if (lpFileName == NULL) /* create from template */ memcpy (&HMHandleTemp, &TabWin32Handles[iIndex].hmHandleData, sizeof(HMHANDLEDATA)); else { memset(&HMHandleTemp, 0, sizeof(HMHandleTemp)); HMHandleTemp.dwAccess = dwDesiredAccess; HMHandleTemp.dwShare = dwShareMode; HMHandleTemp.dwCreation = dwCreationDisposition; HMHandleTemp.dwFlags = dwFlagsAndAttributes; HMHandleTemp.hWin32Handle = iIndexNew; HMHandleTemp.lpDeviceData = pDevData; } /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ HMHandleTemp.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* now copy back our temporary handle data */ memcpy(&TabWin32Handles[iIndexNew].hmHandleData, &HMHandleTemp, sizeof(HMHANDLEDATA)); rc = pDeviceHandler->CreateFile(lpFileName, /* call the device handler */ &HMHandleTemp, lpSecurityAttributes, pHMHandleData); #ifdef DEBUG_LOCAL dprintf(("KERNEL32/HandleManager:CheckPoint2: %s lpHandlerData=%08xh\n", lpFileName, HMHandleTemp.lpHandlerData)); #endif if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; // Note: // device handlers have to return an Win32-style error code // from CreateFile() ! SetLastError(rc); return (INVALID_HANDLE_VALUE); /* signal error */ } else { /* copy data fields that might have been modified by CreateFile */ memcpy(&TabWin32Handles[iIndexNew].hmHandleData, &HMHandleTemp, sizeof(HMHANDLEDATA)); if(lpSecurityAttributes && lpSecurityAttributes->bInheritHandle) { dprintf(("Set inheritance for child processes")); HMSetHandleInformation(iIndexNew, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); } SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? } return (HFILE)iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMOpenFile * Purpose : Wrapper for the OpenFile() API * Parameters: * Variables : * Result : * Remark : Fix parameters passed to the HMDeviceManager::OpenFile * Supply access mode and share mode validation routines * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ /*********************************************************************** * FILE_ConvertOFMode * * Convert OF_* mode into flags for CreateFile. */ static void FILE_ConvertOFMode( INT mode, DWORD *access, DWORD *sharing ) { switch(mode & 0x03) { case OF_READ: *access = GENERIC_READ; break; case OF_WRITE: *access = GENERIC_WRITE; break; case OF_READWRITE: *access = GENERIC_READ | GENERIC_WRITE; break; default: *access = 0; break; } switch(mode & 0x70) { case OF_SHARE_EXCLUSIVE: *sharing = 0; break; case OF_SHARE_DENY_WRITE: *sharing = FILE_SHARE_READ; break; case OF_SHARE_DENY_READ: *sharing = FILE_SHARE_WRITE; break; case OF_SHARE_DENY_NONE: case OF_SHARE_COMPAT: default: *sharing = FILE_SHARE_READ | FILE_SHARE_WRITE; break; } } HFILE WIN32API OpenFile(LPCSTR lpFileName, OFSTRUCT* pOFStruct, UINT fuMode) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ VOID *pDevData; PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ dprintf(("KERNEL32: OpenFile(%s, %08xh, %08xh)\n", lpFileName, pOFStruct, fuMode)); // name resolving CHAR szFilename[260]; if (TRUE == HandleNamesResolveName((PSZ)lpFileName, szFilename, sizeof(szFilename), TRUE)) { // use the resolved name lpFileName = szFilename; } if(fuMode & OF_REOPEN) { pDeviceHandler = _HMDeviceFind((LPSTR)pOFStruct->szPathName); /* find device */ } else pDeviceHandler = _HMDeviceFind((LPSTR)lpFileName); /* find device */ if (NULL == pDeviceHandler) /* this name is unknown to us */ { SetLastError(ERROR_FILE_NOT_FOUND); return (INVALID_HANDLE_VALUE); /* signal error */ } else pHMHandleData = NULL; if(fuMode & OF_REOPEN) { pDevData = _HMDeviceGetData((LPSTR)pOFStruct->szPathName); } else pDevData = _HMDeviceGetData((LPSTR)lpFileName); if(pDeviceHandler == HMGlobals.pHMOpen32) { pDeviceHandler = HMGlobals.pHMFile; } iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return (INVALID_HANDLE_VALUE); /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; FILE_ConvertOFMode(fuMode, /* map OF_flags */ &pHMHandleData->dwAccess, &pHMHandleData->dwShare); //SvL; Must be OPEN_EXISTING because mmaps depend on it (to duplicate // the file handle when this handle is a parameter for CreateFileMappingA/W pHMHandleData->dwCreation = OPEN_EXISTING; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->lpDeviceData = pDevData; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; rc = pDeviceHandler->OpenFile(lpFileName, /* call the device handler */ &TabWin32Handles[iIndexNew].hmHandleData, pOFStruct, fuMode); #ifdef DEBUG_LOCAL dprintf(("KERNEL32/HandleManager:CheckPoint3: %s lpHandlerData=%08xh rc=%08xh\n", lpFileName, &TabWin32Handles[iIndexNew].hmHandleData.lpHandlerData, rc)); #endif /* * Based on testcase (5) and MSDN: * "OF_PARSE Fills the OFSTRUCT structure but carries out no other action." */ if (fuMode & OF_PARSE) { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; return 0; } if(rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(pOFStruct->nErrCode); return (INVALID_HANDLE_VALUE); /* signal error */ } else { if(fuMode & (OF_DELETE|OF_EXIST)) { //file handle already closed FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; return TRUE; //TODO: correct? } if(fuMode & OF_VERIFY) { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; return 1; //TODO: correct? } } #ifdef DEBUG_LOCAL dprintf(("KERNEL32/HandleManager: OpenFile(%s)=%08xh\n", lpFileName, iIndexNew)); #endif return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : DWORD HMGetHandleInformation * Purpose : The GetHandleInformation function obtains information about certain * properties of an object handle. The information is obtained as a set of bit flags. * Parameters: HANDLE hObject * LPDWORD lpdwFlags * Variables : * Result : TRUE / FALSE * Remark : * Status : * * Author : SvL *****************************************************************************/ BOOL HMGetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ //Handle information is stored in the handle structure; return it here if(lpdwFlags) { *lpdwFlags = pHMHandle->hmHandleData.dwHandleInformation; } SetLastError(ERROR_SUCCESS); return TRUE; /* deliver return code */ } /***************************************************************************** * Name : BOOL HMSetHandleInformation * Purpose : The SetHandleInformation function sets certain properties of an * object handle. The information is specified as a set of bit flags. * Parameters: HANDLE hObject handle to an object * DWORD dwMask specifies flags to change * DWORD dwFlags specifies new values for flags * Variables : * Result : TRUE / FALSE * Remark : * Status : * * Author : SvL *****************************************************************************/ BOOL HMSetHandleInformation (HANDLE hObject, DWORD dwMask, DWORD dwFlags) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ //SvL: Check if pDeviceHandler is set if (pHMHandle->pDeviceHandler) { fResult = pHMHandle->pDeviceHandler->SetHandleInformation(&pHMHandle->hmHandleData, dwMask, dwFlags); } else { dprintf(("HMSetHandleInformation(%08xh): pDeviceHandler not set", hObject)); fResult = TRUE; } if(fResult == TRUE) { SetLastError(ERROR_SUCCESS); } return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMGetFileNameFromHandle * Purpose : Query the name of the file associated with the system handle (if any) * Parameters: * Variables : * Result : * Remark : * Status : * * Author : SvL *****************************************************************************/ BOOL HMGetFileNameFromHandle(HANDLE hObject, LPSTR lpszFileName, DWORD cbFileName) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ if(lpszFileName == NULL) { DebugInt3(); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ //SvL: Check if pDeviceHandler is set if (pHMHandle->pDeviceHandler) { fResult = pHMHandle->pDeviceHandler->GetFileNameFromHandle(&pHMHandle->hmHandleData, lpszFileName, cbFileName); } else { dprintf(("HMGetFileNameFromHandle(%08xh): pDeviceHandler not set", hObject)); fResult = FALSE; } if(fResult == TRUE) { SetLastError(ERROR_SUCCESS); } return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMCloseFile * Purpose : Wrapper for the CloseHandle() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ BOOL HMCloseHandle(HANDLE hObject) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { //@@@PH it may occur someone closes e.g. a semaphore handle // which is not registered through the HandleManager yet. // so we try to pass on to Open32 instead. dprintf(("KERNEL32: HandleManager:HMCloseHandle(%08xh) passed on to Open32.\n", hObject)); fResult = O32_CloseHandle(hObject); return (fResult); //SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ //return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if(pHMHandle->hmHandleData.dwHandleInformation & HANDLE_FLAG_PROTECT_FROM_CLOSE) { dprintf(("Handle not closed because of HANDLE_FLAG_PROTECT_FROM_CLOSE")); SetLastError(ERROR_SUCCESS); return TRUE; } //SvL: Check if pDeviceHandler is set if (pHMHandle->pDeviceHandler) { fResult = pHMHandle->pDeviceHandler->CloseHandle(&pHMHandle->hmHandleData); } else { dprintf(("HMCloseHAndle(%08xh): pDeviceHandler not set", hObject)); fResult = TRUE; } if (fResult == TRUE) /* remove handle if close succeeded */ { FREEHANDLE(iIndex); // pHMHandle->hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; /* mark handle as free */ SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? } return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMReadFile * Purpose : Wrapper for the ReadHandle() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ BOOL HMReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) { SetLastError(ERROR_SYS_INTERNAL); return (FALSE); } fResult = pHMHandle->pDeviceHandler->ReadFile(&pHMHandle->hmHandleData, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped, lpCompletionRoutine); return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMWriteFile * Purpose : Wrapper for the WriteHandle() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ BOOL HMWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped, LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } /* watcom hack: * watcom may write -1 bytes to a device during flushall(), we should return * ERROR_NOT_ENOUGH_MEMORY or ERROR_NO_ACCESS */ if (nNumberOfBytesToWrite == 0xffffffff) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; fResult = pHMHandle->pDeviceHandler->WriteFile(&pHMHandle->hmHandleData, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped, lpCompletionRoutine); return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMGetFileType * Purpose : Wrapper for the GetFileType() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/12 13:37] *****************************************************************************/ DWORD WIN32API GetFileType(HANDLE hFile) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FILE_TYPE_UNKNOWN; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->GetFileType(&pHMHandle->hmHandleData); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::_DeviceReuqest * Purpose : entry method for special request functions * Parameters: ULONG ulRequestCode * various parameters as required * Variables : * Result : * Remark : the standard behaviour is to return an error code for non- * existant request codes * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ DWORD HMDeviceRequest (HANDLE hFile, ULONG ulRequestCode, ULONG arg1, ULONG arg2, ULONG arg3, ULONG arg4) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (INVALID_HANDLE_ERROR); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->_DeviceRequest(&pHMHandle->hmHandleData, ulRequestCode, arg1, arg2, arg3, arg4); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::GetFileInformationByHandle * Purpose : router function for GetFileInformationByHandle * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API GetFileInformationByHandle (HANDLE hFile, BY_HANDLE_FILE_INFORMATION *pHFI) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->GetFileInformationByHandle(&pHMHandle->hmHandleData, pHFI); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::SetEndOfFile * Purpose : router function for SetEndOfFile * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API SetEndOfFile (HANDLE hFile) { int iIndex; /* index into the handle table */ BOOL bResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; bResult = pHMHandle->pDeviceHandler->SetEndOfFile(&pHMHandle->hmHandleData); return (bResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::SetFileTime * Purpose : router function for SetFileTime * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API SetFileTime (HANDLE hFile, const FILETIME *pFT1, const FILETIME *pFT2, const FILETIME *pFT3) { int iIndex; /* index into the handle table */ BOOL bResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; bResult = pHMHandle->pDeviceHandler->SetFileTime(&pHMHandle->hmHandleData, (LPFILETIME)pFT1, (LPFILETIME)pFT2, (LPFILETIME)pFT3); return (bResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::GetFileTime * Purpose : router function for SetFileTime * Parameters: * Variables : * Result : * Remark : * Status : * * Author : SvL *****************************************************************************/ BOOL WIN32API GetFileTime (HANDLE hFile, FILETIME *pFT1, FILETIME *pFT2, FILETIME *pFT3) { int iIndex; /* index into the handle table */ BOOL bResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; bResult = pHMHandle->pDeviceHandler->GetFileTime(&pHMHandle->hmHandleData, (LPFILETIME)pFT1, (LPFILETIME)pFT2, (LPFILETIME)pFT3); return (bResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::GetFileSize * Purpose : router function for GetFileSize * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD WIN32API GetFileSize (HANDLE hFile, PDWORD pSize) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return -1; //INVALID_SET_FILE_POINTER } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->GetFileSize(&pHMHandle->hmHandleData, pSize); return (dwResult); /* deliver return code */ } /*********************************************************************** * GetFileSizeEx (KERNEL32.@) */ BOOL WINAPI GetFileSizeEx( HANDLE hFile, PLARGE_INTEGER lpFileSize ) { lpFileSize->LowPart = GetFileSize(hFile, ((PDWORD)&lpFileSize->HighPart)); return (lpFileSize->LowPart != INVALID_FILE_SIZE); } /***************************************************************************** * Name : HMDeviceHandler::SetFilePointer * Purpose : router function for SetFilePointer * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD WIN32API SetFilePointer (HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (INVALID_HANDLE_ERROR); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->SetFilePointer(&pHMHandle->hmHandleData, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); return (dwResult); /* deliver return code */ } /*********************************************************************** * SetFilePointerEx (KERNEL32.@) */ BOOL WINAPI SetFilePointerEx( HANDLE hFile, LARGE_INTEGER distance, LARGE_INTEGER *newpos, DWORD method ) { LONG pos; LONG newp; BOOL res; dprintf(("KERNEL32::SetFilePointerEx")); pos = (LONG)distance.LowPart; res = SetFilePointer(hFile, pos, &newp, method); if (res != -1) { if (newpos) newpos->LowPart = (LONG)res; return TRUE; } return FALSE; } /***************************************************************************** * Name : HMDeviceHandler::LockFile * Purpose : router function for LockFile * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API LockFile (HANDLE hFile, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->LockFile(&pHMHandle->hmHandleData, arg2, arg3, arg4, arg5); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : BOOL LockFileEx * Purpose : The LockFileEx function locks a byte range within an open file for shared or exclusive access. * Parameters: HANDLE hFile handle of file to lock * DWORD dwFlags functional behavior modification flags * DWORD dwReserved reserved, must be set to zero * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset * Variables : * Result : TRUE / FALSE * Remark : * Status : UNTESTED STUB * * Author : Patrick Haller [Mon, 1998/06/15 08:00] *****************************************************************************/ BOOL WIN32API LockFileEx(HANDLE hFile, DWORD dwFlags, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped) { int iIndex; /* index into the handle table */ BOOL dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->LockFileEx(&pHMHandle->hmHandleData, dwFlags, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, lpOverlapped); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::UnlockFile * Purpose : router function for UnlockFile * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API UnlockFile (HANDLE hFile, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5) { int iIndex; /* index into the handle table */ BOOL dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->UnlockFile(&pHMHandle->hmHandleData, arg2, arg3, arg4, arg5); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : BOOL UnlockFileEx * Purpose : The UnlockFileEx function unlocks a previously locked byte range in an open file. * Parameters: HANDLE hFile handle of file to lock * DWORD dwReserved reserved, must be set to zero * DWORD nNumberOfBytesToLockLow low-order 32 bits of length to lock * DWORD nNumberOfBytesToLockHigh high-order 32 bits of length to lock * LPOVERLAPPED LPOVERLAPPED addr. of structure with lock region start offset * Variables : * Result : TRUE / FALSE * Remark : * Status : UNTESTED STUB * * Author : Patrick Haller [Mon, 1998/06/15 08:00] *****************************************************************************/ BOOL WIN32API UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh, LPOVERLAPPED lpOverlapped) { int iIndex; /* index into the handle table */ BOOL bResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; bResult = pHMHandle->pDeviceHandler->UnlockFileEx(&pHMHandle->hmHandleData, dwReserved, nNumberOfBytesToLockLow, nNumberOfBytesToLockHigh, lpOverlapped); return (bResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::WaitForSingleObject * Purpose : router function for WaitForSingleObject * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD HMWaitForSingleObject(HANDLE hObject, DWORD dwTimeout) { int iIndex; /* index into the handle table */ BOOL dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { dprintf(("KERNEL32: HandleManager:HMWaitForSingleObject(%08xh) passed on to Open32.\n", hObject)); if(dwTimeout == INFINITE) { //Workaround for applications that block the PM input queue //while waiting for a child process to terminate. //(WaitSingleObject now calls MsgWaitMultipleObjects and // processes messages while waiting for the process to die) //(Napster install now doesn't block PM anymore (forcing a reboot)) HMODULE hUser32 = LoadLibraryA("USER32.DLL"); BOOL (* WINAPI pfnPeekMessageA)(LPMSG,HWND,UINT,UINT,UINT); LONG (* WINAPI pfnDispatchMessageA)(const MSG*); *(FARPROC *)&pfnPeekMessageA = GetProcAddress(hUser32,"PeekMessageA"); *(FARPROC *)&pfnDispatchMessageA = GetProcAddress(hUser32,"DispatchMessageA"); TEB *teb = GetThreadTEB(); if(!teb || !pfnPeekMessageA || !pfnDispatchMessageA) { dprintf(("ERROR: !teb || !pfnPeekMessageA || !pfnDispatchMessageA")); DebugInt3(); return WAIT_FAILED; } //TODO: Ignoring all messages could be dangerous. But processing them, //while the app doesn't expect any, isn't safe either. //-> must active check in pmwindow.cpp if this is enabled again! // teb->o.odin.fIgnoreMsgs = TRUE; while(TRUE) { dwResult = HMMsgWaitForMultipleObjects(1, &hObject, FALSE, INFINITE, QS_ALLINPUT); if(dwResult == WAIT_OBJECT_0 + 1) { MSG msg ; while (pfnPeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) { dprintf(("ERROR: WaitForSingleObject call abandoned because WM_QUIT msg was received!!")); // teb->o.odin.fIgnoreMsgs = FALSE; FreeLibrary(hUser32); return WAIT_ABANDONED; } /* otherwise dispatch it */ pfnDispatchMessageA(&msg); } // end of PeekMessage while loop } else { dprintf(("WaitForSingleObject: Process %x terminated", hObject)); break; } } // teb->o.odin.fIgnoreMsgs = FALSE; FreeLibrary(hUser32); return dwResult; } else { // maybe handles from CreateProcess() ... dwResult = O32_WaitForSingleObject(hObject, dwTimeout); return (dwResult); } } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->WaitForSingleObject(&pHMHandle->hmHandleData, dwTimeout); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::WaitForSingleObjectEx * Purpose : router function for WaitForSingleObjectEx * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD HMWaitForSingleObjectEx(HANDLE hObject, DWORD dwTimeout, BOOL fAlertable) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return WAIT_FAILED; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->WaitForSingleObjectEx(&pHMHandle->hmHandleData, dwTimeout, fAlertable); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::FlushFileBuffers * Purpose : router function for FlushFileBuffers * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API FlushFileBuffers(HANDLE hFile) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFile); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->FlushFileBuffers(&pHMHandle->hmHandleData); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMDeviceHandler::GetOverlappedResult * Purpose : router function for GetOverlappedResult * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL HMGetOverlappedResult(HANDLE hObject, LPOVERLAPPED lpOverlapped, LPDWORD arg3, BOOL arg4) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->GetOverlappedResult(&pHMHandle->hmHandleData, lpOverlapped, arg3, arg4); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HMReleaseMutex * Purpose : router function for ReleaseMutex * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API ReleaseMutex(HANDLE hObject) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return FALSE; /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->ReleaseMutex(&pHMHandle->hmHandleData); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMCreateMutex * Purpose : Wrapper for the CreateMutex() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE WIN32API CreateMutexA(LPSECURITY_ATTRIBUTES lpsa, BOOL bInitialOwner, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ if(lpName) { //check if shared mutex semaphore already exists dprintf(("Event semaphore name %s", lpName)); //TODO: No inheritance?? HANDLE handle = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, lpName); if(handle) { dprintf(("CreateMutex: return handle of existing mutex semaphore %x", handle)); SetLastError(ERROR_ALREADY_EXISTS); return handle; } } pDeviceHandler = HMGlobals.pHMMutex; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = 0; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_MUTEXSEM; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->CreateMutex(&TabWin32Handles[iIndexNew].hmHandleData, lpsa, bInitialOwner, lpName); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return 0; /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMOpenMutex * Purpose : Wrapper for the OpenMutex() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE WIN32API OpenMutexA(DWORD fdwAccess, BOOL fInherit, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ if(lpName) { dprintf(("Mutex semaphore name %s", lpName)); } pDeviceHandler = HMGlobals.pHMMutex; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = fdwAccess; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_MUTEXSEM; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->OpenMutex(&TabWin32Handles[iIndexNew].hmHandleData, fInherit, lpName); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return 0; /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMCreateSemaphore * Purpose : Wrapper for the CreateSemaphore() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE WIN32API CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpsa, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ if(lpName) { //check if shared event semaphore already exists //TODO: No inheritance?? dprintf(("Semaphore name %s", lpName)); HANDLE handle = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, lpName); if(handle) { dprintf(("CreateSemaphore: return handle of existing semaphore %x", handle)); SetLastError(ERROR_ALREADY_EXISTS); return handle; } } pDeviceHandler = HMGlobals.pHMSemaphore; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = 0; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_SEMAPHORE; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->CreateSemaphore(&TabWin32Handles[iIndexNew].hmHandleData, lpsa, lInitialCount, lMaximumCount, lpName); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return 0; /* signal failure */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMOpenSemaphore * Purpose : Wrapper for the OpenSemaphore() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE WIN32API OpenSemaphoreA(DWORD fdwAccess, BOOL fInherit, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ if(lpName) { dprintf(("Semaphore name %s", lpName)); } pDeviceHandler = HMGlobals.pHMSemaphore; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = fdwAccess; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_SEMAPHORE; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->OpenSemaphore(&TabWin32Handles[iIndexNew].hmHandleData, fInherit, lpName); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return 0; /* signal failure */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HMReleaseSemaphore * Purpose : router function for ReleaseSemaphore * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ BOOL WIN32API ReleaseSemaphore(HANDLE hEvent, LONG cReleaseCount, LPLONG lpPreviousCount) { int iIndex; /* index into the handle table */ DWORD dwResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hEvent); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return 0; /* signal failure */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; dwResult = pHMHandle->pDeviceHandler->ReleaseSemaphore(&pHMHandle->hmHandleData, cReleaseCount, lpPreviousCount); return (dwResult); /* deliver return code */ } /***************************************************************************** * Name : HANDLE HMCreateFileMapping * Purpose : Wrapper for the CreateFileMapping() API * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE HMCreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ pDeviceHandler = HMGlobals.pHMFileMapping; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return 0; /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = 0; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_MEMMAP; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ // @@@PH: Note: hFile is a Win32-style handle, it's not (yet) converted to // a valid HandleManager-internal handle! rc = pDeviceHandler->CreateFileMapping(&TabWin32Handles[iIndexNew].hmHandleData, hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName); if(rc != NO_ERROR) /* oops, creation failed within the device handler */ { if(rc != ERROR_ALREADY_EXISTS) { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return (NULL); /* signal error */ } SetLastError(ERROR_ALREADY_EXISTS); return iIndexNew; /* return valid handle */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HANDLE HMOpenFileMapping * Purpose : Wrapper for the OpenFileMapping() API * Parameters: * Variables : * Result : HANDLE if succeeded, * NULL if failed. * Remark : * Status : * * Author : Patrick Haller [Wed, 1998/02/11 20:44] *****************************************************************************/ HANDLE HMOpenFileMapping(DWORD fdwAccess, BOOL fInherit, LPCTSTR lpName) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ pDeviceHandler = HMGlobals.pHMFileMapping; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return (NULL); /* signal error */ } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = fdwAccess; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ rc = pDeviceHandler->OpenFileMapping(&TabWin32Handles[iIndexNew].hmHandleData, fdwAccess, fInherit, lpName); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; SetLastError(rc); /* Hehe, OS/2 and NT are pretty compatible :) */ return (NULL); /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? return iIndexNew; /* return valid handle */ } /***************************************************************************** * Name : HMMapViewOfFileEx * Purpose : router function for MapViewOfFileEx * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ LPVOID HMMapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress) { int iIndex; /* index into the handle table */ LPVOID lpResult; /* result from the device handler's API */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hFileMappingObject); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (NULL); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return NULL; lpResult = pHMHandle->pDeviceHandler->MapViewOfFileEx(&pHMHandle->hmHandleData, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap, lpBaseAddress); return (lpResult); /* deliver return code */ } /***************************************************************************** * Name : HMWaitForMultipleObjects * Purpose : router function for WaitForMultipleObjects * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD HMWaitForMultipleObjects (DWORD cObjects, PHANDLE lphObjects, BOOL fWaitAll, DWORD dwTimeout) { ULONG ulIndex; PHANDLE pArrayOfHandles; PHANDLE pLoop1 = lphObjects; PHANDLE pLoop2; DWORD rc; // allocate array for handle table pArrayOfHandles = (PHANDLE)alloca(cObjects * sizeof(HANDLE)); if (pArrayOfHandles == NULL) { dprintf(("ERROR: HMWaitForMultipleObjects: alloca failed to allocate %d handles", cObjects)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return WAIT_FAILED; } else pLoop2 = pArrayOfHandles; // convert array to odin handles for (ulIndex = 0; ulIndex < cObjects; ulIndex++, pLoop1++, pLoop2++) { rc = HMHandleTranslateToOS2 (*pLoop1, // translate handle pLoop2); dprintf(("KERNEL32: HMWaitForMultipleObjects: handle %3i: ODIN-%08xh, Open32-%08xh\n", ulIndex, *pLoop1, *pLoop2)); // @@@PH to imlpement: check handle type! // SvL: We still use Open32 handles for threads & processes -> don't fail here! if (rc != NO_ERROR) { dprintf(("KERNEL32: HMWaitForMultipleObjects - WARNING: handle %08xh is NOT an Odin handle (probably Open32 thread or process)\n", *pLoop1)); *pLoop2 = *pLoop1; //// SetLastError(ERROR_INVALID_HANDLE); //// return (WAIT_FAILED); } } // OK, now forward to Open32. // @@@PH: Note this will fail on handles that do NOT belong to Open32 // but to i.e. the console subsystem! rc = O32_WaitForMultipleObjects(cObjects, pArrayOfHandles, fWaitAll, dwTimeout); return (rc); // OK, done } /***************************************************************************** * Name : HMWaitForMultipleObjectsEx * Purpose : router function for WaitForMultipleObjectsEx * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD HMWaitForMultipleObjectsEx (DWORD cObjects, PHANDLE lphObjects, BOOL fWaitAll, DWORD dwTimeout, BOOL fAlertable) { // @@@PH: Note: fAlertable is ignored ! return (HMWaitForMultipleObjects(cObjects, lphObjects, fWaitAll, dwTimeout)); } /***************************************************************************** * Name : HMMsgWaitForMultipleObjects * Purpose : router function for MsgWaitForMultipleObjects * Parameters: * Variables : * Result : * Remark : Open32 doesn't implement this properly! (doesn't check dwWakeMask) * Status : * * Author : Patrick Haller [Wed, 1999/06/17 20:44] *****************************************************************************/ DWORD HMMsgWaitForMultipleObjects (DWORD cObjects, LPHANDLE lphObjects, BOOL fWaitAll, DWORD dwTimeout, DWORD dwWakeMask) { ULONG ulIndex; PHANDLE pArrayOfHandles; PHANDLE pLoop1 = lphObjects; PHANDLE pLoop2; DWORD rc; // allocate array for handle table pArrayOfHandles = (PHANDLE)alloca(cObjects * sizeof(HANDLE)); if (pArrayOfHandles == NULL) { dprintf(("ERROR: HMMsgWaitForMultipleObjects: alloca failed to allocate %d handles", cObjects)); SetLastError(ERROR_NOT_ENOUGH_MEMORY); return WAIT_FAILED; } else pLoop2 = pArrayOfHandles; // convert array to odin handles for (ulIndex = 0; ulIndex < cObjects; ulIndex++, pLoop1++, pLoop2++) { rc = HMHandleTranslateToOS2 (*pLoop1, // translate handle pLoop2); dprintf2(("MsgWaitForMultipleObjects handle %x->%x", *pLoop1, *pLoop2)); // SvL: We still use Open32 handles for threads & processes -> don't fail here! if (rc != NO_ERROR) { dprintf(("KERNEL32: HMMsgWaitForMultipleObjects - WARNING: handle %08xh is NOT an Odin handle (probably Open32 thread or process)\n", *pLoop1)); *pLoop2 = *pLoop1; //// SetLastError(ERROR_INVALID_HANDLE); //// return (WAIT_FAILED); } } // OK, now forward to Open32. // @@@PH: Note this will fail on handles that do NOT belong to Open32 // but to i.e. the console subsystem! rc = O32_MsgWaitForMultipleObjects(cObjects, pArrayOfHandles, fWaitAll, dwTimeout, dwWakeMask); dprintf2(("MsgWaitForMultipleObjects returned %d", rc)); return (rc); // OK, done } /***************************************************************************** * Name : HMDeviceIoControl * Purpose : router function for DeviceIoControl * Parameters: * Variables : * Result : * Remark : * Status : * * Author : Sander van Leeuwen *****************************************************************************/ BOOL WIN32API DeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hDevice); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; fResult = pHMHandle->pDeviceHandler->DeviceIoControl(&pHMHandle->hmHandleData, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped); return (fResult); /* deliver return code */ } /***************************************************************************** * Name : BOOL WIN32API CancelIo * Purpose : The CancelIO function cancels all pending input and output * (I/O) operations that were issued by the calling thread for * the specified file handle. The function does not cancel * I/O operations issued for the file handle by other threads. * Parameters: HANDLE hFile file handle for which to cancel I/O * Variables : * Result : If the function succeeds, the return value is nonzero All pending * I/O operations issued by the calling thread for the file handle * were successfully canceled. * If the function fails, the return value is zero. * To get extended error information, call GetLastError. * Remark : If there are any I/O operations in progress for the specified * file HANDLE and they were issued by the calling thread, the * CancelIO function cancels them. * Note that the I/O operations must have been issued as * overlapped I/O. If they were not, the I/O operations would not * have returned to allow the thread to call the CancelIO function. * Calling the CancelIO function with a file handle that was not * opened with FILE_FLAG_OVERLAPPED does nothing. * All I/O operations that are canceled will complete with the * error ERROR_OPERATION_ABORTED. All completion notifications * for the I/O operations will occur normally. * Status : * * Author : Sander van Leeuwen *****************************************************************************/ BOOL WIN32API CancelIo(HANDLE hDevice) { int iIndex; /* index into the handle table */ BOOL fResult; /* result from the device handler's CloseHandle() */ PHMHANDLE pHMHandle; /* pointer to the handle structure in the table */ /* validate handle */ iIndex = _HMHandleQuery(hDevice); /* get the index */ if (-1 == iIndex) /* error ? */ { SetLastError(ERROR_INVALID_HANDLE); /* set win32 error information */ return (FALSE); /* signal failure */ } pHMHandle = &TabWin32Handles[iIndex]; /* call device handler */ if (!pHMHandle || !pHMHandle->pDeviceHandler) return ERROR_SYS_INTERNAL; fResult = pHMHandle->pDeviceHandler->CancelIo(&pHMHandle->hmHandleData); return (fResult); /* deliver return code */ } /***************************************************************************** * Name : HMOpenThreadToken * Purpose : router function for NtOpenThreadToken * Parameters: * Variables : * Result : * Remark : * Status : * * Author : SvL *****************************************************************************/ DWORD HMOpenThreadToken(HANDLE ThreadHandle, DWORD DesiredAccess, DWORD OpenAsSelf, HANDLE *TokenHandle) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ pDeviceHandler = HMGlobals.pHMToken; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return ERROR_NOT_ENOUGH_MEMORY; } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = DesiredAccess; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_THREADTOKEN; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ // @@@PH: Note: hFile is a Win32-style handle, it's not (yet) converted to // a valid HandleManager-internal handle! rc = pDeviceHandler->OpenThreadToken(&TabWin32Handles[iIndexNew].hmHandleData, ThreadHandle, OpenAsSelf); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; return (rc); /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? *TokenHandle = iIndexNew; /* return valid handle */ return STATUS_SUCCESS; } /***************************************************************************** * Name : HMOpenProcessToken * Purpose : router function for NtOpenProcessToken * Parameters: * Variables : * Result : * Remark : * Status : * * Author : SvL *****************************************************************************/ DWORD HMOpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, DWORD dwUserData, HANDLE *TokenHandle) { int iIndex; /* index into the handle table */ int iIndexNew; /* index into the handle table */ HMDeviceHandler *pDeviceHandler; /* device handler for this handle */ PHMHANDLEDATA pHMHandleData; DWORD rc; /* API return code */ pDeviceHandler = HMGlobals.pHMToken; /* device is predefined */ iIndexNew = _HMHandleGetFree(); /* get free handle */ if (-1 == iIndexNew) /* oops, no free handles ! */ { SetLastError(ERROR_NOT_ENOUGH_MEMORY); /* use this as error message */ return ERROR_NOT_ENOUGH_MEMORY; } /* initialize the complete HMHANDLEDATA structure */ pHMHandleData = &TabWin32Handles[iIndexNew].hmHandleData; pHMHandleData->dwAccess = DesiredAccess; pHMHandleData->dwShare = 0; pHMHandleData->dwCreation = 0; pHMHandleData->dwFlags = 0; pHMHandleData->lpHandlerData = NULL; pHMHandleData->dwInternalType = HMTYPE_PROCESSTOKEN; /* we've got to mark the handle as occupied here, since another device */ /* could be created within the device handler -> deadlock */ /* write appropriate entry into the handle table if open succeeded */ TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = iIndexNew; TabWin32Handles[iIndexNew].pDeviceHandler = pDeviceHandler; /* call the device handler */ // @@@PH: Note: hFile is a Win32-style handle, it's not (yet) converted to // a valid HandleManager-internal handle! rc = pDeviceHandler->OpenProcessToken(&TabWin32Handles[iIndexNew].hmHandleData, dwUserData, ProcessHandle); if (rc != NO_ERROR) /* oops, creation failed within the device handler */ { FREEHANDLE(iIndexNew); // TabWin32Handles[iIndexNew].hmHandleData.hHMHandle = INVALID_HANDLE_VALUE; return (rc); /* signal error */ } else SetLastError(ERROR_SUCCESS); //@@@PH 1999/10/27 rc5desg requires this? *TokenHandle = iIndexNew; /* return valid handle */ return STATUS_SUCCESS; } /** * Gets the type of an object. * * @returns the value of one of the HMMTYPE_ defines. * @returns HMTYPE_BAD_HANDLE if hObject isn't a valid handle. * @param hObject Handle to object. */ unsigned WIN32API HMQueryObjectType(HANDLE hObject) { PHMHANDLEDATA pData = HMQueryHandleData(hObject); if (pData) return (unsigned)pData->dwInternalType; return HMTYPE_BAD_HANDLE; } } // extern "C"