[SHELL32]

* Merge r53700. Point 3 in bug 6481 was fixed by fixing the parser (at line 414) to use only ',' as the delimiter, to match Windows behavior.

svn path=/trunk/; revision=53702
This commit is contained in:
Amine Khaldi 2011-09-13 13:13:35 +00:00
parent 744be47dde
commit 3a93089ba7

View file

@ -27,11 +27,15 @@ CPlApplet* Control_UnloadApplet(CPlApplet* applet)
unsigned i; unsigned i;
CPlApplet* next; CPlApplet* next;
for (i = 0; i < applet->count; i++) { for (i = 0; i < applet->count; i++)
if (!applet->info[i].dwSize) continue; {
if (!applet->info[i].dwSize)
continue;
applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData); applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData);
} }
if (applet->proc) applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L); if (applet->proc)
applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
FreeLibrary(applet->hModule); FreeLibrary(applet->hModule);
next = applet->next; next = applet->next;
HeapFree(GetProcessHeap(), 0, applet); HeapFree(GetProcessHeap(), 0, applet);
@ -50,66 +54,75 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel)
applet->hWnd = hWnd; applet->hWnd = hWnd;
if (!(applet->hModule = LoadLibraryW(cmd))) { if (!(applet->hModule = LoadLibraryW(cmd)))
{
WARN("Cannot load control panel applet %s\n", debugstr_w(cmd)); WARN("Cannot load control panel applet %s\n", debugstr_w(cmd));
goto theError; goto theError;
} }
if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) { if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet")))
{
WARN("Not a valid control panel applet %s\n", debugstr_w(cmd)); WARN("Not a valid control panel applet %s\n", debugstr_w(cmd));
goto theError; goto theError;
} }
if (!applet->proc(hWnd, CPL_INIT, 0L, 0L)) { if (!applet->proc(hWnd, CPL_INIT, 0L, 0L))
{
WARN("Init of applet has failed\n"); WARN("Init of applet has failed\n");
goto theError; goto theError;
} }
if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0) { if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0)
{
WARN("No subprogram in applet\n"); WARN("No subprogram in applet\n");
goto theError; goto theError;
} }
applet = (CPlApplet *)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet, applet = (CPlApplet *)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW)); sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW));
for (i = 0; i < applet->count; i++) { for (i = 0; i < applet->count; i++)
ZeroMemory(&newinfo, sizeof(newinfo)); {
newinfo.dwSize = sizeof(NEWCPLINFOW); ZeroMemory(&newinfo, sizeof(newinfo));
applet->info[i].dwSize = sizeof(NEWCPLINFOW); newinfo.dwSize = sizeof(NEWCPLINFOW);
applet->info[i].dwSize = sizeof(NEWCPLINFOW);
/* proc is supposed to return a null value upon success for /* proc is supposed to return a null value upon success for
* CPL_INQUIRE and CPL_NEWINQUIRE * CPL_INQUIRE and CPL_NEWINQUIRE
* However, real drivers don't seem to behave like this * However, real drivers don't seem to behave like this
* So, use introspection rather than return value * So, use introspection rather than return value
*/ */
applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo); applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo);
if (newinfo.hIcon == 0) { if (newinfo.hIcon == 0)
applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info); {
if (info.idIcon == 0 || info.idName == 0) { applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
WARN("Couldn't get info from sp %u\n", i); if (info.idIcon == 0 || info.idName == 0)
applet->info[i].dwSize = 0; {
} else { WARN("Couldn't get info from sp %u\n", i);
/* convert the old data into the new structure */ applet->info[i].dwSize = 0;
applet->info[i].dwFlags = 0; }
applet->info[i].dwHelpContext = 0; else
applet->info[i].lData = info.lData; {
applet->info[i].hIcon = LoadIconW(applet->hModule, /* convert the old data into the new structure */
MAKEINTRESOURCEW(info.idIcon)); applet->info[i].dwFlags = 0;
LoadStringW(applet->hModule, info.idName, applet->info[i].dwHelpContext = 0;
applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR)); applet->info[i].lData = info.lData;
LoadStringW(applet->hModule, info.idInfo, applet->info[i].hIcon = LoadIconW(applet->hModule,
applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); MAKEINTRESOURCEW(info.idIcon));
applet->info[i].szHelpFile[0] = '\0'; LoadStringW(applet->hModule, info.idName,
} applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR));
} LoadStringW(applet->hModule, info.idInfo,
else applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR));
{ applet->info[i].szHelpFile[0] = '\0';
CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize); }
if (newinfo.dwSize != sizeof(NEWCPLINFOW)) }
{ else
{
CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize);
if (newinfo.dwSize != sizeof(NEWCPLINFOW))
{
applet->info[i].dwSize = sizeof(NEWCPLINFOW); applet->info[i].dwSize = sizeof(NEWCPLINFOW);
lstrcpyW(applet->info[i].szName, newinfo.szName); lstrcpyW(applet->info[i].szName, newinfo.szName);
lstrcpyW(applet->info[i].szInfo, newinfo.szInfo); lstrcpyW(applet->info[i].szInfo, newinfo.szInfo);
lstrcpyW(applet->info[i].szHelpFile, newinfo.szHelpFile); lstrcpyW(applet->info[i].szHelpFile, newinfo.szHelpFile);
} }
} }
} }
applet->next = panel->first; applet->next = panel->first;
@ -145,20 +158,25 @@ static BOOL Control_Localize(const CPanel* panel, int cx, int cy,
RECT rc; RECT rc;
GetClientRect(panel->hWnd, &rc); GetClientRect(panel->hWnd, &rc);
for (applet = panel->first; applet; applet = applet->next) { for (applet = panel->first; applet; applet = applet->next)
for (i = 0; i < applet->count; i++) { {
if (!applet->info[i].dwSize) continue; for (i = 0; i < applet->count; i++)
if (x + XSTEP >= rc.right - rc.left) { {
x = (XSTEP-XICON)/2; if (!applet->info[i].dwSize)
y += YSTEP; 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;
} }
if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP) {
*papplet = applet;
*psp = i;
return TRUE;
}
x += XSTEP;
}
} }
return FALSE; return FALSE;
} }
@ -176,25 +194,33 @@ static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam)
hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps); hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps);
hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT)); hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
GetClientRect(panel->hWnd, &rc); GetClientRect(panel->hWnd, &rc);
for (applet = panel->first; applet; applet = applet->next) {
for (i = 0; i < applet->count; i++) { for (applet = panel->first; applet; applet = applet->next)
if (x + XSTEP >= rc.right - rc.left) { {
x = 0; for (i = 0; i < applet->count; i++)
y += YSTEP; {
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;
DrawTextW(hdc, applet->info[i].szName, -1, &txtRect,
DT_CENTER | DT_VCENTER);
x += XSTEP;
} }
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;
DrawTextW(hdc, applet->info[i].szName, -1, &txtRect,
DT_CENTER | DT_VCENTER);
x += XSTEP;
}
} }
SelectObject(hdc, hOldFont); SelectObject(hdc, hOldFont);
if (!wParam) EndPaint(panel->hWnd, &ps); if (!wParam)
EndPaint(panel->hWnd, &ps);
return 0; return 0;
} }
@ -203,15 +229,20 @@ static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
unsigned i; unsigned i;
CPlApplet* applet; CPlApplet* applet;
if (Control_Localize(panel, (short)LOWORD(lParam), (short)HIWORD(lParam), &applet, &i)) { if (Control_Localize(panel, (short)LOWORD(lParam), (short)HIWORD(lParam), &applet, &i))
if (up) { {
if (panel->clkApplet == applet && panel->clkSP == i) { if (up)
applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData); {
} if (panel->clkApplet == applet && panel->clkSP == i)
} else { {
panel->clkApplet = applet; applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData);
panel->clkSP = i; }
} }
else
{
panel->clkApplet = applet;
panel->clkSP = i;
}
} }
return 0; return 0;
} }
@ -219,31 +250,35 @@ static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg, static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
WPARAM lParam1, LPARAM lParam2) WPARAM lParam1, LPARAM lParam2)
{ {
CPanel* panel = (CPanel*)GetWindowLongPtrW(hWnd, 0); CPanel* panel = (CPanel*)GetWindowLongPtrW(hWnd, 0);
if (panel || wMsg == WM_CREATE) { if (panel || wMsg == WM_CREATE)
switch (wMsg) { {
case WM_CREATE: switch (wMsg)
Control_WndProc_Create(hWnd, (CREATESTRUCTW*)lParam2); {
return 0; case WM_CREATE:
case WM_DESTROY: Control_WndProc_Create(hWnd, (CREATESTRUCTW*)lParam2);
{ return 0;
CPlApplet* applet = panel->first;
while (applet) case WM_DESTROY:
applet = Control_UnloadApplet(applet); {
} CPlApplet* applet = panel->first;
PostQuitMessage(0); while (applet)
break; applet = Control_UnloadApplet(applet);
case WM_PAINT:
return Control_WndProc_Paint(panel, lParam1); PostQuitMessage(0);
case WM_LBUTTONUP: }; break;
return Control_WndProc_LButton(panel, lParam2, TRUE);
case WM_LBUTTONDOWN: case WM_PAINT:
return Control_WndProc_LButton(panel, lParam2, FALSE); return Control_WndProc_Paint(panel, lParam1);
/* EPP case WM_COMMAND: */ case WM_LBUTTONUP:
/* EPP return Control_WndProc_Command(mwi, lParam1, lParam2); */ 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 DefWindowProcW(hWnd, wMsg, lParam1, lParam2); return DefWindowProcW(hWnd, wMsg, lParam1, lParam2);
} }
@ -271,15 +306,19 @@ static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, NULL, hInst, panel); hWnd, NULL, hInst, panel);
if (!panel->hWnd) return;
if (!panel->first) { if (!panel->hWnd)
/* FIXME appName & message should be localized */ return;
MessageBoxW(panel->hWnd, L"Cannot load any applets", appName, MB_OK);
return; if (!panel->first)
{
/* FIXME appName & message should be localized */
MessageBoxW(panel->hWnd, L"Cannot load any applets", appName, MB_OK);
return;
} }
while (GetMessageW(&msg, panel->hWnd, 0, 0)) { while (GetMessageW(&msg, panel->hWnd, 0, 0))
{
TranslateMessage(&msg); TranslateMessage(&msg);
DispatchMessageW(&msg); DispatchMessageW(&msg);
} }
@ -298,12 +337,14 @@ static void Control_DoWindow(CPanel* panel, HWND hWnd, HINSTANCE hInst)
*p++ = '\\'; *p++ = '\\';
wcscpy(p, wszAllCpl); wcscpy(p, wszAllCpl);
if ((h = FindFirstFileW(buffer, &fd)) != INVALID_HANDLE_VALUE) { if ((h = FindFirstFileW(buffer, &fd)) != INVALID_HANDLE_VALUE)
do { {
wcscpy(p, fd.cFileName); do
Control_LoadApplet(hWnd, buffer, panel); {
} while (FindNextFileW(h, &fd)); wcscpy(p, fd.cFileName);
FindClose(h); Control_LoadApplet(hWnd, buffer, panel);
} while (FindNextFileW(h, &fd));
FindClose(h);
} }
Control_DoInterface(panel, hWnd, hInst); Control_DoInterface(panel, hWnd, hInst);
@ -360,68 +401,92 @@ static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd)
CloseHandle(hMutex); CloseHandle(hMutex);
return; return;
} }
TRACE("[shell32, Control_DoLaunch] wszCmd = %ws\n", wszCmd);
end = wcscpy(buffer, wszCmd); end = wcscpy(buffer, wszCmd);
for (;;) { for (;;)
ch = *end; {
if (ch == '"') quoted = !quoted; ch = *end;
if (!quoted && (ch == ' ' || ch == ',' || ch == '\0')) { if (ch == '"')
*end = '\0'; quoted = !quoted;
if (beg) {
if (*beg == '@') { if (!quoted && (ch == ',' || ch == '\0'))
sp = atoiW(beg + 1); {
spSet = TRUE; *end = '\0';
} else if (*beg == '\0') { if (beg)
sp = 0; {
spSet = TRUE; if (*beg == '@')
} else { {
extraPmts = beg; sp = atoiW(beg + 1);
spSet = TRUE;
}
else if (*beg == '\0')
{
sp = 0;
spSet = TRUE;
}
else
{
extraPmts = beg;
}
}
if (ch == '\0') break;
beg = end + 1;
if (ch == ' ')
while (end[1] == ' ')
end++;
} }
} end++;
if (ch == '\0') break;
beg = end + 1;
if (ch == ' ') while (end[1] == ' ') end++;
}
end++;
} }
while ((ptr = StrChrW(buffer, '"'))) while ((ptr = StrChrW(buffer, '"')))
memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR)); memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR));
while ((ptr = StrChrW(extraPmts, '"'))) while ((ptr = StrChrW(extraPmts, '"')))
memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR)); memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR));
TRACE("cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp); TRACE("[shell32, Control_DoLaunch] cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp);
Control_LoadApplet(hWnd, buffer, panel); Control_LoadApplet(hWnd, buffer, panel);
if (panel->first) { if (panel->first)
CPlApplet* applet = panel->first; {
CPlApplet* applet = panel->first;
assert(applet && applet->next == NULL); TRACE("[shell32, Control_DoLaunch] applet->count %d, applet->info[sp].szName %ws\n", applet->count, applet->info[sp].szName);
if (sp >= applet->count) {
WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count);
sp = 0;
}
if ((extraPmts) && extraPmts[0] &&(!spSet)) assert(applet && applet->next == NULL);
{ if (sp >= applet->count)
while ((lstrcmpiW(extraPmts, applet->info[sp].szName)) && (sp < applet->count)) {
sp++; WARN("Out of bounds (%u >= %u), setting to 0\n", sp, applet->count);
sp = 0;
}
if (sp >= applet->count) if ((extraPmts) && extraPmts[0] && (!spSet))
{ {
ReleaseMutex(hMutex); while ((lstrcmpiW(extraPmts, applet->info[sp].szName)) && (sp < applet->count))
CloseHandle(hMutex); sp++;
Control_UnloadApplet(applet);
HeapFree(GetProcessHeap(), 0, buffer); if (sp >= applet->count)
return; {
} ReleaseMutex(hMutex);
} CloseHandle(hMutex);
if (applet->info[sp].dwSize) { Control_UnloadApplet(applet);
if (!applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData)) HeapFree(GetProcessHeap(), 0, buffer);
applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts); return;
} }
Control_UnloadApplet(applet); }
if (applet->info[sp].dwSize)
{
if (!applet->proc(applet->hWnd, CPL_DBLCLK, sp, applet->info[sp].lData))
applet->proc(applet->hWnd, CPL_STARTWPARMSA, sp, (LPARAM)extraPmts);
}
Control_UnloadApplet(applet);
} }
ReleaseMutex(hMutex); ReleaseMutex(hMutex);
CloseHandle(hMutex); CloseHandle(hMutex);
HeapFree(GetProcessHeap(), 0, buffer); HeapFree(GetProcessHeap(), 0, buffer);
@ -440,9 +505,14 @@ EXTERN_C void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DW
memset(&panel, 0, sizeof(panel)); memset(&panel, 0, sizeof(panel));
if (!cmd || !*cmd) { if (!cmd || !*cmd)
{
TRACE("[shell32, Control_RunDLLW] Calling Control_DoWindow\n");
Control_DoWindow(&panel, hWnd, hInst); Control_DoWindow(&panel, hWnd, hInst);
} else { }
else
{
TRACE("[shell32, Control_RunDLLW] Calling Control_DoLaunch\n");
Control_DoLaunch(&panel, hWnd, cmd); Control_DoLaunch(&panel, hWnd, cmd);
} }
} }
@ -455,10 +525,12 @@ EXTERN_C void WINAPI Control_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWO
{ {
DWORD len = MultiByteToWideChar(CP_ACP, 0, cmd, -1, NULL, 0 ); DWORD len = MultiByteToWideChar(CP_ACP, 0, cmd, -1, NULL, 0 );
LPWSTR wszCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); LPWSTR wszCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (wszCmd && MultiByteToWideChar(CP_ACP, 0, cmd, -1, wszCmd, len )) if (wszCmd && MultiByteToWideChar(CP_ACP, 0, cmd, -1, wszCmd, len ))
{ {
Control_RunDLLW(hWnd, hInst, wszCmd, nCmdShow); Control_RunDLLW(hWnd, hInst, wszCmd, nCmdShow);
} }
HeapFree(GetProcessHeap(), 0, wszCmd); HeapFree(GetProcessHeap(), 0, wszCmd);
} }