7624e2007a96f12c23f9d80f94cb87d670d7efe3
[reactos.git] / reactos / ntoskrnl / ke / apc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/apc.c
5 * PURPOSE: Possible implementation of APCs
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <string.h>
15 #include <internal/string.h>
16 #include <internal/i386/segment.h>
17 #include <internal/ps.h>
18
19 #define NDEBUG
20 #include <internal/debug.h>
21
22 extern VOID KeApcProlog(VOID);
23
24 /* FUNCTIONS *****************************************************************/
25
26 VOID KeApcProlog2(PKAPC Apc)
27 {
28 Apc->KernelRoutine(Apc,
29 &Apc->NormalRoutine,
30 &Apc->NormalContext,
31 &Apc->SystemArgument2,
32 &Apc->SystemArgument2);
33 PsSuspendThread(CONTAINING_RECORD(Apc->Thread,ETHREAD,Tcb));
34 }
35
36 VOID KeDeliverKernelApc(PKAPC Apc)
37 /*
38 * FUNCTION: Simulates an interrupt on the target thread which will transfer
39 * control to a kernel mode routine
40 */
41 {
42 PKTHREAD TargetThread;
43 PULONG Stack;
44
45 TargetThread = Apc->Thread;
46
47 if (TargetThread == KeGetCurrentThread())
48 {
49 Apc->KernelRoutine(Apc,
50 &Apc->NormalRoutine,
51 &Apc->NormalContext,
52 &Apc->SystemArgument2,
53 &Apc->SystemArgument2);
54 return;
55 }
56
57 if (TargetThread->Context.cs == KERNEL_CS)
58 {
59 TargetThread->Context.esp = TargetThread->Context.esp - 16;
60 Stack = (PULONG)TargetThread->Context.esp;
61 Stack[0] = TargetThread->Context.eax;
62 Stack[1] = TargetThread->Context.eip;
63 Stack[2] = TargetThread->Context.cs;
64 Stack[3] = TargetThread->Context.eflags;
65 TargetThread->Context.eip = (ULONG)KeApcProlog;
66 TargetThread->Context.eax = (ULONG)Apc;
67 }
68 else
69 {
70 TargetThread->Context.esp = TargetThread->Context.esp - 40;
71 Stack = (PULONG)TargetThread->Context.esp;
72 Stack[9] = TargetThread->Context.ss;
73 Stack[8] = TargetThread->Context.esp;
74 Stack[7] = TargetThread->Context.gs;
75 Stack[6] = TargetThread->Context.fs;
76 Stack[5] = TargetThread->Context.ds;
77 Stack[4] = TargetThread->Context.es;
78 Stack[3] = TargetThread->Context.eflags;
79 Stack[2] = TargetThread->Context.cs;
80 Stack[1] = TargetThread->Context.eip;
81 Stack[0] = TargetThread->Context.eax;
82 TargetThread->Context.eip = (ULONG)KeApcProlog;
83 TargetThread->Context.eax = (ULONG)Apc;
84 }
85
86 PsResumeThread(CONTAINING_RECORD(TargetThread,ETHREAD,Tcb));
87 }
88
89 void KeInsertQueueApc(struct _KAPC *Apc, PVOID SystemArgument1,
90 PVOID SystemArgument2, UCHAR Mode)
91 {
92 KIRQL oldlvl;
93
94 DPRINT("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
95 "SystemArgument2 %x, Mode %d)\n",Apc,SystemArgument1,
96 SystemArgument2,Mode);
97
98 KeRaiseIrql(DISPATCH_LEVEL,&oldlvl);
99
100 if (Apc->KernelRoutine != NULL)
101 {
102 KeDeliverKernelApc(Apc);
103 }
104 KeLowerIrql(oldlvl);
105 }
106
107 VOID KeInitializeApc(PKAPC Apc,
108 PKTHREAD Thread,
109 UCHAR StateIndex,
110 PKKERNEL_ROUTINE KernelRoutine,
111 PKRUNDOWN_ROUTINE RundownRoutine,
112 PKNORMAL_ROUTINE NormalRoutine,
113 UCHAR Mode,
114 PVOID Context)
115 {
116 memset(Apc,0,sizeof(KAPC));
117 Apc->Thread = Thread;
118 Apc->ApcListEntry.Flink=NULL;
119 Apc->ApcListEntry.Blink=NULL;
120 Apc->KernelRoutine=KernelRoutine;
121 Apc->RundownRoutine=RundownRoutine;
122 Apc->NormalRoutine=NormalRoutine;
123 Apc->NormalContext=Context;
124 Apc->Inserted=FALSE;
125 Apc->ApcStateIndex=StateIndex;
126 Apc->ApcMode=Mode;
127 }
128
129
130 NTSTATUS STDCALL NtQueueApcThread(HANDLE ThreadHandle,
131 PKNORMAL_ROUTINE ApcRoutine,
132 PVOID NormalContext,
133 PVOID SystemArgument1,
134 PVOID SystemArgument2)
135 {
136 return(ZwQueueApcThread(ThreadHandle,
137 ApcRoutine,
138 NormalContext,
139 SystemArgument1,
140 SystemArgument2));
141 }
142
143 NTSTATUS STDCALL ZwQueueApcThread(HANDLE ThreadHandle,
144 PKNORMAL_ROUTINE ApcRoutine,
145 PVOID NormalContext,
146 PVOID SystemArgument1,
147 PVOID SystemArgument2)
148 {
149 UNIMPLEMENTED;
150 }
151
152 NTSTATUS STDCALL NtTestAlert(VOID)
153 {
154 return(ZwTestAlert());
155 }
156
157 NTSTATUS STDCALL ZwTestAlert(VOID)
158 {
159 UNIMPLEMENTED;
160 }