[DEVMGR]
[reactos.git] / reactos / dll / win32 / devmgr / advprop.c
index b4d4834..26d1097 100644 (file)
  * UPDATE HISTORY:
  *      04-04-2004  Created
  */
-#include "precomp.h"
-
-#define NDEBUG
-#include <debug.h>
-
-typedef INT_PTR (WINAPI *PPROPERTYSHEETW)(LPCPROPSHEETHEADERW);
-typedef HPROPSHEETPAGE (WINAPI *PCREATEPROPERTYSHEETPAGEW)(LPCPROPSHEETPAGEW);
-typedef BOOL (WINAPI *PDESTROYPROPERTYSHEETPAGE)(HPROPSHEETPAGE);
-
-typedef struct _DEVADVPROP_INFO
-{
-    HWND hWndGeneralPage;
-    HWND hWndParent;
-    WNDPROC ParentOldWndProc;
-    HICON hDevIcon;
 
-    HDEVINFO DeviceInfoSet;
-    SP_DEVINFO_DATA DeviceInfoData;
-    HDEVINFO CurrentDeviceInfoSet;
-    SP_DEVINFO_DATA CurrentDeviceInfoData;
-    DEVINST ParentDevInst;
-    HMACHINE hMachine;
-    LPCWSTR lpMachineName;
-
-    HINSTANCE hComCtl32;
-    PCREATEPROPERTYSHEETPAGEW pCreatePropertySheetPageW;
-    PDESTROYPROPERTYSHEETPAGE pDestroyPropertySheetPage;
-
-    DWORD PropertySheetType;
-    DWORD nDevPropSheets;
-    HPROPSHEETPAGE *DevPropSheets;
-
-    union
-    {
-        UINT Flags;
-        struct
-        {
-            UINT Extended : 1;
-            UINT FreeDevPropSheets : 1;
-            UINT CanDisable : 1;
-            UINT DeviceStarted : 1;
-            UINT DeviceUsageChanged : 1;
-            UINT CloseDevInst : 1;
-            UINT IsAdmin : 1;
-            UINT DoDefaultDevAction : 1;
-            UINT PageInitialized : 1;
-            UINT ShowRemotePages : 1;
-            UINT HasDriverPage : 1;
-            UINT HasResourcePage : 1;
-            UINT HasPowerPage : 1;
-        };
-    };
-
-    WCHAR szDevName[255];
-    WCHAR szTemp[255];
-    WCHAR szDeviceID[1];
-    /* struct may be dynamically expanded here! */
-} DEVADVPROP_INFO, *PDEVADVPROP_INFO;
-
-
-typedef struct _ENUMDRIVERFILES_CONTEXT
-{
-    HWND hDriversListView;
-    UINT nCount;
-} ENUMDRIVERFILES_CONTEXT, *PENUMDRIVERFILES_CONTEXT;
+#include "precomp.h"
 
-#define PM_INITIALIZE (WM_APP + 0x101)
+#include <winver.h>
 
 
 static UINT WINAPI
