Leaked source code of windows server 2003
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.

1871 lines
48 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation
  6. //
  7. // File: miscutil.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #include "newdevp.h"
  11. TCHAR szUnknownDevice[64];
  12. TCHAR szUnknown[64];
  13. HMODULE hSrClientDll;
  14. typedef
  15. BOOL
  16. (*SRSETRESTOREPOINT)(
  17. PRESTOREPOINTINFO pRestorePtSpec,
  18. PSTATEMGRSTATUS pSMgrStatus
  19. );
  20. PTCHAR
  21. BuildFriendlyName(
  22. DEVINST DevInst,
  23. BOOL UseNewDeviceDesc,
  24. HMACHINE hMachine
  25. )
  26. {
  27. PTCHAR FriendlyName;
  28. CONFIGRET ConfigRet = CR_FAILURE;
  29. ULONG cbSize = 0;
  30. TCHAR szBuffer[LINE_LEN];
  31. *szBuffer = TEXT('\0');
  32. //
  33. // Try the registry for NewDeviceDesc
  34. //
  35. if (UseNewDeviceDesc) {
  36. HKEY hKey;
  37. DWORD dwType = REG_SZ;
  38. ConfigRet = CM_Open_DevNode_Key(DevInst,
  39. KEY_READ,
  40. 0,
  41. RegDisposition_OpenExisting,
  42. &hKey,
  43. CM_REGISTRY_HARDWARE
  44. );
  45. if (ConfigRet == CR_SUCCESS) {
  46. cbSize = sizeof(szBuffer);
  47. if (RegQueryValueEx(hKey,
  48. REGSTR_VAL_NEW_DEVICE_DESC,
  49. NULL,
  50. &dwType,
  51. (LPBYTE)szBuffer,
  52. &cbSize
  53. ) != ERROR_SUCCESS) {
  54. ConfigRet = CR_FAILURE;
  55. }
  56. RegCloseKey(hKey);
  57. }
  58. }
  59. if (ConfigRet != CR_SUCCESS) {
  60. //
  61. // Try the registry for FRIENDLYNAME
  62. //
  63. cbSize = sizeof(szBuffer);
  64. ConfigRet = CM_Get_DevNode_Registry_Property_Ex(DevInst,
  65. CM_DRP_FRIENDLYNAME,
  66. NULL,
  67. szBuffer,
  68. &cbSize,
  69. 0,
  70. hMachine
  71. );
  72. }
  73. if (ConfigRet != CR_SUCCESS) {
  74. //
  75. // Try the registry for DEVICEDESC
  76. //
  77. cbSize = sizeof(szBuffer);
  78. ConfigRet = CM_Get_DevNode_Registry_Property_Ex(DevInst,
  79. CM_DRP_DEVICEDESC,
  80. NULL,
  81. szBuffer,
  82. &cbSize,
  83. 0,
  84. hMachine
  85. );
  86. }
  87. if ((ConfigRet == CR_SUCCESS) &&
  88. *szBuffer &&
  89. (cbSize > 0)) {
  90. FriendlyName = LocalAlloc(LPTR, cbSize);
  91. if (FriendlyName) {
  92. StringCbCopy(FriendlyName, cbSize, szBuffer);
  93. }
  94. }
  95. else {
  96. FriendlyName = NULL;
  97. }
  98. return FriendlyName;
  99. }
  100. /* ----------------------------------------------------------------------
  101. * SetDlgText - Set Dialog Text Field
  102. *
  103. * Concatenates a number of string resources and does a SetWindowText()
  104. * for a dialog text control.
  105. *
  106. * Parameters:
  107. *
  108. * hDlg - Dialog handle
  109. * iControl - Dialog control ID to receive text
  110. * nStartString - ID of first string resource to concatenate
  111. * nEndString - ID of last string resource to concatenate
  112. *
  113. * Note: the string IDs must be consecutive.
  114. */
  115. void
  116. SetDlgText(HWND hDlg, int iControl, int nStartString, int nEndString)
  117. {
  118. int iX;
  119. TCHAR szText[SDT_MAX_TEXT];
  120. szText[0] = '\0';
  121. for (iX = nStartString; iX<= nEndString; iX++) {
  122. LoadString(hNewDev,
  123. iX,
  124. szText + lstrlen(szText),
  125. SIZECHARS(szText) - lstrlen(szText)
  126. );
  127. }
  128. if (iControl) {
  129. SetDlgItemText(hDlg, iControl, szText);
  130. } else {
  131. SetWindowText(hDlg, szText);
  132. }
  133. }
  134. void
  135. LoadText(PTCHAR szText, int SizeText, int nStartString, int nEndString)
  136. {
  137. int iX;
  138. for (iX = nStartString; iX<= nEndString; iX++) {
  139. LoadString(hNewDev,
  140. iX,
  141. szText + lstrlen(szText),
  142. SizeText - lstrlen(szText)
  143. );
  144. }
  145. return;
  146. }
  147. VOID
  148. _OnSysColorChange(
  149. HWND hWnd,
  150. WPARAM wParam,
  151. LPARAM lParam
  152. )
  153. {
  154. HWND hChildWnd;
  155. hChildWnd = GetWindow(hWnd, GW_CHILD);
  156. while (hChildWnd != NULL) {
  157. SendMessage(hChildWnd, WM_SYSCOLORCHANGE, wParam, lParam);
  158. hChildWnd = GetWindow(hChildWnd, GW_HWNDNEXT);
  159. }
  160. }
  161. BOOL
  162. NoPrivilegeWarning(
  163. HWND hWnd
  164. )
  165. /*++
  166. This function checks to see if the user has Administrator privileges.
  167. If the user does NOT have this administrator privilege then a warning is displayed telling
  168. them that they have insufficient privileges to install hardware on this machine.
  169. Arguments
  170. hWnd - Parent window handle
  171. Return Value:
  172. TRUE if the user does NOT have Administrator privileges and
  173. FALSE if the user does have this privilege
  174. --*/
  175. {
  176. TCHAR szMsg[MAX_PATH];
  177. TCHAR szCaption[MAX_PATH];
  178. if (!pSetupIsUserAdmin()) {
  179. if (LoadString(hNewDev,
  180. IDS_NDW_NOTADMIN,
  181. szMsg,
  182. SIZECHARS(szMsg))
  183. &&
  184. LoadString(hNewDev,
  185. IDS_NEWDEVICENAME,
  186. szCaption,
  187. SIZECHARS(szCaption)))
  188. {
  189. MessageBox(hWnd, szMsg, szCaption, MB_OK | MB_ICONEXCLAMATION);
  190. }
  191. return TRUE;
  192. }
  193. return FALSE;
  194. }
  195. LONG
  196. NdwBuildClassInfoList(
  197. PNEWDEVWIZ NewDevWiz,
  198. DWORD ClassListFlags
  199. )
  200. {
  201. LONG Error;
  202. //
  203. // Build the class info list
  204. //
  205. while (!SetupDiBuildClassInfoList(ClassListFlags,
  206. NewDevWiz->ClassGuidList,
  207. NewDevWiz->ClassGuidSize,
  208. &NewDevWiz->ClassGuidNum
  209. ))
  210. {
  211. Error = GetLastError();
  212. if (NewDevWiz->ClassGuidList) {
  213. LocalFree(NewDevWiz->ClassGuidList);
  214. NewDevWiz->ClassGuidList = NULL;
  215. }
  216. if (Error == ERROR_INSUFFICIENT_BUFFER &&
  217. NewDevWiz->ClassGuidNum > NewDevWiz->ClassGuidSize)
  218. {
  219. NewDevWiz->ClassGuidList = LocalAlloc(LPTR, NewDevWiz->ClassGuidNum*sizeof(GUID));
  220. if (!NewDevWiz->ClassGuidList) {
  221. NewDevWiz->ClassGuidSize = 0;
  222. NewDevWiz->ClassGuidNum = 0;
  223. return ERROR_NOT_ENOUGH_MEMORY;
  224. }
  225. NewDevWiz->ClassGuidSize = NewDevWiz->ClassGuidNum;
  226. } else {
  227. if (NewDevWiz->ClassGuidList) {
  228. LocalFree(NewDevWiz->ClassGuidList);
  229. }
  230. NewDevWiz->ClassGuidSize = 0;
  231. NewDevWiz->ClassGuidNum = 0;
  232. NewDevWiz->ClassGuidList = NULL;
  233. return Error;
  234. }
  235. }
  236. return ERROR_SUCCESS;
  237. }
  238. void
  239. HideWindowByMove(
  240. HWND hDlg
  241. )
  242. {
  243. RECT rect;
  244. //
  245. // Move the window offscreen, using the virtual coords for Upper Left Corner
  246. //
  247. GetWindowRect(hDlg, &rect);
  248. MoveWindow(hDlg,
  249. GetSystemMetrics(SM_XVIRTUALSCREEN),
  250. GetSystemMetrics(SM_YVIRTUALSCREEN) - (rect.bottom - rect.top),
  251. rect.right - rect.left,
  252. rect.bottom - rect.top,
  253. TRUE
  254. );
  255. }
  256. LONG
  257. NdwUnhandledExceptionFilter(
  258. struct _EXCEPTION_POINTERS *ExceptionPointers
  259. )
  260. {
  261. LONG lRet;
  262. BOOL BeingDebugged;
  263. lRet = UnhandledExceptionFilter(ExceptionPointers);
  264. BeingDebugged = IsDebuggerPresent();
  265. //
  266. // Normal code path is to handle the exception.
  267. // However, if a debugger is present, and the system's unhandled
  268. // exception filter returns continue search, we let it go
  269. // thru to allow the debugger a chance at it.
  270. //
  271. if (lRet == EXCEPTION_CONTINUE_SEARCH && !BeingDebugged) {
  272. lRet = EXCEPTION_EXECUTE_HANDLER;
  273. }
  274. return lRet;
  275. }
  276. BOOL
  277. SetClassGuid(
  278. HDEVINFO hDeviceInfo,
  279. PSP_DEVINFO_DATA DeviceInfoData,
  280. LPGUID ClassGuid
  281. )
  282. {
  283. TCHAR ClassGuidString[MAX_GUID_STRING_LEN];
  284. pSetupStringFromGuid(ClassGuid,
  285. ClassGuidString,
  286. SIZECHARS(ClassGuidString)
  287. );
  288. return SetupDiSetDeviceRegistryProperty(hDeviceInfo,
  289. DeviceInfoData,
  290. SPDRP_CLASSGUID,
  291. (LPBYTE)ClassGuidString,
  292. sizeof(ClassGuidString)
  293. );
  294. }
  295. HPROPSHEETPAGE
  296. CreateWizExtPage(
  297. int PageResourceId,
  298. DLGPROC pfnDlgProc,
  299. PNEWDEVWIZ NewDevWiz
  300. )
  301. {
  302. PROPSHEETPAGE psp;
  303. memset(&psp, 0, sizeof(psp));
  304. psp.dwSize = sizeof(PROPSHEETPAGE);
  305. psp.dwFlags = PSP_DEFAULT;
  306. psp.hInstance = hNewDev;
  307. psp.lParam = (LPARAM)NewDevWiz;
  308. psp.pszTemplate = MAKEINTRESOURCE(PageResourceId);
  309. psp.pfnDlgProc = pfnDlgProc;
  310. return CreatePropertySheetPage(&psp);
  311. }
  312. BOOL
  313. AddClassWizExtPages(
  314. HWND hwndParentDlg,
  315. PNEWDEVWIZ NewDevWiz,
  316. PSP_NEWDEVICEWIZARD_DATA DeviceWizardData,
  317. DI_FUNCTION InstallFunction,
  318. HPROPSHEETPAGE hIntroPage
  319. )
  320. {
  321. DWORD NumPages;
  322. BOOL bRet = FALSE;
  323. memset(DeviceWizardData, 0, sizeof(SP_NEWDEVICEWIZARD_DATA));
  324. DeviceWizardData->ClassInstallHeader.InstallFunction = InstallFunction;
  325. DeviceWizardData->ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  326. DeviceWizardData->hwndWizardDlg = hwndParentDlg;
  327. if (SetupDiSetClassInstallParams(NewDevWiz->hDeviceInfo,
  328. &NewDevWiz->DeviceInfoData,
  329. &DeviceWizardData->ClassInstallHeader,
  330. sizeof(SP_NEWDEVICEWIZARD_DATA)
  331. )
  332. &&
  333. (SetupDiCallClassInstaller(InstallFunction,
  334. NewDevWiz->hDeviceInfo,
  335. &NewDevWiz->DeviceInfoData
  336. )
  337. ||
  338. (ERROR_DI_DO_DEFAULT == GetLastError()))
  339. &&
  340. SetupDiGetClassInstallParams(NewDevWiz->hDeviceInfo,
  341. &NewDevWiz->DeviceInfoData,
  342. &DeviceWizardData->ClassInstallHeader,
  343. sizeof(SP_NEWDEVICEWIZARD_DATA),
  344. NULL
  345. )
  346. &&
  347. DeviceWizardData->NumDynamicPages)
  348. {
  349. //
  350. // If this is not a non interactive install and we were given a intro
  351. // page then add it first.
  352. //
  353. PropSheet_AddPage(hwndParentDlg, hIntroPage);
  354. for (NumPages = 0; NumPages < DeviceWizardData->NumDynamicPages; NumPages++) {
  355. //
  356. // If this is a non interactive install then we will destory the property
  357. // sheet pages since we can't display them, otherwise we will add them
  358. // to the wizard.
  359. //
  360. if (pSetupGetGlobalFlags() & PSPGF_NONINTERACTIVE) {
  361. DestroyPropertySheetPage(DeviceWizardData->DynamicPages[NumPages]);
  362. } else {
  363. PropSheet_AddPage(hwndParentDlg, DeviceWizardData->DynamicPages[NumPages]);
  364. }
  365. }
  366. //
  367. // If class/co-installers said they had pages to display then we always return TRUE,
  368. // regardless of if we actually added those pages to the wizard or not.
  369. //
  370. bRet = TRUE;
  371. }
  372. //
  373. // Clear the class install parameters.
  374. //
  375. SetupDiSetClassInstallParams(NewDevWiz->hDeviceInfo,
  376. &NewDevWiz->DeviceInfoData,
  377. NULL,
  378. 0
  379. );
  380. return bRet;
  381. }
  382. BOOL
  383. FileExists(
  384. IN PCTSTR FileName,
  385. OUT PWIN32_FIND_DATA FindData OPTIONAL
  386. )
  387. /*++
  388. Routine Description:
  389. Determine if a file exists and is accessible.
  390. Errormode is set (and then restored) so the user will not see
  391. any pop-ups.
  392. Arguments:
  393. FileName - supplies full path of file to check for existance.
  394. FindData - if specified, receives find data for the file.
  395. Return Value:
  396. TRUE if the file exists and is accessible.
  397. FALSE if not. GetLastError() returns extended error info.
  398. --*/
  399. {
  400. WIN32_FIND_DATA findData;
  401. HANDLE FindHandle;
  402. UINT OldMode;
  403. DWORD Error;
  404. OldMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  405. FindHandle = FindFirstFile(FileName, &findData);
  406. if(FindHandle == INVALID_HANDLE_VALUE) {
  407. Error = GetLastError();
  408. } else {
  409. FindClose(FindHandle);
  410. if(FindData) {
  411. *FindData = findData;
  412. }
  413. Error = NO_ERROR;
  414. }
  415. SetErrorMode(OldMode);
  416. SetLastError(Error);
  417. return (Error == NO_ERROR);
  418. }
  419. BOOL
  420. pVerifyUpdateDriverInfoPath(
  421. PNEWDEVWIZ NewDevWiz
  422. )
  423. /*++
  424. This API will verify that the selected driver node lives in the path
  425. specified in UpdateDriverInfo->InfPathName.
  426. Return Value:
  427. This API will return TRUE in all cases except where we have a valid
  428. UpdateDriverInfo structure and a valid InfPathName field and that
  429. path does not match the path where the selected driver lives.
  430. --*/
  431. {
  432. SP_DRVINFO_DATA DriverInfoData;
  433. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  434. //
  435. // If we don't have a UpdateDriverInfo structure or a valid InfPathName field
  436. // in that structure then just return TRUE now.
  437. //
  438. if (!NewDevWiz->UpdateDriverInfo || !NewDevWiz->UpdateDriverInfo->InfPathName) {
  439. return TRUE;
  440. }
  441. //
  442. // Get the selected driver's path
  443. //
  444. ZeroMemory(&DriverInfoData, sizeof(DriverInfoData));
  445. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  446. if (!SetupDiGetSelectedDriver(NewDevWiz->hDeviceInfo,
  447. &NewDevWiz->DeviceInfoData,
  448. &DriverInfoData
  449. )) {
  450. //
  451. // There is no selected driver so just return TRUE
  452. //
  453. return TRUE;
  454. }
  455. DriverInfoDetailData.cbSize = sizeof(DriverInfoDetailData);
  456. if (!SetupDiGetDriverInfoDetail(NewDevWiz->hDeviceInfo,
  457. &NewDevWiz->DeviceInfoData,
  458. &DriverInfoData,
  459. &DriverInfoDetailData,
  460. sizeof(DriverInfoDetailData),
  461. NULL
  462. )
  463. &&
  464. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  465. //
  466. // We should never hit this case, but if we have a selected driver and
  467. // we can't get the SP_DRVINFO_DETAIL_DATA that contains the InfFileName
  468. // the return FALSE.
  469. //
  470. return FALSE;
  471. }
  472. if (lstrlen(NewDevWiz->UpdateDriverInfo->InfPathName) ==
  473. lstrlen(DriverInfoDetailData.InfFileName)) {
  474. //
  475. // If the two paths are the same size then we will just compare them
  476. //
  477. return (!lstrcmpi(NewDevWiz->UpdateDriverInfo->InfPathName,
  478. DriverInfoDetailData.InfFileName));
  479. } else {
  480. //
  481. // The two paths are different lengths so we'll tack a trailing backslash
  482. // onto the UpdateDriverInfo->InfPathName and then do a _tcsnicmp
  483. // NOTE that we only tack on a trailing backslash if the length of the
  484. // path is greater than two since it isn't needed on the driver letter
  485. // followed by a colon case (A:).
  486. //
  487. // The reason we do this is we don't want the following case to match
  488. // c:\winnt\in
  489. // c:\winnt\inf\foo.inf
  490. //
  491. TCHAR TempPath[MAX_PATH];
  492. if (FAILED(StringCchCopy(TempPath, SIZECHARS(TempPath), NewDevWiz->UpdateDriverInfo->InfPathName))) {
  493. //
  494. // If we were passed in a path greater than MAX_PATH then just return FALSE.
  495. //
  496. return FALSE;
  497. }
  498. if (lstrlen(NewDevWiz->UpdateDriverInfo->InfPathName) > 2) {
  499. if (FAILED(StringCchCat(TempPath, SIZECHARS(TempPath), TEXT("\\")))) {
  500. //
  501. // If we were passed in a path of MAX_PATH size and we can't add a
  502. // backslash on the end, then just return FALSE.
  503. //
  504. return FALSE;
  505. }
  506. }
  507. return (!_tcsnicmp(TempPath,
  508. DriverInfoDetailData.InfFileName,
  509. lstrlen(TempPath)));
  510. }
  511. }
  512. BOOL
  513. RemoveDir(
  514. PTSTR Path
  515. )
  516. /*++
  517. Routine Description:
  518. This routine recursively deletes the specified directory and all the
  519. files in it.
  520. Arguments:
  521. Path - Path to remove.
  522. Return Value:
  523. TRUE - if the directory was sucessfully deleted.
  524. FALSE - if the directory was not successfully deleted.
  525. --*/
  526. {
  527. WIN32_FIND_DATA FindFileData;
  528. HANDLE hFind;
  529. BOOL bFind = TRUE;
  530. BOOL Ret = TRUE;
  531. TCHAR szTemp[MAX_PATH];
  532. TCHAR FindPath[MAX_PATH];
  533. DWORD dwAttributes;
  534. if (FAILED(StringCchCopy(FindPath, SIZECHARS(FindPath), Path))) {
  535. //
  536. // If the specified Path does not fit in our local buffer then
  537. // fail now, since we don't want to delete a partial path!
  538. //
  539. return FALSE;
  540. }
  541. //
  542. //If this is a directory then tack on *.* to the end of the path
  543. //
  544. dwAttributes = GetFileAttributes(Path);
  545. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  546. if (!pSetupConcatenatePaths(FindPath,TEXT("*.*"),MAX_PATH,NULL)) {
  547. //
  548. // We can't tack *.* onto the end so bail out now, otherwise
  549. // we won't be deleting what we think we should be deleting.
  550. //
  551. return FALSE;
  552. }
  553. }
  554. hFind = FindFirstFile(FindPath, &FindFileData);
  555. while ((hFind != INVALID_HANDLE_VALUE) && (bFind == TRUE)) {
  556. //
  557. // Only process the directory, or delete the file, if we can
  558. // fit the path and filename in our buffer, otherwise we could
  559. // delete some other file!
  560. //
  561. if (SUCCEEDED(StringCchCopy(szTemp, SIZECHARS(szTemp), Path)) &&
  562. pSetupConcatenatePaths(szTemp,FindFileData.cFileName,SIZECHARS(szTemp),NULL)) {
  563. if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
  564. //
  565. // Handle the reparse point case.
  566. //
  567. HANDLE hReparsePoint = INVALID_HANDLE_VALUE;
  568. hReparsePoint = CreateFile(szTemp,
  569. DELETE,
  570. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  571. NULL,
  572. OPEN_EXISTING,
  573. FILE_FLAG_DELETE_ON_CLOSE | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
  574. NULL
  575. );
  576. if (hReparsePoint != INVALID_HANDLE_VALUE) {
  577. CloseHandle(hReparsePoint);
  578. }
  579. } else if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  580. //
  581. // Handle the directory case.
  582. //
  583. // NOTE: Do not follow the . or .. directories or we will be
  584. // spinning forever.
  585. //
  586. if ((lstrcmp(FindFileData.cFileName, TEXT(".")) != 0) &&
  587. (lstrcmp(FindFileData.cFileName, TEXT("..")) != 0)) {
  588. if (!RemoveDir(szTemp)) {
  589. Ret = FALSE;
  590. }
  591. RemoveDirectory(szTemp);
  592. }
  593. } else {
  594. //
  595. // Handle the file case.
  596. // Make sure to clear off any hidden, read-only, or system
  597. // attributes off of the file.
  598. //
  599. SetFileAttributes(szTemp, FILE_ATTRIBUTE_NORMAL);
  600. DeleteFile(szTemp);
  601. }
  602. }
  603. bFind = FindNextFile(hFind, &FindFileData);
  604. }
  605. FindClose(hFind);
  606. //
  607. //Remove the root directory
  608. //
  609. dwAttributes = GetFileAttributes(Path);
  610. if (dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  611. if (!RemoveDirectory(Path)) {
  612. Ret = FALSE;
  613. }
  614. }
  615. return Ret;
  616. }
  617. BOOL
  618. pAToI(
  619. IN PCTSTR Field,
  620. OUT PINT IntegerValue
  621. )
  622. /*++
  623. Routine Description:
  624. Arguments:
  625. Return Value:
  626. Remarks:
  627. Hexadecimal numbers are also supported. They must be prefixed by '0x' or '0X', with no
  628. space allowed between the prefix and the number.
  629. --*/
  630. {
  631. INT Value;
  632. UINT c;
  633. BOOL Neg;
  634. UINT Base;
  635. UINT NextDigitValue;
  636. INT OverflowCheck;
  637. BOOL b;
  638. if(!Field) {
  639. SetLastError(ERROR_INVALID_PARAMETER);
  640. return(FALSE);
  641. }
  642. if(*Field == TEXT('-')) {
  643. Neg = TRUE;
  644. Field++;
  645. } else {
  646. Neg = FALSE;
  647. if(*Field == TEXT('+')) {
  648. Field++;
  649. }
  650. }
  651. if ((*Field == TEXT('0')) &&
  652. ((*(Field+1) == TEXT('x')) || (*(Field+1) == TEXT('X')))) {
  653. //
  654. // The number is in hexadecimal.
  655. //
  656. Base = 16;
  657. Field += 2;
  658. } else {
  659. //
  660. // The number is in decimal.
  661. //
  662. Base = 10;
  663. }
  664. for(OverflowCheck = Value = 0; *Field; Field++) {
  665. c = (UINT)*Field;
  666. if((c >= (UINT)'0') && (c <= (UINT)'9')) {
  667. NextDigitValue = c - (UINT)'0';
  668. } else if(Base == 16) {
  669. if((c >= (UINT)'a') && (c <= (UINT)'f')) {
  670. NextDigitValue = (c - (UINT)'a') + 10;
  671. } else if ((c >= (UINT)'A') && (c <= (UINT)'F')) {
  672. NextDigitValue = (c - (UINT)'A') + 10;
  673. } else {
  674. break;
  675. }
  676. } else {
  677. break;
  678. }
  679. Value *= Base;
  680. Value += NextDigitValue;
  681. //
  682. // Check for overflow. For decimal numbers, we check to see whether the
  683. // new value has overflowed into the sign bit (i.e., is less than the
  684. // previous value. For hexadecimal numbers, we check to make sure we
  685. // haven't gotten more digits than will fit in a DWORD.
  686. //
  687. if(Base == 16) {
  688. if(++OverflowCheck > (sizeof(INT) * 2)) {
  689. break;
  690. }
  691. } else {
  692. if(Value < OverflowCheck) {
  693. break;
  694. } else {
  695. OverflowCheck = Value;
  696. }
  697. }
  698. }
  699. if(*Field) {
  700. SetLastError(ERROR_INVALID_DATA);
  701. return(FALSE);
  702. }
  703. if(Neg) {
  704. Value = 0-Value;
  705. }
  706. b = TRUE;
  707. try {
  708. *IntegerValue = Value;
  709. } except(EXCEPTION_EXECUTE_HANDLER) {
  710. b = FALSE;
  711. }
  712. if(!b) {
  713. SetLastError(ERROR_INVALID_PARAMETER);
  714. }
  715. return(b);
  716. }
  717. void
  718. RemoveCdmDirectory(
  719. PTSTR CdmDirectory
  720. )
  721. {
  722. TCHAR ReinstallBackupDirectory[MAX_PATH];
  723. //
  724. // First verify that this directory is a subdirectory of %windir%\system32\ReinstallBackups
  725. //
  726. if (GetSystemDirectory(ReinstallBackupDirectory, SIZECHARS(ReinstallBackupDirectory)) &&
  727. pSetupConcatenatePaths(ReinstallBackupDirectory, TEXT("ReinstallBackups"), SIZECHARS(ReinstallBackupDirectory), NULL)) {
  728. do {
  729. PTSTR p = _tcsrchr(CdmDirectory, TEXT('\\'));
  730. if (!p) {
  731. break;
  732. }
  733. *p = 0;
  734. if (_tcsnicmp(CdmDirectory,
  735. ReinstallBackupDirectory,
  736. lstrlen(ReinstallBackupDirectory))) {
  737. //
  738. // This is not a subdirectory of the ReinstallBackups directory, so don't
  739. // delete it!
  740. //
  741. break;
  742. }
  743. if (!lstrcmpi(CdmDirectory,
  744. ReinstallBackupDirectory)) {
  745. //
  746. // We have reached the actuall ReinstallBackups directory so stop deleting!
  747. //
  748. break;
  749. }
  750. } while (RemoveDir(CdmDirectory));
  751. }
  752. }
  753. BOOL
  754. pSetupGetDriverDate(
  755. IN PCTSTR DriverVer,
  756. IN OUT PFILETIME pFileTime
  757. )
  758. /*++
  759. Routine Description:
  760. Retreive the date from a DriverVer string.
  761. The Date specified in DriverVer string has the following format:
  762. DriverVer=xx/yy/zzzz
  763. or
  764. DriverVer=xx-yy-zzzz
  765. where xx is the month, yy is the day, and zzzz is the for digit year.
  766. Note that the year MUST be 4 digits. A year of 98 will be considered
  767. 0098 and not 1998!
  768. This date should be the date of the Drivers and not for the INF itself.
  769. So a single INF can have multiple driver install Sections and each can
  770. have different dates depending on when the driver was last updated.
  771. Arguments:
  772. DriverVer - String that holds the DriverVer entry from an INF file.
  773. pFileTime - points to a FILETIME structure that will receive the Date,
  774. if it exists.
  775. Return Value:
  776. BOOL. TRUE if a valid date existed in the specified string and FALSE otherwise.
  777. --*/
  778. {
  779. SYSTEMTIME SystemTime;
  780. TCHAR DriverDate[LINE_LEN];
  781. PTSTR Convert, Temp;
  782. DWORD Value;
  783. if (!DriverVer) {
  784. SetLastError(ERROR_INVALID_PARAMETER);
  785. return FALSE;
  786. }
  787. try {
  788. *DriverDate = 0;
  789. ZeroMemory(&SystemTime, sizeof(SystemTime));
  790. pFileTime->dwLowDateTime = 0;
  791. pFileTime->dwHighDateTime = 0;
  792. //
  793. // First copy just the DriverDate portion of the DriverVer into the DriverDate
  794. // variable. The DriverDate should be everything before the first comma.
  795. // If this can't fit, then someone put bad data into their INF, so just treat
  796. // the driver date as 0/0/0000 and the time as 0.
  797. //
  798. if (SUCCEEDED(StringCchCopy(DriverDate, SIZECHARS(DriverDate), DriverVer))) {
  799. Temp = DriverDate;
  800. while (*Temp && (*Temp != TEXT(','))) {
  801. Temp++;
  802. }
  803. if (*Temp) {
  804. *Temp = TEXT('\0');
  805. }
  806. Convert = DriverDate;
  807. if (*Convert) {
  808. Temp = DriverDate;
  809. while (*Temp && (*Temp != TEXT('-')) && (*Temp != TEXT('/')))
  810. Temp++;
  811. if (*Temp == TEXT('\0')) {
  812. //
  813. // There is no day or year in this date, so exit.
  814. //
  815. goto clean0;
  816. }
  817. *Temp = 0;
  818. //
  819. //Convert the month
  820. //
  821. pAToI(Convert, (PINT)&Value);
  822. SystemTime.wMonth = LOWORD(Value);
  823. Convert = Temp+1;
  824. if (*Convert) {
  825. Temp = Convert;
  826. while (*Temp && (*Temp != TEXT('-')) && (*Temp != TEXT('/')))
  827. Temp++;
  828. if (*Temp == TEXT('\0')) {
  829. //
  830. // There is no year in this date, so exit.
  831. //
  832. goto clean0;
  833. }
  834. *Temp = 0;
  835. //
  836. //Convert the day
  837. //
  838. pAToI(Convert, (PINT)&Value);
  839. SystemTime.wDay = LOWORD(Value);
  840. Convert = Temp+1;
  841. if (*Convert) {
  842. //
  843. //Convert the year
  844. //
  845. pAToI(Convert, (PINT)&Value);
  846. SystemTime.wYear = LOWORD(Value);
  847. //
  848. //Convert SYSTEMTIME into FILETIME
  849. //
  850. SystemTimeToFileTime(&SystemTime, pFileTime);
  851. }
  852. }
  853. }
  854. }
  855. clean0:;
  856. } except(EXCEPTION_EXECUTE_HANDLER) {
  857. SetLastError(ERROR_INVALID_PARAMETER);
  858. return FALSE;
  859. }
  860. SetLastError(NO_ERROR);
  861. return((pFileTime->dwLowDateTime != 0) || (pFileTime->dwHighDateTime != 0));
  862. }
  863. BOOL
  864. IsInternetAvailable(
  865. HMODULE *hCdmInstance
  866. )
  867. {
  868. CDM_INTERNET_AVAILABLE_PROC pfnCDMInternetAvailable;
  869. if (!hCdmInstance) {
  870. return FALSE;
  871. }
  872. //
  873. // We can't call CDM during GUI setup.
  874. //
  875. if (GuiSetupInProgress) {
  876. return FALSE;
  877. }
  878. //
  879. // Load CDM.DLL if it is not already loaded
  880. //
  881. if (!(*hCdmInstance)) {
  882. *hCdmInstance = LoadLibrary(TEXT("CDM.DLL"));
  883. }
  884. if (!(*hCdmInstance)) {
  885. return FALSE;
  886. }
  887. pfnCDMInternetAvailable = (CDM_INTERNET_AVAILABLE_PROC)GetProcAddress(*hCdmInstance,
  888. "DownloadIsInternetAvailable"
  889. );
  890. if (!pfnCDMInternetAvailable) {
  891. return FALSE;
  892. }
  893. return pfnCDMInternetAvailable();
  894. }
  895. BOOL
  896. GetLogPnPIdPolicy(
  897. )
  898. /*++
  899. Routine Description:
  900. This function checks the policy portion of the registry to see if the user wants
  901. us to log the Hardware Id for devices that we cannot find drivers for.
  902. Arguments:
  903. none
  904. Return Value:
  905. BOOL - TRUE if we can log the Hardware Id and FALSE if the policy tells us not
  906. to log the hardware Id.
  907. --*/
  908. {
  909. HKEY hKey;
  910. DWORD LogPnPIdPolicy;
  911. ULONG cbData;
  912. BOOL bLogHardwareIds = TRUE;
  913. //
  914. // If we are in gui-setup then we can't log hardware Ids, so always return
  915. // FALSE.
  916. //
  917. if (GuiSetupInProgress) {
  918. return FALSE;
  919. }
  920. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  921. TEXT("Software\\Policies\\Microsoft\\Windows\\DriverSearching"),
  922. 0,
  923. KEY_READ,
  924. &hKey
  925. ) == ERROR_SUCCESS) {
  926. LogPnPIdPolicy = 0;
  927. cbData = sizeof(LogPnPIdPolicy);
  928. if ((RegQueryValueEx(hKey,
  929. TEXT("DontLogHardwareIds"),
  930. NULL,
  931. NULL,
  932. (LPBYTE)&LogPnPIdPolicy,
  933. &cbData
  934. ) == ERROR_SUCCESS) &&
  935. (LogPnPIdPolicy)) {
  936. bLogHardwareIds = FALSE;
  937. }
  938. RegCloseKey(hKey);
  939. }
  940. return (bLogHardwareIds);
  941. }
  942. void
  943. CdmLogDriverNotFound(
  944. HMODULE hCdmInstance,
  945. HANDLE hContext,
  946. LPCTSTR DeviceInstanceId,
  947. DWORD Flags
  948. )
  949. {
  950. LOG_DRIVER_NOT_FOUND_PROC pfnLogDriverNotFound;
  951. if (!hCdmInstance) {
  952. return;
  953. }
  954. pfnLogDriverNotFound = (LOG_DRIVER_NOT_FOUND_PROC)GetProcAddress(hCdmInstance,
  955. "LogDriverNotFound"
  956. );
  957. if (!pfnLogDriverNotFound) {
  958. return;
  959. }
  960. pfnLogDriverNotFound(hContext, DeviceInstanceId, Flags);
  961. }
  962. void
  963. CdmCancelCDMOperation(
  964. HMODULE hCdmInstance
  965. )
  966. {
  967. CANCEL_CDM_OPERATION_PROC pfnCancelCDMOperation;
  968. if (!hCdmInstance) {
  969. return;
  970. }
  971. pfnCancelCDMOperation = (CANCEL_CDM_OPERATION_PROC)GetProcAddress(hCdmInstance,
  972. "CancelCDMOperation"
  973. );
  974. if (!pfnCancelCDMOperation) {
  975. return;
  976. }
  977. pfnCancelCDMOperation();
  978. }
  979. BOOL
  980. GetInstalledInf(
  981. IN DEVNODE DevNode, OPTIONAL
  982. IN PTSTR DeviceInstanceId, OPTIONAL
  983. IN OUT PTSTR InfFile,
  984. IN OUT DWORD *Size
  985. )
  986. {
  987. DEVNODE dn;
  988. HKEY hKey = INVALID_HANDLE_VALUE;
  989. DWORD dwType;
  990. BOOL bSuccess = FALSE;
  991. if (DevNode != 0) {
  992. dn = DevNode;
  993. } else if (CM_Locate_DevNode(&dn, DeviceInstanceId, 0) != CR_SUCCESS) {
  994. goto clean0;
  995. }
  996. //
  997. // Open the device's driver (software) registry key so we can get the InfPath
  998. //
  999. if (CM_Open_DevNode_Key(dn,
  1000. KEY_READ,
  1001. 0,
  1002. RegDisposition_OpenExisting,
  1003. &hKey,
  1004. CM_REGISTRY_SOFTWARE
  1005. ) != CR_SUCCESS) {
  1006. goto clean0;
  1007. }
  1008. if (hKey != INVALID_HANDLE_VALUE) {
  1009. dwType = REG_SZ;
  1010. if (RegQueryValueEx(hKey,
  1011. REGSTR_VAL_INFPATH,
  1012. NULL,
  1013. &dwType,
  1014. (LPBYTE)InfFile,
  1015. Size
  1016. ) == ERROR_SUCCESS) {
  1017. bSuccess = TRUE;
  1018. }
  1019. }
  1020. clean0:
  1021. if (hKey != INVALID_HANDLE_VALUE) {
  1022. RegCloseKey(hKey);
  1023. }
  1024. return bSuccess;
  1025. }
  1026. BOOL
  1027. IsInfFromOem(
  1028. IN PCTSTR InfFile
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. Determine if an Inf is an OEM Inf.
  1033. Arguments:
  1034. InfFile - supplies name of Inf file.
  1035. Return Value:
  1036. BOOL. TRUE if the InfFile is an OEM Inf file, and FALSE otherwise.
  1037. --*/
  1038. {
  1039. PTSTR p;
  1040. //
  1041. // Make sure we are passed a valid Inf file and it's length is at least 8
  1042. // chararacters or more for oemX.inf
  1043. if (!InfFile ||
  1044. (InfFile[0] == TEXT('\0')) ||
  1045. (lstrlen(InfFile) < 8)) {
  1046. return FALSE;
  1047. }
  1048. //
  1049. // First check that the first 3 characters are OEM
  1050. //
  1051. if (_tcsnicmp(InfFile, TEXT("oem"), 3)) {
  1052. return FALSE;
  1053. }
  1054. //
  1055. // Next verify that any characters after "oem" and before ".inf"
  1056. // are digits.
  1057. //
  1058. p = (PTSTR)InfFile;
  1059. p = CharNext(p);
  1060. p = CharNext(p);
  1061. p = CharNext(p);
  1062. while ((*p != TEXT('\0')) && (*p != TEXT('.'))) {
  1063. if ((*p < TEXT('0')) || (*p > TEXT('9'))) {
  1064. return FALSE;
  1065. }
  1066. p = CharNext(p);
  1067. }
  1068. //
  1069. // Finally, verify that the last 4 characters are ".inf"
  1070. //
  1071. if (_wcsicmp(p, TEXT(".inf"))) {
  1072. return FALSE;
  1073. }
  1074. //
  1075. // This is an OEM Inf file
  1076. //
  1077. return TRUE;
  1078. }
  1079. BOOL
  1080. IsConnectedToInternet()
  1081. {
  1082. DWORD dwFlags = INTERNET_CONNECTION_LAN |
  1083. INTERNET_CONNECTION_MODEM |
  1084. INTERNET_CONNECTION_PROXY;
  1085. //
  1086. // If we are in gui-setup then return FALSE since we can't connect to the
  1087. // Internet at this time, and since the network is not fully installed yet
  1088. // bad things can happen when we call Inet APIs.
  1089. //
  1090. if (GuiSetupInProgress) {
  1091. return FALSE;
  1092. }
  1093. return InternetGetConnectedState(&dwFlags, 0);
  1094. }
  1095. DWORD
  1096. GetSearchOptions(
  1097. void
  1098. )
  1099. {
  1100. DWORD SearchOptions = SEARCH_FLOPPY;
  1101. DWORD cbData;
  1102. HKEY hKeyDeviceInstaller;
  1103. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  1104. REGSTR_PATH_DEVICEINSTALLER,
  1105. 0,
  1106. KEY_READ,
  1107. &hKeyDeviceInstaller
  1108. ) == ERROR_SUCCESS) {
  1109. cbData = sizeof(SearchOptions);
  1110. if (RegQueryValueEx(hKeyDeviceInstaller,
  1111. REGSTR_VAL_SEARCHOPTIONS,
  1112. NULL,
  1113. NULL,
  1114. (LPBYTE)&SearchOptions,
  1115. &cbData
  1116. ) != ERROR_SUCCESS) {
  1117. SearchOptions = SEARCH_FLOPPY;
  1118. }
  1119. RegCloseKey(hKeyDeviceInstaller);
  1120. }
  1121. return SearchOptions;
  1122. }
  1123. VOID
  1124. SetSearchOptions(
  1125. DWORD SearchOptions
  1126. )
  1127. {
  1128. HKEY hKeyDeviceInstaller;
  1129. if (RegCreateKeyEx(HKEY_CURRENT_USER,
  1130. REGSTR_PATH_DEVICEINSTALLER,
  1131. 0,
  1132. NULL,
  1133. REG_OPTION_NON_VOLATILE,
  1134. KEY_WRITE,
  1135. NULL,
  1136. &hKeyDeviceInstaller,
  1137. NULL) == ERROR_SUCCESS) {
  1138. RegSetValueEx(hKeyDeviceInstaller,
  1139. REGSTR_VAL_SEARCHOPTIONS,
  1140. 0,
  1141. REG_DWORD,
  1142. (LPBYTE)&SearchOptions,
  1143. sizeof(SearchOptions)
  1144. );
  1145. RegCloseKey(hKeyDeviceInstaller);
  1146. }
  1147. }
  1148. BOOL
  1149. IsInstallComplete(
  1150. HDEVINFO hDevInfo,
  1151. PSP_DEVINFO_DATA DeviceInfoData
  1152. )
  1153. /*++
  1154. Routine Description:
  1155. This routine determines whether the install is complete on the specified
  1156. device or not. If a device has configflags and CONFIGFLAG_REINSTALL and
  1157. CONFIGFLAG_FINISH_INSTALL are not set then the install is considered
  1158. complete.
  1159. This API is needed since we could bring up the Found New Hardware wizard
  1160. for one user and another user can switch away to their session. Umpnpmgr.dll
  1161. will prompt the new user to install drivers as well. If the new user does
  1162. complete the device install then we want the first user's Found New
  1163. Hardware wizard to go away as well.
  1164. Arguments:
  1165. hDevInfo -
  1166. DeviceInfoData -
  1167. Return Value:
  1168. BOOL. TRUE if the installation is complete and FALSE otherwise.
  1169. --*/
  1170. {
  1171. BOOL bDriverInstalled = FALSE;
  1172. DWORD ConfigFlags = 0;
  1173. if (SetupDiGetDeviceRegistryProperty(hDevInfo,
  1174. DeviceInfoData,
  1175. SPDRP_CONFIGFLAGS,
  1176. NULL,
  1177. (PBYTE)&ConfigFlags,
  1178. sizeof(ConfigFlags),
  1179. NULL) &&
  1180. !(ConfigFlags & CONFIGFLAG_REINSTALL) &&
  1181. !(ConfigFlags & CONFIGFLAG_FINISH_INSTALL)) {
  1182. bDriverInstalled = TRUE;
  1183. }
  1184. return bDriverInstalled;
  1185. }
  1186. BOOL
  1187. GetIsWow64 (
  1188. VOID
  1189. )
  1190. /*++
  1191. Routine Description:
  1192. Determine if we're running on WOW64 or not. This will tell us if somebody
  1193. is calling the 32-bit version of newdev.dll on a 64-bit machine.
  1194. We call the GetSystemWow64Directory API, and if it fails and GetLastError()
  1195. returns ERROR_CALL_NOT_IMPLENETED then this means we are on a 32-bit OS.
  1196. Arguments:
  1197. none
  1198. Return value:
  1199. TRUE if running under WOw64 (and special Wow64 features available)
  1200. --*/
  1201. {
  1202. #ifdef _WIN64
  1203. //
  1204. // If this is the 64-bit version of newdev.dll then always return FALSE.
  1205. //
  1206. return FALSE;
  1207. #else
  1208. TCHAR Wow64Directory[MAX_PATH];
  1209. if ((GetSystemWow64Directory(Wow64Directory, SIZECHARS(Wow64Directory)) == 0) &&
  1210. (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)) {
  1211. return FALSE;
  1212. }
  1213. //
  1214. // GetSystemWow64Directory succeeded so we are on a 64-bit OS.
  1215. //
  1216. return TRUE;
  1217. #endif
  1218. }
  1219. BOOL
  1220. OpenCdmContextIfNeeded(
  1221. HMODULE *hCdmInstance,
  1222. HANDLE *hCdmContext
  1223. )
  1224. {
  1225. OPEN_CDM_CONTEXT_EX_PROC pfnOpenCDMContextEx;
  1226. //
  1227. // We can't load CDM if we are in the gui-setup.
  1228. //
  1229. if (GuiSetupInProgress) {
  1230. return FALSE;
  1231. }
  1232. //
  1233. // First check to see if they are already loaded
  1234. //
  1235. if (*hCdmInstance && *hCdmContext) {
  1236. return TRUE;
  1237. }
  1238. //
  1239. // Load CDM.DLL if it is not already loaded
  1240. //
  1241. if (!(*hCdmInstance)) {
  1242. *hCdmInstance = LoadLibrary(TEXT("CDM.DLL"));
  1243. }
  1244. if (*hCdmInstance) {
  1245. //
  1246. // Get a context handle to Cdm.dll by calling OpenCDMContextEx(FALSE).
  1247. // By passing FALSE we are telling CDM.DLL to not connect to the Internet
  1248. // if there isn't currently a connection.
  1249. //
  1250. if (!(*hCdmContext)) {
  1251. pfnOpenCDMContextEx = (OPEN_CDM_CONTEXT_EX_PROC)GetProcAddress(*hCdmInstance,
  1252. "OpenCDMContextEx"
  1253. );
  1254. if (pfnOpenCDMContextEx) {
  1255. *hCdmContext = pfnOpenCDMContextEx(FALSE);
  1256. }
  1257. }
  1258. }
  1259. if (*hCdmInstance && *hCdmContext) {
  1260. return TRUE;
  1261. } else {
  1262. return FALSE;
  1263. }
  1264. }
  1265. BOOL
  1266. pSetSystemRestorePoint(
  1267. BOOL Begin,
  1268. BOOL CancelOperation,
  1269. int RestorePointResourceId
  1270. )
  1271. {
  1272. RESTOREPOINTINFO RestorePointInfo;
  1273. STATEMGRSTATUS SMgrStatus;
  1274. SRSETRESTOREPOINT pfnSrSetRestorePoint;
  1275. BOOL b = FALSE;
  1276. if (!hSrClientDll) {
  1277. hSrClientDll = LoadLibrary(TEXT("SRCLIENT.DLL"));
  1278. if (!hSrClientDll) {
  1279. return FALSE;
  1280. }
  1281. }
  1282. pfnSrSetRestorePoint = (SRSETRESTOREPOINT)GetProcAddress(hSrClientDll,
  1283. "SRSetRestorePointW"
  1284. );
  1285. //
  1286. // If we can't get the proc address for SRSetRestorePoint then just
  1287. // free the library.
  1288. //
  1289. if (!pfnSrSetRestorePoint) {
  1290. FreeLibrary(hSrClientDll);
  1291. hSrClientDll = FALSE;
  1292. return FALSE;
  1293. }
  1294. //
  1295. // Set the system restore point.
  1296. //
  1297. RestorePointInfo.dwEventType = Begin
  1298. ? BEGIN_NESTED_SYSTEM_CHANGE
  1299. : END_NESTED_SYSTEM_CHANGE;
  1300. RestorePointInfo.dwRestorePtType = CancelOperation
  1301. ? CANCELLED_OPERATION
  1302. : DEVICE_DRIVER_INSTALL;
  1303. RestorePointInfo.llSequenceNumber = 0;
  1304. if (RestorePointResourceId) {
  1305. if (!LoadString(hNewDev,
  1306. RestorePointResourceId,
  1307. (LPTSTR)RestorePointInfo.szDescription,
  1308. SIZECHARS(RestorePointInfo.szDescription)
  1309. )) {
  1310. RestorePointInfo.szDescription[0] = TEXT('\0');
  1311. }
  1312. } else {
  1313. RestorePointInfo.szDescription[0] = TEXT('\0');
  1314. }
  1315. b = pfnSrSetRestorePoint(&RestorePointInfo, &SMgrStatus);
  1316. //
  1317. // If we are calling END_NESTED_SYSTEM_CHANGE then unload the srclient.dll
  1318. // since we won't be needing it again.
  1319. //
  1320. if (!Begin) {
  1321. FreeLibrary(hSrClientDll);
  1322. hSrClientDll = FALSE;
  1323. }
  1324. return b;
  1325. }
  1326. BOOL
  1327. GetProcessorExtension(
  1328. LPTSTR ProcessorExtension,
  1329. DWORD ProcessorExtensionSize
  1330. )
  1331. {
  1332. SYSTEM_INFO SystemInfo;
  1333. BOOL bReturn = TRUE;
  1334. ZeroMemory(&SystemInfo, sizeof(SystemInfo));
  1335. GetSystemInfo(&SystemInfo);
  1336. switch(SystemInfo.wProcessorArchitecture) {
  1337. case PROCESSOR_ARCHITECTURE_INTEL:
  1338. if (FAILED(StringCchCopy(ProcessorExtension, ProcessorExtensionSize, TEXT("i386")))) {
  1339. bReturn = FALSE;
  1340. }
  1341. break;
  1342. case PROCESSOR_ARCHITECTURE_IA64:
  1343. if (FAILED(StringCchCopy(ProcessorExtension, ProcessorExtensionSize, TEXT("IA64")))) {
  1344. bReturn = FALSE;
  1345. }
  1346. break;
  1347. case PROCESSOR_ARCHITECTURE_MSIL:
  1348. if (FAILED(StringCchCopy(ProcessorExtension, ProcessorExtensionSize, TEXT("MSIL")))) {
  1349. bReturn = FALSE;
  1350. }
  1351. break;
  1352. case PROCESSOR_ARCHITECTURE_AMD64:
  1353. if (FAILED(StringCchCopy(ProcessorExtension, ProcessorExtensionSize, TEXT("AMD64")))) {
  1354. bReturn = FALSE;
  1355. }
  1356. break;
  1357. default:
  1358. ASSERT(0);
  1359. bReturn = FALSE;
  1360. break;
  1361. }
  1362. return bReturn;
  1363. }
  1364. BOOL
  1365. GetGuiSetupInProgress(
  1366. VOID
  1367. )
  1368. /*++
  1369. Routine Description:
  1370. This routine determines if we're doing a gui-mode setup.
  1371. This value is retrieved from the following registry location:
  1372. \HKLM\System\Setup\
  1373. SystemSetupInProgress : REG_DWORD : 0x00 (where nonzero means we're doing a gui-setup)
  1374. Arguments:
  1375. None.
  1376. Return Value:
  1377. TRUE if we are in gui-mode setup, FALSE otherwise.
  1378. --*/
  1379. {
  1380. HKEY hKey;
  1381. DWORD Err, DataType, DataSize = sizeof(DWORD);
  1382. DWORD Value = 0;
  1383. if((Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1384. TEXT("System\\Setup"),
  1385. 0,
  1386. KEY_READ,
  1387. &hKey)) == ERROR_SUCCESS) {
  1388. //
  1389. // Attempt to read the the "SystemSetupInProgress" value.
  1390. //
  1391. Err = RegQueryValueEx(
  1392. hKey,
  1393. TEXT("SystemSetupInProgress"),
  1394. NULL,
  1395. &DataType,
  1396. (LPBYTE)&Value,
  1397. &DataSize);
  1398. RegCloseKey(hKey);
  1399. }
  1400. if(Err == NO_ERROR) {
  1401. if(Value) {
  1402. return(TRUE);
  1403. }
  1404. }
  1405. return(FALSE);
  1406. }
  1407. DWORD
  1408. GetBusInformation(
  1409. DEVNODE DevNode
  1410. )
  1411. /*++
  1412. Routine Description:
  1413. This routine retrieves the bus information flags.
  1414. Arguments:
  1415. DeviceInfoSet -
  1416. DeviceInfoData -
  1417. Return Value:
  1418. DWORD that contains the bus information flags.
  1419. --*/
  1420. {
  1421. GUID BusTypeGuid;
  1422. TCHAR BusTypeGuidString[MAX_GUID_STRING_LEN];
  1423. HKEY hBusInformationKey;
  1424. DWORD BusInformation = 0;
  1425. DWORD dwType, cbData;
  1426. //
  1427. // Get the bus type GUID for this device.
  1428. //
  1429. cbData = sizeof(BusTypeGuid);
  1430. if (CM_Get_DevNode_Registry_Property(DevNode,
  1431. CM_DRP_BUSTYPEGUID,
  1432. &dwType,
  1433. (PVOID)&BusTypeGuid,
  1434. &cbData,
  1435. 0) != CR_SUCCESS) {
  1436. goto clean0;
  1437. }
  1438. //
  1439. // Convert the bus type GUID into a string.
  1440. //
  1441. if (pSetupStringFromGuid(&BusTypeGuid,
  1442. BusTypeGuidString,
  1443. SIZECHARS(BusTypeGuidString)
  1444. ) != NO_ERROR) {
  1445. goto clean0;
  1446. }
  1447. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1448. REGSTR_PATH_BUSINFORMATION,
  1449. 0,
  1450. KEY_READ,
  1451. &hBusInformationKey
  1452. ) != ERROR_SUCCESS) {
  1453. goto clean0;
  1454. }
  1455. cbData = sizeof(BusInformation);
  1456. if (RegQueryValueEx(hBusInformationKey,
  1457. BusTypeGuidString,
  1458. NULL,
  1459. &dwType,
  1460. (LPBYTE)&BusInformation,
  1461. &cbData) != ERROR_SUCCESS) {
  1462. BusInformation = 0;
  1463. }
  1464. RegCloseKey(hBusInformationKey);
  1465. clean0:
  1466. return BusInformation;
  1467. }