kernel32: Add an ability to execute 32-bit applications from 16-bit ones using winoldap.dll
Dmitry Timoshkov
dmitry at codeweavers.com
Tue Dec 25 00:24:46 CST 2007
Hello,
this patch should fix the problem reported in the bug 3620.
winoldap.mod in Windows is a 16-bit .exe which uses its command line to load
a 32-bit module and pass the parameters to it. Since winebuild doesn't allow
to create a 16-bit builtin exe, I decided to create a 16-bit builtin dll
instead. That adds some complexity due to need to create another thread to
launch a 32-bit application from, and wait until it finishes.
Changelog:
kernel32: Add an ability to execute 32-bit applications from 16-bit
ones using winoldap.dll.
---
.gitignore | 1 +
dlls/Makefile.in | 3 +-
dlls/kernel32/Makefile.in | 3 +-
dlls/kernel32/kernel16.c | 103 ++++++++++++++++++++++++++++++++++++++++++
dlls/kernel32/ne_module.c | 19 +++++++-
dlls/kernel32/winoldap.spec | 2 +
programs/winecfg/libraries.c | 1 +
7 files changed, 129 insertions(+), 3 deletions(-)
create mode 100644 dlls/kernel32/winoldap.spec
diff --git a/.gitignore b/.gitignore
index eee1787..5767c9c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -543,6 +543,7 @@ dlls/winmm/tests/winmm_crosstest.exe
dlls/winmm/winmm_res.res
dlls/winnls.dll16
dlls/winnls32/libwinnls32.def
+dlls/winoldap.dll16
dlls/winscard/libwinscard.def
dlls/winscard/rsrc.res
dlls/winsock.dll16
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index d7b0976..1ff64b7 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -385,6 +385,7 @@ WIN16_FILES = \
wineps16.drv16 \
wing.dll16 \
winnls.dll16 \
+ winoldap.dll16 \
winsock.dll16 \
wintab.dll16 \
wprocs.dll16
@@ -412,7 +413,7 @@ dispdib.dll16 gdi.exe16 wing.dll16:
imm.dll16:
echo "imm32.dll" >$@
-comm.drv16 krnl386.exe16 stress.dll16 system.drv16 toolhelp.dll16 win87em.dll16 windebug.dll16:
+comm.drv16 krnl386.exe16 stress.dll16 system.drv16 toolhelp.dll16 win87em.dll16 windebug.dll16 winoldap.dll16:
echo "kernel32.dll" >$@
lzexpand.dll16:
diff --git a/dlls/kernel32/Makefile.in b/dlls/kernel32/Makefile.in
index aab68e6..01c5847 100644
--- a/dlls/kernel32/Makefile.in
+++ b/dlls/kernel32/Makefile.in
@@ -16,7 +16,8 @@ SPEC_SRCS16 = \
system.drv.spec \
toolhelp.spec \
win87em.spec \
- windebug.spec
+ windebug.spec \
+ winoldap.spec
C_SRCS = \
actctx.c \
diff --git a/dlls/kernel32/kernel16.c b/dlls/kernel32/kernel16.c
index 50b11a0..bc9888b 100644
--- a/dlls/kernel32/kernel16.c
+++ b/dlls/kernel32/kernel16.c
@@ -130,3 +130,106 @@ HANDLE WINAPI CreateThread16( SECURITY_ATTRIBUTES *sa, DWORD stack,
args->param = param;
return CreateThread( sa, stack, start_thread16, args, flags, id );
}
+
+/***********************************************************************
+ * wait_input_idle
+ *
+ * Wrapper to call WaitForInputIdle user32 API
+ */
+static DWORD wait_input_idle( HANDLE process, DWORD timeout )
+{
+ HMODULE user32 = GetModuleHandleA( "user32.dll" );
+ if (user32)
+ {
+ DWORD (WINAPI *pWaitForInputIdle)( HANDLE hProcess, DWORD dwTimeOut );
+
+ pWaitForInputIdle = (void *)GetProcAddress( user32, "WaitForInputIdle" );
+ return pWaitForInputIdle( process, timeout );
+ }
+ return 0;
+}
+
+struct winexec_thread_args
+{
+ HANDLE event;
+ LPCSTR cmd_line;
+ UINT cmd_show;
+ BOOL ret;
+};
+
+static DWORD WINAPI winexec_thread( LPVOID param )
+{
+ struct winexec_thread_args *args = (struct winexec_thread_args *)param;
+ PROCESS_INFORMATION info;
+ STARTUPINFOA startup;
+ char *cmdline;
+ DWORD count;
+
+ args->ret = FALSE;
+
+ memset( &startup, 0, sizeof(startup) );
+ startup.cb = sizeof(startup);
+ startup.dwFlags = STARTF_USESHOWWINDOW;
+ startup.wShowWindow = args->cmd_show;
+
+ /* cmdline needs to be writable for CreateProcess */
+ if (!(cmdline = HeapAlloc( GetProcessHeap(), 0, strlen(args->cmd_line)+1 )))
+ {
+ SetEvent( args->event );
+ return 0;
+ }
+ strcpy( cmdline, args->cmd_line );
+
+ ReleaseThunkLock( &count );
+
+ if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE,
+ 0, NULL, NULL, &startup, &info ))
+ {
+ HINSTANCE16 hwinoldap;
+
+ /* Give 30 seconds to the app to come up */
+ wait_input_idle( info.hProcess, 30000 );
+
+ args->ret = TRUE;
+ SetEvent(args->event);
+
+ WaitForSingleObject( info.hProcess, INFINITE );
+
+ CloseHandle( info.hThread );
+ CloseHandle( info.hProcess );
+
+ /* decrement WINOLDAP usage count to signal that we have finished */
+ hwinoldap = GetModuleHandle16( "winoldap" );
+ FreeLibrary16( hwinoldap );
+ }
+
+ RestoreThunkLock( count );
+ HeapFree( GetProcessHeap(), 0, cmdline );
+
+ if (!args->ret);
+ SetEvent( args->event );
+
+ return 0;
+}
+
+/**************************************************************************
+ * WinExec (WINOLDAP.1)
+ */
+BOOL WINAPI WINOLDAP_WinExec( LPCSTR cmd_line, UINT cmd_show )
+{
+ HANDLE hthread;
+ struct winexec_thread_args args;
+
+ args.event = CreateEventW( NULL, 0, 0, NULL );
+ args.cmd_line = cmd_line;
+ args.cmd_show = cmd_show;
+ args.ret = FALSE;
+
+ hthread = CreateThread( NULL, 0, winexec_thread, &args, 0, 0 );
+ if (!hthread) return FALSE;
+
+ WaitForSingleObject( args.event, INFINITE );
+ CloseHandle( args.event );
+
+ return args.ret;
+}
diff --git a/dlls/kernel32/ne_module.c b/dlls/kernel32/ne_module.c
index e41ced9..2d95e41 100644
--- a/dlls/kernel32/ne_module.c
+++ b/dlls/kernel32/ne_module.c
@@ -1704,7 +1704,24 @@ HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
HeapFree( GetProcessHeap(), 0, cmdline );
if (name != lpCmdLine) HeapFree( GetProcessHeap(), 0, name );
- if (ret == 21 || ret == ERROR_BAD_FORMAT) /* 32-bit module or unknown executable*/
+ if (ret == 21) /* 32-bit module */
+ {
+ ret = LoadModule16( "winoldap.dll", NULL );
+
+ if (ret >= 32)
+ {
+ BOOL (WINAPI *pWinExec)(LPCSTR, UINT);
+ FARPROC16 proc;
+
+ proc = GetProcAddress16( ret, "WinExec" );
+ /* WINOLDAP is always a builtin dll */
+ pWinExec = (void *)((ENTRYPOINT16 *)MapSL( (SEGPTR)proc ))->target;
+ pWinExec( lpCmdLine, nCmdShow );
+ }
+ else
+ ret = 21;
+ }
+ else if (ret == ERROR_BAD_FORMAT) /* unknown executable */
{
DWORD count;
ReleaseThunkLock( &count );
diff --git a/dlls/kernel32/winoldap.spec b/dlls/kernel32/winoldap.spec
new file mode 100644
index 0000000..29dc85e
--- /dev/null
+++ b/dlls/kernel32/winoldap.spec
@@ -0,0 +1,2 @@
+# Wine extension
+1 pascal WinExec(str long) WINOLDAP_WinExec
diff --git a/programs/winecfg/libraries.c b/programs/winecfg/libraries.c
index 8e4e46b..2a168be 100644
--- a/programs/winecfg/libraries.c
+++ b/programs/winecfg/libraries.c
@@ -81,6 +81,7 @@ static const char * const builtin_only[] =
"wineps.drv",
"winex11.drv",
"winmm",
+ "winoldap",
"wintab32",
"wnaspi32",
"wow32",
--
1.5.3.7
More information about the wine-patches
mailing list