@@ -382,6 +319,7 @@ DriverDetailsDlgProc(IN HWND hwndDlg,
             {
                 LV_COLUMN lvc;
                 HWND hDriversListView;
+                WCHAR szBuffer[260];
 
                 dap = (PDEVADVPROP_INFO)lParam;
                 if (dap != NULL)
@@ -404,6 +342,13 @@ DriverDetailsDlgProc(IN HWND hwndDlg,
                     UpdateDriverDetailsDlg(hwndDlg,
                                            hDriversListView,
                                            dap);
+
+                    if (ListView_GetItemCount(hDriversListView) == 0)
+                    {
+                        if(LoadStringW(hDllInstance, IDS_NODRIVERS, szBuffer, _countof(szBuffer)))
+                            MessageBoxW(hwndDlg, szBuffer, dap->szDevName, MB_OK);
+                        EndDialog(hwndDlg, IDCANCEL);
+                    }
                 }
 
                 Ret = TRUE;
@@ -463,6 +408,71 @@ DriverDetailsDlgProc(IN HWND hwndDlg,
 }
 
 
+static
+VOID
+UpdateDriver(
+    IN HWND hwndDlg,
+    IN PDEVADVPROP_INFO dap)
+{
+    TOKEN_PRIVILEGES Privileges;
+    HANDLE hToken;
+    DWORD dwReboot;
+    BOOL NeedReboot = FALSE;
+
+    // Better use InstallDevInst:
+    //     BOOL
+    //     WINAPI
+    //     InstallDevInst(
+    //         HWND hWnd,
+    //         LPWSTR wszDeviceId,
+    //         BOOL bUpdate,
+    //         DWORD *dwReboot);
+    // See: http://comp.os.ms-windows.programmer.win32.narkive.com/J8FTd4KK/signature-of-undocumented-installdevinstex
+
+    if (!InstallDevInst(hwndDlg, dap->szDeviceID, TRUE, &dwReboot))
+        return;
+
+    if (NeedReboot == FALSE)
+        return;
+
+    //FIXME: load text from resource file
+    if (MessageBoxW(hwndDlg, L"Reboot now?", L"Reboot required", MB_YESNO | MB_ICONQUESTION) != IDYES)
+        return;
+
+    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
+    {
+        ERR("OpenProcessToken failed\n");
+        return;
+    }
+
+    /* Get the LUID for the Shutdown privilege */
+    if (!LookupPrivilegeValueW(NULL, SE_SHUTDOWN_NAME, &Privileges.Privileges[0].Luid))
+    {
+        ERR("LookupPrivilegeValue failed\n");
+        CloseHandle(hToken);
+        return;
+    }
+
+    /* Assign the Shutdown privilege to our process */
+    Privileges.PrivilegeCount = 1;
+    Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+    if (!AdjustTokenPrivileges(hToken, FALSE, &Privileges, 0, NULL, NULL))
+    {
+        ERR("AdjustTokenPrivileges failed\n");
+        CloseHandle(hToken);
+        return;
+    }
+
+    /* Finally shut down the system */
+    if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED))
+    {
+        ERR("ExitWindowsEx failed\n");
+        CloseHandle(hToken);
+    }
+}
+
+
 static VOID
 UpdateDriverDlg(IN HWND hwndDlg,
                 IN PDEVADVPROP_INFO dap)
@@ -550,14 +560,16 @@ AdvProcDriverDlgProc(IN HWND hwndDlg,
                 switch (LOWORD(wParam))
                 {
                     case IDC_DRIVERDETAILS:
-                    {
                         DialogBoxParam(hDllInstance,
                                        MAKEINTRESOURCE(IDD_DRIVERDETAILS),
                                        hwndDlg,
                                        DriverDetailsDlgProc,
                                        (ULONG_PTR)dap);
                         break;
-                    }
+
+                    case IDC_UPDATEDRIVER:
+                        UpdateDriver(hwndDlg, dap);
+                        break;
                 }
                 break;
             }
@@ -753,6 +765,9 @@ DisplayDevicePropertyText(IN PDEVADVPROP_INFO dap,
         return;
     }
 
+    if (dwType == REG_SZ)
+        dwSize += sizeof(WCHAR);
+
     lpBuffer = HeapAlloc(GetProcessHeap(),
                          HEAP_ZERO_MEMORY,
                          dwSize);
@@ -1053,6 +1068,96 @@ DisplayMatchingDeviceId(IN PDEVADVPROP_INFO dap,
 }
 
 
