/************************************************************************** * ISF_ControlPanel_fnEnumObjects */ static BOOL SHELL_RegisterCPanelApp(IEnumIDList* list, LPCSTR path) { LPITEMIDLIST pidl; CPlApplet* applet; CPanel panel; CPLINFO info; unsigned i; int iconIdx; char displayName[MAX_PATH]; char comment[MAX_PATH]; WCHAR wpath[MAX_PATH]; MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH); panel.first = NULL; applet = Control_LoadApplet(0, wpath, &panel); if (applet) { for(i=0; i<applet->count; ++i) { WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0); WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0); applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info); if (info.idIcon > 0) iconIdx = -info.idIcon; /* negative icon index instead of icon number */ else iconIdx = 0; pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx); if (pidl) AddToEnumList(list, pidl); } Control_UnloadApplet(applet); } return TRUE; }
static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up) { unsigned i; CPlApplet* applet; if (Control_Localize(panel, (short)LOWORD(lParam), (short)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; }
CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) { CPlApplet* applet; unsigned i; CPLINFO info; NEWCPLINFOW newinfo; if (!(applet = (CPlApplet *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) return applet; applet->hWnd = hWnd; if (!(applet->hModule = LoadLibraryW(cmd))) { WARN("Cannot load control panel applet %s\n", debugstr_w(cmd)); goto theError; } if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet"))) { WARN("Not a valid control panel applet %s\n", debugstr_w(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 = (CPlApplet *)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet, sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW)); for (i = 0; i < applet->count; i++) { ZeroMemory(&newinfo, sizeof(newinfo)); newinfo.dwSize = sizeof(NEWCPLINFOW); applet->info[i].dwSize = sizeof(NEWCPLINFOW); /* 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)&newinfo); if (newinfo.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 = LoadIconW(applet->hModule, MAKEINTRESOURCEW(info.idIcon)); LoadStringW(applet->hModule, info.idName, applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR)); LoadStringW(applet->hModule, info.idInfo, applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR)); applet->info[i].szHelpFile[0] = '\0'; } } else { CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize); if (newinfo.dwSize != sizeof(NEWCPLINFOW)) { applet->info[i].dwSize = sizeof(NEWCPLINFOW); lstrcpyW(applet->info[i].szName, newinfo.szName); lstrcpyW(applet->info[i].szInfo, newinfo.szInfo); lstrcpyW(applet->info[i].szHelpFile, newinfo.szHelpFile); } } } applet->next = panel->first; panel->first = applet; return applet; theError: Control_UnloadApplet(applet); return NULL; }
static void Control_DoLaunch(CPanel *pPanel, HWND hWnd, LPCWSTR pwszCmd) { HANDLE hMutex; /* Make a pwszCmd copy so we can modify it */ LPWSTR pwszCmdCopy = _wcsdup(pwszCmd); LPWSTR pwszPath = pwszCmdCopy, pwszArg = NULL, pwszArg2 = NULL; if (!pwszCmdCopy) return; /* 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 */ hMutex = CreateMutexW(NULL, TRUE, PathFindFileNameW(pwszPath)); if (!hMutex || GetLastError() == ERROR_ALREADY_EXISTS) { TRACE("Next instance disallowed\n"); if (hMutex) CloseHandle(hMutex); return; } /* Load applet cpl */ TRACE("Load applet %ls\n", pwszPath); Control_LoadApplet(hWnd, pwszPath, pPanel); if (pPanel->first) { INT i = 0; /* 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 */ 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_STARTWPARMSW, i, (LPARAM)pwszArg)) pApplet->proc(pApplet->hWnd, CPL_DBLCLK, i, pApplet->info[i].lData); } else ERR("Applet not found: %ls\n", pwszArg ? pwszArg : L"NULL"); Control_UnloadApplet(pApplet); } else ERR("Failed to load applet %ls\n", pwszPath); ReleaseMutex(hMutex); CloseHandle(hMutex); free(pwszCmdCopy); }