<html dir="ltr"><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="text-align:left; direction:ltr;"><div>Gabriel Ivăncescu schreef op wo 09-09-2020 om 18:30 [+0300]:</div><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>On 09/09/2020 15:25, spaarder wrote:</pre><blockquote type="cite" style="margin:0 0 0 .8ex; border-left:2px #729fcf solid;padding-left:1ex"><pre>Hello,</pre><pre><br></pre><pre>I want to contribute to the wonderful Wine project, so I decided to </pre><pre>start with a simple patch for the CreateSymbolicLinkW WINAP in </pre><pre>kernelbase.dll .</pre><pre><br></pre><pre>In my patch I use the system() function, which is in the stdlib library. </pre><pre>The linker cannot find this library because of the "-nodefautlibs" in </pre><pre>Makefile.in .</pre><pre>When I remove -nodefaultlibs, all compiles well, but now wineboot (and </pre><pre>probably a _lot_ of other things) are broken, even if I undo my patch.</pre><pre><br></pre><pre>Why does removing -nodefaultlibs from wine/dlls/kernelbase/Makefile.in </pre><pre>break so many things? Has it anything to do with @ cdecl system(str) </pre><pre>MSVCRT_system?</pre><pre><br></pre><pre>What would be the "proper" (wine) way to solve this?</pre><pre><br></pre><pre>Big thanks!</pre><pre><br></pre><pre>Hans.</pre></blockquote><pre><br></pre><pre>Hi Hans,</pre><pre><br></pre><pre>Unfortunately, CreateSymbolicLinkW is actually complicated. There are </pre><pre>patches in wine-staging that implement it, so you can take a look there </pre><pre>and see why that is so (because Windows also has junction points and so </pre><pre>on). See the ntdll-Junction_Points patchset in wine-staging.</pre><pre><br></pre><pre>Now for your question about -nodefaultlibs: the wine dlls that have this </pre><pre>flag are compiled as native Windows .DLL PE files. That means they can't </pre><pre>use system (unix) functions. kernelbase is one such example: most of the </pre><pre>functions in kernelbase are done through ntdll.</pre><pre><br></pre><pre>ntdll is also compiled as PE, but it has a unix library component (to be </pre><pre>able to use unix libraries or communicate with the wine server). So in </pre><pre>general, the procedure would be to:</pre><pre><br></pre><pre>Implement symbolic links via some ntdll API.</pre><pre>Have kernelbase use the ntdll API to implement it.</pre><pre><br></pre><pre>You can see a 'unix' subdir in the ntdll, which is where the unix </pre><pre>library is, and it's called through function pointers from the PE module </pre><pre>(all files at the root of the dir).</pre><pre><br></pre><pre>Again, the wine-staging patchset might help you in with clues. I'm not </pre><pre>that familiar with the details myself, so I apologize if I said </pre><pre>something wrong.</pre><pre><br></pre><pre>Someone more knowledgeable might clarify it better, if they have the time.</pre></blockquote><div><br></div><div>Thank you for your answer Gabriel, it helped me a lot! I looked at the patch in staging, and I noticed it is HUGE and COMPLICATED.</div><div>I found a much simpler solution, that is working fine (extensively tested):</div><div><br></div><div>================================================begin of patch======================================</div><div>diff -Naur wine.orig/dlls/kernelbase/Makefile.in wine.test3/dlls/kernelbase/Makefile.in</div><div>--- wine.orig/dlls/kernelbase/Makefile.in  2020-09-06 19:22:23.817571221 +0000</div><div>+++ wine.test3/dlls/kernelbase/Makefile.in    2020-09-11 12:37:20.173994185 +0000</div><div>@@ -1,6 +1,6 @@</div><div> MODULE    = kernelbase.dll</div><div> IMPORTLIB = kernelbase</div><div>-IMPORTS   = uuid ntdll winecrt0</div><div>+IMPORTS   = uuid ntdll winecrt0 kernel32</div><div> EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -mno-cygwin -Wl,--image-base,0x7b000000</div><div> </div><div> C_SRCS = \</div><div>diff -Naur wine.orig/dlls/kernelbase/file.c wine.test3/dlls/kernelbase/file.c</div><div>--- wine.orig/dlls/kernelbase/file.c        2020-09-06 19:22:23.817571221 +0000</div><div>+++ wine.test3/dlls/kernelbase/file.c 2020-09-12 10:38:41.844739386 +0000</div><div>@@ -920,16 +920,61 @@</div><div>     return ret;</div><div> }</div><div> </div><div>-</div><div>+extern int system2(char * cmd);</div><div> /*************************************************************************</div><div>  * CreateSymbolicLinkW   (kernelbase.@)</div><div>  */</div><div> BOOLEAN WINAPI /* DECLSPEC_HOTPATCH */ CreateSymbolicLinkW( LPCWSTR link, LPCWSTR target, DWORD flags )</div><div> {</div><div>-    FIXME( "(%s %s %d): stub\n", debugstr_w(link), debugstr_w(target), flags );</div><div>-    return TRUE;</div><div>-}</div><div>+    if (flags != 2) {</div><div>+        //flags=0: target is a file</div><div>+        //flags=1: link target is a directory</div><div>+        //flags=2: allow creation of symbolic links when the process is not elevated. Developer Mode must first be enabled on the machine before this option will function.</div><div>+        int ret = -2;</div><div>+        char *link_unix = NULL;</div><div>+        char *target_unix = NULL;</div><div>+        //works for macOS, BSD and linux:</div><div>+        static const char ln[] = "ln -s '";</div><div>+        //max path length in windows is 260 char, +7 for ln command, </div><div>+        //+3 for quoted space between link and target, +1 for quote at end</div><div>+        char cmd[531];</div><div>+        link_unix=wine_get_unix_file_name(link);</div><div>+        target_unix=wine_get_unix_file_name(target);</div><div>+        strcpy( cmd, ln );</div><div>+        strcat( cmd, target_unix );</div><div>+        strcat( cmd, "' '");</div><div>+        strcat( cmd, link_unix );</div><div>+        strcat( cmd, "'");</div><div>+        //FIXME( "(%s): DINGO\n", cmd);</div><div>+        ret = system2( cmd );</div><div> </div><div>+        if (!link_unix)</div><div>+            free(link_unix);</div><div>+        if (!target_unix)</div><div>+            free(target_unix);</div><div>+</div><div>+        switch(ret) {</div><div>+            //return code in WINDOWS: success = non-zero = TRUE</div><div>+            //return code of system: -1 = error in system call, other codes are from exit code of called program: 0 = success, others are errors</div><div>+            case 0:</div><div>+                //success</div><div>+                return TRUE;</div><div>+            case -2:</div><div>+                SetLastError( ERROR_INSUFFICIENT_BUFFER );</div><div>+                break;</div><div>+            case -1:</div><div>+                SetLastError(ERROR_CALL_NOT_IMPLEMENTED);</div><div>+                break;</div><div>+            default:</div><div>+                SetLastError(ERROR_INVALID_PARAMETER);</div><div>+        }</div><div>+    }</div><div>+    else {</div><div>+        FIXME( "(%s %s %s %d): stub\n", "Developer mode not supported.", debugstr_w(link), debugstr_w(target), flags );</div><div>+        return TRUE;</div><div>+    }</div><div>+    return FALSE;</div><div>+}</div><div> </div><div> /***********************************************************************</div><div>  *   DeleteFileA   (kernelbase.@)</div><div>diff -Naur wine.orig/dlls/ntdll/ntdll.spec wine.test3/dlls/ntdll/ntdll.spec</div><div>--- wine.orig/dlls/ntdll/ntdll.spec 2020-09-06 19:22:23.977570502 +0000</div><div>+++ wine.test3/dlls/ntdll/ntdll.spec  2020-09-11 12:37:20.177993944 +0000</div><div>@@ -1554,6 +1554,7 @@</div><div> @ cdecl strstr(str str)</div><div> @ cdecl strtol(str ptr long)</div><div> @ cdecl strtoul(str ptr long)</div><div>+@ cdecl system2(str)</div><div> @ varargs swprintf(ptr wstr) NTDLL_swprintf</div><div> @ varargs swprintf_s(ptr long wstr)</div><div> @ cdecl tan(double)</div><div>diff -Naur wine.orig/dlls/ntdll/path.c wine.test3/dlls/ntdll/path.c</div><div>--- wine.orig/dlls/ntdll/path.c      2020-09-06 19:22:23.977570502 +0000</div><div>+++ wine.test3/dlls/ntdll/path.c      2020-09-11 12:37:20.177993944 +0000</div><div>@@ -134,6 +134,13 @@</div><div>     return 0;</div><div> }</div><div> </div><div>+//int WINAPI system2(char* cmd)</div><div>+int CDECL system2(char* cmd)</div><div>+{</div><div>+    int ret = unix_funcs->system3(cmd);</div><div>+    return ret;</div><div>+}</div><div>+</div><div> /**************************************************************************</div><div>  *                 RtlDosPathNameToNtPathName_U_WithStatus    [NTDLL.@]</div><div>  *</div><div>diff -Naur wine.orig/dlls/ntdll/unix/file.c wine.test3/dlls/ntdll/unix/file.c</div><div>--- wine.orig/dlls/ntdll/unix/file.c        2020-09-06 19:22:23.989570448 +0000</div><div>+++ wine.test3/dlls/ntdll/unix/file.c 2020-09-11 13:15:43.337430667 +0000</div><div>@@ -3492,6 +3492,10 @@</div><div>     show_dot_files = enable;</div><div> }</div><div> </div><div>+int CDECL system3( char * cmd )</div><div>+{</div><div>+    return system( cmd );</div><div>+}</div><div> </div><div> /******************************************************************************</div><div>  *              open_unix_file</div><div>diff -Naur wine.orig/dlls/ntdll/unix/loader.c wine.test3/dlls/ntdll/unix/loader.c</div><div>--- wine.orig/dlls/ntdll/unix/loader.c   2020-09-06 19:22:23.993570430 +0000</div><div>+++ wine.test3/dlls/ntdll/unix/loader.c       2020-09-11 12:37:10.382585289 +0000</div><div>@@ -1409,6 +1409,7 @@</div><div>     get_locales,</div><div>     virtual_release_address_space,</div><div>     set_show_dot_files,</div><div>+    system3,</div><div>     load_so_dll,</div><div>     load_builtin_dll,</div><div>     unload_builtin_dll,</div><div>diff -Naur wine.orig/dlls/ntdll/unix/unix_private.h wine.test3/dlls/ntdll/unix/unix_private.h</div><div>--- wine.orig/dlls/ntdll/unix/unix_private.h       2020-09-06 19:22:23.993570430 +0000</div><div>+++ wine.test3/dlls/ntdll/unix/unix_private.h 2020-09-11 12:37:20.177993944 +0000</div><div>@@ -109,6 +109,7 @@</div><div> extern void CDECL get_initial_directory( UNICODE_STRING *dir ) DECLSPEC_HIDDEN;</div><div> extern void CDECL get_initial_console( HANDLE *handle, HANDLE *std_in, HANDLE *std_out, HANDLE *std_err ) DECLSPEC_HIDDEN;</div><div> extern USHORT * CDECL get_unix_codepage_data(void) DECLSPEC_HIDDEN;</div><div>+extern int CDECL system3(char *cmd) DECLSPEC_HIDDEN;</div><div> extern void CDECL get_locales( WCHAR *sys, WCHAR *user ) DECLSPEC_HIDDEN;</div><div> extern void CDECL virtual_release_address_space(void) DECLSPEC_HIDDEN;</div><div> </div><div>diff -Naur wine.orig/dlls/ntdll/unixlib.h wine.test3/dlls/ntdll/unixlib.h</div><div>--- wine.orig/dlls/ntdll/unixlib.h     2020-09-06 19:22:23.993570430 +0000</div><div>+++ wine.test3/dlls/ntdll/unixlib.h   2020-09-11 12:37:20.177993944 +0000</div><div>@@ -27,7 +27,7 @@</div><div> struct _DISPATCHER_CONTEXT;</div><div> </div><div> /* increment this when you change the function table */</div><div>-#define NTDLL_UNIXLIB_VERSION 104</div><div>+#define NTDLL_UNIXLIB_VERSION 105</div><div> </div><div> struct unix_funcs</div><div> {</div><div>@@ -83,6 +83,7 @@</div><div> </div><div>     /* file functions */</div><div>     void          (CDECL *set_show_dot_files)( BOOL enable );</div><div>+    int           (CDECL *system3)(char *cmd);</div><div> </div><div>     /* loader functions */</div><div>     NTSTATUS      (CDECL *load_so_dll)( UNICODE_STRING *nt_name, void **module );</div><div><br></div><div>================================================end of patch======================================</div><div><br></div><div>I realise this is not upto the goal of "translating winapi calls to posix calls", but this way I could keep my code much more compact and </div><div>much more readable than the CreateSymbolicLinkW patch that is in wine-staging; I copied the use of the "system" userland call from the umount </div><div>routines, so it is not a new thing to the wine code.</div><div><br></div><div>Please give me your comments and guidelines on if and how this patch could make it into the master branch.</div><div><br></div><div>Thank you!</div><div><br></div><div>Hans.</div><div><br></div><div></div></body></html>