+static VOID
+DisplayClassCoinstallers(IN PDEVADVPROP_INFO dap,
+                          IN HWND hwndListView)
+{
+    HDEVINFO DeviceInfoSet;
+    PSP_DEVINFO_DATA DeviceInfoData;
+    WCHAR szClassGuid[45];
+    HKEY hKey = INVALID_HANDLE_VALUE;
+    DWORD dwSize;
+    DWORD dwType;
+    LPBYTE lpBuffer = NULL;
+    LPWSTR lpStr;
+    INT index;
+    INT len;
+    LONG lError;
+
+    if (dap->CurrentDeviceInfoSet != INVALID_HANDLE_VALUE)
+    {
+        DeviceInfoSet = dap->CurrentDeviceInfoSet;
+        DeviceInfoData = &dap->CurrentDeviceInfoData;
+    }
+    else
+    {
+        DeviceInfoSet = dap->DeviceInfoSet;
+        DeviceInfoData = &dap->DeviceInfoData;
+    }
+
+    dwSize = 45 * sizeof(WCHAR);
+    if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+                                          DeviceInfoData,
+                                          SPDRP_CLASSGUID,
+                                          &dwType,
+                                          (LPBYTE)szClassGuid,
+                                          dwSize,
+                                          &dwSize))
+        return;
+
+    lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                           L"SYSTEM\\CurrentControlSet\\Control\\CoDeviceInstallers",
+                           0,
+                           GENERIC_READ,
+                           &hKey);
+    if (lError != ERROR_SUCCESS)
+        return;
+
+    dwSize = 0;
+    lError = RegQueryValueEx(hKey,
+                             szClassGuid,
+                             NULL,
+                             &dwType,
+                             NULL,
+                             &dwSize);
+    if (lError != ERROR_SUCCESS)
+        goto done;
+
+    if (dwSize == 0)
+        goto done;
+
+    lpBuffer = HeapAlloc(GetProcessHeap(),
+                         HEAP_ZERO_MEMORY,
+                         dwSize);
+
+    RegQueryValueEx(hKey,
+                    szClassGuid,
+                    NULL,
+                    &dwType,
+                    lpBuffer,
+                    &dwSize);
+
+    lpStr = (LPWSTR)lpBuffer;
+    index = 0;
+    while (*lpStr != 0)
+    {
+        len = wcslen(lpStr) + 1;
+
+        SetListViewText(hwndListView, index, lpStr);
+
+        lpStr += len;
+        index++;
+    }
+
+done:
+    if (lpBuffer != NULL)
+        HeapFree(GetProcessHeap(), 0, lpBuffer);
+
+    if (hKey != INVALID_HANDLE_VALUE)
+        RegCloseKey(hKey);
+}
+
+
 static VOID
 DisplayDeviceCoinstallers(IN PDEVADVPROP_INFO dap,
                           IN HWND hwndListView)
@@ -1336,10 +1441,10 @@ DisplayDeviceProperties(IN PDEVADVPROP_INFO dap,
                                    L"Installer32");
             break;
 
-#if 0
         case 18: /* Class Coinstaller */
+            DisplayClassCoinstallers(dap,
+                                     hwndListView);
             break;
-#endif
 
         case 19: /* Device Coinstaller */
             DisplayDeviceCoinstallers(dap,
@@ -1576,8 +1681,8 @@ ApplyGeneralSettings(IN HWND hwndDlg,
         else
         {
             /* FIXME - display an error message */
-            DPRINT1("Failed to enable/disable device! LastError: %d\n",
-                    GetLastError());
+            FIXME("Failed to enable/disable device! LastError: %d\n",
+                  GetLastError());
         }
     }
     else
@@ -1610,6 +1715,8 @@ UpdateDevInfo(IN HWND hwndDlg,
     DWORD nDriverPages = 0;
     BOOL RecalcPages = FALSE;
 
+    TRACE("UpdateDevInfo()\n");
+
     hPropSheetDlg = GetParent(hwndDlg);
 
     if (dap->PageInitialized)
@@ -2005,6 +2112,7 @@ GetParentNode:
                                           dap->PropertySheetType) &&
         nDriverPages != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
     {
+TRACE("Count %d additional pages!\n", nDriverPages);
         dap->nDevPropSheets += nDriverPages;
     }
     else
@@ -2020,9 +2128,13 @@ GetParentNode:
     if (dap->Extended)
         dap->nDevPropSheets++;
 
+    if (dap->HasResourcePage)
+        dap->nDevPropSheets++;
+
     /* add the device property sheets */
     if (dap->nDevPropSheets != 0)
     {
+TRACE("Show %d pages!\n", dap->nDevPropSheets);
         dap->DevPropSheets = HeapAlloc(GetProcessHeap(),
                                        HEAP_ZERO_MEMORY,
                                        dap->nDevPropSheets * sizeof(HPROPSHEETPAGE));
@@ -2042,20 +2154,28 @@ GetParentNode:
                 {
                     /* add the property sheets */
                     for (iPage = 0;
-                         iPage != nDriverPages;
+                         iPage < nDriverPages;
                          iPage++)
                     {
+TRACE("Add page %d\n", iPage);
+TRACE("Sheet %p\n", dap->DevPropSheets[iPage]);
+
                         if (PropSheet_AddPage(hPropSheetDlg,
                                               dap->DevPropSheets[iPage]))
                         {
                             RecalcPages = TRUE;
                         }
+                        else
+                        {
+TRACE("PropSheet_AddPage() failed\n");
+                        }
                     }
 
                     dap->FreeDevPropSheets = TRUE;
                 }
                 else
                 {
+TRACE("SetupDiGetClassDevPropertySheets() failed\n");
                     /* cleanup, we were unable to get the device property sheets */
                     iPage = nDriverPages;
                     dap->nDevPropSheets -= nDriverPages;
@@ -2117,10 +2237,33 @@ GetParentNode:
                         dap->DevPropSheets[iPage] = NULL;
                     }
                 }
-
-                /* FIXME: Add the resources page */
             }
 
