summaryrefslogblamecommitdiffstats
path: root/private/os2/client/dllwin32.c
blob: 951d10c034040b0fe0bc4b0f5de2e79a8ab95b60 (plain) (tree)













































































































































































































































































































                                                                              
#include <os2ssrtl.h>
#include <os2tile.h>
#include <os2dbg.h>
#include <os2err.h>

ULONG
LoadLibraryA(PSZ);

ULONG
GetProcAddress(HANDLE, PSZ);

ULONG
GetLastError(VOID);

ULONG
FreeLibrary(HANDLE);

VOID
Od2ProbeForRead(
    IN PVOID Address,
    IN ULONG Length,
    IN ULONG Alignment
    );

VOID
Od2ProbeForWrite(
    IN PVOID Address,
    IN ULONG Length,
    IN ULONG Alignment
    );

VOID
Od2ExitGP();

typedef (*func) (PVOID);


//
// Dos32LoadModule -
//
// Purpose : Load a win32 thunk DLL that will intermediate between an OS/2
//           app and win32 APIs.
//
// Returns : If NO_ERROR is returned, the value pointed by pDllHandle
//           is used for other win32 thunk APIs. It is invalid for usage
//           with regular OS/2 APIs. If ERROR_MOD_NOT_FOUND is returned,
//           the value pointed by pDllHandle is undefined.
//
APIRET
Dos32LoadModule(
    IN  PSZ     DllName,
    OUT PULONG  pDllHandle
    )
{
    try {
        Od2ProbeForRead((PVOID)DllName, sizeof(ULONG), 1);
        Od2ProbeForWrite( pDllHandle, sizeof(ULONG), 1 );
    } except( EXCEPTION_EXECUTE_HANDLER ) {
       Od2ExitGP();
    }

    *pDllHandle = (ULONG) LoadLibraryA(DllName);

#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("Dos32LoadModule:  DllName    - %s\n", DllName);
        DbgPrint("                  DllHandle  - 0x%lx\n", *pDllHandle);
    }
#endif

    if (*pDllHandle == (ULONG)NULL) {
        return(ERROR_MOD_NOT_FOUND);
    }
    return(NO_ERROR);
}



//
// Dos32GetProcAddr -
//
// Purpose : Get a cookie (flat pointer) to a routine in a win32 thunk DLL,
//           previously opened by Dos32LoadModule. For example, if the OS/2
//           app wants to call the WinSocketFoo API, it builds a win32
//           intermediate DLL, named MySock.DLL, that export WinSocketFoo.
//           The app calls Dos32LoadModule with "MySock" and then
//           Dos32GetProcAddr with pszProcName of value "WinSoketFoo". If no
//           error is returned, it can use the value pointed by pWin32Thunk
//           in a later call to Dos32Dispatch, for calling the WinSocketFoo
//           routine, which in turn will call a real Win32.
//
// Returns : NO_ERROR if the pszProcName is exported by the win32 intermediate
//           DLL which relates to DllHandle. If ERROR_PROC_NOT_FOUND or
//           ERROR_INVALID_HANDLE are returned, the value pointed by
//           pWin32Thunk is undefined.
//
APIRET
Dos32GetProcAddr(
    IN  HANDLE  DllHandle,
    IN  PSZ     pszProcName,
    OUT PULONG  pWin32Thunk
    )
{
    try {
        Od2ProbeForRead((PVOID)pszProcName, sizeof(ULONG), 1);
        Od2ProbeForWrite( pWin32Thunk, sizeof(ULONG), 1 );
    } except( EXCEPTION_EXECUTE_HANDLER ) {
       Od2ExitGP();
    }

    *pWin32Thunk = (ULONG) GetProcAddress(DllHandle, pszProcName);

#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("Dos32GetProcAddr: DllHandle  - 0x%lx\n", DllHandle);
        DbgPrint("                  ProcName   - %s\n", pszProcName);
        DbgPrint("                  Win32Thunk - 0x%lx\n", *pWin32Thunk);
    }
#endif

    if (*pWin32Thunk == (ULONG)NULL) {
        if (GetLastError() == 6 /* ERROR_INVALID_HANDLE */) {
            return(ERROR_INVALID_HANDLE);
        }
        return(ERROR_PROC_NOT_FOUND);
    }
    return(NO_ERROR);
}



