A first stab at implementing the RunDll features.

This commit is contained in:
Eric Pouech 2001-02-23 01:12:26 +00:00 committed by Alexandre Julliard
parent 92285494a9
commit 92b23186ae
9 changed files with 501 additions and 40 deletions

View File

@ -14,6 +14,7 @@ C_SRCS = \
changenotify.c \ changenotify.c \
classes.c \ classes.c \
clipboard.c \ clipboard.c \
control.c \
dataobject.c \ dataobject.c \
dialogs.c \ dialogs.c \
enumidlist.c \ enumidlist.c \

386
dlls/shell32/control.c Normal file
View File

@ -0,0 +1,386 @@
/* Control Panel management */
/* Eric Pouech 2001 */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "debugtools.h"
#include "cpl.h"
DEFAULT_DEBUG_CHANNEL(shlctrl);
typedef struct CPlApplet {
struct CPlApplet* next; /* linked list */
HWND hWnd;
unsigned count; /* number of subprograms */
HMODULE hModule; /* module of loaded applet */
APPLET_PROC proc; /* entry point address */
NEWCPLINFOA info[1]; /* array of count information.
* dwSize field is 0 if entry is invalid */
} CPlApplet;
typedef struct CPanel {
CPlApplet* first; /* linked list */
HWND hWnd;
unsigned status;
CPlApplet* clkApplet;
unsigned clkSP;
} CPanel;
static CPlApplet* Control_UnloadApplet(CPlApplet* applet)
{
unsigned i;
CPlApplet* next;
for (i = 0; i < applet->count; i++) {
if (!applet->info[i].dwSize) continue;
applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData);
}
if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
FreeLibrary(applet->hModule);
next = applet->next;
HeapFree(GetProcessHeap(), 0, applet);
return next;
}
static CPlApplet* Control_LoadApplet(HWND hWnd, LPCSTR cmd, CPanel* panel)
{
CPlApplet* applet;
unsigned i;
CPLINFO info;
if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet))))
return applet;
applet->hWnd = hWnd;
if (!(applet->hModule = LoadLibraryA(cmd))) {
WARN("Cannot load control panel applet %s\n", cmd);
goto theError;
}
if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) {
WARN("Not a valid control panel applet %s\n", cmd);
goto theError;
}
if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) {
WARN("Init of applet has failed\n");
goto theError;
}
if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) {
WARN("No subprogram in applet\n");
goto theError;
}
applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOA));
for (i = 0; i < applet->count; i++) {
applet->info[i].dwSize = sizeof(NEWCPLINFOA);
/* proc is supposed to return a null value upon success for
* CPL_INQUIRE and CPL_NEWINQUIRE
* However, real drivers don't seem to behave like this
* So, use introspection rather than return value
*/
applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&applet->info[i]);
if (applet->info[i].hIcon == 0) {
applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
if (info.idIcon == 0 || info.idName == 0) {
WARN("Couldn't get info from sp %u\n", i);
applet->info[i].dwSize = 0;
} else {
/* convert the old data into the new structure */
applet->info[i].dwFlags = 0;
applet->info[i].dwHelpContext = 0;
applet->info[i].lData = info.lData;
applet->info[i].hIcon = LoadIconA(applet->hModule,
MAKEINTRESOURCEA(info.idIcon));
LoadStringA(applet->hModule, info.idName,
applet->info[i].szName, sizeof(applet->info[i].szName));
LoadStringA(applet->hModule, info.idInfo,
applet->info[i].szInfo, sizeof(applet->info[i].szInfo));
applet->info[i].szHelpFile[0] = '\0';
}
}
}
applet->next = panel->first;
panel->first = applet;
return applet;
theError:
Control_UnloadApplet(applet);
return NULL;
}
static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTA* cs)
{
CPanel* panel = (CPanel*)cs->lpCreateParams;
SetWindowLongA(hWnd, 0, (LPARAM)panel);
panel->status = 0;
panel->hWnd = hWnd;
}
#define XICON 32
#define XSTEP 128
#define YICON 32
#define YSTEP 64
static BOOL Control_Localize(const CPanel* panel, unsigned cx, unsigned cy,
CPlApplet** papplet, unsigned* psp)
{
unsigned i, x = (XSTEP-XICON)/2, y = 0;
CPlApplet* applet;
RECT rc;
GetClientRect(panel->hWnd, &rc);
for (applet = panel->first; applet; applet = applet = applet->next) {
for (i = 0; i < applet->count; i++) {
if (!applet->info[i].dwSize) continue;
if (x + XSTEP >= rc.right - rc.left) {
x = (XSTEP-XICON)/2;
y += YSTEP;
}
if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) {
*papplet = applet;
*psp = i;
return TRUE;
}
x += XSTEP;
}
}
return FALSE;
}
static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rc, txtRect;
unsigned i, x = 0, y = 0;
CPlApplet* applet;
HGDIOBJ hOldFont;
hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps);
hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
GetClientRect(panel->hWnd, &rc);
for (applet = panel->first; applet; applet = applet = applet->next) {
for (i = 0; i < applet->count; i++) {
if (x + XSTEP >= rc.right - rc.left) {
x = 0;
y += YSTEP;
}
if (!applet->info[i].dwSize) continue;
DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon);
txtRect.left = x;
txtRect.right = x + XSTEP;
txtRect.top = y + YICON;
txtRect.bottom = y + YSTEP;
DrawTextA(hdc, applet->info[i].szName, -1, &txtRect,
DT_CENTER | DT_VCENTER);
x += XSTEP;
}
}
SelectObject(hdc, hOldFont);
if (!wParam) EndPaint(panel->hWnd, &ps);
return 0;
}
static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
{
unsigned i;
CPlApplet* applet;
if (Control_Localize(panel, LOWORD(lParam), HIWORD(lParam), &applet, &i)) {
if (up) {
if (panel->clkApplet == applet && panel->clkSP == i) {
applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData);
}
} else {
panel->clkApplet = applet;
panel->clkSP = i;
}
}
return 0;
}
static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
WPARAM lParam1, LPARAM lParam2)
{
CPanel* panel = (CPanel*)GetWindowLongA(hWnd, 0);
if (panel || wMsg == WM_CREATE) {
switch (wMsg) {
case WM_CREATE:
Control_WndProc_Create(hWnd, (CREATESTRUCTA*)lParam2);
return 0;
case WM_DESTROY:
while ((panel->first = Control_UnloadApplet(panel->first)));
break;
case WM_PAINT:
return Control_WndProc_Paint(panel, lParam1);
case WM_LBUTTONUP:
return Control_WndProc_LButton(panel, lParam2, TRUE);
case WM_LBUTTONDOWN:
return Control_WndProc_LButton(panel, lParam2, FALSE);
/* EPP case WM_COMMAND: */
/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */
}
}
return DefWindowProcA(hWnd, wMsg, lParam1, lParam2);
}
static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
{
WNDCLASSA wc;
MSG msg;
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = Control_WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = sizeof(CPlApplet*);
wc.hInstance = hInst;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "Shell_Control_WndClass";
if (!RegisterClassA(&wc)) return;
CreateWindowExA(0, wc.lpszClassName, "Wine Control Panel",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, (HMENU)0, hInst, panel);
if (!panel->hWnd) return;
while (GetMessageA(&msg, panel->hWnd, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
if (!panel->first) break;
}
}
static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst)
{
HANDLE h;
WIN32_FIND_DATAA fd;
char buffer[MAX_PATH];
/* FIXME: should grab path somewhere from configuration */
if ((h = FindFirstFileA("c:\\windows\\system\\*.cpl", &fd)) != 0) {
do {
sprintf(buffer, "c:\\windows\\system\\%s", fd.cFileName);
Control_LoadApplet(hWnd, buffer, panel);
} while (FindNextFileA(h, &fd));
FindClose(h);
}
if (panel->first) Control_DoInterface(panel, hWnd, hInst);
}
static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCSTR cmd)
/* forms to parse:
* foo.cpl,@sp,str
* foo.cpl,@sp
* foo.cpl,,str
* foo.cpl @sp
* foo.cpl str
*/
{
char* buffer;
char* beg = NULL;
char* end;
char ch;
unsigned sp = 0;
char* extraPmts = NULL;
buffer = HeapAlloc(GetProcessHeap(), 0, strlen(cmd) + 1);
if (!buffer) return;
end = strcpy(buffer, cmd);
for (;;) {
ch = *end;
if (ch == ' ' || ch == ',' || ch == '\0') {
*end = '\0';
if (beg) {
if (*beg == '@') {
sp = atoi(beg + 1);
} else if (*beg == '\0') {
sp = 0;
} else {
extraPmts = beg;
}
}
if (ch == '\0') break;
beg = end + 1;
if (ch == ' ') while (end[1] == ' ') end++;
}
end++;
}
Control_LoadApplet(hWnd, buffer, panel);
if (panel->first) {
CPlApplet* applet = panel->first;
assert(applet && applet->next == NULL);
if (sp >= applet->count) {
WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count);
sp = 0;
}
if (applet->info[sp].dwSize) {
if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts))
applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData);
}
Control_UnloadApplet(applet);
}
HeapFree(GetProcessHeap(), 0, buffer);
}
/*************************************************************************
* Control_RunDLL [SHELL32.12]
*
*/
void WINAPI Control_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
{
CPanel panel;
TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n",
hWnd, (DWORD)hInst, debugstr_a(cmd), nCmdShow);
memset(&panel, 0, sizeof(panel));
if (!cmd || !*cmd) {
Control_DoWindow(&panel, hWnd, hInst);
} else {
Control_DoLaunch(&panel, hWnd, cmd);
}
}
/*************************************************************************
* Control_FillCache_RunDLL [SHELL32.8]
*
*/
HRESULT WINAPI Control_FillCache_RunDLL(HWND hWnd, HANDLE hModule, DWORD w, DWORD x)
{
FIXME("0x%04x 0x%04x 0x%04lx 0x%04lx stub\n",hWnd, hModule, w, x);
return 0;
}
/*************************************************************************
* RunDLL_CallEntry16 [SHELL32.122]
* the name is propably wrong
*/
HRESULT WINAPI RunDLL_CallEntry16(DWORD v, DWORD w, DWORD x, DWORD y, DWORD z)
{
FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n",v,w,x,y,z);
return 0;
}

