blob: 84d5b1d34d509872ea44beebca3f8b01fa05c6f4 [file] [log] [blame]
Alexandre Julliard58199531994-04-21 01:20:00 +00001/*
Alexandre Julliard594997c1995-04-30 10:05:20 +00002 * Task functions
Alexandre Julliard234bc241994-12-10 13:02:28 +00003 *
Alexandre Julliard594997c1995-04-30 10:05:20 +00004 * Copyright 1995 Alexandre Julliard
5 */
6
Alexandre Julliard58199531994-04-21 01:20:00 +00007#include <stdlib.h>
8#include <string.h>
Alexandre Julliardef702d81996-05-28 18:54:58 +00009
Alexandre Julliard58199531994-04-21 01:20:00 +000010#include "windows.h"
Alexandre Julliard77b99181997-09-14 17:17:23 +000011#include "user.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000012#include "callback.h"
Alexandre Julliard491502b1997-11-01 19:08:16 +000013#include "drive.h"
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +000014#include "file.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000015#include "global.h"
16#include "instance.h"
Alexandre Julliardef702d81996-05-28 18:54:58 +000017#include "message.h"
Alexandre Julliarda2f2e011995-06-06 16:40:35 +000018#include "miscemu.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000019#include "module.h"
20#include "neexe.h"
Alexandre Julliard3051b641996-07-05 17:14:13 +000021#include "peexe.h"
22#include "pe_image.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000023#include "process.h"
Alexandre Julliardb817f4f1996-03-14 18:08:34 +000024#include "queue.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000025#include "selectors.h"
Alexandre Julliardf1aa3031996-08-05 17:42:43 +000026#include "stackframe.h"
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000027#include "task.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000028#include "thread.h"
Alexandre Julliard594997c1995-04-30 10:05:20 +000029#include "toolhelp.h"
Alexandre Julliard9ea19e51997-01-01 17:29:55 +000030#include "winnt.h"
Alexandre Julliarda845b881998-06-01 10:44:35 +000031#include "winsock.h"
Alexandre Julliard23946ad1997-06-16 17:43:53 +000032#include "thread.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000033#include "debug.h"
Alexandre Julliarde2991ea1995-07-29 13:09:43 +000034#include "dde_proc.h"
Alexandre Julliard642d3131998-07-12 19:29:36 +000035#include "server.h"
Alexandre Julliardaca05781994-10-17 18:12:41 +000036
Alexandre Julliard2787be81995-05-22 18:23:01 +000037 /* Min. number of thunks allocated when creating a new segment */
38#define MIN_THUNKS 32
Alexandre Julliard58199531994-04-21 01:20:00 +000039
Alexandre Julliard670cdc41997-08-24 16:00:30 +000040 /* Pointer to function to switch to a larger stack */
41int (*IF1632_CallLargeStack)( int (*func)(), void *arg ) = NULL;
Alexandre Julliard18f92e71996-07-17 20:02:21 +000042
Alexandre Julliard642d3131998-07-12 19:29:36 +000043
44static THHOOK DefaultThhook = { 0 };
45THHOOK *pThhook = &DefaultThhook;
46
47#define hCurrentTask (pThhook->CurTDB)
48#define hFirstTask (pThhook->HeadTDB)
49#define hLockedTask (pThhook->LockTDB)
50
Alexandre Julliard18f92e71996-07-17 20:02:21 +000051static HTASK16 hTaskToKill = 0;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000052static UINT16 nTaskCount = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +000053
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000054static void TASK_YieldToSystem(TDB*);
Alexandre Julliard808cb041995-08-17 17:11:36 +000055
Alexandre Julliard642d3131998-07-12 19:29:36 +000056/***********************************************************************
57 * TASK_InstallTHHook
58 */
59void TASK_InstallTHHook( THHOOK *pNewThhook )
60{
61 THHOOK *pOldThhook = pThhook;
62
63 pThhook = pNewThhook? pNewThhook : &DefaultThhook;
64
65 *pThhook = *pOldThhook;
66}
Alexandre Julliard808cb041995-08-17 17:11:36 +000067
68/***********************************************************************
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000069 * TASK_GetNextTask
70 */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000071HTASK16 TASK_GetNextTask( HTASK16 hTask )
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000072{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000073 TDB* pTask = (TDB*)GlobalLock16(hTask);
Alexandre Julliard2ace16a1996-04-28 15:09:19 +000074
75 if (pTask->hNext) return pTask->hNext;
76 return (hFirstTask != hTask) ? hFirstTask : 0;
77}
78
79
80/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +000081 * TASK_LinkTask
Alexandre Julliard58199531994-04-21 01:20:00 +000082 */
Alexandre Julliard18f92e71996-07-17 20:02:21 +000083static void TASK_LinkTask( HTASK16 hTask )
Alexandre Julliard58199531994-04-21 01:20:00 +000084{
Alexandre Julliard18f92e71996-07-17 20:02:21 +000085 HTASK16 *prevTask;
Alexandre Julliard594997c1995-04-30 10:05:20 +000086 TDB *pTask;
87
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000088 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
Alexandre Julliard594997c1995-04-30 10:05:20 +000089 prevTask = &hFirstTask;
90 while (*prevTask)
91 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +000092 TDB *prevTaskPtr = (TDB *)GlobalLock16( *prevTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +000093 if (prevTaskPtr->priority >= pTask->priority) break;
94 prevTask = &prevTaskPtr->hNext;
95 }
96 pTask->hNext = *prevTask;
97 *prevTask = hTask;
98 nTaskCount++;
Alexandre Julliard58199531994-04-21 01:20:00 +000099}
100
101
Alexandre Julliard594997c1995-04-30 10:05:20 +0000102/***********************************************************************
103 * TASK_UnlinkTask
Alexandre Julliard58199531994-04-21 01:20:00 +0000104 */
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000105static void TASK_UnlinkTask( HTASK16 hTask )
Alexandre Julliard58199531994-04-21 01:20:00 +0000106{
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000107 HTASK16 *prevTask;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000108 TDB *pTask;
109
110 prevTask = &hFirstTask;
111 while (*prevTask && (*prevTask != hTask))
112 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000113 pTask = (TDB *)GlobalLock16( *prevTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000114 prevTask = &pTask->hNext;
115 }
116 if (*prevTask)
117 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000118 pTask = (TDB *)GlobalLock16( *prevTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000119 *prevTask = pTask->hNext;
120 pTask->hNext = 0;
121 nTaskCount--;
122 }
Alexandre Julliard58199531994-04-21 01:20:00 +0000123}
124
125
Alexandre Julliard594997c1995-04-30 10:05:20 +0000126/***********************************************************************
127 * TASK_CreateThunks
128 *
129 * Create a thunk free-list in segment 'handle', starting from offset 'offset'
130 * and containing 'count' entries.
Alexandre Julliard58199531994-04-21 01:20:00 +0000131 */
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000132static void TASK_CreateThunks( HGLOBAL16 handle, WORD offset, WORD count )
Alexandre Julliard58199531994-04-21 01:20:00 +0000133{
Alexandre Julliard594997c1995-04-30 10:05:20 +0000134 int i;
135 WORD free;
136 THUNKS *pThunk;
137
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000138 pThunk = (THUNKS *)((BYTE *)GlobalLock16( handle ) + offset);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000139 pThunk->next = 0;
140 pThunk->magic = THUNK_MAGIC;
141 pThunk->free = (int)&pThunk->thunks - (int)pThunk;
142 free = pThunk->free;
143 for (i = 0; i < count-1; i++)
144 {
145 free += 8; /* Offset of next thunk */
146 pThunk->thunks[4*i] = free;
147 }
148 pThunk->thunks[4*i] = 0; /* Last thunk */
Alexandre Julliard58199531994-04-21 01:20:00 +0000149}
150
151
Alexandre Julliard594997c1995-04-30 10:05:20 +0000152/***********************************************************************
153 * TASK_AllocThunk
154 *
155 * Allocate a thunk for MakeProcInstance().
Alexandre Julliard58199531994-04-21 01:20:00 +0000156 */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000157static SEGPTR TASK_AllocThunk( HTASK16 hTask )
Alexandre Julliard58199531994-04-21 01:20:00 +0000158{
Alexandre Julliard594997c1995-04-30 10:05:20 +0000159 TDB *pTask;
160 THUNKS *pThunk;
161 WORD sel, base;
162
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000163 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000164 sel = pTask->hCSAlias;
165 pThunk = &pTask->thunks;
166 base = (int)pThunk - (int)pTask;
167 while (!pThunk->free)
168 {
169 sel = pThunk->next;
170 if (!sel) /* Allocate a new segment */
171 {
172 sel = GLOBAL_Alloc( GMEM_FIXED, sizeof(THUNKS) + (MIN_THUNKS-1)*8,
173 pTask->hPDB, TRUE, FALSE, FALSE );
174 if (!sel) return (SEGPTR)0;
175 TASK_CreateThunks( sel, 0, MIN_THUNKS );
176 pThunk->next = sel;
177 }
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000178 pThunk = (THUNKS *)GlobalLock16( sel );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000179 base = 0;
180 }
181 base += pThunk->free;
182 pThunk->free = *(WORD *)((BYTE *)pThunk + pThunk->free);
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000183 return PTR_SEG_OFF_TO_SEGPTR( sel, base );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000184}
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000185
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000186
Alexandre Julliard594997c1995-04-30 10:05:20 +0000187/***********************************************************************
188 * TASK_FreeThunk
189 *
190 * Free a MakeProcInstance() thunk.
191 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000192static BOOL32 TASK_FreeThunk( HTASK16 hTask, SEGPTR thunk )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000193{
194 TDB *pTask;
195 THUNKS *pThunk;
196 WORD sel, base;
197
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000198 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000199 sel = pTask->hCSAlias;
200 pThunk = &pTask->thunks;
201 base = (int)pThunk - (int)pTask;
202 while (sel && (sel != HIWORD(thunk)))
203 {
204 sel = pThunk->next;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000205 pThunk = (THUNKS *)GlobalLock16( sel );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000206 base = 0;
207 }
208 if (!sel) return FALSE;
209 *(WORD *)((BYTE *)pThunk + LOWORD(thunk) - base) = pThunk->free;
210 pThunk->free = LOWORD(thunk) - base;
211 return TRUE;
212}
213
214
215/***********************************************************************
216 * TASK_CallToStart
217 *
218 * 32-bit entry point for a new task. This function is responsible for
219 * setting up the registers and jumping to the 16-bit entry point.
220 */
221static void TASK_CallToStart(void)
222{
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000223 int exit_code = 1;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000224 TDB *pTask = (TDB *)GlobalLock16( hCurrentTask );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000225 NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000226 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000227
Alexandre Julliard02e90081998-01-04 17:49:09 +0000228 SET_CUR_THREAD( pTask->thdb );
Alexandre Julliard642d3131998-07-12 19:29:36 +0000229 CLIENT_InitThread();
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000230 /* Terminate the stack frame */
231 THREAD_STACK16(pTask->thdb)->frame32 = NULL;
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000232 if (pModule->flags & NE_FFLAGS_WIN32)
233 {
234 /* FIXME: all this is an ugly hack */
235
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000236 FARPROC32 entry = (FARPROC32)RVA_PTR( PROCESS_Current()->exe_modref->module, OptionalHeader.AddressOfEntryPoint );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000237
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000238 pTask->userhandler = (USERSIGNALPROC)&USER_SignalProc;
239 if (pModule->heap_size)
240 LocalInit( pTask->hInstance, 0, pModule->heap_size );
241
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000242 InitApp( pTask->hModule );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000243 PE_InitializeDLLs( PROCESS_Current(), DLL_PROCESS_ATTACH, (LPVOID)-1 );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000244 TRACE(relay, "(entryproc=%p)\n", entry );
Alexandre Julliard77b99181997-09-14 17:17:23 +0000245 exit_code = entry();
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000246 TASK_KillCurrentTask( exit_code );
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000247 }
248 else
249 {
250 /* Registers at initialization must be:
251 * ax zero
252 * bx stack size in bytes
253 * cx heap size in bytes
254 * si previous app instance
255 * di current app instance
256 * bp zero
257 * es selector to the PSP
258 * ds dgroup of the application
259 * ss stack selector
260 * sp top of the stack
261 */
Alexandre Julliard21979011997-03-05 08:22:35 +0000262 CONTEXT context;
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000263
Alexandre Julliard21979011997-03-05 08:22:35 +0000264 memset( &context, 0, sizeof(context) );
265 CS_reg(&context) = pSegTable[pModule->cs - 1].selector;
266 DS_reg(&context) = pSegTable[pModule->dgroup - 1].selector;
267 ES_reg(&context) = pTask->hPDB;
268 EIP_reg(&context) = pModule->ip;
269 EBX_reg(&context) = pModule->stack_size;
270 ECX_reg(&context) = pModule->heap_size;
271 EDI_reg(&context) = context.SegDs;
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000272
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000273 TRACE(task, "Starting main program: cs:ip=%04lx:%04x ds=%04lx ss:sp=%04x:%04x\n",
Alexandre Julliard21979011997-03-05 08:22:35 +0000274 CS_reg(&context), IP_reg(&context), DS_reg(&context),
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000275 SELECTOROF(pTask->thdb->cur_stack),
276 OFFSETOF(pTask->thdb->cur_stack) );
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000277
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000278 Callbacks->CallRegisterShortProc( &context, 0 );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000279 /* This should never return */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000280 ERR( task, "Main program returned! (should never happen)\n" );
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000281 TASK_KillCurrentTask( 1 );
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000282 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000283}
284
285
286/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000287 * TASK_Create
Alexandre Julliard594997c1995-04-30 10:05:20 +0000288 */
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000289HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
290 HINSTANCE16 hPrevInstance, UINT16 cmdShow)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000291{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000292 HTASK16 hTask;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000293 TDB *pTask;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000294 LPSTR cmd_line;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000295 WORD sp;
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000296 char *stack32Top;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000297 char name[10];
Alexandre Julliard594997c1995-04-30 10:05:20 +0000298 STACK16FRAME *frame16;
299 STACK32FRAME *frame32;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000300 PDB32 *pdb32 = thdb->process;
301 SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000302
303 /* Allocate the task structure */
304
305 hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000306 pModule->self, FALSE, FALSE, FALSE );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000307 if (!hTask) return 0;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000308 pTask = (TDB *)GlobalLock16( hTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000309
Alexandre Julliard491502b1997-11-01 19:08:16 +0000310 /* Fill the task structure */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000311
Alexandre Julliard2787be81995-05-22 18:23:01 +0000312 pTask->nEvents = 1; /* So the task can be started */
313 pTask->hSelf = hTask;
314 pTask->flags = 0;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000315
316 if (pModule->flags & NE_FFLAGS_WIN32)
317 pTask->flags |= TDBF_WIN32;
318
Alexandre Julliard2787be81995-05-22 18:23:01 +0000319 pTask->version = pModule->expected_version;
320 pTask->hInstance = hInstance;
321 pTask->hPrevInstance = hPrevInstance;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000322 pTask->hModule = pModule->self;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000323 pTask->hParent = hCurrentTask;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000324 pTask->magic = TDB_MAGIC;
325 pTask->nCmdShow = cmdShow;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000326 pTask->thdb = thdb;
Alexandre Julliard491502b1997-11-01 19:08:16 +0000327 pTask->curdrive = DRIVE_GetCurrentDrive() | 0x80;
328 strcpy( pTask->curdir, "\\" );
329 lstrcpyn32A( pTask->curdir + 1, DRIVE_GetDosCwd( DRIVE_GetCurrentDrive() ),
330 sizeof(pTask->curdir) - 1 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000331
332 /* Create the thunks block */
333
334 TASK_CreateThunks( hTask, (int)&pTask->thunks - (int)pTask, 7 );
335
336 /* Copy the module name */
337
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000338 GetModuleName( pModule->self, name, sizeof(name) );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000339 strncpy( pTask->module_name, name, sizeof(pTask->module_name) );
340
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000341 /* Allocate a selector for the PDB */
342
343 pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000344 pModule->self, FALSE, FALSE, FALSE, NULL );
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000345
Alexandre Julliard594997c1995-04-30 10:05:20 +0000346 /* Fill the PDB */
347
348 pTask->pdb.int20 = 0x20cd;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000349 pTask->pdb.dispatcher[0] = 0x9a; /* ljmp */
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000350 PUT_DWORD(&pTask->pdb.dispatcher[1], (DWORD)NE_GetEntryPoint(
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000351 GetModuleHandle16("KERNEL"), 102 )); /* KERNEL.102 is DOS3Call() */
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000352 pTask->pdb.savedint22 = INT_GetHandler( 0x22 );
353 pTask->pdb.savedint23 = INT_GetHandler( 0x23 );
354 pTask->pdb.savedint24 = INT_GetHandler( 0x24 );
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000355 pTask->pdb.fileHandlesPtr =
356 PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel(pTask->hPDB),
357 (int)&((PDB *)0)->fileHandles );
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000358 pTask->pdb.hFileHandles = 0;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000359 memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000360 pTask->pdb.environment = pdb32->env_db->env_sel;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +0000361 pTask->pdb.nbFiles = 20;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000362
363 /* Fill the command line */
364
365 cmd_line = pdb32->env_db->cmd_line;
366 while (*cmd_line && (*cmd_line != ' ') && (*cmd_line != '\t')) cmd_line++;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +0000367 while ((*cmd_line == ' ') || (*cmd_line == '\t')) cmd_line++;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000368 lstrcpyn32A( pTask->pdb.cmdLine+1, cmd_line, sizeof(pTask->pdb.cmdLine)-1);
369 pTask->pdb.cmdLine[0] = strlen( pTask->pdb.cmdLine + 1 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000370
371 /* Get the compatibility flags */
372
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000373 pTask->compat_flags = GetProfileInt32A( "Compatibility", name, 0 );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000374
Alexandre Julliard594997c1995-04-30 10:05:20 +0000375 /* Allocate a code segment alias for the TDB */
376
377 pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
378 sizeof(TDB), pTask->hPDB, TRUE,
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000379 FALSE, FALSE, NULL );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000380
381 /* Set the owner of the environment block */
382
383 FarSetOwner( pTask->pdb.environment, pTask->hPDB );
384
385 /* Default DTA overwrites command-line */
386
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000387 pTask->dta = PTR_SEG_OFF_TO_SEGPTR( pTask->hPDB,
388 (int)&pTask->pdb.cmdLine - (int)&pTask->pdb );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000389
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000390 /* Create the 16-bit stack frame */
391
392 if (!(sp = pModule->sp))
393 sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
394 sp &= ~1;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000395 pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( pTask->hInstance, sp );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000396 pTask->thdb->cur_stack -= sizeof(STACK16FRAME) + sizeof(STACK32FRAME *);
397 frame16 = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
398 frame16->ebp = sp + (int)&((STACK16FRAME *)0)->bp;
399 frame16->bp = LOWORD(frame16->ebp);
400 frame16->ds = frame16->es = pTask->hInstance;
401 frame16->entry_point = 0;
402 frame16->entry_cs = 0;
403 /* The remaining fields will be initialized in TASK_Reschedule */
Alexandre Julliard491502b1997-11-01 19:08:16 +0000404
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000405 /* Create the 32-bit stack frame */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000406
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000407 stack32Top = (char*)pTask->thdb->teb.stack_top;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000408 frame16->frame32 = frame32 = (STACK32FRAME *)stack32Top - 1;
409 frame32->frame16 = pTask->thdb->cur_stack + sizeof(STACK16FRAME);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000410 frame32->edi = 0;
411 frame32->esi = 0;
412 frame32->edx = 0;
413 frame32->ecx = 0;
414 frame32->ebx = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000415 frame32->retaddr = (DWORD)TASK_CallToStart;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000416 /* The remaining fields will be initialized in TASK_Reschedule */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000417
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000418 if (!THREAD_Current()->cur_stack)
419 THREAD_Current()->cur_stack = pTask->thdb->cur_stack;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000420
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000421 /* Add the task to the linked list */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000422
423 TASK_LinkTask( hTask );
424
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000425 TRACE(task, "module='%s' cmdline='%s' task=%04x\n",
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000426 name, cmd_line, hTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000427
Alexandre Julliard58199531994-04-21 01:20:00 +0000428 return hTask;
429}
430
431
Alexandre Julliard594997c1995-04-30 10:05:20 +0000432/***********************************************************************
433 * TASK_DeleteTask
Alexandre Julliard58199531994-04-21 01:20:00 +0000434 */
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000435static void TASK_DeleteTask( HTASK16 hTask )
Alexandre Julliard58199531994-04-21 01:20:00 +0000436{
Alexandre Julliard594997c1995-04-30 10:05:20 +0000437 TDB *pTask;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000438 HGLOBAL16 hPDB;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000439
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000440 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000441 hPDB = pTask->hPDB;
442
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000443 pTask->magic = 0xdead; /* invalidate signature */
444
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000445 /* Delete the Win32 part of the task */
446
Alexandre Julliard02e90081998-01-04 17:49:09 +0000447 K32OBJ_DecCount( &pTask->thdb->process->header );
448 K32OBJ_DecCount( &pTask->thdb->header );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000449
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000450 /* Free the task module */
451
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000452 FreeModule16( pTask->hModule );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000453
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000454 /* Free the selector aliases */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000455
456 GLOBAL_FreeBlock( pTask->hCSAlias );
457 GLOBAL_FreeBlock( pTask->hPDB );
458
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000459 /* Free the task structure itself */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000460
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000461 GlobalFree16( hTask );
Alexandre Julliard7e56f681996-01-31 19:02:28 +0000462
463 /* Free all memory used by this task (including the 32-bit stack, */
464 /* the environment block and the thunk segments). */
465
466 GlobalFreeAll( hPDB );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000467}
468
469
470/***********************************************************************
471 * TASK_KillCurrentTask
472 *
473 * Kill the currently running task. As it's not possible to kill the
474 * current task like this, it is simply marked for destruction, and will
475 * be killed when either TASK_Reschedule or this function is called again
476 * in the context of another task.
477 */
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000478void TASK_KillCurrentTask( INT16 exitCode )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000479{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000480 TDB* pTask = (TDB*) GlobalLock16( hCurrentTask );
Alexandre Julliard889f7421997-04-15 17:19:52 +0000481 if (!pTask) USER_ExitWindows(); /* No current task yet */
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000482
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000483 TRACE(task, "Killing task %04x\n", hCurrentTask );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000484
Alexandre Julliard77b99181997-09-14 17:17:23 +0000485 /* Delete active sockets */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000486
Alexandre Julliard77b99181997-09-14 17:17:23 +0000487 if( pTask->pwsi )
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000488 WINSOCK_DeleteTaskWSI( pTask, pTask->pwsi );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000489
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000490 /* Perform USER cleanup */
491
Alexandre Julliard77b99181997-09-14 17:17:23 +0000492 if (pTask->userhandler)
493 pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
494 pTask->hInstance, pTask->hQueue );
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000495
Alexandre Julliard594997c1995-04-30 10:05:20 +0000496 if (hTaskToKill && (hTaskToKill != hCurrentTask))
497 {
498 /* If another task is already marked for destruction, */
Alexandre Julliardef702d81996-05-28 18:54:58 +0000499 /* we can kill it now, as we are in another context. */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000500 TASK_DeleteTask( hTaskToKill );
501 }
502
503 if (nTaskCount <= 1)
504 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000505 TRACE(task, "this is the last task, exiting\n" );
Alexandre Julliard889f7421997-04-15 17:19:52 +0000506 USER_ExitWindows();
Alexandre Julliard594997c1995-04-30 10:05:20 +0000507 }
508
509 /* Remove the task from the list to be sure we never switch back to it */
510 TASK_UnlinkTask( hCurrentTask );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000511 if( nTaskCount )
512 {
513 TDB* p = (TDB *)GlobalLock16( hFirstTask );
514 while( p )
515 {
516 if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0;
517 p = (TDB *)GlobalLock16( p->hNext );
518 }
519 }
520
Alexandre Julliard594997c1995-04-30 10:05:20 +0000521 hTaskToKill = hCurrentTask;
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000522 hLockedTask = 0;
Alexandre Julliardd4719651995-12-12 18:49:11 +0000523
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000524 pTask->nEvents = 0;
525 TASK_YieldToSystem(pTask);
526
Alexandre Julliardd4719651995-12-12 18:49:11 +0000527 /* We should never return from this Yield() */
528
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000529 ERR(task,"Return of the living dead %04x!!!\n", hCurrentTask);
Alexandre Julliardd4719651995-12-12 18:49:11 +0000530 exit(1);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000531}
532
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000533/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000534 * TASK_Reschedule
535 *
536 * This is where all the magic of task-switching happens!
537 *
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000538 * Note: This function should only be called via the TASK_YieldToSystem()
539 * wrapper, to make sure that all the context is saved correctly.
540 *
541 * It must not call functions that may yield control.
Alexandre Julliard594997c1995-04-30 10:05:20 +0000542 */
543void TASK_Reschedule(void)
544{
545 TDB *pOldTask = NULL, *pNewTask;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000546 HTASK16 hTask = 0;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000547 STACK16FRAME *newframe16;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000548
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000549#ifdef CONFIG_IPC
Alexandre Julliarde2991ea1995-07-29 13:09:43 +0000550 dde_reschedule();
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000551#endif
Alexandre Julliard594997c1995-04-30 10:05:20 +0000552 /* First check if there's a task to kill */
553
554 if (hTaskToKill && (hTaskToKill != hCurrentTask))
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000555 {
Alexandre Julliard594997c1995-04-30 10:05:20 +0000556 TASK_DeleteTask( hTaskToKill );
Alexandre Julliardb7258be1995-09-01 15:57:28 +0000557 hTaskToKill = 0;
558 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000559
Alexandre Julliardef702d81996-05-28 18:54:58 +0000560 /* Find a task to yield to */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000561
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000562 pOldTask = (TDB *)GlobalLock16( hCurrentTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000563 if (pOldTask && pOldTask->hYieldTo)
564 {
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000565 /* check for DirectedYield() */
566
Alexandre Julliard594997c1995-04-30 10:05:20 +0000567 hTask = pOldTask->hYieldTo;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000568 pNewTask = (TDB *)GlobalLock16( hTask );
569 if( !pNewTask || !pNewTask->nEvents) hTask = 0;
570 pOldTask->hYieldTo = 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000571 }
572
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000573 /* extract hardware events only! */
574
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000575 if (!hTask) EVENT_WaitNetEvent( FALSE, TRUE );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000576
Alexandre Julliardef702d81996-05-28 18:54:58 +0000577 while (!hTask)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000578 {
Alexandre Julliardef702d81996-05-28 18:54:58 +0000579 /* Find a task that has an event pending */
580
Alexandre Julliard594997c1995-04-30 10:05:20 +0000581 hTask = hFirstTask;
582 while (hTask)
583 {
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000584 pNewTask = (TDB *)GlobalLock16( hTask );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000585
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000586 TRACE(task, "\ttask = %04x, events = %i\n", hTask, pNewTask->nEvents);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000587
Alexandre Julliardef702d81996-05-28 18:54:58 +0000588 if (pNewTask->nEvents) break;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000589 hTask = pNewTask->hNext;
590 }
Alexandre Julliardef702d81996-05-28 18:54:58 +0000591 if (hLockedTask && (hTask != hLockedTask)) hTask = 0;
592 if (hTask) break;
593
594 /* No task found, wait for some events to come in */
595
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000596 EVENT_WaitNetEvent( TRUE, TRUE );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000597 }
598
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000599 if (hTask == hCurrentTask)
600 {
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000601 TRACE(task, "returning to the current task(%04x)\n", hTask );
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000602 return; /* Nothing to do */
603 }
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000604 pNewTask = (TDB *)GlobalLock16( hTask );
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000605 TRACE(task, "Switching to task %04x (%.8s)\n",
Alexandre Julliard594997c1995-04-30 10:05:20 +0000606 hTask, pNewTask->module_name );
607
Alexandre Julliard594997c1995-04-30 10:05:20 +0000608 /* Make the task the last in the linked list (round-robin scheduling) */
609
610 pNewTask->priority++;
611 TASK_UnlinkTask( hTask );
612 TASK_LinkTask( hTask );
613 pNewTask->priority--;
614
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000615 /* Finish initializing the new task stack if necessary */
616
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000617 newframe16 = THREAD_STACK16( pNewTask->thdb );
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000618 if (!newframe16->entry_cs)
619 {
620 STACK16FRAME *oldframe16 = CURRENT_STACK16;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000621 STACK32FRAME *oldframe32 = oldframe16->frame32;
622 STACK32FRAME *newframe32 = newframe16->frame32;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +0000623 newframe16->entry_ip = oldframe16->entry_ip;
624 newframe16->entry_cs = oldframe16->entry_cs;
625 newframe16->ip = oldframe16->ip;
626 newframe16->cs = oldframe16->cs;
627 newframe32->ebp = oldframe32->ebp;
628 newframe32->restore_addr = oldframe32->restore_addr;
629 newframe32->codeselector = oldframe32->codeselector;
630 }
631
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000632 /* Switch to the new stack */
Alexandre Julliard594997c1995-04-30 10:05:20 +0000633
634 hCurrentTask = hTask;
Alexandre Julliard02e90081998-01-04 17:49:09 +0000635 SET_CUR_THREAD( pNewTask->thdb );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000636 pNewTask->ss_sp = pNewTask->thdb->cur_stack;
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000637}
638
639
640/***********************************************************************
641 * TASK_YieldToSystem
642 *
643 * Scheduler interface, this way we ensure that all "unsafe" events are
644 * processed outside the scheduler.
645 */
646void TASK_YieldToSystem(TDB* pTask)
647{
648 MESSAGEQUEUE* pQ;
649
Alexandre Julliard491502b1997-11-01 19:08:16 +0000650 Callbacks->CallTaskRescheduleProc();
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000651
652 if( pTask )
653 {
654 pQ = (MESSAGEQUEUE*)GlobalLock16(pTask->hQueue);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000655 if( pQ && pQ->flags & QUEUE_FLAG_XEVENT &&
656 !(pQ->wakeBits & (QS_SENDMESSAGE | QS_SMRESULT)) )
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000657 {
658 pQ->flags &= ~QUEUE_FLAG_XEVENT;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000659 EVENT_WaitNetEvent( FALSE, FALSE );
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000660 }
661 }
Alexandre Julliard2787be81995-05-22 18:23:01 +0000662}
663
664
665/***********************************************************************
666 * InitTask (KERNEL.91)
Alexandre Julliard77b99181997-09-14 17:17:23 +0000667 *
668 * Called by the application startup code.
Alexandre Julliard2787be81995-05-22 18:23:01 +0000669 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000670void WINAPI InitTask( CONTEXT *context )
Alexandre Julliard2787be81995-05-22 18:23:01 +0000671{
672 TDB *pTask;
673 NE_MODULE *pModule;
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000674 SEGTABLEENTRY *pSegTable;
675 INSTANCEDATA *pinstance;
676 LONG stacklow, stackhi;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000677
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000678 if (context) EAX_reg(context) = 0;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000679 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000680 if (!(pModule = NE_GetPtr( pTask->hModule ))) return;
Alexandre Julliard2787be81995-05-22 18:23:01 +0000681
Alexandre Julliard77b99181997-09-14 17:17:23 +0000682 /* This is a hack to install task USER signal handler before
683 * implicitly loaded DLLs are initialized (see windows/user.c) */
684
685 pTask->userhandler = (USERSIGNALPROC)&USER_SignalProc;
686
Alexandre Julliard77b99181997-09-14 17:17:23 +0000687 /* Initialize implicitly loaded DLLs */
Alexandre Julliard2787be81995-05-22 18:23:01 +0000688 NE_InitializeDLLs( pTask->hModule );
689
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000690 if (context)
691 {
692 /* Registers on return are:
693 * ax 1 if OK, 0 on error
694 * cx stack limit in bytes
695 * dx cmdShow parameter
696 * si instance handle of the previous instance
697 * di instance handle of the new task
698 * es:bx pointer to command-line inside PSP
699 */
700 EAX_reg(context) = 1;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000701
702 if (!pTask->pdb.cmdLine[0]) EBX_reg(context) = 0x80;
703 else
704 {
705 LPBYTE p = &pTask->pdb.cmdLine[1];
706 while ((*p == ' ') || (*p == '\t')) p++;
707 EBX_reg(context) = 0x80 + (p - pTask->pdb.cmdLine);
708 }
Alexandre Julliard139a4b11996-11-02 14:24:07 +0000709 ECX_reg(context) = pModule->stack_size;
710 EDX_reg(context) = pTask->nCmdShow;
711 ESI_reg(context) = (DWORD)pTask->hPrevInstance;
712 EDI_reg(context) = (DWORD)pTask->hInstance;
713 ES_reg (context) = (WORD)pTask->hPDB;
714 }
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000715
716 /* Initialize the local heap */
717 if ( pModule->heap_size )
718 {
719 LocalInit( pTask->hInstance, 0, pModule->heap_size );
720 }
721
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000722 /* Initialize the INSTANCEDATA structure */
723 pSegTable = NE_SEG_TABLE( pModule );
724 stacklow = pSegTable[pModule->ss - 1].minsize;
725 stackhi = stacklow + pModule->stack_size;
726 if (stackhi > 0xffff) stackhi = 0xffff;
727 pinstance = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN(CURRENT_DS, 0);
728 pinstance->stackbottom = stackhi; /* yup, that's right. Confused me too. */
729 pinstance->stacktop = stacklow;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000730 pinstance->stackmin = OFFSETOF( pTask->thdb->cur_stack );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000731}
732
733
734/***********************************************************************
735 * WaitEvent (KERNEL.30)
736 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000737BOOL16 WINAPI WaitEvent( HTASK16 hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000738{
739 TDB *pTask;
740
741 if (!hTask) hTask = hCurrentTask;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000742 pTask = (TDB *)GlobalLock16( hTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000743 if (pTask->nEvents > 0)
744 {
745 pTask->nEvents--;
746 return FALSE;
747 }
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000748 TASK_YieldToSystem(pTask);
749
Alexandre Julliardef702d81996-05-28 18:54:58 +0000750 /* When we get back here, we have an event */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000751
Alexandre Julliardbd34d4f1995-06-20 19:08:12 +0000752 if (pTask->nEvents > 0) pTask->nEvents--;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000753 return TRUE;
754}
755
756
757/***********************************************************************
758 * PostEvent (KERNEL.31)
759 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000760void WINAPI PostEvent( HTASK16 hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000761{
762 TDB *pTask;
763
764 if (!hTask) hTask = hCurrentTask;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000765 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000766 pTask->nEvents++;
767}
768
769
770/***********************************************************************
771 * SetPriority (KERNEL.32)
772 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000773void WINAPI SetPriority( HTASK16 hTask, INT16 delta )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000774{
775 TDB *pTask;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000776 INT16 newpriority;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000777
778 if (!hTask) hTask = hCurrentTask;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000779 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000780 newpriority = pTask->priority + delta;
781 if (newpriority < -32) newpriority = -32;
782 else if (newpriority > 15) newpriority = 15;
783
784 pTask->priority = newpriority + 1;
785 TASK_UnlinkTask( hTask );
786 TASK_LinkTask( hTask );
787 pTask->priority--;
788}
789
790
791/***********************************************************************
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000792 * LockCurrentTask (KERNEL.33)
793 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000794HTASK16 WINAPI LockCurrentTask( BOOL16 bLock )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000795{
796 if (bLock) hLockedTask = hCurrentTask;
797 else hLockedTask = 0;
798 return hLockedTask;
799}
800
801
802/***********************************************************************
803 * IsTaskLocked (KERNEL.122)
804 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000805HTASK16 WINAPI IsTaskLocked(void)
Alexandre Julliarda2f2e011995-06-06 16:40:35 +0000806{
807 return hLockedTask;
808}
809
810
811/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000812 * OldYield (KERNEL.117)
813 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000814void WINAPI OldYield(void)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000815{
816 TDB *pCurTask;
817
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000818 pCurTask = (TDB *)GlobalLock16( hCurrentTask );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000819 if (pCurTask) pCurTask->nEvents++; /* Make sure we get back here */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000820 TASK_YieldToSystem(pCurTask);
Alexandre Julliard594997c1995-04-30 10:05:20 +0000821 if (pCurTask) pCurTask->nEvents--;
822}
823
824
825/***********************************************************************
826 * DirectedYield (KERNEL.150)
827 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000828void WINAPI DirectedYield( HTASK16 hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000829{
Alexandre Julliardef702d81996-05-28 18:54:58 +0000830 TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
831 pCurTask->hYieldTo = hTask;
832 OldYield();
833}
Alexandre Julliard594997c1995-04-30 10:05:20 +0000834
Alexandre Julliardef702d81996-05-28 18:54:58 +0000835
836/***********************************************************************
837 * UserYield (USER.332)
838 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000839void WINAPI UserYield(void)
Alexandre Julliardef702d81996-05-28 18:54:58 +0000840{
841 TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
842 MESSAGEQUEUE *queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
843 /* Handle sent messages */
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000844 while (queue && (queue->wakeBits & QS_SENDMESSAGE))
Alexandre Julliardef702d81996-05-28 18:54:58 +0000845 QUEUE_ReceiveMessage( queue );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000846
847 OldYield();
Alexandre Julliardef702d81996-05-28 18:54:58 +0000848
849 queue = (MESSAGEQUEUE *)GlobalLock16( pCurTask->hQueue );
Alexandre Julliard3db94ef1997-09-28 17:43:24 +0000850 while (queue && (queue->wakeBits & QS_SENDMESSAGE))
Alexandre Julliardef702d81996-05-28 18:54:58 +0000851 QUEUE_ReceiveMessage( queue );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000852}
853
854
855/***********************************************************************
Alexandre Julliarde658d821997-11-30 17:45:40 +0000856 * Yield16 (KERNEL.29)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000857 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000858void WINAPI Yield16(void)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000859{
Alexandre Julliardef702d81996-05-28 18:54:58 +0000860 TDB *pCurTask = (TDB *)GlobalLock16( hCurrentTask );
861 if (pCurTask) pCurTask->hYieldTo = 0;
862 if (pCurTask && pCurTask->hQueue) UserYield();
863 else OldYield();
Alexandre Julliard594997c1995-04-30 10:05:20 +0000864}
865
866
867/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000868 * MakeProcInstance16 (KERNEL.51)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000869 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000870FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000871{
Alexandre Julliarde658d821997-11-30 17:45:40 +0000872 BYTE *thunk,*lfunc;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000873 SEGPTR thunkaddr;
Alexandre Julliard54c27111998-03-29 19:44:57 +0000874
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000875 if (!hInstance) hInstance = CURRENT_DS;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000876 thunkaddr = TASK_AllocThunk( hCurrentTask );
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000877 if (!thunkaddr) return (FARPROC16)0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000878 thunk = PTR_SEG_TO_LIN( thunkaddr );
Alexandre Julliarde658d821997-11-30 17:45:40 +0000879 lfunc = PTR_SEG_TO_LIN( func );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000880
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000881 TRACE(task, "(%08lx,%04x): got thunk %08lx\n",
Alexandre Julliard59730ae1996-03-24 16:20:51 +0000882 (DWORD)func, hInstance, (DWORD)thunkaddr );
Alexandre Julliarde658d821997-11-30 17:45:40 +0000883 if (((lfunc[0]==0x8c) && (lfunc[1]==0xd8)) ||
884 ((lfunc[0]==0x1e) && (lfunc[1]==0x58))
885 ) {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000886 FIXME(task,"thunk would be useless for %p, overwriting with nop;nop;\n", func );
Alexandre Julliarde658d821997-11-30 17:45:40 +0000887 lfunc[0]=0x90; /* nop */
888 lfunc[1]=0x90; /* nop */
889 }
Alexandre Julliard594997c1995-04-30 10:05:20 +0000890
891 *thunk++ = 0xb8; /* movw instance, %ax */
892 *thunk++ = (BYTE)(hInstance & 0xff);
893 *thunk++ = (BYTE)(hInstance >> 8);
894 *thunk++ = 0xea; /* ljmp func */
895 *(DWORD *)thunk = (DWORD)func;
Alexandre Julliard18f92e71996-07-17 20:02:21 +0000896 return (FARPROC16)thunkaddr;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000897}
898
899
900/***********************************************************************
Alexandre Julliard3051b641996-07-05 17:14:13 +0000901 * FreeProcInstance16 (KERNEL.52)
Alexandre Julliard594997c1995-04-30 10:05:20 +0000902 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000903void WINAPI FreeProcInstance16( FARPROC16 func )
Alexandre Julliard594997c1995-04-30 10:05:20 +0000904{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000905 TRACE(task, "(%08lx)\n", (DWORD)func );
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000906 TASK_FreeThunk( hCurrentTask, (SEGPTR)func );
Alexandre Julliard58199531994-04-21 01:20:00 +0000907}
908
909
910/**********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +0000911 * GetCodeHandle (KERNEL.93)
Alexandre Julliard58199531994-04-21 01:20:00 +0000912 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000913HANDLE16 WINAPI GetCodeHandle( FARPROC16 proc )
Alexandre Julliard58199531994-04-21 01:20:00 +0000914{
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000915 HANDLE16 handle;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000916 BYTE *thunk = (BYTE *)PTR_SEG_TO_LIN( proc );
917
918 /* Return the code segment containing 'proc'. */
919 /* Not sure if this is really correct (shouldn't matter that much). */
920
921 /* Check if it is really a thunk */
922 if ((thunk[0] == 0xb8) && (thunk[3] == 0xea))
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000923 handle = GlobalHandle16( thunk[6] + (thunk[7] << 8) );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000924 else
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000925 handle = GlobalHandle16( HIWORD(proc) );
Alexandre Julliard594997c1995-04-30 10:05:20 +0000926
Alexandre Julliard594997c1995-04-30 10:05:20 +0000927 return handle;
Alexandre Julliard58199531994-04-21 01:20:00 +0000928}
929
Alexandre Julliard594997c1995-04-30 10:05:20 +0000930
Alexandre Julliarde658d821997-11-30 17:45:40 +0000931/**********************************************************************
932 * DefineHandleTable16 (KERNEL.94)
933 */
934BOOL16 WINAPI DefineHandleTable16( WORD wOffset )
935{
936 return TRUE; /* FIXME */
937}
938
939
Alexandre Julliard594997c1995-04-30 10:05:20 +0000940/***********************************************************************
941 * SetTaskQueue (KERNEL.34)
942 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000943HQUEUE16 WINAPI SetTaskQueue( HTASK16 hTask, HQUEUE16 hQueue )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000944{
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000945 HQUEUE16 hPrev;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000946 TDB *pTask;
947
948 if (!hTask) hTask = hCurrentTask;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000949 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000950
Alexandre Julliard594997c1995-04-30 10:05:20 +0000951 hPrev = pTask->hQueue;
952 pTask->hQueue = hQueue;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000953
954 TIMER_SwitchQueue( hPrev, hQueue );
955
Alexandre Julliard594997c1995-04-30 10:05:20 +0000956 return hPrev;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000957}
958
Alexandre Julliard594997c1995-04-30 10:05:20 +0000959
960/***********************************************************************
961 * GetTaskQueue (KERNEL.35)
962 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000963HQUEUE16 WINAPI GetTaskQueue( HTASK16 hTask )
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000964{
Alexandre Julliard594997c1995-04-30 10:05:20 +0000965 TDB *pTask;
966
967 if (!hTask) hTask = hCurrentTask;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000968 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +0000969 return pTask->hQueue;
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +0000970}
971
Alexandre Julliard594997c1995-04-30 10:05:20 +0000972
973/***********************************************************************
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000974 * SwitchStackTo (KERNEL.108)
975 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000976void WINAPI SwitchStackTo( WORD seg, WORD ptr, WORD top )
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000977{
978 TDB *pTask;
979 STACK16FRAME *oldFrame, *newFrame;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000980 INSTANCEDATA *pData;
981 UINT16 copySize;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000982
983 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000984 if (!(pData = (INSTANCEDATA *)GlobalLock16( seg ))) return;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000985 TRACE(task, "old=%04x:%04x new=%04x:%04x\n",
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000986 SELECTOROF( pTask->thdb->cur_stack ),
987 OFFSETOF( pTask->thdb->cur_stack ), seg, ptr );
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000988
Alexandre Julliardac9c9b01996-07-28 18:50:11 +0000989 /* Save the old stack */
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000990
Alexandre Julliarda845b881998-06-01 10:44:35 +0000991 oldFrame = THREAD_STACK16( pTask->thdb );
992 /* pop frame + args and push bp */
993 pData->old_ss_sp = pTask->thdb->cur_stack - sizeof(STACK16FRAME)
994 - 2 * sizeof(WORD);
995 *(WORD *)PTR_SEG_TO_LIN(pData->old_ss_sp) = oldFrame->bp;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000996 pData->stacktop = top;
997 pData->stackmin = ptr;
998 pData->stackbottom = ptr;
999
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001000 /* Switch to the new stack */
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001001
Alexandre Julliard17216f51997-10-12 16:30:17 +00001002 /* Note: we need to take the 3 arguments into account; otherwise,
1003 * the stack will underflow upon return from this function.
1004 */
Alexandre Julliarda845b881998-06-01 10:44:35 +00001005 copySize = oldFrame->bp - OFFSETOF(pData->old_ss_sp);
1006 copySize += 3 * sizeof(WORD) + sizeof(STACK16FRAME);
1007 pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( seg, ptr - copySize );
1008 newFrame = THREAD_STACK16( pTask->thdb );
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001009
1010 /* Copy the stack frame and the local variables to the new stack */
1011
Alexandre Julliarda845b881998-06-01 10:44:35 +00001012 memmove( newFrame, oldFrame, copySize );
1013 newFrame->bp = ptr;
1014 *(WORD *)PTR_SEG_OFF_TO_LIN( seg, ptr ) = 0; /* clear previous bp */
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001015}
1016
1017
1018/***********************************************************************
1019 * SwitchStackBack (KERNEL.109)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001020 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001021void WINAPI SwitchStackBack( CONTEXT *context )
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001022{
1023 TDB *pTask;
1024 STACK16FRAME *oldFrame, *newFrame;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001025 INSTANCEDATA *pData;
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001026
1027 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001028 if (!(pData = (INSTANCEDATA *)GlobalLock16(SELECTOROF(pTask->thdb->cur_stack))))
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001029 return;
1030 if (!pData->old_ss_sp)
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001031 {
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001032 WARN( task, "No previous SwitchStackTo\n" );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001033 return;
1034 }
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001035 TRACE(task, "restoring stack %04x:%04x\n",
1036 SELECTOROF(pData->old_ss_sp), OFFSETOF(pData->old_ss_sp) );
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001037
Alexandre Julliarda845b881998-06-01 10:44:35 +00001038 oldFrame = THREAD_STACK16( pTask->thdb );
1039
1040 /* Pop bp from the previous stack */
1041
1042 BP_reg(context) = *(WORD *)PTR_SEG_TO_LIN(pData->old_ss_sp);
1043 pData->old_ss_sp += sizeof(WORD);
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001044
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001045 /* Switch back to the old stack */
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001046
Alexandre Julliarda845b881998-06-01 10:44:35 +00001047 pTask->thdb->cur_stack = pData->old_ss_sp - sizeof(STACK16FRAME);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001048 SS_reg(context) = SELECTOROF(pData->old_ss_sp);
Alexandre Julliarda845b881998-06-01 10:44:35 +00001049 ESP_reg(context) = OFFSETOF(pData->old_ss_sp) - sizeof(DWORD); /*ret addr*/
Alexandre Julliardd37eb361997-07-20 16:23:21 +00001050 pData->old_ss_sp = 0;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001051
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001052 /* Build a stack frame for the return */
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001053
Alexandre Julliarda845b881998-06-01 10:44:35 +00001054 newFrame = THREAD_STACK16( pTask->thdb );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001055 newFrame->frame32 = oldFrame->frame32;
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001056 if (TRACE_ON(relay))
Alexandre Julliard3db94ef1997-09-28 17:43:24 +00001057 {
1058 newFrame->entry_ip = oldFrame->entry_ip;
1059 newFrame->entry_cs = oldFrame->entry_cs;
1060 }
Alexandre Julliardac9c9b01996-07-28 18:50:11 +00001061}
1062
1063
1064/***********************************************************************
Alexandre Julliardade697e1995-11-26 13:59:11 +00001065 * GetTaskQueueDS (KERNEL.118)
1066 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001067void WINAPI GetTaskQueueDS( CONTEXT *context )
Alexandre Julliardade697e1995-11-26 13:59:11 +00001068{
Alexandre Julliardca22b331996-07-12 19:02:39 +00001069 DS_reg(context) = GlobalHandleToSel( GetTaskQueue(0) );
Alexandre Julliardade697e1995-11-26 13:59:11 +00001070}
Alexandre Julliardade697e1995-11-26 13:59:11 +00001071
1072
1073/***********************************************************************
1074 * GetTaskQueueES (KERNEL.119)
1075 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001076void WINAPI GetTaskQueueES( CONTEXT *context )
Alexandre Julliardade697e1995-11-26 13:59:11 +00001077{
Alexandre Julliardca22b331996-07-12 19:02:39 +00001078 ES_reg(context) = GlobalHandleToSel( GetTaskQueue(0) );
Alexandre Julliardade697e1995-11-26 13:59:11 +00001079}
Alexandre Julliardade697e1995-11-26 13:59:11 +00001080
1081
1082/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +00001083 * GetCurrentTask (KERNEL.36)
1084 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001085HTASK16 WINAPI GetCurrentTask(void)
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001086{
Alexandre Julliardaf0bae51995-10-03 17:06:08 +00001087 return hCurrentTask;
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001088}
1089
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001090DWORD WINAPI WIN16_GetCurrentTask(void)
Alexandre Julliard2d93d001996-05-21 15:01:41 +00001091{
1092 /* This is the version used by relay code; the first task is */
1093 /* returned in the high word of the result */
Alexandre Julliard594997c1995-04-30 10:05:20 +00001094 return MAKELONG( hCurrentTask, hFirstTask );
1095}
1096
1097
1098/***********************************************************************
1099 * GetCurrentPDB (KERNEL.37)
1100 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001101HANDLE16 WINAPI GetCurrentPDB(void)
Alexandre Julliard594997c1995-04-30 10:05:20 +00001102{
1103 TDB *pTask;
1104
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001105 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001106 return pTask->hPDB;
1107}
1108
1109
1110/***********************************************************************
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001111 * GetInstanceData (KERNEL.54)
1112 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001113INT16 WINAPI GetInstanceData( HINSTANCE16 instance, WORD buffer, INT16 len )
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001114{
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001115 char *ptr = (char *)GlobalLock16( instance );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001116 if (!ptr || !len) return 0;
1117 if ((int)buffer + len >= 0x10000) len = 0x10000 - buffer;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001118 memcpy( (char *)GlobalLock16(CURRENT_DS) + buffer, ptr + buffer, len );
Alexandre Julliarda2f2e011995-06-06 16:40:35 +00001119 return len;
1120}
1121
1122
1123/***********************************************************************
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001124 * GetExeVersion (KERNEL.105)
1125 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001126WORD WINAPI GetExeVersion(void)
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001127{
1128 TDB *pTask;
1129
1130 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
1131 return pTask->version;
1132}
1133
1134
1135/***********************************************************************
Alexandre Julliard349a9531997-02-02 19:01:52 +00001136 * SetErrorMode16 (KERNEL.107)
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001137 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001138UINT16 WINAPI SetErrorMode16( UINT16 mode )
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001139{
1140 TDB *pTask;
Alexandre Julliard349a9531997-02-02 19:01:52 +00001141 UINT16 oldMode;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001142
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001143 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001144 oldMode = pTask->error_mode;
1145 pTask->error_mode = mode;
Alexandre Julliard349a9531997-02-02 19:01:52 +00001146 pTask->thdb->process->error_mode = mode;
Alexandre Julliard4f8c37b1996-01-14 18:12:01 +00001147 return oldMode;
1148}
1149
1150
1151/***********************************************************************
Alexandre Julliard349a9531997-02-02 19:01:52 +00001152 * SetErrorMode32 (KERNEL32.486)
1153 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001154UINT32 WINAPI SetErrorMode32( UINT32 mode )
Alexandre Julliard349a9531997-02-02 19:01:52 +00001155{
1156 return SetErrorMode16( (UINT16)mode );
1157}
1158
1159
1160/***********************************************************************
Alexandre Julliard808cb041995-08-17 17:11:36 +00001161 * GetDOSEnvironment (KERNEL.131)
1162 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001163SEGPTR WINAPI GetDOSEnvironment(void)
Alexandre Julliard808cb041995-08-17 17:11:36 +00001164{
1165 TDB *pTask;
1166
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001167 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001168 return PTR_SEG_OFF_TO_SEGPTR( pTask->pdb.environment, 0 );
Alexandre Julliard808cb041995-08-17 17:11:36 +00001169}
1170
1171
1172/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +00001173 * GetNumTasks (KERNEL.152)
1174 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001175UINT16 WINAPI GetNumTasks(void)
Alexandre Julliard594997c1995-04-30 10:05:20 +00001176{
1177 return nTaskCount;
1178}
1179
1180
1181/***********************************************************************
1182 * GetTaskDS (KERNEL.155)
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001183 *
1184 * Note: this function apparently returns a DWORD with LOWORD == HIWORD.
1185 * I don't think we need to bother with this.
Alexandre Julliard594997c1995-04-30 10:05:20 +00001186 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001187HINSTANCE16 WINAPI GetTaskDS(void)
Alexandre Julliard594997c1995-04-30 10:05:20 +00001188{
1189 TDB *pTask;
1190
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001191 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001192 return pTask->hInstance;
1193}
1194
1195
1196/***********************************************************************
1197 * IsTask (KERNEL.320)
1198 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001199BOOL16 WINAPI IsTask( HTASK16 hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001200{
1201 TDB *pTask;
1202
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001203 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return FALSE;
1204 if (GlobalSize16( hTask ) < sizeof(TDB)) return FALSE;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001205 return (pTask->magic == TDB_MAGIC);
1206}
1207
1208
1209/***********************************************************************
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001210 * SetTaskSignalProc (KERNEL.38)
Alexandre Julliard77b99181997-09-14 17:17:23 +00001211 *
1212 * Real 16-bit interface is provided by the THUNK_SetTaskSignalProc.
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001213 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001214FARPROC16 WINAPI SetTaskSignalProc( HTASK16 hTask, FARPROC16 proc )
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001215{
1216 TDB *pTask;
1217 FARPROC16 oldProc;
1218
1219 if (!hTask) hTask = hCurrentTask;
1220 if (!(pTask = (TDB *)GlobalLock16( hTask ))) return NULL;
Alexandre Julliard77b99181997-09-14 17:17:23 +00001221 oldProc = (FARPROC16)pTask->userhandler;
1222 pTask->userhandler = (USERSIGNALPROC)proc;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001223 return oldProc;
1224}
1225
1226
1227/***********************************************************************
1228 * SetSigHandler (KERNEL.140)
1229 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001230WORD WINAPI SetSigHandler( FARPROC16 newhandler, FARPROC16* oldhandler,
1231 UINT16 *oldmode, UINT16 newmode, UINT16 flag )
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001232{
Alexandre Julliard54c27111998-03-29 19:44:57 +00001233 FIXME(task,"(%p,%p,%p,%d,%d), unimplemented.\n",
1234 newhandler,oldhandler,oldmode,newmode,flag );
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001235
1236 if (flag != 1) return 0;
1237 if (!newmode) newhandler = NULL; /* Default handler */
1238 if (newmode != 4)
1239 {
1240 TDB *pTask;
1241
1242 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return 0;
1243 if (oldmode) *oldmode = pTask->signal_flags;
1244 pTask->signal_flags = newmode;
1245 if (oldhandler) *oldhandler = pTask->sighandler;
1246 pTask->sighandler = newhandler;
1247 }
1248 return 0;
1249}
1250
1251
1252/***********************************************************************
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00001253 * GlobalNotify (KERNEL.154)
1254 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001255VOID WINAPI GlobalNotify( FARPROC16 proc )
Alexandre Julliardbf9130a1996-10-13 17:45:47 +00001256{
1257 TDB *pTask;
1258
1259 if (!(pTask = (TDB *)GlobalLock16( hCurrentTask ))) return;
1260 pTask->discardhandler = proc;
1261}
1262
1263
1264/***********************************************************************
Alexandre Julliard594997c1995-04-30 10:05:20 +00001265 * GetExePtr (KERNEL.133)
1266 */
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001267static HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001268{
1269 char *ptr;
Alexandre Julliard18f92e71996-07-17 20:02:21 +00001270 HANDLE16 owner;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001271
1272 /* Check for module handle */
1273
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001274 if (!(ptr = GlobalLock16( handle ))) return 0;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001275 if (((NE_MODULE *)ptr)->magic == IMAGE_OS2_SIGNATURE) return handle;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001276
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001277 /* Search for this handle inside all tasks */
1278
1279 *hTask = hFirstTask;
1280 while (*hTask)
1281 {
1282 TDB *pTask = (TDB *)GlobalLock16( *hTask );
1283 if ((*hTask == handle) ||
1284 (pTask->hInstance == handle) ||
1285 (pTask->hQueue == handle) ||
1286 (pTask->hPDB == handle)) return pTask->hModule;
1287 *hTask = pTask->hNext;
1288 }
1289
Alexandre Julliard594997c1995-04-30 10:05:20 +00001290 /* Check the owner for module handle */
1291
1292 owner = FarGetOwner( handle );
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001293 if (!(ptr = GlobalLock16( owner ))) return 0;
Alexandre Julliard23946ad1997-06-16 17:43:53 +00001294 if (((NE_MODULE *)ptr)->magic == IMAGE_OS2_SIGNATURE) return owner;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001295
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001296 /* Search for the owner inside all tasks */
Alexandre Julliard594997c1995-04-30 10:05:20 +00001297
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001298 *hTask = hFirstTask;
1299 while (*hTask)
Alexandre Julliard594997c1995-04-30 10:05:20 +00001300 {
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001301 TDB *pTask = (TDB *)GlobalLock16( *hTask );
1302 if ((*hTask == owner) ||
Alexandre Julliard594997c1995-04-30 10:05:20 +00001303 (pTask->hInstance == owner) ||
1304 (pTask->hQueue == owner) ||
1305 (pTask->hPDB == owner)) return pTask->hModule;
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001306 *hTask = pTask->hNext;
Alexandre Julliard594997c1995-04-30 10:05:20 +00001307 }
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001308
Alexandre Julliard594997c1995-04-30 10:05:20 +00001309 return 0;
1310}
1311
Alexandre Julliardebfc0fe1998-06-28 18:40:26 +00001312HMODULE16 WINAPI GetExePtr( HANDLE16 handle )
1313{
1314 HTASK16 dummy;
1315 return GetExePtrHelper( handle, &dummy );
1316}
1317
1318void WINAPI WIN16_GetExePtr( CONTEXT *context )
1319{
1320 WORD *stack = PTR_SEG_OFF_TO_LIN(SS_reg(context), SP_reg(context));
1321 HANDLE16 handle = (HANDLE16)stack[2];
1322 HTASK16 hTask = 0;
1323 HMODULE16 hModule;
1324
1325 hModule = GetExePtrHelper( handle, &hTask );
1326
1327 AX_reg(context) = CX_reg(context) = hModule;
1328 if (hTask) ES_reg(context) = hTask;
1329}
1330
Alexandre Julliard594997c1995-04-30 10:05:20 +00001331/***********************************************************************
1332 * TaskFirst (TOOLHELP.63)
1333 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001334BOOL16 WINAPI TaskFirst( TASKENTRY *lpte )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001335{
1336 lpte->hNext = hFirstTask;
1337 return TaskNext( lpte );
1338}
1339
1340
1341/***********************************************************************
1342 * TaskNext (TOOLHELP.64)
1343 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001344BOOL16 WINAPI TaskNext( TASKENTRY *lpte )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001345{
1346 TDB *pTask;
1347 INSTANCEDATA *pInstData;
1348
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001349 TRACE(toolhelp, "(%p): task=%04x\n", lpte, lpte->hNext );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001350 if (!lpte->hNext) return FALSE;
Alexandre Julliard1285c2f1996-05-06 16:06:24 +00001351 pTask = (TDB *)GlobalLock16( lpte->hNext );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001352 if (!pTask || pTask->magic != TDB_MAGIC) return FALSE;
1353 pInstData = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( pTask->hInstance, 0 );
1354 lpte->hTask = lpte->hNext;
1355 lpte->hTaskParent = pTask->hParent;
1356 lpte->hInst = pTask->hInstance;
1357 lpte->hModule = pTask->hModule;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001358 lpte->wSS = SELECTOROF( pTask->thdb->cur_stack );
1359 lpte->wSP = OFFSETOF( pTask->thdb->cur_stack );
Alexandre Julliard594997c1995-04-30 10:05:20 +00001360 lpte->wStackTop = pInstData->stacktop;
1361 lpte->wStackMinimum = pInstData->stackmin;
1362 lpte->wStackBottom = pInstData->stackbottom;
1363 lpte->wcEvents = pTask->nEvents;
1364 lpte->hQueue = pTask->hQueue;
1365 strncpy( lpte->szModule, pTask->module_name, 8 );
1366 lpte->szModule[8] = '\0';
1367 lpte->wPSPOffset = 0x100; /*??*/
1368 lpte->hNext = pTask->hNext;
1369 return TRUE;
1370}
1371
1372
1373/***********************************************************************
1374 * TaskFindHandle (TOOLHELP.65)
1375 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001376BOOL16 WINAPI TaskFindHandle( TASKENTRY *lpte, HTASK16 hTask )
Alexandre Julliard594997c1995-04-30 10:05:20 +00001377{
1378 lpte->hNext = hTask;
1379 return TaskNext( lpte );
Alexandre Julliard3f2abfa1994-08-16 15:43:11 +00001380}
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001381
1382
1383/***********************************************************************
Alexandre Julliard21979011997-03-05 08:22:35 +00001384 * GetAppCompatFlags16 (KERNEL.354)
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001385 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001386DWORD WINAPI GetAppCompatFlags16( HTASK16 hTask )
Alexandre Julliard21979011997-03-05 08:22:35 +00001387{
1388 return GetAppCompatFlags32( hTask );
1389}
1390
1391
1392/***********************************************************************
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001393 * GetAppCompatFlags32 (USER32.206)
Alexandre Julliard21979011997-03-05 08:22:35 +00001394 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +00001395DWORD WINAPI GetAppCompatFlags32( HTASK32 hTask )
Alexandre Julliard339eefc1996-06-23 14:56:20 +00001396{
1397 TDB *pTask;
1398
1399 if (!hTask) hTask = GetCurrentTask();
1400 if (!(pTask=(TDB *)GlobalLock16( (HTASK16)hTask ))) return 0;
1401 if (GlobalSize16(hTask) < sizeof(TDB)) return 0;
1402 return pTask->compat_flags;
1403}