progwrp/procthread.c
2025-12-13 23:37:26 +01:00

557 lines
12 KiB
C

#include "progwrp.h"
#include "export.h"
#include "implementations.h"
#ifdef _M_IX86
_allmul()
{
__asm
{
pop ebx ; assembler was adding push ebx by default, so adding this
mov eax, [esp+8]
mov ecx, [esp+16]
or ecx, eax
mov ecx, [esp+12]
jnz hard
mov eax, [esp+4]
mul ecx
ret 16
hard:
push ebx
mul ecx
mov ebx, eax
mov eax, [esp+8]
mul dword ptr [esp+20]
add ebx, eax
mov eax, [esp+8]
mul ecx
add edx, ebx
pop ebx
ret 16
}
}
_aulldiv()
{
__asm
{
pop ebx
pop esi
push ebx
push esi
mov eax, [esp+24]
or eax, eax
jnz hard
mov ecx, [esp+20]
mov eax, [esp+16]
xor edx, edx
div ecx
mov ebx, eax
mov eax, [esp+12]
div ecx
mov edx, ebx
jmp result
hard:
mov ecx, eax
mov ebx, [esp+20]
mov edx, [esp+16]
mov eax, [esp+12]
loop_shr:
shr ecx, 1
rcr ebx, 1
shr edx, 1
rcr eax, 1
or ecx, ecx
jnz loop_shr
div ebx
mov esi, eax
mul dword ptr [esp+24]
mov ecx, eax
mov eax, [esp+20]
mul esi
add edx, ecx
jb decrement
cmp edx, [esp+10]
ja decrement
jb xor_edx
cmp eax, [esp+12]
jbe xor_edx
decrement:
dec esi
xor_edx:
xor edx, edx
mov eax, esi
result:
pop esi
pop ebx
ret 16
}
}
#endif
HANDLE WINAPI Implementation_CreateRemoteThreadEx(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
LPDWORD lpThreadId
)
/*
Only difference is the use of thread attributes. Not applicable in XP and below...
I could add support for a few of the attributes (ideal processor, inherited handles,
nested job objects> - unless I can attach them to generic handles).
*/
{
return CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter,
dwCreationFlags, lpThreadId);
}
// Flags to indicate if an attribute is present in the list.
// I believe these are used so that Windows doesn't have to scan the complete list to see if an attribute is present.
#define PARENT_PROCESS (1 << ProcThreadAttributeParentProcess)
#define EXTENDED_FLAGS (1 << ProcThreadAttributeExtendedFlags)
#define HANDLE_LIST (1 << ProcThreadAttributeHandleList)
#define GROUP_AFFINITY (1 << ProcThreadAttributeGroupAffinity)
#define PREFERRED_NODE (1 << ProcThreadAttributePreferredNode)
#define IDEAL_PROCESSOR (1 << ProcThreadAttributeIdealProcessor)
#define UMS_THREAD (1 << ProcThreadAttributeUmsThread)
#define MITIGATION_POLICY (1 << ProcThreadAttributeMitigationPolicy)
// This structure stores the value for each attribute
typedef struct _PROC_THREAD_ATTRIBUTE_ENTRY
{
DWORD_PTR Attribute; // PROC_THREAD_ATTRIBUTE_xxx
SIZE_T cbSize;
PVOID lpValue;
} PROC_THREAD_ATTRIBUTE_ENTRY, *LPPROC_THREAD_ATTRIBUTE_ENTRY;
// This structure contains a list of attributes that have been added using UpdateProcThreadAttribute
typedef struct _PROC_THREAD_ATTRIBUTE_LIST
{
DWORD dwFlags;
ULONG Size;
ULONG Count;
ULONG Reserved;
PULONG Unknown;
PROC_THREAD_ATTRIBUTE_ENTRY Entries[ANYSIZE_ARRAY];
} PROC_THREAD_ATTRIBUTE_LIST, *LPPROC_THREAD_ATTRIBUTE_LIST;
BOOL WINAPI Implementation_InitializeProcThreadAttributeList(
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
DWORD dwAttributeCount,
DWORD dwFlags,
PSIZE_T lpSize
)
{
if(!lpSize)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
*lpSize = sizeof(PROC_THREAD_ATTRIBUTE_LIST)+ (sizeof(PROC_THREAD_ATTRIBUTE_ENTRY) * dwAttributeCount);
if(!lpAttributeList)
return FALSE;
else
{
lpAttributeList->Count = dwAttributeCount;
lpAttributeList->Size = *lpSize;
return TRUE;
}
return FALSE;
}
BOOL WINAPI Implementation_UpdateProcThreadAttribute(
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,
DWORD dwFlags,
DWORD_PTR Attribute,
PVOID lpValue,
SIZE_T cbSize,
PVOID lpPreviousValue,
PSIZE_T lpReturnSize
)
{
if(dwFlags || !lpAttributeList)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch(Attribute)
{
case PROC_THREAD_ATTRIBUTE_HANDLE_LIST:
lpAttributeList->Entries[0].Attribute = Attribute;
lpAttributeList->dwFlags |= 1;
lpAttributeList->Entries[0].lpValue = lpValue;
return TRUE;
break;
}
return FALSE;
}
void WINAPI Implementation_DeleteProcThreadAttributeList(
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList
)
{
;
}
BOOL WINAPI Implementation_QueryFullProcessImageNameW(
HANDLE hProcess,
DWORD dwFlags,
LPWSTR lpExeName,
PDWORD lpdwSize
)
{
return FALSE;
}
BOOL WINAPI Implementation_QueryFullProcessImageNameA(
HANDLE hProcess,
DWORD dwFlags,
LPSTR lpExeName,
PDWORD lpdwSize
)
{
return FALSE;
}
BOOL WINAPI Implementation_QueryThreadCycleTime(
HANDLE ThreadHandle,
PULONG64 CycleTime
)
{
LARGE_INTEGER QpcFirst;
LARGE_INTEGER QpcLast;
LARGE_INTEGER CtFreq;
ULONG64 TscFirst;
ULONG64 TscLast;
ULONG64 TscFreq;
ULONG64 Delta;
ULONG64 Dividend;
DWORD OldTp;
ULONG64 CreationTime, ExitTime, KernelTime, UserTime;
if(!CycleTime)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
OldTp = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
TscFirst = __rdtsc();
QueryPerformanceCounter(&QpcFirst);
TscLast = __rdtsc();
QueryPerformanceCounter(&QpcLast);
SetThreadPriority(GetCurrentThread(), OldTp);
QueryPerformanceFrequency(&CtFreq);
if(!CtFreq.QuadPart)
CtFreq.QuadPart = 1000;
Delta = QpcLast.QuadPart - QpcFirst.QuadPart;
Dividend = Delta / CtFreq.QuadPart;
if(!Dividend)
Dividend = 1;
TscFreq = (TscLast - TscFirst) / Dividend;
if(!GetThreadTimes(ThreadHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime))
return FALSE;
*CycleTime = ((KernelTime + UserTime) / 10000000) * TscFreq;
return TRUE;
}
BOOL WINAPI Implementation_QueryProcessCycleTime(
HANDLE ProcessHandle,
PULONG64 CycleTime
)
{
LARGE_INTEGER QpcFirst;
LARGE_INTEGER QpcLast;
LARGE_INTEGER CtFreq;
ULONG64 TscFirst;
ULONG64 TscLast;
ULONG64 TscFreq;
ULONG64 Delta;
ULONG64 Dividend;
DWORD OldTp;
ULONG64 CreationTime, ExitTime, KernelTime, UserTime;
if(!CycleTime)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
OldTp = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
TscFirst = __rdtsc();
QueryPerformanceCounter(&QpcFirst);
TscLast = __rdtsc();
QueryPerformanceCounter(&QpcLast);
SetThreadPriority(GetCurrentThread(), OldTp);
QueryPerformanceFrequency(&CtFreq);
if(!CtFreq.QuadPart)
CtFreq.QuadPart = 1000;
Delta = QpcLast.QuadPart - QpcFirst.QuadPart;
Dividend = Delta / CtFreq.QuadPart;
if(!Dividend)
Dividend = 1;
TscFreq = (TscLast - TscFirst) / Dividend;
if(!GetProcessTimes(ProcessHandle, &CreationTime, &ExitTime, &KernelTime, &UserTime))
return FALSE;
*CycleTime = ((KernelTime + UserTime) / 10000000) * TscFreq;
return TRUE;
}
BOOL WINAPI Implementation_GetNamedPipeServerProcessId(
HANDLE Pipe,
PULONG ServerProcessId
)
{
return FALSE;
}
BOOL WINAPI Implementation_GetNamedPipeClientProcessId(
HANDLE Pipe,
PULONG ClientProcessId
)
{
return FALSE;
}
BOOL WINAPI Implementation_Wow64GetThreadContext(
HANDLE hThread,
PWOW64_CONTEXT lpContext
)
{
return FALSE;
}
#define ThreadBasicInformation 0
typedef struct _THREAD_BASIC_INFORMATION {
NTSTATUS ExitStatus;
PVOID TebBaseAddress;
CLIENT_ID ClientId;
KAFFINITY AffinityMask;
KPRIORITY Priority;
KPRIORITY BasePriority;
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
DWORD WINAPI Implementation_GetThreadId(
HANDLE Thread
)
{
THREAD_BASIC_INFORMATION tbi;
NTSTATUS Status = NtQueryInformationThread(Thread, ThreadBasicInformation, (PVOID)&tbi, sizeof(THREAD_BASIC_INFORMATION), NULL);
if(Status)
{
BaseSetLastNTError(Status);
return 0;
}
return (DWORD)tbi.ClientId.UniqueThread;
}
#ifdef _M_IX86
NTSTATUS NTAPI NtSetInformationProcess(HANDLE ProcessHandle, ULONG ProcessInfoClass, PVOID ProcessInformation, ULONG InfoLength);
BOOL WINAPI Implementation_SetProcessDEPPolicy(DWORD dwFlags)
{
DWORD dwFlagscpy;
NTSTATUS Status;
dwFlagscpy = dwFlags;
if ( (dwFlags & 0xFFFFFFFC) != 0 ) //check that only bits 0 and 1 are set
{
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
return FALSE;
}
if ( (dwFlags & PROCESS_DEP_ENABLE) != 0 )
{
dwFlags = 9;
if ( (dwFlagscpy & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION) != 0 )
dwFlags = 13;
}
else
{
if ( (dwFlags & PROCESS_DEP_DISABLE_ATL_THUNK_EMULATION) != 0 )
{
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
return FALSE;
}
dwFlags = 2; // Set DEP to be disabled for the process
}
Status = NtSetInformationProcess((HANDLE)-1, 0x22, (PVOID)&dwFlags,(ULONG) 4); //class ProcessExecuteFlags
if ( Status < 0 )
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
#else
BOOL WINAPI Implementation_SetProcessDEPPolicy(DWORD dwFlags)
{
BaseSetLastNTError(0xC00000BB);
return FALSE;
}
#endif
DWORD WINAPI Implementation_GetProcessId(
HANDLE Process
)
{
PROCESS_BASIC_INFORMATION pbi;
NTSTATUS Status = NtQueryInformationProcess(Process, ProcessBasicInformation, (PVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION), NULL);
if(Status)
{
BaseSetLastNTError(Status);
return 0;
}
return (DWORD)pbi.UniqueProcessId;
}
BOOL WINAPI Implementation_GetProcessHandleCount(
HANDLE hProcess,
PDWORD pdwHandleCount
)
{
ULONG ulProcessHandleCount;
if(!pdwHandleCount)
{
BaseSetLastNTError(ERROR_INVALID_PARAMETER);
return FALSE;
}
NTSTATUS Status = NtQueryInformationProcess(hProcess, 20, (PVOID)&ulProcessHandleCount, sizeof(ULONG), NULL);
if(Status)
{
BaseSetLastNTError(Status);
return FALSE;
}
*pdwHandleCount = ulProcessHandleCount;
return TRUE;
}
BOOL WINAPI Implementation_IsProcessInJob(
HANDLE ProcessHandle,
HANDLE JobHandle,
PBOOL Result
)
{
int i;
DWORD dwProcessId;
PJOBOBJECT_BASIC_PROCESS_ID_LIST jbpil;
JOBOBJECT_BASIC_ACCOUNTING_INFORMATION jbai;
if(!Result || !QueryInformationJobObject(JobHandle, JobObjectBasicAccountingInformation, &jbai, sizeof(JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), NULL))
return FALSE;
*Result = FALSE;
jbpil = (PJOBOBJECT_BASIC_PROCESS_ID_LIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) * (sizeof(ULONG_PTR)* jbai.TotalProcesses));
if(QueryInformationJobObject(JobHandle, JobObjectBasicProcessIdList, &jbpil, sizeof(JOBOBJECT_BASIC_PROCESS_ID_LIST) * (sizeof(ULONG_PTR)* jbai.TotalProcesses), NULL))
{
dwProcessId = Implementation_GetProcessId(ProcessHandle);
for(i = 0; i < jbpil->NumberOfProcessIdsInList; i++)
{
if(dwProcessId == jbpil->ProcessIdList[i])
{
*Result = TRUE;
HeapFree(GetProcessHeap(), 0, jbpil);
return FALSE;
}
}
HeapFree(GetProcessHeap(), 0, jbpil);
return TRUE;
}
else {
HeapFree(GetProcessHeap(), 0, jbpil);
return FALSE;
}
}
BOOL WINAPI Implementation_IsWow64Process(
HANDLE hProcess,
PBOOL Wow64Process
)
{
if(!Wow64Process)
return FALSE;
*Wow64Process = TRUE;
return TRUE;
}
BOOL WINAPI Implementation_DuplicateHandle(
HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
LPHANDLE lpTargetHandle,
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwOptions
)
{
typedef BOOL(WINAPI* pfnDuplicateHandle)(HANDLE, HANDLE, HANDLE, LPHANDLE, DWORD, BOOL, DWORD);
pfnDuplicateHandle pDuplicateHandle = (pfnDuplicateHandle)Implementation_GetProcAddress(GetModuleHandleA("kernel32.dll"), "DuplicateHandle");
if (dwDesiredAccess & PROCESS_QUERY_LIMITED_INFORMATION)
{
dwDesiredAccess &= ~PROCESS_QUERY_LIMITED_INFORMATION;
dwDesiredAccess |= PROCESS_QUERY_INFORMATION;
}
return pDuplicateHandle(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess,
bInheritHandle, dwOptions);
}