[DEVMGR]
authorGed Murphy <gedmurphy@reactos.org>
Tue, 16 Jun 2015 21:13:28 +0000 (21:13 +0000)
committerGed Murphy <gedmurphy@reactos.org>
Tue, 16 Jun 2015 21:13:28 +0000 (21:13 +0000)
- Move the devmgmt code to devmgr where it belongs and start to rewrite it (devmgmt_new wasn't a good design). It's not part of devmgr yet, I'll merge it and add it to the build when it's more complete.
- Add support for caching devices to speed up switching device views
- start to add dynamic context support so we can enable/disable, update and uninstall devices depending on its state.
- WIP

svn path=/trunk/; revision=68165

14 files changed:
reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/DeviceView.h [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/MainWindow.h [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/Node.cpp [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/Node.h [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/Resource.h [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/devmgmt.h [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/res/computer.ico [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/res/root.bmp [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/rsrc.rc [new file with mode: 0644]
reactos/dll/win32/devmgr/devmgmt/stdafx.h [new file with mode: 0644]

diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp b/reactos/dll/win32/devmgr/devmgmt/DeviceView.cpp
new file mode 100644 (file)
index 0000000..d844cc9
--- /dev/null
@@ -0,0 +1,873 @@
+/*
+* PROJECT:     ReactOS Device Manager
+* LICENSE:     GPL - See COPYING in the top level directory
+* FILE:        dll/win32/devmgr/devmgr/DeviceView.cpp
+* PURPOSE:     Implements the tree view which contains the devices
+* COPYRIGHT:   Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "DeviceView.h"
+
+
+/* DATA *********************************************/
+
+#define CLASS_NAME_LEN      256
+#define CLASS_DESC_LEN      256
+
+INT_PTR
+WINAPI
+DevicePropertiesExW(
+    IN HWND hWndParent OPTIONAL,
+    IN LPCWSTR lpMachineName OPTIONAL,
+    IN LPCWSTR lpDeviceID OPTIONAL,
+    IN DWORD dwFlags OPTIONAL,
+    IN BOOL bShowDevMgr
+);
+
+typedef INT_PTR(WINAPI *pDevicePropertiesExW)(HWND,LPCWSTR,LPCWSTR,DWORD,BOOL);
+
+struct RefreshThreadData
+{
+    CDeviceView *This;
+    BOOL ScanForChanges;
+    BOOL UpdateView;
+};
+
+
+/* PUBLIC METHODS *************************************/
+
+CDeviceView::CDeviceView(
+    HWND hMainWnd
+    ) :
+    m_hMainWnd(hMainWnd),
+    m_hTreeView(NULL),
+    m_hPropertyDialog(NULL),
+    m_hShortcutMenu(NULL),
+    m_ViewType(DevicesByType),
+    m_ShowHidden(FALSE),
+    m_RootClassImage(-1),
+    m_RootDevInst(0)
+{
+    ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
+}
+
+CDeviceView::~CDeviceView(void)
+{
+}
+
+bool
+CDeviceView::Initialize()
+{
+    // Get the device image list
+    m_ImageListData.cbSize = sizeof(SP_CLASSIMAGELIST_DATA);
+    BOOL bSuccess = SetupDiGetClassImageList(&m_ImageListData);
+    if (bSuccess == FALSE) return false;
+
+    // Create the main treeview
+    m_hTreeView = CreateWindowExW(WS_EX_CLIENTEDGE,
+                                  WC_TREEVIEW,
+                                  NULL,
+                                  WS_CHILD | WS_VISIBLE | WS_BORDER | TVS_HASLINES |
+                                   TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_LINESATROOT,
+                                  0, 0, 0, 0,
+                                  m_hMainWnd,
+                                  (HMENU)IDC_TREEVIEW,
+                                  g_hInstance,
+                                  NULL);
+    if (m_hTreeView)
+    {
+        // Set the image list against the treeview
+        (void)TreeView_SetImageList(m_hTreeView,
+                                    m_ImageListData.ImageList,
+                                    TVSIL_NORMAL);
+
+        // Give the treeview arrows instead of +/- boxes (on Win7)
+        SetWindowTheme(m_hTreeView, L"explorer", NULL);
+    }
+
+    return !!(m_hTreeView);
+}
+
+bool
+CDeviceView::Uninitialize()
+{
+    EmptyDeviceView();
+
+    if (m_ImageListData.ImageList != NULL)
+    {
+        SetupDiDestroyClassImageList(&m_ImageListData);
+        ZeroMemory(&m_ImageListData, sizeof(SP_CLASSIMAGELIST_DATA));
+    }
+
+    return true;
+}
+
+void
+CDeviceView::Size(
+    _In_ int x,
+    _In_ int y,
+    _In_ int cx,
+    _In_ int cy
+    )
+{
+    // Resize the treeview
+    SetWindowPos(m_hTreeView,
+                 NULL,
+                 x,
+                 y,
+                 cx,
+                 cy,
+                 SWP_NOZORDER);
+}
+
+void
+CDeviceView::Refresh(_In_ ViewType Type,
+                     _In_ bool ScanForChanges,
+                     _In_ bool UpdateView)
+{
+    // Enum devices on a seperate thread to keep the gui responsive
+
+    m_ViewType = Type;
+
+    RefreshThreadData *ThreadData;
+    ThreadData = new RefreshThreadData();
+    ThreadData->This = this;
+    ThreadData->ScanForChanges = ScanForChanges;
+    ThreadData->UpdateView = UpdateView;
+
+    HANDLE hThread;
+    hThread = (HANDLE)_beginthreadex(NULL,
+                                     0,
+                                     &RefreshThread,
+                                     ThreadData,
+                                     0,
+                                     NULL);
+
+    if (hThread) CloseHandle(hThread);
+}
+
+void
+CDeviceView::DisplayPropertySheet()
+{
+    //
+    // In ReactOS we can link to DevicePropertiesEx but
+    // not in windows as it's not part of the SDK 
+
+#ifndef __REACTOS__
+    HMODULE hModule = LoadLibraryW(L"devmgr.dll");
+    if (hModule == NULL) return;
+
+    pDevicePropertiesExW DevicePropertiesExW;
+    DevicePropertiesExW = (pDevicePropertiesExW)GetProcAddress(hModule,
+                                                               "DevicePropertiesExW");
+    if (DevicePropertiesExW == NULL)
+    {
+        FreeLibrary(hModule);
+        return;
+    }
+#endif
+
+    CNode *Node = GetSelectedNode();
+    if (Node && Node->HasProperties())
+    {
+        DevicePropertiesExW(m_hTreeView,
+                            NULL,
+                            Node->GetDeviceId(),
+                            1,//DPF_EXTENDED,
+                            FALSE);
+    }
+
+#ifndef __REACTOS__
+    FreeLibrary(hModule);
+#endif
+}
+
+void
+CDeviceView::SetFocus()
+{
+}
+
+bool
+CDeviceView::HasProperties(_In_ LPTV_ITEMW TvItem)
+{
+    CNode *Node = GetNode(TvItem);
+    if (Node)
+    {
+        return Node->HasProperties();
+    }
+    return false;
+}
+
+bool
+CDeviceView::IsDisabled(_In_ LPTV_ITEMW TvItem)
+{
+    CNode *Node = GetNode(TvItem);
+    if (Node)
+    {
+        return Node->IsDisabled();
+    }
+    return false;
+}
+
+bool
+CDeviceView::CanDisable(_In_ LPTV_ITEMW TvItem)
+{
+    CNode *Node = GetNode(TvItem);
+    if (Node)
+    {
+        return Node->CanDisable();
+    }
+    return false;
+}
+
+
+/* PRIVATE METHODS ********************************************/
+
+bool
+CDeviceView::AddRootDevice()
+{
+    // Check whether we've loaded the root bitmap into the imagelist (done on first run)
+    if (m_RootClassImage == -1)
+    {
+        // Load the bitmap we'll be using as the root image
+        HBITMAP hRootImage;
+        hRootImage = LoadBitmapW(g_hInstance,
+                                 MAKEINTRESOURCEW(IDB_ROOT_IMAGE));
+        if (hRootImage == NULL) return FALSE;
+
+        // Add this bitmap to the device image list. This is a bit hacky, but it's safe
+        m_RootClassImage = ImageList_Add(m_ImageListData.ImageList,
+                                   hRootImage,
+                                   NULL);
+        DeleteObject(hRootImage);
+    }
+
+    /* Get the root instance */
+    CONFIGRET cr;
+    cr = CM_Locate_DevNodeW(&m_RootDevInst,
+                            NULL,
+                            CM_LOCATE_DEVNODE_NORMAL);
+    if (cr != CR_SUCCESS)
+    {
+        return false;
+    }
+
+    /* The root name is the computer name */
+    WCHAR RootDeviceName[ROOT_NAME_SIZE];
+    DWORD Size = ROOT_NAME_SIZE;
+    if (GetComputerNameW(RootDeviceName, &Size))
+        _wcslwr_s(RootDeviceName);
+
+    TV_ITEMW tvi;
+    TV_INSERTSTRUCT tvins;
+    ZeroMemory(&tvi, sizeof(tvi));
+    ZeroMemory(&tvins, sizeof(tvins));
+
+    // Insert the root / parent item into our treeview
+    tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+    tvi.pszText = RootDeviceName;
+    tvi.cchTextMax = wcslen(RootDeviceName);
+    tvi.iImage = m_RootClassImage;
+    tvi.iSelectedImage = m_RootClassImage;
+    tvins.item = tvi;
+    m_hTreeRoot = TreeView_InsertItem(m_hTreeView, &tvins);
+
+    return (m_hTreeRoot != NULL);
+
+}
+
+bool
+CDeviceView::GetNextClass(_In_ ULONG ClassIndex,
+                          _Out_ LPGUID ClassGuid,
+                          _Out_ HDEVINFO *hDevInfo)
+{
+    CONFIGRET cr;
+
+    // Get the next class in the list
+    cr = CM_Enumerate_Classes(ClassIndex,
+                              ClassGuid,
+                              0);
+    if (cr != CR_SUCCESS) return false;
+
+    // Check for devices without a class
+    if (IsEqualGUID(*ClassGuid, GUID_DEVCLASS_UNKNOWN))
+    {
+        // Get device info for all devices for all classes
+        *hDevInfo = SetupDiGetClassDevsW(NULL,
+                                         NULL,
+                                         NULL,
+                                         DIGCF_ALLCLASSES);
+    }
+    else
+    {
+        // We only want the devices for this class
+        *hDevInfo = SetupDiGetClassDevsW(ClassGuid,
+                                         NULL,
+                                         NULL,
+                                         DIGCF_PRESENT);
+        
+    }
+
+    return (hDevInfo != INVALID_HANDLE_VALUE);
+}
+
+unsigned int __stdcall CDeviceView::RefreshThread(void *Param)
+{
+    RefreshThreadData *ThreadData = (RefreshThreadData *)Param;
+    CDeviceView *This = ThreadData->This;
+
+
+    // Empty the treeview
+    This->EmptyDeviceView();
+    This->m_hTreeRoot = NULL;
+
+    // Refresh the devices only if requested. This means
+    // switching views uses the cache and remains fast
+    if (ThreadData->ScanForChanges)
+    {
+        This->RefreshDeviceList();
+    }
+
+    // display the type of view the user wants
+    switch (This->m_ViewType)
+    {
+        case DevicesByType:
+            (void)This->ListDevicesByType();
+            break;
+
+        case DevicesByConnection:
+            (VOID)This->ListDevicesByConnection();
+            break;
+
+        case ResourcesByType:
+            break;
+
+        case ResourcesByConnection:
+            break;
+    }
+
+    delete ThreadData;
+
+    return 0;
+}
+
+
+bool
+CDeviceView::ListDevicesByType()
+{
+    CNode *ClassNode, *DeviceNode;
+    HDEVINFO hDevInfo;
+    HTREEITEM hTreeItem = NULL;
+    GUID ClassGuid;
+    INT ClassIndex;
+    LPTSTR DeviceId = NULL;
+    BOOL bClassSuccess, bSuccess;
+
+    // Start by adding the root node to the tree
+    bSuccess = AddRootDevice();
+    if (bSuccess == false) return false;
+
+    ClassIndex = 0;
+    do
+    {
+        // Loop through all the device classes
+        bClassSuccess = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
+        if (bClassSuccess)
+        {
+            bool bClassUnknown = false;
+            bool AddedParent = false;
+            INT DeviceIndex = 0;
+            BOOL MoreItems;
+
+            // Get the cached class node
+            ClassNode = GetClassNode(&ClassGuid);
+            if (ClassNode == NULL)
+            {
+                ATLASSERT(FALSE);
+                ClassIndex++;
+                continue;
+            }
+
+            // Set a flag is this is the (special case) unknown class
+            if (IsEqualGUID(ClassGuid, GUID_DEVCLASS_UNKNOWN))
+                bClassUnknown = true;
+
+            do
+            {
+                // Get a handle to all the devices in this class
+                SP_DEVINFO_DATA DeviceInfoData;
+                ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));
+                DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+                bSuccess = SetupDiEnumDeviceInfo(hDevInfo,
+                                                 DeviceIndex,
+                                                 &DeviceInfoData);
+                if (bSuccess == FALSE && GetLastError() == ERROR_NO_MORE_ITEMS)
+                    MoreItems = FALSE;
+
+                if (bSuccess)
+                {
+                    MoreItems = TRUE;
+
+                    // The unknown class handle contains all devices on the system,
+                    // and we're just looking for the ones with a null GUID
+                    if (bClassUnknown)
+                    {
+                        if (IsEqualGUID(DeviceInfoData.ClassGuid, GUID_NULL) == FALSE)
+                        {
+                            // This is a known device, we aren't interested in it
+                            DeviceIndex++;
+                            continue;
+                        }
+                    }
+
+                    // Get the cached device node
+                    DeviceNode = GetDeviceNode(DeviceInfoData.DevInst);
+                    if (DeviceNode == NULL)
+                    {
+                        ATLASSERT(bClassUnknown == true);
+                        DeviceIndex++;
+                        continue;
+                    }
+
+                    // Check if this is a hidden device
+                    if (DeviceNode->IsHidden())
+                    {
+                        // Ignore this device if we aren't displaying hidden devices
+                        if (m_ShowHidden == FALSE)
+                        {
+                            DeviceIndex++;
+                            continue;
+                        }
+                    }
+
+                    // We have a device, we need to add the parent if it hasn't yet been added
+                    if (AddedParent == false)
+                    {
+                        // Insert the new class under the root item
+                        hTreeItem = InsertIntoTreeView(m_hTreeRoot,
+                                                       ClassNode);
+                        AddedParent = true;
+                    }
+
+                    // Add the device under the class item node
+                    (void)InsertIntoTreeView(hTreeItem, DeviceNode);
+
+                    // Expand the class if it has a problem device
+                    if (DeviceNode->HasProblem())
+                    {
+                        (void)TreeView_Expand(m_hTreeView,
+                                              hTreeItem,
+                                              TVE_EXPAND);
+                    }
+                }
+
+                DeviceIndex++;
+
+            } while (MoreItems);
+
+            // If this class has devices, sort them alphabetically
+            if (AddedParent == true)
+            {
+                (void)TreeView_SortChildren(m_hTreeView,
+                                            hTreeItem,
+                                            0);
+            }
+        }
+
+        ClassIndex++;
+
+    } while (bClassSuccess);
+
+    // Sort the classes alphabetically
+    (void)TreeView_SortChildren(m_hTreeView,
+                                m_hTreeRoot,
+                                0);
+
+    // Expand the root item
+    (void)TreeView_Expand(m_hTreeView,
+                          m_hTreeRoot,
+                          TVE_EXPAND);
+
+    // Pre-select the root item
+    (VOID)TreeView_SelectItem(m_hTreeView,
+                              m_hTreeRoot);
+
+    return 0;
+}
+
+bool
+CDeviceView::ListDevicesByConnection()
+{
+    BOOL bSuccess;
+
+    // Start by adding the root node to the tree
+    bSuccess = AddRootDevice();
+    if (bSuccess == false) return false;
+
+    /* Walk the device tree and add all the devices */
+    RecurseChildDevices(m_RootDevInst, m_hTreeRoot);
+
+    /* Expand the root item */
+    (VOID)TreeView_Expand(m_hTreeView,
+                          m_hTreeRoot,
+                          TVE_EXPAND);
+
+    return true;
+}
+
+VOID
+CDeviceView::RecurseChildDevices(
+    _In_ DEVINST ParentDevice,
+    _In_ HTREEITEM hParentTreeItem
+    )
+{
+
+    HTREEITEM hDevItem = NULL;
+    DEVINST Device;
+    BOOL bSuccess;
+
+    /* Check if the parent has any child devices */
+    if (GetChildDevice(ParentDevice, &Device) == FALSE)
+        return;
+
+    // Get the cached device node
+    CNode *DeviceNode;
+    DeviceNode = GetDeviceNode(Device);
+    if (DeviceNode == NULL)
+    {
+        ATLASSERT(FALSE);
+        return;
+    }
+
+
+    /* Check if this is a hidden device */
+    if ((m_ShowHidden == TRUE) || (!(DeviceNode->IsHidden())))
+    {
+        /* Add this device to the tree under its parent */
+        hDevItem = InsertIntoTreeView(hParentTreeItem,
+                                      DeviceNode);
+
+
+        if (hDevItem)
+        {
+            /* Check if this child has any children itself */
+            RecurseChildDevices(Device, hDevItem);
+        }
+    }
+
+
+    for (;;)
+    {
+        /* Check if the parent device has anything at the same level */
+        bSuccess = GetSiblingDevice(Device, &Device);
+        if (bSuccess == FALSE) break;
+
+        DeviceNode = GetDeviceNode(Device);
+        if (DeviceNode == NULL)
+        {
+            ATLASSERT(FALSE);
+        }
+
+        /* Check if this is a hidden device */
+        if (DeviceNode->IsHidden())
+        {
+            if (m_ShowHidden == FALSE)
+                continue;
+        }
+
+        /* Add this device to the tree under its parent */
+        hDevItem = InsertIntoTreeView(hParentTreeItem,
+                                      DeviceNode);
+        if (hDevItem)
+        {
+            /* Check if this child has any children itself */
+            RecurseChildDevices(Device, hDevItem);
+        }
+    }
+
+    (void)TreeView_SortChildren(m_hTreeView,
+                                hParentTreeItem,
+                                0);
+
+}
+
+bool
+CDeviceView::GetChildDevice(
+    _In_ DEVINST ParentDevInst,
+    _Out_ PDEVINST DevInst
+)
+{
+    CONFIGRET cr;
+    cr = CM_Get_Child(DevInst,
+                      ParentDevInst,
+                      0);
+    return (cr == CR_SUCCESS);
+}
+
+bool
+CDeviceView::GetSiblingDevice(
+    _In_ DEVINST PrevDevice,
+    _Out_ PDEVINST DevInst
+)
+{
+    CONFIGRET cr;
+    cr = CM_Get_Sibling(DevInst,
+                        PrevDevice,
+                        0);
+    return (cr == CR_SUCCESS);
+}
+
+HTREEITEM
+CDeviceView::InsertIntoTreeView(
+    _In_ HTREEITEM hParent,
+    _In_ CNode *Node
+    )
+{
+    
+    LPWSTR lpLabel;
+    lpLabel = Node->GetDisplayName();
+
+    TV_ITEMW tvi;
+    TV_INSERTSTRUCT tvins;
+    ZeroMemory(&tvi, sizeof(tvi));
+    ZeroMemory(&tvins, sizeof(tvins));
+
+    tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
+    tvi.pszText = lpLabel;
+    tvi.cchTextMax = wcslen(lpLabel);
+    tvi.lParam = (LPARAM)Node;
+    tvi.iImage = Node->GetClassImage();
+    tvi.iSelectedImage = Node->GetClassImage();
+
+    if (Node->GetOverlayImage())
+    {
+        tvi.mask |= TVIF_STATE;
+        tvi.stateMask = TVIS_OVERLAYMASK;
+        tvi.state = INDEXTOOVERLAYMASK(Node->GetOverlayImage());
+    }
+
+    tvins.item = tvi;
+    tvins.hParent = hParent;
+
+    return TreeView_InsertItem(m_hTreeView, &tvins);
+}
+
+void
+CDeviceView::RecurseDeviceView(
+    _In_ HTREEITEM hParentItem
+    )
+{
+    HTREEITEM hItem;
+    TVITEMW tvItem;
+
+    // Check if this node has any children
+    hItem = TreeView_GetChild(m_hTreeView, hParentItem);
+    if (hItem == NULL) return;
+
+    // The lParam contains the node pointer data
+    tvItem.hItem = hItem;
+    tvItem.mask = TVIF_PARAM;
+    if (TreeView_GetItem(m_hTreeView, &tvItem) &&
+        tvItem.lParam != NULL)
+    {
+        // Delete the node class
+        //delete reinterpret_cast<CNode *>(tvItem.lParam);
+    }
+
+    // This node may have its own children
+    RecurseDeviceView(hItem);
+
+    // Delete all the siblings
+    for (;;)
+    {
+        // Get the next item at this level
+        hItem = TreeView_GetNextSibling(m_hTreeView, hItem);
+        if (hItem == NULL) break;
+
+        // The lParam contains the node pointer data
+        tvItem.hItem = hItem;
+        tvItem.mask = TVIF_PARAM;
+        if (TreeView_GetItem(m_hTreeView, &tvItem))
+        {
+            //if (tvItem.lParam != NULL)
+            //    delete reinterpret_cast<CNode *>(tvItem.lParam);
+        }
+
+        /* This node may have its own children */
+        RecurseDeviceView(hItem);
+    }
+}
+
+
+void
+CDeviceView::EmptyDeviceView()
+{
+    HTREEITEM hItem;
+
+    // Check if there are any items in the tree
+    hItem = TreeView_GetRoot(m_hTreeView);
+    if (hItem == NULL) return;
+
+    // Free all the class nodes
+    //RecurseDeviceView(hItem);
+
+    // Delete all the items
+    (VOID)TreeView_DeleteAllItems(m_hTreeView);
+}
+
+
+
+
+CNode*
+CDeviceView::GetClassNode(_In_ LPGUID ClassGuid)
+{
+    POSITION Pos;
+    CNode *Node;
+
+    Pos = m_ClassNodeList.GetHeadPosition();
+
+    do
+    {
+        Node = m_ClassNodeList.GetNext(Pos);
+        if (IsEqualGUID(*Node->GetClassGuid(), *ClassGuid))
+        {
+            //ATLASSERT(Node->GetType() == NodeClass);
+            break;
+        }
+
+        Node = NULL;
+
+    } while (Pos != NULL);
+
+    return Node;
+}
+
+CNode*
+CDeviceView::GetDeviceNode(_In_ DEVINST Device)
+{
+    POSITION Pos;
+    CNode *Node;
+
+    Pos = m_DeviceNodeList.GetHeadPosition();
+
+    do
+    {
+        Node = m_DeviceNodeList.GetNext(Pos);
+        if (Node->GetDeviceInst() == Device)
+        {
+            //ATLASSERT(Node->GetType() == NodeDevice);
+            break;
+        }
+
+        Node = NULL;
+
+    } while (Pos != NULL);
+
+    return Node;
+}
+
+CNode* CDeviceView::GetNode(LPTV_ITEMW TvItem)
+{
+    TvItem->mask = TVIF_PARAM;
+    if (TreeView_GetItem(m_hTreeView, TvItem))
+    {
+        return (CNode *)TvItem->lParam;
+    }
+}
+
+CNode* CDeviceView::GetSelectedNode()
+{
+    TV_ITEM TvItem;
+    TvItem.hItem = TreeView_GetSelection(m_hTreeView);
+    return GetNode(&TvItem);
+}
+
+void
+CDeviceView::EmptyLists()
+{
+    POSITION Pos;
+    CNode *Node;
+
+    if (!m_ClassNodeList.IsEmpty())
+    {
+        Pos = m_ClassNodeList.GetHeadPosition();
+        do
+        {
+            Node = m_ClassNodeList.GetNext(Pos);
+            delete Node;
+
+        } while (Pos != NULL);
+    }
+
+    if (!m_DeviceNodeList.IsEmpty())
+    {
+        Pos = m_DeviceNodeList.GetHeadPosition();
+        do
+        {
+            Node = m_DeviceNodeList.GetNext(Pos);
+            delete Node;
+
+        } while (Pos != NULL);
+    }
+}
+
+bool
+CDeviceView::RefreshDeviceList()
+{
+    GUID ClassGuid;
+    CNode *Node;
+    HDEVINFO hDevInfo;
+    SP_DEVINFO_DATA DeviceInfoData;
+    DWORD i;
+    BOOL Success;
+
+    ULONG ClassIndex = 0;
+
+    EmptyLists();
+
+    do
+    {
+        Success = GetNextClass(ClassIndex, &ClassGuid, &hDevInfo);
+        if (Success)
+        {
+            /* Create a new class node */
+            Node = new CNode(&ClassGuid, &m_ImageListData);
+            if (Node->Setup())
+            {
+                m_ClassNodeList.AddTail(Node);
+            }
+        }
+        ClassIndex++;
+    } while (Success);
+
+
+    hDevInfo = SetupDiGetClassDevsW(NULL,
+                                    0,
+                                    0,
+                                    DIGCF_PRESENT | DIGCF_ALLCLASSES);
+    if (hDevInfo == INVALID_HANDLE_VALUE)
+    {
+        return false;
+    }
+
+
+    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+    for (i = 0;; i++)
+    {
+        Success = SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData);
+        if (Success == FALSE) break;
+
+
+        Node = new CNode(DeviceInfoData.DevInst, &m_ImageListData);
+        Node->Setup();
+        m_DeviceNodeList.AddTail(Node);
+    }
+
+    SetupDiDestroyDeviceInfoList(hDevInfo);
+
+    return TRUE;
+}
\ No newline at end of file
diff --git a/reactos/dll/win32/devmgr/devmgmt/DeviceView.h b/reactos/dll/win32/devmgr/devmgmt/DeviceView.h
new file mode 100644 (file)
index 0000000..26cbecf
--- /dev/null
@@ -0,0 +1,131 @@
+#pragma once
+#include "Node.h"
+
+enum ViewType
+{
+    DevicesByType,
+    DevicesByConnection,
+    ResourcesByType,
+    ResourcesByConnection
+};
+
+
+class CDeviceView
+{
+    CAtlList<CNode *> m_ClassNodeList;
+    CAtlList<CNode *> m_DeviceNodeList;
+
+    SP_CLASSIMAGELIST_DATA m_ImageListData;
+
+    HWND m_hMainWnd;
+    HWND m_hTreeView;
+    HWND m_hPropertyDialog;
+    HWND m_hShortcutMenu;
+    ViewType m_ViewType;
+
+    HTREEITEM m_hTreeRoot;
+    DEVINST m_RootDevInst;
+
+    bool m_ShowHidden;
+    int m_RootClassImage;
+
+public:
+    CDeviceView(
+        HWND hMainWnd
+        );
+
+    ~CDeviceView(void);
+
+    bool Initialize();
+    bool Uninitialize();
+
+    VOID Size(
+        _In_ int x,
+        _In_ int y,
+        _In_ int cx,
+        _In_ int cy
+        );
+
+    VOID Refresh(
+        _In_ ViewType Type,
+        _In_ bool ScanForChanges,
+        _In_ bool UpdateView
+        );
+
+    VOID DisplayPropertySheet();
+    VOID SetFocus();
+
+    //VOID SetDeviceListType(ListDevices List)
+    //{
+    //    m_ListDevices = List;
+    //}
+
+    VOID ShowHiddenDevices(_In_ bool ShowHidden)
+    {
+        m_ShowHidden = ShowHidden;
+    }
+
+    ViewType GetCurrentView() { return m_ViewType; }
+
+    bool HasProperties(_In_ LPTV_ITEMW TvItem);
+    //bool SelDeviceIsHidden();
+    bool CanDisable(_In_ LPTV_ITEMW TvItem);
+    bool IsDisabled(_In_ LPTV_ITEMW TvItem);
+    bool SelDeviceIsStarted();
+    bool SelDeviceIsInstalled();
+
+private:
+    bool AddRootDevice();
+
+    bool RefreshDeviceList();
+
+    static unsigned int __stdcall RefreshThread(
+        void *Param
+        );
+
+    bool ListDevicesByConnection(
+        );
+    bool ListDevicesByType(
+        );
+
+    bool GetNextClass(
+        _In_ ULONG ClassIndex,
+        _Out_ LPGUID ClassGuid,
+        _Out_ HDEVINFO *hDevInfo
+        );
+
+    VOID RecurseChildDevices(
+        _In_ DEVINST ParentDevice,
+        _In_ HTREEITEM hParentTreeItem
+        );
+
+    bool GetChildDevice(
+        _In_ DEVINST ParentDevInst,
+        _Out_ PDEVINST DevInst
+        );
+
+    bool GetSiblingDevice(
+        _In_ DEVINST PrevDevice,
+        _Out_ PDEVINST DevInst
+        );
+
+    HTREEITEM InsertIntoTreeView(
+        _In_ HTREEITEM hParent,
+        _In_ CNode *Node
+        );
+
+    VOID RecurseDeviceView(
+        _In_ HTREEITEM hParentItem
+        );
+
+    VOID EmptyDeviceView(
+        );
+
+    CNode* GetNode(_In_ LPTV_ITEMW TvItem);
+    CNode* GetSelectedNode();
+
+    CNode* GetClassNode(_In_ LPGUID ClassGuid);
+    CNode* GetDeviceNode(_In_ DEVINST Device);
+    void EmptyLists();
+};
+
diff --git a/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp b/reactos/dll/win32/devmgr/devmgmt/MainWindow.cpp
new file mode 100644 (file)
index 0000000..b708b8d
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * PROJECT:     ReactOS Device Manager
+ * LICENSE:     GPL - See COPYING in the top level directory
+ * FILE:        dll/win32/devmgr/devmgr/MainWindow.cpp
+ * PURPOSE:     Implements the main container window for the device view
+ * COPYRIGHT:   Copyright 2014 - 2015 Ged Murphy <gedmurphy@reactos.org>
+ */
+
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "MainWindow.h"
+
+
+/* DATA *****************************************************/
+
+#define BTN_PROPERTIES      0
+#define BTN_SCAN_HARDWARE   1
+#define BTN_SEPERATOR       -1
+#define BTN_ENABLE_DRV      2
+#define BTN_DISABLE_DRV     3
+#define BTN_UPDATE_DRV      4
+#define BTN_UNINSTALL_DRV   5
+
+
+// menu hints
+static const MENU_HINT MainMenuHintTable[] =
+{
+    // File Menu
+    { IDC_EXIT, IDS_HINT_EXIT },
+
+    // Action Menu
+    { IDC_UPDATE_DRV, NULL },
+    { IDC_DISABLE_DRV, NULL },
+    { IDC_UNINSTALL_DRV, NULL },
+    { IDC_SCAN_HARDWARE, IDS_HINT_REFRESH },
+    { IDC_ADD_HARDWARE, NULL },
+    { IDC_PROPERTIES, IDS_HINT_PROP},
+
+    // View Menu
+    { IDC_DEVBYTYPE, IDS_HINT_DEV_BY_TYPE},
+    { IDC_DEVBYCONN, IDS_HINT_DEV_BY_CONN},
+    { IDC_RESBYTYPE, IDS_HINT_RES_BY_TYPE},
+    { IDC_RESBYCONN, IDS_HINT_RES_BY_TYPE},
+
+    { 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 TBBUTTON TbButtons[] =
+{
+    { BTN_PROPERTIES, IDC_PROPERTIES, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+    { BTN_SCAN_HARDWARE, IDC_SCAN_HARDWARE, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+    { 2, IDC_STATIC, TBSTATE_ENABLED, BTNS_SEP, 0, 0 },
+    { BTN_ENABLE_DRV, IDC_ENABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+    { BTN_DISABLE_DRV, IDC_DISABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+    { BTN_UPDATE_DRV, IDC_UPDATE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 },
+    { BTN_UNINSTALL_DRV, IDC_UNINSTALL_DRV, TBSTATE_ENABLED, BTNS_BUTTON, 0, 0 }
+};
+
+
+/* PUBLIC METHODS **********************************************/
+
+CMainWindow::CMainWindow(void) :
+    m_ToolbarhImageList(NULL),
+    m_hMainWnd(NULL),
+    m_hStatusBar(NULL),
+    m_hToolBar(NULL),
+    m_CmdShow(0)
+{
+    m_szMainWndClass = L"DevMgmtWndClass";
+}
+
+CMainWindow::~CMainWindow(void)
+{
+    // Destroy any previous list
+    if (m_ToolbarhImageList) ImageList_Destroy(m_ToolbarhImageList);
+}
+
+bool
+CMainWindow::Initialize(LPCTSTR lpCaption,
+                        int nCmdShow)
+{
+    CAtlStringW szCaption;
+    WNDCLASSEXW wc = {0};
+
+    // Store the show window value
+    m_CmdShow = nCmdShow;
+
+    // Setup the window class struct
+    wc.cbSize = sizeof(WNDCLASSEXW);
+    wc.lpfnWndProc = MainWndProc;
+    wc.hInstance = g_hInstance;
+    wc.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCEW(IDI_MAIN_ICON));
+    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+    wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
+    wc.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
+    wc.lpszClassName = m_szMainWndClass;
+    wc.hIconSm = (HICON)LoadImage(g_hInstance,
+                                  MAKEINTRESOURCE(IDI_MAIN_ICON),
+                                  IMAGE_ICON,
+                                  16,
+                                  16,
+                                  LR_SHARED);
+
+    // Register the window
+    if (RegisterClassExW(&wc))
+    {
+        // Create the main window and store the object pointer
+        m_hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
+                                     m_szMainWndClass,
+                                     lpCaption,
+                                     WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
+                                     CW_USEDEFAULT,
+                                     CW_USEDEFAULT,
+                                     500,
+                                     500,
+                                     NULL,
+                                     NULL,
+                                     g_hInstance,
+                                     this);
+    }
+
+    // Return creation result 
+    return !!(m_hMainWnd);
+}
+
+void
+CMainWindow::Uninitialize()
+{
+    // Unregister the window class 
+    UnregisterClassW(m_szMainWndClass, g_hInstance);
+}
+
+int
+CMainWindow::Run()
+{
+    MSG Msg;
+
+    // Pump the message queue 
+    while (GetMessageW(&Msg, NULL, 0, 0 ) != 0)
+    {
+        TranslateMessage(&Msg);
+        DispatchMessageW(&Msg);
+    }
+
+    return 0;
+}
+
+
+/* PRIVATE METHODS **********************************************/
+
+bool
+CMainWindow::MainWndMenuHint(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(m_hStatusBar,
+                        SB_SIMPLEID,
+                        g_hInstance,
+                        HintId);
+
+    return Found;
+}
+
+bool
+CMainWindow::RefreshView(ViewType Type)
+{
+    UINT CheckId;
+    BOOL bSuccess;
+
+    // Refreshed the cached view
+    m_DeviceView->Refresh(Type, FALSE, TRUE);
+
+    // Get the menu item id
+    switch (Type)
+    {
+        case DevicesByType: CheckId = IDC_DEVBYTYPE; break;
+        case DevicesByConnection: CheckId = IDC_DEVBYCONN; break;
+        case ResourcesByType: CheckId = IDC_RESBYTYPE; break;
+        case ResourcesByConnection: CheckId = IDC_RESBYCONN; break;
+        default: ATLASSERT(FALSE); break;
+    }
+
+    // Set the new check item
+    bSuccess = CheckMenuRadioItem(m_hMenu,
+                                  IDC_DEVBYTYPE,
+                                  IDC_RESBYCONN,
+                                  CheckId,
+                                  MF_BYCOMMAND);
+
+    return TRUE;
+}
+
+bool
+CMainWindow::ScanForHardwareChanges()
+{
+    // Refresh the cache and and display
+    m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
+                          true,
+                          true);
+    return true;
+}
+
+
+
+
+bool
+CMainWindow::CreateToolBar()
+{
+    TBADDBITMAP TbAddBitmap;
+    INT Index;
+
+    DWORD dwStyles = WS_CHILDWINDOW | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
+    DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
+
+    // Create the toolbar window
+    m_hToolBar = CreateWindowExW(dwExStyles,
+                                 TOOLBARCLASSNAME,
+                                 NULL,
+                                 dwStyles,
+                                 0, 0, 0, 0,
+                                 m_hMainWnd,
+                                 (HMENU)IDC_TOOLBAR,
+                                 g_hInstance,
+                                 NULL);
+    if (m_hToolBar == NULL) return FALSE;
+
+    // Don't show clipped buttons
+    SendMessageW(m_hToolBar,
+                 TB_SETEXTENDEDSTYLE,
+                 0,
+                 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
+
+    SendMessageW(m_hToolBar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 16));
+
+    // Set the struct size, the toobar needs this...
+    SendMessageW(m_hToolBar,
+                 TB_BUTTONSTRUCTSIZE,
+                 sizeof(TBBUTTON),
+                 0);
+
+    TbAddBitmap.hInst = g_hInstance;
+    TbAddBitmap.nID = IDB_TOOLBAR;
+    Index = SendMessageW(m_hToolBar, TB_ADDBITMAP, _countof(TbButtons), (LPARAM)&TbAddBitmap);
+
+    SendMessageW(m_hToolBar, TB_ADDBUTTONSW, _countof(TbButtons), (LPARAM)TbButtons);
+    SendMessageW(m_hToolBar, TB_AUTOSIZE, 0, 0);
+
+    if (TRUE)
+    {
+        ShowWindow(m_hToolBar, SW_SHOW);
+    }
+
+    return TRUE;
+}
+
+bool
+CMainWindow::CreateStatusBar()
+{
+    int StatWidths[] = {110, -1}; // widths of status bar
+    bool bRet = FALSE;
+
+    // Create the status bar
+    m_hStatusBar = CreateWindowExW(0,
+                                   STATUSCLASSNAME,
+                                   NULL,
+                                   WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
+                                   0, 0, 0, 0,
+                                   m_hMainWnd,
+                                   (HMENU)IDC_STATUSBAR,
+                                   g_hInstance,
+                                   NULL);
+    if (m_hStatusBar)
+    {
+        // Set the width
+        bRet = (SendMessageW(m_hStatusBar,
+                             SB_SETPARTS,
+                             sizeof(StatWidths) / sizeof(int),
+                             (LPARAM)StatWidths) != 0);
+    }
+
+    return bRet;
+}
+
+void CMainWindow::UpdateContext(_In_ LPTV_ITEMW TvItem)
+{
+    WORD State;
+
+    // properties button
+    if (m_DeviceView->HasProperties(TvItem))
+    {
+        State = TBSTATE_ENABLED;
+    }
+    else
+    {
+        State = TBSTATE_HIDDEN;
+    }
+    SendMessageW(m_hToolBar, TB_SETSTATE, IDC_PROPERTIES, MAKELPARAM(State, 0));
+    SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UPDATE_DRV, MAKELPARAM(State, 0)); //hack
+    SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UNINSTALL_DRV, MAKELPARAM(State, 0)); // hack
+
+    // enable driver button
+    if (m_DeviceView->IsDisabled(TvItem))
+    {
+        State = TBSTATE_ENABLED;
+    }
+    else
+    {
+        State = TBSTATE_HIDDEN;
+    }
+    SendMessageW(m_hToolBar, TB_SETSTATE, IDC_ENABLE_DRV, MAKELPARAM(State, 0));
+
+    // disable driver button
+    if (m_DeviceView->CanDisable(TvItem) && !m_DeviceView->IsDisabled(TvItem))
+    {
+        State = TBSTATE_ENABLED;
+    }
+    else
+    {
+        State = TBSTATE_HIDDEN;
+    }
+    SendMessageW(m_hToolBar, TB_SETSTATE, IDC_DISABLE_DRV, MAKELPARAM(State, 0));
+
+
+
+    
+
+}
+
+
+
+bool
+CMainWindow::StatusBarLoadString(IN HWND hStatusBar,
+                                 IN INT PartId,
+                                 IN HINSTANCE hInstance,
+                                 IN UINT uID)
+{
+    CAtlStringW szMessage;
+    bool bRet = false;
+
+    // Load the string
+    if (szMessage.LoadStringW(hInstance, uID))
+    {
+        // Show the string on the status bar
+        bRet = (SendMessageW(hStatusBar,
+                             SB_SETTEXT,
+                             (WPARAM)PartId,
+                             (LPARAM)szMessage.GetBuffer()) != 0);
+    }
+
+    return bRet;
+}
+
+LRESULT
+CMainWindow::OnCreate(HWND hwnd)
+{
+    LRESULT RetCode;
+
+    RetCode = -1;
+    m_hMainWnd = hwnd;
+
+    // Store a handle to the main menu
+    m_hMenu = GetMenu(m_hMainWnd);
+
+    // Create the toolbar and statusbar
+    if (CreateToolBar() && CreateStatusBar())
+    {
+        // Create the device view object
+        m_DeviceView = new CDeviceView(m_hMainWnd);
+        if (m_DeviceView->Initialize())
+        {
+            // Do the initial scan
+            ScanForHardwareChanges();
+
+            // Display the window according to the user request
+            ShowWindow(hwnd, m_CmdShow);
+            RetCode = 0;
+        }
+    }
+
+    return RetCode;
+}
+
+LRESULT
+CMainWindow::OnSize()
+{
+    RECT rcClient, rcTool, rcStatus;
+    INT lvHeight, iToolHeight, iStatusHeight;
+
+    // Autosize the toolbar
+    SendMessage(m_hToolBar, TB_AUTOSIZE, 0, 0);
+
+    // Get the toolbar rect and save the height
+    GetWindowRect(m_hToolBar, &rcTool);
+    iToolHeight = rcTool.bottom - rcTool.top;
+
+    // Resize the status bar
+    SendMessage(m_hStatusBar, WM_SIZE, 0, 0);
+
+    // Get the statusbar rect and save the height
+    GetWindowRect(m_hStatusBar, &rcStatus);
+    iStatusHeight = rcStatus.bottom - rcStatus.top;
+
+    // Get the full client rect
+    GetClientRect(m_hMainWnd, &rcClient);
+
+    // Calculate the remaining height for the treeview
+    lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
+
+    // Resize the device view
+    m_DeviceView->Size(0,
+                       iToolHeight,
+                       rcClient.right,
+                       lvHeight);
+
+    return 0;
+}
+
+LRESULT
+CMainWindow::OnNotify(LPARAM lParam)
+{
+    LPNMHDR NmHdr = (LPNMHDR)lParam;
+
+    switch (NmHdr->code)
+    {
+        case TVN_SELCHANGED:
+        {
+            LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
+            UpdateContext(&NmTreeView->itemNew);
+            break;
+        }
+
+        case TVN_DELETEITEMW:
+        {
+            LPNMTREEVIEW NmTreeView = (LPNMTREEVIEW)lParam;
+            NmTreeView->action = NmTreeView->action;
+
+            break;
+        }
+
+        case NM_DBLCLK:
+        {
+            m_DeviceView->DisplayPropertySheet();
+            break;
+        }
+
+        case NM_RETURN:
+        {
+            m_DeviceView->DisplayPropertySheet();
+            break;
+        }
+    }
+
+    return 0;
+}
+
+LRESULT
+CMainWindow::OnContext(LPARAM lParam)
+{
+    return 0;
+}
+
+LRESULT
+CMainWindow::OnCommand(WPARAM wParam,
+                       LPARAM lParam)
+{
+    LRESULT RetCode = 0;
+    WORD Msg;
+
+    // Get the message
+    Msg = LOWORD(wParam);
+
+    switch (Msg)
+    {
+        case IDC_PROPERTIES:
+        {
+            m_DeviceView->DisplayPropertySheet();
+            break;
+        }
+
+        case IDC_SCAN_HARDWARE:
+        {
+            ScanForHardwareChanges();
+            break;
+        }
+
+        case IDC_DEVBYTYPE:
+        {
+            RefreshView(DevicesByType);
+            break;
+        }
+
+        case IDC_DEVBYCONN:
+        {
+            RefreshView(DevicesByConnection);
+            break;
+        }
+
+        case IDC_SHOWHIDDEN:
+        {
+            UINT CurCheckState, NewCheckState;
+            
+            // Get the current state
+            CurCheckState = GetMenuState(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND);
+
+            if (CurCheckState == MF_CHECKED)
+            {
+                // Inform the device view of the change
+                m_DeviceView->ShowHiddenDevices(false);
+                NewCheckState = MF_UNCHECKED;
+            }
+            else if (CurCheckState == MF_UNCHECKED)
+            {
+                m_DeviceView->ShowHiddenDevices(true);
+                NewCheckState = MF_CHECKED;
+            }
+            else
+            {
+                ATLASSERT(FALSE);
+                break;
+            }
+
+            // Set the new check state
+            CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | NewCheckState);
+
+            // Refresh the device view
+            m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
+                                  false,
+                                  true);
+            break;
+        }
+
+        case IDC_ABOUT:
+        {
+            // Apportion blame
+            MessageBoxW(m_hMainWnd,
+                        L"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
+                        L"About",
+                        MB_OK | MB_APPLMODAL);
+
+            // Set focus back to the treeview
+            m_DeviceView->SetFocus();
+            break;
+        }
+
+        case IDC_EXIT:
+        {
+            // Post a close message to the window
+            PostMessageW(m_hMainWnd,
+                         WM_CLOSE,
+                         0,
+                         0);
+            break;
+        }
+
+        default:
+            // We didn't handle it
+            RetCode = -1;
+            break;
+    }
+
+    return RetCode;
+}
+
+LRESULT
+CMainWindow::OnDestroy()
+{
+    // Uninitialize the device view
+    m_DeviceView->Uninitialize();
+
+    // Kill the object
+    delete m_DeviceView;
+    m_DeviceView = NULL;
+
+    // Clear the user data pointer
+    SetWindowLongPtr(m_hMainWnd, GWLP_USERDATA, 0);
+
+    // Break the message loop
+    PostQuitMessage(0);
+
+    return 0;
+}
+
+LRESULT CALLBACK
+CMainWindow::MainWndProc(HWND hwnd,
+                         UINT msg,
+                         WPARAM wParam,
+                         LPARAM lParam)
+{
+    CMainWindow *pThis;
+    LRESULT RetCode = 0;
+
+    // Get the object pointer from window context
+    pThis = (CMainWindow *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
+    if (pThis == NULL)
+    {
+        // Check that this isn't a create message
+        if (msg != WM_CREATE)
+        {
+            // Don't handle null info pointer
+            goto HandleDefaultMessage;
+        }
+    }
+
+    switch(msg)
+    {
+        case WM_CREATE:
+        {
+            // Get the object pointer from the create param
+            pThis = (CMainWindow *)((LPCREATESTRUCT)lParam)->lpCreateParams;
+
+            // Store the pointer in the window's global user data
+            SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
+
+            // Call the create handler
+            RetCode = pThis->OnCreate(hwnd);
+            break;
+        }
+
+        case WM_SIZE:
+        {
+            RetCode = pThis->OnSize();
+            break;
+        }
+
+        case WM_NOTIFY:
+        {
+            RetCode = pThis->OnNotify(lParam);
+            break;
+        }
+
+        case WM_CONTEXTMENU:
+        {
+            RetCode = pThis->OnContext(lParam);
+            break;
+        }
+
+        case WM_MENUSELECT:
+        {
+            if (pThis->m_hStatusBar != NULL)
+            {
+                if (!pThis->MainWndMenuHint(LOWORD(wParam),
+                                            MainMenuHintTable,
+                                            sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
+                                            IDS_HINT_BLANK))
+                {
+                    pThis->MainWndMenuHint(LOWORD(wParam),
+                                           SystemMenuHintTable,
+                                           sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
+                                           IDS_HINT_BLANK);
+                }
+            }
+
+            break;
+        }
+
+        case WM_COMMAND:
+        {
+            // Handle the command message
+            RetCode = pThis->OnCommand(wParam, lParam);
+            if (RetCode == -1)
+            {
+                // Hand it off to the default message handler
+                goto HandleDefaultMessage;
+            }
+        }
+
+        case WM_CLOSE:
+        {
+            // Destroy the main window
+            DestroyWindow(hwnd);
+        }
+        break;
+
+        case WM_DESTROY:
+        {
+            // Call the destroy handler
+            RetCode = pThis->OnDestroy();
+            break;
+        }
+
+        default:
+        {
+HandleDefaultMessage:
+            RetCode = DefWindowProc(hwnd, msg, wParam, lParam);
+            break;
+        }
+    }
+
+    return RetCode;
+}
+
+
+//////// MOVE ME ////////////////
+
+HINSTANCE g_hInstance = NULL;
+HANDLE ProcessHeap = NULL;
+
+BOOL
+WINAPI
+DeviceManager_ExecuteW(HWND hWndParent,
+                       HINSTANCE hInst,
+                       LPCWSTR lpMachineName,
+                       int nCmdShow)
+{
+    CMainWindow MainWindow;
+    INITCOMMONCONTROLSEX icex;
+    CAtlStringW szAppName;
+    int Ret = 1;
+
+    // Store the global values
+    g_hInstance = hInst;
+    ProcessHeap = GetProcessHeap();
+
+    // Initialize common controls
+    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+    icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES;
+    InitCommonControlsEx(&icex);
+
+    // Load the application name
+    if (szAppName.LoadStringW(g_hInstance, IDS_APPNAME))
+    {
+        // Initialize the main window
+        if (MainWindow.Initialize(szAppName, nCmdShow))
+        {
+            // Run the application
+            Ret = MainWindow.Run();
+
+            // Uninitialize the main window
+            MainWindow.Uninitialize();
+        }
+    }
+
+    return Ret;
+}
diff --git a/reactos/dll/win32/devmgr/devmgmt/MainWindow.h b/reactos/dll/win32/devmgr/devmgmt/MainWindow.h
new file mode 100644 (file)
index 0000000..ebb0600
--- /dev/null
@@ -0,0 +1,70 @@
+#pragma once
+#include "DeviceView.h"
+
+typedef struct _MENU_HINT
+{
+    WORD CmdId;
+    UINT HintId;
+} MENU_HINT, *PMENU_HINT;
+
+class CMainWindow
+{
+    CAtlStringW m_szMainWndClass;
+    CDeviceView *m_DeviceView;
+    HWND m_hMainWnd;
+    HWND m_hStatusBar;
+    HWND m_hToolBar;
+    HIMAGELIST m_ToolbarhImageList;
+    HMENU m_hMenu;
+    int m_CmdShow;
+
+public:
+    CMainWindow(void);
+    ~CMainWindow(void);
+
+    bool Initialize(LPCTSTR lpCaption, int nCmdShow);
+    int Run();
+    void Uninitialize();
+
+private:
+    static LRESULT CALLBACK MainWndProc(
+        HWND hwnd,
+        UINT msg,
+        WPARAM wParam,
+        LPARAM lParam
+        );
+
+    LRESULT OnCreate(HWND hwnd);
+    LRESULT OnDestroy();
+    LRESULT OnSize();
+    LRESULT OnNotify(LPARAM lParam);
+    LRESULT OnContext(LPARAM lParam);
+    LRESULT OnCommand(WPARAM wParam, LPARAM lParam);
+
+    bool CreateToolBar();
+    bool CreateStatusBar();
+
+    void UpdateContext(_In_ LPTV_ITEMW TvItem);
+
+    bool StatusBarLoadString(
+        HWND hStatusBar,
+        INT PartId,
+        HINSTANCE hInstance,
+        UINT uID
+        );
+
+    bool MainWndMenuHint(
+        WORD CmdId,
+        const MENU_HINT *HintArray,
+        DWORD HintsCount,
+        UINT DefHintId
+        );
+
+    bool RefreshView(
+        ViewType Type
+        );
+
+    bool ScanForHardwareChanges(
+        );
+};
+
diff --git a/reactos/dll/win32/devmgr/devmgmt/Node.cpp b/reactos/dll/win32/devmgr/devmgmt/Node.cpp
new file mode 100644 (file)
index 0000000..2167f83
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+* PROJECT:     ReactOS Device Manager
+* LICENSE:     GPL - See COPYING in the top level directory
+* FILE:        dll/win32/devmgr/devmgr/node.cpp
+* PURPOSE:     Object for each device in the tree
+* COPYRIGHT:   Copyright 2015 Ged Murphy <gedmurphy@reactos.org>
+*
+*/
+
+#include "stdafx.h"
+#include "devmgmt.h"
+#include "Node.h"
+
+
+/* PUBLIC METHODS *******************************************/
+
+CNode::CNode(_In_ LPGUID ClassGuid,
+             _In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
+    m_ImageListData(ImageListData),
+    m_NodeType(NodeClass),
+    m_DevInst(0),
+    m_DeviceId(NULL),
+    m_ClassImage(0),
+    m_Status(0),
+    m_ProblemNumber(0),
+    m_OverlayImage(0)
+{
+    m_DisplayName[0] = UNICODE_NULL;
+    CopyMemory(&m_ClassGuid, ClassGuid, sizeof(GUID));
+}
+
+CNode::CNode(_In_opt_ DEVINST Device,
+             _In_ PSP_CLASSIMAGELIST_DATA ImageListData) :
+    m_ImageListData(ImageListData),
+    m_NodeType(NodeDevice),
+    m_DevInst(Device),
+    m_DeviceId(NULL),
+    m_ClassImage(0),
+    m_Status(0),
+    m_ProblemNumber(0),
+    m_OverlayImage(0)
+{
+    m_DisplayName[0] = UNICODE_NULL;
+    CopyMemory(&m_ClassGuid, &GUID_NULL, sizeof(GUID));
+}
+
+CNode::~CNode()
+{
+    Cleanup();
+}
+
+bool
+CNode::Setup()
+{
+    // TODO: Make this polymorphic
+
+    if (m_NodeType == NodeClass)
+    {
+        return SetupClassNode();
+    }
+    else if (m_NodeType == NodeDevice)
+    {
+        return SetupDeviceNode();
+    }
+
+    return FALSE;
+}
+
+bool
+CNode::HasProperties()
+{
+    return (m_DeviceId != NULL);
+}
+
+bool
+CNode::IsHidden()
+{
+    return ((m_Status & DN_NO_SHOW_IN_DM) != 0);
+}
+
+bool
+CNode::CanDisable()
+{
+    return (m_NodeType == NodeDevice && ((m_Status & DN_DISABLEABLE) != 0));
+}
+
+bool
+CNode::IsDisabled()
+{
+    return ((m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED)) != 0);
+}
+
+bool
+CNode::IsStarted()
+{
+    return ((m_Status & DN_STARTED) != 0);
+}
+
+bool
+CNode::IsInstalled()
+{
+    return ((m_Status & DN_HAS_PROBLEM) != 0 ||
+            (m_Status & (DN_DRIVER_LOADED | DN_STARTED)) != 0);
+}
+
+
+/* PRIVATE METHODS ******************************************/
+
+bool
+CNode::SetupClassNode()
+{
+    DWORD RequiredSize, Type, Size;
+    DWORD Success;
+    HKEY hKey;
+
+    // Open the registry key for this class
+    hKey = SetupDiOpenClassRegKeyExW(&m_ClassGuid,
+                                     MAXIMUM_ALLOWED,
+                                     DIOCR_INSTALLER,
+                                     NULL,
+                                     0);
+    if (hKey != INVALID_HANDLE_VALUE)
+    {
+        Size = DISPLAY_NAME_LEN;
+        Type = REG_SZ;
+
+        // Lookup the class description (win7+)
+        Success = RegQueryValueExW(hKey,
+                                   L"ClassDesc",
+                                   NULL,
+                                   &Type,
+                                   (LPBYTE)m_DisplayName,
+                                   &Size);
+        if (Success == ERROR_SUCCESS)
+        {
+            // Check if the string starts with an @
+            if (m_DisplayName[0] == L'@')
+            {
+                // The description is located in a module resource
+                Success = ConvertResourceDescriptorToString(m_DisplayName, DISPLAY_NAME_LEN);
+            }
+        }
+        else if (Success == ERROR_FILE_NOT_FOUND)
+        {
+            // WinXP stores the description in the default value
+            Success = RegQueryValueExW(hKey,
+                                       NULL,
+                                       NULL,
+                                       &Type,
+                                       (LPBYTE)m_DisplayName,
+                                       &Size);
+        }
+
+        // Close the registry key
+        RegCloseKey(hKey);
+    }
+    else
+    {
+        Success = GetLastError();
+    }
+
+    // Check if we failed to get the class description
+    if (Success != ERROR_SUCCESS)
+    {
+        // Use the class name as the description
+        RequiredSize = DISPLAY_NAME_LEN;
+        (VOID)SetupDiClassNameFromGuidW(&m_ClassGuid,
+                                        m_DisplayName,
+                                        RequiredSize,
+                                        &RequiredSize);
+    }
+
+    // Get the image index for this class
+    (VOID)SetupDiGetClassImageIndex(m_ImageListData,
+                                    &m_ClassGuid,
+                                    &m_ClassImage);
+
+    return true;
+}
+
+bool
+CNode::SetupDeviceNode()
+{
+    WCHAR ClassGuidString[MAX_GUID_STRING_LEN];
+    ULONG ulLength;
+    CONFIGRET cr;
+
+//    ATLASSERT(m_DeviceId == NULL);
+
+    // Get the length of the device id string
+    cr = CM_Get_Device_ID_Size(&ulLength, m_DevInst, 0);
+    if (cr == CR_SUCCESS)
+    {
+        // We alloc heap here because this will be stored in the lParam of the TV
+        m_DeviceId = (LPWSTR)HeapAlloc(GetProcessHeap(),
+                                      0,
+                                      (ulLength + 1) * sizeof(WCHAR));
+        if (m_DeviceId)
+        {
+            // Now get the actual device id
+            cr = CM_Get_Device_IDW(m_DevInst,
+                                   m_DeviceId,
+                                   ulLength + 1,
+                                   0);
+            if (cr != CR_SUCCESS)
+            {
+                HeapFree(GetProcessHeap(), 0, m_DeviceId);
+                m_DeviceId = NULL;
+            }
+        }
+    }
+
+    // Make sure we got the string
+    if (m_DeviceId == NULL)
+        return false;
+
+    // Get the current status of the device
+    cr = CM_Get_DevNode_Status_Ex(&m_Status,
+                                  &m_ProblemNumber,
+                                  m_DevInst,
+                                  0,
+                                  NULL);
+    if (cr != CR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(), 0, m_DeviceId);
+        m_DeviceId = NULL;
+        return false;
+    }
+
+    // Check if the device has a problem
+    if (m_Status & DN_HAS_PROBLEM)
+    {
+        m_OverlayImage = 1;
+    }
+
+    // The disabled overlay takes precidence over the problem overlay
+    if (m_ProblemNumber & (CM_PROB_DISABLED | CM_PROB_HARDWARE_DISABLED))
+    {
+        m_OverlayImage = 2;
+    }
+
+
+    // Get the class guid for this device
+    ulLength = MAX_GUID_STRING_LEN * sizeof(WCHAR);
+    cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+                                           CM_DRP_CLASSGUID,
+                                           NULL,
+                                           ClassGuidString,
+                                           &ulLength,
+                                           0);
+    if (cr == CR_SUCCESS)
+    {
+        // Convert the string to a proper guid
+        CLSIDFromString(ClassGuidString, &m_ClassGuid);
+    }
+    else
+    {
+        // It's a device with no driver
+        m_ClassGuid = GUID_DEVCLASS_UNKNOWN;
+    }
+
+
+    // Get the image for the class this device is in
+    SetupDiGetClassImageIndex(m_ImageListData,
+                              &m_ClassGuid,
+                              &m_ClassImage);
+
+    // Get the description for the device
+    ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
+    cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+                                           CM_DRP_FRIENDLYNAME,
+                                           NULL,
+                                           m_DisplayName,
+                                           &ulLength,
+                                           0);
+    if (cr != CR_SUCCESS)
+    {
+        ulLength = DISPLAY_NAME_LEN * sizeof(WCHAR);
+        cr = CM_Get_DevNode_Registry_PropertyW(m_DevInst,
+                                               CM_DRP_DEVICEDESC,
+                                               NULL,
+                                               m_DisplayName,
+                                               &ulLength,
+                                               0);
+
+    }
+
+    // Cleanup if something failed
+    if (cr != CR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(), 0, m_DeviceId);
+        m_DeviceId = NULL;
+    }
+
+    return (cr == CR_SUCCESS ? true : false);
+}
+
+void
+CNode::Cleanup()
+{
+    if (m_DeviceId)
+    {
+        HeapFree(GetProcessHeap(), 0, m_DeviceId);
+        m_DeviceId = NULL;
+    }
+}
+
+DWORD
+CNode::ConvertResourceDescriptorToString(
+    _Inout_z_ LPWSTR ResourceDescriptor,
+    _In_ DWORD ResourceDescriptorSize
+)
+{
+    WCHAR ModulePath[MAX_PATH];
+    WCHAR ResString[256];
+    INT ResourceId;
+    HMODULE hModule;
+    LPWSTR ptr;
+    DWORD Size;
+    DWORD dwError;
+
+
+    // First check for a semi colon */
+    ptr = wcschr(ResourceDescriptor, L';');
+    if (ptr)
+    {
+        // This must be an inf based descriptor, the desc is after the semi colon
+        wcscpy_s(ResourceDescriptor, ResourceDescriptorSize, ++ptr);
+        dwError = ERROR_SUCCESS;
+    }
+    else
+    {
+        // This must be a dll resource based descriptor. Find the comma
+        ptr = wcschr(ResourceDescriptor, L',');
+        if (ptr == NULL) return ERROR_INVALID_DATA;
+
+        // Terminate the string where the comma was
+        *ptr = UNICODE_NULL;
+
+        // Expand any environment strings
+        Size = ExpandEnvironmentStringsW(&ResourceDescriptor[1], ModulePath, MAX_PATH);
+        if (Size > MAX_PATH) return ERROR_BUFFER_OVERFLOW;
+        if (Size == 0) return GetLastError();
+
+        // Put the comma back and move past it
+        *ptr = L',';
+        ptr++;
+
+        // Load the dll
+        hModule = LoadLibraryExW(ModulePath, NULL, LOAD_LIBRARY_AS_DATAFILE);
+        if (hModule == NULL) return GetLastError();
+
+        // Convert the resource id to a number
+        ResourceId = _wtoi(ptr);
+
+        // If the number is negative, make it positive
+        if (ResourceId < 0) ResourceId = -ResourceId;
+
+        // Load the string from the dll
+        if (LoadStringW(hModule, ResourceId, ResString, 256))
+        {
+            wcscpy_s(ResourceDescriptor, ResourceDescriptorSize, ResString);
+            dwError = ERROR_SUCCESS;
+        }
+        else
+        {
+            dwError = GetLastError();
+        }
+
+        // Free the library
+        FreeLibrary(hModule);
+    }
+
+    return dwError;
+}
diff --git a/reactos/dll/win32/devmgr/devmgmt/Node.h b/reactos/dll/win32/devmgr/devmgmt/Node.h
new file mode 100644 (file)
index 0000000..2a858bb
--- /dev/null
@@ -0,0 +1,78 @@
+#pragma once
+
+#define DISPLAY_NAME_LEN    256
+#define ROOT_NAME_SIZE      MAX_COMPUTERNAME_LENGTH + 1
+
+enum NodeType
+{
+    NodeClass,
+    NodeDevice
+};
+
+typedef ULONG Actions;
+#define Update      0x01
+#define Enable      0x02
+#define Disable     0x04
+#define Uninstall   0x08
+
+
+class CNode
+{
+private:
+    PSP_CLASSIMAGELIST_DATA m_ImageListData;
+    NodeType m_NodeType;
+    DEVINST m_DevInst;
+    Actions m_Actions;
+    LPWSTR m_DeviceId;
+    WCHAR m_DisplayName[DISPLAY_NAME_LEN];
+    GUID  m_ClassGuid;
+    INT m_ClassImage;
+    ULONG m_Status;
+    ULONG m_ProblemNumber;
+    INT m_OverlayImage;
+
+public:
+    CNode(
+        _In_ LPGUID ClassGuid,
+        _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+        );
+
+    CNode(
+        _In_ DEVINST Device,
+        _In_ PSP_CLASSIMAGELIST_DATA ImageListData
+        );
+
+    ~CNode();
+
+    bool Setup();
+
+    LPGUID GetClassGuid() { return &m_ClassGuid;  }
+    DEVINST GetDeviceInst() { return m_DevInst; }
+
+    LPWSTR GetDisplayName() { return m_DisplayName; }
+    INT GetClassImage() { return m_ClassImage; }
+    INT GetOverlayImage() { return m_OverlayImage; }
+    LPWSTR GetDeviceId() { return m_DeviceId; }
+    Actions GetActions() { return m_Actions; }
+
+    bool HasProblem() { return !!(m_ProblemNumber); }
+    bool HasProperties();
+    bool IsHidden();
+    bool CanDisable();
+    bool IsDisabled();
+    bool IsStarted();
+    bool IsInstalled();
+    bool CanInstall() { return TRUE; } // unimplemented
+    bool CanUninstall() { return TRUE; } // unimplemented
+
+private:
+    bool SetupClassNode();
+    bool SetupDeviceNode();
+    void Cleanup();
+
+    DWORD ConvertResourceDescriptorToString(
+        _Inout_z_ LPWSTR ResourceDescriptor,
+        _In_ DWORD ResourceDescriptorSize
+        );
+};
+
diff --git a/reactos/dll/win32/devmgr/devmgmt/Resource.h b/reactos/dll/win32/devmgr/devmgmt/Resource.h
new file mode 100644 (file)
index 0000000..3184e15
--- /dev/null
@@ -0,0 +1,63 @@
+#define IDC_STATIC          -1
+
+#define IDI_MAIN_ICON       20
+#define IDB_ROOT_IMAGE      21
+#define IDB_TOOLBAR         22
+
+/* windows */
+#define IDC_TREEVIEW        50
+#define IDC_TOOLBAR         51
+#define IDC_STATUSBAR       52
+#define IDR_MAINMENU        53
+#define IDR_POPUP           54
+
+/* Actions */
+#define IDC_PROPERTIES      100
+#define IDC_SCAN_HARDWARE   101
+#define IDC_ENABLE_DRV      102
+#define IDC_DISABLE_DRV     103
+#define IDC_UPDATE_DRV      104
+#define IDC_UNINSTALL_DRV   105
+#define IDC_ADD_HARDWARE    106
+#define IDC_ABOUT           107
+#define IDC_EXIT            108
+
+/* view menu */
+#define IDC_DEVBYTYPE       200
+#define IDC_DEVBYCONN       201
+#define IDC_RESBYTYPE       202
+#define IDC_RESBYCONN       203
+#define IDC_SHOWHIDDEN      204
+
+/* about box info */
+#define IDD_ABOUTBOX        300
+#define IDC_LICENSE_EDIT    301
+#define IDS_APPNAME         302
+#define IDS_LICENSE         303
+
+/* tooltips */
+#define IDS_TOOLTIP_PROP    6000
+#define IDS_TOOLTIP_REFRESH 6001
+#define IDS_TOOLTIP_HELP    6002
+
+/* menu hints */
+#define IDS_HINT_BLANK          20000
+#define IDS_HINT_REFRESH        20002
+#define IDS_HINT_PROP           20003
+#define IDS_HINT_HELP           20004
+#define IDS_HINT_ABOUT          20005
+#define IDS_HINT_EXIT           20006
+
+#define IDS_HINT_DEV_BY_TYPE    20020
+#define IDS_HINT_DEV_BY_CONN    20021
+#define IDS_HINT_RES_BY_TYPE    20022
+#define IDS_HINT_RES_BY_CONN    20023
+
+/* system menu hints */
+#define IDS_HINT_SYS_RESTORE    21001
+#define IDS_HINT_SYS_MOVE       21002
+#define IDS_HINT_SYS_SIZE       21003
+#define IDS_HINT_SYS_MINIMIZE   21004
+#define IDS_HINT_SYS_MAXIMIZE   21005
+#define IDS_HINT_SYS_CLOSE      21006
+
diff --git a/reactos/dll/win32/devmgr/devmgmt/devmgmt.h b/reactos/dll/win32/devmgr/devmgmt/devmgmt.h
new file mode 100644 (file)
index 0000000..f8abae2
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma once
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#pragma once
+#include "resource.h"
+
+extern HINSTANCE g_hInstance;
+extern HANDLE ProcessHeap;
+
diff --git a/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc b/reactos/dll/win32/devmgr/devmgmt/lang/en-US.rc
new file mode 100644 (file)
index 0000000..caf82ca
--- /dev/null
@@ -0,0 +1,72 @@
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+IDR_MAINMENU MENU
+BEGIN
+  POPUP "&File"
+  BEGIN
+    MENUITEM "E&xit",                       IDC_EXIT
+  END
+  POPUP "Action"
+  BEGIN
+    MENUITEM "Update driver software..."    IDC_UPDATE_DRV
+    MENUITEM "Disable"                      IDC_DISABLE_DRV
+    MENUITEM "Uninstall"                    IDC_UNINSTALL_DRV
+    MENUITEM SEPARATOR
+    MENUITEM "Scan for hardware changes"    IDC_SCAN_HARDWARE
+    MENUITEM "Add hardware"                 IDC_ADD_HARDWARE, GRAYED
+    MENUITEM SEPARATOR
+    MENUITEM "Properties",                  IDC_PROPERTIES
+  END
+  POPUP "View"
+  BEGIN
+    MENUITEM "Devices by type",             IDC_DEVBYTYPE
+    MENUITEM "Devices by connection",       IDC_DEVBYCONN
+    MENUITEM "Resources by type",           IDC_RESBYTYPE, GRAYED
+    MENUITEM "Resources by connection",     IDC_RESBYCONN, GRAYED
+    MENUITEM SEPARATOR
+    MENUITEM "Show hidden devices",         IDC_SHOWHIDDEN
+  END
+  POPUP "Help"
+  BEGIN
+    MENUITEM "About",                       IDC_ABOUT
+  END
+END
+
+IDR_POPUP MENU
+BEGIN
+  POPUP "popup"
+  BEGIN
+    MENUITEM "Properties",                  IDC_PROPERTIES, GRAYED
+  END
+END
+
+STRINGTABLE DISCARDABLE
+BEGIN
+  IDS_TOOLTIP_PROP      "Properties"
+  IDS_TOOLTIP_REFRESH   "Scan for hardware changes"
+  IDS_TOOLTIP_HELP      "Help"
+END
+
+/* Hints */
+STRINGTABLE DISCARDABLE
+BEGIN
+  IDS_APPNAME           "ReactOS Device Manager"
+  IDS_HINT_BLANK        " "
+  IDS_HINT_EXIT         " Exits the program."
+  IDS_HINT_REFRESH      " Scan for changed or new Plug and Play devices."
+  IDS_HINT_PROP         " Open property dialog for the current selection."
+  IDS_HINT_HELP         " Display help window."
+  IDS_HINT_ABOUT        " About ReactOS Device Manager."
+
+  IDS_HINT_DEV_BY_TYPE  "Displays devices by hardware type"
+  IDS_HINT_DEV_BY_CONN  "Displays devices by connection"
+  IDS_HINT_RES_BY_TYPE  "Diaplays resources by type"
+  IDS_HINT_RES_BY_CONN  "Displays resources by connection type"
+
+  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/dll/win32/devmgr/devmgmt/res/computer.ico b/reactos/dll/win32/devmgr/devmgmt/res/computer.ico
new file mode 100644 (file)
index 0000000..56edfcb
Binary files /dev/null and b/reactos/dll/win32/devmgr/devmgmt/res/computer.ico differ
diff --git a/reactos/dll/win32/devmgr/devmgmt/res/root.bmp b/reactos/dll/win32/devmgr/devmgmt/res/root.bmp
new file mode 100644 (file)
index 0000000..e2734fb
Binary files /dev/null and b/reactos/dll/win32/devmgr/devmgmt/res/root.bmp differ
diff --git a/reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp b/reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp
new file mode 100644 (file)
index 0000000..c7dd5ac
Binary files /dev/null and b/reactos/dll/win32/devmgr/devmgmt/res/toolbar.bmp differ
diff --git a/reactos/dll/win32/devmgr/devmgmt/rsrc.rc b/reactos/dll/win32/devmgr/devmgmt/rsrc.rc
new file mode 100644 (file)
index 0000000..2d50111
--- /dev/null
@@ -0,0 +1,80 @@
+#include <windows.h>
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+IDI_MAIN_ICON   ICON    "res/computer.ico"
+IDB_ROOT_IMAGE  BITMAP  "res/root.bmp"
+
+/* main toolbar icons */
+IDB_TOOLBAR    BITMAP DISCARDABLE "res/toolbar.bmp"
+
+// UTF-8
+#pragma code_page(65001)
+
+#ifdef LANGUAGE_BG_BG
+    #include "lang/bg-BG.rc"
+#endif
+#ifdef LANGUAGE_DE_DE
+    #include "lang/de-DE.rc"
+#endif
+#ifdef LANGUAGE_EL_GR
+    #include "lang/el-GR.rc"
+#endif
+#ifdef LANGUAGE_EN_US
+    #include "lang/en-US.rc"
+#endif
+#ifdef LANGUAGE_ES_ES
+    #include "lang/es-ES.rc"
+#endif
+#ifdef LANGUAGE_FR_FR
+    #include "lang/fr-FR.rc"
+#endif
+#ifdef LANGUAGE_HE_IL
+    #include "lang/he-IL.rc"
+#endif
+#ifdef LANGUAGE_ID_ID
+    #include "lang/id-ID.rc"
+#endif
+#ifdef LANGUAGE_IT_IT
+    #include "lang/it-IT.rc"
+#endif
+#ifdef LANGUAGE_JA_JP
+    #include "lang/ja-JP.rc"
+#endif
+#ifdef LANGUAGE_KO_KR
+    #include "lang/ko-KR.rc"
+#endif
+#ifdef LANGUAGE_NB_NO
+    #include "lang/no-NO.rc"
+#endif
+#ifdef LANGUAGE_PL_PL
+    #include "lang/pl-PL.rc"
+#endif
+#ifdef LANGUAGE_PT_BR
+    #include "lang/pt-BR.rc"
+#endif
+#ifdef LANGUAGE_RO_RO
+    #include "lang/ro-RO.rc"
+#endif
+#ifdef LANGUAGE_RU_RU
+    #include "lang/ru-RU.rc"
+#endif
+#ifdef LANGUAGE_SK_SK
+    #include "lang/sk-SK.rc"
+#endif
+#ifdef LANGUAGE_SV_SE
+    #include "lang/sv-SE.rc"
+#endif
+#ifdef LANGUAGE_TH_TH
+    #include "lang/th-TH.rc"
+#endif
+#ifdef LANGUAGE_TR_TR
+    #include "lang/tr-TR.rc"
+#endif
+#ifdef LANGUAGE_UK_UA
+    #include "lang/uk-UA.rc"
+#endif
+#ifdef LANGUAGE_ZH_CN
+    #include "lang/zh-CN.rc"
+#endif
diff --git a/reactos/dll/win32/devmgr/devmgmt/stdafx.h b/reactos/dll/win32/devmgr/devmgmt/stdafx.h
new file mode 100644 (file)
index 0000000..e233e57
--- /dev/null
@@ -0,0 +1,50 @@
+#pragma once
+
+#ifndef __REACTOS___
+
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#include <windowsx.h>
+#include <setupapi.h>
+#include <cfgmgr32.h>
+#include <commctrl.h>
+#include <Uxtheme.h>
+#include <Cfgmgr32.h>
+#include <devguid.h>
+#include <process.h>
+
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // some CString constructors will be explicit
+#include <tchar.h>
+#include <atlbase.h>
+#include <atlstr.h>
+#include <atlcoll.h>
+
+#else
+
+#include <tchar.h>
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <wingdi.h>
+#include <winnls.h>
+#include <wincon.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <strsafe.h>
+#include <process.h>
+
+#include <string.h>
+#include <wchar.h>
+
+#include <setupapi.h>
+#include <commctrl.h>
+#include <cfgmgr32.h>
+#include <Uxtheme.h>
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlwin.h>
+#include <atlstr.h>
+
+#endif
\ No newline at end of file