summaryrefslogtreecommitdiffstats
path: root/private/os2/client/dllwin32.c
blob: 951d10c034040b0fe0bc4b0f5de2e79a8ab95b60 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#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);
}