4 * Copyright 1995 Alexandre Julliard
20 #include "selectors.h"
26 /* Min. number of thunks allocated when creating a new segment */
29 /* 32-bit stack size for each task */
30 /* Must not be greater than 64k, or MAKE_SEGPTR won't work */
31 #define STACK32_SIZE 0x10000
34 static HTASK hFirstTask
= 0;
35 static HTASK hCurrentTask
= 0;
36 static HTASK hTaskToKill
= 0;
37 static HTASK hLockedTask
= 0;
38 static WORD nTaskCount
= 0;
40 /* TASK_Reschedule() 16-bit entry point */
41 static FARPROC TASK_RescheduleProc
;
43 #define TASK_SCHEDULE() CallTo16_word_(TASK_RescheduleProc,0)
46 /***********************************************************************
51 TASK_RescheduleProc
= (FARPROC
)GetWndProcEntry16( "TASK_Reschedule" );
56 /***********************************************************************
59 static void TASK_LinkTask( HTASK hTask
)
64 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return;
65 prevTask
= &hFirstTask
;
68 TDB
*prevTaskPtr
= (TDB
*)GlobalLock( *prevTask
);
69 if (prevTaskPtr
->priority
>= pTask
->priority
) break;
70 prevTask
= &prevTaskPtr
->hNext
;
72 pTask
->hNext
= *prevTask
;
78 /***********************************************************************
81 static void TASK_UnlinkTask( HTASK hTask
)
86 prevTask
= &hFirstTask
;
87 while (*prevTask
&& (*prevTask
!= hTask
))
89 pTask
= (TDB
*)GlobalLock( *prevTask
);
90 prevTask
= &pTask
->hNext
;
94 pTask
= (TDB
*)GlobalLock( *prevTask
);
95 *prevTask
= pTask
->hNext
;
102 /***********************************************************************
105 * Create a thunk free-list in segment 'handle', starting from offset 'offset'
106 * and containing 'count' entries.
108 static void TASK_CreateThunks( HGLOBAL handle
, WORD offset
, WORD count
)
114 pThunk
= (THUNKS
*)((BYTE
*)GlobalLock( handle
) + offset
);
116 pThunk
->magic
= THUNK_MAGIC
;
117 pThunk
->free
= (int)&pThunk
->thunks
- (int)pThunk
;
119 for (i
= 0; i
< count
-1; i
++)
121 free
+= 8; /* Offset of next thunk */
122 pThunk
->thunks
[4*i
] = free
;
124 pThunk
->thunks
[4*i
] = 0; /* Last thunk */
128 /***********************************************************************
131 * Allocate a thunk for MakeProcInstance().
133 static SEGPTR
TASK_AllocThunk( HTASK hTask
)
139 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return 0;
140 sel
= pTask
->hCSAlias
;
141 pThunk
= &pTask
->thunks
;
142 base
= (int)pThunk
- (int)pTask
;
143 while (!pThunk
->free
)
146 if (!sel
) /* Allocate a new segment */
148 sel
= GLOBAL_Alloc( GMEM_FIXED
, sizeof(THUNKS
) + (MIN_THUNKS
-1)*8,
149 pTask
->hPDB
, TRUE
, FALSE
, FALSE
);
150 if (!sel
) return (SEGPTR
)0;
151 TASK_CreateThunks( sel
, 0, MIN_THUNKS
);
154 pThunk
= (THUNKS
*)GlobalLock( sel
);
157 base
+= pThunk
->free
;
158 pThunk
->free
= *(WORD
*)((BYTE
*)pThunk
+ pThunk
->free
);
159 return MAKELONG( base
, sel
);
163 /***********************************************************************
166 * Free a MakeProcInstance() thunk.
168 static BOOL
TASK_FreeThunk( HTASK hTask
, SEGPTR thunk
)
174 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return 0;
175 sel
= pTask
->hCSAlias
;
176 pThunk
= &pTask
->thunks
;
177 base
= (int)pThunk
- (int)pTask
;
178 while (sel
&& (sel
!= HIWORD(thunk
)))
181 pThunk
= (THUNKS
*)GlobalLock( sel
);
184 if (!sel
) return FALSE
;
185 *(WORD
*)((BYTE
*)pThunk
+ LOWORD(thunk
) - base
) = pThunk
->free
;
186 pThunk
->free
= LOWORD(thunk
) - base
;
191 /***********************************************************************
194 * 32-bit entry point for a new task. This function is responsible for
195 * setting up the registers and jumping to the 16-bit entry point.
197 static void TASK_CallToStart(void)
199 int cs_reg
, ds_reg
, ip_reg
;
200 TDB
*pTask
= (TDB
*)GlobalLock( hCurrentTask
);
201 NE_MODULE
*pModule
= (NE_MODULE
*)GlobalLock( pTask
->hModule
);
202 SEGTABLEENTRY
*pSegTable
= NE_SEG_TABLE( pModule
);
204 /* Registers at initialization must be:
206 * bx stack size in bytes
207 * cx heap size in bytes
208 * si previous app instance
209 * di current app instance
211 * es selector to the PSP
212 * ds dgroup of the application
214 * sp top of the stack
217 cs_reg
= pSegTable
[pModule
->cs
- 1].selector
;
218 ip_reg
= pModule
->ip
;
219 ds_reg
= pSegTable
[pModule
->dgroup
- 1].selector
;
220 IF1632_Saved16_ss
= pTask
->ss
;
221 IF1632_Saved16_sp
= pTask
->sp
;
222 dprintf_task( stddeb
, "Starting main program: cs:ip=%04x:%04x ds=%04x ss:sp=%04x:%04x\n",
223 cs_reg
, ip_reg
, ds_reg
,
224 IF1632_Saved16_ss
, IF1632_Saved16_sp
);
226 CallTo16_regs_( (FARPROC
)(cs_reg
<< 16 | ip_reg
), ds_reg
,
227 pTask
->hPDB
/*es*/, 0 /*bp*/, 0 /*ax*/,
228 pModule
->stack_size
/*bx*/, pModule
->heap_size
/*cx*/,
229 0 /*dx*/, 0 /*si*/, ds_reg
/*di*/ );
230 /* This should never return */
231 fprintf( stderr
, "TASK_CallToStart: Main program returned!\n" );
236 /***********************************************************************
239 HTASK
TASK_CreateTask( HMODULE hModule
, HANDLE hInstance
, HANDLE hPrevInstance
,
240 HANDLE hEnvironment
, char *cmdLine
, WORD cmdShow
)
245 SEGTABLEENTRY
*pSegTable
;
247 char *stack16Top
, *stack32Top
;
248 STACK16FRAME
*frame16
;
249 STACK32FRAME
*frame32
;
250 extern DWORD CALL16_RetAddr_word
;
253 if (!(pModule
= (NE_MODULE
*)GlobalLock( hModule
))) return 0;
254 pSegTable
= NE_SEG_TABLE( pModule
);
256 /* Allocate the task structure */
258 hTask
= GLOBAL_Alloc( GMEM_FIXED
| GMEM_ZEROINIT
, sizeof(TDB
),
259 hModule
, FALSE
, FALSE
, FALSE
);
260 if (!hTask
) return 0;
261 pTask
= (TDB
*)GlobalLock( hTask
);
263 /* get current directory */
265 GetModuleFileName( hModule
, filename
, sizeof(filename
) );
266 name
= strrchr(filename
, '\\');
267 if (name
) *(name
+1) = 0;
269 /* Fill the task structure */
271 pTask
->nEvents
= 1; /* So the task can be started */
272 pTask
->hSelf
= hTask
;
274 pTask
->version
= pModule
->expected_version
;
275 pTask
->hInstance
= hInstance
;
276 pTask
->hPrevInstance
= hPrevInstance
;
277 pTask
->hModule
= hModule
;
278 pTask
->hParent
= hCurrentTask
;
279 pTask
->curdrive
= filename
[0] - 'A' + 0x80;
280 pTask
->magic
= TDB_MAGIC
;
281 pTask
->nCmdShow
= cmdShow
;
282 strcpy( pTask
->curdir
, filename
+2 );
284 /* Create the thunks block */
286 TASK_CreateThunks( hTask
, (int)&pTask
->thunks
- (int)pTask
, 7 );
288 /* Copy the module name */
290 name
= MODULE_GetModuleName( hModule
);
291 strncpy( pTask
->module_name
, name
, sizeof(pTask
->module_name
) );
295 pTask
->pdb
.int20
= 0x20cd;
296 pTask
->pdb
.dispatcher
[0] = 0x9a; /* ljmp */
297 *(DWORD
*)&pTask
->pdb
.dispatcher
[1] = MODULE_GetEntryPoint( GetModuleHandle("KERNEL"), 102 ); /* KERNEL.102 is DOS3Call() */
298 pTask
->pdb
.savedint22
= INT_GetHandler( 0x22 );
299 pTask
->pdb
.savedint23
= INT_GetHandler( 0x23 );
300 pTask
->pdb
.savedint24
= INT_GetHandler( 0x24 );
301 pTask
->pdb
.environment
= hEnvironment
;
302 strncpy( pTask
->pdb
.cmdLine
+ 1, cmdLine
, 126 );
303 pTask
->pdb
.cmdLine
[127] = '\0';
304 pTask
->pdb
.cmdLine
[0] = strlen( pTask
->pdb
.cmdLine
+ 1 );
306 /* Get the compatibility flags */
308 pTask
->compat_flags
= GetProfileInt( name
, "Compatibility", 0 );
310 /* Allocate a selector for the PDB */
312 pTask
->hPDB
= GLOBAL_CreateBlock( GMEM_FIXED
, &pTask
->pdb
, sizeof(PDB
),
313 hModule
, FALSE
, FALSE
, FALSE
, NULL
);
315 /* Allocate a code segment alias for the TDB */
317 pTask
->hCSAlias
= GLOBAL_CreateBlock( GMEM_FIXED
, (void *)pTask
,
318 sizeof(TDB
), pTask
->hPDB
, TRUE
,
319 FALSE
, FALSE
, NULL
);
321 /* Set the owner of the environment block */
323 FarSetOwner( pTask
->pdb
.environment
, pTask
->hPDB
);
325 /* Default DTA overwrites command-line */
327 pTask
->dta
= MAKELONG( (int)&pTask
->pdb
.cmdLine
- (int)&pTask
->pdb
,
330 /* Allocate the 32-bit stack */
332 pTask
->hStack32
= GLOBAL_Alloc( GMEM_FIXED
, STACK32_SIZE
, pTask
->hPDB
,
333 FALSE
, FALSE
, FALSE
);
335 /* Create the 32-bit stack frame */
337 *(DWORD
*)GlobalLock(pTask
->hStack32
) = 0xDEADBEEF;
338 stack32Top
= (char*)GlobalLock(pTask
->hStack32
) + STACK32_SIZE
;
339 frame32
= (STACK32FRAME
*)stack32Top
- 1;
340 frame32
->saved_esp
= (DWORD
)stack32Top
;
347 frame32
->retaddr
= (DWORD
)TASK_CallToStart
;
348 frame32
->codeselector
= WINE_CODE_SELECTOR
;
349 pTask
->esp
= (DWORD
)frame32
;
351 /* Create the 16-bit stack frame */
353 pTask
->ss
= hInstance
;
354 pTask
->sp
= ((pModule
->sp
!= 0) ? pModule
->sp
:
355 pSegTable
[pModule
->ss
-1].minsize
+ pModule
->stack_size
) & ~1;
356 stack16Top
= (char *)PTR_SEG_OFF_TO_LIN( pTask
->ss
, pTask
->sp
);
357 frame16
= (STACK16FRAME
*)stack16Top
- 1;
358 frame16
->saved_ss
= pTask
->ss
;
359 frame16
->saved_sp
= pTask
->sp
;
360 frame16
->ds
= frame16
->es
= pTask
->hInstance
;
361 frame16
->entry_point
= 0;
362 frame16
->ordinal_number
= 24; /* WINPROCS.24 is TASK_Reschedule */
363 frame16
->dll_id
= 24; /* WINPROCS */
365 frame16
->ip
= LOWORD( CALL16_RetAddr_word
);
366 frame16
->cs
= HIWORD( CALL16_RetAddr_word
);
367 pTask
->sp
-= sizeof(STACK16FRAME
);
369 /* If there's no 16-bit stack yet, use a part of the new task stack */
370 /* This is only needed to have a stack to switch from on the first */
371 /* call to DirectedYield(). */
373 if (!IF1632_Saved16_ss
)
375 IF1632_Saved16_ss
= pTask
->ss
;
376 IF1632_Saved16_sp
= pTask
->sp
;
379 /* Add a breakpoint at the start of the task */
383 fprintf( stderr
, "Task '%s': ", name
);
384 DEBUG_AddBreakpoint( pSegTable
[pModule
->cs
-1].selector
, pModule
->ip
);
387 /* Add the task to the linked list */
389 TASK_LinkTask( hTask
);
391 dprintf_task( stddeb
, "CreateTask: module='%s' cmdline='%s' task=%04x\n",
392 name
, cmdLine
, hTask
);
398 /***********************************************************************
401 void TASK_DeleteTask( HTASK hTask
)
405 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return;
407 /* Free the task module */
409 FreeModule( pTask
->hModule
);
411 /* Free all memory used by this task (including the 32-bit stack, */
412 /* the environment block and the thunk segments). */
414 GlobalFreeAll( pTask
->hPDB
);
416 /* Free the selector aliases */
418 GLOBAL_FreeBlock( pTask
->hCSAlias
);
419 GLOBAL_FreeBlock( pTask
->hPDB
);
421 /* Free the task structure itself */
427 /***********************************************************************
428 * TASK_KillCurrentTask
430 * Kill the currently running task. As it's not possible to kill the
431 * current task like this, it is simply marked for destruction, and will
432 * be killed when either TASK_Reschedule or this function is called again
433 * in the context of another task.
435 void TASK_KillCurrentTask( int exitCode
)
437 if (hTaskToKill
&& (hTaskToKill
!= hCurrentTask
))
439 /* If another task is already marked for destruction, */
440 /* we call kill it now, as we are in another context. */
441 TASK_DeleteTask( hTaskToKill
);
446 dprintf_task( stddeb
, "Killing the last task, exiting\n" );
450 /* Remove the task from the list to be sure we never switch back to it */
451 TASK_UnlinkTask( hCurrentTask
);
453 hTaskToKill
= hCurrentTask
;
456 /* We never return from Yield() */
460 /***********************************************************************
463 * This is where all the magic of task-switching happens!
465 * This function should only be called via the TASK_SCHEDULE() macro, to make
466 * sure that all the context is saved correctly.
468 void TASK_Reschedule(void)
470 TDB
*pOldTask
= NULL
, *pNewTask
;
474 /* First check if there's a task to kill */
476 if (hTaskToKill
&& (hTaskToKill
!= hCurrentTask
))
477 TASK_DeleteTask( hTaskToKill
);
479 /* If current task is locked, simply return */
481 if (hLockedTask
) return;
483 /* Find a task to yield to */
485 pOldTask
= (TDB
*)GlobalLock( hCurrentTask
);
486 if (pOldTask
&& pOldTask
->hYieldTo
)
488 /* If a task is stored in hYieldTo of the current task (put there */
489 /* by DirectedYield), yield to it only if it has events pending. */
490 hTask
= pOldTask
->hYieldTo
;
491 if (!(pNewTask
= (TDB
*)GlobalLock( hTask
)) || !pNewTask
->nEvents
)
500 pNewTask
= (TDB
*)GlobalLock( hTask
);
501 if (pNewTask
->nEvents
&& (hTask
!= hCurrentTask
)) break;
502 hTask
= pNewTask
->hNext
;
506 /* If there's a task to kill, switch to any other task, */
507 /* even if it doesn't have events pending. */
509 if (!hTask
&& hTaskToKill
) hTask
= hFirstTask
;
511 if (!hTask
) return; /* Do nothing */
513 pNewTask
= (TDB
*)GlobalLock( hTask
);
514 dprintf_task( stddeb
, "Switching to task %04x (%.8s)\n",
515 hTask
, pNewTask
->module_name
);
517 /* Save the stacks of the previous task (if any) */
521 pOldTask
->ss
= IF1632_Saved16_ss
;
522 pOldTask
->sp
= IF1632_Saved16_sp
;
523 pOldTask
->esp
= IF1632_Saved32_esp
;
525 else IF1632_Original32_esp
= IF1632_Saved32_esp
;
527 /* Make the task the last in the linked list (round-robin scheduling) */
529 pNewTask
->priority
++;
530 TASK_UnlinkTask( hTask
);
531 TASK_LinkTask( hTask
);
532 pNewTask
->priority
--;
534 /* Switch to the new stack */
536 hCurrentTask
= hTask
;
537 IF1632_Saved16_ss
= pNewTask
->ss
;
538 IF1632_Saved16_sp
= pNewTask
->sp
;
539 IF1632_Saved32_esp
= pNewTask
->esp
;
540 IF1632_Stack32_base
= WIN16_GlobalLock( pNewTask
->hStack32
);
544 /***********************************************************************
545 * InitTask (KERNEL.91)
547 void InitTask( struct sigcontext_struct context
)
549 static int firstTask
= 1;
552 SEGTABLEENTRY
*pSegTable
;
553 INSTANCEDATA
*pinstance
;
554 LONG stacklow
, stackhi
;
557 if (!(pTask
= (TDB
*)GlobalLock( hCurrentTask
))) return;
558 if (!(pModule
= (NE_MODULE
*)GlobalLock( pTask
->hModule
))) return;
562 extern BOOL
WIDGETS_Init(void);
563 extern BOOL
WIN_CreateDesktopWindow(void);
565 /* Perform global initialisations that need a task context */
567 /* Initialize built-in window classes */
568 if (!WIDGETS_Init()) return;
570 /* Create desktop window */
571 if (!WIN_CreateDesktopWindow()) return;
576 NE_InitializeDLLs( pTask
->hModule
);
578 /* Registers on return are:
579 * ax 1 if OK, 0 on error
580 * cx stack limit in bytes
581 * dx cmdShow parameter
582 * si instance handle of the previous instance
583 * di instance handle of the new task
584 * es:bx pointer to command-line inside PSP
587 context
.sc_ebx
= 0x81;
588 context
.sc_ecx
= pModule
->stack_size
;
589 context
.sc_edx
= pTask
->nCmdShow
;
590 context
.sc_esi
= pTask
->hPrevInstance
;
591 context
.sc_edi
= pTask
->hInstance
;
592 context
.sc_es
= pTask
->hPDB
;
594 /* Initialize the local heap */
595 if ( pModule
->heap_size
)
597 LocalInit( pTask
->hInstance
, 0, pModule
->heap_size
);
601 /* Initialize the INSTANCEDATA structure */
602 pSegTable
= NE_SEG_TABLE( pModule
);
603 stacklow
= pSegTable
[pModule
->ss
- 1].minsize
;
604 stackhi
= stacklow
+ pModule
->stack_size
;
605 if (stackhi
> 0xffff) stackhi
= 0xffff;
606 pinstance
= (INSTANCEDATA
*)PTR_SEG_OFF_TO_LIN(CURRENT_DS
, 0);
607 pinstance
->stackbottom
= stackhi
; /* yup, that's right. Confused me too. */
608 pinstance
->stacktop
= stacklow
;
609 pinstance
->stackmin
= IF1632_Saved16_sp
;
613 /***********************************************************************
614 * WaitEvent (KERNEL.30)
616 BOOL
WaitEvent( HTASK hTask
)
620 if (!hTask
) hTask
= hCurrentTask
;
621 pTask
= (TDB
*)GlobalLock( hTask
);
622 if (pTask
->nEvents
> 0)
628 /* When we get back here, we have an event (or the task is the only one) */
629 if (pTask
->nEvents
> 0) pTask
->nEvents
--;
634 /***********************************************************************
635 * PostEvent (KERNEL.31)
637 void PostEvent( HTASK hTask
)
641 if (!hTask
) hTask
= hCurrentTask
;
642 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return;
647 /***********************************************************************
648 * SetPriority (KERNEL.32)
650 void SetPriority( HTASK hTask
, int delta
)
655 if (!hTask
) hTask
= hCurrentTask
;
656 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return;
657 newpriority
= pTask
->priority
+ delta
;
658 if (newpriority
< -32) newpriority
= -32;
659 else if (newpriority
> 15) newpriority
= 15;
661 pTask
->priority
= newpriority
+ 1;
662 TASK_UnlinkTask( hTask
);
663 TASK_LinkTask( hTask
);
668 /***********************************************************************
669 * LockCurrentTask (KERNEL.33)
671 HTASK
LockCurrentTask( BOOL bLock
)
673 if (bLock
) hLockedTask
= hCurrentTask
;
674 else hLockedTask
= 0;
679 /***********************************************************************
680 * IsTaskLocked (KERNEL.122)
682 WORD
IsTaskLocked(void)
688 /***********************************************************************
689 * OldYield (KERNEL.117)
695 pCurTask
= (TDB
*)GlobalLock( hCurrentTask
);
696 if (pCurTask
) pCurTask
->nEvents
++; /* Make sure we get back here */
698 if (pCurTask
) pCurTask
->nEvents
--;
702 /***********************************************************************
703 * DirectedYield (KERNEL.150)
705 void DirectedYield( HTASK hTask
)
709 if ((pCurTask
= (TDB
*)GlobalLock( hCurrentTask
)) != NULL
)
710 pCurTask
->hYieldTo
= hTask
;
716 /***********************************************************************
725 /***********************************************************************
726 * MakeProcInstance (KERNEL.51)
728 FARPROC
MakeProcInstance( FARPROC func
, HANDLE hInstance
)
733 thunkaddr
= TASK_AllocThunk( hCurrentTask
);
734 if (!thunkaddr
) return (FARPROC
)0;
735 thunk
= PTR_SEG_TO_LIN( thunkaddr
);
737 dprintf_task( stddeb
, "MakeProcInstance(%08lx,%04x): got thunk %08lx\n",
738 (SEGPTR
)func
, hInstance
, (SEGPTR
)thunkaddr
);
740 *thunk
++ = 0xb8; /* movw instance, %ax */
741 *thunk
++ = (BYTE
)(hInstance
& 0xff);
742 *thunk
++ = (BYTE
)(hInstance
>> 8);
743 *thunk
++ = 0xea; /* ljmp func */
744 *(DWORD
*)thunk
= (DWORD
)func
;
745 return (FARPROC
)thunkaddr
;
749 /***********************************************************************
750 * FreeProcInstance (KERNEL.52)
752 void FreeProcInstance( FARPROC func
)
754 dprintf_task( stddeb
, "FreeProcInstance(%08lx)\n", (SEGPTR
)func
);
755 TASK_FreeThunk( hCurrentTask
, (SEGPTR
)func
);
759 /**********************************************************************
760 * GetCodeHandle (KERNEL.93)
762 HANDLE
GetCodeHandle( FARPROC proc
)
765 BYTE
*thunk
= (BYTE
*)PTR_SEG_TO_LIN( proc
);
767 /* Return the code segment containing 'proc'. */
768 /* Not sure if this is really correct (shouldn't matter that much). */
770 /* Check if it is really a thunk */
771 if ((thunk
[0] == 0xb8) && (thunk
[3] == 0xea))
772 handle
= GlobalHandle( thunk
[6] + (thunk
[7] << 8) );
774 handle
= GlobalHandle( HIWORD(proc
) );
776 printf( "STUB: GetCodeHandle(%08lx) returning %04x\n",
777 (DWORD
)proc
, handle
);
782 /***********************************************************************
783 * SetTaskQueue (KERNEL.34)
785 HGLOBAL
SetTaskQueue( HANDLE hTask
, HGLOBAL hQueue
)
790 if (!hTask
) hTask
= hCurrentTask
;
791 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return 0;
792 hPrev
= pTask
->hQueue
;
793 pTask
->hQueue
= hQueue
;
798 /***********************************************************************
799 * GetTaskQueue (KERNEL.35)
801 HGLOBAL
GetTaskQueue( HANDLE hTask
)
805 if (!hTask
) hTask
= hCurrentTask
;
806 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return 0;
807 return pTask
->hQueue
;
811 /***********************************************************************
812 * GetCurrentTask (KERNEL.36)
814 HTASK
GetCurrentTask(void)
816 /* Undocumented: first task is returned in high word */
817 return MAKELONG( hCurrentTask
, hFirstTask
);
821 /***********************************************************************
822 * GetCurrentPDB (KERNEL.37)
824 WORD
GetCurrentPDB(void)
828 if (!(pTask
= (TDB
*)GlobalLock( hCurrentTask
))) return 0;
833 /***********************************************************************
834 * GetInstanceData (KERNEL.54)
836 int GetInstanceData( HANDLE instance
, WORD buffer
, int len
)
838 char *ptr
= (char *)GlobalLock( instance
);
839 if (!ptr
|| !len
) return 0;
840 if ((int)buffer
+ len
>= 0x10000) len
= 0x10000 - buffer
;
841 memcpy( ptr
+ buffer
, (char *)GlobalLock( CURRENT_DS
) + buffer
, len
);
846 /***********************************************************************
847 * GetNumTasks (KERNEL.152)
849 WORD
GetNumTasks(void)
855 /***********************************************************************
856 * GetTaskDS (KERNEL.155)
862 if (!(pTask
= (TDB
*)GlobalLock( hCurrentTask
))) return 0;
863 return pTask
->hInstance
;
867 /***********************************************************************
868 * IsTask (KERNEL.320)
870 BOOL
IsTask( HTASK hTask
)
874 if (!(pTask
= (TDB
*)GlobalLock( hTask
))) return FALSE
;
875 if (GlobalSize( hTask
) < sizeof(TDB
)) return FALSE
;
876 return (pTask
->magic
== TDB_MAGIC
);
880 /***********************************************************************
881 * GetExePtr (KERNEL.133)
883 HMODULE
GetExePtr( HANDLE handle
)
889 /* Check for module handle */
891 if (!(ptr
= GlobalLock( handle
))) return 0;
892 if (((NE_MODULE
*)ptr
)->magic
== NE_SIGNATURE
) return handle
;
894 /* Check the owner for module handle */
896 owner
= FarGetOwner( handle
);
897 if (!(ptr
= GlobalLock( owner
))) return 0;
898 if (((NE_MODULE
*)ptr
)->magic
== NE_SIGNATURE
) return owner
;
900 /* Search for this handle and its owner inside all tasks */
905 TDB
*pTask
= (TDB
*)GlobalLock( hTask
);
906 if ((hTask
== handle
) ||
907 (pTask
->hInstance
== handle
) ||
908 (pTask
->hQueue
== handle
) ||
909 (pTask
->hPDB
== handle
)) return pTask
->hModule
;
910 if ((hTask
== owner
) ||
911 (pTask
->hInstance
== owner
) ||
912 (pTask
->hQueue
== owner
) ||
913 (pTask
->hPDB
== owner
)) return pTask
->hModule
;
914 hTask
= pTask
->hNext
;
920 /***********************************************************************
921 * TaskFirst (TOOLHELP.63)
923 BOOL
TaskFirst( TASKENTRY
*lpte
)
925 lpte
->hNext
= hFirstTask
;
926 return TaskNext( lpte
);
930 /***********************************************************************
931 * TaskNext (TOOLHELP.64)
933 BOOL
TaskNext( TASKENTRY
*lpte
)
936 INSTANCEDATA
*pInstData
;
938 dprintf_toolhelp( stddeb
, "TaskNext(%p): task=%04x\n", lpte
, lpte
->hNext
);
939 if (!lpte
->hNext
) return FALSE
;
940 pTask
= (TDB
*)GlobalLock( lpte
->hNext
);
941 if (!pTask
|| pTask
->magic
!= TDB_MAGIC
) return FALSE
;
942 pInstData
= (INSTANCEDATA
*)PTR_SEG_OFF_TO_LIN( pTask
->hInstance
, 0 );
943 lpte
->hTask
= lpte
->hNext
;
944 lpte
->hTaskParent
= pTask
->hParent
;
945 lpte
->hInst
= pTask
->hInstance
;
946 lpte
->hModule
= pTask
->hModule
;
947 lpte
->wSS
= pTask
->ss
;
948 lpte
->wSP
= pTask
->sp
;
949 lpte
->wStackTop
= pInstData
->stacktop
;
950 lpte
->wStackMinimum
= pInstData
->stackmin
;
951 lpte
->wStackBottom
= pInstData
->stackbottom
;
952 lpte
->wcEvents
= pTask
->nEvents
;
953 lpte
->hQueue
= pTask
->hQueue
;
954 strncpy( lpte
->szModule
, pTask
->module_name
, 8 );
955 lpte
->szModule
[8] = '\0';
956 lpte
->wPSPOffset
= 0x100; /*??*/
957 lpte
->hNext
= pTask
->hNext
;
962 /***********************************************************************
963 * TaskFindHandle (TOOLHELP.65)
965 BOOL
TaskFindHandle( TASKENTRY
*lpte
, HTASK hTask
)
968 return TaskNext( lpte
);