source: trunk/src/shell32/control.c@ 6709

Last change on this file since 6709 was 6709, checked in by sandervl, 24 years ago

restored old version

File size: 10.5 KB
Line 
1/* Control Panel management */
2/* Eric Pouech 2001 */
3
4#include <assert.h>
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9#include "winbase.h"
10#include "wingdi.h"
11#include "winuser.h"
12#include "debugtools.h"
13#include "cpl.h"
14
15DEFAULT_DEBUG_CHANNEL(shlctrl);
16
17typedef struct CPlApplet {
18 struct CPlApplet* next; /* linked list */
19 HWND hWnd;
20 unsigned count; /* number of subprograms */
21 HMODULE hModule; /* module of loaded applet */
22 APPLET_PROC proc; /* entry point address */
23 NEWCPLINFOA info[1]; /* array of count information.
24 * dwSize field is 0 if entry is invalid */
25} CPlApplet;
26
27typedef struct CPanel {
28 CPlApplet* first; /* linked list */
29 HWND hWnd;
30 unsigned status;
31 CPlApplet* clkApplet;
32 unsigned clkSP;
33} CPanel;
34
35static CPlApplet* Control_UnloadApplet(CPlApplet* applet)
36{
37 unsigned i;
38 CPlApplet* next;
39
40 for (i = 0; i < applet->count; i++) {
41 if (!applet->info[i].dwSize) continue;
42 applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData);
43 }
44 if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
45 FreeLibrary(applet->hModule);
46 next = applet->next;
47 HeapFree(GetProcessHeap(), 0, applet);
48 return next;
49}
50
51static CPlApplet* Control_LoadApplet(HWND hWnd, LPCSTR cmd, CPanel* panel)
52{
53 CPlApplet* applet;
54 unsigned i;
55 CPLINFO info;
56
57 if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet))))
58 return applet;
59
60 applet->hWnd = hWnd;
61
62 if (!(applet->hModule = LoadLibraryA(cmd))) {
63 WARN("Cannot load control panel applet %s\n", cmd);
64 goto theError;
65 }
66 if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) {
67 WARN("Not a valid control panel applet %s\n", cmd);
68 goto theError;
69 }
70 if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) {
71 WARN("Init of applet has failed\n");
72 goto theError;
73 }
74 if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) {
75 WARN("No subprogram in applet\n");
76 goto theError;
77 }
78
79 applet = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
80 sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOA));
81
82 for (i = 0; i < applet->count; i++) {
83 applet->info[i].dwSize = sizeof(NEWCPLINFOA);
84 /* proc is supposed to return a null value upon success for
85 * CPL_INQUIRE and CPL_NEWINQUIRE
86 * However, real drivers don't seem to behave like this
87 * So, use introspection rather than return value
88 */
89 applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&applet->info[i]);
90 if (applet->info[i].hIcon == 0) {
91 applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
92 if (info.idIcon == 0 || info.idName == 0) {
93 WARN("Couldn't get info from sp %u\n", i);
94 applet->info[i].dwSize = 0;
95 } else {
96 /* convert the old data into the new structure */
97 applet->info[i].dwFlags = 0;
98 applet->info[i].dwHelpContext = 0;
99 applet->info[i].lData = info.lData;
100 applet->info[i].hIcon = LoadIconA(applet->hModule,
101 MAKEINTRESOURCEA(info.idIcon));
102 LoadStringA(applet->hModule, info.idName,
103 applet->info[i].szName, sizeof(applet->info[i].szName));
104 LoadStringA(applet->hModule, info.idInfo,
105 applet->info[i].szInfo, sizeof(applet->info[i].szInfo));
106 applet->info[i].szHelpFile[0] = '\0';
107 }
108 }
109 }
110
111 applet->next = panel->first;
112 panel->first = applet;
113
114 return applet;
115
116 theError:
117 Control_UnloadApplet(applet);
118 return NULL;
119}
120
121static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTA* cs)
122{
123 CPanel* panel = (CPanel*)cs->lpCreateParams;
124
125 SetWindowLongA(hWnd, 0, (LPARAM)panel);
126 panel->status = 0;
127 panel->hWnd = hWnd;
128}
129
130#define XICON 32
131#define XSTEP 128
132#define YICON 32
133#define YSTEP 64
134
135static BOOL Control_Localize(const CPanel* panel, unsigned cx, unsigned cy,
136 CPlApplet** papplet, unsigned* psp)
137{
138 unsigned i, x = (XSTEP-XICON)/2, y = 0;
139 CPlApplet* applet;
140 RECT rc;
141
142 GetClientRect(panel->hWnd, &rc);
143 for (applet = panel->first; applet; applet = applet = applet->next) {
144 for (i = 0; i < applet->count; i++) {
145 if (!applet->info[i].dwSize) continue;
146 if (x + XSTEP >= rc.right - rc.left) {
147 x = (XSTEP-XICON)/2;
148 y += YSTEP;
149 }
150 if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) {
151 *papplet = applet;
152 *psp = i;
153 return TRUE;
154 }
155 x += XSTEP;
156 }
157 }
158 return FALSE;
159}
160
161static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam)
162{
163 HDC hdc;
164 PAINTSTRUCT ps;
165 RECT rc, txtRect;
166 unsigned i, x = 0, y = 0;
167 CPlApplet* applet;
168 HGDIOBJ hOldFont;
169
170 hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps);
171 hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
172 GetClientRect(panel->hWnd, &rc);
173 for (applet = panel->first; applet; applet = applet = applet->next) {
174 for (i = 0; i < applet->count; i++) {
175 if (x + XSTEP >= rc.right - rc.left) {
176 x = 0;
177 y += YSTEP;
178 }
179 if (!applet->info[i].dwSize) continue;
180 DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon);
181 txtRect.left = x;
182 txtRect.right = x + XSTEP;
183 txtRect.top = y + YICON;
184 txtRect.bottom = y + YSTEP;
185 DrawTextA(hdc, applet->info[i].szName, -1, &txtRect,
186 DT_CENTER | DT_VCENTER);
187 x += XSTEP;
188 }
189 }
190 SelectObject(hdc, hOldFont);
191 if (!wParam) EndPaint(panel->hWnd, &ps);
192 return 0;
193}
194
195static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
196{
197 unsigned i;
198 CPlApplet* applet;
199
200 if (Control_Localize(panel, LOWORD(lParam), HIWORD(lParam), &applet, &i)) {
201 if (up) {
202 if (panel->clkApplet == applet && panel->clkSP == i) {
203 applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData);
204 }
205 } else {
206 panel->clkApplet = applet;
207 panel->clkSP = i;
208 }
209 }
210 return 0;
211}
212
213static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
214 WPARAM lParam1, LPARAM lParam2)
215{
216 CPanel* panel = (CPanel*)GetWindowLongA(hWnd, 0);
217
218 if (panel || wMsg == WM_CREATE) {
219 switch (wMsg) {
220 case WM_CREATE:
221 Control_WndProc_Create(hWnd, (CREATESTRUCTA*)lParam2);
222 return 0;
223 case WM_DESTROY:
224 while ((panel->first = Control_UnloadApplet(panel->first)));
225 break;
226 case WM_PAINT:
227 return Control_WndProc_Paint(panel, lParam1);
228 case WM_LBUTTONUP:
229 return Control_WndProc_LButton(panel, lParam2, TRUE);
230 case WM_LBUTTONDOWN:
231 return Control_WndProc_LButton(panel, lParam2, FALSE);
232/* EPP case WM_COMMAND: */
233/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */
234 }
235 }
236
237 return DefWindowProcA(hWnd, wMsg, lParam1, lParam2);
238}
239
240static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
241{
242 WNDCLASSA wc;
243 MSG msg;
244
245 wc.style = CS_HREDRAW|CS_VREDRAW;
246 wc.lpfnWndProc = Control_WndProc;
247 wc.cbClsExtra = 0;
248 wc.cbWndExtra = sizeof(CPlApplet*);
249 wc.hInstance = hInst;
250 wc.hIcon = 0;
251 wc.hCursor = 0;
252 wc.hbrBackground = GetStockObject(WHITE_BRUSH);
253 wc.lpszMenuName = NULL;
254 wc.lpszClassName = "Shell_Control_WndClass";
255
256 if (!RegisterClassA(&wc)) return;
257
258 CreateWindowExA(0, wc.lpszClassName, "Wine Control Panel",
259 WS_OVERLAPPEDWINDOW | WS_VISIBLE,
260 CW_USEDEFAULT, CW_USEDEFAULT,
261 CW_USEDEFAULT, CW_USEDEFAULT,
262 hWnd, (HMENU)0, hInst, panel);
263 if (!panel->hWnd) return;
264 while (GetMessageA(&msg, panel->hWnd, 0, 0)) {
265 TranslateMessage(&msg);
266 DispatchMessageA(&msg);
267 if (!panel->first) break;
268 }
269}
270
271static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst)
272{
273 HANDLE h;
274 WIN32_FIND_DATAA fd;
275 char buffer[MAX_PATH];
276
277 /* FIXME: should grab path somewhere from configuration */
278 if ((h = FindFirstFileA("c:\\windows\\system\\*.cpl", &fd)) != 0) {
279 do {
280 sprintf(buffer, "c:\\windows\\system\\%s", fd.cFileName);
281 Control_LoadApplet(hWnd, buffer, panel);
282 } while (FindNextFileA(h, &fd));
283 FindClose(h);
284 }
285
286 if (panel->first) Control_DoInterface(panel, hWnd, hInst);
287}
288
289static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCSTR cmd)
290 /* forms to parse:
291 * foo.cpl,@sp,str
292 * foo.cpl,@sp
293 * foo.cpl,,str
294 * foo.cpl @sp
295 * foo.cpl str
296 */
297{
298 char* buffer;
299 char* beg = NULL;
300 char* end;
301 char ch;
302 unsigned sp = 0;
303 char* extraPmts = NULL;
304
305 buffer = HeapAlloc(GetProcessHeap(), 0, strlen(cmd) + 1);
306 if (!buffer) return;
307
308 end = strcpy(buffer, cmd);
309
310 for (;;) {
311 ch = *end;
312 if (ch == ' ' || ch == ',' || ch == '\0') {
313 *end = '\0';
314 if (beg) {
315 if (*beg == '@') {
316 sp = atoi(beg + 1);
317 } else if (*beg == '\0') {
318 sp = 0;
319 } else {
320 extraPmts = beg;
321 }
322 }
323 if (ch == '\0') break;
324 beg = end + 1;
325 if (ch == ' ') while (end[1] == ' ') end++;
326 }
327 end++;
328 }
329 Control_LoadApplet(hWnd, buffer, panel);
330
331 if (panel->first) {
332 CPlApplet* applet = panel->first;
333
334 assert(applet && applet->next == NULL);
335 if (sp >= applet->count) {
336 WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count);
337 sp = 0;
338 }
339 if (applet->info[sp].dwSize) {
340 if (!applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts))
341 applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData);
342 }
343 Control_UnloadApplet(applet);
344 }
345 HeapFree(GetProcessHeap(), 0, buffer);
346}
347
348/*************************************************************************
349 * Control_RunDLL [SHELL32.12]
350 *
351 */
352void WINAPI Control_RunDLL(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
353{
354 CPanel panel;
355
356 TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n",
357 hWnd, (DWORD)hInst, debugstr_a(cmd), nCmdShow);
358
359 memset(&panel, 0, sizeof(panel));
360
361 if (!cmd || !*cmd) {
362 Control_DoWindow(&panel, hWnd, hInst);
363 } else {
364 Control_DoLaunch(&panel, hWnd, cmd);
365 }
366}
367
368/*************************************************************************
369 * Control_FillCache_RunDLL [SHELL32.8]
370 *
371 */
372HRESULT WINAPI Control_FillCache_RunDLL(HWND hWnd, HANDLE hModule, DWORD w, DWORD x)
373{
374 FIXME("0x%04x 0x%04x 0x%04lx 0x%04lx stub\n",hWnd, hModule, w, x);
375 return 0;
376}
377
378/*************************************************************************
379 * RunDLL_CallEntry16 [SHELL32.122]
380 * the name is propably wrong
381 */
382HRESULT WINAPI RunDLL_CallEntry16(DWORD v, DWORD w, DWORD x, DWORD y, DWORD z)
383{
384 FIXME("0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n",v,w,x,y,z);
385 return 0;
386}
Note: See TracBrowser for help on using the repository browser.