Author: rharabien Date: Sun Jan 15 00:59:29 2012 New Revision: 54967
URL: http://svn.reactos.org/svn/reactos?rev=54967&view=rev Log: - Try to fix KVM
Modified: trunk/reactos/dll/win32/shell32/control.cpp
Modified: trunk/reactos/dll/win32/shell32/control.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/control.c... ============================================================================== --- trunk/reactos/dll/win32/shell32/control.cpp [iso-8859-1] (original) +++ trunk/reactos/dll/win32/shell32/control.cpp [iso-8859-1] Sun Jan 15 00:59:29 2012 @@ -348,102 +348,146 @@ Control_DoInterface(panel, hWnd, hInst); }
-static void Control_DoLaunch(CPanel *pPanel, HWND hWnd, LPCWSTR pwszCmd) -{ - /* Make a pwszCmd copy so we can modify it */ - LPWSTR pwszCmdCopy = _wcsdup(pwszCmd); - if (!pwszCmdCopy) +static void Control_DoLaunch(CPanel* panel, HWND hWnd, LPCWSTR wszCmd) + /* forms to parse: + * foo.cpl,@sp,str + * foo.cpl,@sp + * foo.cpl,,str + * foo.cpl @sp + * foo.cpl str + * "a path\foo.cpl" + */ +{ + LPWSTR buffer; + LPWSTR beg = NULL; + LPWSTR end; + WCHAR ch; + LPCWSTR ptr, ptr2; + WCHAR szName[MAX_PATH]; + unsigned sp = 0; + LPWSTR extraPmts = NULL; + int quoted = 0; + BOOL spSet = FALSE; + HANDLE hMutex; + UINT Length; + + ptr = wcsrchr(wszCmd, L'\'); + ptr2 = wcsrchr(wszCmd, L','); + if (!ptr2) + { + ptr2 = wszCmd + wcslen(wszCmd) + 1; + } + + if (ptr) + ptr++; + else + ptr = wszCmd; + + Length = (ptr2 - ptr); + if (Length >= MAX_PATH) return;
- LPWSTR pwszPath = pwszCmdCopy, pwszArg = NULL, pwszArg2 = NULL; - - /* Path can be quoted */ - if (pwszPath[0] == L'"') - { - ++pwszPath; - pwszArg = wcschr(pwszPath, L'"'); - if (pwszArg) - *(pwszArg++) = '\0'; - } - else - pwszArg = pwszCmdCopy; - - /* First argument starts after space or ','. Note: we ignore characters between '"' and ',' or ' '. */ - if (pwszArg) - pwszArg = wcspbrk(pwszArg, L" ,"); - if (pwszArg) - { - /* NULL terminate path and find first character of arg */ - *(pwszArg++) = L'\0'; - if (pwszArg[0] == L'"') - { - ++pwszArg; - pwszArg2 = wcschr(pwszArg, L'"'); - if (pwszArg2) - *(pwszArg2++) = L'\0'; - } else - pwszArg2 = pwszArg; - - /* Second argument always starts with ','. Note: we ignore characters between '"' and ','. */ - if (pwszArg2) - pwszArg2 = wcschr(pwszArg2, L','); - } - - TRACE("Launch %ls, arg %ls, arg2 %ls\n", pwszPath, pwszArg, pwszArg2); - - /* Create a mutex to disallow running multiple instances */ - HANDLE hMutex = CreateMutexW(NULL, TRUE, PathFindFileNameW(pwszPath)); - if (!hMutex || GetLastError() == ERROR_ALREADY_EXISTS) - { - TRACE("Next instance disallowed\n"); - if (hMutex) - CloseHandle(hMutex); + memcpy(szName, (LPVOID)ptr, Length * sizeof(WCHAR)); + szName[Length] = L'\0'; + hMutex = CreateMutexW(NULL, TRUE, szName); + + if ((!hMutex) || (GetLastError() == ERROR_ALREADY_EXISTS)) return; - } - - /* Load applet cpl */ - TRACE("Load applet %ls\n", pwszPath); - Control_LoadApplet(hWnd, pwszPath, pPanel); - if (pPanel->first) - { - /* First pPanel applet is the new one */ - CPlApplet *pApplet = pPanel->first; - assert(pApplet && pApplet->next == NULL); - TRACE("pApplet->count %d\n", pApplet->count); - - /* Note: if there is only one applet, first argument is ignored */ - INT i = 0; - if (pApplet->count > 1 && pwszArg && pwszArg[0]) - { - /* If arg begins with '@', number specifies applet index */ - if (pwszArg[0] == L'@') - i = _wtoi(pwszArg + 1); - else - { - /* Otherwise it's applet name */ - for (i = 0; i < (INT)pApplet->count; ++i) - if (!wcscmp(pwszArg, pApplet->info[i].szName)) - break; - } - } - - if (i >= 0 && i < (INT)pApplet->count && pApplet->info[i].dwSize) - { - /* Start the applet */ - TRACE("Starting applet %d\n", i); - if (!pApplet->proc(pApplet->hWnd, CPL_DBLCLK, i, pApplet->info[i].lData)) - pApplet->proc(pApplet->hWnd, CPL_STARTWPARMSA, i, (LPARAM)pwszArg); - } else - ERR("Applet not found: %ls\n", pwszArg ? pwszArg : L"NULL"); - - Control_UnloadApplet(pApplet); - } - else - ERR("Failed to load applet %ls\n", pwszPath); + buffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(wszCmd) + 1) * sizeof(*wszCmd)); + if (!buffer) + { + CloseHandle(hMutex); + return; + } + + TRACE("[shell32, Control_DoLaunch] wszCmd = %ws\n", wszCmd); + + end = wcscpy(buffer, wszCmd); + for (;;) + { + ch = *end; + if (ch == '"') + quoted = !quoted; + + if (!quoted && (ch == ',' || ch == '\0')) + { + *end = '\0'; + if (beg) + { + if (*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++; + } + while ((ptr = StrChrW(buffer, '"'))) + memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR)); + + while ((ptr = StrChrW(extraPmts, '"'))) + memmove((LPVOID)ptr, ptr+1, wcslen(ptr)*sizeof(WCHAR)); + + TRACE("[shell32, Control_DoLaunch] cmd %s, extra %s, sp %d\n", debugstr_w(buffer), debugstr_w(extraPmts), sp); + + Control_LoadApplet(hWnd, buffer, panel); + + if (panel->first) + { + CPlApplet* applet = panel->first; + + TRACE("[shell32, Control_DoLaunch] applet->count %d, applet->info[sp].szName %ws\n", applet->count, applet->info[sp].szName); + + 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 ((extraPmts) && extraPmts[0] && (!spSet)) + { + while ((lstrcmpiW(extraPmts, applet->info[sp].szName)) && (sp < applet->count)) + sp++; + + if (sp >= applet->count) + { + ReleaseMutex(hMutex); + CloseHandle(hMutex); + Control_UnloadApplet(applet); + HeapFree(GetProcessHeap(), 0, buffer); + return; + } + } + + 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); CloseHandle(hMutex); - free(pwszCmdCopy); + HeapFree(GetProcessHeap(), 0, buffer); }
/************************************************************************* @@ -452,22 +496,22 @@ */ EXTERN_C void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow) { - CPanel Panel; + CPanel panel;
TRACE("(%p, %p, %s, 0x%08x)\n", hWnd, hInst, debugstr_w(cmd), nCmdShow);
- memset(&Panel, 0, sizeof(Panel)); + memset(&panel, 0, sizeof(panel));
if (!cmd || !*cmd) { TRACE("[shell32, Control_RunDLLW] Calling Control_DoWindow\n"); - Control_DoWindow(&Panel, hWnd, hInst); + Control_DoWindow(&panel, hWnd, hInst); } else { TRACE("[shell32, Control_RunDLLW] Calling Control_DoLaunch\n"); - Control_DoLaunch(&Panel, hWnd, cmd); + Control_DoLaunch(&panel, hWnd, cmd); } }