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.

888 lines
20 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1999
  6. //
  7. // File: miscutil.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "HdwWiz.h"
  11. /* ----------------------------------------------------------------------
  12. * SetDlgText - Set Dialog Text Field
  13. *
  14. * Concatenates a number of string resources and does a SetWindowText()
  15. * for a dialog text control.
  16. *
  17. * Parameters:
  18. *
  19. * hDlg - Dialog handle
  20. * iControl - Dialog control ID to receive text
  21. * nStartString - ID of first string resource to concatenate
  22. * nEndString - ID of last string resource to concatenate
  23. *
  24. * Note: the string IDs must be consecutive.
  25. */
  26. void
  27. SetDlgText(HWND hDlg, int iControl, int nStartString, int nEndString)
  28. {
  29. int iX;
  30. TCHAR szText[MAX_PATH*4];
  31. szText[0] = '\0';
  32. for (iX = nStartString; iX<= nEndString; iX++) {
  33. LoadString(hHdwWiz,
  34. iX,
  35. szText + lstrlen(szText),
  36. sizeof(szText)/sizeof(TCHAR) - lstrlen(szText)
  37. );
  38. }
  39. if (iControl) {
  40. SetDlgItemText(hDlg, iControl, szText);
  41. } else {
  42. SetWindowText(hDlg, szText);
  43. }
  44. }
  45. VOID
  46. HdwWizPropagateMessage(
  47. HWND hWnd,
  48. UINT uMessage,
  49. WPARAM wParam,
  50. LPARAM lParam
  51. )
  52. {
  53. while ((hWnd = GetWindow(hWnd, GW_CHILD))) {
  54. SendMessage(hWnd, uMessage, wParam, lParam);
  55. }
  56. }
  57. BOOL
  58. Use256Color(
  59. VOID
  60. )
  61. {
  62. HDC hdc;
  63. BOOL bRetVal= FALSE;
  64. hdc = GetDC(NULL);
  65. if(hdc) {
  66. if (GetDeviceCaps(hdc, BITSPIXEL) >= 8) {
  67. bRetVal = TRUE;
  68. }
  69. ReleaseDC(NULL, hdc);
  70. }
  71. return bRetVal;
  72. }
  73. HPALETTE
  74. CreateDIBPalette(
  75. LPBITMAPINFO lpbmi,
  76. LPINT lpiNumColors
  77. )
  78. {
  79. LPBITMAPINFOHEADER lpbi;
  80. LPLOGPALETTE lpPal;
  81. HANDLE hLogPal;
  82. HPALETTE hPal = NULL;
  83. int i;
  84. lpbi = (LPBITMAPINFOHEADER)lpbmi;
  85. if (lpbi->biBitCount <= 8) {
  86. *lpiNumColors = (1 << lpbi->biBitCount);
  87. } else {
  88. *lpiNumColors = 0; // No palette needed for 24 BPP DIB
  89. }
  90. if (*lpiNumColors) {
  91. hLogPal = GlobalAlloc(GHND,
  92. sizeof (LOGPALETTE) +
  93. sizeof (PALETTEENTRY) * (*lpiNumColors));
  94. if (hLogPal) {
  95. lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);
  96. if (lpPal) {
  97. lpPal->palVersion = 0x300;
  98. lpPal->palNumEntries = (unsigned short)(*lpiNumColors);
  99. for (i = 0; i < *lpiNumColors; i++)
  100. {
  101. lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
  102. lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
  103. lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
  104. lpPal->palPalEntry[i].peFlags = 0;
  105. }
  106. hPal = CreatePalette (lpPal);
  107. GlobalUnlock (hLogPal);
  108. GlobalFree (hLogPal);
  109. }
  110. }
  111. }
  112. return hPal;
  113. }
  114. BOOL
  115. LoadBitmapAndPalette(
  116. HINSTANCE hInstance,
  117. LPCTSTR pszResource,
  118. PRESOURCEBITMAP ResourceBitmap
  119. )
  120. {
  121. HBITMAP hBitmap = NULL;
  122. HPALETTE hPalette = NULL;
  123. LPBITMAPINFOHEADER lpbi;
  124. HDC hdc;
  125. HRSRC hRsrc;
  126. HGLOBAL hGlobal;
  127. int iNumColors;
  128. hRsrc = FindResource(hInstance, pszResource, RT_BITMAP);
  129. if (hRsrc) {
  130. hGlobal = LoadResource(hInstance, hRsrc);
  131. if (hGlobal) {
  132. lpbi = (LPBITMAPINFOHEADER)LockResource(hGlobal);
  133. if (lpbi) {
  134. hdc = GetDC(NULL);
  135. hPalette = CreateDIBPalette ((LPBITMAPINFO)lpbi, &iNumColors);
  136. if (hPalette) {
  137. SelectPalette(hdc, hPalette, TRUE);
  138. RealizePalette(hdc);
  139. }
  140. hBitmap = CreateDIBitmap(hdc,
  141. (LPBITMAPINFOHEADER)lpbi,
  142. (LONG)CBM_INIT,
  143. (LPSTR)lpbi + lpbi->biSize + iNumColors * sizeof(RGBQUAD),
  144. (LPBITMAPINFO)lpbi,
  145. DIB_RGB_COLORS
  146. );
  147. UnlockResource(hGlobal);
  148. }
  149. FreeResource(hGlobal);
  150. }
  151. }
  152. if (!hBitmap || !hPalette) {
  153. if (hBitmap)
  154. DeleteObject(hBitmap);
  155. if (hPalette)
  156. DeleteObject(hPalette);
  157. return FALSE;
  158. }
  159. ResourceBitmap->hBitmap = hBitmap;
  160. ResourceBitmap->hPalette = hPalette;
  161. GetObject(hBitmap, sizeof(ResourceBitmap->Bitmap), &ResourceBitmap->Bitmap);
  162. return TRUE;
  163. }
  164. void
  165. HideWindowByMove(
  166. HWND hDlg
  167. )
  168. {
  169. RECT rect;
  170. GetWindowRect(hDlg, &rect);
  171. MoveWindow(hDlg,
  172. 0,
  173. -(rect.bottom - rect.top),
  174. rect.right - rect.left,
  175. rect.bottom - rect.top,
  176. FALSE
  177. );
  178. }
  179. LONG
  180. HdwBuildClassInfoList(
  181. PHARDWAREWIZ HardwareWiz,
  182. DWORD ClassListFlags,
  183. PTCHAR MachineName
  184. )
  185. {
  186. LONG Error;
  187. while (!SetupDiBuildClassInfoListEx(ClassListFlags,
  188. HardwareWiz->ClassGuidList,
  189. HardwareWiz->ClassGuidSize,
  190. &HardwareWiz->ClassGuidNum,
  191. MachineName,
  192. NULL
  193. )) {
  194. Error = GetLastError();
  195. if (HardwareWiz->ClassGuidList) {
  196. LocalFree(HardwareWiz->ClassGuidList);
  197. HardwareWiz->ClassGuidList = NULL;
  198. }
  199. if (Error == ERROR_INSUFFICIENT_BUFFER &&
  200. HardwareWiz->ClassGuidNum > HardwareWiz->ClassGuidSize) {
  201. HardwareWiz->ClassGuidList = LocalAlloc(LPTR, HardwareWiz->ClassGuidNum*sizeof(GUID));
  202. if (!HardwareWiz->ClassGuidList) {
  203. HardwareWiz->ClassGuidSize = 0;
  204. HardwareWiz->ClassGuidNum = 0;
  205. return ERROR_NOT_ENOUGH_MEMORY;
  206. }
  207. HardwareWiz->ClassGuidSize = HardwareWiz->ClassGuidNum;
  208. } else {
  209. if (HardwareWiz->ClassGuidList) {
  210. LocalFree(HardwareWiz->ClassGuidList);
  211. }
  212. HardwareWiz->ClassGuidSize = 0;
  213. HardwareWiz->ClassGuidNum = 0;
  214. return Error;
  215. }
  216. }
  217. return ERROR_SUCCESS;
  218. }
  219. int
  220. HdwMessageBox(
  221. HWND hWnd,
  222. LPTSTR szIdText,
  223. LPTSTR szIdCaption,
  224. UINT Type
  225. )
  226. {
  227. TCHAR szText[MAX_PATH];
  228. TCHAR szCaption[MAX_PATH];
  229. if (!HIWORD(szIdText)) {
  230. *szText = TEXT('\0');
  231. LoadString(hHdwWiz, LOWORD(szIdText), szText, MAX_PATH);
  232. szIdText = szText;
  233. }
  234. if (!HIWORD(szIdCaption)) {
  235. *szCaption = TEXT('\0');
  236. LoadString(hHdwWiz, LOWORD(szIdCaption), szCaption, MAX_PATH);
  237. szIdCaption = szCaption;
  238. }
  239. return MessageBox(hWnd, szIdText, szIdCaption, Type);
  240. }
  241. LONG
  242. HdwUnhandledExceptionFilter(
  243. struct _EXCEPTION_POINTERS *ExceptionPointers
  244. )
  245. {
  246. LONG lRet;
  247. BOOL BeingDebugged;
  248. lRet = UnhandledExceptionFilter(ExceptionPointers);
  249. BeingDebugged = IsDebuggerPresent();
  250. //
  251. // Normal code path is to handle the exception.
  252. // However, if a debugger is present, and the system's unhandled
  253. // exception filter returns continue search, we let it go
  254. // thru to allow the debugger a chance at it.
  255. //
  256. if (lRet == EXCEPTION_CONTINUE_SEARCH && !BeingDebugged) {
  257. lRet = EXCEPTION_EXECUTE_HANDLER;
  258. }
  259. return lRet;
  260. }
  261. BOOL
  262. NoPrivilegeWarning(
  263. HWND hWnd
  264. )
  265. /*++
  266. This function checks to see if the user has SE_LOAD_DRIVER_NAME privileges
  267. which means they can install and load new kernel mode drivers.
  268. If the user does NOT have this privilege then a warning is displayed telling
  269. them that they have insufficient privileges to install hardware on this machine.
  270. Arguments
  271. hWnd - Parent window handle
  272. Return Value:
  273. TRUE if the user does NOT have SE_LOAD_DRIVER_NAME privileges and
  274. FALSE if the user does have this privilege
  275. --*/
  276. {
  277. TCHAR szMsg[MAX_PATH];
  278. TCHAR szCaption[MAX_PATH];
  279. if (!pSetupDoesUserHavePrivilege((PCTSTR)SE_LOAD_DRIVER_NAME)) {
  280. if (LoadString(hHdwWiz,
  281. IDS_HDWUNINSTALL_NOPRIVILEGE,
  282. szMsg,
  283. MAX_PATH)
  284. &&
  285. LoadString(hHdwWiz,
  286. IDS_HDWWIZNAME,
  287. szCaption,
  288. MAX_PATH))
  289. {
  290. MessageBox(hWnd, szMsg, szCaption, MB_OK | MB_ICONEXCLAMATION);
  291. }
  292. return TRUE;
  293. }
  294. return FALSE;
  295. }
  296. VOID
  297. _OnSysColorChange(
  298. HWND hWnd,
  299. WPARAM wParam,
  300. LPARAM lParam
  301. )
  302. {
  303. HWND hChildWnd;
  304. hChildWnd = GetWindow(hWnd, GW_CHILD);
  305. while (hChildWnd != NULL) {
  306. SendMessage(hChildWnd, WM_SYSCOLORCHANGE, wParam, lParam);
  307. hChildWnd = GetWindow(hChildWnd, GW_HWNDNEXT);
  308. }
  309. }
  310. void
  311. LoadText(
  312. PTCHAR szText,
  313. int SizeText,
  314. int nStartString,
  315. int nEndString
  316. )
  317. {
  318. int iX;
  319. for (iX = nStartString; iX<= nEndString; iX++) {
  320. LoadString(hHdwWiz,
  321. iX,
  322. szText + lstrlen(szText),
  323. SizeText/sizeof(TCHAR) - lstrlen(szText)
  324. );
  325. }
  326. return;
  327. }
  328. /* InstallFailedWarning
  329. *
  330. * Displays device install failed warning in a message box. For use
  331. * when installation fails.
  332. *
  333. */
  334. void
  335. InstallFailedWarning(
  336. HWND hDlg,
  337. PHARDWAREWIZ HardwareWiz
  338. )
  339. {
  340. int len;
  341. TCHAR szMsg[MAX_MESSAGE_STRING];
  342. TCHAR szTitle[MAX_MESSAGE_TITLE];
  343. PTCHAR ErrorMsg;
  344. LoadString(hHdwWiz,
  345. IDS_ADDNEWDEVICE,
  346. szTitle,
  347. sizeof(szTitle)/sizeof(TCHAR)
  348. );
  349. if ((len = LoadString(hHdwWiz, IDS_HDW_ERRORFIN1, szMsg, sizeof(szMsg)/sizeof(TCHAR)))) {
  350. LoadString(hHdwWiz, IDS_HDW_ERRORFIN2, szMsg+len, sizeof(szMsg)/sizeof(TCHAR)-len);
  351. }
  352. if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  353. NULL,
  354. HRESULT_FROM_SETUPAPI(HardwareWiz->LastError),
  355. 0,
  356. (LPTSTR)&ErrorMsg,
  357. 0,
  358. NULL
  359. ))
  360. {
  361. lstrcat(szMsg, TEXT("\n\n"));
  362. if ((lstrlen(szMsg) + lstrlen(ErrorMsg)) < SIZECHARS(szMsg)) {
  363. lstrcat(szMsg, ErrorMsg);
  364. }
  365. LocalFree(ErrorMsg);
  366. }
  367. MessageBox(hDlg, szMsg, szTitle, MB_OK | MB_TASKMODAL | MB_ICONEXCLAMATION);
  368. }
  369. void
  370. SetDriverDescription(
  371. HWND hDlg,
  372. int iControl,
  373. PHARDWAREWIZ HardwareWiz
  374. )
  375. {
  376. CONFIGRET ConfigRet;
  377. ULONG ulSize;
  378. PTCHAR FriendlyName;
  379. PTCHAR Location;
  380. SP_DRVINFO_DATA DriverInfoData;
  381. //
  382. // If there is a selected driver use its driver description,
  383. // since this is what the user is going to install.
  384. //
  385. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  386. if (SetupDiGetSelectedDriver(HardwareWiz->hDeviceInfo,
  387. &HardwareWiz->DeviceInfoData,
  388. &DriverInfoData
  389. )
  390. &&
  391. *DriverInfoData.Description) {
  392. wcscpy(HardwareWiz->DriverDescription, DriverInfoData.Description);
  393. SetDlgItemText(hDlg, iControl, HardwareWiz->DriverDescription);
  394. return;
  395. }
  396. FriendlyName = BuildFriendlyName(HardwareWiz->DeviceInfoData.DevInst, NULL);
  397. if (FriendlyName) {
  398. SetDlgItemText(hDlg, iControl, FriendlyName);
  399. LocalFree(FriendlyName);
  400. return;
  401. }
  402. SetDlgItemText(hDlg, iControl, szUnknown);
  403. return;
  404. }
  405. HPROPSHEETPAGE
  406. CreateWizExtPage(
  407. int PageResourceId,
  408. DLGPROC pfnDlgProc,
  409. PHARDWAREWIZ HardwareWiz
  410. )
  411. {
  412. PROPSHEETPAGE psp;
  413. memset(&psp, 0, sizeof(PROPSHEETPAGE));
  414. psp.dwSize = sizeof(PROPSHEETPAGE);
  415. psp.dwFlags = PSP_DEFAULT;
  416. psp.hInstance = hHdwWiz;
  417. psp.lParam = (LPARAM)HardwareWiz;
  418. psp.pszTemplate = MAKEINTRESOURCE(PageResourceId);
  419. psp.pfnDlgProc = pfnDlgProc;
  420. return CreatePropertySheetPage(&psp);
  421. }
  422. BOOL
  423. AddClassWizExtPages(
  424. HWND hwndParentDlg,
  425. PHARDWAREWIZ HardwareWiz,
  426. PSP_NEWDEVICEWIZARD_DATA DeviceWizardData,
  427. DI_FUNCTION InstallFunction
  428. )
  429. {
  430. DWORD NumPages;
  431. BOOL bRet = FALSE;
  432. memset(DeviceWizardData, 0, sizeof(SP_NEWDEVICEWIZARD_DATA));
  433. DeviceWizardData->ClassInstallHeader.InstallFunction = InstallFunction;
  434. DeviceWizardData->ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  435. DeviceWizardData->hwndWizardDlg = hwndParentDlg;
  436. if (SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  437. &HardwareWiz->DeviceInfoData,
  438. &DeviceWizardData->ClassInstallHeader,
  439. sizeof(SP_NEWDEVICEWIZARD_DATA)
  440. )
  441. &&
  442. (SetupDiCallClassInstaller(InstallFunction,
  443. HardwareWiz->hDeviceInfo,
  444. &HardwareWiz->DeviceInfoData
  445. )
  446. ||
  447. (ERROR_DI_DO_DEFAULT == GetLastError()))
  448. &&
  449. SetupDiGetClassInstallParams(HardwareWiz->hDeviceInfo,
  450. &HardwareWiz->DeviceInfoData,
  451. &DeviceWizardData->ClassInstallHeader,
  452. sizeof(SP_NEWDEVICEWIZARD_DATA),
  453. NULL
  454. )
  455. &&
  456. DeviceWizardData->NumDynamicPages)
  457. {
  458. NumPages = 0;
  459. while (NumPages < DeviceWizardData->NumDynamicPages) {
  460. PropSheet_AddPage(hwndParentDlg, DeviceWizardData->DynamicPages[NumPages++]);
  461. }
  462. bRet = TRUE;
  463. }
  464. //
  465. // Clear the class install parameters.
  466. //
  467. SetupDiSetClassInstallParams(HardwareWiz->hDeviceInfo,
  468. &HardwareWiz->DeviceInfoData,
  469. NULL,
  470. 0
  471. );
  472. return bRet;
  473. }
  474. void
  475. RemoveClassWizExtPages(
  476. HWND hwndParentDlg,
  477. PSP_NEWDEVICEWIZARD_DATA DeviceWizardData
  478. )
  479. {
  480. DWORD NumPages;
  481. NumPages = DeviceWizardData->NumDynamicPages;
  482. while (NumPages--) {
  483. PropSheet_RemovePage(hwndParentDlg,
  484. (WPARAM)-1,
  485. DeviceWizardData->DynamicPages[NumPages]
  486. );
  487. }
  488. memset(DeviceWizardData, 0, sizeof(SP_NEWDEVICEWIZARD_DATA));
  489. return;
  490. }
  491. BOOL
  492. IsDeviceHidden(
  493. PHARDWAREWIZ HardwareWiz,
  494. PSP_DEVINFO_DATA DeviceInfoData
  495. )
  496. {
  497. BOOL bHidden = FALSE;
  498. ULONG DevNodeStatus, DevNodeProblem;
  499. HKEY hKeyClass;
  500. //
  501. // If the DN_NO_SHOW_IN_DM status bit is set
  502. // then we should hide this device.
  503. //
  504. if ((CM_Get_DevNode_Status(&DevNodeStatus,
  505. &DevNodeProblem,
  506. DeviceInfoData->DevInst,
  507. 0) == CR_SUCCESS) &&
  508. (DevNodeStatus & DN_NO_SHOW_IN_DM)) {
  509. bHidden = TRUE;
  510. goto HiddenDone;
  511. }
  512. //
  513. // If the devices class has the NoDisplayClass value then
  514. // don't display this device.
  515. //
  516. if (hKeyClass = SetupDiOpenClassRegKeyEx(&DeviceInfoData->ClassGuid,
  517. KEY_READ,
  518. DIOCR_INSTALLER,
  519. HardwareWiz->hMachine ? HardwareWiz->MachineName : NULL,
  520. NULL)) {
  521. if (RegQueryValueEx(hKeyClass, REGSTR_VAL_NODISPLAYCLASS, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
  522. bHidden = TRUE;
  523. }
  524. RegCloseKey(hKeyClass);
  525. }
  526. HiddenDone:
  527. return bHidden;
  528. }
  529. DWORD
  530. SetPrivilegeAttribute(
  531. LPCTSTR PrivilegeName,
  532. DWORD NewPrivilegeAttribute,
  533. DWORD *OldPrivilegeAttribute
  534. )
  535. /*++
  536. sets the security attributes for a given privilege.
  537. Arguments:
  538. PrivilegeName - Name of the privilege we are manipulating.
  539. NewPrivilegeAttribute - The new attribute value to use.
  540. OldPrivilegeAttribute - Pointer to receive the old privilege value. OPTIONAL
  541. Return value:
  542. NO_ERROR or WIN32 error.
  543. --*/
  544. {
  545. LUID PrivilegeValue;
  546. TOKEN_PRIVILEGES TokenPrivileges, OldTokenPrivileges;
  547. DWORD ReturnLength;
  548. HANDLE TokenHandle;
  549. //
  550. // First, find out the LUID Value of the privilege
  551. //
  552. if (!LookupPrivilegeValue(NULL, PrivilegeName, &PrivilegeValue))
  553. {
  554. return GetLastError();
  555. }
  556. //
  557. // Get the token handle
  558. //
  559. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
  560. {
  561. return GetLastError();
  562. }
  563. //
  564. // Set up the privilege set we will need
  565. //
  566. TokenPrivileges.PrivilegeCount = 1;
  567. TokenPrivileges.Privileges[0].Luid = PrivilegeValue;
  568. TokenPrivileges.Privileges[0].Attributes = NewPrivilegeAttribute;
  569. ReturnLength = sizeof( TOKEN_PRIVILEGES );
  570. if (!AdjustTokenPrivileges (
  571. TokenHandle,
  572. FALSE,
  573. &TokenPrivileges,
  574. sizeof( TOKEN_PRIVILEGES ),
  575. &OldTokenPrivileges,
  576. &ReturnLength
  577. ))
  578. {
  579. CloseHandle(TokenHandle);
  580. return GetLastError();
  581. }
  582. else
  583. {
  584. if (OldPrivilegeAttribute != NULL)
  585. {
  586. *OldPrivilegeAttribute = OldTokenPrivileges.Privileges[0].Attributes;
  587. }
  588. CloseHandle(TokenHandle);
  589. return NO_ERROR;
  590. }
  591. }
  592. BOOL
  593. ShutdownMachine(
  594. HWND hWnd
  595. )
  596. {
  597. BOOL fOk;
  598. DWORD dwExitWinCode = EWX_SHUTDOWN;
  599. DWORD OldState;
  600. DWORD dwError;
  601. if (IsPwrShutdownAllowed()) {
  602. dwExitWinCode |= EWX_POWEROFF;
  603. }
  604. dwError = SetPrivilegeAttribute(SE_SHUTDOWN_NAME, SE_PRIVILEGE_ENABLED, &OldState);
  605. if (GetKeyState(VK_CONTROL) < 0) {
  606. dwExitWinCode |= EWX_FORCE;
  607. }
  608. fOk = ExitWindowsEx(dwExitWinCode, REASON_PLANNED_FLAG | REASON_HWINSTALL);
  609. //
  610. // If we were able to set the privilege, then reset it.
  611. //
  612. if (dwError == ERROR_SUCCESS) {
  613. SetPrivilegeAttribute(SE_SHUTDOWN_NAME, OldState, NULL);
  614. }
  615. else
  616. {
  617. //
  618. // Otherwise, if we failed, then it must have been some
  619. // security stuff.
  620. //
  621. if (!fOk)
  622. {
  623. TCHAR Title[MAX_PATH], Message[MAX_PATH];
  624. if (LoadString(hHdwWiz, IDS_NO_PERMISSION_SHUTDOWN, Message, SIZECHARS(Message)) &&
  625. LoadString(hHdwWiz, IDS_SHUTDOWN, Title, SIZECHARS(Title))) {
  626. MessageBox(hWnd, Message, Title, MB_OK | MB_ICONSTOP);
  627. }
  628. }
  629. }
  630. return fOk;
  631. }
  632. int
  633. DeviceProperties(
  634. HWND hWnd,
  635. HMACHINE hMachine,
  636. LPCSTR MachineName,
  637. DEVNODE DevNode,
  638. ULONG Flags
  639. )
  640. {
  641. TCHAR DeviceID[MAX_DEVICE_ID_LEN];
  642. PDEVICEPROPERTIESEX pDevicePropertiesEx = NULL;
  643. int iRet = 0;
  644. if (!hDevMgr) {
  645. return 0;
  646. }
  647. pDevicePropertiesEx = (PVOID) GetProcAddress(hDevMgr, "DevicePropertiesExW");
  648. if (!pDevicePropertiesEx) {
  649. return 0;
  650. }
  651. if (CM_Get_Device_ID_Ex(DevNode,
  652. DeviceID,
  653. SIZECHARS(DeviceID),
  654. 0,
  655. hMachine
  656. ) == CR_SUCCESS) {
  657. iRet = pDevicePropertiesEx(hWnd,
  658. MachineName,
  659. (LPCSTR)DeviceID,
  660. Flags,
  661. FALSE);
  662. }
  663. return iRet;
  664. }
  665. #if DBG
  666. //
  667. // Debugging aids
  668. //
  669. void
  670. Trace(
  671. LPCTSTR format,
  672. ...
  673. )
  674. {
  675. // according to wsprintf specification, the max buffer size is
  676. // 1024
  677. TCHAR Buffer[1024];
  678. va_list arglist;
  679. va_start(arglist, format);
  680. wvsprintf(Buffer, format, arglist);
  681. va_end(arglist);
  682. OutputDebugString(TEXT("HDWWIZ: "));
  683. OutputDebugString(Buffer);
  684. OutputDebugString(TEXT("\n"));
  685. }
  686. #endif