Добрый день На днях решил разобраться с созданием потока используя NtCreateThread. Единственный найденый мною пример http://www.wasm.ru/forum/files/_1687450158__CreateThread.c оказался не рабочим . Я так понял что там неверно определяются стек или контекст потока, потому что обьект потока создается нормально но при попытке запуска все виснет. Буду очень признателен за любую инфу по теме или пример рабочего кода
Klayd http://cygwin.com/ml/cygwin-developers/2001-02/msg00032.html - пример из книги Неббета. Хотя сам его не проверял.
Klayd нестранно) нужно или уведомлять сервер подсистемы win32 о создании новго потока, или использовать в нём только апишки из ntdll
asd чето не могу скомпилить, в ntdll.h почемуто находит множество ошибок.. мож у когото есть пример проверенный?
Проблема решена Написал свой вариант: Код (Text): function ROUND_UP(VALUE: ULONG; ROUND: ULONG): ULONG; begin Result := (VALUE + (ROUND - 1)) and (not(ROUND - 1)) end; function RtlpCreateStack(Process: HANDLE; MaximumStackSize: ULONG; CommittedStackSize: ULONG; ZeroBits: ULONG; InitialTeb: PTHREAD_STACK): NTSTATUS; var Status: NTSTATUS; Stack: PCHAR; SysInfo: SYSTEM_BASIC_INFORMATION; GuardPage: BOOLEAN; RegionSize: ULONG; OldProtect: ULONG; Peb: PPEB; NtHeaders: PIMAGE_NT_HEADERS; label Exit; begin Status := NtQuerySystemInformation(SystemBasicInformation, @SysInfo, SizeOf(SysInfo), nil); if Status <> STATUS_SUCCESS then goto Exit; if Process = GetCurrentProcess() then begin Peb := RtlGetCurrentPeb(); NtHeaders := RtlImageNtHeader(Peb^.ImageBaseAddress); if MaximumStackSize = 0 then MaximumStackSize := NtHeaders^.OptionalHeader.SizeOfStackReserve; if CommittedStackSize = 0 then CommittedStackSize := NtHeaders^.OptionalHeader.SizeOfStackCommit end else begin if CommittedStackSize = 0 then CommittedStackSize := SysInfo.PhysicalPageSize; if MaximumStackSize = 0 then MaximumStackSize := SysInfo.AllocationGranularity end; if CommittedStackSize >= MaximumStackSize then MaximumStackSize := ROUND_UP(CommittedStackSize, (1024*1024)); CommittedStackSize := ROUND_UP(CommittedStackSize, SysInfo.PhysicalPageSize); MaximumStackSize := ROUND_UP(MaximumStackSize, SysInfo.AllocationGranularity); Stack := nil; Status := NtAllocateVirtualMemory(Process, @Stack, ZeroBits, @MaximumStackSize, MEM_RESERVE, PAGE_READWRITE); if Status <> STATUS_SUCCESS then goto Exit; InitialTeb^.OldStackBase := nil; InitialTeb^.OldStackLimit := nil; InitialTeb^.StackAllocationBase := Stack; InitialTeb^.StackBase := Stack + MaximumStackSize; Stack := Stack + MaximumStackSize - CommittedStackSize; if MaximumStackSize > CommittedStackSize then begin Stack := Stack - SysInfo.PhysicalPageSize; CommittedStackSize := CommittedStackSize + SysInfo.PhysicalPageSize; GuardPage := TRUE end else GuardPage := FALSE; Status := NtAllocateVirtualMemory(Process, @Stack, 0, @CommittedStackSize, MEM_COMMIT, PAGE_READWRITE); InitialTeb^.StackLimit := Stack; if Status <> STATUS_SUCCESS then goto Exit; if GuardPage then begin RegionSize := SysInfo.PhysicalPageSize; Status := NtProtectVirtualMemory(Process, @Stack, @RegionSize, PAGE_GUARD or PAGE_READWRITE, @OldProtect); if Status <> STATUS_SUCCESS then goto Exit; InitialTeb^.StackLimit := PVOID(ULONG(InitialTeb^.StackLimit) - RegionSize); end; Status := STATUS_SUCCESS; Exit: Result := Status end; function RtlpFreeStack(Process: HANDLE; InitialTeb: PTHREAD_STACK): NTSTATUS; var Status: NTSTATUS; Zero: ULONG; label Exit; begin Zero := 0; Status := NtFreeVirtualMemory(Process, @InitialTeb^.StackAllocationBase, @Zero, MEM_RELEASE); if Status <> STATUS_SUCCESS then goto Exit; RtlZeroMemory(InitialTeb, SizeOf(InitialTeb^) ); Exit: Result := Status; end; function CreateUserThread(Process: HANDLE; ThreadSecurityDescriptor: PSECURITY_DESCRIPTOR; CreateSuspended: BOOLEAN; ZeroBits: ULONG; MaximumStackSize: ULONG; CommittedStackSize: ULONG; StartAddress: PVOID; Parameter: PVOID; Thread: PHANDLE; ClientId: PCLIENT_ID): NTSTATUS; var InitialTeb: THREAD_STACK; ThreadHandle: HANDLE; ThreadContext: CONTEXT; ThreadClientId: CLIENT_ID; ObjectAttributes: OBJECT_ATTRIBUTES; Status: NTSTATUS; label Exit; begin Status := RtlpCreateStack(Process, MaximumStackSize, CommittedStackSize, ZeroBits, @InitialTeb); if Status <> STATUS_SUCCESS then goto Exit; RtlInitializeContext(Process, @ThreadContext, Parameter, StartAddress, InitialTeb.StackBase); InitializeObjectAttributes(@ObjectAttributes, nil, 0, 0, ThreadSecurityDescriptor ); Status := NtCreateThread(@ThreadHandle, THREAD_ALL_ACCESS, @ObjectAttributes, Process, @ThreadClientId, @ThreadContext, @InitialTeb, CreateSuspended); if Status <> STATUS_SUCCESS then RtlpFreeStack(Process, @InitialTeb) else begin if Thread <> nil then Thread^ := ThreadHandle; if ClientId <> nil then ClientId^ := ThreadClientId end; Exit: Result := Status end; извините за паскаль
я делал примерно так только на асме тред не регистрировал в crsss (ClientCallServer не вызывал) были какие-то косяки, ща не помню точно что, но что-то серьезное не работало вейт на хендле чтоли
если не использовать в потоке, как сказал Cr4sh, ниче кроме ntdll, то работает нормально тока сомневаюсь что станет работать на 64 разрядной винде :\
боян пробовал сам лично ... нифига не получилось, тред создается нормально только в простых приложения если попробовать создать удаленый тред в службе ... служба на пару с csrss занимают все процессорное время и начинают тупить по максимуму ... в обяз надо информировать csrss ап: причем стабильность даж в простых приложения не гарантирована ... мбо у меня тред был на нативах ... но тем неменее тупил ...
тут CreateUserThread вопщемто является прототипом RtlCreateUserThread поэтому csrss надо информировать самому