blob: 3b807be569e3110cf749061f9ce818df50ac9659 [file] [log] [blame]
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001/*
2 * VxD emulation
3 *
4 * Copyright 1995 Anand Kumria
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000019 */
20
Patrik Stridvalld016f812002-08-17 00:43:16 +000021#include "config.h"
Patrik Stridvall51e6c0c2002-08-31 19:04:14 +000022#include "wine/port.h"
Patrik Stridvalld016f812002-08-17 00:43:16 +000023
Alexandre Julliard642d3131998-07-12 19:29:36 +000024#include <fcntl.h>
25#include <memory.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000026#include <stdarg.h>
Patrik Stridvall51e6c0c2002-08-31 19:04:14 +000027#include <stdio.h>
Jeremy Whited3e22d92000-02-10 19:03:02 +000028#include <sys/types.h>
Patrik Stridvalld016f812002-08-17 00:43:16 +000029#ifdef HAVE_UNISTD_H
30# include <unistd.h>
31#endif
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000032
33#define NONAMELESSUNION
34#define NONAMELESSSTRUCT
Jeremy Whited3e22d92000-02-10 19:03:02 +000035#include "windef.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000036#include "winbase.h"
37#include "winreg.h"
Patrik Stridvall9c1de6d2002-09-12 22:07:02 +000038#include "winternl.h"
Jeremy Whited3e22d92000-02-10 19:03:02 +000039#include "wingdi.h"
Marcus Meissner219cfd81999-02-24 13:05:13 +000040#include "winuser.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000041#include "ntstatus.h"
Marcus Meissner219cfd81999-02-24 13:05:13 +000042#include "wine/winbase16.h"
43#include "wine/winuser16.h"
Alexandre Julliarde9836522003-11-15 00:13:20 +000044#include "dosexe.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000045#include "wine/debug.h"
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000046
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000047WINE_DEFAULT_DEBUG_CHANNEL(vxd);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000048
Jukka Heinonen56dff0d2002-11-20 19:40:12 +000049#define W32S_APP2WINE(addr) ((addr)? (DWORD)(addr) + W32S_offset : 0)
50#define W32S_WINE2APP(addr) ((addr)? (DWORD)(addr) - W32S_offset : 0)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000051
Alexandre Julliard139a4b11996-11-02 14:24:07 +000052#define VXD_BARF(context,name) \
Alexandre Julliard61fece01999-06-26 19:09:08 +000053 DPRINTF( "vxd %s: unknown/not implemented parameters:\n" \
Alexandre Julliard139a4b11996-11-02 14:24:07 +000054 "vxd %s: AX %04x, BX %04x, CX %04x, DX %04x, " \
55 "SI %04x, DI %04x, DS %04x, ES %04x\n", \
56 (name), (name), AX_reg(context), BX_reg(context), \
57 CX_reg(context), DX_reg(context), SI_reg(context), \
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +000058 DI_reg(context), (WORD)context->SegDs, (WORD)context->SegEs )
Alexandre Julliard139a4b11996-11-02 14:24:07 +000059
Alexandre Julliardbecb9a32000-12-11 03:48:15 +000060UINT W32S_offset = 0;
Alexandre Julliard670cdc41997-08-24 16:00:30 +000061
62static WORD VXD_WinVersion(void)
63{
Alexandre Julliard3db94ef1997-09-28 17:43:24 +000064 WORD version = LOWORD(GetVersion16());
Alexandre Julliard670cdc41997-08-24 16:00:30 +000065 return (version >> 8) | (version << 8);
66}
67
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000068/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +000069 * VXD_VMM (WPROCS.401)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000070 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +000071void WINAPI VXD_VMM ( CONTEXT86 *context )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000072{
73 unsigned service = AX_reg(context);
74
Alexandre Julliard908464d2000-11-01 03:11:12 +000075 TRACE("[%04x] VMM\n", (UINT16)service);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000076
77 switch(service)
78 {
79 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +000080 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000081 RESET_CFLAG(context);
82 break;
83
Ulrich Weigandff1c5691998-10-14 18:01:08 +000084 case 0x026d: /* Get_Debug_Flag '/m' */
85 case 0x026e: /* Get_Debug_Flag '/n' */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +000086 SET_AL( context, 0 );
Ulrich Weigandff1c5691998-10-14 18:01:08 +000087 RESET_CFLAG(context);
88 break;
89
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000090 default:
91 VXD_BARF( context, "VMM" );
92 }
93}
94
95/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +000096 * VXD_PageFile (WPROCS.433)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000097 */
Alexandre Julliard617955d1999-06-26 18:40:24 +000098void WINAPI VXD_PageFile( CONTEXT86 *context )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +000099{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000100 unsigned service = AX_reg(context);
101
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000102 /* taken from Ralf Brown's Interrupt List */
103
Alexandre Julliard61fece01999-06-26 19:09:08 +0000104 TRACE("[%04x] PageFile\n", (UINT16)service );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000105
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000106 switch(service)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000107 {
108 case 0x00: /* get version, is this windows version? */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000109 TRACE("returning version\n");
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000110 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardca22b331996-07-12 19:02:39 +0000111 RESET_CFLAG(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000112 break;
113
114 case 0x01: /* get swap file info */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000115 TRACE("VxD PageFile: returning swap file info\n");
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000116 SET_AX( context, 0x00 ); /* paging disabled */
Vincent Béron9a624912002-05-31 23:06:46 +0000117 context->Ecx = 0; /* maximum size of paging file */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000118 /* FIXME: do I touch DS:SI or DS:DI? */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000119 RESET_CFLAG(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000120 break;
121
122 case 0x02: /* delete permanent swap on exit */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000123 TRACE("VxD PageFile: supposed to delete swap\n");
Alexandre Julliardca22b331996-07-12 19:02:39 +0000124 RESET_CFLAG(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000125 break;
126
127 case 0x03: /* current temporary swap file size */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000128 TRACE("VxD PageFile: what is current temp. swap size\n");
Alexandre Julliardca22b331996-07-12 19:02:39 +0000129 RESET_CFLAG(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000130 break;
131
132 case 0x04: /* read or write?? INTERRUP.D */
133 case 0x05: /* cancel?? INTERRUP.D */
134 case 0x06: /* test I/O valid INTERRUP.D */
135 default:
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000136 VXD_BARF( context, "pagefile" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000137 break;
138 }
139}
140
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000141/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000142 * VXD_Reboot (WPROCS.409)
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000143 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000144void WINAPI VXD_Reboot ( CONTEXT86 *context )
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000145{
146 unsigned service = AX_reg(context);
147
Alexandre Julliard908464d2000-11-01 03:11:12 +0000148 TRACE("[%04x] Reboot\n", (UINT16)service);
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000149
150 switch(service)
151 {
152 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000153 SET_AX( context, VXD_WinVersion() );
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000154 RESET_CFLAG(context);
155 break;
156
157 default:
158 VXD_BARF( context, "REBOOT" );
159 }
160}
161
162/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000163 * VXD_VDD (WPROCS.410)
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000164 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000165void WINAPI VXD_VDD ( CONTEXT86 *context )
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000166{
167 unsigned service = AX_reg(context);
168
Alexandre Julliard908464d2000-11-01 03:11:12 +0000169 TRACE("[%04x] VDD\n", (UINT16)service);
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000170
171 switch(service)
172 {
173 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000174 SET_AX( context, VXD_WinVersion() );
Ulrich Weigand0b597bc1998-10-11 19:01:33 +0000175 RESET_CFLAG(context);
176 break;
177
178 default:
179 VXD_BARF( context, "VDD" );
180 }
181}
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000182
183/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000184 * VXD_VMD (WPROCS.412)
Ulrich Weigandab635b21998-11-14 18:33:34 +0000185 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000186void WINAPI VXD_VMD ( CONTEXT86 *context )
Ulrich Weigandab635b21998-11-14 18:33:34 +0000187{
188 unsigned service = AX_reg(context);
189
Alexandre Julliard908464d2000-11-01 03:11:12 +0000190 TRACE("[%04x] VMD\n", (UINT16)service);
Ulrich Weigandab635b21998-11-14 18:33:34 +0000191
192 switch(service)
193 {
194 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000195 SET_AX( context, VXD_WinVersion() );
Ulrich Weigandab635b21998-11-14 18:33:34 +0000196 RESET_CFLAG(context);
197 break;
198
199 default:
200 VXD_BARF( context, "VMD" );
201 }
202}
203
204/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000205 * VXD_VXDLoader (WPROCS.439)
James Abbatiello5f150ba2000-08-28 19:29:26 +0000206 */
207void WINAPI VXD_VXDLoader( CONTEXT86 *context )
208{
209 unsigned service = AX_reg(context);
210
211 TRACE("[%04x] VXDLoader\n", (UINT16)service);
212
213 switch (service)
214 {
215 case 0x0000: /* get version */
216 TRACE("returning version\n");
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000217 SET_AX( context, 0x0000 );
218 SET_DX( context, VXD_WinVersion() );
James Abbatiello5f150ba2000-08-28 19:29:26 +0000219 RESET_CFLAG(context);
220 break;
221
222 case 0x0001: /* load device */
223 FIXME("load device %04lx:%04x (%s)\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000224 context->SegDs, DX_reg(context),
Alexandre Julliard982a2232000-12-13 20:20:09 +0000225 debugstr_a(MapSL(MAKESEGPTR(context->SegDs, DX_reg(context)))));
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000226 SET_AX( context, 0x0000 );
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000227 context->SegEs = 0x0000;
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000228 SET_DI( context, 0x0000 );
James Abbatiello5f150ba2000-08-28 19:29:26 +0000229 RESET_CFLAG(context);
230 break;
231
232 case 0x0002: /* unload device */
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000233 FIXME("unload device (%08lx)\n", context->Ebx);
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000234 SET_AX( context, 0x0000 );
James Abbatiello5f150ba2000-08-28 19:29:26 +0000235 RESET_CFLAG(context);
236 break;
237
238 default:
239 VXD_BARF( context, "VXDLDR" );
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000240 SET_AX( context, 0x000B ); /* invalid function number */
James Abbatiello5f150ba2000-08-28 19:29:26 +0000241 SET_CFLAG(context);
242 break;
Vincent Béron9a624912002-05-31 23:06:46 +0000243 }
James Abbatiello5f150ba2000-08-28 19:29:26 +0000244}
245
246/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000247 * VXD_Shell (WPROCS.423)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000248 */
Alexandre Julliard617955d1999-06-26 18:40:24 +0000249void WINAPI VXD_Shell( CONTEXT86 *context )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000250{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000251 unsigned service = DX_reg(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000252
Alexandre Julliard61fece01999-06-26 19:09:08 +0000253 TRACE("[%04x] Shell\n", (UINT16)service);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000254
255 switch (service) /* Ralf Brown says EDX, but I use DX instead */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000256 {
257 case 0x0000:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000258 TRACE("returning version\n");
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000259 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000260 context->Ebx = 1; /* system VM Handle */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000261 break;
262
263 case 0x0001:
264 case 0x0002:
265 case 0x0003:
Juergen Schmiedf08b8191999-05-22 10:33:50 +0000266 /* SHELL_SYSMODAL_Message
267 ebx virtual maschine handle
268 eax message box flags
269 ecx address of message
270 edi address of caption
271 return response in eax
272 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000273 case 0x0004:
Juergen Schmiedf08b8191999-05-22 10:33:50 +0000274 /* SHELL_Message
275 ebx virtual maschine handle
276 eax message box flags
277 ecx address of message
278 edi address of caption
279 esi address callback
280 edx reference data for callback
281 return response in eax
282 */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000283 case 0x0005:
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000284 VXD_BARF( context, "shell" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000285 break;
286
287 case 0x0006: /* SHELL_Get_VM_State */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000288 TRACE("VxD Shell: returning VM state\n");
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000289 /* Actually we don't, not yet. We have to return a structure
290 * and I am not to sure how to set it up and return it yet,
291 * so for now let's do nothing. I can (hopefully) get this
292 * by the next release
293 */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000294 /* RESET_CFLAG(context); */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000295 break;
296
297 case 0x0007:
298 case 0x0008:
299 case 0x0009:
300 case 0x000A:
301 case 0x000B:
302 case 0x000C:
303 case 0x000D:
304 case 0x000E:
305 case 0x000F:
306 case 0x0010:
307 case 0x0011:
308 case 0x0012:
309 case 0x0013:
310 case 0x0014:
311 case 0x0015:
312 case 0x0016:
Ulrich Weigandab635b21998-11-14 18:33:34 +0000313 VXD_BARF( context, "SHELL" );
314 break;
315
316 /* the new Win95 shell API */
317 case 0x0100: /* get version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000318 SET_AX( context, VXD_WinVersion() );
Ulrich Weigandab635b21998-11-14 18:33:34 +0000319 break;
320
321 case 0x0104: /* retrieve Hook_Properties list */
322 case 0x0105: /* call Hook_Properties callbacks */
323 VXD_BARF( context, "SHELL" );
324 break;
325
326 case 0x0106: /* install timeout callback */
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000327 TRACE("VxD Shell: ignoring shell callback (%ld sec.)\n", context->Ebx);
Ulrich Weigandab635b21998-11-14 18:33:34 +0000328 SET_CFLAG(context);
329 break;
330
331 case 0x0107: /* get version of any VxD */
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000332 default:
Ulrich Weigandab635b21998-11-14 18:33:34 +0000333 VXD_BARF( context, "SHELL" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000334 break;
335 }
336}
337
338
339/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000340 * VXD_Comm (WPROCS.414)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000341 */
Alexandre Julliard617955d1999-06-26 18:40:24 +0000342void WINAPI VXD_Comm( CONTEXT86 *context )
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000343{
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000344 unsigned service = AX_reg(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000345
Alexandre Julliard61fece01999-06-26 19:09:08 +0000346 TRACE("[%04x] Comm\n", (UINT16)service);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000347
348 switch (service)
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000349 {
350 case 0x0000: /* get version */
Alexandre Julliard61fece01999-06-26 19:09:08 +0000351 TRACE("returning version\n");
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000352 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardca22b331996-07-12 19:02:39 +0000353 RESET_CFLAG(context);
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000354 break;
355
356 case 0x0001: /* set port global */
357 case 0x0002: /* get focus */
358 case 0x0003: /* virtualise port */
359 default:
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000360 VXD_BARF( context, "comm" );
Alexandre Julliardaf0bae51995-10-03 17:06:08 +0000361 }
362}
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000363
364/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000365 * VXD_Timer (WPROCS.405)
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000366 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000367void WINAPI VXD_Timer( CONTEXT86 *context )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000368{
369 unsigned service = AX_reg(context);
370
Alexandre Julliard61fece01999-06-26 19:09:08 +0000371 TRACE("[%04x] Virtual Timer\n", (UINT16)service);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000372
373 switch(service)
374 {
375 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000376 SET_AX( context, VXD_WinVersion() );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000377 RESET_CFLAG(context);
378 break;
379
380 case 0x0100: /* clock tick time, in 840nsecs */
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000381 context->Eax = GetTickCount();
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000382
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000383 context->Edx = context->Eax >> 22;
384 context->Eax <<= 10; /* not very precise */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000385 break;
386
387 case 0x0101: /* current Windows time, msecs */
388 case 0x0102: /* current VM time, msecs */
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000389 context->Eax = GetTickCount();
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000390 break;
391
392 default:
393 VXD_BARF( context, "VTD" );
394 }
395}
396
Alexandre Julliarda098c822003-05-15 23:25:49 +0000397
398/***********************************************************************
399 * timer_thread
400 */
401static DWORD CALLBACK timer_thread( void *arg )
402{
403 DWORD *system_time = arg;
404
405 for (;;)
406 {
407 *system_time = GetTickCount();
408 Sleep( 55 );
409 }
410}
411
412
Alexandre Julliard642d3131998-07-12 19:29:36 +0000413/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000414 * VXD_TimerAPI (WPROCS.1490)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000415 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000416void WINAPI VXD_TimerAPI ( CONTEXT86 *context )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000417{
Alexandre Julliarda098c822003-05-15 23:25:49 +0000418 static WORD System_Time_Selector;
419
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000420 unsigned service = AX_reg(context);
421
Alexandre Julliard908464d2000-11-01 03:11:12 +0000422 TRACE("[%04x] TimerAPI\n", (UINT16)service);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000423
424 switch(service)
425 {
426 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000427 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000428 RESET_CFLAG(context);
429 break;
430
431 case 0x0009: /* get system time selector */
Ulrich Weigand1cd07941998-12-10 11:01:09 +0000432 if ( !System_Time_Selector )
433 {
Alexandre Julliarda098c822003-05-15 23:25:49 +0000434 HANDLE16 handle = GlobalAlloc16( GMEM_FIXED, sizeof(DWORD) );
435 System_Time_Selector = handle | 7;
436 CloseHandle( CreateThread( NULL, 0, timer_thread, GlobalLock16(handle), 0, NULL ) );
Ulrich Weigand1cd07941998-12-10 11:01:09 +0000437 }
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000438 SET_AX( context, System_Time_Selector );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000439 RESET_CFLAG(context);
440 break;
441
442 default:
443 VXD_BARF( context, "VTDAPI" );
444 }
445}
446
447/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000448 * VXD_ConfigMG (WPROCS.451)
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000449 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000450void WINAPI VXD_ConfigMG ( CONTEXT86 *context )
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000451{
452 unsigned service = AX_reg(context);
453
Alexandre Julliard908464d2000-11-01 03:11:12 +0000454 TRACE("[%04x] ConfigMG\n", (UINT16)service);
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000455
456 switch(service)
457 {
458 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000459 SET_AX( context, VXD_WinVersion() );
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000460 RESET_CFLAG(context);
461 break;
462
463 default:
464 VXD_BARF( context, "CONFIGMG" );
465 }
466}
467
468/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000469 * VXD_Enable (WPROCS.455)
Ulrich Weigandab635b21998-11-14 18:33:34 +0000470 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000471void WINAPI VXD_Enable ( CONTEXT86 *context )
Ulrich Weigandab635b21998-11-14 18:33:34 +0000472{
473 unsigned service = AX_reg(context);
474
Alexandre Julliard908464d2000-11-01 03:11:12 +0000475 TRACE("[%04x] Enable\n", (UINT16)service);
Ulrich Weigandab635b21998-11-14 18:33:34 +0000476
477 switch(service)
478 {
479 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000480 SET_AX( context, VXD_WinVersion() );
Ulrich Weigandab635b21998-11-14 18:33:34 +0000481 RESET_CFLAG(context);
482 break;
483
484 default:
485 VXD_BARF( context, "ENABLE" );
486 }
487}
488
489/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000490 * VXD_APM (WPROCS.438)
Ulrich Weigandab635b21998-11-14 18:33:34 +0000491 */
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000492void WINAPI VXD_APM ( CONTEXT86 *context )
Ulrich Weigandab635b21998-11-14 18:33:34 +0000493{
494 unsigned service = AX_reg(context);
495
Alexandre Julliard908464d2000-11-01 03:11:12 +0000496 TRACE("[%04x] APM\n", (UINT16)service);
Ulrich Weigandab635b21998-11-14 18:33:34 +0000497
498 switch(service)
499 {
500 case 0x0000: /* version */
Alexandre Julliard3fa613c2002-08-31 18:47:00 +0000501 SET_AX( context, VXD_WinVersion() );
Ulrich Weigandab635b21998-11-14 18:33:34 +0000502 RESET_CFLAG(context);
503 break;
504
505 default:
506 VXD_BARF( context, "APM" );
507 }
508}
509
510/***********************************************************************
Patrik Stridvall3ca98232001-06-20 23:03:14 +0000511 * VXD_Win32s (WPROCS.445)
Alexandre Julliard642d3131998-07-12 19:29:36 +0000512 *
513 * This is an implementation of the services of the Win32s VxD.
514 * Since official documentation of these does not seem to be available,
Vincent Béron9a624912002-05-31 23:06:46 +0000515 * certain arguments of some of the services remain unclear.
Alexandre Julliard642d3131998-07-12 19:29:36 +0000516 *
Vincent Béron9a624912002-05-31 23:06:46 +0000517 * FIXME: The following services are currently unimplemented:
Alexandre Julliard642d3131998-07-12 19:29:36 +0000518 * Exception handling (0x01, 0x1C)
519 * Debugger support (0x0C, 0x14, 0x17)
520 * Low-level memory access (0x02, 0x03, 0x0A, 0x0B)
521 * Memory Statistics (0x1B)
Vincent Béron9a624912002-05-31 23:06:46 +0000522 *
Alexandre Julliard642d3131998-07-12 19:29:36 +0000523 *
524 * We have a specific problem running Win32s on Linux (and probably also
525 * the other x86 unixes), since Win32s tries to allocate its main 'flat
526 * code/data segment' selectors with a base of 0xffff0000 (and limit 4GB).
Vincent Béron9a624912002-05-31 23:06:46 +0000527 * The rationale for this seems to be that they want one the one hand to
528 * be able to leave the Win 3.1 memory (starting with the main DOS memory)
Alexandre Julliard642d3131998-07-12 19:29:36 +0000529 * at linear address 0, but want at other hand to have offset 0 of the
530 * flat data/code segment point to an unmapped page (to catch NULL pointer
531 * accesses). Hence they allocate the flat segments with a base of 0xffff0000
532 * so that the Win 3.1 memory area at linear address zero shows up in the
533 * flat segments at offset 0x10000 (since linear addresses wrap around at
534 * 4GB). To compensate for that discrepancy between flat segment offsets
535 * and plain linear addresses, all flat pointers passed between the 32-bit
536 * and the 16-bit parts of Win32s are shifted by 0x10000 in the appropriate
537 * direction by the glue code (mainly) in W32SKRNL and WIN32S16.
538 *
539 * The problem for us is now that Linux does not allow a LDT selector with
540 * base 0xffff0000 to be created, since it would 'see' a part of the kernel
541 * address space. To address this problem we introduce *another* offset:
542 * We add 0x10000 to every linear address we get as an argument from Win32s.
543 * This means especially that the flat code/data selectors get actually
544 * allocated with base 0x0, so that flat offsets and (real) linear addresses
545 * do again agree! In fact, every call e.g. of a Win32s VxD service now
546 * has all pointer arguments (which are offsets in the flat data segement)
547 * first reduced by 0x10000 by the W32SKRNL glue code, and then again
548 * increased by 0x10000 by *our* code.
549 *
550 * Note that to keep everything consistent, this offset has to be applied by
551 * every Wine function that operates on 'linear addresses' passed to it by
552 * Win32s. Fortunately, since Win32s does not directly call any Wine 32-bit
553 * API routines, this affects only two locations: this VxD and the DPMI
554 * handler. (NOTE: Should any Win32s application pass a linear address to
555 * any routine apart from those, e.g. some other VxD handler, that code
556 * would have to take the offset into account as well!)
557 *
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000558 * The offset is set the first time any application calls the GetVersion()
559 * service of the Win32s VxD. (Note that the offset is never reset.)
Vincent Béron9a624912002-05-31 23:06:46 +0000560 *
Alexandre Julliard642d3131998-07-12 19:29:36 +0000561 */
562
Ulrich Weigandff9c44f1999-06-27 15:28:51 +0000563void WINAPI VXD_Win32s( CONTEXT86 *context )
Alexandre Julliard642d3131998-07-12 19:29:36 +0000564{
Alexandre Julliard642d3131998-07-12 19:29:36 +0000565 switch (AX_reg(context))
566 {
567 case 0x0000: /* Get Version */
568 /*
569 * Input: None
570 *
571 * Output: EAX: LoWord: Win32s Version (1.30)
572 * HiWord: VxD Version (200)
573 *
574 * EBX: Build (172)
575 *
576 * ECX: ??? (1)
577 *
578 * EDX: Debugging Flags
579 *
Vincent Béron9a624912002-05-31 23:06:46 +0000580 * EDI: Error Flag
Alexandre Julliard642d3131998-07-12 19:29:36 +0000581 * 0 if OK,
582 * 1 if VMCPD VxD not found
583 */
584
Alexandre Julliard61fece01999-06-26 19:09:08 +0000585 TRACE("GetVersion()\n");
Vincent Béron9a624912002-05-31 23:06:46 +0000586
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000587 context->Eax = VXD_WinVersion() | (200 << 16);
588 context->Ebx = 0;
589 context->Ecx = 0;
590 context->Edx = 0;
591 context->Edi = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000592
Vincent Béron9a624912002-05-31 23:06:46 +0000593 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +0000594 * If this is the first time we are called for this process,
595 * hack the memory image of WIN32S16 so that it doesn't try
596 * to access the GDT directly ...
597 *
Vincent Béron9a624912002-05-31 23:06:46 +0000598 * The first code segment of WIN32S16 (version 1.30) contains
Alexandre Julliard642d3131998-07-12 19:29:36 +0000599 * an unexported function somewhere between the exported functions
600 * SetFS and StackLinearToSegmented that tries to find a selector
601 * in the LDT that maps to the memory image of the LDT itself.
602 * If it succeeds, it stores this selector into a global variable
603 * which will be used to speed up execution by using this selector
604 * to modify the LDT directly instead of using the DPMI calls.
605 *
606 * To perform this search of the LDT, this function uses the
607 * sgdt and sldt instructions to find the linear address of
608 * the (GDT and then) LDT. While those instructions themselves
609 * execute without problem, the linear address that sgdt returns
610 * points (at least under Linux) to the kernel address space, so
611 * that any subsequent access leads to a segfault.
612 *
613 * Fortunately, WIN32S16 still contains as a fallback option the
614 * mechanism of using DPMI calls to modify LDT selectors instead
615 * of direct writes to the LDT. Thus we can circumvent the problem
616 * by simply replacing the first byte of the offending function
617 * with an 'retf' instruction. This means that the global variable
618 * supposed to contain the LDT alias selector will remain zero,
619 * and hence WIN32S16 will fall back to using DPMI calls.
620 *
621 * The heuristic we employ to _find_ that function is as follows:
622 * We search between the addresses of the exported symbols SetFS
623 * and StackLinearToSegmented for the byte sequence '0F 01 04'
624 * (this is the opcode of 'sgdt [si]'). We then search backwards
Andreas Mohr8bc7f162002-02-27 01:34:08 +0000625 * from this address for the last occurrence of 'CB' (retf) that marks
Alexandre Julliard642d3131998-07-12 19:29:36 +0000626 * the end of the preceeding function. The following byte (which
627 * should now be the first byte of the function we are looking for)
628 * will be replaced by 'CB' (retf).
629 *
630 * This heuristic works for the retail as well as the debug version
631 * of Win32s version 1.30. For versions earlier than that this
632 * hack should not be necessary at all, since the whole mechanism
633 * ('PERF130') was introduced only in 1.30 to improve the overall
634 * performance of Win32s.
635 */
636
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000637 if (!W32S_offset)
Alexandre Julliard642d3131998-07-12 19:29:36 +0000638 {
639 HMODULE16 hModule = GetModuleHandle16("win32s16");
Alexandre Julliard5ce902b2000-11-27 21:59:08 +0000640 SEGPTR func1 = (SEGPTR)GetProcAddress16(hModule, "SetFS");
641 SEGPTR func2 = (SEGPTR)GetProcAddress16(hModule, "StackLinearToSegmented");
Alexandre Julliard642d3131998-07-12 19:29:36 +0000642
Vincent Béron9a624912002-05-31 23:06:46 +0000643 if ( hModule && func1 && func2
Alexandre Julliard642d3131998-07-12 19:29:36 +0000644 && SELECTOROF(func1) == SELECTOROF(func2))
645 {
Alexandre Julliard982a2232000-12-13 20:20:09 +0000646 BYTE *start = MapSL(func1);
647 BYTE *end = MapSL(func2);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000648 BYTE *p, *retv = NULL;
649 int found = 0;
650
651 for (p = start; p < end; p++)
652 if (*p == 0xCB) found = 0, retv = p;
653 else if (*p == 0x0F) found = 1;
654 else if (*p == 0x01 && found == 1) found = 2;
655 else if (*p == 0x04 && found == 2) { found = 3; break; }
656 else found = 0;
657
658 if (found == 3 && retv)
659 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000660 TRACE("PERF130 hack: "
Alexandre Julliard642d3131998-07-12 19:29:36 +0000661 "Replacing byte %02X at offset %04X:%04X\n",
Vincent Béron9a624912002-05-31 23:06:46 +0000662 *(retv+1), SELECTOROF(func1),
Alexandre Julliard642d3131998-07-12 19:29:36 +0000663 OFFSETOF(func1) + retv+1-start);
664
665 *(retv+1) = (BYTE)0xCB;
666 }
667 }
668 }
669
Vincent Béron9a624912002-05-31 23:06:46 +0000670 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +0000671 * Mark process as Win32s, so that subsequent DPMI calls
Andreas Mohra00b49f1998-12-07 10:48:09 +0000672 * will perform the W32S_APP2WINE/W32S_WINE2APP address shift.
Alexandre Julliard642d3131998-07-12 19:29:36 +0000673 */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000674 W32S_offset = 0x10000;
675 break;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000676
677
678 case 0x0001: /* Install Exception Handling */
679 /*
680 * Input: EBX: Flat address of W32SKRNL Exception Data
681 *
682 * ECX: LoWord: Flat Code Selector
683 * HiWord: Flat Data Selector
684 *
Vincent Béron9a624912002-05-31 23:06:46 +0000685 * EDX: Flat address of W32SKRNL Exception Handler
Alexandre Julliard642d3131998-07-12 19:29:36 +0000686 * (this is equal to W32S_BackTo32 + 0x40)
687 *
688 * ESI: SEGPTR KERNEL.HASGPHANDLER
689 *
690 * EDI: SEGPTR phCurrentTask (KERNEL.THHOOK + 0x10)
691 *
692 * Output: EAX: 0 if OK
693 */
694
Vincent Béron9a624912002-05-31 23:06:46 +0000695 TRACE("[0001] EBX=%lx ECX=%lx EDX=%lx ESI=%lx EDI=%lx\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000696 context->Ebx, context->Ecx, context->Edx,
697 context->Esi, context->Edi);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000698
699 /* FIXME */
700
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000701 context->Eax = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000702 break;
703
704
705 case 0x0002: /* Set Page Access Flags */
706 /*
707 * Input: EBX: New access flags
708 * Bit 2: User Page if set, Supervisor Page if clear
709 * Bit 1: Read-Write if set, Read-Only if clear
710 *
711 * ECX: Size of memory area to change
712 *
713 * EDX: Flat start address of memory area
714 *
715 * Output: EAX: Size of area changed
716 */
717
Vincent Béron9a624912002-05-31 23:06:46 +0000718 TRACE("[0002] EBX=%lx ECX=%lx EDX=%lx\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000719 context->Ebx, context->Ecx, context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000720
721 /* FIXME */
722
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000723 context->Eax = context->Ecx;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000724 break;
725
726
727 case 0x0003: /* Get Page Access Flags */
728 /*
729 * Input: EDX: Flat address of page to query
730 *
731 * Output: EAX: Page access flags
732 * Bit 2: User Page if set, Supervisor Page if clear
733 * Bit 1: Read-Write if set, Read-Only if clear
734 */
735
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000736 TRACE("[0003] EDX=%lx\n", context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000737
738 /* FIXME */
739
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000740 context->Eax = 6;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000741 break;
742
743
744 case 0x0004: /* Map Module */
745 /*
746 * Input: ECX: IMTE (offset in Module Table) of new module
747 *
748 * EDX: Flat address of Win32s Module Table
749 *
750 * Output: EAX: 0 if OK
751 */
752
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000753 if (!context->Edx || CX_reg(context) == 0xFFFF)
Alexandre Julliard642d3131998-07-12 19:29:36 +0000754 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000755 TRACE("MapModule: Initialization call\n");
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000756 context->Eax = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000757 }
758 else
759 {
760 /*
761 * Structure of a Win32s Module Table Entry:
762 */
763 struct Win32sModule
764 {
765 DWORD flags;
766 DWORD flatBaseAddr;
767 LPCSTR moduleName;
768 LPCSTR pathName;
769 LPCSTR unknown;
770 LPBYTE baseAddr;
771 DWORD hModule;
772 DWORD relocDelta;
773 };
774
Vincent Béron9a624912002-05-31 23:06:46 +0000775 /*
776 * Note: This function should set up a demand-paged memory image
Alexandre Julliard642d3131998-07-12 19:29:36 +0000777 * of the given module. Since mmap does not allow file offsets
778 * not aligned at 1024 bytes, we simply load the image fully
779 * into memory.
780 */
781
Vincent Béron9a624912002-05-31 23:06:46 +0000782 struct Win32sModule *moduleTable =
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000783 (struct Win32sModule *)W32S_APP2WINE(context->Edx);
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000784 struct Win32sModule *module = moduleTable + context->Ecx;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000785
Alexandre Julliarda5dea212002-08-09 19:57:38 +0000786 IMAGE_NT_HEADERS *nt_header = RtlImageNtHeader( (HMODULE)module->baseAddr );
787 IMAGE_SECTION_HEADER *pe_seg = (IMAGE_SECTION_HEADER*)((char *)&nt_header->OptionalHeader +
788 nt_header->FileHeader.SizeOfOptionalHeader);
789
Alexandre Julliard642d3131998-07-12 19:29:36 +0000790
Alexandre Julliarda3960291999-02-26 11:11:13 +0000791 HFILE image = _lopen(module->pathName, OF_READ);
Alexandre Julliard908464d2000-11-01 03:11:12 +0000792 BOOL error = (image == HFILE_ERROR);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000793 UINT i;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000794
Alexandre Julliard61fece01999-06-26 19:09:08 +0000795 TRACE("MapModule: Loading %s\n", module->pathName);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000796
Vincent Béron9a624912002-05-31 23:06:46 +0000797 for (i = 0;
798 !error && i < nt_header->FileHeader.NumberOfSections;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000799 i++, pe_seg++)
800 if(!(pe_seg->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
801 {
802 DWORD off = pe_seg->PointerToRawData;
803 DWORD len = pe_seg->SizeOfRawData;
804 LPBYTE addr = module->baseAddr + pe_seg->VirtualAddress;
805
Alexandre Julliard61fece01999-06-26 19:09:08 +0000806 TRACE("MapModule: "
Vincent Béron9a624912002-05-31 23:06:46 +0000807 "Section %d at %08lx from %08lx len %08lx\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +0000808 i, (DWORD)addr, off, len);
809
Alexandre Julliarda3960291999-02-26 11:11:13 +0000810 if ( _llseek(image, off, SEEK_SET) != off
811 || _lread(image, addr, len) != len)
Alexandre Julliard642d3131998-07-12 19:29:36 +0000812 error = TRUE;
813 }
Vincent Béron9a624912002-05-31 23:06:46 +0000814
Alexandre Julliarda3960291999-02-26 11:11:13 +0000815 _lclose(image);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000816
817 if (error)
Alexandre Julliard61fece01999-06-26 19:09:08 +0000818 ERR("MapModule: Unable to load %s\n", module->pathName);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000819
820 else if (module->relocDelta != 0)
821 {
822 IMAGE_DATA_DIRECTORY *dir = nt_header->OptionalHeader.DataDirectory
823 + IMAGE_DIRECTORY_ENTRY_BASERELOC;
824 IMAGE_BASE_RELOCATION *r = (IMAGE_BASE_RELOCATION *)
825 (dir->Size? module->baseAddr + dir->VirtualAddress : 0);
826
Alexandre Julliard61fece01999-06-26 19:09:08 +0000827 TRACE("MapModule: Reloc delta %08lx\n", module->relocDelta);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000828
829 while (r && r->VirtualAddress)
830 {
831 LPBYTE page = module->baseAddr + r->VirtualAddress;
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000832 WORD *TypeOffset = (WORD *)(r + 1);
833 int count = (r->SizeOfBlock - sizeof(*r)) / sizeof(*TypeOffset);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000834
Vincent Béron9a624912002-05-31 23:06:46 +0000835 TRACE("MapModule: %d relocations for page %08lx\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +0000836 count, (DWORD)page);
837
838 for(i = 0; i < count; i++)
839 {
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000840 int offset = TypeOffset[i] & 0xFFF;
841 int type = TypeOffset[i] >> 12;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000842 switch(type)
843 {
Vincent Béron9a624912002-05-31 23:06:46 +0000844 case IMAGE_REL_BASED_ABSOLUTE:
Alexandre Julliard642d3131998-07-12 19:29:36 +0000845 break;
846 case IMAGE_REL_BASED_HIGH:
847 *(WORD *)(page+offset) += HIWORD(module->relocDelta);
848 break;
849 case IMAGE_REL_BASED_LOW:
850 *(WORD *)(page+offset) += LOWORD(module->relocDelta);
851 break;
852 case IMAGE_REL_BASED_HIGHLOW:
853 *(DWORD*)(page+offset) += module->relocDelta;
854 break;
855 default:
Alexandre Julliard61fece01999-06-26 19:09:08 +0000856 WARN("MapModule: Unsupported fixup type\n");
Alexandre Julliard642d3131998-07-12 19:29:36 +0000857 break;
858 }
859 }
860
861 r = (IMAGE_BASE_RELOCATION *)((LPBYTE)r + r->SizeOfBlock);
862 }
863 }
864
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000865 context->Eax = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000866 RESET_CFLAG(context);
867 }
868 break;
869
870
871 case 0x0005: /* UnMap Module */
872 /*
Vincent Béron9a624912002-05-31 23:06:46 +0000873 * Input: EDX: Flat address of module image
Alexandre Julliard642d3131998-07-12 19:29:36 +0000874 *
875 * Output: EAX: 1 if OK
876 */
Vincent Béron9a624912002-05-31 23:06:46 +0000877
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000878 TRACE("UnMapModule: %lx\n", (DWORD)W32S_APP2WINE(context->Edx));
Alexandre Julliard642d3131998-07-12 19:29:36 +0000879
880 /* As we didn't map anything, there's nothing to unmap ... */
881
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000882 context->Eax = 1;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000883 break;
884
885
886 case 0x0006: /* VirtualAlloc */
Vincent Béron9a624912002-05-31 23:06:46 +0000887 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +0000888 * Input: ECX: Current Process
889 *
890 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +0000891 *
Alexandre Julliard642d3131998-07-12 19:29:36 +0000892 * DWORD *retv [out] Flat base address of allocated region
893 * LPVOID base [in] Flat address of region to reserve/commit
894 * DWORD size [in] Size of region
895 * DWORD type [in] Type of allocation
896 * DWORD prot [in] Type of access protection
897 *
898 * Output: EAX: NtStatus
899 */
900 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000901 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
902 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
903 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000904 DWORD size = stack[2];
905 DWORD type = stack[3];
906 DWORD prot = stack[4];
907 DWORD result;
908
Vincent Béron9a624912002-05-31 23:06:46 +0000909 TRACE("VirtualAlloc(%lx, %lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +0000910 (DWORD)retv, (DWORD)base, size, type, prot);
911
912 if (type & 0x80000000)
913 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000914 WARN("VirtualAlloc: strange type %lx\n", type);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000915 type &= 0x7fffffff;
916 }
917
918 if (!base && (type & MEM_COMMIT) && prot == PAGE_READONLY)
919 {
Alexandre Julliard61fece01999-06-26 19:09:08 +0000920 WARN("VirtualAlloc: NLS hack, allowing write access!\n");
Alexandre Julliard642d3131998-07-12 19:29:36 +0000921 prot = PAGE_READWRITE;
922 }
923
924 result = (DWORD)VirtualAlloc(base, size, type, prot);
925
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000926 if (W32S_WINE2APP(result))
927 *retv = W32S_WINE2APP(result),
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000928 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000929 else
930 *retv = 0,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000931 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +0000932 }
933 break;
934
935
936 case 0x0007: /* VirtualFree */
Vincent Béron9a624912002-05-31 23:06:46 +0000937 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +0000938 * Input: ECX: Current Process
939 *
940 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +0000941 *
Alexandre Julliard642d3131998-07-12 19:29:36 +0000942 * DWORD *retv [out] TRUE if success, FALSE if failure
943 * LPVOID base [in] Flat address of region
944 * DWORD size [in] Size of region
945 * DWORD type [in] Type of operation
946 *
947 * Output: EAX: NtStatus
948 */
949 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000950 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
951 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
952 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000953 DWORD size = stack[2];
954 DWORD type = stack[3];
955 DWORD result;
956
Vincent Béron9a624912002-05-31 23:06:46 +0000957 TRACE("VirtualFree(%lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +0000958 (DWORD)retv, (DWORD)base, size, type);
959
960 result = VirtualFree(base, size, type);
961
962 if (result)
963 *retv = TRUE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000964 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000965 else
966 *retv = FALSE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000967 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +0000968 }
969 break;
970
971
972 case 0x0008: /* VirtualProtect */
Vincent Béron9a624912002-05-31 23:06:46 +0000973 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +0000974 * Input: ECX: Current Process
975 *
976 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +0000977 *
Alexandre Julliard642d3131998-07-12 19:29:36 +0000978 * DWORD *retv [out] TRUE if success, FALSE if failure
979 * LPVOID base [in] Flat address of region
980 * DWORD size [in] Size of region
981 * DWORD new_prot [in] Desired access protection
982 * DWORD *old_prot [out] Previous access protection
983 *
984 * Output: EAX: NtStatus
985 */
986 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000987 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
988 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
989 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000990 DWORD size = stack[2];
991 DWORD new_prot = stack[3];
Alexandre Julliardbecb9a32000-12-11 03:48:15 +0000992 DWORD *old_prot = (DWORD *)W32S_APP2WINE(stack[4]);
Alexandre Julliard642d3131998-07-12 19:29:36 +0000993 DWORD result;
994
Vincent Béron9a624912002-05-31 23:06:46 +0000995 TRACE("VirtualProtect(%lx, %lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +0000996 (DWORD)retv, (DWORD)base, size, new_prot, (DWORD)old_prot);
997
998 result = VirtualProtect(base, size, new_prot, old_prot);
999
1000 if (result)
1001 *retv = TRUE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001002 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001003 else
1004 *retv = FALSE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001005 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001006 }
1007 break;
1008
1009
1010 case 0x0009: /* VirtualQuery */
Vincent Béron9a624912002-05-31 23:06:46 +00001011 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001012 * Input: ECX: Current Process
1013 *
1014 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001015 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001016 * DWORD *retv [out] Nr. bytes returned
1017 * LPVOID base [in] Flat address of region
1018 * LPMEMORY_BASIC_INFORMATION info [out] Info buffer
1019 * DWORD len [in] Size of buffer
1020 *
1021 * Output: EAX: NtStatus
1022 */
1023 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001024 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
1025 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
1026 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Patrik Stridvallba9dc782002-11-04 22:43:24 +00001027 PMEMORY_BASIC_INFORMATION info =
1028 (PMEMORY_BASIC_INFORMATION)W32S_APP2WINE(stack[2]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001029 DWORD len = stack[3];
1030 DWORD result;
1031
Vincent Béron9a624912002-05-31 23:06:46 +00001032 TRACE("VirtualQuery(%lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001033 (DWORD)retv, (DWORD)base, (DWORD)info, len);
1034
1035 result = VirtualQuery(base, info, len);
1036
1037 *retv = result;
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001038 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001039 }
1040 break;
1041
1042
1043 case 0x000A: /* SetVirtMemProcess */
1044 /*
1045 * Input: ECX: Process Handle
1046 *
1047 * EDX: Flat address of region
1048 *
1049 * Output: EAX: NtStatus
1050 */
1051
Alexandre Julliard61fece01999-06-26 19:09:08 +00001052 TRACE("[000a] ECX=%lx EDX=%lx\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001053 context->Ecx, context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001054
1055 /* FIXME */
1056
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001057 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001058 break;
1059
1060
1061 case 0x000B: /* ??? some kind of cleanup */
1062 /*
1063 * Input: ECX: Process Handle
1064 *
1065 * Output: EAX: NtStatus
1066 */
1067
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001068 TRACE("[000b] ECX=%lx\n", context->Ecx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001069
1070 /* FIXME */
1071
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001072 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001073 break;
1074
1075
1076 case 0x000C: /* Set Debug Flags */
1077 /*
1078 * Input: EDX: Debug Flags
1079 *
1080 * Output: EDX: Previous Debug Flags
1081 */
1082
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001083 FIXME("[000c] EDX=%lx\n", context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001084
1085 /* FIXME */
1086
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001087 context->Edx = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001088 break;
1089
1090
1091 case 0x000D: /* NtCreateSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001092 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001093 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001094 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001095 * HANDLE32 *retv [out] Handle of Section created
1096 * DWORD flags1 [in] (?? unknown ??)
1097 * DWORD atom [in] Name of Section to create
1098 * LARGE_INTEGER *size [in] Size of Section
1099 * DWORD protect [in] Access protection
1100 * DWORD flags2 [in] (?? unknown ??)
1101 * HFILE32 hFile [in] Handle of file to map
1102 * DWORD psp [in] (Win32s: PSP that hFile belongs to)
1103 *
1104 * Output: EAX: NtStatus
1105 */
1106 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001107 DWORD *stack = (DWORD *) W32S_APP2WINE(context->Edx);
1108 HANDLE *retv = (HANDLE *)W32S_APP2WINE(stack[0]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001109 DWORD flags1 = stack[1];
1110 DWORD atom = stack[2];
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001111 LARGE_INTEGER *size = (LARGE_INTEGER *)W32S_APP2WINE(stack[3]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001112 DWORD protect = stack[4];
1113 DWORD flags2 = stack[5];
Alexandre Julliard5ce902b2000-11-27 21:59:08 +00001114 HANDLE hFile = DosFileHandleToWin32Handle(stack[6]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001115 DWORD psp = stack[7];
1116
Alexandre Julliarda3960291999-02-26 11:11:13 +00001117 HANDLE result = INVALID_HANDLE_VALUE;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001118 char name[128];
1119
Alexandre Julliard61fece01999-06-26 19:09:08 +00001120 TRACE("NtCreateSection(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001121 (DWORD)retv, flags1, atom, (DWORD)size, protect, flags2,
1122 (DWORD)hFile, psp);
1123
Alexandre Julliarda3960291999-02-26 11:11:13 +00001124 if (!atom || GlobalGetAtomNameA(atom, name, sizeof(name)))
Alexandre Julliard642d3131998-07-12 19:29:36 +00001125 {
Alexandre Julliard61fece01999-06-26 19:09:08 +00001126 TRACE("NtCreateSection: name=%s\n", atom? name : NULL);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001127
Vincent Béron9a624912002-05-31 23:06:46 +00001128 result = CreateFileMappingA(hFile, NULL, protect,
Ge van Geldorp399901e2004-01-23 01:51:33 +00001129 size? size->u.HighPart : 0,
1130 size? size->u.LowPart : 0,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001131 atom? name : NULL);
1132 }
1133
Alexandre Julliarda3960291999-02-26 11:11:13 +00001134 if (result == INVALID_HANDLE_VALUE)
Alexandre Julliard61fece01999-06-26 19:09:08 +00001135 WARN("NtCreateSection: failed!\n");
Alexandre Julliard642d3131998-07-12 19:29:36 +00001136 else
Alexandre Julliard61fece01999-06-26 19:09:08 +00001137 TRACE("NtCreateSection: returned %lx\n", (DWORD)result);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001138
Alexandre Julliarda3960291999-02-26 11:11:13 +00001139 if (result != INVALID_HANDLE_VALUE)
Alexandre Julliard642d3131998-07-12 19:29:36 +00001140 *retv = result,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001141 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001142 else
1143 *retv = result,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001144 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001145 }
1146 break;
1147
1148
1149 case 0x000E: /* NtOpenSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001150 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001151 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001152 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001153 * HANDLE32 *retv [out] Handle of Section opened
1154 * DWORD protect [in] Access protection
1155 * DWORD atom [in] Name of Section to create
1156 *
1157 * Output: EAX: NtStatus
1158 */
1159 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001160 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
1161 HANDLE *retv = (HANDLE *)W32S_APP2WINE(stack[0]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001162 DWORD protect = stack[1];
1163 DWORD atom = stack[2];
1164
Alexandre Julliarda3960291999-02-26 11:11:13 +00001165 HANDLE result = INVALID_HANDLE_VALUE;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001166 char name[128];
1167
Vincent Béron9a624912002-05-31 23:06:46 +00001168 TRACE("NtOpenSection(%lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001169 (DWORD)retv, protect, atom);
1170
Alexandre Julliarda3960291999-02-26 11:11:13 +00001171 if (atom && GlobalGetAtomNameA(atom, name, sizeof(name)))
Alexandre Julliard642d3131998-07-12 19:29:36 +00001172 {
Alexandre Julliard61fece01999-06-26 19:09:08 +00001173 TRACE("NtOpenSection: name=%s\n", name);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001174
Alexandre Julliarda3960291999-02-26 11:11:13 +00001175 result = OpenFileMappingA(protect, FALSE, name);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001176 }
1177
Alexandre Julliarda3960291999-02-26 11:11:13 +00001178 if (result == INVALID_HANDLE_VALUE)
Alexandre Julliard61fece01999-06-26 19:09:08 +00001179 WARN("NtOpenSection: failed!\n");
Alexandre Julliard642d3131998-07-12 19:29:36 +00001180 else
Alexandre Julliard61fece01999-06-26 19:09:08 +00001181 TRACE("NtOpenSection: returned %lx\n", (DWORD)result);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001182
Alexandre Julliarda3960291999-02-26 11:11:13 +00001183 if (result != INVALID_HANDLE_VALUE)
Alexandre Julliard642d3131998-07-12 19:29:36 +00001184 *retv = result,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001185 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001186 else
1187 *retv = result,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001188 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001189 }
1190 break;
1191
1192
1193 case 0x000F: /* NtCloseSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001194 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001195 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001196 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001197 * HANDLE32 handle [in] Handle of Section to close
1198 * DWORD *id [out] Unique ID (?? unclear ??)
1199 *
1200 * Output: EAX: NtStatus
1201 */
1202 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001203 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
Alexandre Julliard73755972002-07-31 19:26:03 +00001204 HANDLE handle = (HANDLE)stack[0];
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001205 DWORD *id = (DWORD *)W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001206
Alexandre Julliard61fece01999-06-26 19:09:08 +00001207 TRACE("NtCloseSection(%lx, %lx)\n", (DWORD)handle, (DWORD)id);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001208
1209 CloseHandle(handle);
1210 if (id) *id = 0; /* FIXME */
1211
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001212 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001213 }
1214 break;
1215
1216
1217 case 0x0010: /* NtDupSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001218 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001219 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001220 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001221 * HANDLE32 handle [in] Handle of Section to duplicate
1222 *
1223 * Output: EAX: NtStatus
1224 */
1225 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001226 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
Alexandre Julliard73755972002-07-31 19:26:03 +00001227 HANDLE handle = (HANDLE)stack[0];
Alexandre Julliarda3960291999-02-26 11:11:13 +00001228 HANDLE new_handle;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001229
Alexandre Julliard61fece01999-06-26 19:09:08 +00001230 TRACE("NtDupSection(%lx)\n", (DWORD)handle);
Vincent Béron9a624912002-05-31 23:06:46 +00001231
Alexandre Julliard62a8b431999-01-19 17:48:23 +00001232 DuplicateHandle( GetCurrentProcess(), handle,
1233 GetCurrentProcess(), &new_handle,
1234 0, FALSE, DUPLICATE_SAME_ACCESS );
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001235 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001236 }
1237 break;
1238
1239
1240 case 0x0011: /* NtMapViewOfSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001241 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001242 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001243 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001244 * HANDLE32 SectionHandle [in] Section to be mapped
1245 * DWORD ProcessHandle [in] Process to be mapped into
1246 * DWORD * BaseAddress [in/out] Address to be mapped at
1247 * DWORD ZeroBits [in] (?? unclear ??)
1248 * DWORD CommitSize [in] (?? unclear ??)
1249 * LARGE_INTEGER *SectionOffset [in] Offset within section
1250 * DWORD * ViewSize [in] Size of view
1251 * DWORD InheritDisposition [in] (?? unclear ??)
1252 * DWORD AllocationType [in] (?? unclear ??)
1253 * DWORD Protect [in] Access protection
1254 *
1255 * Output: EAX: NtStatus
1256 */
1257 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001258 DWORD * stack = (DWORD *)W32S_APP2WINE(context->Edx);
Alexandre Julliard73755972002-07-31 19:26:03 +00001259 HANDLE SectionHandle = (HANDLE)stack[0];
Alexandre Julliard642d3131998-07-12 19:29:36 +00001260 DWORD ProcessHandle = stack[1]; /* ignored */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001261 DWORD * BaseAddress = (DWORD *)W32S_APP2WINE(stack[2]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001262 DWORD ZeroBits = stack[3];
1263 DWORD CommitSize = stack[4];
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001264 LARGE_INTEGER *SectionOffset = (LARGE_INTEGER *)W32S_APP2WINE(stack[5]);
1265 DWORD * ViewSize = (DWORD *)W32S_APP2WINE(stack[6]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001266 DWORD InheritDisposition = stack[7];
1267 DWORD AllocationType = stack[8];
1268 DWORD Protect = stack[9];
1269
Andreas Mohra00b49f1998-12-07 10:48:09 +00001270 LPBYTE address = (LPBYTE)(BaseAddress?
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001271 W32S_APP2WINE(*BaseAddress) : 0);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001272 DWORD access = 0, result;
1273
1274 switch (Protect & ~(PAGE_GUARD|PAGE_NOCACHE))
1275 {
1276 case PAGE_READONLY: access = FILE_MAP_READ; break;
1277 case PAGE_READWRITE: access = FILE_MAP_WRITE; break;
1278 case PAGE_WRITECOPY: access = FILE_MAP_COPY; break;
1279
1280 case PAGE_EXECUTE_READ: access = FILE_MAP_READ; break;
1281 case PAGE_EXECUTE_READWRITE: access = FILE_MAP_WRITE; break;
1282 case PAGE_EXECUTE_WRITECOPY: access = FILE_MAP_COPY; break;
1283 }
1284
Alexandre Julliard61fece01999-06-26 19:09:08 +00001285 TRACE("NtMapViewOfSection"
Alexandre Julliard642d3131998-07-12 19:29:36 +00001286 "(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n",
Vincent Béron9a624912002-05-31 23:06:46 +00001287 (DWORD)SectionHandle, ProcessHandle, (DWORD)BaseAddress,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001288 ZeroBits, CommitSize, (DWORD)SectionOffset, (DWORD)ViewSize,
1289 InheritDisposition, AllocationType, Protect);
Alexandre Julliard61fece01999-06-26 19:09:08 +00001290 TRACE("NtMapViewOfSection: "
Vincent Béron9a624912002-05-31 23:06:46 +00001291 "base=%lx, offset=%lx, size=%lx, access=%lx\n",
Ge van Geldorp399901e2004-01-23 01:51:33 +00001292 (DWORD)address, SectionOffset? SectionOffset->u.LowPart : 0,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001293 ViewSize? *ViewSize : 0, access);
1294
Vincent Béron9a624912002-05-31 23:06:46 +00001295 result = (DWORD)MapViewOfFileEx(SectionHandle, access,
Ge van Geldorp399901e2004-01-23 01:51:33 +00001296 SectionOffset? SectionOffset->u.HighPart : 0,
1297 SectionOffset? SectionOffset->u.LowPart : 0,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001298 ViewSize? *ViewSize : 0, address);
1299
Alexandre Julliard61fece01999-06-26 19:09:08 +00001300 TRACE("NtMapViewOfSection: result=%lx\n", result);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001301
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001302 if (W32S_WINE2APP(result))
Alexandre Julliard642d3131998-07-12 19:29:36 +00001303 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001304 if (BaseAddress) *BaseAddress = W32S_WINE2APP(result);
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001305 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001306 }
1307 else
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001308 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001309 }
1310 break;
1311
1312
1313 case 0x0012: /* NtUnmapViewOfSection */
Vincent Béron9a624912002-05-31 23:06:46 +00001314 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001315 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001316 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001317 * DWORD ProcessHandle [in] Process (defining address space)
1318 * LPBYTE BaseAddress [in] Base address of view to be unmapped
1319 *
1320 * Output: EAX: NtStatus
1321 */
1322 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001323 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001324 DWORD ProcessHandle = stack[0]; /* ignored */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001325 LPBYTE BaseAddress = (LPBYTE)W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001326
Vincent Béron9a624912002-05-31 23:06:46 +00001327 TRACE("NtUnmapViewOfSection(%lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001328 ProcessHandle, (DWORD)BaseAddress);
1329
1330 UnmapViewOfFile(BaseAddress);
1331
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001332 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001333 }
1334 break;
1335
1336
1337 case 0x0013: /* NtFlushVirtualMemory */
Vincent Béron9a624912002-05-31 23:06:46 +00001338 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001339 * Input: EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001340 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001341 * DWORD ProcessHandle [in] Process (defining address space)
1342 * LPBYTE *BaseAddress [in?] Base address of range to be flushed
1343 * DWORD *ViewSize [in?] Number of bytes to be flushed
1344 * DWORD *unknown [???] (?? unknown ??)
1345 *
1346 * Output: EAX: NtStatus
1347 */
1348 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001349 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001350 DWORD ProcessHandle = stack[0]; /* ignored */
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001351 DWORD *BaseAddress = (DWORD *)W32S_APP2WINE(stack[1]);
1352 DWORD *ViewSize = (DWORD *)W32S_APP2WINE(stack[2]);
1353 DWORD *unknown = (DWORD *)W32S_APP2WINE(stack[3]);
Vincent Béron9a624912002-05-31 23:06:46 +00001354
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001355 LPBYTE address = (LPBYTE)(BaseAddress? W32S_APP2WINE(*BaseAddress) : 0);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001356 DWORD size = ViewSize? *ViewSize : 0;
1357
Vincent Béron9a624912002-05-31 23:06:46 +00001358 TRACE("NtFlushVirtualMemory(%lx, %lx, %lx, %lx)\n",
1359 ProcessHandle, (DWORD)BaseAddress, (DWORD)ViewSize,
Alexandre Julliard642d3131998-07-12 19:29:36 +00001360 (DWORD)unknown);
Vincent Béron9a624912002-05-31 23:06:46 +00001361 TRACE("NtFlushVirtualMemory: base=%lx, size=%lx\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001362 (DWORD)address, size);
1363
1364 FlushViewOfFile(address, size);
1365
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001366 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001367 }
1368 break;
1369
1370
1371 case 0x0014: /* Get/Set Debug Registers */
1372 /*
1373 * Input: ECX: 0 if Get, 1 if Set
1374 *
1375 * EDX: Get: Flat address of buffer to receive values of
1376 * debug registers DR0 .. DR7
1377 * Set: Flat address of buffer containing values of
1378 * debug registers DR0 .. DR7 to be set
1379 * Output: None
1380 */
1381
Vincent Béron9a624912002-05-31 23:06:46 +00001382 FIXME("[0014] ECX=%lx EDX=%lx\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001383 context->Ecx, context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001384
1385 /* FIXME */
1386 break;
1387
1388
1389 case 0x0015: /* Set Coprocessor Emulation Flag */
1390 /*
1391 * Input: EDX: 0 to deactivate, 1 to activate coprocessor emulation
1392 *
1393 * Output: None
1394 */
1395
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001396 TRACE("[0015] EDX=%lx\n", context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001397
1398 /* We don't care, as we always have a coprocessor anyway */
1399 break;
1400
1401
1402 case 0x0016: /* Init Win32S VxD PSP */
1403 /*
1404 * If called to query required PSP size:
1405 *
1406 * Input: EBX: 0
1407 * Output: EDX: Required size of Win32s VxD PSP
1408 *
1409 * If called to initialize allocated PSP:
1410 *
1411 * Input: EBX: LoWord: Selector of Win32s VxD PSP
1412 * HiWord: Paragraph of Win32s VxD PSP (DOSMEM)
1413 * Output: None
1414 */
Vincent Béron9a624912002-05-31 23:06:46 +00001415
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001416 if (context->Ebx == 0)
1417 context->Edx = 0x80;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001418 else
1419 {
Alexandre Julliard982a2232000-12-13 20:20:09 +00001420 PDB16 *psp = MapSL( MAKESEGPTR( BX_reg(context), 0 ));
Alexandre Julliard642d3131998-07-12 19:29:36 +00001421 psp->nbFiles = 32;
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001422 psp->fileHandlesPtr = MAKELONG(HIWORD(context->Ebx), 0x5c);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001423 memset((LPBYTE)psp + 0x5c, '\xFF', 32);
1424 }
1425 break;
1426
1427
1428 case 0x0017: /* Set Break Point */
1429 /*
1430 * Input: EBX: Offset of Break Point
1431 * CX: Selector of Break Point
1432 *
1433 * Output: None
1434 */
1435
Vincent Béron9a624912002-05-31 23:06:46 +00001436 FIXME("[0017] EBX=%lx CX=%x\n",
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001437 context->Ebx, CX_reg(context));
Alexandre Julliard642d3131998-07-12 19:29:36 +00001438
1439 /* FIXME */
1440 break;
1441
1442
1443 case 0x0018: /* VirtualLock */
Vincent Béron9a624912002-05-31 23:06:46 +00001444 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001445 * Input: ECX: Current Process
1446 *
1447 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001448 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001449 * DWORD *retv [out] TRUE if success, FALSE if failure
1450 * LPVOID base [in] Flat address of range to lock
1451 * DWORD size [in] Size of range
1452 *
1453 * Output: EAX: NtStatus
1454 */
1455 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001456 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
1457 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
1458 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001459 DWORD size = stack[2];
1460 DWORD result;
1461
Vincent Béron9a624912002-05-31 23:06:46 +00001462 TRACE("VirtualLock(%lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001463 (DWORD)retv, (DWORD)base, size);
1464
1465 result = VirtualLock(base, size);
1466
1467 if (result)
1468 *retv = TRUE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001469 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001470 else
1471 *retv = FALSE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001472 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001473 }
1474 break;
1475
1476
1477 case 0x0019: /* VirtualUnlock */
Vincent Béron9a624912002-05-31 23:06:46 +00001478 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001479 * Input: ECX: Current Process
1480 *
1481 * EDX: Flat address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001482 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001483 * DWORD *retv [out] TRUE if success, FALSE if failure
1484 * LPVOID base [in] Flat address of range to unlock
1485 * DWORD size [in] Size of range
1486 *
1487 * Output: EAX: NtStatus
1488 */
1489 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001490 DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx);
1491 DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]);
1492 LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001493 DWORD size = stack[2];
1494 DWORD result;
1495
Vincent Béron9a624912002-05-31 23:06:46 +00001496 TRACE("VirtualUnlock(%lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001497 (DWORD)retv, (DWORD)base, size);
1498
1499 result = VirtualUnlock(base, size);
1500
1501 if (result)
1502 *retv = TRUE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001503 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001504 else
1505 *retv = FALSE,
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001506 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001507 }
1508 break;
1509
1510
1511 case 0x001A: /* KGetSystemInfo */
1512 /*
1513 * Input: None
1514 *
1515 * Output: ECX: Start of sparse memory arena
1516 * EDX: End of sparse memory arena
1517 */
1518
Alexandre Julliard61fece01999-06-26 19:09:08 +00001519 TRACE("KGetSystemInfo()\n");
Vincent Béron9a624912002-05-31 23:06:46 +00001520
Alexandre Julliard642d3131998-07-12 19:29:36 +00001521 /*
Vincent Béron9a624912002-05-31 23:06:46 +00001522 * Note: Win32s reserves 0GB - 2GB for Win 3.1 and uses 2GB - 4GB as
1523 * sparse memory arena. We do it the other way around, since
Alexandre Julliard642d3131998-07-12 19:29:36 +00001524 * we have to reserve 3GB - 4GB for Linux, and thus use
1525 * 0GB - 3GB as sparse memory arena.
1526 *
1527 * FIXME: What about other OSes ?
1528 */
1529
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001530 context->Ecx = W32S_WINE2APP(0x00000000);
1531 context->Edx = W32S_WINE2APP(0xbfffffff);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001532 break;
1533
1534
1535 case 0x001B: /* KGlobalMemStat */
1536 /*
1537 * Input: ESI: Flat address of buffer to receive memory info
1538 *
1539 * Output: None
1540 */
1541 {
1542 struct Win32sMemoryInfo
1543 {
1544 DWORD DIPhys_Count; /* Total physical pages */
1545 DWORD DIFree_Count; /* Free physical pages */
1546 DWORD DILin_Total_Count; /* Total virtual pages (private arena) */
1547 DWORD DILin_Total_Free; /* Free virtual pages (private arena) */
1548
1549 DWORD SparseTotal; /* Total size of sparse arena (bytes ?) */
1550 DWORD SparseFree; /* Free size of sparse arena (bytes ?) */
1551 };
1552
Vincent Béron9a624912002-05-31 23:06:46 +00001553 struct Win32sMemoryInfo *info =
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001554 (struct Win32sMemoryInfo *)W32S_APP2WINE(context->Esi);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001555
Alexandre Julliard61fece01999-06-26 19:09:08 +00001556 FIXME("KGlobalMemStat(%lx)\n", (DWORD)info);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001557
1558 /* FIXME */
1559 }
1560 break;
1561
1562
1563 case 0x001C: /* Enable/Disable Exceptions */
1564 /*
1565 * Input: ECX: 0 to disable, 1 to enable exception handling
1566 *
1567 * Output: None
1568 */
1569
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001570 TRACE("[001c] ECX=%lx\n", context->Ecx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001571
1572 /* FIXME */
1573 break;
1574
1575
1576 case 0x001D: /* VirtualAlloc called from 16-bit code */
Vincent Béron9a624912002-05-31 23:06:46 +00001577 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001578 * Input: EDX: Segmented address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001579 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001580 * LPVOID base [in] Flat address of region to reserve/commit
1581 * DWORD size [in] Size of region
1582 * DWORD type [in] Type of allocation
1583 * DWORD prot [in] Type of access protection
1584 *
1585 * Output: EAX: NtStatus
1586 * EDX: Flat base address of allocated region
1587 */
1588 {
Alexandre Julliard982a2232000-12-13 20:20:09 +00001589 DWORD *stack = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) ));
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001590 LPVOID base = (LPVOID)W32S_APP2WINE(stack[0]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001591 DWORD size = stack[1];
1592 DWORD type = stack[2];
1593 DWORD prot = stack[3];
1594 DWORD result;
1595
Vincent Béron9a624912002-05-31 23:06:46 +00001596 TRACE("VirtualAlloc16(%lx, %lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001597 (DWORD)base, size, type, prot);
1598
1599 if (type & 0x80000000)
1600 {
Alexandre Julliard61fece01999-06-26 19:09:08 +00001601 WARN("VirtualAlloc16: strange type %lx\n", type);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001602 type &= 0x7fffffff;
1603 }
1604
1605 result = (DWORD)VirtualAlloc(base, size, type, prot);
1606
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001607 if (W32S_WINE2APP(result))
1608 context->Edx = W32S_WINE2APP(result),
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001609 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001610 else
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001611 context->Edx = 0,
1612 context->Eax = STATUS_NO_MEMORY; /* FIXME */
1613 TRACE("VirtualAlloc16: returning base %lx\n", context->Edx);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001614 }
1615 break;
1616
1617
1618 case 0x001E: /* VirtualFree called from 16-bit code */
Vincent Béron9a624912002-05-31 23:06:46 +00001619 /*
Alexandre Julliard642d3131998-07-12 19:29:36 +00001620 * Input: EDX: Segmented address of arguments on stack
Vincent Béron9a624912002-05-31 23:06:46 +00001621 *
Alexandre Julliard642d3131998-07-12 19:29:36 +00001622 * LPVOID base [in] Flat address of region
1623 * DWORD size [in] Size of region
1624 * DWORD type [in] Type of operation
1625 *
1626 * Output: EAX: NtStatus
1627 * EDX: TRUE if success, FALSE if failure
1628 */
1629 {
Alexandre Julliard982a2232000-12-13 20:20:09 +00001630 DWORD *stack = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) ));
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001631 LPVOID base = (LPVOID)W32S_APP2WINE(stack[0]);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001632 DWORD size = stack[1];
1633 DWORD type = stack[2];
1634 DWORD result;
1635
Vincent Béron9a624912002-05-31 23:06:46 +00001636 TRACE("VirtualFree16(%lx, %lx, %lx)\n",
Alexandre Julliard642d3131998-07-12 19:29:36 +00001637 (DWORD)base, size, type);
1638
1639 result = VirtualFree(base, size, type);
1640
1641 if (result)
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001642 context->Edx = TRUE,
1643 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001644 else
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001645 context->Edx = FALSE,
1646 context->Eax = STATUS_NO_MEMORY; /* FIXME */
Alexandre Julliard642d3131998-07-12 19:29:36 +00001647 }
1648 break;
1649
1650
1651 case 0x001F: /* FWorkingSetSize */
1652 /*
1653 * Input: EDX: 0 if Get, 1 if Set
1654 *
1655 * ECX: Get: Buffer to receive Working Set Size
1656 * Set: Buffer containing Working Set Size
1657 *
1658 * Output: NtStatus
1659 */
1660 {
Alexandre Julliardbecb9a32000-12-11 03:48:15 +00001661 DWORD *ptr = (DWORD *)W32S_APP2WINE(context->Ecx);
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001662 BOOL set = context->Edx;
Vincent Béron9a624912002-05-31 23:06:46 +00001663
Alexandre Julliard61fece01999-06-26 19:09:08 +00001664 TRACE("FWorkingSetSize(%lx, %lx)\n", (DWORD)ptr, (DWORD)set);
Alexandre Julliard642d3131998-07-12 19:29:36 +00001665
1666 if (set)
1667 /* We do it differently ... */;
1668 else
1669 *ptr = 0x100;
1670
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +00001671 context->Eax = STATUS_SUCCESS;
Alexandre Julliard642d3131998-07-12 19:29:36 +00001672 }
1673 break;
1674
1675
1676 default:
1677 VXD_BARF( context, "W32S" );
1678 }
1679
Alexandre Julliard642d3131998-07-12 19:29:36 +00001680}