3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * FILE: ntoskrnl/ke/kthread.c
22 * PURPOSE: Process manager definitions
23 * PROGRAMMER: David Welch (welch@cwcom.net)
28 #ifndef __INCLUDE_INTERNAL_PS_H
29 #define __INCLUDE_INTERNAL_PS_H
33 /* Forward declarations. */
40 #include <internal/arch/ps.h>
44 #include <internal/mm.h>
47 #ifndef KeGetCurrentProcessorNumber
48 #define KeGetCurrentProcessorNumber() (KeGetCurrentKPCR()->ProcessorNumber)
51 extern LCID PsDefaultThreadLocaleId
;
52 extern LCID PsDefaultSystemLocaleId
;
56 typedef struct _KTHREAD
58 /* For waiting on thread exit */
59 DISPATCHER_HEADER DispatcherHeader
; /* 00 */
61 /* List of mutants owned by the thread */
62 LIST_ENTRY MutantListHead
; /* 10 */
63 PVOID InitialStack
; /* 18 */
64 ULONG_PTR StackLimit
; /* 1C */
66 /* Pointer to the thread's environment block in user memory */
69 /* Pointer to the thread's TLS array */
70 PVOID TlsArray
; /* 24 */
71 PVOID KernelStack
; /* 28 */
72 UCHAR DebugActive
; /* 2C */
74 /* Thread state (one of THREAD_STATE_xxx constants below) */
76 BOOLEAN Alerted
[2]; /* 2E */
78 UCHAR NpxState
; /* 31 */
79 CHAR Saturation
; /* 32 */
80 CHAR Priority
; /* 33 */
81 KAPC_STATE ApcState
; /* 34 */
82 ULONG ContextSwitches
; /* 4C */
83 LONG WaitStatus
; /* 50 */
84 KIRQL WaitIrql
; /* 54 */
85 CHAR WaitMode
; /* 55 */
86 UCHAR WaitNext
; /* 56 */
87 UCHAR WaitReason
; /* 57 */
88 PKWAIT_BLOCK WaitBlockList
; /* 58 */
89 LIST_ENTRY WaitListEntry
; /* 5C */
90 ULONG WaitTime
; /* 64 */
91 CHAR BasePriority
; /* 68 */
92 UCHAR DecrementCount
; /* 69 */
93 UCHAR PriorityDecrement
; /* 6A */
94 CHAR Quantum
; /* 6B */
95 KWAIT_BLOCK WaitBlock
[4]; /* 6C */
96 PVOID LegoData
; /* CC */
97 ULONG KernelApcDisable
; /* D0 */
98 KAFFINITY UserAffinity
; /* D4 */
99 UCHAR SystemAffinityActive
;/* D8 */
100 UCHAR PowerState
; /* D9 */
101 UCHAR NpxIrql
; /* DA */
102 UCHAR Pad
[1]; /* DB */
103 SSDT_ENTRY
*ServiceTable
; /* DC */
104 PKQUEUE Queue
; /* E0 */
105 KSPIN_LOCK ApcQueueLock
; /* E4 */
106 KTIMER Timer
; /* E8 */
107 LIST_ENTRY QueueListEntry
; /* 110 */
108 KAFFINITY Affinity
; /* 118 */
109 UCHAR Preempted
; /* 11C */
110 UCHAR ProcessReadyQueue
; /* 11D */
111 UCHAR KernelStackResident
; /* 11E */
112 UCHAR NextProcessor
; /* 11F */
113 PVOID CallbackStack
; /* 120 */
114 struct _W32THREAD
*Win32Thread
; /* 124 */
115 struct _KTRAP_FRAME
*TrapFrame
; /* 128 */
116 PKAPC_STATE ApcStatePointer
[2]; /* 12C */
117 UCHAR EnableStackSwap
; /* 134 */
118 UCHAR LargeStack
; /* 135 */
119 UCHAR ResourceIndex
; /* 136 */
120 UCHAR PreviousMode
; /* 137 */
121 ULONG KernelTime
; /* 138 */
122 ULONG UserTime
; /* 13C */
123 KAPC_STATE SavedApcState
; /* 140 */
124 UCHAR Alertable
; /* 158 */
125 UCHAR ApcStateIndex
; /* 159 */
126 UCHAR ApcQueueable
; /* 15A */
127 UCHAR AutoAlignment
; /* 15B */
128 PVOID StackBase
; /* 15C */
129 KAPC SuspendApc
; /* 160 */
130 KSEMAPHORE SuspendSemaphore
; /* 190 */
131 LIST_ENTRY ThreadListEntry
; /* 1A4 */
132 CHAR FreezeCount
; /* 1AC */
133 UCHAR SuspendCount
; /* 1AD */
134 UCHAR IdealProcessor
; /* 1AE */
135 UCHAR DisableBoost
; /* 1AF */
140 /* Top level irp definitions. */
141 #define FSRTL_FSP_TOP_LEVEL_IRP (0x01)
142 #define FSRTL_CACHE_TOP_LEVEL_IRP (0x02)
143 #define FSRTL_MOD_WRITE_TOP_LEVEL_IRP (0x03)
144 #define FSRTL_FAST_IO_TOP_LEVEL_IRP (0x04)
145 #define FSRTL_MAX_TOP_LEVEL_IRP_FLAG (0x04)
152 BOOLEAN EffectiveOnly
;
153 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
;
154 } PS_IMPERSONATION_INFORMATION
, *PPS_IMPERSONATION_INFORMATION
;
157 #include <pshpack1.h>
159 /* This needs to be fixed ASAP! */
160 typedef struct _ETHREAD
164 LARGE_INTEGER CreateTime
;
165 UCHAR NestedFaultCount
:2;
168 LARGE_INTEGER ExitTime
;
169 LIST_ENTRY LpcReplyChain
;
172 LIST_ENTRY PostBlockList
;
174 struct _TERMINATION_PORT
*TerminationPort
;
175 struct _ETHREAD
* ReaperLink
;
177 KSPIN_LOCK ActiveTimerListLock
;
178 LIST_ENTRY ActiveTimerListHead
;
180 KSEMAPHORE LpcReplySemaphore
;
181 PVOID LpcReplyMessage
;
182 ULONG LpcReplyMessageId
;
183 ULONG PerformanceCountLow
;
184 PPS_IMPERSONATION_INFORMATION ImpersonationInfo
;
187 PDEVICE_OBJECT DeviceToVerify
;
188 ULONG ReadClusterSize
;
189 UCHAR ForwardClusterOnly
;
190 UCHAR DisablePageFaultClustering
;
192 UCHAR HideFromDebugger
;
194 #ifdef _ENABLE_THRDEVTPAIR
196 #endif /* _ENABLE_THRDEVTPAIR */
197 ACCESS_MASK GrantedAccess
;
198 struct _EPROCESS
*ThreadsProcess
;
199 PKSTART_ROUTINE StartAddress
;
200 LPTHREAD_START_ROUTINE Win32StartAddress
;
201 ULONG LpcReceivedMessageId
;
202 UCHAR LpcExitThreadCalled
;
203 UCHAR HardErrorsAreDisabled
;
204 UCHAR LpcReceivedMsgIdValid
;
205 UCHAR ActiveImpersonationInfo
;
206 ULONG PerformanceCountHigh
;
207 LIST_ENTRY ThreadListEntry
;
208 BOOLEAN SystemThread
;
216 typedef struct _ETHREAD
*PETHREAD
;
218 #endif /* __USE_W32API */
221 typedef struct _KPROCESS
223 /* So it's possible to wait for the process to terminate */
224 DISPATCHER_HEADER DispatcherHeader
; /* 000 */
226 * Presumably a list of profile objects associated with this process,
229 LIST_ENTRY ProfileListHead
; /* 010 */
231 * We use the first member of this array to hold the physical address of
232 * the page directory for this process.
234 PHYSICAL_ADDRESS DirectoryTableBase
; /* 018 */
236 * Presumably a descriptor for the process's LDT, currently unused.
238 ULONG LdtDescriptor
[2]; /* 020 */
240 * Virtual Dos Machine flag.
242 ULONG NtVdmFlag
; /* 028 */
243 ULONG VdmUnused
; /* 02C */
244 /* Is the i/o permission map enabled for the process. */
245 USHORT IopmOffset
; /* 030 */
247 * Presumably I/O privilege level to be used for this process, currently
250 UCHAR Iopl
; /* 032 */
251 /* Set if this process is a virtual dos machine? */
252 UCHAR VdmFlag
; /* 033 */
253 /* Bitmask of the processors being used by this process's threads? */
254 ULONG ActiveProcessors
; /* 034 */
255 /* Aggregate of the time this process's threads have spent in kernel mode? */
256 ULONG KernelTime
; /* 038 */
257 /* Aggregate of the time this process's threads have spent in user mode? */
258 ULONG UserTime
; /* 03C */
259 /* List of this process's threads that are ready for execution? */
260 LIST_ENTRY ReadyListHead
; /* 040 */
261 /* List of this process's threads that have their stacks swapped out? */
262 LIST_ENTRY SwapListEntry
; /* 048 */
263 /* List of this process's threads? */
264 LIST_ENTRY ThreadListHead
; /* 050 */
265 /* Maybe a lock for this data structure, the type is assumed. */
266 KSPIN_LOCK ProcessLock
; /* 058 */
267 /* Default affinity mask for this process's threads? */
268 ULONG Affinity
; /* 05C */
269 /* Count of the stacks allocated for this process's threads? */
270 USHORT StackCount
; /* 060 */
271 /* Base priority for this process's threads? */
272 KPRIORITY BasePriority
; /* 062 */
273 /* Default quantum for this process's threads */
274 UCHAR ThreadQuantum
; /* 063 */
276 UCHAR AutoAlignment
; /* 064 */
277 /* Process execution state, currently either active or terminated. */
278 UCHAR State
; /* 065 */
279 /* Seed for generating thread ids for this process's threads? */
280 UCHAR ThreadSeed
; /* 066 */
281 /* Disable priority boosts? */
282 UCHAR DisableBoost
; /* 067 */
287 typedef struct _KPROCESS
*PKPROCESS
;
289 typedef struct _HARDWARE_PTE_X86
{
293 ULONG WriteThrough
: 1;
294 ULONG CacheDisable
: 1;
299 ULONG CopyOnWrite
: 1;
302 ULONG PageFrameNumber
: 20;
303 } HARDWARE_PTE_X86
, *PHARDWARE_PTE_X86
;
305 typedef struct _WOW64_PROCESS
308 } WOW64_PROCESS
, *PWOW64_PROCESS
;
310 #endif /* __USE_W32API */
314 /* Microkernel specific process state. */
315 KPROCESS Pcb
; /* 000 */
316 /* Exit status of the process. */
317 NTSTATUS ExitStatus
; /* 068 */
319 KEVENT LockEvent
; /* 06C */
321 ULONG LockCount
; /* 07C */
323 /* Time of process creation. */
324 LARGE_INTEGER CreateTime
; /* 080 */
326 /* Time of process exit. */
327 LARGE_INTEGER ExitTime
; /* 088 */
329 PKTHREAD LockOwner
; /* 090 */
331 HANDLE UniqueProcessId
; /* 094 */
333 LIST_ENTRY ActiveProcessLinks
; /* 098 */
335 ULONG QuotaPeakPoolUsage
[2]; /* 0A0 */
337 ULONG QuotaPoolUsage
[2]; /* 0A8 */
339 ULONG PagefileUsage
; /* 0B0 */
341 ULONG CommitCharge
; /* 0B4 */
343 ULONG PeakPagefileUsage
; /* 0B8 */
345 ULONG PeakVirtualSize
; /* 0BC */
347 LARGE_INTEGER VirtualSize
; /* 0C0 */
350 LIST_ENTRY SessionProcessLinks
;
351 struct _EPORT
*DebugPort
;
352 struct _EPORT
*ExceptionPort
;
353 PHANDLE_TABLE ObjectTable
;
355 FAST_MUTEX WorkingSetLock
;
356 ULONG WorkingSetPage
;
357 UCHAR ProcessOutswapEnabled
;
358 UCHAR ProcessOutswapped
;
359 UCHAR AddressSpaceInitialized
;
360 UCHAR AddressSpaceDeleted
;
361 FAST_MUTEX AddressCreationLock
;
362 KSPIN_LOCK HyperSpaceLock
;
363 PETHREAD ForkInProgress
;
365 UCHAR ForkWasSuccessful
;
366 UCHAR MmAgressiveWsTrimMask
;
367 PKEVENT VmOperationEvent
;
369 ULONG LastFaultCount
;
370 ULONG ModifiedPageCount
;
374 ULONG NumberOfPrivatePages
;
375 ULONG NumberOfLockedPages
;
376 USHORT NextPageColor
;
377 UCHAR ExitProcessCalled
;
378 UCHAR CreateProcessReported
;
379 HANDLE SectionHandle
;
381 PVOID SectionBaseAddress
;
382 PEPROCESS_QUOTA_BLOCK QuotaBlock
;
383 NTSTATUS LastThreadExitStatus
;
384 PPAGEFAULT_HISTORY WorkingSetWatch
;
385 HANDLE Win32WindowStation
;
386 HANDLE InheritedFromUniqueProcessId
;
388 ULONG DefaultHardErrorProcessing
;
389 PVOID LdtInformation
;
394 LIST_ENTRY PhysicalVadList
;
395 HARDWARE_PTE_X86 PageDirectoryPte
;
397 ULONG PaePageDirectoryPage
;
398 CHAR ImageFileName
[16];
399 ULONG VmTrimFaultValue
;
400 UCHAR SetTimerResolution
;
402 UCHAR SubSystemMinorVersion
;
403 UCHAR SubSystemMajorVersion
;
404 USHORT SubSystemVersion
;
405 struct _W32PROCESS
*Win32Process
;
409 PVOID LockedPagesList
;
410 struct _EPORT
*SecurityPort
;
411 PWOW64_PROCESS Wow64
;
412 LARGE_INTEGER ReadOperationCount
;
413 LARGE_INTEGER WriteOperationCount
;
414 LARGE_INTEGER OtherOperationCount
;
415 LARGE_INTEGER ReadTransferCount
;
416 LARGE_INTEGER WriteTransferCount
;
417 LARGE_INTEGER OtherTransferCount
;
418 ULONG CommitChargeLimit
;
419 ULONG CommitChargePeak
;
420 LIST_ENTRY ThreadListHead
;
421 PRTL_BITMAP VadPhysicalPagesBitMap
;
422 ULONG VadPhysicalPages
;
427 * FIXME - ReactOS specified - remove the following fields ASAP!!!
429 MADDRESS_SPACE AddressSpace
;
430 LIST_ENTRY ProcessListEntry
;
433 PVOID TebLastAllocated
;
436 #define PROCESS_STATE_TERMINATED (1)
437 #define PROCESS_STATE_ACTIVE (2)
439 VOID
PiInitDefaultLocale(VOID
);
440 VOID
PiInitProcessManager(VOID
);
441 VOID
PiShutdownProcessManager(VOID
);
442 VOID
PsInitThreadManagment(VOID
);
443 VOID
PsInitProcessManagment(VOID
);
444 VOID
PsInitIdleThread(VOID
);
445 VOID
PiTerminateProcessThreads(PEPROCESS Process
, NTSTATUS ExitStatus
);
446 VOID
PsTerminateCurrentThread(NTSTATUS ExitStatus
);
447 VOID
PsTerminateOtherThread(PETHREAD Thread
, NTSTATUS ExitStatus
);
448 VOID
PsReleaseThread(PETHREAD Thread
);
449 VOID
PsBeginThread(PKSTART_ROUTINE StartRoutine
, PVOID StartContext
);
450 VOID
PsBeginThreadWithContextInternal(VOID
);
451 VOID
PiKillMostProcesses(VOID
);
452 NTSTATUS STDCALL
PiTerminateProcess(PEPROCESS Process
, NTSTATUS ExitStatus
);
453 VOID
PiInitApcManagement(VOID
);
454 VOID STDCALL
PiDeleteThread(PVOID ObjectBody
);
455 VOID
PsReapThreads(VOID
);
456 VOID
PsInitializeThreadReaper(VOID
);
457 VOID
PsQueueThreadReap(PETHREAD Thread
);
459 PsInitializeThread(PEPROCESS Process
,
461 POBJECT_ATTRIBUTES ObjectAttributes
,
462 KPROCESSOR_MODE AccessMode
,
465 PACCESS_TOKEN STDCALL
PsReferenceEffectiveToken(PETHREAD Thread
,
466 PTOKEN_TYPE TokenType
,
468 PSECURITY_IMPERSONATION_LEVEL Level
);
470 NTSTATUS STDCALL
PsOpenTokenOfProcess(HANDLE ProcessHandle
,
471 PACCESS_TOKEN
* Token
);
474 PspTerminateProcessThreads(PEPROCESS Process
,
475 NTSTATUS ExitStatus
);
476 NTSTATUS
PsSuspendThread(PETHREAD Thread
, PULONG PreviousCount
);
477 NTSTATUS
PsResumeThread(PETHREAD Thread
, PULONG PreviousCount
);
480 PspAssignPrimaryToken(PEPROCESS Process
,
482 VOID STDCALL
PsExitSpecialApc(PKAPC Apc
,
483 PKNORMAL_ROUTINE
*NormalRoutine
,
484 PVOID
*NormalContext
,
485 PVOID
*SystemArgument1
,
486 PVOID
*SystemArgument2
);
488 #define THREAD_STATE_INITIALIZED (0)
489 #define THREAD_STATE_READY (1)
490 #define THREAD_STATE_RUNNING (2)
491 #define THREAD_STATE_SUSPENDED (3)
492 #define THREAD_STATE_FROZEN (4)
493 #define THREAD_STATE_TERMINATED_1 (5)
494 #define THREAD_STATE_TERMINATED_2 (6)
495 #define THREAD_STATE_BLOCKED (7)
496 #define THREAD_STATE_MAX (8)
500 * Internal thread priorities, added by Phillip Susi
501 * TODO: rebalence these to make use of all priorities... the ones above 16
502 * can not all be used right now
504 #define PROCESS_PRIO_IDLE 3
505 #define PROCESS_PRIO_NORMAL 8
506 #define PROCESS_PRIO_HIGH 13
507 #define PROCESS_PRIO_RT 18
510 VOID STDCALL
PiDeleteProcess(PVOID ObjectBody
);
514 PspReapRoutine(PVOID Context
);
518 PspExitThread(NTSTATUS ExitStatus
);
520 extern LIST_ENTRY PspReaperListHead
;
521 extern WORK_QUEUE_ITEM PspReaperWorkItem
;
522 extern BOOLEAN PspReaping
;
526 PspTerminateThreadByPointer(PETHREAD Thread
,
527 NTSTATUS ExitStatus
);
529 VOID
PsUnfreezeOtherThread(PETHREAD Thread
);
530 VOID
PsFreezeOtherThread(PETHREAD Thread
);
531 VOID
PsFreezeProcessThreads(PEPROCESS Process
);
532 VOID
PsUnfreezeProcessThreads(PEPROCESS Process
);
533 ULONG
PsEnumThreadsByProcess(PEPROCESS Process
);
534 PEPROCESS
PsGetNextProcess(PEPROCESS OldProcess
);
536 PsApplicationProcessorInit(VOID
);
538 PsPrepareForApplicationProcessorInit(ULONG Id
);
540 PsIdleThreadMain(PVOID Context
);
543 PiSuspendThreadRundownRoutine(PKAPC Apc
);
545 PiSuspendThreadKernelRoutine(PKAPC Apc
,
546 PKNORMAL_ROUTINE
* NormalRoutine
,
547 PVOID
* NormalContext
,
548 PVOID
* SystemArgument1
,
549 PVOID
* SystemArguemnt2
);
551 PiSuspendThreadNormalRoutine(PVOID NormalContext
,
552 PVOID SystemArgument1
,
553 PVOID SystemArgument2
);
555 PsInitialiseSuspendImplementation(VOID
);
558 PspExitProcess(PEPROCESS Process
);
562 PspDeleteProcess(PVOID ObjectBody
);
566 PspDeleteThread(PVOID ObjectBody
);
568 extern LONG PiNrThreadsAwaitingReaping
;
571 PsInitWin32Thread (PETHREAD Thread
);
574 PsTerminateWin32Process (PEPROCESS Process
);
577 PsTerminateWin32Thread (PETHREAD Thread
);
580 PsInitialiseW32Call(VOID
);
584 PspRunCreateThreadNotifyRoutines(PETHREAD
, BOOLEAN
);
588 PspRunCreateProcessNotifyRoutines(PEPROCESS
, BOOLEAN
);
590 #include <pshpack1.h>
591 typedef struct _PS_JOB_TOKEN_FILTER
593 UINT CapturedSidCount
;
594 PSID_AND_ATTRIBUTES CapturedSids
;
595 UINT CapturedSidsLength
;
596 UINT CapturedGroupCount
;
597 PSID_AND_ATTRIBUTES CapturedGroups
;
598 UINT CapturedGroupsLength
;
599 UINT CapturedPrivilegeCount
;
600 PLUID_AND_ATTRIBUTES CapturedPrivileges
;
601 UINT CapturedPrivilegesLength
;
602 } PS_JOB_TOKEN_FILTER
, *PPS_JOB_TOKEN_FILTER
;
605 #include <pshpack1.h>
610 LIST_ENTRY ProcessListHead
;
612 LARGE_INTEGER TotalUserTime
;
613 LARGE_INTEGER TotalKernelTime
;
614 LARGE_INTEGER ThisPeriodTotalUserTime
;
615 LARGE_INTEGER ThisPeriodTotalKernelTime
;
616 UINT TotalPageFaultCount
;
618 UINT ActiveProcesses
;
619 UINT TotalTerminatedProcesses
;
620 LARGE_INTEGER PerProcessUserTimeLimit
;
621 LARGE_INTEGER PerJobUserTimeLimit
;
623 UINT MinimumWorkingSetSize
;
624 UINT MaximumWorkingSetSize
;
625 UINT ActiveProcessLimit
;
628 UINT UIRestrictionsClass
;
629 UINT SecurityLimitFlags
;
631 PPS_JOB_TOKEN_FILTER Filter
;
632 UINT EndOfJobTimeAction
;
633 PVOID CompletionPort
;
636 UINT SchedulingClass
;
637 ULONGLONG ReadOperationCount
;
638 ULONGLONG WriteOperationCount
;
639 ULONGLONG OtherOperationCount
;
640 ULONGLONG ReadTransferCount
;
641 ULONGLONG WriteTransferCount
;
642 ULONGLONG OtherTransferCount
;
644 UINT ProcessMemoryLimit
;
646 UINT PeakProcessMemoryUsed
;
647 UINT PeakJobMemoryUsed
;
648 UINT CurrentJobMemoryUsed
;
649 FAST_MUTEX MemoryLimitsLock
;
653 VOID INIT_FUNCTION
PsInitJobManagment(VOID
);
657 NTSTATUS
PsCreateCidHandle(PVOID Object
, POBJECT_TYPE ObjectType
, PHANDLE Handle
);
658 NTSTATUS
PsDeleteCidHandle(HANDLE CidHandle
, POBJECT_TYPE ObjectType
);
659 PHANDLE_TABLE_ENTRY
PsLookupCidHandle(HANDLE CidHandle
, POBJECT_TYPE ObjectType
, PVOID
*Object
);
660 VOID
PsUnlockCidHandle(PHANDLE_TABLE_ENTRY CidEntry
);
661 NTSTATUS
PsLockProcess(PEPROCESS Process
, BOOLEAN Timeout
);
662 VOID
PsUnlockProcess(PEPROCESS Process
);
664 #define ETHREAD_TO_KTHREAD(pEThread) (&(pEThread)->Tcb)
665 #define KTHREAD_TO_ETHREAD(pKThread) (CONTAINING_RECORD((pKThread), ETHREAD, Tcb))
666 #define EPROCESS_TO_KPROCESS(pEProcess) (&(pEProcess)->Pcb)
667 #define KPROCESS_TO_EPROCESS(pKProcess) (CONTAINING_RECORD((pKProcess), EPROCESS, Pcb))
669 #endif /* ASSEMBLER */
671 #endif /* __INCLUDE_INTERNAL_PS_H */