Now I really need you help people.
Ok, here is the problem: LdrInitializeThunk is called from within start_process - the first thing to be executed in the new process's context. But this is not right. All what I found so far indicates, that LdrInitializeThunk should be queued as an APC, so it executes first no matter what.
To complicate matters more, LdrInitializeThunk calling wineserver to stop the process if it's created with CREATE_SUSPENDED flag set. This is wrong. New process should never make it to it's main thread yet. And even worse, none of this happens where it should be - in ntdll. Functions such as NtCreateProcess and NtCreateThread are stubs. So when I'm looking on-line for any information, they all refer to these ntdll functions.
I'm looking at this code and can't figure out what part of it belongs where. In kernel we have: 1. CreateProcessW that figures out what the executable is and calls the one of the other functions. That's talk about PE for now (create_process). 2. create_process: I'm not sure what the first part does (something about child). It looks to me that most of the first part including new_process wineserver call should be a part of NtCreateProcess. Everything else from create_process should go into NtCreateThread. 3. THREAD_InitStack shoul probably stay, except all the memory allocation goes to NtCreateThread. 4. start_process should stay the way it is, except delete call to LdrInitializeThunk. 5. LdrInitializeThunk - have no clue what should stay, and what should go somewhere else.
Then we have a wineserver's init_process_done. Some parts of it looks like should go into create_process. But I'm not sure here ether.
Vitaliy Margolen wrote:
Now I really need you help people.
Ok, here is the problem: LdrInitializeThunk is called from within start_process - the first thing to be executed in the new process's context. But this is not right. All what I found so far indicates, that LdrInitializeThunk should be queued as an APC, so it executes first no matter what.
That's because we run on top of other libraries and they need to be initialized first.
To complicate matters more, LdrInitializeThunk calling wineserver to stop the process if it's created with CREATE_SUSPENDED flag set. This is wrong. New process should never make it to it's main thread yet.
Unfortunately, I don't believe there is a syscall that will allow use to create a process truly suspended.
And even worse, none of this happens where it should be - in ntdll. Functions such as NtCreateProcess and NtCreateThread are stubs. So when I'm looking on-line for any information, they all refer to these ntdll functions.
I believe these functions are too low level to be reasonably implemented in Wine. We defer to a threading library, which roughly corresponds to the kernel32 API, whereas the ntdll API corresponds to us having to make syscalls ourselves. Also, NT process objects don't map exactly to Unix process objects. For example, in NT you can create a process without any threads.
Saturday, September 10, 2005, 2:04:23 PM, Robert Shearman wrote:
Vitaliy Margolen wrote:
Now I really need you help people.
Ok, here is the problem: LdrInitializeThunk is called from within start_process - the first thing to be executed in the new process's context. But this is not right. All what I found so far indicates, that LdrInitializeThunk should be queued as an APC, so it executes first no matter what.
That's because we run on top of other libraries and they need to be initialized first.
But can this be done _after_ main thread resumes? Or partially on process creation, inside LdrInitializeThunk after thread resumes?
To complicate matters more, LdrInitializeThunk calling wineserver to stop the process if it's created with CREATE_SUSPENDED flag set. This is wrong. New process should never make it to it's main thread yet.
Unfortunately, I don't believe there is a syscall that will allow use to create a process truly suspended.
It's not a major problem here. What is, is that on windows it is possible to "inject" some code into newly created process and execute it _before_ call to entry point. This code can do pretty much anything, as long as it handles exceptions itself because default exception stack is not setup yet. For obvious reasons you can't do whole lot before LdrInitializeThunk done initializing new process. So windows queues it as an APC to the new process. This way it will be called first when the process resumes. What wine does, is not correct. A simple way to fix this, is to move call to LdrInitializeThunk outside _TRY block and suspend thread not inside wineserver but before _TRY block in start_process.
And even worse, none of this happens where it should be - in ntdll. Functions such as NtCreateProcess and NtCreateThread are stubs. So when I'm looking on-line for any information, they all refer to these ntdll functions.
I believe these functions are too low level to be reasonably implemented in Wine. We defer to a threading library, which roughly corresponds to the kernel32 API, whereas the ntdll API corresponds to us having to make syscalls ourselves. Also, NT process objects don't map exactly to Unix process objects. For example, in NT you can create a process without any threads.
Yeah that's what I thought. But eventually all wineserver calls will need to go into ntdll. I'm hopping that some day it will be possible to use native kernel32 to test how close our ntdll to native. So this is not as big of a problem ATM.
Vitaliy.