| 352 | } |
| 353 | |
| 354 | HANDLE NtCreateThreadEx( HANDLE hProcess, LPVOID lpRemoteThreadStart, LPVOID lpParam, DWORD createFlags, DWORD* threadId ) |
| 355 | { |
| 356 | PS_ATTRIBUTE_LIST attrList; |
| 357 | CLIENT_ID clientId; |
| 358 | HANDLE hThread; |
| 359 | |
| 360 | if (ntdll::NtCreateThreadEx == NULL) |
| 361 | return NULL; |
| 362 | |
| 363 | ZeroMemory( &attrList, sizeof( attrList ) ); |
| 364 | attrList.Attributes[0].Attribute = ProcThreadAttributeValue( PsAttributeClientId, TRUE, FALSE, FALSE ); |
| 365 | attrList.Attributes[0].Size = sizeof( CLIENT_ID ); |
| 366 | attrList.Attributes[0].ValuePtr = (ULONG_PTR *)&clientId; |
| 367 | attrList.TotalLength = sizeof( PS_ATTRIBUTE_LIST ); |
| 368 | |
| 369 | if (!NT_SUCCESS( ntdll::NtCreateThreadEx( &hThread, THREAD_ALL_ACCESS, NULL, hProcess, lpRemoteThreadStart, lpParam, createFlags, 0, 0x1000, 0x100000, &attrList ) )) |
| 370 | return NULL; |
| 371 | |
| 372 | if (threadId) |
| 373 | *threadId = (DWORD)clientId.UniqueThread; |
| 374 | |
| 375 | return hThread; |
| 376 | } |
| 377 | |
| 378 | HANDLE NtCreateThread( LPVOID lpRemoteThreadStart, LPVOID lpParam, DWORD createFlags, DWORD* threadId ) |
| 379 | { |