Repository navigation
Conversation
There was a problem hiding this comment.
Maybe we should be more deffensive here? Looks like this function could return ERROR_INSUFFICIENT_BUFFER. Also, these is some remark for Windows XP, which we (sadly) still support.
There was a problem hiding this comment.
Well, the function returns a DWORD, which is unsigned, so I'm not sure what the less than zero part was meant to signify? As I understand it the function returns zero on error and puts an explicit error code, such as ERROR_INSUFFICIENT_BUFFER, to be retrieved by GetLastError().
We should definitely make sure that the code works well for Windows XP, especially since these functions tend to behave strangely on XP with respect to null termination (unfortunately).
There was a problem hiding this comment.
Oh, reading the documentation again I see what you mean. Yes, I agree there should be a check for ERROR_INSUFFICIENT_BUFFER error case here. Taking note.
|
/cc @piscisaureus |
|
Okay, I improved it a bit, and now it works reliably and also adheres to the semantics inferred from the last few asserts of the However the current test has some code that (I quote) "verify that the path returned from uv_exepath is a subdirectory of executable_path". This seems incredibly brittle since not only is executable_path equal to Do you think it is it worth trying to work around the problem by e.g. stripping
Together with the invalid parameter asserts I believe this should fully verify all the postconditions that the function should meet and would be more robust, though a little bit more work, than the current version. Opinions? |
|
@TomCrypto your suggestions sound great to me! Bert (@piscisaureus) is our Chief Windows Officer, maybe he has some extra thoughts. |
There was a problem hiding this comment.
Why didn't you just set all share flags (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE) ?
There was a problem hiding this comment.
Good point, I actually just lifted the parameters to CreateFile straight from the MSDN page for GetFinalPathNameByHandle thinking they would be appropriate, but I agree now they are not very permissive in the context of opening one's own executable file. Changing them.
Another thing that worries me a little bit is that opening the .exe file may not succeed, so I'd like to be as defensive as possible. I spent some time checking whether there is a method to obtain the HANDLE to the primary section that was used to create the process, but it seems that there's no easy method for that. So I guess this strategy will have to do. In general the patch looks well-written and clean to me. Good work! |
|
Thanks! For the fallback, I think falling back to GUID is best. After all if the executable isn't on a mapped drive it's already a weird situation IMHO. If everything fails I guess the result of About stripping |
Added some helper functions.
|
Rewrote the function to be able to handle fallback, now it does the following:
That means that as long as |
|
GetFinalPathNameByHandleW isn't supported in Windows XP/2k3. I'm fine with landing this after we officially drop support for them. |
|
We now use |
|
I'm going to close this one. We use |
This is a draft of a possible fix to #206. It uses
GetModuleFileNameWas before to get some kind of path to the executable, and then gets a handle to the file and resolves the full path (without any symlinks) usingGetFinalPathNameByHandleW. It's not finished, of course, I have a few questions. With this commit the function will read through symbolic links and return resolved paths like:Which are completely valid (and fully resolved) Windows paths, but the
VOLUME_NAME_DOSflag used means that the file actually needs to be on a mounted drive with an assigned drive letter or the function will fail withERROR_PATH_NOT_FOUND, as MSDN states. The file could be on a mounted drive with no drive letter assigned, and in this case I assume it could be addressed via its GUID (viaVOLUME_NAME_GUID) as a long UNC path. But is this realistic?Basically should the function return "usual" paths like
C:\path\to\executable.exeor should it return full-blown UNC paths (which, by the way, apparently can be slightly longer than 32768 characters)? Or whichever is shorter? Does anyone have an opinion on this?I mean, logically the function should never fail (besides out of resource errors) since the executable always exists somewhere, but this could be a faulty assumption?
EDIT: actually I noticed that the exepath test expects the passed buffer to be filled and truncated if it is too short, so since
uv_exepathis a two-step process now it might be necessary to allocate 32KB of memory upfront to reliably get the initial path and then have theGetFinalPathNameByHandleWfunction handle the truncation for us, assuming it does (since the expanded full path may be longer than the symlink). I'll need to look into that.