View File

@ -157,7 +157,7 @@ INT SIC_GetIconIndex (LPCSTR sSourceFile, INT dwSourceIndex )
return ret; return ret;
} }
/**************************************************************************** /****************************************************************************
* SIC_LoadIcon [internal] * SIC_GetIcon [internal]
* *
* NOTES * NOTES
* retrives the specified icon from the iconcache. if not found try's to load the icon * retrives the specified icon from the iconcache. if not found try's to load the icon

View File

@ -14,7 +14,7 @@ import advapi32.dll
import kernel32.dll import kernel32.dll
import ntdll.dll import ntdll.dll
debug_channels (exec pidl shell) debug_channels (exec pidl shell shlctrl)
# Functions exported by the Win95 shell32.dll # Functions exported by the Win95 shell32.dll
# (these need to have these exact ordinals, for some # (these need to have these exact ordinals, for some
@ -172,10 +172,10 @@ debug_channels (exec pidl shell)
164 stdcall Win32DeleteFile(str) Win32DeleteFile 164 stdcall Win32DeleteFile(str) Win32DeleteFile
165 stdcall SHCreateDirectory(long long) SHCreateDirectory 165 stdcall SHCreateDirectory(long long) SHCreateDirectory
166 stub CallCPLEntry16 166 stub CallCPLEntry16
167 stub SHAddFromPropSheetExtArray 167 stdcall SHAddFromPropSheetExtArray(long long long) SHAddFromPropSheetExtArray
168 stub SHCreatePropSheetExtArray 168 stdcall SHCreatePropSheetExtArray(long str long) SHCreatePropSheetExtArray
169 stub SHDestroyPropSheetExtArray 169 stdcall SHDestroyPropSheetExtArray(long) SHDestroyPropSheetExtArray
170 stub SHReplaceFromPropSheetExtArray 170 stdcall SHReplaceFromPropSheetExtArray(long long long long) SHReplaceFromPropSheetExtArray
171 stdcall PathCleanupSpec(ptr ptr) PathCleanupSpecAW 171 stdcall PathCleanupSpec(ptr ptr) PathCleanupSpecAW
172 stub SHCreateLinks 172 stub SHCreateLinks
173 stdcall SHValidateUNC(long long long)SHValidateUNC 173 stdcall SHValidateUNC(long long long)SHValidateUNC

View File

@ -76,20 +76,6 @@ LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
return argv; return argv;
} }
/*************************************************************************
* Control_RunDLL [SHELL32.12]
*
* Wild speculation in the following!
*
* http://premium.microsoft.com/msdn/library/techart/msdn193.htm
*/
void WINAPI Control_RunDLL( HWND hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4 )
{
FIXME("(0x%08x, %p, %s, 0x%08lx): stub\n", hwnd, code,
debugstr_a(cmd), arg4);
}
/************************************************************************* /*************************************************************************
* SHGetFileInfoA [SHELL32.@] * SHGetFileInfoA [SHELL32.@]
* *

View File

@ -881,22 +881,6 @@ BOOL WINAPI SHWaitForFileToOpen(
FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout); FIXME("%p 0x%08lx 0x%08lx stub\n", pidl, dwFlags, dwTimeout);
return 0; return 0;
} }
/*************************************************************************
* Control_FillCache_RunDLL [SHELL32.8]
*
*/
HRESULT WINAPI Control_FillCache_RunDLL(HWND hWnd, HANDLE hModule, DWORD w, DWORD x)
{ FIXME("0x%04x 0x%04x 0x%04lx 0x%04lx stub\n",hWnd, hModule,w,x);
return 0;
}
/*************************************************************************
* RunDLL_CallEntry16 [SHELL32.122]
* the name is propably wrong
*/
HRESULT WINAPI RunDLL_CallEntry16(DWORD v, DWORD w, DWORD x, DWORD y, DWORD z)
{ FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n",v,w,x,y,z);
return 0;
}
/************************************************************************ /************************************************************************
* shell32_654 [SHELL32.654] * shell32_654 [SHELL32.654]
@ -983,3 +967,39 @@ DWORD WINAPI SHELL32_714(LPVOID x)
FIXME("(%s)stub\n", debugstr_w(x)); FIXME("(%s)stub\n", debugstr_w(x));
return 0; return 0;
} }
/*************************************************************************
* SHAddFromPropSheetExtArray [SHELL32]
*/
DWORD WINAPI SHAddFromPropSheetExtArray(DWORD a, DWORD b, DWORD c)
{
FIXME("(%08lx,%08lx,%08lx)stub\n", a, b, c);
return 0;
}
/*************************************************************************
* SHCreatePropSheetExtArray [SHELL32]
*/
DWORD WINAPI SHCreatePropSheetExtArray(DWORD a, LPCSTR b, DWORD c)
{
FIXME("(%08lx,%s,%08lx)stub\n", a, debugstr_a(b), c);
return 0;
}
/*************************************************************************
* SHReplaceFromPropSheetExtArray [SHELL]
*/
DWORD WINAPI SHReplaceFromPropSheetExtArray(DWORD a, DWORD b, DWORD c, DWORD d)
{
FIXME("(%08lx,%08lx,%08lx,%08lx)stub\n", a, b, c, d);
return 0;
}
/*************************************************************************
* SHDestroyPropSheetExtArray [SHELL32]
*/
DWORD WINAPI SHDestroyPropSheetExtArray(DWORD a)
{
FIXME("(%08lx)stub\n", a);
return 0;
}

