Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1296 lines
30 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. api.cpp
  5. Abstract:
  6. This module implements Device Manager exported APIs.
  7. Author:
  8. William Hsieh (williamh) created
  9. Revision History:
  10. --*/
  11. #include "devmgr.h"
  12. #include "devgenpg.h"
  13. #include "devdrvpg.h"
  14. #include "devpopg.h"
  15. #include "api.h"
  16. #include "printer.h"
  17. #include "tswizard.h"
  18. STDAPI_(BOOL)
  19. DeviceManager_ExecuteA(
  20. HWND hwndStub,
  21. HINSTANCE hAppInstance,
  22. LPCWSTR lpMachineName,
  23. int nCmdShow
  24. )
  25. {
  26. try
  27. {
  28. CTString tstrMachineName(lpMachineName);
  29. return DeviceManager_Execute(hwndStub,
  30. hAppInstance,
  31. (LPCTSTR)tstrMachineName,
  32. nCmdShow
  33. );
  34. }
  35. catch(CMemoryException* e)
  36. {
  37. e->Delete();
  38. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  39. }
  40. return FALSE;
  41. }
  42. STDAPI_(BOOL)
  43. DeviceManager_ExecuteW(
  44. HWND hwndStub,
  45. HINSTANCE hAppInstance,
  46. LPCWSTR lpMachineName,
  47. int nCmdShow
  48. )
  49. {
  50. try
  51. {
  52. CTString tstrMachineName(lpMachineName);
  53. return DeviceManager_Execute(hwndStub,
  54. hAppInstance,
  55. (LPCTSTR)tstrMachineName,
  56. nCmdShow
  57. );
  58. }
  59. catch(CMemoryException* e)
  60. {
  61. e->Delete();
  62. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  63. }
  64. return FALSE;
  65. }
  66. BOOL
  67. DeviceManager_Execute(
  68. HWND hwndStub,
  69. HINSTANCE hAppInstance,
  70. LPCTSTR lpMachineName,
  71. int nCmdShow
  72. )
  73. {
  74. SHELLEXECUTEINFO sei;
  75. TCHAR MachineOptions[MAX_PATH];
  76. TCHAR Parameters[MAX_PATH * 2];
  77. if (lpMachineName)
  78. {
  79. wsprintf(MachineOptions, DEVMGR_MACHINENAME_OPTION, lpMachineName);
  80. }
  81. else
  82. {
  83. MachineOptions[0] = _T('\0');
  84. }
  85. WCHAR* FilePart;
  86. DWORD Size;
  87. Size = SearchPath(NULL, DEVMGR_MSC_FILE, NULL, MAX_PATH, Parameters, &FilePart);
  88. if (!Size || Size >=MAX_PATH)
  89. {
  90. lstrcpy(Parameters, DEVMGR_MSC_FILE);
  91. }
  92. lstrcat(Parameters, MMC_COMMAND_LINE);
  93. lstrcat(Parameters, MachineOptions);
  94. memset(&sei, 0, sizeof(sei));
  95. sei.cbSize = sizeof(sei);
  96. sei.hwnd = hwndStub;
  97. sei.nShow = nCmdShow;
  98. sei.hInstApp = hAppInstance;
  99. sei.lpFile = MMC_FILE;
  100. sei.lpParameters = Parameters;
  101. return ShellExecuteEx(&sei);
  102. }
  103. STDAPI_(BOOL)
  104. DeviceManagerPrintA(
  105. LPCSTR MachineName,
  106. LPCSTR FileName,
  107. int ReportType,
  108. DWORD ClassGuids,
  109. LPGUID ClassGuidList
  110. )
  111. {
  112. BOOL Result;
  113. try
  114. {
  115. CTString strMachineName(MachineName);
  116. CTString strFileName(FileName);
  117. Result = DeviceManagerDoPrint(strMachineName,
  118. strFileName,
  119. ReportType,
  120. ClassGuids,
  121. ClassGuidList
  122. );
  123. }
  124. catch (CMemoryException* e)
  125. {
  126. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  127. Result = 0;
  128. }
  129. return Result;
  130. }
  131. STDAPI_(BOOL)
  132. DeviceManagerPrintW(
  133. LPCWSTR MachineName,
  134. LPCWSTR FileName,
  135. int ReportType,
  136. DWORD ClassGuids,
  137. LPGUID ClassGuidList
  138. )
  139. {
  140. BOOL Result;
  141. try
  142. {
  143. CTString strMachineName(MachineName);
  144. CTString strFileName(FileName);
  145. Result = DeviceManagerDoPrint(strMachineName,
  146. strFileName,
  147. ReportType,
  148. ClassGuids,
  149. ClassGuidList
  150. );
  151. }
  152. catch (CMemoryException* e)
  153. {
  154. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  155. Result = FALSE;
  156. }
  157. return Result;
  158. }
  159. BOOL
  160. DeviceManagerDoPrint(
  161. LPCTSTR MachineName,
  162. LPCTSTR FileName,
  163. int ReportType,
  164. DWORD ClassGuids,
  165. LPGUID ClassGuidList
  166. )
  167. {
  168. int PrintStatus = 0;
  169. if (!FileName || _T('\0') == *FileName)
  170. {
  171. SetLastError(ERROR_INVALID_PARAMETER);
  172. return FALSE;
  173. }
  174. TCHAR FullPathName[MAX_PATH + 1];
  175. LPTSTR FilePart;
  176. if (!GetFullPathName(FileName, ARRAYLEN(FullPathName), FullPathName, &FilePart))
  177. {
  178. return FALSE;
  179. }
  180. CMachine TheMachine(MachineName);
  181. if (TheMachine.Initialize())
  182. {
  183. CPrinter ThePrinter;
  184. if (ThePrinter.StartDoc(FullPathName))
  185. {
  186. if (0 == ReportType)
  187. {
  188. // print system and resource summary
  189. PrintStatus = ThePrinter.PrintResourceSummary(TheMachine);
  190. } else if (1 == ReportType)
  191. {
  192. // print selected classes
  193. CClass* pClass;
  194. for (DWORD i = 0; i < ClassGuids; i++)
  195. {
  196. pClass = TheMachine.ClassGuidToClass(&ClassGuidList[i]);
  197. if (pClass)
  198. {
  199. PrintStatus = ThePrinter.PrintClass(pClass);
  200. }
  201. }
  202. } else if (2 == ReportType)
  203. {
  204. // print resource/system summary and all device information
  205. PrintStatus = ThePrinter.PrintAll(TheMachine);
  206. }
  207. else
  208. {
  209. SetLastError(ERROR_INVALID_PARAMETER);
  210. }
  211. ThePrinter.EndDoc();
  212. }
  213. }
  214. return 0 != PrintStatus;
  215. }
  216. BOOL
  217. AddPageCallback(
  218. HPROPSHEETPAGE hPage,
  219. LPARAM lParam
  220. )
  221. {
  222. CPropSheetData* ppsData = (CPropSheetData*)lParam;
  223. ASSERT(ppsData);
  224. return ppsData->InsertPage(hPage);
  225. }
  226. void
  227. ReportCmdLineError(
  228. HWND hwndParent,
  229. int ErrorStringID,
  230. LPCTSTR Caption
  231. )
  232. {
  233. TCHAR Title[LINE_LEN + 1];
  234. TCHAR Msg[LINE_LEN + 1];
  235. ::LoadString(g_hInstance, ErrorStringID, Msg, ARRAYLEN(Msg));
  236. if (!Caption)
  237. {
  238. ::LoadString(g_hInstance, IDS_NAME_DEVMGR,
  239. Title, ARRAYLEN(Title));
  240. Caption = Title;
  241. }
  242. MessageBox(hwndParent, Msg, Caption, MB_OK | MB_ICONERROR);
  243. }
  244. STDAPI_(void)
  245. DeviceProperties_RunDLLA(
  246. HWND hwndStub,
  247. HINSTANCE hAppInstance,
  248. LPSTR lpCmdLine,
  249. int nCmdShow
  250. )
  251. {
  252. try
  253. {
  254. CTString tstrCmdLine(lpCmdLine);
  255. DeviceProperties_RunDLL(hwndStub,
  256. hAppInstance,
  257. (LPCTSTR)tstrCmdLine,
  258. nCmdShow
  259. );
  260. }
  261. catch (CMemoryException* e)
  262. {
  263. e->ReportError();
  264. e->Delete();
  265. }
  266. }
  267. STDAPI_(void)
  268. DeviceProperties_RunDLLW(
  269. HWND hwndStub,
  270. HINSTANCE hAppInstance,
  271. LPWSTR lpCmdLine,
  272. int nCmdShow
  273. )
  274. {
  275. try
  276. {
  277. CTString tstrCmdLine(lpCmdLine);
  278. DeviceProperties_RunDLL(hwndStub,
  279. hAppInstance,
  280. (LPCTSTR)tstrCmdLine,
  281. nCmdShow
  282. );
  283. }
  284. catch (CMemoryException* e)
  285. {
  286. e->ReportError();
  287. e->Delete();
  288. }
  289. }
  290. void
  291. DeviceProperties_RunDLL(
  292. HWND hwndStub,
  293. HINSTANCE hAppInstance,
  294. LPCTSTR lpCmdLine,
  295. int nCmdShow
  296. )
  297. {
  298. try
  299. {
  300. CRunDLLCommandLine CmdLine;
  301. CmdLine.ParseCommandLine(lpCmdLine);
  302. if (NULL == CmdLine.GetDeviceID())
  303. {
  304. ReportCmdLineError(hwndStub, IDS_NO_DEVICEID);
  305. return;
  306. }
  307. DevicePropertiesEx(hwndStub,
  308. CmdLine.GetMachineName(),
  309. CmdLine.GetDeviceID(),
  310. CmdLine.GetFlags(),
  311. CmdLine.ToShowDeviceTree()
  312. );
  313. }
  314. catch (CMemoryException* e)
  315. {
  316. e->ReportError();
  317. e->Delete();
  318. return;
  319. }
  320. }
  321. STDAPI_(int)
  322. DevicePropertiesA(
  323. HWND hwndParent,
  324. LPCSTR MachineName,
  325. LPCSTR DeviceID,
  326. BOOL ShowDeviceTree
  327. )
  328. {
  329. try
  330. {
  331. CTString tstrMachineName(MachineName);
  332. CTString tstrDeviceID(DeviceID);
  333. return DevicePropertiesEx(hwndParent,
  334. (LPCTSTR)tstrMachineName,
  335. (LPCTSTR)tstrDeviceID,
  336. DEVPROP_SHOW_RESOURCE_TAB,
  337. ShowDeviceTree
  338. );
  339. }
  340. catch (CMemoryException* e)
  341. {
  342. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  343. e->Delete();
  344. }
  345. return 0;
  346. }
  347. STDAPI_(int)
  348. DevicePropertiesW(
  349. HWND hwndParent,
  350. LPCWSTR MachineName,
  351. LPCWSTR DeviceID,
  352. BOOL ShowDeviceTree
  353. )
  354. {
  355. try
  356. {
  357. CTString tstrMachineName(MachineName);
  358. CTString tstrDeviceID(DeviceID);
  359. return DevicePropertiesEx(hwndParent,
  360. (LPCTSTR)tstrMachineName,
  361. (LPCTSTR)tstrDeviceID,
  362. DEVPROP_SHOW_RESOURCE_TAB,
  363. ShowDeviceTree
  364. );
  365. }
  366. catch (CMemoryException* e)
  367. {
  368. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  369. e->Delete();
  370. }
  371. return 0;
  372. }
  373. STDAPI_(int)
  374. DevicePropertiesExA(
  375. HWND hwndParent,
  376. LPCSTR MachineName,
  377. LPCSTR DeviceID,
  378. DWORD Flags,
  379. BOOL ShowDeviceTree
  380. )
  381. {
  382. try
  383. {
  384. CTString tstrMachineName(MachineName);
  385. CTString tstrDeviceID(DeviceID);
  386. return DevicePropertiesEx(hwndParent,
  387. (LPCTSTR)tstrMachineName,
  388. (LPCTSTR)tstrDeviceID,
  389. Flags,
  390. ShowDeviceTree
  391. );
  392. }
  393. catch (CMemoryException* e)
  394. {
  395. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  396. e->Delete();
  397. }
  398. return 0;
  399. }
  400. STDAPI_(int)
  401. DevicePropertiesExW(
  402. HWND hwndParent,
  403. LPCWSTR MachineName,
  404. LPCWSTR DeviceID,
  405. DWORD Flags,
  406. BOOL ShowDeviceTree
  407. )
  408. {
  409. try
  410. {
  411. CTString tstrMachineName(MachineName);
  412. CTString tstrDeviceID(DeviceID);
  413. return DevicePropertiesEx(hwndParent,
  414. (LPCTSTR)tstrMachineName,
  415. (LPCTSTR)tstrDeviceID,
  416. Flags,
  417. ShowDeviceTree
  418. );
  419. }
  420. catch (CMemoryException* e)
  421. {
  422. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  423. e->Delete();
  424. }
  425. return 0;
  426. }
  427. int
  428. DevicePropertiesEx(
  429. HWND hwndParent,
  430. LPCTSTR MachineName,
  431. LPCTSTR DeviceID,
  432. DWORD Flags,
  433. BOOL ShowDeviceTree
  434. )
  435. {
  436. HPROPSHEETPAGE hPage;
  437. DWORD DiFlags;
  438. DWORD DiFlagsEx;
  439. //
  440. // Verify that a DeviceID was passed in unless they want to show the
  441. // whole device tree.
  442. //
  443. if ((!DeviceID || (TEXT('\0') == *DeviceID)) && !ShowDeviceTree) {
  444. SetLastError(ERROR_INVALID_PARAMETER);
  445. return -1;
  446. }
  447. //
  448. // Verify that valid flags are passed in
  449. //
  450. if (Flags &~ DEVPROP_BITS) {
  451. SetLastError(ERROR_INVALID_FLAGS);
  452. return -1;
  453. }
  454. if (ShowDeviceTree) {
  455. return PropertyRunDeviceTree(hwndParent, MachineName, DeviceID);
  456. }
  457. int Result = -1;
  458. CDeviceGeneralPage* pGenPage = NULL;
  459. CDeviceDriverPage* pDrvPage = NULL;
  460. CDevice* pDevice;
  461. PVOID Context;
  462. try {
  463. CMachine TheMachine(MachineName);
  464. // create the machine just for this device
  465. if (!TheMachine.Initialize(hwndParent, DeviceID)) {
  466. return -1;
  467. }
  468. if (!TheMachine.GetFirstDevice(&pDevice, Context)) {
  469. SetLastError(SPAPI_E_NO_SUCH_DEVINST);
  470. return -1;
  471. }
  472. //
  473. // If the troubleshooter should be launched then set the appropriate
  474. // BOOL inside of the pDevice class.
  475. //
  476. if (Flags & DEVPROP_LAUNCH_TROUBLESHOOTER) {
  477. pDevice->m_bLaunchTroubleShooter = TRUE;
  478. }
  479. CPropSheetData& psd = pDevice->m_psd;
  480. //
  481. // Initialize CPropSheetData without ConsoleHandle
  482. //
  483. if (psd.Create(g_hInstance, hwndParent, MAX_PROP_PAGES, 0l)) {
  484. psd.m_psh.pszCaption = pDevice->GetDisplayName();
  485. //
  486. // Add any class/device specific property pages.
  487. //
  488. TheMachine.DiGetClassDevPropertySheet(*pDevice, &psd.m_psh,
  489. MAX_PROP_PAGES,
  490. TheMachine.IsLocal() ?
  491. DIGCDP_FLAG_ADVANCED :
  492. DIGCDP_FLAG_REMOTE_ADVANCED);
  493. //
  494. // Add the general tab
  495. //
  496. DiFlags = TheMachine.DiGetFlags(*pDevice);
  497. DiFlagsEx = TheMachine.DiGetExFlags(*pDevice);
  498. if (DiFlags & DI_GENERALPAGE_ADDED) {
  499. TCHAR szText[MAX_PATH];
  500. LoadResourceString(IDS_GENERAL_PAGE_WARNING, szText,
  501. ARRAYLEN(szText));
  502. MessageBox(hwndParent, szText, pDevice->GetDisplayName(),
  503. MB_ICONEXCLAMATION | MB_OK);
  504. //
  505. // fall through to create our general page.
  506. //
  507. }
  508. SafePtr<CDeviceGeneralPage> GenPagePtr;
  509. CDeviceGeneralPage* pGeneralPage = new CDeviceGeneralPage();
  510. GenPagePtr.Attach(pGeneralPage);
  511. hPage = pGeneralPage->Create(pDevice);
  512. if (hPage) {
  513. if (psd.InsertPage(hPage, 0)) {
  514. GenPagePtr.Detach();
  515. }
  516. else {
  517. ::DestroyPropertySheetPage(hPage);
  518. }
  519. }
  520. //
  521. // Add the driver tab
  522. //
  523. if (!(DiFlags & DI_DRIVERPAGE_ADDED)) {
  524. SafePtr<CDeviceDriverPage> DrvPagePtr;
  525. CDeviceDriverPage* pDriverPage = new CDeviceDriverPage();
  526. DrvPagePtr.Attach(pDriverPage);
  527. hPage = pDriverPage->Create(pDevice);
  528. if (hPage) {
  529. if (psd.InsertPage(hPage)) {
  530. DrvPagePtr.Detach();
  531. }
  532. else {
  533. ::DestroyPropertySheetPage(hPage);
  534. }
  535. }
  536. }
  537. //
  538. // Add the resource tab
  539. //
  540. if ((Flags & DEVPROP_SHOW_RESOURCE_TAB) &&
  541. pDevice->HasResources() &&
  542. !(DiFlags & DI_RESOURCEPAGE_ADDED)) {
  543. TheMachine.DiGetExtensionPropSheetPage(*pDevice,
  544. AddPageCallback,
  545. SPPSR_SELECT_DEVICE_RESOURCES,
  546. (LPARAM)&psd
  547. );
  548. }
  549. #ifndef _WIN64
  550. //
  551. // Add the power tab if this is the local machine
  552. //
  553. if (TheMachine.IsLocal() && !(DiFlagsEx & DI_FLAGSEX_POWERPAGE_ADDED))
  554. {
  555. //
  556. // Check if the device support power management
  557. //
  558. CPowerShutdownEnable ShutdownEnable;
  559. CPowerWakeEnable WakeEnable;
  560. if (ShutdownEnable.Open(pDevice->GetDeviceID()) || WakeEnable.Open(pDevice->GetDeviceID())) {
  561. ShutdownEnable.Close();
  562. WakeEnable.Close();
  563. SafePtr<CDevicePowerMgmtPage> PowerMgmtPagePtr;
  564. CDevicePowerMgmtPage* pPowerPage = new CDevicePowerMgmtPage;
  565. PowerMgmtPagePtr.Attach(pPowerPage);
  566. hPage = pPowerPage->Create(pDevice);
  567. if (hPage) {
  568. if (psd.InsertPage(hPage)) {
  569. PowerMgmtPagePtr.Detach();
  570. }
  571. else {
  572. ::DestroyPropertySheetPage(hPage);
  573. }
  574. }
  575. }
  576. }
  577. #endif
  578. //
  579. // Add any Bus property pages if this is the local machine
  580. //
  581. if (TheMachine.IsLocal())
  582. {
  583. CBusPropPageProvider* pBusPropPageProvider = new CBusPropPageProvider();
  584. SafePtr<CBusPropPageProvider> ProviderPtr;
  585. ProviderPtr.Attach(pBusPropPageProvider);
  586. if (pBusPropPageProvider->EnumPages(pDevice, &psd)) {
  587. psd.AddProvider(pBusPropPageProvider);
  588. ProviderPtr.Detach();
  589. }
  590. }
  591. Result = (int)psd.DoSheet();
  592. if (-1 != Result) {
  593. if (TheMachine.DiGetExFlags(*pDevice) & DI_FLAGSEX_PROPCHANGE_PENDING) {
  594. //
  595. // property change pending, issue a DICS_PROPERTYCHANGE
  596. // to the class installer
  597. //
  598. SP_PROPCHANGE_PARAMS pcp;
  599. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  600. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  601. pcp.Scope = DICS_FLAG_GLOBAL;
  602. pcp.StateChange = DICS_PROPCHANGE;
  603. TheMachine.DiSetClassInstallParams(*pDevice,
  604. &pcp.ClassInstallHeader,
  605. sizeof(pcp)
  606. );
  607. TheMachine.DiCallClassInstaller(DIF_PROPERTYCHANGE, *pDevice);
  608. TheMachine.DiTurnOnDiFlags(*pDevice, DI_PROPERTIES_CHANGE);
  609. TheMachine.DiTurnOffDiExFlags(*pDevice, DI_FLAGSEX_PROPCHANGE_PENDING);
  610. }
  611. //
  612. // Merge restart/reboot flags
  613. //
  614. DiFlags = TheMachine.DiGetFlags(*pDevice);
  615. if (DI_NEEDREBOOT & DiFlags) {
  616. Result |= ID_PSREBOOTSYSTEM;
  617. }
  618. if (DI_NEEDRESTART & DiFlags) {
  619. Result |= ID_PSRESTARTWINDOWS;
  620. }
  621. }
  622. }
  623. }
  624. catch (CMemoryException* e) {
  625. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  626. e->Delete();
  627. }
  628. return -1;
  629. }
  630. STDAPI_(UINT)
  631. DeviceProblemTextA(
  632. HMACHINE hMachine,
  633. DEVNODE DevNode,
  634. ULONG ProblemNumber,
  635. LPSTR Buffer,
  636. UINT BufferSize
  637. )
  638. {
  639. #ifndef UNICODE
  640. return GetDeviceProblemText(hMachine, DevNode, ProblemNumber, Buffer, BufferSize);
  641. #else
  642. WCHAR* wchBuffer = NULL;
  643. UINT RealSize = 0;
  644. if (BufferSize && !Buffer)
  645. {
  646. SetLastError(ERROR_INVALID_PARAMETER);
  647. return 0;
  648. }
  649. if (BufferSize)
  650. {
  651. try
  652. {
  653. wchBuffer = new WCHAR[BufferSize];
  654. }
  655. catch (CMemoryException* e)
  656. {
  657. e->Delete();
  658. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  659. return 0;
  660. }
  661. }
  662. RealSize = GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
  663. wchBuffer, BufferSize);
  664. if (RealSize && BufferSize > RealSize)
  665. {
  666. ASSERT(wchBuffer);
  667. RealSize = WideCharToMultiByte(CP_ACP, 0, wchBuffer, RealSize,
  668. Buffer, BufferSize, NULL, NULL);
  669. Buffer[RealSize] = '\0';
  670. }
  671. if (wchBuffer)
  672. {
  673. delete wchBuffer;
  674. }
  675. return RealSize;
  676. #endif
  677. }
  678. STDAPI_(UINT)
  679. DeviceProblemTextW(
  680. HMACHINE hMachine,
  681. DEVNODE DevNode,
  682. ULONG ProblemNumber,
  683. LPWSTR Buffer,
  684. UINT BufferSize
  685. )
  686. {
  687. #ifdef UNICODE
  688. return GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
  689. Buffer, BufferSize);
  690. #else
  691. CHAR* chBuffer = NULL;
  692. UINT RealSize = 0;
  693. if (BufferSize && !Buffer)
  694. {
  695. SetLastError(ERROR_INVALID_PARAMETER);
  696. return 0;
  697. }
  698. if (BufferSize)
  699. {
  700. try
  701. {
  702. chBuffer = new CHAR[BufferSize];
  703. }
  704. catch (CMemoryException* e)
  705. {
  706. e->Delete();
  707. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  708. return 0;
  709. }
  710. }
  711. RealSize = GetDeviceProblemText(hMachine, DevNode, ProblemNumber,
  712. chBuffer, BufferSize);
  713. if (RealSize && BufferSize > RealSize)
  714. {
  715. ASSERT(chBuffer);
  716. RealSize = MultiByteToWideChar((CP_ACP, 0, chBuffer, RealSize,
  717. Buffer, BufferSize);
  718. Buffer[RealSize] = UNICODE_NULL;
  719. }
  720. if (chBuffer)
  721. {
  722. delete chBuffer;
  723. }
  724. return RealSize;
  725. #endif
  726. }
  727. int
  728. PropertyRunDeviceTree(
  729. HWND hwndParent,
  730. LPCTSTR MachineName,
  731. LPCTSTR DeviceID
  732. )
  733. {
  734. SHELLEXECUTEINFOW sei;
  735. TCHAR MachineOptions[MAX_PATH];
  736. TCHAR DeviceIdOptions[MAX_PATH*2];
  737. TCHAR CommandOptions[MAX_PATH];
  738. TCHAR Parameters[MAX_PATH * 3];
  739. TCHAR* FilePart;
  740. DWORD Size;
  741. Size = SearchPath(NULL, DEVMGR_MSC_FILE, NULL, MAX_PATH, Parameters, &FilePart);
  742. if (!Size || Size >=MAX_PATH)
  743. {
  744. lstrcpy(Parameters, DEVMGR_MSC_FILE);
  745. }
  746. lstrcat(Parameters, MMC_COMMAND_LINE);
  747. if (MachineName)
  748. {
  749. wsprintf(MachineOptions, DEVMGR_MACHINENAME_OPTION, MachineName);
  750. lstrcat(Parameters, MachineOptions);
  751. }
  752. if (DeviceID)
  753. {
  754. wsprintf(DeviceIdOptions, DEVMGR_DEVICEID_OPTION, DeviceID);
  755. wsprintf(CommandOptions, DEVMGR_COMMAND_OPTION, DEVMGR_CMD_PROPERTY);
  756. lstrcat(Parameters, DeviceIdOptions);
  757. lstrcat(Parameters, CommandOptions);
  758. }
  759. // no deviceid, no command.
  760. memset(&sei, 0, sizeof(sei));
  761. sei.cbSize = sizeof(sei);
  762. sei.hwnd = hwndParent;
  763. sei.nShow = SW_NORMAL;
  764. sei.hInstApp = g_hInstance;
  765. sei.lpFile = MMC_FILE;
  766. sei.fMask = SEE_MASK_NOCLOSEPROCESS;
  767. sei.lpParameters = Parameters;
  768. if (ShellExecuteEx(&sei) && sei.hProcess)
  769. {
  770. WaitForSingleObject(sei.hProcess, INFINITE);
  771. return 1;
  772. }
  773. return 0;
  774. }
  775. STDAPI_(void)
  776. DeviceProblenWizard_RunDLLA(
  777. HWND hwndStub,
  778. HINSTANCE hAppInstance,
  779. LPSTR lpCmdLine,
  780. int nCmdShow
  781. )
  782. {
  783. try
  784. {
  785. CTString tstrCmdLine(lpCmdLine);
  786. DeviceProblenWizard_RunDLL(hwndStub,
  787. hAppInstance,
  788. (LPCTSTR)tstrCmdLine,
  789. nCmdShow
  790. );
  791. }
  792. catch (CMemoryException* e)
  793. {
  794. e->ReportError();
  795. e->Delete();
  796. }
  797. }
  798. STDAPI_(void)
  799. DeviceProblenWizard_RunDLLW(
  800. HWND hwndStub,
  801. HINSTANCE hAppInstance,
  802. LPWSTR lpCmdLine,
  803. int nCmdShow
  804. )
  805. {
  806. try
  807. {
  808. CTString tstrCmdLine(lpCmdLine);
  809. DeviceProblenWizard_RunDLL(hwndStub,
  810. hAppInstance,
  811. (LPCTSTR)tstrCmdLine,
  812. nCmdShow
  813. );
  814. }
  815. catch (CMemoryException* e)
  816. {
  817. e->ReportError();
  818. e->Delete();
  819. }
  820. }
  821. void
  822. DeviceProblenWizard_RunDLL(
  823. HWND hwndStub,
  824. HINSTANCE hAppInstance,
  825. LPCTSTR lpCmdLine,
  826. int nCmdShow
  827. )
  828. {
  829. try
  830. {
  831. CRunDLLCommandLine CmdLine;
  832. CmdLine.ParseCommandLine(lpCmdLine);
  833. if (NULL == CmdLine.GetDeviceID())
  834. {
  835. ReportCmdLineError(hwndStub, IDS_NO_DEVICEID);
  836. return;
  837. }
  838. DeviceProblemWizard(hwndStub,
  839. CmdLine.GetMachineName(),
  840. CmdLine.GetDeviceID()
  841. );
  842. }
  843. catch (CMemoryException* e)
  844. {
  845. e->ReportError();
  846. e->Delete();
  847. return;
  848. }
  849. }
  850. STDAPI_(int)
  851. DeviceProblemWizardA(
  852. HWND hwndParent,
  853. LPCSTR MachineName,
  854. LPCSTR DeviceId
  855. )
  856. {
  857. try
  858. {
  859. CTString tstrMachineName(MachineName);
  860. CTString tstrDeviceId(DeviceId);
  861. return DeviceProblemWizard(hwndParent, tstrMachineName, tstrDeviceId);
  862. }
  863. catch(CMemoryException* e)
  864. {
  865. e->Delete();
  866. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  867. }
  868. return 0;
  869. }
  870. STDAPI_(int)
  871. DeviceProblemWizardW(
  872. HWND hwndParent,
  873. LPCWSTR MachineName,
  874. LPCWSTR DeviceId
  875. )
  876. {
  877. try
  878. {
  879. CTString tstrMachineName(MachineName);
  880. CTString tstrDeviceId(DeviceId);
  881. return DeviceProblemWizard(hwndParent, tstrMachineName, tstrDeviceId);
  882. }
  883. catch (CMemoryException* e)
  884. {
  885. e->Delete();
  886. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  887. }
  888. return 0;
  889. }
  890. int
  891. DeviceProblemWizard(
  892. HWND hwndParent,
  893. LPCTSTR MachineName,
  894. LPCTSTR DeviceId
  895. )
  896. {
  897. DWORD Problem, Status;
  898. try
  899. {
  900. if (!DeviceId)
  901. {
  902. SetLastError(ERROR_INVALID_PARAMETER);
  903. return 0;
  904. }
  905. CMachine TheMachine(MachineName);
  906. // create the machine just for this device
  907. if (!TheMachine.Initialize(hwndParent, DeviceId))
  908. {
  909. return 0;
  910. }
  911. PVOID Context;
  912. CDevice* pDevice;
  913. if (!TheMachine.GetFirstDevice(&pDevice, Context))
  914. {
  915. SetLastError(SPAPI_E_NO_SUCH_DEVINST);
  916. return 0;
  917. }
  918. if (pDevice->GetStatus(&Status, &Problem)) {
  919. // if the device is a phantom device, use the CM_PROB_DEVICE_NOT_THERE
  920. if (pDevice->IsPhantom()) {
  921. Problem = CM_PROB_PHANTOM;
  922. }
  923. // if the device is not started and no problem is assigned to it
  924. // fake the problem number to be failed start.
  925. if (!(Status & DN_STARTED) && !Problem && pDevice->IsRAW()) {
  926. Problem = CM_PROB_FAILED_START;
  927. }
  928. }
  929. CProblemAgent* pProblemAgent = new CProblemAgent(pDevice, Problem, TRUE);
  930. if (pProblemAgent) {
  931. pProblemAgent->FixIt(hwndParent);
  932. }
  933. return TRUE;
  934. }
  935. catch(CMemoryException* e)
  936. {
  937. e->Delete();
  938. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  939. }
  940. return 0;
  941. }
  942. // This API creates a property sheet and asks the given device's property
  943. // provider to add any advanced pages to the property sheet.
  944. // The purpose of this API is for application to manage device advanced
  945. // properties. Standard device property pages(General, Driver, Resource,
  946. // Power, Bus) are not added.
  947. //
  948. // INPUT:
  949. // hwndParent -- the caller's window handle to be used as the owner
  950. // window of any widnows this function may create
  951. // MachineName -- optional machine name. If given, it must be in
  952. // its fully qualified form. NULL means local machine
  953. // DeviceId -- device id.
  954. // OUTPUT:
  955. // See PropertySheet API for the return value
  956. //
  957. STDAPI_(int)
  958. DeviceAdvancedPropertiesA(
  959. HWND hwndParent,
  960. LPTSTR MachineName,
  961. LPTSTR DeviceId
  962. )
  963. {
  964. try
  965. {
  966. CTString tstrMachineName(MachineName);
  967. CTString tstrDeviceID(DeviceId);
  968. return DeviceAdvancedProperties(hwndParent,
  969. (LPCTSTR)tstrMachineName,
  970. (LPCTSTR)tstrDeviceID
  971. );
  972. }
  973. catch (CMemoryException* e)
  974. {
  975. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  976. e->Delete();
  977. }
  978. return 0;
  979. }
  980. STDAPI_(int)
  981. DeviceAdvancedPropertiesW(
  982. HWND hwndParent,
  983. LPCWSTR MachineName,
  984. LPCWSTR DeviceId
  985. )
  986. {
  987. try
  988. {
  989. CTString tstrMachineName(MachineName);
  990. CTString tstrDeviceID(DeviceId);
  991. return DeviceAdvancedProperties(hwndParent,
  992. (LPCTSTR)tstrMachineName,
  993. (LPCTSTR)tstrDeviceID
  994. );
  995. }
  996. catch (CMemoryException* e)
  997. {
  998. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  999. e->Delete();
  1000. }
  1001. return 0;
  1002. }
  1003. int DeviceAdvancedProperties(
  1004. HWND hwndParent,
  1005. LPCTSTR MachineName,
  1006. LPCTSTR DeviceId
  1007. )
  1008. {
  1009. if (!DeviceId)
  1010. {
  1011. SetLastError(ERROR_INVALID_PARAMETER);
  1012. return -1;
  1013. }
  1014. CMachine TheMachine(MachineName);
  1015. CDevice* pDevice;
  1016. PVOID Context;
  1017. try
  1018. {
  1019. if (TheMachine.Initialize(hwndParent, DeviceId) &&
  1020. TheMachine.GetFirstDevice(&pDevice, Context))
  1021. {
  1022. TheMachine.EnableRefresh(FALSE);
  1023. CPropSheetData& psd = pDevice->m_psd;
  1024. //initialize CPropSheetData without ConsoleHandle
  1025. if (psd.Create(g_hInstance, hwndParent, MAX_PROP_PAGES, 0l))
  1026. {
  1027. psd.m_psh.pszCaption = pDevice->GetDisplayName();
  1028. if (TheMachine.DiGetClassDevPropertySheet(*pDevice, &psd.m_psh,
  1029. MAX_PROP_PAGES,
  1030. TheMachine.IsLocal() ?
  1031. DIGCDP_FLAG_ADVANCED :
  1032. DIGCDP_FLAG_REMOTE_ADVANCED))
  1033. {
  1034. int Result = (int)psd.DoSheet();
  1035. if (-1 != Result)
  1036. {
  1037. // merge restart/reboot flags
  1038. DWORD DiFlags = TheMachine.DiGetFlags(*pDevice);
  1039. if (DI_NEEDREBOOT & DiFlags)
  1040. {
  1041. Result |= ID_PSREBOOTSYSTEM;
  1042. }
  1043. if (DI_NEEDRESTART & DiFlags)
  1044. {
  1045. Result |= ID_PSRESTARTWINDOWS;
  1046. }
  1047. }
  1048. return Result;
  1049. }
  1050. }
  1051. }
  1052. }
  1053. catch (CMemoryException* e)
  1054. {
  1055. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1056. e->Delete();
  1057. }
  1058. return -1;
  1059. }