Hmm, maybe make explorer responsible for putting up the messagebox, and set up some IPC method (good lord, not COM, just some mailbox or something) for the loader to notify it...
On Wed, Apr 23, 2008 at 10:51 PM, Dan Kegel dank@kegel.com wrote:
Hmm, maybe make explorer responsible for putting up the messagebox, and set up some IPC method (good lord, not COM, just some mailbox or something) for the loader to notify it...
I thought of that, but your going to end up invoking more crap I really think you don't need. This is a failure case after all. Explorer is not running at this point so that means you have to start it, then you could to send the messages which would be the simplest form of IPC to it which is going to delay load user32 anyway so it can display the message box...Its better just to do the equivalent of LoadLibrary/GetProcAddress in the loader from a helper function and be done with it.
On Wed, Apr 23, 2008 at 8:00 PM, Steven Edwards winehacker@gmail.com wrote:
Hmm, maybe make explorer responsible for putting up the messagebox, and set up some IPC method for the loader to notify it...
I thought of that, but your going to end up invoking more crap I really think you don't need. This is a failure case after all. Explorer is not running at this point
Why not? I thought Explorer was the first thing to start up... - Dan
On Wed, Apr 23, 2008 at 11:14 PM, Dan Kegel dank@kegel.com wrote:
Why not? I thought Explorer was the first thing to start up...
Your right, I thought it was loaded yet but I guess it does anytime user32 is initalized. Looking at the process list after the messagebox exits only wineserver, services and winedevice stay resident for a while so I thought it had not loaded yet. I'll see if I can rework it to send a message to explorer to display the dialog.
On Thu, Apr 24, 2008 at 12:33 AM, Steven Edwards winehacker@gmail.com wrote:
Your right, I thought it was loaded yet but I guess it does anytime user32 is initalized. Looking at the process list after the messagebox exits only wineserver, services and winedevice stay resident for a while so I thought it had not loaded yet. I'll see if I can rework it to send a message to explorer to display the dialog.
You were right. Looking at it a bit more maybe the best route is to add a set of custom messages to user32 and explorer maybe something like WM_WINE_DLLNOTFOUND/WM_WINE_MISSINGFUCTION or something and manually do the server call using send_message. I am not exactly sure how to do it as the actual wineserver call yet. I'll look at it a bit more tomorrow and see if I can figure the plumbing out.
On Wed, Apr 23, 2008 at 9:45 PM, Steven Edwards winehacker@gmail.com wrote:
On Thu, Apr 24, 2008 at 12:33 AM, Steven Edwards winehacker@gmail.com wrote:
Your right, I thought it was loaded yet but I guess it does anytime user32 is initalized. Looking at the process list after the messagebox exits only wineserver, services and winedevice stay resident for a while so I thought it had not loaded yet. I'll see if I can rework it to send a message to explorer to display the dialog.
You were right. Looking at it a bit more maybe the best route is to add a set of custom messages to user32 and explorer maybe something like WM_WINE_DLLNOTFOUND/WM_WINE_MISSINGFUCTION or something and manually do the server call using send_message. I am not exactly sure how to do it as the actual wineserver call yet. I'll look at it a bit more tomorrow and see if I can figure the plumbing out.
Alternately we could cheeze it and exec xmessage :-)
"Steven Edwards" winehacker@gmail.com writes:
On Wed, Apr 23, 2008 at 11:14 PM, Dan Kegel dank@kegel.com wrote:
Why not? I thought Explorer was the first thing to start up...
Your right, I thought it was loaded yet but I guess it does anytime user32 is initalized. Looking at the process list after the messagebox exits only wineserver, services and winedevice stay resident for a while so I thought it had not loaded yet. I'll see if I can rework it to send a message to explorer to display the dialog.
You certainly don't want to call through explorer for that, showing a message box directly is fine. You have to be careful to only do it when loading the main exe, not for any random dll load; also you have to properly handle the case of a missing X display.
On Thu, Apr 24, 2008 at 2:36 AM, Alexandre Julliard julliard@winehq.org wrote:
You certainly don't want to call through explorer for that, showing a message box directly is fine.
Well, that's easier :-)
You have to be careful to only do it when loading the main exe, not for any random dll load
Yeah, I guess some apps tolerate missing DLLs by loading them manually. We'll miss a few problems (e.g. apps that delay-load but can't handle the missing dll) but that's ok.
also you have to properly handle the case of a missing X display
right, and just not call MessageBox.
Hmm, ideally we would send them to a web page that gave information tailored to the dll in question, but a MessageBox is good enough for 1.0.
On Thu, Apr 24, 2008 at 4:50 AM, Dan Kegel dank@kegel.com wrote:
On Thu, Apr 24, 2008 at 2:36 AM, Alexandre Julliard julliard@winehq.org wrote:
You certainly don't want to call through explorer for that, showing a message box directly is fine.
Well, that's easier :-)
You have to be careful to only do it when loading the main exe, not for any random dll load
Yeah, I guess some apps tolerate missing DLLs by loading them manually. We'll miss a few problems (e.g. apps that delay-load but can't handle the missing dll) but that's ok.
also you have to properly handle the case of a missing X display
right, and just not call MessageBox.
Hmm, ideally we would send them to a web page that gave information tailored to the dll in question, but a MessageBox is good enough for 1.0.
A link to a wiki page (http://wiki.winehq/MissingDLL ?) with list of
common dlls/where they come from/what they do/how to use winetricks/etc.) would be a bit easier/quicker to implement.
On Thu, Apr 24, 2008 at 5:36 AM, Alexandre Julliard julliard@winehq.org wrote:
You certainly don't want to call through explorer for that, showing a message box directly is fine. You have to be careful to only do it when loading the main exe, not for any random dll load; also you have to properly handle the case of a missing X display.
OK so is doing this in ntdll even the right case? I don't really see where to do it only from the main exe. I understand we don't want to report the error if the application is manually doing a GetProcAddress/LoadLibrary but again don't really know how to limit it. Here is my stab #2, it actually returns something sane to the user.
"Steven Edwards" winehacker@gmail.com writes:
On Thu, Apr 24, 2008 at 5:36 AM, Alexandre Julliard julliard@winehq.org wrote:
You certainly don't want to call through explorer for that, showing a message box directly is fine. You have to be careful to only do it when loading the main exe, not for any random dll load; also you have to properly handle the case of a missing X display.
OK so is doing this in ntdll even the right case? I don't really see where to do it only from the main exe.
It depends which cases you are trying to catch, but for the case of users starting an app from their desktop, you could probably do it in start.exe.
On Thu, Apr 24, 2008 at 11:12 AM, Alexandre Julliard julliard@winehq.org wrote:
It depends which cases you are trying to catch, but for the case of users starting an app from their desktop, you could probably do it in start.exe.
As per our discussion on IRC, start uses CreateProcess which according to Raymond and my own testing does not wait around and return anything of any meaning, see
http://blogs.msdn.com/oldnewthing/archive/2005/01/19/356048.aspx
So checking the return value and doing something like
WINE_ERR("start failed, error %d\n", GetLastError());
does not even work, let alone because if it finds the EXE there is no error as far as CreateProcess cares. On the other had, The child process returns an exit code such as STATUS_ENTRYPOINT_NOT_FOUND but I don't see how to get this information from the parent process, return it to start.exe.so and have start do something like print an error or display a message box. Can anyone lurking point me to an example of how to get the child's return value and pass that back to the parent?
Thanks
On Fri, Apr 25, 2008 at 8:50 AM, Steven Edwards winehacker@gmail.com wrote:
does not even work, let alone because if it finds the EXE there is no error as far as CreateProcess cares. On the other had, The child process returns an exit code such as STATUS_ENTRYPOINT_NOT_FOUND but I don't see how to get this information from the parent process, return it to start.exe.so and have start do something like print an error or display a message box. Can anyone lurking point me to an example of how to get the child's return value and pass that back to the parent?
A few ideas:
* have start.exe examine the import table of the exe and do an explicit check (hard)
* have start.exe set an environment variable saying "show graphical error box on dll load failure", and clear that before calling executed apps' WinMain() (easy)
On Fri, Apr 25, 2008 at 2:07 PM, Dan Kegel dank@kegel.com wrote:
- have start.exe examine the import table of the exe and do an explicit check
(hard)
Seems like too much to go in to start anyway. And I am lazy
- have start.exe set an environment variable saying "show graphical error box
on dll load failure", and clear that before calling executed apps' WinMain() (easy)
So something like start.exe.so in Unix mode would set a variable like VERSBOSE_USERDEBUG or which then we could query in the loader using RtlQueryEnvironmentVariable_U or something that would trigger the MessageBox from the example code I already wrote in ntdll?
Thanks Steven
On Sat, Apr 26, 2008 at 1:53 PM, Steven Edwards winehacker@gmail.com wrote:
- have start.exe set an environment variable saying "show graphical error box
on dll load failure", and clear that before calling executed apps' WinMain() (easy)
So something like start.exe.so in Unix mode would set a variable like VERSBOSE_USERDEBUG or which then we could query in the loader using RtlQueryEnvironmentVariable_U or something that would trigger the MessageBox from the example code I already wrote in ntdll?
So that worked. Comments are welcome!
On Sat, Apr 26, 2008 at 11:37 PM, Steven Edwards winehacker@gmail.com wrote:
- have start.exe set an environment variable saying "show
graphical error box
on dll load failure", and clear that before calling executed apps' WinMain()
So that worked. Comments are welcome!
1. I'd output the console message before the gui one.
2. You never clear that environment variable... what happens when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
On Sun, Apr 27, 2008 at 9:19 AM, Dan Kegel dank@kegel.com wrote:
- You never clear that environment variable... what happens
when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
I assume you mean if the application is just checking manually for the dll via GetModuleHandle or LoadLibrary? I'll write a test case for this to see if it causes a problem. My assumption was that the failure case for that was at a higher level but I'll check with a test case. I don't think we need to clear the variable....what I mean is I wonder if there is a way to set the variable to be inherited by all child processes launched by start.exe.so in unix mode. I'll look in to this as well.
On Mon, Apr 28, 2008 at 3:51 AM, Steven Edwards winehacker@gmail.com wrote:
On Sun, Apr 27, 2008 at 9:19 AM, Dan Kegel dank@kegel.com wrote:
- You never clear that environment variable... what happens
when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
I assume you mean if the application is just checking manually for the dll via GetModuleHandle or LoadLibrary? I'll write a test case for this to see if it causes a problem. My assumption was that the failure case for that was at a higher level but I'll check with a test case. I don't think we need to clear the variable....what I mean is I wonder if there is a way to set the variable to be inherited by all child processes launched by start.exe.so in unix mode. I'll look in to this as well.
I assumed the code path must be different so I wrote a test app that tried to do a GetProcAddress or LoadLibrary on a non-existent dll and was right, It did not throw the messagebox. So that just leaves the issue of do we want to clear the environment for the child process. My thinking is no, because I assume most applications that invoke other applications via CreateProcess inherit the environment of the parent just like apps started from start.exe.CreateProcess do. It would not really make since for a vendor to have an application foo.exe that calls bar.exe to be randomly setting and unsetting variables in the package so I assume then we want the verbose variable to remain resident for all child processes started by start.exe in case foo.exe calls bar.exe which is linked to a missing dll so the user will get a warning rather than just failing silently. Unless you can point me to a case otherwise I think that it is correct behavior.
IMHO if we can extend this patch a bit to return more information via the message box such as the name of the missing dll and also address the case of dlls that are there but with missing exports, then this should go in before the freeze so we have time to shake it down. If worse comes to worse we can revert it. I think the behavior as it stands with this patch is better than a user clicking on a menu or *.exe from KDE/GNOME and nothing happening at all.
Thanks Steven
Steven Edwards schrieb:
On Mon, Apr 28, 2008 at 3:51 AM, Steven Edwards winehacker@gmail.com wrote:
On Sun, Apr 27, 2008 at 9:19 AM, Dan Kegel dank@kegel.com wrote:
- You never clear that environment variable... what happens
when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
I assume you mean if the application is just checking manually for the dll via GetModuleHandle or LoadLibrary? I'll write a test case for this to see if it causes a problem. My assumption was that the failure case for that was at a higher level but I'll check with a test case. I don't think we need to clear the variable....what I mean is I wonder if there is a way to set the variable to be inherited by all child processes launched by start.exe.so in unix mode. I'll look in to this as well.
I assumed the code path must be different so I wrote a test app that tried to do a GetProcAddress or LoadLibrary on a non-existent dll and was right, It did not throw the messagebox.
But I think it will still trigger the msg box if the application is checking for an existent foo.dll via LoadLibrary and foo.dll depends on a missing xyz.dll. It won't trigger if you clear the environment variable as Dan said. I'm not sure though which way is the right one here.
On Tue, 29 Apr 2008, Peter Beutner wrote:
Steven Edwards schrieb:
On Mon, Apr 28, 2008 at 3:51 AM, Steven Edwards winehacker@gmail.com wrote:
On Sun, Apr 27, 2008 at 9:19 AM, Dan Kegel dank@kegel.com wrote:
- You never clear that environment variable... what happens
when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
I assume you mean if the application is just checking manually for the dll via GetModuleHandle or LoadLibrary? I'll write a test case for this to see if it causes a problem. My assumption was that the failure case for that was at a higher level but I'll check with a test case. I don't think we need to clear the variable....what I mean is I wonder if there is a way to set the variable to be inherited by all child processes launched by start.exe.so in unix mode. I'll look in to this as well.
I assumed the code path must be different so I wrote a test app that tried to do a GetProcAddress or LoadLibrary on a non-existent dll and was right, It did not throw the messagebox.
But I think it will still trigger the msg box if the application is checking for an existent foo.dll via LoadLibrary and foo.dll depends on a missing xyz.dll. It won't trigger if you clear the environment variable as Dan said. I'm not sure though which way is the right one here.
Windows doesn't do that - when my application tries to load a module that links against a missing DLL then LoadLibrary simply fails without showing any message. The "ignore it if LoadLibrary fails" logic is common in many programs that use optional plugins.
Paul Chitescu
Paul Chitescu schrieb:
On Tue, 29 Apr 2008, Peter Beutner wrote:
Steven Edwards schrieb:
On Mon, Apr 28, 2008 at 3:51 AM, Steven Edwards winehacker@gmail.com wrote:
On Sun, Apr 27, 2008 at 9:19 AM, Dan Kegel dank@kegel.com wrote:
- You never clear that environment variable... what happens
when an app just tests for the existence of a DLL by trying to load it? We don't want to print an error then. (That's why I originally suggested clearing the env var after the app finished loading. That's still broken -- it won't catch errors in helper exes -- but it's better than nothing.)
I assume you mean if the application is just checking manually for the dll via GetModuleHandle or LoadLibrary? I'll write a test case for this to see if it causes a problem. My assumption was that the failure case for that was at a higher level but I'll check with a test case. I don't think we need to clear the variable....what I mean is I wonder if there is a way to set the variable to be inherited by all child processes launched by start.exe.so in unix mode. I'll look in to this as well.
I assumed the code path must be different so I wrote a test app that tried to do a GetProcAddress or LoadLibrary on a non-existent dll and was right, It did not throw the messagebox.
But I think it will still trigger the msg box if the application is checking for an existent foo.dll via LoadLibrary and foo.dll depends on a missing xyz.dll. It won't trigger if you clear the environment variable as Dan said. I'm not sure though which way is the right one here.
Windows doesn't do that - when my application tries to load a module that links against a missing DLL then LoadLibrary simply fails without showing any message. The "ignore it if LoadLibrary fails" logic is common in many programs that use optional plugins.
So clearing the env variable would be the correct thing. But still not entirely satisfying as mentioned above by Dan.
I just tried to solve it differently, doing it entirely in ntdll. (and probably you could even do it without using a global variable) It certainly avoids all that pain dealing with environment variables ;).
Not really heavily tested, but I think it works.
On Tue, Apr 29, 2008 at 11:52 AM, Peter Beutner p.beutner@gmx.net wrote:
So clearing the env variable would be the correct thing. But still not entirely satisfying as mentioned above by Dan.
I just tried to solve it differently, doing it entirely in ntdll. (and probably you could even do it without using a global variable) It certainly avoids all that pain dealing with environment variables ;).
Not really heavily tested, but I think it works.
I think your patch is better than mine in that the message box is more verbose but we still want the console ERR to print first and the MessageBox error to only show up from applications started with start.exe.so in Unix mode. I'll combine my patch with yours and send it along for further comment from Alexandre.
On Tue, Apr 29, 2008 at 10:44 AM, Paul Chitescu paulc@voip.null.ro wrote:
Windows doesn't do that - when my application tries to load a module that links against a missing DLL then LoadLibrary simply fails without showing any message. The "ignore it if LoadLibrary fails" logic is common in many programs that use optional plugins.
Then that would mean my patch is still correct. If LoadLibrary calls foo.dll which is present but xyz.dll is missing then LoadLibrary is still going to fail which will not trigger this case.
Steven Edwards schrieb:
On Tue, Apr 29, 2008 at 10:44 AM, Paul Chitescu paulc@voip.null.ro wrote:
Windows doesn't do that - when my application tries to load a module that links against a missing DLL then LoadLibrary simply fails without showing any message. The "ignore it if LoadLibrary fails" logic is common in many programs that use optional plugins.
Then that would mean my patch is still correct. If LoadLibrary calls foo.dll which is present but xyz.dll is missing then LoadLibrary is still going to fail which will not trigger this case.
LoadLibrary will fail but the msg box will be displayed. just try:
int main(int argc, char **argv) { HMODULE hmod;
hmod = LoadLibrary("cryptnet.dll");
return 0; }
then remove/rename crypt32.dll.so(which is imported by cryptnet.dll) and run
wine start.exe /unix test.exe
And the msg box will pop up.
On Tue, Apr 29, 2008 at 1:28 PM, Peter Beutner p.beutner@gmx.net wrote:
And the msg box will pop up.
Your right. I see unless report_missing_dll_verbose is unset then its going to spam on every dependent dll load failure for LoadLibrary. Here is your and my patch combined.
Julliard: Can you comment please?
Thanks
"Steven Edwards" winehacker@gmail.com writes:
On Tue, Apr 29, 2008 at 1:28 PM, Peter Beutner p.beutner@gmx.net wrote:
And the msg box will pop up.
Your right. I see unless report_missing_dll_verbose is unset then its going to spam on every dependent dll load failure for LoadLibrary. Here is your and my patch combined.
Julliard: Can you comment please?
That's ugly, both the environment variable hack and the global verbose flag are really bad. There has to be a better way to do this.
On Tue, Apr 29, 2008 at 2:12 PM, Alexandre Julliard julliard@winehq.org wrote:
That's ugly, both the environment variable hack and the global verbose flag are really bad. There has to be a better way to do this.
I am open to suggestions =)