+            if (dap->HasResourcePage)
+            {
+                PROPSHEETPAGE pspDriver = {0};
+                pspDriver.dwSize = sizeof(PROPSHEETPAGE);
+                pspDriver.dwFlags = PSP_DEFAULT;
+                pspDriver.hInstance = hDllInstance;
+                pspDriver.pszTemplate = (LPCWSTR)MAKEINTRESOURCE(IDD_DEVICERESOURCES);
+                pspDriver.pfnDlgProc = ResourcesProcDriverDlgProc;
+                pspDriver.lParam = (LPARAM)dap;
+                dap->DevPropSheets[iPage] = dap->pCreatePropertySheetPageW(&pspDriver);
+                if (dap->DevPropSheets[iPage] != NULL)
+                {
+                    if (PropSheet_AddPage(hPropSheetDlg,
+                                          dap->DevPropSheets[iPage]))
+                    {
+                        iPage++;
+                        RecalcPages = TRUE;
+                    }
+                    else
+                    {
+                        dap->pDestroyPropertySheetPage(dap->DevPropSheets[iPage]);
+                        dap->DevPropSheets[iPage] = NULL;
+                    }
+                }
+            }
             /* FIXME: Add the power page */
         }
         else
@@ -2374,7 +2517,7 @@ DisplayDeviceAdvancedProperties(IN HWND hWndParent,
                                        0,
                                        &DevIdSize))
         {
-            DPRINT1("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
+            ERR("SetupDiGetDeviceInstanceId unexpectedly returned TRUE!\n");
             return -1;
         }
 
@@ -2866,7 +3009,7 @@ DevicePropertiesExW(IN HWND hWndParent  OPTIONAL,
 
     if (dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION))
     {
-        DPRINT1("DevPropertiesExW: Invalid flags: 0x%x\n",
+        FIXME("DevPropertiesExW: Invalid flags: 0x%x\n",
                 dwFlags & ~(DPF_EXTENDED | DPF_DEVICE_STATUS_ACTION));
         SetLastError(ERROR_INVALID_FLAGS);
         return -1;
@@ -2874,7 +3017,7 @@ DevicePropertiesExW(IN HWND hWndParent  OPTIONAL,
 
     if (bShowDevMgr)
     {
-        DPRINT("DevPropertiesExW doesn't support bShowDevMgr!\n");
+        FIXME("DevPropertiesExW doesn't support bShowDevMgr!\n");
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     }
     else
@@ -3095,7 +3238,7 @@ DeviceProperties_RunDLLW(HWND hWndParent,
                                   szDeviceID,
                                   szMachineName))
     {
-        DPRINT1("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
+        ERR("DeviceProperties_RunDLLW DeviceID: %S, MachineName: %S\n", szDeviceID, szMachineName);
         return;
     }