View File

@ -12,6 +12,7 @@ INSTALLED_INCLUDES = \
commctrl.h \ commctrl.h \
commdlg.h \ commdlg.h \
compobj.h \ compobj.h \
cpl.h \
d3d.h \ d3d.h \
d3dcaps.h \ d3dcaps.h \
d3dtypes.h \ d3dtypes.h \

71
include/cpl.h Normal file
View File

@ -0,0 +1,71 @@
/* Control panel definitions */
#ifndef _INC_CPL
#define _INC_CPL
#include "pshpack1.h"
#ifdef __cplusplus
extern "C" {
#endif
#define WM_CPL_LAUNCH (WM_USER+1000)
#define WM_CPL_LAUNCHED (WM_USER+1001)
typedef LONG (APIENTRY *APPLET_PROC)(HWND hwndCpl, UINT msg, LPARAM lParam1, LPARAM lParam2);
typedef struct tagCPLINFO {
int idIcon;
int idName;
int idInfo;
LONG lData;
} CPLINFO, *LPCPLINFO;
typedef struct tagNEWCPLINFOA
{
DWORD dwSize;
DWORD dwFlags;
DWORD dwHelpContext;
LONG lData;
HICON hIcon;
CHAR szName[32];
CHAR szInfo[64];
CHAR szHelpFile[128];
} NEWCPLINFOA, *LPNEWCPLINFOA;
typedef struct tagNEWCPLINFOW
{
DWORD dwSize;
DWORD dwFlags;
DWORD dwHelpContext;
LONG lData;
HICON hIcon;
WCHAR szName[32];
WCHAR szInfo[64];
WCHAR szHelpFile[128];
} NEWCPLINFOW, *LPNEWCPLINFOW;
DECL_WINELIB_TYPE_AW(NEWCPLINFO)
DECL_WINELIB_TYPE_AW(LPNEWCPLINFO)
#define CPL_DYNAMIC_RES 0
#define CPL_INIT 1
#define CPL_GETCOUNT 2
#define CPL_INQUIRE 3
#define CPL_SELECT 4
#define CPL_DBLCLK 5
#define CPL_STOP 6
#define CPL_EXIT 7
#define CPL_NEWINQUIRE 8
#define CPL_STARTWPARMSA 9
#define CPL_STARTWPARMSW 10
#define CPL_STARTWPARMS WINELIB_NAME_AW(CPL_STARTWPARMS)
#define CPL_SETUP 200
#ifdef __cplusplus
}
#endif
#include "poppack.h"
#endif /* _INC_CPL */

View File

@ -3083,10 +3083,6 @@ typedef struct
#define DI_COMPAT 4 #define DI_COMPAT 4
#define DI_DEFAULTSIZE 8 #define DI_DEFAULTSIZE 8
/* misc messages */
#define WM_CPL_LAUNCH (WM_USER + 1000)
#define WM_CPL_LAUNCHED (WM_USER + 1001)
/* WM_NOTIFYFORMAT commands and return values */ /* WM_NOTIFYFORMAT commands and return values */
#define NFR_ANSI 1 #define NFR_ANSI 1
#define NFR_UNICODE 2 #define NFR_UNICODE 2