//
// Dos32Dispatch -
//
// Purpose : Dos32Dispatch calls the 32bit thunk routine Win32Thunk,
//           previosly obtained by Dos32GetProcAddr. It returns the error
//           code returned by Win32Thunk in pRetCode. It translates the
//           pArguments 16:16 pointer to a flat pointer and passes it to the
//           Win32Thunk call. The structure pointed by pArguments, and the
//           values of pRetCode are app specific and are not interpreted
//           or modified by the OS/2 subsystem.
//
//           The Win32Thunk has to by defined as following:
//
//           ULONG WinSocketFoo(
//              PVIOD pFlatArg
//              );
//
// Returns : NO_ERROR if the Win32Thunk argument is a valid pointer and no
//           exception occured in the call to it.
//
APIRET
Dos32Dispatch(
    IN  ULONG       Win32Thunk,
    IN  PVOID       pArguments,
    OUT PULONG      pRetCode
    )
{
#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("Dos32Dispatch:    Win32Thunk - 0x%lx\n", Win32Thunk);
    }
#endif

    try {
        *pRetCode = (*(func)Win32Thunk) (pArguments);
    } except( EXCEPTION_EXECUTE_HANDLER ) {
       Od2ExitGP();
    }

    return(NO_ERROR);
}



//
// Dos32FreeModule -
//
// Purpose : Unload a win32 thunk DLL that intermediates between an OS/2 app
//           and win32 APIs.
//
// Returns : If NO_ERROR is returnd, the DllHandle is used for other win32
//           thunk APIs. It is invalid for usage with regular OS/2 APIs.
//           If ERROR_INVALID_HANDLE is returned, DllHandle is undefined.
//
APIRET
Dos32FreeModule(
    IN  HANDLE  DllHandle
    )
{
#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("Dos32FreeMudule:  DllHandle  - 0x%lx\n", DllHandle);
    }
#endif

    if (FreeLibrary(DllHandle)) {
        return(NO_ERROR);
    }
    return(ERROR_INVALID_HANDLE);
}



//
// FarPtr2FlatPtr -
//
// Purpose : Translates the segmented pointer FarPtr to a flat pointer
//           pointed by pFlatPtr.
//
// Returns : NO_ERROR if the FarPtr is a valid 16:16 pointer. In this
//           case pFlatPtr contains a valid 32 bit flat pointer to be used
//           by win32 code. If ERROR_INVALID_PARAMETER is returned then
//           the 16:16 pointer is not valid and the value pointed by pFlatPtr
//           is undefined.
//
APIRET
FarPtr2FlatPtr(
    IN  ULONG   FarPtr,
    OUT PULONG  pFlatPtr
    )
{
    try {
        Od2ProbeForWrite( pFlatPtr, sizeof( ULONG ), 1 );
    } except( EXCEPTION_EXECUTE_HANDLER ) {
       Od2ExitGP();
    }

    try {
        Od2ProbeForRead((PVOID)*pFlatPtr = FARPTRTOFLAT(FarPtr),
                        sizeof(ULONG),
                        1);
    } except( EXCEPTION_CONTINUE_EXECUTION ) {
        return(ERROR_INVALID_PARAMETER);
    }

    if ((*pFlatPtr < BASE_TILE) || (*pFlatPtr >= BASE_TILE + _512M)) {
        return(ERROR_INVALID_PARAMETER);
    }

#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("FarPtr2FlatPtr:   FarPtr  - 0x%lx\n", FarPtr);
        DbgPrint("                  FlatPtr - 0x%lx\n", *pFlatPtr);
    }
#endif

    return(NO_ERROR);
}



//
// FlatPtr2FarPtr -
//
// Purpose : Translates the flat pointer FlatPtr to a far pointer pFarPtr.
//
// Returns : NO_ERROR if the FlatPtr has a valid 16:16 pointer in the
//           16 bit app context. In this case pFarPtr contains a valid 16:16
//           segmented pointer to by used by the 16 bit OS/2 code.
//           If ERROR_INVALID_PARAMETER is returned then the pFarPtr is
//           undefined.
//
APIRET
FlatPtr2FarPtr(
    IN  ULONG   FlatPtr,
    OUT PULONG  pFarPtr
    )
{
    if ((FlatPtr < BASE_TILE) || (FlatPtr >= BASE_TILE + _512M)) {
        return(ERROR_INVALID_PARAMETER);
    }

    try {
        Od2ProbeForWrite( pFarPtr, sizeof( ULONG ), 1 );
    } except( EXCEPTION_EXECUTE_HANDLER ) {
       Od2ExitGP();
    }

#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("FlatPtr2FarPtr:   FlatPtr - 0x%lx\n", FlatPtr);
    }
#endif

    try {
        Od2ProbeForRead( (PVOID) FlatPtr, 1, 1 );
    } except (EXCEPTION_CONTINUE_EXECUTION ) {
        return(ERROR_INVALID_PARAMETER);
    }


    *pFarPtr = FLATTOFARPTR(FlatPtr);

#if DBG
    IF_OD2_DEBUG ( LOADER ) {
        DbgPrint("                  FarPtr  - 0x%lx\n", *pFarPtr);
    }
#endif

    return(NO_ERROR);
}