From 7c67a5ec0d66da005cd844bdbfd2b675193b1d1d Mon Sep 17 00:00:00 2001 From: Ged Murphy Date: Thu, 28 Sep 2006 20:05:17 +0000 Subject: [PATCH] Initial development of a devmgmt.msc clone. Unusable at the moment though. svn path=/trunk/; revision=24289 --- reactos/base/applications/devmgmt/En.rc | 72 +++ reactos/base/applications/devmgmt/about.c | 62 ++ reactos/base/applications/devmgmt/devmgmt.c | 67 ++ .../base/applications/devmgmt/devmgmt.rbuild | 28 + reactos/base/applications/devmgmt/devmgmt.rc | 29 + .../base/applications/devmgmt/enumdevices.c | 356 +++++++++++ reactos/base/applications/devmgmt/mainwnd.c | 590 ++++++++++++++++++ .../base/applications/devmgmt/manifest.xml | 23 + reactos/base/applications/devmgmt/misc.c | 261 ++++++++ reactos/base/applications/devmgmt/precomp.h | 102 +++ .../applications/devmgmt/res/computer.ico | Bin 0 -> 7886 bytes .../base/applications/devmgmt/res/exit.bmp | Bin 0 -> 822 bytes .../base/applications/devmgmt/res/help.bmp | Bin 0 -> 822 bytes .../applications/devmgmt/res/properties.bmp | Bin 0 -> 822 bytes .../base/applications/devmgmt/res/refresh.bmp | Bin 0 -> 822 bytes .../base/applications/devmgmt/res/root.bmp | Bin 0 -> 822 bytes reactos/base/applications/devmgmt/resource.h | 63 ++ 17 files changed, 1653 insertions(+) create mode 100644 reactos/base/applications/devmgmt/En.rc create mode 100644 reactos/base/applications/devmgmt/about.c create mode 100644 reactos/base/applications/devmgmt/devmgmt.c create mode 100644 reactos/base/applications/devmgmt/devmgmt.rbuild create mode 100644 reactos/base/applications/devmgmt/devmgmt.rc create mode 100644 reactos/base/applications/devmgmt/enumdevices.c create mode 100644 reactos/base/applications/devmgmt/mainwnd.c create mode 100644 reactos/base/applications/devmgmt/manifest.xml create mode 100644 reactos/base/applications/devmgmt/misc.c create mode 100644 reactos/base/applications/devmgmt/precomp.h create mode 100644 reactos/base/applications/devmgmt/res/computer.ico create mode 100644 reactos/base/applications/devmgmt/res/exit.bmp create mode 100644 reactos/base/applications/devmgmt/res/help.bmp create mode 100644 reactos/base/applications/devmgmt/res/properties.bmp create mode 100644 reactos/base/applications/devmgmt/res/refresh.bmp create mode 100644 reactos/base/applications/devmgmt/res/root.bmp create mode 100644 reactos/base/applications/devmgmt/resource.h diff --git a/reactos/base/applications/devmgmt/En.rc b/reactos/base/applications/devmgmt/En.rc new file mode 100644 index 00000000000..aee0a8fd9d7 --- /dev/null +++ b/reactos/base/applications/devmgmt/En.rc @@ -0,0 +1,72 @@ +IDR_MAINMENU MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "E&xit", IDC_EXIT + END + POPUP "Action" + BEGIN + MENUITEM "Print", IDC_PRINT, GRAYED + MENUITEM SEPARATOR + MENUITEM "Properties...", IDC_PROP + MENUITEM SEPARATOR + MENUITEM "Help", IDC_PROGHELP, GRAYED + END + POPUP "Help" + BEGIN + MENUITEM "Help", IDC_PROGHELP + MENUITEM "About", IDC_ABOUT + END +END + +IDR_POPUP MENU +BEGIN + POPUP "popup" + BEGIN + MENUITEM "Properties...", IDC_PROP, GRAYED + MENUITEM SEPARATOR + MENUITEM "Help", IDC_PROGHELP + END +END + +IDD_ABOUTBOX DIALOGEX 22,16,190,182 +CAPTION "About Device Manager" +FONT 8,"Tahoma",0,0 +STYLE WS_BORDER | WS_DLGFRAME | WS_SYSMENU | DS_MODALFRAME +BEGIN + LTEXT "Device Manager v0.1\nCopyright (C) 2006\nby Ged Murphy (gedmurphy@gmail.com)", IDC_STATIC, 48, 7, 130, 26 + PUSHBUTTON "Close", IDOK, 75, 162, 44, 15 + ICON IDI_MAIN_ICON, IDC_STATIC, 10, 10, 7, 30 + EDITTEXT IDC_LICENSE_EDIT, 8, 44, 174, 107, WS_VISIBLE | WS_VSCROLL | WS_TABSTOP | ES_READONLY | ES_MULTILINE +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_LICENSE "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\r\n\r\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r\n\r\nYou should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA." +END + +STRINGTABLE DISCARDABLE +BEGIN + IDS_TOOLTIP_PROP "Properties" + IDS_TOOLTIP_REFRESH "Refresh" + IDS_TOOLTIP_HELP "Help" + IDS_TOOLTIP_EXIT "Exit" +END + +/* Hints */ +STRINGTABLE DISCARDABLE +BEGIN + IDS_HINT_BLANK " " + IDS_HINT_EXIT " Exits the program." + IDS_HINT_REFRESH " Refresh the service list." + IDS_HINT_PROP " Open property sheet for the current selection." + IDS_HINT_HELP " Display help window." + IDS_HINT_ABOUT " About ReactOS Device Manager." + + IDS_HINT_SYS_RESTORE " Restores this window to normal size." + IDS_HINT_SYS_MOVE " Moves this window." + IDS_HINT_SYS_SIZE " Resizes this window." + IDS_HINT_SYS_MINIMIZE " Collapses this window to an icon." + IDS_HINT_SYS_MAXIMIZE " Expands this window to fill this screen." + IDS_HINT_SYS_CLOSE " Closes this window." +END diff --git a/reactos/base/applications/devmgmt/about.c b/reactos/base/applications/devmgmt/about.c new file mode 100644 index 00000000000..b7766d2efb5 --- /dev/null +++ b/reactos/base/applications/devmgmt/about.c @@ -0,0 +1,62 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/devmgmt/about.c + * PURPOSE: About dialog box message handler + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +BOOL CALLBACK +AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND hLicenseEditWnd; + HICON hIcon = NULL; + TCHAR strLicense[700]; + + switch (message) + { + case WM_INITDIALOG: + + hIcon = LoadImage(hInstance, + MAKEINTRESOURCE(IDI_MAIN_ICON), + IMAGE_ICON, + 16, + 16, + 0); + + SendMessage(hDlg, + WM_SETICON, + ICON_SMALL, + (LPARAM)hIcon); + + hLicenseEditWnd = GetDlgItem(hDlg, + IDC_LICENSE_EDIT); + + LoadString(hInstance, + IDS_LICENSE, + strLicense, + sizeof(strLicense) / sizeof(TCHAR)); + + SetWindowText(hLicenseEditWnd, + strLicense); + + return TRUE; + + case WM_COMMAND: + + if ((LOWORD(wParam) == IDOK) || (LOWORD(wParam) == IDCANCEL)) + { + DestroyIcon(hIcon); + EndDialog(hDlg, + LOWORD(wParam)); + return TRUE; + } + + break; + } + + return FALSE; +} diff --git a/reactos/base/applications/devmgmt/devmgmt.c b/reactos/base/applications/devmgmt/devmgmt.c new file mode 100644 index 00000000000..afb233b6176 --- /dev/null +++ b/reactos/base/applications/devmgmt/devmgmt.c @@ -0,0 +1,67 @@ +/* + * PROJECT: ReactOS Device Managment + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/devmgmt/devmgmt.c + * PURPOSE: Program HQ + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +HINSTANCE hInstance; +HANDLE ProcessHeap; + +int WINAPI +WinMain(HINSTANCE hThisInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + LPTSTR lpAppName; + HWND hMainWnd; + MSG Msg; + int Ret = 1; + INITCOMMONCONTROLSEX icex; + + hInstance = hThisInstance; + ProcessHeap = GetProcessHeap(); + + icex.dwSize = sizeof(INITCOMMONCONTROLSEX); + icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES; + InitCommonControlsEx(&icex); + + if (!AllocAndLoadString(&lpAppName, + hInstance, + IDS_APPNAME)) + { + return 1; + } + + if (InitMainWindowImpl()) + { + hMainWnd = CreateMainWindow(lpAppName, + nCmdShow); + if (hMainWnd != NULL) + { + /* pump the message queue */ + while( GetMessage( &Msg, NULL, 0, 0 ) ) + { + TranslateMessage(&Msg); + DispatchMessage(&Msg); + + } + + Ret = 0; + } + + UninitMainWindowImpl(); + } + + LocalFree((HLOCAL)lpAppName); + + return Ret; +} + + + diff --git a/reactos/base/applications/devmgmt/devmgmt.rbuild b/reactos/base/applications/devmgmt/devmgmt.rbuild new file mode 100644 index 00000000000..8448678cf78 --- /dev/null +++ b/reactos/base/applications/devmgmt/devmgmt.rbuild @@ -0,0 +1,28 @@ + + + + . + + + + + 0x600 + 0x501 + ntdll + setupapi + gdi32 + kernel32 + user32 + comctl32 + advapi32 + + about.c + devmgmt.c + enumdevices.c + mainwnd.c + misc.c + + devmgmt.rc + precomp.h + + diff --git a/reactos/base/applications/devmgmt/devmgmt.rc b/reactos/base/applications/devmgmt/devmgmt.rc new file mode 100644 index 00000000000..79667eed93c --- /dev/null +++ b/reactos/base/applications/devmgmt/devmgmt.rc @@ -0,0 +1,29 @@ +#include +#include +#include "resource.h" + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Device Manager\0" +#define REACTOS_STR_INTERNAL_NAME "devmgmt\0" +#define REACTOS_STR_ORIGINAL_FILENAME "devmgmt.exe\0" +//#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +//1 24 DISCARDABLE "manifest.xml" + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APPNAME "ReactOS Device Manager" +END + +IDI_MAIN_ICON ICON "res/computer.ico" +IDB_ROOT_IMAGE BITMAP "res/root.bmp" + +/* main toolbar icons */ +IDB_PROP BITMAP DISCARDABLE "res/properties.bmp" +IDB_REFRESH BITMAP DISCARDABLE "res/refresh.bmp" +IDB_HELP BITMAP DISCARDABLE "res/help.bmp" +IDB_EXIT BITMAP DISCARDABLE "res/exit.bmp" + + +#include "En.rc" diff --git a/reactos/base/applications/devmgmt/enumdevices.c b/reactos/base/applications/devmgmt/enumdevices.c new file mode 100644 index 00000000000..e48d5a25480 --- /dev/null +++ b/reactos/base/applications/devmgmt/enumdevices.c @@ -0,0 +1,356 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/devmgmt/enumdevices.c + * PURPOSE: Enumerates all devices on the local machine + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +SP_CLASSIMAGELIST_DATA ImageListData; + + +static HTREEITEM +InsertIntoTreeView(HWND hTV, + HTREEITEM hRoot, + LPTSTR lpLabel, + INT DevImage) +{ + TV_ITEM tvi; + TV_INSERTSTRUCT tvins; + + ZeroMemory(&tvi, sizeof(tvi)); + ZeroMemory(&tvins, sizeof(tvins)); + + tvi.mask = TVIF_TEXT | TVIF_IMAGE; + tvi.pszText = lpLabel; + tvi.cchTextMax = lstrlen(lpLabel); + tvi.iImage = DevImage; + tvi.iSelectedImage = DevImage; + + tvins.item = tvi; + tvins.hInsertAfter = hRoot; + + return TreeView_InsertItem(hTV, &tvins); +} + + +static INT +EnumDeviceClasses(INT ClassIndex, + TCHAR *DeviceClassName, + TCHAR *DeviceClassDesc, + BOOL *DevicePresent, + INT *ClassImage) +{ + GUID ClassGuid; + HKEY KeyClass; + HDEVINFO hDevInfo; + TCHAR ClassName[MAX_CLASS_NAME_LEN]; + DWORD RequiredSize = MAX_CLASS_NAME_LEN; + UINT Ret; + + *DevicePresent = FALSE; + + Ret = CM_Enumerate_Classes(ClassIndex, + &ClassGuid, + 0); + if (Ret != CR_SUCCESS) + { + /* all classes enumerated */ + if(Ret == CR_NO_SUCH_VALUE) + return -1; + + if (Ret == CR_INVALID_DATA) + ; /*FIXME: what should we do here? */ + + /* handle other errors... */ + } + + if (SetupDiClassNameFromGuid(&ClassGuid, + ClassName, + RequiredSize, + &RequiredSize)) + { + lstrcpy(DeviceClassName, ClassName); + } + else + { + *DeviceClassName = _T('\0'); + } + + if (!SetupDiGetClassImageIndex(&ImageListData, + &ClassGuid, + ClassImage)) + { + /* set the blank icon */ + *ClassImage = 41; + } + + /* FIXME: why are we calling this here? */ + hDevInfo = SetupDiGetClassDevs(&ClassGuid, + 0, + NULL, + DIGCF_PRESENT); + if (hDevInfo == INVALID_HANDLE_VALUE) + return -2; + + KeyClass = SetupDiOpenClassRegKeyEx(&ClassGuid, + MAXIMUM_ALLOWED, + DIOCR_INSTALLER, + NULL, + 0); + if (KeyClass != INVALID_HANDLE_VALUE) + { + DWORD dwSize = MAX_CLASS_NAME_LEN; + + if (RegQueryValue(KeyClass, + NULL, + DeviceClassDesc, + &dwSize) != ERROR_SUCCESS) + { + *DeviceClassDesc = _T('\0'); + } + } + else + { + return -3; + } + + /* FIXME: Can we call this earlier, or see above? */ + SetupDiDestroyDeviceInfoList(hDevInfo); + + *DevicePresent = TRUE; + + RegCloseKey(KeyClass); + + return 0; +} + + +static INT +EnumDevices(INT index, + TCHAR* DeviceClassName, + TCHAR* DeviceName) +{ + HDEVINFO hDevInfo; + SP_DEVINFO_DATA DeviceInfoData; + DWORD RequiredSize = 0; + GUID *guids = NULL; + BOOL bRet; + + *DeviceName = _T('\0'); + + bRet = SetupDiClassGuidsFromName(DeviceClassName, + NULL, + RequiredSize, + &RequiredSize); + if (RequiredSize == 0) + return -2; + + if (!bRet) + { + guids = HeapAlloc(GetProcessHeap(), 0, RequiredSize); + if (guids == NULL) + return -1; + + bRet = SetupDiClassGuidsFromName(DeviceClassName, + guids, + RequiredSize, + &RequiredSize); + + if (!bRet || RequiredSize == 0) + { + /* incorrect class name */ + HeapFree(GetProcessHeap(), 0, guids); + return -3; + } + } + + /* get device info set for our device class */ + hDevInfo = SetupDiGetClassDevs(guids, + 0, + NULL, + DIGCF_PRESENT); + + HeapFree(GetProcessHeap(), 0, guids); + if(hDevInfo == INVALID_HANDLE_VALUE) + { + if(!bRet) + { + /* device info is unavailable */ + return -4; + } + } + + ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA)); + DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + bRet = SetupDiEnumDeviceInfo(hDevInfo, + index, + &DeviceInfoData); + + if (!bRet) + { + //no such device: + SetupDiDestroyDeviceInfoList(hDevInfo); + return -1; + } + + /* get the device's friendly name */ + if (!SetupDiGetDeviceRegistryProperty(hDevInfo, + &DeviceInfoData, + SPDRP_FRIENDLYNAME, + 0, + (BYTE*)DeviceName, + MAX_DEV_LEN, + NULL)) + { + /* if the friendly name fails, try the description instead */ + bRet = SetupDiGetDeviceRegistryProperty(hDevInfo, + &DeviceInfoData, + SPDRP_DEVICEDESC, + 0, + (BYTE*)DeviceName, + MAX_DEV_LEN, + NULL); + if (!bRet) + { + /* if the description fails, just give up! */ + SetupDiDestroyDeviceInfoList(hDevInfo); + return -5; + } + } + + return 0; +} + + +VOID +ListDevicesByType(PMAIN_WND_INFO Info, + HTREEITEM hRoot) +{ + HTREEITEM hDevItem; + TCHAR DevName[MAX_DEV_LEN]; + TCHAR DevDesc[MAX_DEV_LEN]; + BOOL DevExist = FALSE; + INT ClassRet; + INT index = 0; + INT DevImage; + + do + { + ClassRet = EnumDeviceClasses(index, + DevName, + DevDesc, + &DevExist, + &DevImage); + + if ((ClassRet != -1) && (DevExist)) + { + TCHAR DeviceName[MAX_DEV_LEN]; + INT Ret, DevIndex = 0; + + if (DevDesc[0] != _T('\0')) + { + hDevItem = InsertIntoTreeView(Info->hTreeView, + hRoot, + DevDesc, + DevImage); + } + else + { + hDevItem = InsertIntoTreeView(Info->hTreeView, + hRoot, + DevName, + DevImage); + } + + do + { + Ret = EnumDevices(DevIndex, + DevName, + DeviceName); + if (Ret == 0) + { + InsertIntoTreeView(Info->hTreeView, + hDevItem, + DeviceName, + DevImage); + } + + DevIndex++; + + } while (Ret != -1); + + if (!TreeView_GetChild(Info->hTreeView, + hDevItem)) + { + TreeView_DeleteItem(Info->hTreeView, + hDevItem); + } + else + { + TreeView_SortChildren(Info->hTreeView, + hDevItem, + 0); + } + } + + index++; + + } while (ClassRet != -1); + + TreeView_Expand(Info->hTreeView, + hRoot, + TVE_EXPAND); + + TreeView_SortChildren(Info->hTreeView, + hRoot, + 0); +} + + +HTREEITEM +InitTreeView(PMAIN_WND_INFO Info) +{ + HTREEITEM hRoot; + HBITMAP hComp; + TCHAR ComputerName[MAX_PATH]; + DWORD dwSize = MAX_PATH; + INT RootImage; + //COLORREF Mask = RGB(255, 0, 128); + + TreeView_DeleteAllItems(Info->hTreeView); + + /* get the device image List */ + ImageListData.cbSize = sizeof(ImageListData); + SetupDiGetClassImageList(&ImageListData); + + hComp = LoadBitmap(hInstance, + MAKEINTRESOURCE(IDB_ROOT_IMAGE)); + + ImageList_Add(ImageListData.ImageList, + hComp, + NULL); + + TreeView_SetImageList(Info->hTreeView, + &ImageListData.ImageList, + TVSIL_NORMAL); + + if (!GetComputerName(ComputerName, + &dwSize)) + { + ComputerName[0] = _T('\0'); + } + + RootImage = ImageList_GetImageCount(ImageListData.ImageList) - 1; + + hRoot = InsertIntoTreeView(Info->hTreeView, + NULL, + ComputerName, + RootImage); + + return hRoot; +} diff --git a/reactos/base/applications/devmgmt/mainwnd.c b/reactos/base/applications/devmgmt/mainwnd.c new file mode 100644 index 00000000000..a62540c95f4 --- /dev/null +++ b/reactos/base/applications/devmgmt/mainwnd.c @@ -0,0 +1,590 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/devmgmt/mainwnd.c + * PURPOSE: Main window message handler + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +static const TCHAR szMainWndClass[] = TEXT("DevMgmtWndClass"); + +/* Toolbar buttons */ +TBBUTTON Buttons [] = +{ /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */ + {TBICON_PROP, IDC_PROP, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* properties */ + {TBICON_REFRESH, IDC_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* refresh */ + + /* Note: First item for a seperator is its width in pixels */ + {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */ + + {TBICON_HELP, IDC_PROGHELP,TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* help */ + {TBICON_EXIT, IDC_EXIT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* exit */ + +}; + + +/* menu hints */ +static const MENU_HINT MainMenuHintTable[] = { + /* File Menu */ + {IDC_EXIT, IDS_HINT_EXIT}, + + /* Action Menu */ + {IDC_REFRESH, IDS_HINT_REFRESH}, + {IDC_PROP, IDS_HINT_PROP}, + + /* Help Menu */ + {IDC_PROGHELP, IDS_HINT_HELP}, + {IDC_ABOUT, IDS_HINT_ABOUT} +}; +/* system menu hints */ +static const MENU_HINT SystemMenuHintTable[] = { + {SC_RESTORE, IDS_HINT_SYS_RESTORE}, + {SC_MOVE, IDS_HINT_SYS_MOVE}, + {SC_SIZE, IDS_HINT_SYS_SIZE}, + {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE}, + {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE}, + {SC_CLOSE, IDS_HINT_SYS_CLOSE}, +}; + + +static BOOL +MainWndMenuHint(PMAIN_WND_INFO Info, + WORD CmdId, + const MENU_HINT *HintArray, + DWORD HintsCount, + UINT DefHintId) +{ + BOOL Found = FALSE; + const MENU_HINT *LastHint; + UINT HintId = DefHintId; + + LastHint = HintArray + HintsCount; + while (HintArray != LastHint) + { + if (HintArray->CmdId == CmdId) + { + HintId = HintArray->HintId; + Found = TRUE; + break; + } + HintArray++; + } + + StatusBarLoadString(Info->hStatus, + SB_SIMPLEID, + hInstance, + HintId); + + return Found; +} + + +static VOID +UpdateMainStatusBar(PMAIN_WND_INFO Info) +{ + if (Info->hStatus != NULL) + { + SendMessage(Info->hStatus, + SB_SIMPLE, + (WPARAM)Info->InMenuLoop, + 0); + } +} + + +static BOOL +CreateToolbar(PMAIN_WND_INFO Info) +{ + INT NumButtons = sizeof(Buttons) / sizeof(Buttons[0]); + + Info->hTool = CreateWindowEx(0, + TOOLBARCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS, + 0, 0, 0, 0, + Info->hMainWnd, + (HMENU)IDC_TOOLBAR, + hInstance, + NULL); + if(Info->hTool != NULL) + { + HIMAGELIST hImageList; + + SendMessage(Info->hTool, + TB_SETEXTENDEDSTYLE, + 0, + TBSTYLE_EX_HIDECLIPPEDBUTTONS); + + SendMessage(Info->hTool, + TB_BUTTONSTRUCTSIZE, + sizeof(Buttons[0]), + 0); + + hImageList = InitImageList(IDB_PROP, + IDB_EXIT, + 16, + 16); + if (hImageList == NULL) + return FALSE; + + ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool, + TB_SETIMAGELIST, + 0, + (LPARAM)hImageList)); + + SendMessage(Info->hTool, + TB_ADDBUTTONS, + NumButtons, + (LPARAM)Buttons); + + return TRUE; + } + + return FALSE; +} + + +static BOOL +CreateTreeView(PMAIN_WND_INFO Info) +{ + Info->hTreeView = CreateWindowEx(0, + WC_TREEVIEW, + NULL, + WS_CHILD | WS_VISIBLE | WS_BORDER | + TVS_HASLINES | TVS_HASBUTTONS | TVS_SHOWSELALWAYS, + 0, 0, 0, 0, + Info->hMainWnd, + (HMENU) IDC_TREEVIEW, + hInstance, + NULL); + if (Info->hTreeView == NULL) + { + DisplayString(_T("Could not create TreeView.")); + return FALSE; + } + + return TRUE; +} + +static BOOL +CreateStatusBar(PMAIN_WND_INFO Info) +{ + INT StatWidths[] = {110, -1}; /* widths of status bar */ + + Info->hStatus = CreateWindowEx(0, + STATUSCLASSNAME, + NULL, + WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP, + 0, 0, 0, 0, + Info->hMainWnd, + (HMENU)IDC_STATUSBAR, + hInstance, + NULL); + if(Info->hStatus == NULL) + return FALSE; + + + SendMessage(Info->hStatus, + SB_SETPARTS, + sizeof(StatWidths) / sizeof(INT), + (LPARAM)StatWidths); + + return TRUE; +} + + + +static VOID +InitMainWnd(PMAIN_WND_INFO Info) +{ + HTREEITEM hRoot; + + if (!CreateToolbar(Info)) + DisplayString(_T("error creating toolbar")); + + if (!CreateTreeView(Info)) + { + DisplayString(_T("error creating list view")); + return; + } + + if (!CreateStatusBar(Info)) + DisplayString(_T("error creating status bar")); + + /* Create Popup Menu */ + Info->hShortcutMenu = LoadMenu(hInstance, + MAKEINTRESOURCE(IDR_POPUP)); + Info->hShortcutMenu = GetSubMenu(Info->hShortcutMenu, + 0); + + hRoot = InitTreeView(Info); + if (hRoot) + ListDevicesByType(Info, hRoot); +} + + +static VOID +MainWndCommand(PMAIN_WND_INFO Info, + WORD CmdId, + HWND hControl) +{ + UNREFERENCED_PARAMETER(hControl); + + switch (CmdId) + { + case IDC_PROP: + { + // call builtin driver prop sheet + } + break; + + case IDC_REFRESH: + { + // refresh treeview + } + break; + + case IDC_PROGHELP: + DisplayString(_T("Help is not yet implemented\n")); + SetFocus(Info->hTreeView); + break; + + case IDC_EXIT: + PostMessage(Info->hMainWnd, + WM_CLOSE, + 0, + 0); + break; + + case IDC_ABOUT: + DialogBox(hInstance, + MAKEINTRESOURCE(IDD_ABOUTBOX), + Info->hMainWnd, + (DLGPROC)AboutDialogProc); + SetFocus(Info->hTreeView); + break; + + } +} + + +static VOID CALLBACK +MainWndResize(PMAIN_WND_INFO Info, + WORD cx, + WORD cy) +{ + RECT rcClient, rcTool, rcStatus; + int lvHeight, iToolHeight, iStatusHeight; + + /* Size toolbar and get height */ + SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0); + GetWindowRect(Info->hTool, &rcTool); + iToolHeight = rcTool.bottom - rcTool.top; + + /* Size status bar and get height */ + SendMessage(Info->hStatus, WM_SIZE, 0, 0); + GetWindowRect(Info->hStatus, &rcStatus); + iStatusHeight = rcStatus.bottom - rcStatus.top; + + /* Calculate remaining height and size list view */ + GetClientRect(Info->hMainWnd, &rcClient); + lvHeight = rcClient.bottom - iToolHeight - iStatusHeight; + SetWindowPos(Info->hTreeView, + NULL, + 0, + iToolHeight, + rcClient.right, + lvHeight, + SWP_NOZORDER); +} + + +static LRESULT CALLBACK +MainWndProc(HWND hwnd, + UINT msg, + WPARAM wParam, + LPARAM lParam) +{ + PMAIN_WND_INFO Info; + LRESULT Ret = 0; + + /* Get the window context */ + Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd, + GWLP_USERDATA); + if (Info == NULL && msg != WM_CREATE) + { + goto HandleDefaultMessage; + } + + switch(msg) + { + case WM_CREATE: + { + Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams); + + /* Initialize the main window context */ + Info->hMainWnd = hwnd; + + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + (LONG_PTR)Info); + + InitMainWnd(Info); + + /* Show the window */ + ShowWindow(hwnd, + Info->nCmdShow); + + } + break; + + case WM_SIZE: + { + MainWndResize(Info, + LOWORD(lParam), + HIWORD(lParam)); + } + break; + + case WM_NOTIFY: + { + LPNMHDR pnmhdr = (LPNMHDR)lParam; + + switch (pnmhdr->code) + { + case NM_DBLCLK: + { + POINT pt; + RECT rect; + + GetCursorPos(&pt); + GetWindowRect(Info->hTreeView, &rect); + + if (PtInRect(&rect, pt)) + { + SendMessage(hwnd, + WM_COMMAND, + //ID_PROP, + MAKEWPARAM((WORD)IDC_PROP, (WORD)0), + 0); + } + + //OpenPropSheet(Info); + } + break; + + case TTN_GETDISPINFO: + { + LPTOOLTIPTEXT lpttt; + UINT idButton; + + lpttt = (LPTOOLTIPTEXT)lParam; + + /* Specify the resource identifier of the descriptive + * text for the given button. */ + idButton = (UINT)lpttt->hdr.idFrom; + switch (idButton) + { + case IDC_PROP: + lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP); + break; + + case IDC_REFRESH: + lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH); + break; + + case IDC_PROGHELP: + lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_HELP); + break; + + case IDC_EXIT: + lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT); + break; + + } + } + break; + } + } + break; + + case WM_CONTEXTMENU: + { + POINT pt; + RECT lvRect; + + INT xPos = GET_X_LPARAM(lParam); + INT yPos = GET_Y_LPARAM(lParam); + + GetCursorPos(&pt); + + /* display popup when cursor is in the list view */ + GetWindowRect(Info->hTreeView, &lvRect); + if (PtInRect(&lvRect, pt)) + { + TrackPopupMenuEx(Info->hShortcutMenu, + TPM_RIGHTBUTTON, + xPos, + yPos, + Info->hMainWnd, + NULL); + } + } + break; + + case WM_COMMAND: + { + MainWndCommand(Info, + LOWORD(wParam), + (HWND)lParam); + goto HandleDefaultMessage; + } + + case WM_MENUSELECT: + { + if (Info->hStatus != NULL) + { + if (!MainWndMenuHint(Info, + LOWORD(wParam), + MainMenuHintTable, + sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]), + IDS_HINT_BLANK)) + { + MainWndMenuHint(Info, + LOWORD(wParam), + SystemMenuHintTable, + sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]), + IDS_HINT_BLANK); + } + } + } + break; + + case WM_ENTERMENULOOP: + { + Info->InMenuLoop = TRUE; + UpdateMainStatusBar(Info); + break; + } + + case WM_EXITMENULOOP: + { + Info->InMenuLoop = FALSE; + UpdateMainStatusBar(Info); + break; + } + + case WM_CLOSE: + { + DestroyMenu(Info->hShortcutMenu); + DestroyWindow(hwnd); + } + break; + + case WM_DESTROY: + { + //DestroyMainWnd(Info); + + HeapFree(ProcessHeap, + 0, + Info); + SetWindowLongPtr(hwnd, + GWLP_USERDATA, + 0); + + /* Break the message queue loop */ + PostQuitMessage(0); + } + break; + + default: + { +HandleDefaultMessage: + + Ret = DefWindowProc(hwnd, + msg, + wParam, + lParam); + } + break; + } + return Ret; +} + + + +HWND +CreateMainWindow(LPCTSTR lpCaption, + int nCmdShow) +{ + PMAIN_WND_INFO Info; + HWND hMainWnd = NULL; + + Info = HeapAlloc(ProcessHeap, + HEAP_ZERO_MEMORY, + sizeof(MAIN_WND_INFO)); + + if (Info != NULL) + { + Info->nCmdShow = nCmdShow; + + hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE, + szMainWndClass, + lpCaption, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CW_USEDEFAULT, + CW_USEDEFAULT, + 650, + 450, + NULL, + NULL, + hInstance, + Info); + if (hMainWnd == NULL) + { + GetError(); + HeapFree(ProcessHeap, + 0, + Info); + } + } + + return hMainWnd; +} + +BOOL +InitMainWindowImpl(VOID) +{ + WNDCLASSEX wc = {0}; + + wc.cbSize = sizeof(WNDCLASSEX); + wc.lpfnWndProc = MainWndProc; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, + MAKEINTRESOURCE(IDI_MAIN_ICON)); + wc.hCursor = LoadCursor(NULL, + IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); + wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU); + wc.lpszClassName = szMainWndClass; + wc.hIconSm = (HICON)LoadImage(hInstance, + MAKEINTRESOURCE(IDI_MAIN_ICON), + IMAGE_ICON, + 16, + 16, + LR_SHARED); + + return RegisterClassEx(&wc) != (ATOM)0; +} + + +VOID +UninitMainWindowImpl(VOID) +{ + UnregisterClass(szMainWndClass, + hInstance); +} + diff --git a/reactos/base/applications/devmgmt/manifest.xml b/reactos/base/applications/devmgmt/manifest.xml new file mode 100644 index 00000000000..4df22534fca --- /dev/null +++ b/reactos/base/applications/devmgmt/manifest.xml @@ -0,0 +1,23 @@ + + + +ReactOS Service Manager + + + + + + diff --git a/reactos/base/applications/devmgmt/misc.c b/reactos/base/applications/devmgmt/misc.c new file mode 100644 index 00000000000..3a24fe720bd --- /dev/null +++ b/reactos/base/applications/devmgmt/misc.c @@ -0,0 +1,261 @@ +/* + * PROJECT: ReactOS Services + * LICENSE: GPL - See COPYING in the top level directory + * FILE: base/system/devmgmt/misc.c + * PURPOSE: miscallanous functions + * COPYRIGHT: Copyright 2006 Ged Murphy + * + */ + +#include "precomp.h" + +static INT +LengthOfStrResource(IN HINSTANCE hInst, + IN UINT uID) +{ + HRSRC hrSrc; + HGLOBAL hRes; + LPWSTR lpName, lpStr; + + if (hInst == NULL) + { + return -1; + } + + /* There are always blocks of 16 strings */ + lpName = (LPWSTR)MAKEINTRESOURCE((uID >> 4) + 1); + + /* Find the string table block */ + if ((hrSrc = FindResourceW(hInst, lpName, (LPWSTR)RT_STRING)) && + (hRes = LoadResource(hInst, hrSrc)) && + (lpStr = LockResource(hRes))) + { + UINT x; + + /* Find the string we're looking for */ + uID &= 0xF; /* position in the block, same as % 16 */ + for (x = 0; x < uID; x++) + { + lpStr += (*lpStr) + 1; + } + + /* Found the string */ + return (int)(*lpStr); + } + return -1; +} + +INT +AllocAndLoadString(OUT LPTSTR *lpTarget, + IN HINSTANCE hInst, + IN UINT uID) +{ + INT ln; + + ln = LengthOfStrResource(hInst, + uID); + if (ln++ > 0) + { + (*lpTarget) = (LPTSTR)LocalAlloc(LMEM_FIXED, + ln * sizeof(TCHAR)); + if ((*lpTarget) != NULL) + { + INT Ret; + if (!(Ret = LoadString(hInst, uID, *lpTarget, ln))) + { + LocalFree((HLOCAL)(*lpTarget)); + } + return Ret; + } + } + return 0; +} + +DWORD +LoadAndFormatString(IN HINSTANCE hInstance, + IN UINT uID, + OUT LPTSTR *lpTarget, + ...) +{ + DWORD Ret = 0; + LPTSTR lpFormat; + va_list lArgs; + + if (AllocAndLoadString(&lpFormat, + hInstance, + uID) > 0) + { + va_start(lArgs, lpTarget); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, + 0, + 0, + (LPTSTR)lpTarget, + 0, + &lArgs); + va_end(lArgs); + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} + +BOOL +StatusBarLoadAndFormatString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID, + ...) +{ + BOOL Ret = FALSE; + LPTSTR lpFormat, lpStr; + va_list lArgs; + + if (AllocAndLoadString(&lpFormat, + hInstance, + uID) > 0) + { + va_start(lArgs, uID); + /* let's use FormatMessage to format it because it has the ability to allocate + memory automatically */ + Ret = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, + lpFormat, + 0, + 0, + (LPTSTR)&lpStr, + 0, + &lArgs); + va_end(lArgs); + + if (lpStr != NULL) + { + Ret = (BOOL)SendMessage(hStatusBar, + SB_SETTEXT, + (WPARAM)PartId, + (LPARAM)lpStr); + LocalFree((HLOCAL)lpStr); + } + + LocalFree((HLOCAL)lpFormat); + } + + return Ret; +} + +BOOL +StatusBarLoadString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID) +{ + BOOL Ret = FALSE; + LPTSTR lpStr; + + if (AllocAndLoadString(&lpStr, + hInstance, + uID) > 0) + { + Ret = (BOOL)SendMessage(hStatusBar, + SB_SETTEXT, + (WPARAM)PartId, + (LPARAM)lpStr); + LocalFree((HLOCAL)lpStr); + } + + return Ret; +} + + +INT +GetTextFromEdit(OUT LPTSTR lpString, + IN HWND hDlg, + IN UINT Res) +{ + INT len = GetWindowTextLength(GetDlgItem(hDlg, Res)); + if(len > 0) + { + GetDlgItemText(hDlg, + Res, + lpString, + len + 1); + } + else + lpString = NULL; + + return len; +} + + +HIMAGELIST +InitImageList(UINT StartResource, + UINT EndResource, + UINT Width, + UINT Height) +{ + HBITMAP hBitmap; + HIMAGELIST hImageList; + UINT i; + INT Ret; + + /* Create the toolbar icon image list */ + hImageList = ImageList_Create(Width, + Height, + ILC_MASK | ILC_COLOR24, + EndResource - StartResource, + 0); + if (hImageList == NULL) + return NULL; + + /* Add all icons to the image list */ + for (i = StartResource; i <= EndResource; i++) + { + hBitmap = LoadImage(hInstance, + MAKEINTRESOURCE(i), + IMAGE_BITMAP, + Width, + Height, + LR_LOADTRANSPARENT); + if (hBitmap == NULL) + return NULL; + + Ret = ImageList_AddMasked(hImageList, + hBitmap, + RGB(255, 0, 128)); + if (Ret == -1) + return NULL; + + DeleteObject(hBitmap); + } + + return hImageList; +} + + +VOID GetError(VOID) +{ + LPVOID lpMsgBuf; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL ); + + MessageBox(NULL, lpMsgBuf, _T("Error!"), MB_OK | MB_ICONERROR); + + LocalFree(lpMsgBuf); +} + + +VOID DisplayString(PTCHAR Msg) +{ + MessageBox(NULL, Msg, _T("Note!"), MB_ICONEXCLAMATION|MB_OK); +} + diff --git a/reactos/base/applications/devmgmt/precomp.h b/reactos/base/applications/devmgmt/precomp.h new file mode 100644 index 00000000000..52c6c82c602 --- /dev/null +++ b/reactos/base/applications/devmgmt/precomp.h @@ -0,0 +1,102 @@ +#ifndef __DEVMGMT_PRECOMP_H +#define __DEVMGMT_PRECOMP_H + +//#define WIN32_LEAN_AND_MEAN +#include +#include /* GET_X/Y_LPARAM */ +#include +#include +#include +#include +#include +#include "resource.h" + +#ifdef _MSC_VER +#pragma warning(disable : 4100) +#endif + +#ifndef SB_SIMPLEID +#define SB_SIMPLEID 0xFF +#endif + +#define NO_ITEM_SELECTED -1 +#define MAX_KEY_LENGTH 256 +#define MAX_DEV_LEN 1000 + + +typedef struct _MAIN_WND_INFO +{ + HWND hMainWnd; + HWND hTreeView; + HWND hStatus; + HWND hTool; + HWND hProgDlg; + HMENU hShortcutMenu; + int nCmdShow; + + /* status flags */ + BOOL InMenuLoop : 1; + +} MAIN_WND_INFO, *PMAIN_WND_INFO; + + +BOOL CALLBACK AboutDialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); + + +/* servman.c */ +extern HINSTANCE hInstance; +extern HANDLE ProcessHeap; + +/* mainwnd.c */ +typedef struct _MENU_HINT +{ + WORD CmdId; + UINT HintId; +} MENU_HINT, *PMENU_HINT; + +BOOL InitMainWindowImpl(VOID); +VOID UninitMainWindowImpl(VOID); +HWND CreateMainWindow(LPCTSTR lpCaption, int nCmdShow); + + +/* enumdevices.c */ +HTREEITEM InitTreeView(PMAIN_WND_INFO Info); +VOID ListDevicesByType(PMAIN_WND_INFO Info, HTREEITEM hRoot); + + +/* misc.c */ +INT AllocAndLoadString(OUT LPTSTR *lpTarget, + IN HINSTANCE hInst, + IN UINT uID); + +DWORD LoadAndFormatString(IN HINSTANCE hInstance, + IN UINT uID, + OUT LPTSTR *lpTarget, + ...); + +BOOL StatusBarLoadAndFormatString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID, + ...); + +BOOL StatusBarLoadString(IN HWND hStatusBar, + IN INT PartId, + IN HINSTANCE hInstance, + IN UINT uID); + +INT GetTextFromEdit(OUT LPTSTR lpString, + IN HWND hDlg, + IN UINT Res); + +VOID GetError(VOID); + +VOID DisplayString(PTCHAR); + +HIMAGELIST InitImageList(UINT NumButtons, + UINT StartResource, + UINT Width, + UINT Height); + + +#endif /* __DEVMGMT_PRECOMP_H */ diff --git a/reactos/base/applications/devmgmt/res/computer.ico b/reactos/base/applications/devmgmt/res/computer.ico new file mode 100644 index 0000000000000000000000000000000000000000..deb7f520f20ffe7a1d9e8b5e5ca499021bc72119 GIT binary patch literal 7886 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 Z`YZT)z9l*4_49pM6@5*A8z{|){sTa=A_xEg literal 0 HcmV?d00001 diff --git a/reactos/base/applications/devmgmt/res/exit.bmp b/reactos/base/applications/devmgmt/res/exit.bmp new file mode 100644 index 0000000000000000000000000000000000000000..97381f1f6f774edb3d5d4524d0da52d58e62b7d9 GIT binary patch literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;U*m;fhyVja1H*qa6FuS)ME%iYNB8XATT@dB z)F|o@!5Gj0K}?bT$OtG4QNMTJ-bITRZQs8Az`=tMU2-lF3=ZiaVaB->SxcMJ!{siDO09&c6I_aR#cWrN{Sg8 z8$uAW`hb8tKrKM^GiJ<~G-*;xYfD{SU4B70l`AbReL%&Pm6b(BMcLWeF)=aW;o*M%{=&k7nCACR>@O%T%+Ag6 f4+`+{^>uV|G&V8T)zec^QQ_w1#8eLqSRxSs(y#Wa literal 0 HcmV?d00001 diff --git a/reactos/base/applications/devmgmt/res/help.bmp b/reactos/base/applications/devmgmt/res/help.bmp new file mode 100644 index 0000000000000000000000000000000000000000..4c958c2e9a056ae052583c47732d8e960dc603e2 GIT binary patch literal 822 zcmZ?rHDhJ~12Z700mK4O%*Y@C7H0s;3voj*M1X;zf#E+K?c2R$Sy$QgZ13)1Z6KPN z5~99Z9$H8DbedV&Seisfa2Pp+JJdhOJfwxn(C z$veB#clBjm+%)^y^)oYae7XWPzkYZ-CC;KRSZhkO@ysNv`I%0i-@X7k>B80p8|tGr zHOFmfP1rl7^vCB9-9g$A^^;@Fy8Klqgy~L=HJO!cy|p{{&+niA{{1^Rw`omP$l98) z?Y%kQKfmt|(t@~WO;c*SmqK@dI!H^53DA~93p;^Ue17v{X_5D`V&B6H+a6vzHa*K5 z7@>!kPPnjhB~U#O&Cl~*kncMs+Gs^pBvAd|Kff2|y3NmWzIAN-v6WMSib3HSW%BXW z)1?&=K=m6sa{m4O`|{qkZ=c=+)!#X_cSeH6=FV(jfcHllL(&E?C9G~t{q*|zvWmz# zneO+_9s2(H!^c<8F6>wiv}l1;>AV~rk(ZKYuqBj1+i^o8R0sS&9!5WBw zjElQgeR%m~MO^|=0X#hbbphEx?LZq3F6_O1a_^V-uYm~2IJl^{Kf(x@V2~BV6CNbG SfguJAWFP`EARdG(05SmSGt!Cx literal 0 HcmV?d00001 diff --git a/reactos/base/applications/devmgmt/res/properties.bmp b/reactos/base/applications/devmgmt/res/properties.bmp new file mode 100644 index 0000000000000000000000000000000000000000..15e080ec9234c1662b775c1133b2f78bbb7c493c GIT binary patch literal 822 zcmb7?v2KGf6h$3%%o26#C*%wA0ol8kl_3%lJ8LqqBX*doC=EqoL5i4xWawleCI)7p zw11G^`ZWj%Crys9Wtq#peh<%|XAev;!#u^9{EZQN68jAAAICIkgRvDm-TS<5w(A?% zyzR&t+S3g{*4KXu+P3`?d<)95^nE{yBKQsUX__7cM?n~dwr#tv>v`T#-!u&p;7<`* zmKla&nxxHIaeMO%n30l;zf;uMkuc``10_P%rv#4X2^l=;`f>Pj2;D<={I4UB#6a--h XAVR7~$F9@ehpqRH^}ht+9{24BrGpYR literal 0 HcmV?d00001 diff --git a/reactos/base/applications/devmgmt/res/refresh.bmp b/reactos/base/applications/devmgmt/res/refresh.bmp new file mode 100644 index 0000000000000000000000000000000000000000..e7c12bbd3025cd7bbad4290c926fada655fee3aa GIT binary patch literal 822 zcmZ8fSx*yD6t3~n7vqyZ!5^Rnv1QS?Z(vL`QR7P4rUe@m5hO^^unGlf3zHbj&C?OEk3;ycbWZ;pxd^0wBV5IT3T7FzroH_L1jJ{nqWgq7O5GV@| z8oH|?u+jabEYH|@&4)JzjjuxH*MZ>{M~{ravaLgJd5WqibL{y|s=7d5cRAuVtbO5D zW^55oyT}aqsV1MQA)t8y6bEBL6uji{&uDN~-}5K_?f3U^a>47TJ9IS#cyR`l@RBUG zRIGh;PTyXR@SrojzMNW%q>|BPzg<^*iLSdkY1Tv4tW;3)lg8SMMClQ{Gz;OCMHzrk z%(1KUoU-r`U{D^s(=$z$ALB;eSi9tK%q_e`m`cXd$yjPFI%j$ZcjDySJOu*I>)}{N zDG{P1=z+EyCIJ(wiZV0}x3=SV#7>WQM+Sa%?G+$EQ*~DRIDf-x^0(_@R0__;y4)U~ z2!qqqU;jjRrq@?~Er;NM1SUdNWucJ7L@sp~dH=+eo#81KvKJJ_=Uj=P6K;>d#Hd6{ zbEt|uH6|uyxu*VB*2yxXYWm3)ORFRinocE_pg9=%A8$}RoK%#4=#`UYB4|jIiN>1m z&RYjzh@b=}=p&j}gC9vO8})ZgSO{rOfNonD?+Y`7F^?f0m{<>ce=L1o@lU{EHBWC0 zSDu0~@lwY%@8N~OE&*-FR|mOhCueotmX>>jG}lJ;0nCEG2ASxRodosZd&40UsnHDi5)>f>uieOX*|o%ze{VV&lSuhyhs` zH8Dmv8kZVHO-#$PR?&daa-sBLDbn`d@d!-LoSd2OJ2T%oGt~{{d&{;*IrsxG_wCL- zW&5}H%Xaad#f~S)EeeF?2<8Z4Ifmmg7739=G3fDPK@NHe_97(7B4#{(iIZf0E;>CE zodt`=Vl#8mui;2E_B|Y#2~SSVM!$WZpa1b|erk4l{$~smpHCwFXdtthP3KbKsfdzX zO=Z(7$;5gl1;NM96R+RCc|Y-PA+gB$1t)fAX#vSBC$XZ4eFJ@=08fxp;N7z5b@w|4 zIdABWjF1cSOdoRPXlaA0LQt9xf5|JqX)*hEIYv_pbR$mFi!>Lfe-c{q_vY$SY&L=f zoTu6*RUwz=(r0xQR^!oY^_AC8Rki32UN#->G#t8Ws<={D*;ZFwSXU71%hOVUYAoZS znYAucjo98aWN8Z6PKO-l0^LnwXFV+McC}h-t5ju476_2RM2^vvr5onzmxAkIPkYeP zz;_s=4r8e6OrWh^INxydL=8?!VjCEtD~+V9_P8R~9?tYGI! z+-$yPJ`Q{adqF>#+tW|eip8jV!aK(Xu0HqQ8fUv6i}pvz=D&OzUu*=3rdD`?0J%st zcw(B%bm%LGo%R<&?})d14BJPU>*K8Bx!=uSY6eJMTY<*~vPRWGp3rQ{V%ComSLmj7 z1UVjH$FRpf#`fOpu{~s*wgzKqH6e4jq!uaFf-IYlFI_O`+w{k*rfREM*IIi7yv0-n zCwCZht#t;PNewa#kZGwXV?6okgPLC7QsST!N-HUgG`URI;@WzmlvE1I)rIJch!E9O zNa1)E6Na!Dejqdr