windows-nt/Source/XPSP1/NT/shell/osshell/snapins/devmgr/snapin/api.cpp
2020-09-26 16:20:57 +08:00

1297 lines
30 KiB
C++

/*++
Copyright (C) 1997-1999 Microsoft Corporation
Module Name:
api.cpp
Abstract:
This module implements Device Manager exported APIs.
Author:
William Hsieh (williamh) created
Revision History:
--*/
#include "devmgr.h"
#include "devgenpg.h"
#include "devdrvpg.h"
#include "devpopg.h"
#include "api.h"
#include "printer.h"
#include "tswizard.h"
STDAPI_(BOOL)
DeviceManager_ExecuteA(
HWND hwndStub,
HINSTANCE hAppInstance,
LPCWSTR lpMachineName,
int nCmdShow
)
{
try
{
CTString tstrMachineName(lpMachineName);
return DeviceManager_Execute(hwndStub,
hAppInstance,
(LPCTSTR)tstrMachineName,
nCmdShow
);
}
catch(CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return FALSE;
}
STDAPI_(BOOL)
DeviceManager_ExecuteW(
HWND hwndStub,
HINSTANCE hAppInstance,
LPCWSTR lpMachineName,
int nCmdShow
)
{
try
{
CTString tstrMachineName(lpMachineName);
return DeviceManager_Execute(hwndStub,
hAppInstance,
(LPCTSTR)tstrMachineName,
nCmdShow
);
}
catch(CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return FALSE;
}
BOOL
DeviceManager_Execute(
HWND hwndStub,
HINSTANCE hAppInstance,
LPCTSTR lpMachineName,
int nCmdShow
)
{
SHELLEXECUTEINFO sei;
TCHAR MachineOptions[MAX_PATH];
TCHAR Parameters[MAX_PATH * 2];
if (lpMachineName)
{
wsprintf(MachineOptions, DEVMGR_MACHINENAME_OPTION, lpMachineName);
}
else
{
MachineOptions[0] = _T('\0');
}
WCHAR* FilePart;
DWORD Size;
Size = SearchPath(NULL, DEVMGR_MSC_FILE, NULL, MAX_PATH, Parameters, &FilePart);
if (!Size || Size >=MAX_PATH)
{
lstrcpy(Parameters, DEVMGR_MSC_FILE);
}
lstrcat(Parameters, MMC_COMMAND_LINE);
lstrcat(Parameters, MachineOptions);
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.hwnd = hwndStub;
sei.nShow = nCmdShow;
sei.hInstApp = hAppInstance;
sei.lpFile = MMC_FILE;
sei.lpParameters = Parameters;
return ShellExecuteEx(&sei);
}
STDAPI_(BOOL)
DeviceManagerPrintA(
LPCSTR MachineName,
LPCSTR FileName,
int ReportType,
DWORD ClassGuids,
LPGUID ClassGuidList
)
{
BOOL Result;
try
{
CTString strMachineName(MachineName);
CTString strFileName(FileName);
Result = DeviceManagerDoPrint(strMachineName,
strFileName,
ReportType,
ClassGuids,
ClassGuidList
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Result = 0;
}
return Result;
}
STDAPI_(BOOL)
DeviceManagerPrintW(
LPCWSTR MachineName,
LPCWSTR FileName,
int ReportType,
DWORD ClassGuids,
LPGUID ClassGuidList
)
{
BOOL Result;
try
{
CTString strMachineName(MachineName);
CTString strFileName(FileName);
Result = DeviceManagerDoPrint(strMachineName,
strFileName,
ReportType,
ClassGuids,
ClassGuidList
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Result = FALSE;
}
return Result;
}
BOOL
DeviceManagerDoPrint(
LPCTSTR MachineName,
LPCTSTR FileName,
int ReportType,
DWORD ClassGuids,
LPGUID ClassGuidList
)
{
int PrintStatus = 0;
if (!FileName || _T('\0') == *FileName)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
TCHAR FullPathName[MAX_PATH + 1];
LPTSTR FilePart;
if (!GetFullPathName(FileName, ARRAYLEN(FullPathName), FullPathName, &FilePart))
{
return FALSE;
}
CMachine TheMachine(MachineName);
if (TheMachine.Initialize())
{
CPrinter ThePrinter;
if (ThePrinter.StartDoc(FullPathName))
{
if (0 == ReportType)
{
// print system and resource summary
PrintStatus = ThePrinter.PrintResourceSummary(TheMachine);
} else if (1 == ReportType)
{
// print selected classes
CClass* pClass;
for (DWORD i = 0; i < ClassGuids; i++)
{
pClass = TheMachine.ClassGuidToClass(&ClassGuidList[i]);
if (pClass)
{
PrintStatus = ThePrinter.PrintClass(pClass);
}
}
} else if (2 == ReportType)
{
// print resource/system summary and all device information
PrintStatus = ThePrinter.PrintAll(TheMachine);
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
}
ThePrinter.EndDoc();
}
}
return 0 != PrintStatus;
}
BOOL
AddPageCallback(
HPROPSHEETPAGE hPage,
LPARAM lParam
)
{
CPropSheetData* ppsData = (CPropSheetData*)lParam;
ASSERT(ppsData);
return ppsData->InsertPage(hPage);
}
void
ReportCmdLineError(
HWND hwndParent,
int ErrorStringID,
LPCTSTR Caption
)
{
TCHAR Title[LINE_LEN + 1];
TCHAR Msg[LINE_LEN + 1];
::LoadString(g_hInstance, ErrorStringID, Msg, ARRAYLEN(Msg));
if (!Caption)
{
::LoadString(g_hInstance, IDS_NAME_DEVMGR,
Title, ARRAYLEN(Title));
Caption = Title;
}
MessageBox(hwndParent, Msg, Caption, MB_OK | MB_ICONERROR);
}
STDAPI_(void)
DeviceProperties_RunDLLA(
HWND hwndStub,
HINSTANCE hAppInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
try
{
CTString tstrCmdLine(lpCmdLine);
DeviceProperties_RunDLL(hwndStub,
hAppInstance,
(LPCTSTR)tstrCmdLine,
nCmdShow
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
}
}
STDAPI_(void)
DeviceProperties_RunDLLW(
HWND hwndStub,
HINSTANCE hAppInstance,
LPWSTR lpCmdLine,
int nCmdShow
)
{
try
{
CTString tstrCmdLine(lpCmdLine);
DeviceProperties_RunDLL(hwndStub,
hAppInstance,
(LPCTSTR)tstrCmdLine,
nCmdShow
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
}
}
void
DeviceProperties_RunDLL(
HWND hwndStub,
HINSTANCE hAppInstance,
LPCTSTR lpCmdLine,
int nCmdShow
)
{
try
{
CRunDLLCommandLine CmdLine;
CmdLine.ParseCommandLine(lpCmdLine);
if (NULL == CmdLine.GetDeviceID())
{
ReportCmdLineError(hwndStub, IDS_NO_DEVICEID);
return;
}
DevicePropertiesEx(hwndStub,
CmdLine.GetMachineName(),
CmdLine.GetDeviceID(),
CmdLine.GetFlags(),
CmdLine.ToShowDeviceTree()
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
return;
}
}
STDAPI_(int)
DevicePropertiesA(
HWND hwndParent,
LPCSTR MachineName,
LPCSTR DeviceID,
BOOL ShowDeviceTree
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceID);
return DevicePropertiesEx(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID,
DEVPROP_SHOW_RESOURCE_TAB,
ShowDeviceTree
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
STDAPI_(int)
DevicePropertiesW(
HWND hwndParent,
LPCWSTR MachineName,
LPCWSTR DeviceID,
BOOL ShowDeviceTree
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceID);
return DevicePropertiesEx(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID,
DEVPROP_SHOW_RESOURCE_TAB,
ShowDeviceTree
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
STDAPI_(int)
DevicePropertiesExA(
HWND hwndParent,
LPCSTR MachineName,
LPCSTR DeviceID,
DWORD Flags,
BOOL ShowDeviceTree
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceID);
return DevicePropertiesEx(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID,
Flags,
ShowDeviceTree
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
STDAPI_(int)
DevicePropertiesExW(
HWND hwndParent,
LPCWSTR MachineName,
LPCWSTR DeviceID,
DWORD Flags,
BOOL ShowDeviceTree
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceID);
return DevicePropertiesEx(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID,
Flags,
ShowDeviceTree
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
int
DevicePropertiesEx(
HWND hwndParent,
LPCTSTR MachineName,
LPCTSTR DeviceID,
DWORD Flags,
BOOL ShowDeviceTree
)
{
HPROPSHEETPAGE hPage;
DWORD DiFlags;
DWORD DiFlagsEx;
//
// Verify that a DeviceID was passed in unless they want to show the
// whole device tree.
//
if ((!DeviceID || (TEXT('\0') == *DeviceID)) && !ShowDeviceTree) {
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
//
// Verify that valid flags are passed in
//
if (Flags &~ DEVPROP_BITS) {
SetLastError(ERROR_INVALID_FLAGS);
return -1;
}
if (ShowDeviceTree) {
return PropertyRunDeviceTree(hwndParent, MachineName, DeviceID);
}
int Result = -1;
CDeviceGeneralPage* pGenPage = NULL;
CDeviceDriverPage* pDrvPage = NULL;
CDevice* pDevice;
PVOID Context;
try {
CMachine TheMachine(MachineName);
// create the machine just for this device
if (!TheMachine.Initialize(hwndParent, DeviceID)) {
return -1;
}
if (!TheMachine.GetFirstDevice(&pDevice, Context)) {
SetLastError(SPAPI_E_NO_SUCH_DEVINST);
return -1;
}
//
// If the troubleshooter should be launched then set the appropriate
// BOOL inside of the pDevice class.
//
if (Flags & DEVPROP_LAUNCH_TROUBLESHOOTER) {
pDevice->m_bLaunchTroubleShooter = TRUE;
}
CPropSheetData& psd = pDevice->m_psd;
//
// Initialize CPropSheetData without ConsoleHandle
//
if (psd.Create(g_hInstance, hwndParent, MAX_PROP_PAGES, 0l)) {
psd.m_psh.pszCaption = pDevice->GetDisplayName();
//
// Add any class/device specific property pages.
//
TheMachine.DiGetClassDevPropertySheet(*pDevice, &psd.m_psh,
MAX_PROP_PAGES,
TheMachine.IsLocal() ?
DIGCDP_FLAG_ADVANCED :
DIGCDP_FLAG_REMOTE_ADVANCED);
//
// Add the general tab
//
DiFlags = TheMachine.DiGetFlags(*pDevice);
DiFlagsEx = TheMachine.DiGetExFlags(*pDevice);
if (DiFlags & DI_GENERALPAGE_ADDED) {
TCHAR szText[MAX_PATH];
LoadResourceString(IDS_GENERAL_PAGE_WARNING, szText,
ARRAYLEN(szText));
MessageBox(hwndParent, szText, pDevice->GetDisplayName(),
MB_ICONEXCLAMATION | MB_OK);
//
// fall through to create our general page.
//
}
SafePtr<CDeviceGeneralPage> GenPagePtr;
CDeviceGeneralPage* pGeneralPage = new CDeviceGeneralPage();
GenPagePtr.Attach(pGeneralPage);
hPage = pGeneralPage->Create(pDevice);
if (hPage) {
if (psd.InsertPage(hPage, 0)) {
GenPagePtr.Detach();
}
else {
::DestroyPropertySheetPage(hPage);
}
}
//
// Add the driver tab
//
if (!(DiFlags & DI_DRIVERPAGE_ADDED)) {
SafePtr<CDeviceDriverPage> DrvPagePtr;
CDeviceDriverPage* pDriverPage = new CDeviceDriverPage();
DrvPagePtr.Attach(pDriverPage);
hPage = pDriverPage->Create(pDevice);
if (hPage) {
if (psd.InsertPage(hPage)) {
DrvPagePtr.Detach();
}
else {
::DestroyPropertySheetPage(hPage);
}
}
}
//
// Add the resource tab
//
if ((Flags & DEVPROP_SHOW_RESOURCE_TAB) &&
pDevice->HasResources() &&
!(DiFlags & DI_RESOURCEPAGE_ADDED)) {
TheMachine.DiGetExtensionPropSheetPage(*pDevice,
AddPageCallback,
SPPSR_SELECT_DEVICE_RESOURCES,
(LPARAM)&psd
);
}
#ifndef _WIN64
//
// Add the power tab if this is the local machine
//
if (TheMachine.IsLocal() && !(DiFlagsEx & DI_FLAGSEX_POWERPAGE_ADDED))
{
//
// Check if the device support power management
//
CPowerShutdownEnable ShutdownEnable;
CPowerWakeEnable WakeEnable;
if (ShutdownEnable.Open(pDevice->GetDeviceID()) || WakeEnable.Open(pDevice->GetDeviceID())) {
ShutdownEnable.Close();
WakeEnable.Close();
SafePtr<CDevicePowerMgmtPage> PowerMgmtPagePtr;
CDevicePowerMgmtPage* pPowerPage = new CDevicePowerMgmtPage;
PowerMgmtPagePtr.Attach(pPowerPage);
hPage = pPowerPage->Create(pDevice);
if (hPage) {
if (psd.InsertPage(hPage)) {
PowerMgmtPagePtr.Detach();
}
else {
::DestroyPropertySheetPage(hPage);
}
}
}
}
#endif
//
// Add any Bus property pages if this is the local machine
//
if (TheMachine.IsLocal())
{
CBusPropPageProvider* pBusPropPageProvider = new CBusPropPageProvider();
SafePtr<CBusPropPageProvider> ProviderPtr;
ProviderPtr.Attach(pBusPropPageProvider);
if (pBusPropPageProvider->EnumPages(pDevice, &psd)) {
psd.AddProvider(pBusPropPageProvider);
ProviderPtr.Detach();
}
}
Result = (int)psd.DoSheet();
if (-1 != Result) {
if (TheMachine.DiGetExFlags(*pDevice) & DI_FLAGSEX_PROPCHANGE_PENDING) {
//
// property change pending, issue a DICS_PROPERTYCHANGE
// to the class installer
//
SP_PROPCHANGE_PARAMS pcp;
pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
pcp.Scope = DICS_FLAG_GLOBAL;
pcp.StateChange = DICS_PROPCHANGE;
TheMachine.DiSetClassInstallParams(*pDevice,
&pcp.ClassInstallHeader,
sizeof(pcp)
);
TheMachine.DiCallClassInstaller(DIF_PROPERTYCHANGE, *pDevice);
TheMachine.DiTurnOnDiFlags(*pDevice, DI_PROPERTIES_CHANGE);
TheMachine.DiTurnOffDiExFlags(*pDevice, DI_FLAGSEX_PROPCHANGE_PENDING);
}
//
// Merge restart/reboot flags
//
DiFlags = TheMachine.DiGetFlags(*pDevice);
if (DI_NEEDREBOOT & DiFlags) {
Result |= ID_PSREBOOTSYSTEM;
}
if (DI_NEEDRESTART & DiFlags) {
Result |= ID_PSRESTARTWINDOWS;
}
}
}
}
catch (CMemoryException* e) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return -1;
}
STDAPI_(UINT)
DeviceProblemTextA(
HMACHINE hMachine,
DEVNODE DevNode,
ULONG ProblemNumber,
LPSTR Buffer,
UINT BufferSize
)
{
#ifndef UNICODE
return GetDeviceProblemText(hMachine, DevNode, ProblemNumber, Buffer, BufferSize);
#else
WCHAR* wchBuffer = NULL;
UINT RealSize = 0;
if (BufferSize && !Buffer)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (BufferSize)
{
try
{
wchBuffer = new WCHAR[BufferSize];
}
catch (CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
}
RealSize = GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
wchBuffer, BufferSize);
if (RealSize && BufferSize > RealSize)
{
ASSERT(wchBuffer);
RealSize = WideCharToMultiByte(CP_ACP, 0, wchBuffer, RealSize,
Buffer, BufferSize, NULL, NULL);
Buffer[RealSize] = '\0';
}
if (wchBuffer)
{
delete wchBuffer;
}
return RealSize;
#endif
}
STDAPI_(UINT)
DeviceProblemTextW(
HMACHINE hMachine,
DEVNODE DevNode,
ULONG ProblemNumber,
LPWSTR Buffer,
UINT BufferSize
)
{
#ifdef UNICODE
return GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
Buffer, BufferSize);
#else
CHAR* chBuffer = NULL;
UINT RealSize = 0;
if (BufferSize && !Buffer)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
if (BufferSize)
{
try
{
chBuffer = new CHAR[BufferSize];
}
catch (CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
}
RealSize = GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
chBuffer, BufferSize);
if (RealSize && BufferSize > RealSize)
{
ASSERT(chBuffer);
RealSize = MultiByteToWideChar((CP_ACP, 0, chBuffer, RealSize,
Buffer, BufferSize);
Buffer[RealSize] = UNICODE_NULL;
}
if (chBuffer)
{
delete chBuffer;
}
return RealSize;
#endif
}
int
PropertyRunDeviceTree(
HWND hwndParent,
LPCTSTR MachineName,
LPCTSTR DeviceID
)
{
SHELLEXECUTEINFOW sei;
TCHAR MachineOptions[MAX_PATH];
TCHAR DeviceIdOptions[MAX_PATH*2];
TCHAR CommandOptions[MAX_PATH];
TCHAR Parameters[MAX_PATH * 3];
TCHAR* FilePart;
DWORD Size;
Size = SearchPath(NULL, DEVMGR_MSC_FILE, NULL, MAX_PATH, Parameters, &FilePart);
if (!Size || Size >=MAX_PATH)
{
lstrcpy(Parameters, DEVMGR_MSC_FILE);
}
lstrcat(Parameters, MMC_COMMAND_LINE);
if (MachineName)
{
wsprintf(MachineOptions, DEVMGR_MACHINENAME_OPTION, MachineName);
lstrcat(Parameters, MachineOptions);
}
if (DeviceID)
{
wsprintf(DeviceIdOptions, DEVMGR_DEVICEID_OPTION, DeviceID);
wsprintf(CommandOptions, DEVMGR_COMMAND_OPTION, DEVMGR_CMD_PROPERTY);
lstrcat(Parameters, DeviceIdOptions);
lstrcat(Parameters, CommandOptions);
}
// no deviceid, no command.
memset(&sei, 0, sizeof(sei));
sei.cbSize = sizeof(sei);
sei.hwnd = hwndParent;
sei.nShow = SW_NORMAL;
sei.hInstApp = g_hInstance;
sei.lpFile = MMC_FILE;
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpParameters = Parameters;
if (ShellExecuteEx(&sei) && sei.hProcess)
{
WaitForSingleObject(sei.hProcess, INFINITE);
return 1;
}
return 0;
}
STDAPI_(void)
DeviceProblenWizard_RunDLLA(
HWND hwndStub,
HINSTANCE hAppInstance,
LPSTR lpCmdLine,
int nCmdShow
)
{
try
{
CTString tstrCmdLine(lpCmdLine);
DeviceProblenWizard_RunDLL(hwndStub,
hAppInstance,
(LPCTSTR)tstrCmdLine,
nCmdShow
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
}
}
STDAPI_(void)
DeviceProblenWizard_RunDLLW(
HWND hwndStub,
HINSTANCE hAppInstance,
LPWSTR lpCmdLine,
int nCmdShow
)
{
try
{
CTString tstrCmdLine(lpCmdLine);
DeviceProblenWizard_RunDLL(hwndStub,
hAppInstance,
(LPCTSTR)tstrCmdLine,
nCmdShow
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
}
}
void
DeviceProblenWizard_RunDLL(
HWND hwndStub,
HINSTANCE hAppInstance,
LPCTSTR lpCmdLine,
int nCmdShow
)
{
try
{
CRunDLLCommandLine CmdLine;
CmdLine.ParseCommandLine(lpCmdLine);
if (NULL == CmdLine.GetDeviceID())
{
ReportCmdLineError(hwndStub, IDS_NO_DEVICEID);
return;
}
DeviceProblemWizard(hwndStub,
CmdLine.GetMachineName(),
CmdLine.GetDeviceID()
);
}
catch (CMemoryException* e)
{
e->ReportError();
e->Delete();
return;
}
}
STDAPI_(int)
DeviceProblemWizardA(
HWND hwndParent,
LPCSTR MachineName,
LPCSTR DeviceId
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceId(DeviceId);
return DeviceProblemWizard(hwndParent, tstrMachineName, tstrDeviceId);
}
catch(CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return 0;
}
STDAPI_(int)
DeviceProblemWizardW(
HWND hwndParent,
LPCWSTR MachineName,
LPCWSTR DeviceId
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceId(DeviceId);
return DeviceProblemWizard(hwndParent, tstrMachineName, tstrDeviceId);
}
catch (CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return 0;
}
int
DeviceProblemWizard(
HWND hwndParent,
LPCTSTR MachineName,
LPCTSTR DeviceId
)
{
DWORD Problem, Status;
try
{
if (!DeviceId)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
CMachine TheMachine(MachineName);
// create the machine just for this device
if (!TheMachine.Initialize(hwndParent, DeviceId))
{
return 0;
}
PVOID Context;
CDevice* pDevice;
if (!TheMachine.GetFirstDevice(&pDevice, Context))
{
SetLastError(SPAPI_E_NO_SUCH_DEVINST);
return 0;
}
if (pDevice->GetStatus(&Status, &Problem)) {
// if the device is a phantom device, use the CM_PROB_DEVICE_NOT_THERE
if (pDevice->IsPhantom()) {
Problem = CM_PROB_PHANTOM;
}
// if the device is not started and no problem is assigned to it
// fake the problem number to be failed start.
if (!(Status & DN_STARTED) && !Problem && pDevice->IsRAW()) {
Problem = CM_PROB_FAILED_START;
}
}
CProblemAgent* pProblemAgent = new CProblemAgent(pDevice, Problem, TRUE);
if (pProblemAgent) {
pProblemAgent->FixIt(hwndParent);
}
return TRUE;
}
catch(CMemoryException* e)
{
e->Delete();
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return 0;
}
// This API creates a property sheet and asks the given device's property
// provider to add any advanced pages to the property sheet.
// The purpose of this API is for application to manage device advanced
// properties. Standard device property pages(General, Driver, Resource,
// Power, Bus) are not added.
//
// INPUT:
// hwndParent -- the caller's window handle to be used as the owner
// window of any widnows this function may create
// MachineName -- optional machine name. If given, it must be in
// its fully qualified form. NULL means local machine
// DeviceId -- device id.
// OUTPUT:
// See PropertySheet API for the return value
//
STDAPI_(int)
DeviceAdvancedPropertiesA(
HWND hwndParent,
LPTSTR MachineName,
LPTSTR DeviceId
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceId);
return DeviceAdvancedProperties(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
STDAPI_(int)
DeviceAdvancedPropertiesW(
HWND hwndParent,
LPCWSTR MachineName,
LPCWSTR DeviceId
)
{
try
{
CTString tstrMachineName(MachineName);
CTString tstrDeviceID(DeviceId);
return DeviceAdvancedProperties(hwndParent,
(LPCTSTR)tstrMachineName,
(LPCTSTR)tstrDeviceID
);
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return 0;
}
int DeviceAdvancedProperties(
HWND hwndParent,
LPCTSTR MachineName,
LPCTSTR DeviceId
)
{
if (!DeviceId)
{
SetLastError(ERROR_INVALID_PARAMETER);
return -1;
}
CMachine TheMachine(MachineName);
CDevice* pDevice;
PVOID Context;
try
{
if (TheMachine.Initialize(hwndParent, DeviceId) &&
TheMachine.GetFirstDevice(&pDevice, Context))
{
TheMachine.EnableRefresh(FALSE);
CPropSheetData& psd = pDevice->m_psd;
//initialize CPropSheetData without ConsoleHandle
if (psd.Create(g_hInstance, hwndParent, MAX_PROP_PAGES, 0l))
{
psd.m_psh.pszCaption = pDevice->GetDisplayName();
if (TheMachine.DiGetClassDevPropertySheet(*pDevice, &psd.m_psh,
MAX_PROP_PAGES,
TheMachine.IsLocal() ?
DIGCDP_FLAG_ADVANCED :
DIGCDP_FLAG_REMOTE_ADVANCED))
{
int Result = (int)psd.DoSheet();
if (-1 != Result)
{
// merge restart/reboot flags
DWORD DiFlags = TheMachine.DiGetFlags(*pDevice);
if (DI_NEEDREBOOT & DiFlags)
{
Result |= ID_PSREBOOTSYSTEM;
}
if (DI_NEEDRESTART & DiFlags)
{
Result |= ID_PSRESTARTWINDOWS;
}
}
return Result;
}
}
}
}
catch (CMemoryException* e)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
e->Delete();
}
return -1;
}