ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

control.cpp
Go to the documentation of this file.
00001 /* Control Panel management
00002  *
00003  * Copyright 2001 Eric Pouech
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00018  */
00019 
00020 
00021 #include <precomp.h>
00022 
00023 WINE_DEFAULT_DEBUG_CHANNEL(shlctrl);
00024 
00025 CPlApplet*    Control_UnloadApplet(CPlApplet* applet)
00026 {
00027     unsigned    i;
00028     CPlApplet*    next;
00029 
00030     for (i = 0; i < applet->count; i++)
00031     {
00032         if (!applet->info[i].dwSize)
00033             continue;
00034         applet->proc(applet->hWnd, CPL_STOP, i, applet->info[i].lData);
00035     }
00036     if (applet->proc)
00037         applet->proc(applet->hWnd, CPL_EXIT, 0L, 0L);
00038     
00039     FreeLibrary(applet->hModule);
00040     next = applet->next;
00041     HeapFree(GetProcessHeap(), 0, applet);
00042     return next;
00043 }
00044 
00045 CPlApplet*    Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel)
00046 {
00047     CPlApplet*    applet;
00048     unsigned     i;
00049     CPLINFO    info;
00050     NEWCPLINFOW newinfo;
00051 
00052     if (!(applet = (CPlApplet *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet))))
00053        return applet;
00054 
00055     applet->hWnd = hWnd;
00056 
00057     if (!(applet->hModule = LoadLibraryW(cmd)))
00058     {
00059         WARN("Cannot load control panel applet %s\n", debugstr_w(cmd));
00060         goto theError;
00061     }
00062     if (!(applet->proc = (APPLET_PROC)GetProcAddress(applet->hModule, "CPlApplet")))
00063     {
00064         WARN("Not a valid control panel applet %s\n", debugstr_w(cmd));
00065         goto theError;
00066     }
00067     if (!applet->proc(hWnd, CPL_INIT, 0L, 0L))
00068     {
00069         WARN("Init of applet has failed\n");
00070         goto theError;
00071     }
00072     if ((applet->count = applet->proc(hWnd, CPL_GETCOUNT, 0L, 0L)) == 0)
00073     {
00074         WARN("No subprogram in applet\n");
00075         goto theError;
00076     }
00077 
00078     applet = (CPlApplet *)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, applet,
00079              sizeof(*applet) + (applet->count - 1) * sizeof(NEWCPLINFOW));
00080 
00081     for (i = 0; i < applet->count; i++)
00082     {
00083         ZeroMemory(&newinfo, sizeof(newinfo));
00084         newinfo.dwSize = sizeof(NEWCPLINFOW);
00085         applet->info[i].dwSize = sizeof(NEWCPLINFOW);
00086        /* proc is supposed to return a null value upon success for
00087     * CPL_INQUIRE and CPL_NEWINQUIRE
00088     * However, real drivers don't seem to behave like this
00089     * So, use introspection rather than return value
00090     */
00091         applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo);
00092         if (newinfo.hIcon == 0)
00093         {
00094             applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info);
00095             if (info.idIcon == 0 || info.idName == 0)
00096             {
00097                 WARN("Couldn't get info from sp %u\n", i);
00098                 applet->info[i].dwSize = 0;
00099             }
00100             else
00101             {
00102                 /* convert the old data into the new structure */
00103                 applet->info[i].dwFlags = 0;
00104                 applet->info[i].dwHelpContext = 0;
00105                 applet->info[i].lData = info.lData;
00106                 applet->info[i].hIcon = LoadIconW(applet->hModule,
00107                                 MAKEINTRESOURCEW(info.idIcon));
00108                 LoadStringW(applet->hModule, info.idName,
00109                     applet->info[i].szName, sizeof(applet->info[i].szName) / sizeof(WCHAR));
00110                 LoadStringW(applet->hModule, info.idInfo,
00111                     applet->info[i].szInfo, sizeof(applet->info[i].szInfo) / sizeof(WCHAR));
00112                 applet->info[i].szHelpFile[0] = '\0';
00113             }
00114         }
00115         else
00116         {
00117             CopyMemory(&applet->info[i], &newinfo, newinfo.dwSize);
00118             if (newinfo.dwSize != sizeof(NEWCPLINFOW))
00119             {
00120                 applet->info[i].dwSize = sizeof(NEWCPLINFOW);
00121                 lstrcpyW(applet->info[i].szName, newinfo.szName);
00122                 lstrcpyW(applet->info[i].szInfo, newinfo.szInfo);
00123                 lstrcpyW(applet->info[i].szHelpFile, newinfo.szHelpFile);
00124             }
00125         }
00126     }
00127 
00128     applet->next = panel->first;
00129     panel->first = applet;
00130 
00131     return applet;
00132 
00133  theError:
00134     Control_UnloadApplet(applet);
00135     return NULL;
00136 }
00137 
00138 static void Control_WndProc_Create(HWND hWnd, const CREATESTRUCTW* cs)
00139 {
00140    CPanel*    panel = (CPanel*)cs->lpCreateParams;
00141 
00142    SetWindowLongPtrW(hWnd, 0, (LONG_PTR)panel);
00143    panel->status = 0;
00144    panel->hWnd = hWnd;
00145 }
00146 
00147 #define    XICON    32
00148 #define XSTEP    128
00149 #define    YICON    32
00150 #define YSTEP    64
00151 
00152 static BOOL    Control_Localize(const CPanel* panel, int cx, int cy,
00153                  CPlApplet** papplet, unsigned* psp)
00154 {
00155     unsigned int    i;
00156     int                x = (XSTEP-XICON)/2, y = 0;
00157     CPlApplet*    applet;
00158     RECT    rc;
00159 
00160     GetClientRect(panel->hWnd, &rc);
00161     for (applet = panel->first; applet; applet = applet->next)
00162     {
00163         for (i = 0; i < applet->count; i++)
00164         {
00165             if (!applet->info[i].dwSize)
00166                 continue;
00167             if (x + XSTEP >= rc.right - rc.left)
00168             {
00169                 x = (XSTEP-XICON)/2;
00170                 y += YSTEP;
00171             }
00172             if (cx >= x && cx < x + XICON && cy >= y && cy < y + YSTEP)
00173             {
00174                 *papplet = applet;
00175                 *psp = i;
00176                 return TRUE;
00177             }
00178             x += XSTEP;
00179         }
00180     }
00181     return FALSE;
00182 }
00183 
00184 static LRESULT Control_WndProc_Paint(const CPanel* panel, WPARAM wParam)
00185 {
00186     HDC        hdc;
00187     PAINTSTRUCT    ps;
00188     RECT    rc, txtRect;
00189     unsigned int    i;
00190     int                x = 0, y = 0;
00191     CPlApplet*    applet;
00192     HGDIOBJ    hOldFont;
00193 
00194     hdc = (wParam) ? (HDC)wParam : BeginPaint(panel->hWnd, &ps);
00195     hOldFont = SelectObject(hdc, GetStockObject(ANSI_VAR_FONT));
00196     GetClientRect(panel->hWnd, &rc);
00197     
00198     for (applet = panel->first; applet; applet = applet->next)
00199     {
00200         for (i = 0; i < applet->count; i++)
00201         {
00202             if (x + XSTEP >= rc.right - rc.left)
00203             {
00204                 x = 0;
00205                 y += YSTEP;
00206             }
00207             if (!applet->info[i].dwSize)
00208                 continue;
00209             DrawIcon(hdc, x + (XSTEP-XICON)/2, y, applet->info[i].hIcon);
00210             txtRect.left = x;
00211             txtRect.right = x + XSTEP;
00212             txtRect.top = y + YICON;
00213             txtRect.bottom = y + YSTEP;
00214             DrawTextW(hdc, applet->info[i].szName, -1, &txtRect,
00215                   DT_CENTER | DT_VCENTER);
00216             x += XSTEP;
00217         }
00218     }
00219 
00220     SelectObject(hdc, hOldFont);
00221     if (!wParam)
00222         EndPaint(panel->hWnd, &ps);
00223 
00224     return 0;
00225 }
00226 
00227 static LRESULT Control_WndProc_LButton(CPanel* panel, LPARAM lParam, BOOL up)
00228 {
00229     unsigned    i;
00230     CPlApplet*    applet;
00231 
00232     if (Control_Localize(panel, (short)LOWORD(lParam), (short)HIWORD(lParam), &applet, &i))
00233     {
00234         if (up)
00235         {
00236             if (panel->clkApplet == applet && panel->clkSP == i)
00237             {
00238                 applet->proc(applet->hWnd, CPL_DBLCLK, i, applet->info[i].lData);
00239             }
00240         }
00241         else
00242         {
00243             panel->clkApplet = applet;
00244             panel->clkSP = i;
00245         }
00246     }
00247     return 0;
00248 }
00249 
00250 static LRESULT WINAPI Control_WndProc(HWND hWnd, UINT wMsg,
00251                     WPARAM lParam1, LPARAM lParam2)
00252 {
00253     CPanel*    panel = (CPanel*)GetWindowLongPtrW(hWnd, 0);
00254 
00255     if (panel || wMsg == WM_CREATE)
00256     {
00257         switch (wMsg)
00258         {
00259             case WM_CREATE:
00260                 Control_WndProc_Create(hWnd, (CREATESTRUCTW*)lParam2);
00261                 return 0;
00262             case WM_DESTROY:
00263             {
00264                 CPlApplet *applet = panel->first;
00265                 while (applet)
00266                     applet = Control_UnloadApplet(applet);
00267                 
00268                 PostQuitMessage(0);
00269                 break;
00270             }
00271             case WM_PAINT:
00272                 return Control_WndProc_Paint(panel, lParam1);
00273             case WM_LBUTTONUP:
00274                 return Control_WndProc_LButton(panel, lParam2, TRUE);
00275             case WM_LBUTTONDOWN:
00276                 return Control_WndProc_LButton(panel, lParam2, FALSE);
00277             /* EPP       case WM_COMMAND: */
00278             /* EPP      return Control_WndProc_Command(mwi, lParam1, lParam2); */
00279         }
00280     }
00281 
00282    return DefWindowProcW(hWnd, wMsg, lParam1, lParam2);
00283 }
00284 
00285 static void Control_DoInterface(CPanel* panel, HWND hWnd, HINSTANCE hInst)
00286 {
00287     WNDCLASSW    wc;
00288     MSG    msg;
00289     const WCHAR* appName = L"ReactOS Control Panel";
00290     wc.style = CS_HREDRAW|CS_VREDRAW;
00291     wc.lpfnWndProc = Control_WndProc;
00292     wc.cbClsExtra = 0;
00293     wc.cbWndExtra = sizeof(CPlApplet*);
00294     wc.hInstance = hInst;
00295     wc.hIcon = 0;
00296     wc.hCursor = 0;
00297     wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
00298     wc.lpszMenuName = NULL;
00299     wc.lpszClassName = L"Shell_Control_WndClass";
00300 
00301     if (!RegisterClassW(&wc)) return;
00302 
00303     CreateWindowExW(0, wc.lpszClassName, appName,
00304             WS_OVERLAPPEDWINDOW | WS_VISIBLE,
00305             CW_USEDEFAULT, CW_USEDEFAULT,
00306             CW_USEDEFAULT, CW_USEDEFAULT,
00307             hWnd, NULL, hInst, panel);
00308     
00309     if (!panel->hWnd)
00310         return;
00311 
00312     if (!panel->first)
00313     {
00314         /* FIXME appName & message should be localized  */
00315         MessageBoxW(panel->hWnd, L"Cannot load any applets", appName, MB_OK);
00316         return;
00317     }
00318 
00319     while (GetMessageW(&msg, panel->hWnd, 0, 0))
00320     {
00321         TranslateMessage(&msg);
00322         DispatchMessageW(&msg);
00323     }
00324 }
00325 
00326 static void Control_DoWindow(CPanel *panel, HWND hWnd, HINSTANCE hInst)
00327 {
00328     HANDLE hFind;
00329     WIN32_FIND_DATAW wfd;
00330     WCHAR wszPath[MAX_PATH];
00331     WCHAR *Ptr = wszPath;
00332 
00333     Ptr += GetSystemDirectoryW(wszPath, MAX_PATH);
00334     *Ptr++ = '\\';
00335     wcscpy(Ptr, L"*.cpl");
00336 
00337     hFind = FindFirstFileW(wszPath, &wfd);
00338     if (hFind != INVALID_HANDLE_VALUE)
00339     {
00340         do
00341         {
00342             wcscpy(Ptr, wfd.cFileName);
00343             Control_LoadApplet(hWnd, wszPath, panel);
00344         } while (FindNextFileW(hFind, &wfd));
00345         FindClose(hFind);
00346     }
00347 
00348     Control_DoInterface(panel, hWnd, hInst);
00349 }
00350 
00351 static void Control_DoLaunch(CPanel *pPanel, HWND hWnd, LPCWSTR pwszCmd)
00352 {
00353     /* Make a pwszCmd copy so we can modify it */
00354     LPWSTR pwszCmdCopy = _wcsdup(pwszCmd);
00355     if (!pwszCmdCopy)
00356         return;
00357 
00358     LPWSTR pwszPath = pwszCmdCopy, pwszArg = NULL, pwszArg2 = NULL;
00359 
00360     /* Path can be quoted */
00361     if (pwszPath[0] == L'"')
00362     {
00363         ++pwszPath;
00364         pwszArg = wcschr(pwszPath, L'"');
00365         if (pwszArg)
00366             *(pwszArg++) = '\0';
00367     }
00368     else
00369         pwszArg = pwszCmdCopy;
00370 
00371     /* First argument starts after space or ','. Note: we ignore characters between '"' and ',' or ' '. */
00372     if (pwszArg)
00373         pwszArg = wcspbrk(pwszArg, L" ,");
00374     if (pwszArg)
00375     {
00376         /* NULL terminate path and find first character of arg */
00377         *(pwszArg++) = L'\0';
00378         if (pwszArg[0] == L'"')
00379         {
00380             ++pwszArg;
00381             pwszArg2 = wcschr(pwszArg, L'"');
00382             if (pwszArg2)
00383                 *(pwszArg2++) = L'\0';
00384         } else
00385             pwszArg2 = pwszArg;
00386 
00387         /* Second argument always starts with ','. Note: we ignore characters between '"' and ','. */
00388         if (pwszArg2)
00389             pwszArg2 = wcschr(pwszArg2, L',');
00390     }
00391 
00392     TRACE("Launch %ls, arg %ls, arg2 %ls\n", pwszPath, pwszArg, pwszArg2);
00393 
00394     /* Create a mutex to disallow running multiple instances */
00395     HANDLE hMutex = CreateMutexW(NULL, TRUE, PathFindFileNameW(pwszPath));
00396     if (!hMutex || GetLastError() == ERROR_ALREADY_EXISTS)
00397     {
00398         TRACE("Next instance disallowed\n");
00399         if (hMutex)
00400             CloseHandle(hMutex);
00401         return;
00402     }
00403 
00404     /* Load applet cpl */
00405     TRACE("Load applet %ls\n", pwszPath);
00406     Control_LoadApplet(hWnd, pwszPath, pPanel);
00407     if (pPanel->first)
00408     {
00409         /* First pPanel applet is the new one */
00410         CPlApplet *pApplet = pPanel->first;
00411         assert(pApplet && pApplet->next == NULL);
00412         TRACE("pApplet->count %d\n", pApplet->count);
00413 
00414         /* Note: if there is only one applet, first argument is ignored */
00415         INT i = 0;
00416         if (pApplet->count > 1 && pwszArg && pwszArg[0])
00417         {
00418             /* If arg begins with '@', number specifies applet index */
00419             if (pwszArg[0] == L'@')
00420                 i = _wtoi(pwszArg + 1);
00421             else
00422             {
00423                 /* Otherwise it's applet name */
00424                 for (i = 0; i < (INT)pApplet->count; ++i)
00425                     if (!wcscmp(pwszArg, pApplet->info[i].szName))
00426                         break;
00427             }
00428         }
00429 
00430         if (i >= 0 && i < (INT)pApplet->count && pApplet->info[i].dwSize)
00431         {
00432             /* Start the applet */
00433             TRACE("Starting applet %d\n", i);
00434             if (!pApplet->proc(pApplet->hWnd, CPL_DBLCLK, i, pApplet->info[i].lData))
00435                 pApplet->proc(pApplet->hWnd, CPL_STARTWPARMSA, i, (LPARAM)pwszArg);
00436         } else
00437             ERR("Applet not found: %ls\n", pwszArg ? pwszArg : L"NULL");
00438 
00439         Control_UnloadApplet(pApplet);
00440     }
00441     else
00442         ERR("Failed to load applet %ls\n", pwszPath);
00443 
00444     ReleaseMutex(hMutex);
00445     CloseHandle(hMutex);
00446     free(pwszCmdCopy);
00447 }
00448 
00449 /*************************************************************************
00450  * Control_RunDLLW            [SHELL32.@]
00451  *
00452  */
00453 EXTERN_C void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow)
00454 {
00455     CPanel Panel;
00456 
00457     TRACE("(%p, %p, %s, 0x%08x)\n",
00458       hWnd, hInst, debugstr_w(cmd), nCmdShow);
00459 
00460     memset(&Panel, 0, sizeof(Panel));
00461 
00462     if (!cmd || !*cmd)
00463     {
00464         TRACE("[shell32, Control_RunDLLW] Calling Control_DoWindow\n");
00465         Control_DoWindow(&Panel, hWnd, hInst);
00466     }
00467     else
00468     {
00469         TRACE("[shell32, Control_RunDLLW] Calling Control_DoLaunch\n");
00470         Control_DoLaunch(&Panel, hWnd, cmd);
00471     }
00472 }
00473 
00474 /*************************************************************************
00475  * Control_RunDLLA            [SHELL32.@]
00476  *
00477  */
00478 EXTERN_C void WINAPI Control_RunDLLA(HWND hWnd, HINSTANCE hInst, LPCSTR cmd, DWORD nCmdShow)
00479 {
00480     DWORD len = MultiByteToWideChar(CP_ACP, 0, cmd, -1, NULL, 0 );
00481     LPWSTR wszCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00482     
00483     if (wszCmd && MultiByteToWideChar(CP_ACP, 0, cmd, -1, wszCmd, len ))
00484     {
00485         Control_RunDLLW(hWnd, hInst, wszCmd, nCmdShow);
00486     }
00487     
00488     HeapFree(GetProcessHeap(), 0, wszCmd);
00489 }
00490 
00491 /*************************************************************************
00492  * Control_FillCache_RunDLLW            [SHELL32.@]
00493  *
00494  */
00495 EXTERN_C HRESULT WINAPI Control_FillCache_RunDLLW(HWND hWnd, HANDLE hModule, DWORD w, DWORD x)
00496 {
00497     FIXME("%p %p 0x%08x 0x%08x stub\n", hWnd, hModule, w, x);
00498     return 0;
00499 }
00500 
00501 /*************************************************************************
00502  * Control_FillCache_RunDLLA            [SHELL32.@]
00503  *
00504  */
00505 EXTERN_C HRESULT WINAPI Control_FillCache_RunDLLA(HWND hWnd, HANDLE hModule, DWORD w, DWORD x)
00506 {
00507     return Control_FillCache_RunDLLW(hWnd, hModule, w, x);
00508 }
00509 
00510 
00511 /*************************************************************************
00512  * RunDLL_CallEntry16                [SHELL32.122]
00513  * the name is probably wrong
00514  */
00515 EXTERN_C void WINAPI RunDLL_CallEntry16( DWORD proc, HWND hwnd, HINSTANCE inst,
00516                                 LPCSTR cmdline, INT cmdshow )
00517 {
00518 #if !defined(__CYGWIN__) && !defined (__MINGW32__) && !defined(_MSC_VER)
00519     WORD args[5];
00520     SEGPTR cmdline_seg;
00521 
00522     TRACE( "proc %x hwnd %p inst %p cmdline %s cmdshow %d\n",
00523            proc, hwnd, inst, debugstr_a(cmdline), cmdshow );
00524 
00525     cmdline_seg = MapLS( cmdline );
00526     args[4] = HWND_16(hwnd);
00527     args[3] = MapHModuleLS(inst);
00528     args[2] = SELECTOROF(cmdline_seg);
00529     args[1] = OFFSETOF(cmdline_seg);
00530     args[0] = cmdshow;
00531     WOWCallback16Ex( proc, WCB16_PASCAL, sizeof(args), args, NULL );
00532     UnMapLS( cmdline_seg );
00533 #else
00534     FIXME( "proc %lx hwnd %p inst %p cmdline %s cmdshow %d\n",
00535            proc, hwnd, inst, debugstr_a(cmdline), cmdshow );
00536 #endif
00537 }
00538 
00539 /*************************************************************************
00540  * CallCPLEntry16                [SHELL32.166]
00541  *
00542  * called by desk.cpl on "Advanced" with:
00543  * hMod("DeskCp16.Dll"), pFunc("CplApplet"), 0, 1, 0xc, 0
00544  *
00545  */
00546 LRESULT WINAPI CallCPLEntry16(HINSTANCE hMod, FARPROC pFunc, HWND dw3, UINT dw4, LPARAM dw5, LPARAM dw6)
00547 {
00548     FIXME("(%p, %p, %08x, %08x, %08x, %08x): stub.\n", hMod, pFunc, dw3, dw4, dw5, dw6);
00549     return 0x0deadbee;
00550 }

Generated on Thu May 24 2012 04:26:47 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.