2 * ReactOS shell32 - Control Panel
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
33 //#include <process.h>
42 //#define _USE_WINE_WND_
44 //WINE_DEFAULT_DEBUG_CHANNEL(shlctrl);
46 ////////////////////////////////////////////////////////////////////////////////
55 TCHAR szTitle
[MAX_LOADSTRING
];
56 TCHAR szWindowClass
[MAX_LOADSTRING
];
59 ////////////////////////////////////////////////////////////////////////////////
61 BOOL
InitInstance(HINSTANCE hInstance
, int nCmdShow
)
64 WNDCLASSEX wcFrame
= {
66 CS_HREDRAW
| CS_VREDRAW
/*style*/,
71 LoadIcon(hInstance
, (LPCTSTR
)MAKEINTRESOURCE(IDI_CONTROL
)),
72 LoadCursor(0, IDC_ARROW
),
76 (HICON
)LoadImage(hInstance
, (LPCTSTR
)MAKEINTRESOURCE(IDI_CONTROL
), IMAGE_ICON
,
77 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
), LR_SHARED
)
79 ATOM hFrameWndClass
= RegisterClassEx(&wcFrame
); // register frame window class
81 hMenuFrame
= LoadMenu(hInstance
, (LPCTSTR
)MAKEINTRESOURCE(IDR_CONTROL_MENU
));
83 // Initialize the Windows Common Controls DLL
86 if (LoadSettings(&rect
)) {
87 hFrameWnd
= CreateWindowEx(0, (LPCTSTR
)(int)hFrameWndClass
, szTitle
,
88 WS_OVERLAPPEDWINDOW
| WS_EX_CLIENTEDGE
,
89 rect
.left
, rect
.top
, rect
.right
- rect
.left
, rect
.bottom
- rect
.top
,
90 NULL
, hMenuFrame
, hInstance
, NULL
/*lpParam*/);
92 hFrameWnd
= CreateWindowEx(0, (LPCTSTR
)(int)hFrameWndClass
, szTitle
,
93 WS_OVERLAPPEDWINDOW
| WS_EX_CLIENTEDGE
,
94 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
,
95 NULL
, hMenuFrame
, hInstance
, NULL
/*lpParam*/);
103 // Create the status bar
104 hStatusBar
= CreateStatusWindow(WS_VISIBLE
|WS_CHILD
|WS_CLIPSIBLINGS
|SBT_NOBORDERS
,
105 _T(""), hFrameWnd
, STATUS_WINDOW
);
107 // Create the status bar panes
108 SetupStatusBar(hFrameWnd
, FALSE
);
109 CheckMenuItem(GetSubMenu(hMenuFrame
, ID_VIEW_MENU
), ID_VIEW_STATUSBAR
, MF_BYCOMMAND
|MF_CHECKED
);
111 ShowWindow(hFrameWnd
, nCmdShow
);
112 UpdateWindow(hFrameWnd
);
116 ////////////////////////////////////////////////////////////////////////////////
118 void ExitInstance(void)
120 DestroyMenu(hMenuFrame
);
124 int APIENTRY
ControlMain(HINSTANCE hInstance
,
125 HINSTANCE hPrevInstance
,
132 // Initialize global strings
133 LoadString(hInstance
, IDS_APP_TITLE
, szTitle
, MAX_LOADSTRING
);
134 LoadString(hInstance
, IDC_CONTROL
, szWindowClass
, MAX_LOADSTRING
);
136 // Store instance handle in our global variable
139 // Perform application initialization:
140 if (!InitInstance(hInstance
, nCmdShow
)) {
143 hAccel
= LoadAccelerators(hInstance
, (LPCTSTR
)IDC_CONTROL
);
145 // Main message loop:
146 while (GetMessage(&msg
, (HWND
)NULL
, 0, 0)) {
147 if (!TranslateAccelerator(msg
.hwnd
, hAccel
, &msg
)) {
148 TranslateMessage(&msg
);
149 DispatchMessage(&msg
);
156 ////////////////////////////////////////////////////////////////////////////////
158 CPlApplet
* Control_UnloadApplet(CPlApplet
* applet
)
163 for (i
= 0; i
< applet
->count
; i
++) {
164 if (!applet
->info
[i
].dwSize
) continue;
165 applet
->proc(applet
->hWnd
, CPL_STOP
, i
, applet
->info
[i
].lData
);
167 if (applet
->proc
) applet
->proc(applet
->hWnd
, CPL_EXIT
, 0L, 0L);
168 FreeLibrary(applet
->hModule
);
170 HeapFree(GetProcessHeap(), 0, applet
);
174 CPlApplet
* Control_LoadApplet(HWND hWnd
, LPCTSTR cmd
, CPlApplet
** pListHead
)
180 if (!(applet
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*applet
))))
183 if (!(applet
->hModule
= LoadLibrary(cmd
))) {
184 TRACE(_T("Cannot load control panel applet %s\n"), cmd
);
187 if (!(applet
->proc
= (APPLET_PROC
)GetProcAddress(applet
->hModule
, "CPlApplet"))) {
188 // if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "_CPlApplet@16"))) {
189 TRACE(_T("Not a valid control panel applet %s\n"), cmd
);
192 if (!applet
->proc(hWnd
, CPL_INIT
, 0L, 0L)) {
193 TRACE(_T("Init of applet has failed\n"));
196 if ((applet
->count
= applet
->proc(hWnd
, CPL_GETCOUNT
, 0L, 0L)) == 0) {
197 TRACE(_T("No subprogram in applet\n"));
200 applet
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, applet
,
201 // sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOA));
202 sizeof(*applet
) + (applet
->count
- 0) * sizeof(NEWCPLINFO
));
203 for (i
= 0; i
< applet
->count
; i
++) {
204 // applet->info[i].dwSize = sizeof(NEWCPLINFOA);
205 applet
->info
[i
].dwSize
= sizeof(NEWCPLINFO
);
206 /* proc is supposed to return a null value upon success for
207 * CPL_INQUIRE and CPL_NEWINQUIRE
208 * However, real drivers don't seem to behave like this
209 * So, use introspection rather than return value
211 applet
->info
[i
].hIcon
= 0;
212 applet
->proc(hWnd
, CPL_NEWINQUIRE
, i
, (LPARAM
)&applet
->info
[i
]);
213 if (applet
->info
[i
].hIcon
== 0) {
214 applet
->proc(hWnd
, CPL_INQUIRE
, i
, (LPARAM
)&info
);
215 if (info
.idIcon
== 0 || info
.idName
== 0) {
216 TRACE(_T("Couldn't get info from sp %u\n"), i
);
217 applet
->info
[i
].dwSize
= 0;
219 /* convert the old data into the new structure */
220 applet
->info
[i
].dwFlags
= 0;
221 applet
->info
[i
].dwHelpContext
= 0;
222 applet
->info
[i
].lData
= info
.lData
;
223 // applet->info[i].hIcon = LoadIcon(applet->hModule, (LPCTSTR)MAKEINTRESOURCEA(info.idIcon));
224 // applet->info[i].hIcon = LoadIcon(applet->hModule, (LPCTSTR)MAKEINTRESOURCE(info.idIcon));
225 applet
->info
[i
].hIcon
= LoadImage(applet
->hModule
, (LPCTSTR
)info
.idIcon
, IMAGE_ICON
, 0, 0, LR_DEFAULTSIZE
);
227 LoadString(applet
->hModule
, info
.idName
, applet
->info
[i
].szName
, sizeof(applet
->info
[i
].szName
)/sizeof(TCHAR
));
228 //LoadString(applet->hModule, info.idInfo, applet->info[i].szInfo, sizeof(applet->info[i].szInfo)/sizeof(TCHAR));
229 //applet->info[i].szHelpFile[0] = '\0';
230 LoadString(applet
->hModule
, info
.idInfo
, applet
->info
[i
].szInfo
, 192);
233 TRACE(_T("Using CPL_NEWINQUIRE data\n"));
236 applet
->next
= *pListHead
;
240 Control_UnloadApplet(applet
);
244 void Control_DoLaunch(CPlApplet
** pListHead
, HWND hWnd
, LPCTSTR cmd
)
258 TCHAR
* extraPmts
= NULL
;
260 buffer
= HeapAlloc(GetProcessHeap(), 0, _tcslen(cmd
) + 1);
263 end
= _tcscpy(buffer
, cmd
);
267 if (ch
== _T(' ') || ch
== _T(',') || ch
== _T('\0')) {
270 if (*beg
== _T('@')) {
272 } else if (*beg
== _T('\0')) {
278 if (ch
== _T('\0')) break;
280 if (ch
== _T(' ')) while (end
[1] == _T(' ')) end
++;
285 Control_LoadApplet(hWnd
, buffer
, pListHead
);
287 CPlApplet
* applet
= *pListHead
;
288 assert(applet
&& applet
->next
== NULL
);
289 if (sp
>= applet
->count
) {
290 TRACE(_T("Out of bounds (%u >= %u), setting to 0\n"), sp
, applet
->count
);
293 if (applet
->info
[sp
].dwSize
) {
294 if (!applet
->proc(applet
->hWnd
, CPL_STARTWPARMS
, sp
, (LPARAM
)extraPmts
))
295 applet
->proc(applet
->hWnd
, CPL_DBLCLK
, sp
, applet
->info
[sp
].lData
);
297 Control_UnloadApplet(applet
);
301 //static void Control_LaunchApplet(HWND hWnd, CPlEntry* pCPlEntry)
304 HeapFree(GetProcessHeap(), 0, buffer
);
307 //int APIENTRY ControlMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPCTSTR lpCmdLine, int nCmdShow);
309 VOID
Control_RunDLL(HWND hWnd
, HINSTANCE hInst_unused
, LPCTSTR lpCmdLine
, DWORD nCmdShow
)
312 // TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n", hWnd, (DWORD)hInst, debugstr_a(lpCmdLine), nCmdShow);
314 memset(&panel
, 0, sizeof(panel
));
316 if (!lpCmdLine
|| !*lpCmdLine
) {
317 #ifdef _USE_WINE_WND_
318 Control_DoWindow(&panel
, hWnd
, hInst
);
320 ControlMain(hInst
, NULL
, lpCmdLine
, nCmdShow
);
323 Control_DoLaunch(&panel
.first
, hWnd
, lpCmdLine
);
328 ////////////////////////////////////////////////////////////////////////////////
329 #ifdef _USE_WINE_WND_
331 static void Control_WndProc_Create(HWND hWnd
, const CREATESTRUCTA
* cs
)
333 CPanel
* panel
= (CPanel
*)cs
->lpCreateParams
;
335 SetWindowLong(hWnd
, 0, (LPARAM
)panel
);
345 static BOOL
Control_Localize(const CPanel
* panel
, unsigned cx
, unsigned cy
,
346 CPlApplet
** papplet
, unsigned* psp
)
348 unsigned i
, x
= (XSTEP
-XICON
)/2, y
= 0;
352 GetClientRect(panel
->hWnd
, &rc
);
353 for (applet
= panel
->first
; applet
; applet
= applet
= applet
->next
) {
354 for (i
= 0; i
< applet
->count
; i
++) {
355 if (!applet
->info
[i
].dwSize
) continue;
356 if (x
+ XSTEP
>= rc
.right
- rc
.left
) {
360 if (cx
>= x
&& cx
< x
+ XICON
&& cy
>= y
&& cy
< y
+ YSTEP
) {
371 static LRESULT
Control_WndProc_Paint(const CPanel
* panel
, WPARAM wParam
)
376 unsigned i
, x
= 0, y
= 0;
380 hdc
= (wParam
) ? (HDC
)wParam
: BeginPaint(panel
->hWnd
, &ps
);
381 hOldFont
= SelectObject(hdc
, GetStockObject(ANSI_VAR_FONT
));
382 GetClientRect(panel
->hWnd
, &rc
);
383 for (applet
= panel
->first
; applet
; applet
= applet
= applet
->next
) {
384 for (i
= 0; i
< applet
->count
; i
++) {
385 if (x
+ XSTEP
>= rc
.right
- rc
.left
) {
389 if (!applet
->info
[i
].dwSize
) continue;
390 DrawIcon(hdc
, x
+ (XSTEP
-XICON
)/2, y
, applet
->info
[i
].hIcon
);
392 txtRect
.right
= x
+ XSTEP
;
393 txtRect
.top
= y
+ YICON
;
394 txtRect
.bottom
= y
+ YSTEP
;
395 DrawText(hdc
, applet
->info
[i
].szName
, -1, &txtRect
,
396 DT_CENTER
| DT_VCENTER
);
400 SelectObject(hdc
, hOldFont
);
401 if (!wParam
) EndPaint(panel
->hWnd
, &ps
);
405 static LRESULT
Control_WndProc_LButton(CPanel
* panel
, LPARAM lParam
, BOOL up
)
410 if (Control_Localize(panel
, LOWORD(lParam
), HIWORD(lParam
), &applet
, &i
)) {
412 if (panel
->clkApplet
== applet
&& panel
->clkSP
== i
) {
413 applet
->proc(applet
->hWnd
, CPL_DBLCLK
, i
, applet
->info
[i
].lData
);
416 panel
->clkApplet
= applet
;
423 //static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
424 static LRESULT __stdcall
Control_WndProc(HWND hWnd
, UINT wMsg
,
425 WPARAM lParam1
, LPARAM lParam2
)
427 CPanel
* panel
= (CPanel
*)GetWindowLongA(hWnd
, 0);
429 if (panel
|| wMsg
== WM_CREATE
) {
432 Control_WndProc_Create(hWnd
, (CREATESTRUCTA
*)lParam2
);
435 while ((panel
->first
= Control_UnloadApplet(panel
->first
)));
438 return Control_WndProc_Paint(panel
, lParam1
);
440 return Control_WndProc_LButton(panel
, lParam2
, TRUE
);
442 return Control_WndProc_LButton(panel
, lParam2
, FALSE
);
443 /* EPP case WM_COMMAND: */
444 /* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */
448 return DefWindowProcA(hWnd
, wMsg
, lParam1
, lParam2
);
451 static void Control_DoInterface(CPanel
* panel
, HWND hWnd
, HINSTANCE hInst
)
456 wc
.style
= CS_HREDRAW
|CS_VREDRAW
;
457 wc
.lpfnWndProc
= Control_WndProc
;
459 wc
.cbWndExtra
= sizeof(CPlApplet
*);
460 wc
.hInstance
= hInst
;
463 wc
.hbrBackground
= GetStockObject(WHITE_BRUSH
);
464 wc
.lpszMenuName
= NULL
;
465 wc
.lpszClassName
= "Shell_Control_WndClass";
467 if (!RegisterClass(&wc
)) return;
469 CreateWindowEx(0, wc
.lpszClassName
, "Wine Control Panel",
470 WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
471 CW_USEDEFAULT
, CW_USEDEFAULT
,
472 CW_USEDEFAULT
, CW_USEDEFAULT
,
473 hWnd
, (HMENU
)0, hInst
, panel
);
474 if (!panel
->hWnd
) return;
475 while (GetMessage(&msg
, panel
->hWnd
, 0, 0)) {
476 TranslateMessage(&msg
);
477 DispatchMessage(&msg
);
478 if (!panel
->first
) break;
482 static void Control_DoWindow(CPanel
* panel
, HWND hWnd
, HINSTANCE hInst
)
486 TCHAR buffer
[MAX_PATH
];
488 /* TRACE: should grab path somewhere from configuration */
489 if ((h
= FindFirstFile("c:\\winnt\\system32\\*.cpl", &fd
)) != 0) {
491 sprintf(buffer
, "c:\\winnt\\system32\\%s", fd
.cFileName
);
492 if (!strstr(fd
.cFileName
, "powercfg")) {
493 Control_LoadApplet(hWnd
, buffer
, panel
);
495 } while (FindNextFile(h
, &fd
));
499 if (panel
->first
) Control_DoInterface(panel
, hWnd
, hInst
);
502 #endif // _USE_WINE_WND_
505 /*************************************************************************
506 * Control_RunDLL [SHELL32.@]
511 Control_RunDLL(HWND hWnd
, HINSTANCE hInst_unused
, LPCSTR lpCmdLine
, DWORD nCmdShow
)
513 // TRACE("(0x%08x, 0x%08lx, %s, 0x%08lx)\n", hWnd, (DWORD)hInst, debugstr_a(lpCmdLine), nCmdShow);
516 /*************************************************************************
517 * Control_FillCache_RunDLL [SHELL32.@]
521 Control_FillCache_RunDLL(HWND hWnd
, HANDLE hModule
, DWORD w
, DWORD x
)
523 TRACE(_T("0x%04x 0x%04x 0x%04lx 0x%04lx stub\n"), hWnd
, hModule
, w
, x
);
527 /*************************************************************************
528 * RunDLL_CallEntry16 [SHELL32.122]
529 * the name is probably wrong
532 RunDLL_CallEntry16(DWORD v
, DWORD w
, DWORD x
, DWORD y
, DWORD z
)
534 TRACE(_T("0x%04lx 0x%04lx 0x%04lx 0x%04lx 0x%04lx stub\n"),v
,w
,x
,y
,z
);
538 /*************************************************************************
539 * CallCPLEntry16 [SHELL32.166]
541 * called by desk.cpl on "Advanced" with:
542 * hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0
546 CallCPLEntry16(HMODULE hMod
, FARPROC pFunc
, DWORD dw3
, DWORD dw4
, DWORD dw5
, DWORD dw6
)
548 TRACE(_T("(%04x, %p, %08lx, %08lx, %08lx, %08lx): stub.\n"), hMod
, pFunc
, dw3
, dw4
, dw5
, dw6
);