create a window in rundll32
Mike McCormack
mike at codeweavers.com
Thu Jul 17 16:12:59 CDT 2003
ChangeLog:
* rundll32 requires a window for some functions to work, so create one
-------------- next part --------------
Index: programs/rundll32/Makefile.in
===================================================================
RCS file: /home/wine/wine/programs/rundll32/Makefile.in,v
retrieving revision 1.1
diff -u -u -w -r1.1 Makefile.in
--- programs/rundll32/Makefile.in 15 Nov 2002 01:41:20 -0000 1.1
+++ programs/rundll32/Makefile.in 17 Jul 2003 21:06:09 -0000
@@ -4,7 +4,7 @@
VPATH = @srcdir@
MODULE = rundll32.exe
APPMODE = cui
-IMPORTS = kernel32
+IMPORTS = kernel32 user32
C_SRCS = \
rundll32.c
Index: programs/rundll32/rundll32.c
===================================================================
RCS file: /home/wine/wine/programs/rundll32/rundll32.c,v
retrieving revision 1.3
diff -u -u -w -r1.3 rundll32.c
--- programs/rundll32/rundll32.c 18 Nov 2002 19:42:13 -0000 1.3
+++ programs/rundll32/rundll32.c 17 Jul 2003 21:06:09 -0000
@@ -2,6 +2,8 @@
* PURPOSE: Load a DLL and run an entry point with the specified parameters
*
* Copyright 2002 Alberto Massari
+ * Copyright (c) Aric Steward for Codeweavers 2001-2003
+ * Copyright (c) Mike McCormack for Codeweavers 2003
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -27,102 +29,256 @@
*
*/
-/**
- * FIXME - currently receives command-line parameters in ASCII only and later
- * converts to Unicode. Ideally the function should have wWinMain entry point
- * and then work in Unicode only, but it seems Wine does not have necessary
- * support.
- */
-
-#include "config.h"
-#include "wine/port.h"
-
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
+
+/* Exclude rarely-used stuff from Windows headers */
+#define WIN32_LEAN_AND_MEAN
#include <windows.h>
+#include <wine/debug.h>
-typedef void (*EntryPointW) (HWND hWnd, HINSTANCE hInst, LPWSTR lpszCmdLine, int nCmdShow);
-typedef void (*EntryPointA) (HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow);
+WINE_DEFAULT_DEBUG_CHANNEL(rundll32);
-/**
- * Loads procedure.
- *
- * Parameters:
- * strDll - name of the dll.
- * procName - name of the procedure to load from dll
- * pDllHanlde - output variable receives handle of the loaded dll.
+
+/*
+ * Control_RunDLL has these parameters
*/
-static FARPROC LoadProc(char* strDll, char* procName, HMODULE* DllHandle)
-{
- FARPROC proc;
+typedef void (WINAPI *EntryPointW)(HWND hWnd, HINSTANCE hInst, LPWSTR lpszCmdLine, int nCmdShow);
+typedef void (WINAPI *EntryPointA)(HWND hWnd, HINSTANCE hInst, LPSTR lpszCmdLine, int nCmdShow);
+
+/*
+ * Control_RunDLL needs to have a window. So lets make us a very
+ * simple window class.
+ */
+static TCHAR *szTitle = "rundll32";
+static TCHAR *szWindowClass = "class_rundll32";
- *DllHandle = LoadLibrary(strDll);
- if(!*DllHandle)
+static ATOM MyRegisterClass(HINSTANCE hInstance)
{
- exit(-1);
+ WNDCLASSEX wcex;
+
+ wcex.cbSize = sizeof(WNDCLASSEX);
+
+ wcex.style = CS_HREDRAW | CS_VREDRAW;
+ wcex.lpfnWndProc = (WNDPROC)DefWindowProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = hInstance;
+ wcex.hIcon = NULL;
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wcex.lpszMenuName = NULL;
+ wcex.lpszClassName = szWindowClass;
+ wcex.hIconSm = NULL;
+
+ return RegisterClassEx(&wcex);
}
- proc = GetProcAddress(*DllHandle, procName);
- if(!proc)
+
+static LPWSTR GetNextArg(LPCWSTR *cmdline)
{
- FreeLibrary(*DllHandle);
+ LPCWSTR s;
+ LPWSTR arg,d;
+ int in_quotes,bcount,len=0;
+
+ /* count the chars */
+ bcount=0;
+ in_quotes=0;
+ s=*cmdline;
+ while (1) {
+ if (*s==0 || ((*s==0x0009 || *s==0x0020) && !in_quotes)) {
+ /* end of this command line argument */
+ break;
+ } else if (*s==0x005c) {
+ /* '\', count them */
+ bcount++;
+ } else if ((*s==0x0022) && ((bcount & 1)==0)) {
+ /* unescaped '"' */
+ in_quotes=!in_quotes;
+ bcount=0;
+ } else {
+ /* a regular character */
+ bcount=0;
+ }
+ s++;
+ len++;
+ }
+ arg=HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
+ if (!arg)
return NULL;
+
+ bcount=0;
+ in_quotes=0;
+ d=arg;
+ s=*cmdline;
+ while (*s) {
+ if ((*s==0x0009 || *s==0x0020) && !in_quotes) {
+ /* end of this command line argument */
+ break;
+ } else if (*s==0x005c) {
+ /* '\\' */
+ *d++=*s++;
+ bcount++;
+ } else if (*s==0x0022) {
+ /* '"' */
+ if ((bcount & 1)==0) {
+ /* Preceeded by an even number of '\', this is half that
+ * number of '\', plus a quote which we erase.
+ */
+ d-=bcount/2;
+ in_quotes=!in_quotes;
+ s++;
+ } else {
+ /* Preceeded by an odd number of '\', this is half that
+ * number of '\' followed by a '"'
+ */
+ d=d-bcount/2-1;
+ *d++='"';
+ s++;
+ }
+ bcount=0;
+ } else {
+ /* a regular character */
+ *d++=*s++;
+ bcount=0;
}
- return proc;
+ }
+ *d=0;
+ *cmdline=s;
+
+ /* skip the remaining spaces */
+ while (**cmdline==0x0009 || **cmdline==0x0020) {
+ (*cmdline)++;
+ }
+
+ return arg;
}
int main(int argc, char* argv[])
{
- char szDllName[MAX_PATH],szEntryPoint[64],szCmdLine[2048];
- char* comma;
- EntryPointW pfEntryPointW;
- EntryPointA pfEntryPointA;
- HMODULE DllHandle=NULL;
-
- if(argc<2)
- return 0;
- comma=strchr(argv[1],',');
- if(comma==NULL)
- return 0;
- /* Extract the name of the DLL */
- memset(szDllName,0,MAX_PATH);
- strncpy(szDllName,argv[1],(comma-argv[1]));
- /* Merge the other paramters into one big command line */
- memset(szCmdLine,0,2048);
- if(argc>2)
- {
- int i;
- for(i=2;i<argc;i++)
- {
- strcat(szCmdLine,argv[i]);
- if(i+1<argc) strcat(szCmdLine," ");
- }
+ HWND hWnd;
+ LPCWSTR szCmdLine;
+ LPWSTR szDllName,szEntryPoint;
+ char* szProcName;
+ HMODULE hDll;
+ EntryPointW pEntryPointW;
+ EntryPointA pEntryPointA;
+ int len;
+
+ hWnd=NULL;
+ hDll=NULL;
+ szDllName=NULL;
+ szProcName=NULL;
+
+ /* Initialize the rundll32 class */
+ MyRegisterClass( NULL );
+ hWnd = CreateWindow(szWindowClass, szTitle,
+ WS_OVERLAPPEDWINDOW|WS_VISIBLE,
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL);
+
+ /* Skip the rundll32.exe path */
+ szCmdLine=GetCommandLineW();
+ WINE_TRACE("CmdLine=%s\n",wine_dbgstr_w(szCmdLine));
+ szDllName=GetNextArg(&szCmdLine);
+ if (!szDllName || *szDllName==0)
+ goto CLEANUP;
+ HeapFree(GetProcessHeap(),0,szDllName);
+
+ /* Get the dll name and API EntryPoint */
+ szDllName=GetNextArg(&szCmdLine);
+ if (!szDllName || *szDllName==0)
+ goto CLEANUP;
+ WINE_TRACE("DllName=%s\n",wine_dbgstr_w(szDllName));
+ szEntryPoint=szDllName;
+ while (*szEntryPoint!=0 && *szEntryPoint!=0x002c /* ',' */)
+ szEntryPoint++;
+ if (*szEntryPoint==0)
+ goto CLEANUP;
+ *szEntryPoint++=0;
+ WINE_TRACE("EntryPoint=%s\n",wine_dbgstr_w(szEntryPoint));
+
+ /* Load the library */
+ hDll=LoadLibraryW(szDllName);
+ if (!hDll)
+ {
+ /* Windows has a MessageBox here... */
+ WINE_WARN("Unable to load %s\n",wine_dbgstr_w(szDllName));
+ goto CLEANUP;
}
- /* try loading the UNICODE version first */
- strcpy(szEntryPoint,comma+1);
- strcat(szEntryPoint,"W");
- pfEntryPointW=(EntryPointW)LoadProc(szDllName, szEntryPoint, &DllHandle);
- if(pfEntryPointW!=NULL)
- {
- WCHAR wszCmdLine[2048];
- MultiByteToWideChar(CP_ACP,0,szCmdLine,-1,wszCmdLine,2048);
- pfEntryPointW(NULL,DllHandle,wszCmdLine,SW_HIDE);
+ /* Try the Unicode entrypoint. Note that GetProcAddress only takes ascii
+ * names.
+ */
+ len=WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,NULL,0,NULL,NULL);
+ szProcName=HeapAlloc(GetProcessHeap(),0,len);
+ if (!szProcName)
+ goto CLEANUP;
+ WideCharToMultiByte(CP_ACP,0,szEntryPoint,-1,szProcName,len,NULL,NULL);
+ szProcName[len-1]=0x0057;
+ szProcName[len]=0;
+ pEntryPointW=(void*)GetProcAddress(hDll,szProcName);
+ if (pEntryPointW)
+ {
+ WCHAR* szArguments=NULL;
+
+ /* Make a copy of the arguments so they are writable */
+ len=lstrlenW(szCmdLine);
+ if (len>0)
+ {
+ szArguments=HeapAlloc(GetProcessHeap(),0,(len+1)*sizeof(WCHAR));
+ if (!szArguments)
+ goto CLEANUP;
+ lstrcpyW(szArguments,szCmdLine);
+ }
+ WINE_TRACE("Calling %s, arguments=%s\n",
+ szProcName,wine_dbgstr_w(szArguments));
+ pEntryPointW(hWnd,hDll,szArguments,SW_SHOWDEFAULT);
+ if (szArguments)
+ HeapFree(GetProcessHeap(),0,szArguments);
+ }
+ else
+ {
+ /* Then try to append 'A' and finally nothing */
+ szProcName[len-1]=0x0041;
+ pEntryPointA=(void*)GetProcAddress(hDll,szProcName);
+ if (!pEntryPointA)
+ {
+ szProcName[len-1]=0;
+ pEntryPointA=(void*)GetProcAddress(hDll,szProcName);
+ }
+ if (pEntryPointA)
+ {
+ char* szArguments=NULL;
+ /* Convert the command line to ascii */
+ WINE_TRACE("Calling %s, arguments=%s\n",
+ szProcName,wine_dbgstr_a(szArguments));
+ len=WideCharToMultiByte(CP_ACP,0,szCmdLine,-1,NULL,0,NULL,NULL);
+ if (len>1)
+ {
+ szArguments=HeapAlloc(GetProcessHeap(),0,len);
+ if (!szArguments)
+ goto CLEANUP;
+ WideCharToMultiByte(CP_ACP,0,szCmdLine,-1,szArguments,len,NULL,NULL);
+ }
+ pEntryPointA(hWnd,hDll,szArguments,SW_SHOWDEFAULT);
+ if (szArguments)
+ HeapFree(GetProcessHeap(),0,szArguments);
}
else
{
- strcpy(szEntryPoint,comma+1);
- strcat(szEntryPoint,"A");
- pfEntryPointA=(EntryPointA)LoadProc(szDllName, szEntryPoint, &DllHandle);
- if(pfEntryPointA==NULL)
- {
- strcpy(szEntryPoint,comma+1);
- pfEntryPointA=(EntryPointA)LoadProc(szDllName, szEntryPoint, &DllHandle);
- if(pfEntryPointA==NULL)
- return 0;
- }
- pfEntryPointA(NULL,DllHandle,szCmdLine,SW_HIDE);
- }
- if(DllHandle)
- FreeLibrary(DllHandle);
- return 0;
+ /* Windows has a MessageBox here... */
+ WINE_WARN("Unable to find the entry point: %s\n",szProcName);
+ }
+ }
+
+CLEANUP:
+ if (hWnd)
+ DestroyWindow(hWnd);
+ if (hDll)
+ FreeLibrary(hDll);
+ if (szDllName)
+ HeapFree(GetProcessHeap(),0,szDllName);
+ if (szProcName)
+ HeapFree(GetProcessHeap(),0,szProcName);
+ return 0; /* rundll32 always returns 0! */
}
More information about the wine-patches
mailing list