Какая функция просто убивает поток, но не процесс?

Тема в разделе "WASM.BEGINNERS", создана пользователем amvoz, 11 апр 2009.

  1. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    #39 слишком много букоф.
    Что тебе описание её привести из мсдн ?
    Короче ничего не могу предложить, я хз что ты пытаешься сделать.
     
  2. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Я повторю.
    То есть я правильно понял, что её больше использовать не надо?
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Код (Text):
    1. HANDLE
    2. APIENTRY
    3. CreateRemoteThread(
    4.     HANDLE hProcess,
    5.     LPSECURITY_ATTRIBUTES lpThreadAttributes,
    6.     DWORD dwStackSize,
    7.     LPTHREAD_START_ROUTINE lpStartAddress,
    8.     LPVOID lpParameter,
    9.     DWORD dwCreationFlags,
    10.     LPDWORD lpThreadId
    11.     )
    12.  
    13. /*++
    14.  
    15. Routine Description:
    16.  
    17.     A thread object can be created to execute within the address space of the
    18.     another process using CreateRemoteThread.
    19.  
    20.     Creating a thread causes a new thread of execution to begin in the address
    21.     space of the current process. The thread has access to all objects opened
    22.     by the process.
    23.  
    24.     The thread begins executing at the address specified by the StartAddress
    25.     parameter. If the thread returns from this procedure, the results are
    26.     un-specified.
    27.  
    28.     The thread remains in the system until it has terminated and
    29.     all handles to the thread
    30.     have been closed through a call to CloseHandle.
    31.  
    32.     When a thread terminates, it attains a state of signaled satisfying all
    33.     waits on the object.
    34.  
    35.     In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
    36.     object type specific access flags are valid for thread objects:
    37.  
    38.         - THREAD_QUERY_INFORMATION - This access is required to read
    39.           certain information from the thread object.
    40.  
    41.         - SYNCHRONIZE - This access is required to wait on a thread
    42.           object.
    43.  
    44.         - THREAD_GET_CONTEXT - This access is required to read the
    45.           context of a thread using GetThreadContext.
    46.  
    47.         - THREAD_SET_CONTEXT - This access is required to write the
    48.           context of a thread using SetThreadContext.
    49.  
    50.         - THREAD_SUSPEND_RESUME - This access is required to suspend or
    51.           resume a thread using SuspendThread or ResumeThread.
    52.  
    53.         - THREAD_ALL_ACCESS - This set of access flags specifies all of
    54.           the possible access flags for a thread object.
    55.  
    56. Arguments:
    57.  
    58.     hProcess - Supplies the handle to the process in which the thread is
    59.         to be create in.
    60.  
    61.     lpThreadAttributes - An optional parameter that may be used to specify
    62.         the attributes of the new thread.  If the parameter is not
    63.         specified, then the thread is created without a security
    64.         descriptor, and the resulting handle is not inherited on process
    65.         creation.
    66.  
    67.     dwStackSize - Supplies the size in bytes of the stack for the new thread.
    68.         A value of zero specifies that the thread's stack size should be
    69.         the same size as the stack size of the first thread in the process.
    70.         This size is specified in the application's executable file.
    71.  
    72.     lpStartAddress - Supplies the starting address of the new thread.  The
    73.         address is logically a procedure that never returns and that
    74.         accepts a single 32-bit pointer argument.
    75.  
    76.     lpParameter - Supplies a single parameter value passed to the thread.
    77.  
    78.     dwCreationFlags - Supplies additional flags that control the creation
    79.         of the thread.
    80.  
    81.         dwCreationFlags Flags:
    82.  
    83.         CREATE_SUSPENDED - The thread is created in a suspended state.
    84.             The creator can resume this thread using ResumeThread.
    85.             Until this is done, the thread will not begin execution.
    86.  
    87.     lpThreadId - Returns the thread identifier of the thread.  The
    88.         thread ID is valid until the thread terminates.
    89.  
    90. Return Value:
    91.  
    92.     NON-NULL - Returns a handle to the new thread.  The handle has full
    93.         access to the new thread and may be used in any API that
    94.         requires a handle to a thread object.
    95.  
    96.     NULL - The operation failed. Extended error status is available
    97.         using GetLastError.
    98.  
    99. --*/
    100.  
    101. {
    102.     NTSTATUS Status;
    103.     OBJECT_ATTRIBUTES Obja;
    104.     POBJECT_ATTRIBUTES pObja;
    105.     HANDLE Handle;
    106.     CONTEXT ThreadContext;
    107.     INITIAL_TEB InitialTeb;
    108.     CLIENT_ID ClientId;
    109.     ULONG i;
    110.  
    111. #if !defined(BUILD_WOW6432)
    112.     BASE_API_MSG m;
    113.     PBASE_CREATETHREAD_MSG a = (PBASE_CREATETHREAD_MSG)&m.u.CreateThread;
    114. #endif
    115.  
    116. #if defined(WX86) || defined(_AXP64_)
    117.     BOOL bWx86 = FALSE;
    118.     HANDLE Wx86Info;
    119.     PWX86TIB Wx86Tib;
    120. #endif
    121.  
    122.  
    123.  
    124.     //
    125.     // Allocate a stack for this thread in the address space of the target
    126.     // process.
    127.     //
    128.  
    129.     Status = BaseCreateStack(
    130.                 hProcess,
    131.                 dwStackSize,
    132.                 0L,
    133.                 &InitialTeb
    134.                 );
    135.  
    136.     if ( !NT_SUCCESS(Status) ) {
    137.         BaseSetLastNTError(Status);
    138.         return NULL;
    139.         }
    140.  
    141.     //
    142.     // Create an initial context for the new thread.
    143.     //
    144.  
    145.     BaseInitializeContext(
    146.         &ThreadContext,
    147.         lpParameter,
    148.         (PVOID)lpStartAddress,
    149.         InitialTeb.StackBase,
    150.         BaseContextTypeThread
    151.         );
    152.  
    153.     pObja = BaseFormatObjectAttributes(&Obja,lpThreadAttributes,NULL);
    154.  
    155.  
    156.     Status = NtCreateThread(
    157.                 &Handle,
    158.                 THREAD_ALL_ACCESS,
    159.                 pObja,
    160.                 hProcess,
    161.                 &ClientId,
    162.                 &ThreadContext,
    163.                 &InitialTeb,
    164.                 TRUE
    165.                 );
    166.     if (!NT_SUCCESS(Status)) {
    167.         BaseFreeThreadStack(hProcess,NULL, &InitialTeb);
    168.         BaseSetLastNTError(Status);
    169.         return NULL;
    170.         }
    171.  
    172.  
    173.  
    174.     try {
    175.  
    176.  
    177. #if defined(WX86) || defined(_AXP64_)
    178.  
    179.         //
    180.         // Check the Target Processes to see if this is a Wx86 process
    181.         //
    182.         Status = NtQueryInformationProcess(hProcess,
    183.                                            ProcessWx86Information,
    184.                                            &Wx86Info,
    185.                                            sizeof(Wx86Info),
    186.                                            NULL
    187.                                            );
    188.         if (!NT_SUCCESS(Status)) {
    189.             leave;
    190.             }
    191.  
    192.         Wx86Tib = (PWX86TIB)NtCurrentTeb()->Vdm;
    193.  
    194.         //
    195.         // if Wx86 process, setup for emulation
    196.         //
    197.         if ((ULONG_PTR)Wx86Info == sizeof(WX86TIB)) {
    198.  
    199.             //
    200.             // create a WX86Tib and initialize it's Teb->Vdm.
    201.             //
    202.             Status = BaseCreateWx86Tib(hProcess,
    203.                                        Handle,
    204.                                        (ULONG)((ULONG_PTR)lpStartAddress),
    205.                                        dwStackSize,
    206.                                        0L,
    207.                                        (Wx86Tib &&
    208.                                         Wx86Tib->Size == sizeof(WX86TIB) &&
    209.                                         Wx86Tib->EmulateInitialPc)
    210.                                        );
    211.             if (!NT_SUCCESS(Status)) {
    212.                 leave;
    213.                 }
    214.  
    215.             bWx86 = TRUE;
    216.  
    217.             }
    218.         else if (Wx86Tib && Wx86Tib->EmulateInitialPc) {
    219.  
    220.             //
    221.             // if not Wx86 process, and caller wants to call x86 code in that
    222.             // process, fail the call.
    223.             //
    224.             Status = STATUS_ACCESS_DENIED;
    225.             leave;
    226.  
    227.             }
    228.  
    229. #endif  // WX86
    230.  
    231.  
    232.         //
    233.         // Call the Windows server to let it know about the
    234.         // process.
    235.         //
    236.         if ( !BaseRunningInServerProcess ) {
    237.  
    238. #if defined(BUILD_WOW6432)
    239.             Status = CsrBasepCreateThread(Handle,
    240.                                           ClientId
    241.                                           );
    242. #else
    243.             a->ThreadHandle = Handle;
    244.             a->ClientId = ClientId;
    245.             CsrClientCallServer( (PCSR_API_MSG)&m,
    246.                                  NULL,
    247.                                  CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
    248.                                                       BasepCreateThread
    249.                                                     ),
    250.                                  sizeof( *a )
    251.                                );
    252.  
    253.             Status = m.ReturnValue;
    254. #endif
    255.         }
    256.  
    257.         else {
    258.             if (hProcess != NtCurrentProcess()) {
    259.                 CSRREMOTEPROCPROC ProcAddress;
    260.                 ProcAddress = (CSRREMOTEPROCPROC)GetProcAddress(
    261.                                                     GetModuleHandleA("csrsrv"),
    262.                                                     "CsrCreateRemoteThread"
    263.                                                     );
    264.                 if (ProcAddress) {
    265.                     Status = (ProcAddress)(Handle, &ClientId);
    266.                     }
    267.                 }
    268.             }
    269.  
    270.  
    271.         if (!NT_SUCCESS(Status)) {
    272.             Status = (NTSTATUS)STATUS_NO_MEMORY;
    273.             }
    274.         else {
    275.  
    276.             if ( ARGUMENT_PRESENT(lpThreadId) ) {
    277.                 *lpThreadId = HandleToUlong(ClientId.UniqueThread);
    278.                 }
    279.  
    280.             if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
    281.                 NtResumeThread(Handle,&i);
    282.                 }
    283.             }
    284.  
    285.         }
    286.     finally {
    287.         if (!NT_SUCCESS(Status)) {
    288.             BaseFreeThreadStack(hProcess,
    289.                                 Handle,
    290.                                 &InitialTeb
    291.                                 );
    292.  
    293.             NtTerminateThread(Handle, Status);
    294.             NtClose(Handle);
    295.             BaseSetLastNTError(Status);
    296.             Handle = NULL;
    297.             }
    298.         }
    299.  
    300.  
    301.     return Handle;
    302.  
    303. }
    Сложный вопрос.. подождём ответ более опытных товарищей.
     
  4. Flasher

    Flasher Member

    Публикаций:
    0
    Регистрация:
    31 янв 2004
    Сообщения:
    640
    Рас уж этот поток единственный в процессе, не легче заморозить процесс полностью через ZwSuspendProcess, и возвратить к жизни через ZwResumeProcess ? И с хендлами потока возится не придется..
     
  5. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Нет, именно нужно процесс не замораживать.
    В этом примере это решение, может, и подойдёт.
    Но это пример всего лишь. На практике я собираюсь останавливать поток и возобновлять его в многопоточном приложении. Сами понимаете, там процесс нельзя замораживать.
     
  6. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Clerk, Вы пишете всё правильно, только не для того уровня, на котором находится спрашивающий, так что у вас с ним взаимное непонимание. NativeAPI и исходники винды - вещь, безусловно, интересная, но не для WASM.BEGINNERS.
    amvoz
    Вы, кажется, не понимаете нескольких базовых принципов. Вас уже отправляли читать Рихтера, тут я полностью присоединяюсь. Попробую объяснить, что Вы делаете неправильно, хотя не уверен, что это будет воспринято.

    Вариант первый.
    Код (Text):
    1. // первая программа
    2. int main()
    3. {
    4. MessageBox(...);
    5. SuspendThread(GetCurrentThread());
    6. // адрес следующей команды обозначим через M
    7. MessageBox(...);
    8. return 0;
    9. }
    10. // вторая программа
    11. int main()
    12. {
    13. HANDLE hProcess = ...;
    14. CreateRemoteThread(..., M, ...);
    15. }
    Здесь Вы пытаетесь создать поток, который бы начал выполняться с адреса M внутри функции. Общий принцип состоит в том, что нельзя передавать управление извне внутрь функции (за исключением случаев, когда Вы очень хорошо понимаете, что делаете, и работаете на уровне ассемблера).
    Дело в том, что у каждого потока есть своё состояние, и оно содержит далеко не только адрес выполняемой инструкции. Нормальный поток первой программы исполняет функцию main с самого начала и в результате этого пришёл в какое-то состояние, в котором можно было бы продолжать исполнение, но он замораживается. Ненормальный поток, создаваемый CreateRemoteThread из второй программы (поскольку не был приведён во всех деталях код для получения hProcess, я не могу сказать, правилен он или нет, но допустим, что правилен и поток действительно создаётся), находится в совершенно другом состоянии и, не проходя начало функции main, пытается продолжить её выполнение - это заведомо обречено на провал.
    (Комментарий для понимающих: компилятор видит, что MessageBox вызывается дважды, и для экономии запихивает её адрес в esi, а потом делает call esi. Естественно, после CreateRemoteThread в esi вовсе не адрес MessageBox.)

    Вариант второй.
    Код (Text):
    1. CreateRemoteThread(..., &ResumeThread, hThread, ...)
    В качестве hThread Вы берёте значение, выведенное главным потоком первой программы. Это означает, что Вы не понимаете, что такое "псевдодескриптор" (хотя и употребили это слово). А означает оно, что значение, выданное потоку функцией GetCurrentThread(), является дескриптором только для самого этого потока, а для других потоков (в том числе создаваемого по CreateRemoteThread) обозначает совсем другое. Так что второй поток размораживает сам себя - толку от этого никакого.

    Если нужно просто разморозить поток, то не нужно никакой CreateRemoteThread, а можно воспользоваться кодом в другом процессе
    Код (Text):
    1. HANDLE hThread = OpenThread(...);
    2. ResumeThread(hThread);
     
  7. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Спасибо
    Что ж я не восприму-то?
    Всё я восприму.
    Про псевдодескриптор- я предполагал, что раз он псевдо, но не дескриптор, то его действие огораничено. Предполагал также, что хорошо бы найти нормальный дескриптор.
    А вот функцию OpenThread имел ввиду, но оттягивал знакомство с ней до последнего. А знаете, почему? А Вы почитайте её описание и поймёте. Слова русские, но по сути бессмыслица. (а на английском если читать, то ещё хуже)

    "Открывает объект существующего потока"
    Я (не знающий!) должен это понять?
    Объект- понимаю, поток- понимаю, а вот объект потока... Объект чего-то... бр-р-р... Да тем более поток-то существует уже, а тут ещё объект его открывать надо.
    Это всё равно, что сказать: "Открываю объект существующей книги".
    Не открываю книгу, и даже не не открываю существующую книгу, а её объект. Во как.
    Вот и ограничиваешь себя в возможностях. Знаешь (или думаешь, что знаешь) одну-две функции и мусолишь их, почём зря. оттягивая такие вот глупые вопросы до последнего.
    И спросить-то не у кого.
     
  8. amvoz

    amvoz Member

    Публикаций:
    0
    Регистрация:
    12 ноя 2008
    Сообщения:
    640
    Cпешу тык скыть отчитаться о проделанной работе.
    Вот первый код. По его запуску рисуется первое окно и выводится PID потока, после чего поток останавливается.
    Вновь запускается поток другим приложением.
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. int main () {
    4.  MessageBoxA (0, окно\n", Первое\n", 0);
    5.  printf ("%x", GetCurrentThreadId());
    6.  SuspendThread ((void*)GetCurrentThread());
    7.  MessageBoxA (0, "окно\n", "Второе\n", 0);
    8.  return 0;
    9. };
    А вот этим приложением поток, замороженный в первом приложении запускается.
    И первое приложение продолжает выполняться (рисуется окно номер 2)
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. int main () {
    4.  DWORD PID_potoka;
    5.  printf ("Введи PID потока и он запустится\n");
    6.  scanf ("%x", &PID_potoka);
    7.  ResumeThread (OpenThread(THREAD_ALL_ACCESS, 0, PID_potoka));
    8. }
    Правда, остаются невыясненными кое-какие детали. Например, почему поток не останавливается по команде SuspendThread ((void*)GetCurrentThreadId
    Но это действительно детали.

    ...Среда программирования Dev C++ 4.9.2.2
    Если кто будет её использовать, то, возможно, у вас будут проблемы с функцией OpenThread
    Она объявлена в файле winbase.h так
    Код (Text):
    1. #if (_WIN32_WINNT >= 0x0500) || (_WIN32_WINDOWS >= 0x0490)
    2. WINBASEAPI HANDLE WINAPI OpenThread(DWORD,BOOL,DWORD);
    3. #endif
    И что-то она стопорилась. Я, не мудрствуя лукаво, приписал в файл строчку
    Код (Text):
    1. WINBASEAPI HANDLE WINAPI OpenThread(DWORD,BOOL,DWORD);
    Всё работает. Сижу теперь, жду, когда компьютер взорвётся.
    Что ещё... Значения первого параметра OpenThread прописаны в файле WINNT.H. Это значение ни в коем случае не должно быть равно нулю, иначе OpenThread вернёт 0.
    Может, из новичков кому пригодится. Спасибо всем.

    До новых встреч!