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.

1252 lines
21 KiB

  1. /*++
  2. Microsoft Confidential
  3. Copyright (c) 1992-1997 Microsoft Corporation
  4. All rights reserved
  5. Module Name:
  6. util.c
  7. Abstract:
  8. Utility functions for System Control Panel Applet
  9. Author:
  10. Eric Flo (ericflo) 19-Jun-1995
  11. Revision History:
  12. 15-Oct-1997 scotthal
  13. Complete overhaul
  14. --*/
  15. #include "sysdm.h"
  16. //
  17. // Constants
  18. //
  19. #define CCH_MAX_DEC 12 // Number of chars needed to hold 2^32
  20. #define MAX_SWAPSIZE_X86 (4 * 1024) // 4 Gb (number stored in megabytes)
  21. #define MAX_SWAPSIZE_X86_PAE (16 * 1024 * 1024) // 16 Tb
  22. #define MAX_SWAPSIZE_IA64 (32 * 1024 * 1024) // 32 Tb
  23. #define MAX_SWAPSIZE_AMD64 (16 * 1024 * 1024) // 16 Tb
  24. void
  25. ErrMemDlg(
  26. IN HWND hParent
  27. )
  28. /*++
  29. Routine Description:
  30. Displays "out of memory" message.
  31. Arguments:
  32. hParent -
  33. Supplies parent window handle.
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. MessageBox(
  39. hParent,
  40. g_szErrMem,
  41. g_szSystemApplet,
  42. MB_OK | MB_ICONHAND | MB_SYSTEMMODAL
  43. );
  44. return;
  45. }
  46. LPTSTR
  47. SkipWhiteSpace(
  48. IN LPTSTR sz
  49. )
  50. /*++
  51. Routine Description:
  52. SkipWhiteSpace
  53. For the purposes of this fuction, whitespace is space, tab,
  54. cr, or lf.
  55. Arguments:
  56. sz -
  57. Supplies a string (which presumably has leading whitespace)
  58. Return Value:
  59. Pointer to string without leading whitespace if successful.
  60. --*/
  61. {
  62. while( IsWhiteSpace(*sz) )
  63. sz++;
  64. return sz;
  65. }
  66. int
  67. StringToInt(
  68. IN LPTSTR sz
  69. )
  70. /*++
  71. Routine Description:
  72. TCHAR version of atoi
  73. Arguments:
  74. sz -
  75. Supplies the string to convert
  76. Return Value:
  77. Integer representation of the string
  78. --*/
  79. {
  80. int i = 0;
  81. sz = SkipWhiteSpace(sz);
  82. while( IsDigit( *sz ) ) {
  83. i = i * 10 + DigitVal( *sz );
  84. sz++;
  85. }
  86. return i;
  87. }
  88. void
  89. IntToString(
  90. IN INT i,
  91. OUT LPTSTR sz
  92. )
  93. /*++
  94. Routine Description:
  95. TCHAR version of itoa
  96. Arguments:
  97. i -
  98. Supplies the integer to convert
  99. sz -
  100. Returns the string form of the supplied int
  101. Return Value:
  102. None.
  103. --*/
  104. {
  105. TCHAR szTemp[CCH_MAX_DEC];
  106. int iChr;
  107. iChr = 0;
  108. do {
  109. szTemp[iChr++] = TEXT('0') + (i % 10);
  110. i = i / 10;
  111. } while (i != 0);
  112. do {
  113. iChr--;
  114. *sz++ = szTemp[iChr];
  115. } while (iChr != 0);
  116. *sz++ = TEXT('\0');
  117. }
  118. LPTSTR
  119. CheckSlash(
  120. IN LPTSTR lpDir
  121. )
  122. /*++
  123. Routine Description:
  124. Checks for an ending backslash and adds one if
  125. it is missing.
  126. Arguments:
  127. lpDir -
  128. Supplies the name of a directory.
  129. Return Value:
  130. A string that ends with a backslash.
  131. --*/
  132. {
  133. DWORD dwStrLen;
  134. LPTSTR lpEnd;
  135. lpEnd = lpDir + lstrlen(lpDir);
  136. if (*(lpEnd - 1) != TEXT('\\')) {
  137. *lpEnd = TEXT('\\');
  138. lpEnd++;
  139. *lpEnd = TEXT('\0');
  140. }
  141. return lpEnd;
  142. }
  143. BOOL
  144. Delnode_Recurse(
  145. IN LPTSTR lpDir
  146. )
  147. /*++
  148. Routine Description:
  149. Recursive delete function for Delnode
  150. Arguments:
  151. lpDir -
  152. Supplies directory to delete
  153. Return Value:
  154. TRUE if successful.
  155. FALSE if an error occurs.
  156. --*/
  157. {
  158. WIN32_FIND_DATA fd;
  159. HANDLE hFile;
  160. //
  161. // Setup the current working dir
  162. //
  163. if (!SetCurrentDirectory (lpDir)) {
  164. return FALSE;
  165. }
  166. //
  167. // Find the first file
  168. //
  169. hFile = FindFirstFile(TEXT("*.*"), &fd);
  170. if (hFile == INVALID_HANDLE_VALUE) {
  171. if (GetLastError() == ERROR_FILE_NOT_FOUND) {
  172. return TRUE;
  173. } else {
  174. return FALSE;
  175. }
  176. }
  177. do {
  178. //
  179. // Check for "." and ".."
  180. //
  181. if (!lstrcmpi(fd.cFileName, TEXT("."))) {
  182. continue;
  183. }
  184. if (!lstrcmpi(fd.cFileName, TEXT(".."))) {
  185. continue;
  186. }
  187. if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  188. //
  189. // Found a directory.
  190. //
  191. if (!Delnode_Recurse(fd.cFileName)) {
  192. FindClose(hFile);
  193. return FALSE;
  194. }
  195. if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
  196. fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
  197. SetFileAttributes (fd.cFileName, fd.dwFileAttributes);
  198. }
  199. RemoveDirectory (fd.cFileName);
  200. } else {
  201. //
  202. // We found a file. Set the file attributes,
  203. // and try to delete it.
  204. //
  205. if ((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
  206. (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
  207. SetFileAttributes (fd.cFileName, FILE_ATTRIBUTE_NORMAL);
  208. }
  209. DeleteFile (fd.cFileName);
  210. }
  211. //
  212. // Find the next entry
  213. //
  214. } while (FindNextFile(hFile, &fd));
  215. //
  216. // Close the search handle
  217. //
  218. FindClose(hFile);
  219. //
  220. // Reset the working directory
  221. //
  222. if (!SetCurrentDirectory (TEXT(".."))) {
  223. return FALSE;
  224. }
  225. //
  226. // Success.
  227. //
  228. return TRUE;
  229. }
  230. BOOL
  231. Delnode(
  232. IN LPTSTR lpDir
  233. )
  234. /*++
  235. Routine Description:
  236. Recursive function that deletes files and
  237. directories.
  238. Arguments:
  239. lpDir -
  240. Supplies directory to delete.
  241. Return Value:
  242. TRUE if successful
  243. FALSE if an error occurs
  244. --*/
  245. {
  246. TCHAR szCurWorkingDir[MAX_PATH];
  247. if (GetCurrentDirectory(MAX_PATH, szCurWorkingDir)) {
  248. Delnode_Recurse (lpDir);
  249. SetCurrentDirectory (szCurWorkingDir);
  250. if (!RemoveDirectory (lpDir)) {
  251. return FALSE;
  252. }
  253. } else {
  254. return FALSE;
  255. }
  256. return TRUE;
  257. }
  258. LONG
  259. MyRegSaveKey(
  260. IN HKEY hKey,
  261. IN LPCTSTR lpSubKey
  262. )
  263. /*++
  264. Routine Description:
  265. Saves a registry key.
  266. Arguments:
  267. hKey -
  268. Supplies handle to a registry key.
  269. lpSubKey -
  270. Supplies the name of the subkey to save.
  271. Return Value:
  272. ERROR_SUCCESS if successful.
  273. Error code from RegSaveKey() if an error occurs.
  274. --*/
  275. {
  276. HANDLE hToken;
  277. LUID luid;
  278. DWORD dwSize = 1024;
  279. PTOKEN_PRIVILEGES lpPrevPrivilages;
  280. TOKEN_PRIVILEGES tp;
  281. LONG error;
  282. //
  283. // Allocate space for the old privileges
  284. //
  285. lpPrevPrivilages = GlobalAlloc(GPTR, dwSize);
  286. if (!lpPrevPrivilages) {
  287. return GetLastError();
  288. }
  289. if (!OpenProcessToken( GetCurrentProcess(),
  290. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
  291. return GetLastError();
  292. }
  293. LookupPrivilegeValue( NULL, SE_BACKUP_NAME, &luid );
  294. tp.PrivilegeCount = 1;
  295. tp.Privileges[0].Luid = luid;
  296. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  297. if (!AdjustTokenPrivileges( hToken, FALSE, &tp,
  298. dwSize, lpPrevPrivilages, &dwSize )) {
  299. if (GetLastError() == ERROR_MORE_DATA) {
  300. PTOKEN_PRIVILEGES lpTemp;
  301. lpTemp = GlobalReAlloc(lpPrevPrivilages, dwSize, GMEM_MOVEABLE);
  302. if (!lpTemp) {
  303. GlobalFree (lpPrevPrivilages);
  304. return GetLastError();
  305. }
  306. lpPrevPrivilages = lpTemp;
  307. if (!AdjustTokenPrivileges( hToken, FALSE, &tp,
  308. dwSize, lpPrevPrivilages, &dwSize )) {
  309. return GetLastError();
  310. }
  311. } else {
  312. return GetLastError();
  313. }
  314. }
  315. //
  316. // Save the hive
  317. //
  318. error = RegSaveKey(hKey, lpSubKey, NULL);
  319. AdjustTokenPrivileges( hToken, FALSE, lpPrevPrivilages,
  320. 0, NULL, NULL );
  321. CloseHandle (hToken);
  322. return error;
  323. }
  324. UINT
  325. CreateNestedDirectory(
  326. IN LPCTSTR lpDirectory,
  327. IN LPSECURITY_ATTRIBUTES lpSecurityAttributes
  328. )
  329. /*++
  330. Routine Description:
  331. Creates a subdirectory and all its parents
  332. if necessary.
  333. Arguments:
  334. lpDirectory -
  335. Name of directory to create.
  336. lpSecurityAttributes -
  337. Desired security attributes.
  338. Return Value:
  339. Nonzero on success.
  340. Zero on failure.
  341. --*/
  342. {
  343. TCHAR szDirectory[MAX_PATH];
  344. LPTSTR lpEnd;
  345. //
  346. // Check for NULL pointer
  347. //
  348. if (!lpDirectory || !(*lpDirectory)) {
  349. return 0;
  350. }
  351. //
  352. // First, see if we can create the directory without having
  353. // to build parent directories.
  354. //
  355. if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
  356. return 1;
  357. }
  358. //
  359. // If this directory exists already, this is OK too.
  360. //
  361. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  362. return ERROR_ALREADY_EXISTS;
  363. }
  364. //
  365. // No luck, copy the string to a buffer we can munge
  366. //
  367. lstrcpy (szDirectory, lpDirectory);
  368. //
  369. // Find the first subdirectory name
  370. //
  371. lpEnd = szDirectory;
  372. if (szDirectory[1] == TEXT(':')) {
  373. lpEnd += 3;
  374. } else if (szDirectory[1] == TEXT('\\')) {
  375. //
  376. // Skip the first two slashes
  377. //
  378. lpEnd += 2;
  379. //
  380. // Find the slash between the server name and
  381. // the share name.
  382. //
  383. while (*lpEnd && *lpEnd != TEXT('\\')) {
  384. lpEnd++;
  385. }
  386. if (!(*lpEnd)) {
  387. return 0;
  388. }
  389. //
  390. // Skip the slash, and find the slash between
  391. // the share name and the directory name.
  392. //
  393. lpEnd++;
  394. while (*lpEnd && *lpEnd != TEXT('\\')) {
  395. lpEnd++;
  396. }
  397. if (!(*lpEnd)) {
  398. return 0;
  399. }
  400. //
  401. // Leave pointer at the beginning of the directory.
  402. //
  403. lpEnd++;
  404. } else if (szDirectory[0] == TEXT('\\')) {
  405. lpEnd++;
  406. }
  407. while (*lpEnd) {
  408. while (*lpEnd && *lpEnd != TEXT('\\')) {
  409. lpEnd++;
  410. }
  411. if (*lpEnd == TEXT('\\')) {
  412. *lpEnd = TEXT('\0');
  413. if (!CreateDirectory (szDirectory, NULL)) {
  414. if (GetLastError() != ERROR_ALREADY_EXISTS) {
  415. return 0;
  416. }
  417. }
  418. *lpEnd = TEXT('\\');
  419. lpEnd++;
  420. }
  421. }
  422. //
  423. // Create the final directory
  424. //
  425. if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
  426. return 1;
  427. }
  428. if (GetLastError() == ERROR_ALREADY_EXISTS) {
  429. return ERROR_ALREADY_EXISTS;
  430. }
  431. //
  432. // Failed
  433. //
  434. return 0;
  435. }
  436. LONG
  437. MyRegLoadKey(
  438. IN HKEY hKey,
  439. IN LPTSTR lpSubKey,
  440. IN LPTSTR lpFile
  441. )
  442. /*++
  443. Routine Description:
  444. Loads a hive into the registry
  445. Arguments:
  446. hKey -
  447. Supplies a handle to a registry key which will be the parent
  448. of the created key.
  449. lpSubKey -
  450. Supplies the name of the subkey to create.
  451. lpFile -
  452. Supplies the name of the file containing the hive.
  453. Return Value:
  454. ERROR_SUCCESS if successful.
  455. Error code from RegLoadKey if unsuccessful.
  456. --*/
  457. {
  458. NTSTATUS Status;
  459. BOOLEAN WasEnabled;
  460. int error;
  461. //
  462. // Enable the restore privilege
  463. //
  464. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  465. if (NT_SUCCESS(Status)) {
  466. error = RegLoadKey(hKey, lpSubKey, lpFile);
  467. //
  468. // Restore the privilege to its previous state
  469. //
  470. RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  471. } else {
  472. error = GetLastError();
  473. }
  474. return error;
  475. }
  476. LONG
  477. MyRegUnLoadKey(
  478. IN HKEY hKey,
  479. IN LPTSTR lpSubKey
  480. )
  481. /*++
  482. Routine Description:
  483. Unloads a registry key.
  484. Arguments:
  485. hKey -
  486. Supplies handle to parent key
  487. lpSubKey -
  488. Supplies name of subkey to delete
  489. Return Value:
  490. ERROR_SUCCESS if successful
  491. Error code if unsuccessful
  492. --*/
  493. {
  494. LONG error;
  495. NTSTATUS Status;
  496. BOOLEAN WasEnabled;
  497. //
  498. // Enable the restore privilege
  499. //
  500. Status = RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, TRUE, FALSE, &WasEnabled);
  501. if (NT_SUCCESS(Status)) {
  502. error = RegUnLoadKey(hKey, lpSubKey);
  503. //
  504. // Restore the privilege to its previous state
  505. //
  506. RtlAdjustPrivilege(SE_RESTORE_PRIVILEGE, WasEnabled, FALSE, &WasEnabled);
  507. } else {
  508. error = GetLastError();
  509. }
  510. return error;
  511. }
  512. int
  513. GetSelectedItem(
  514. IN HWND hCtrl
  515. )
  516. /*++
  517. Routine Description:
  518. Determines which item in a list view control is selected
  519. Arguments:
  520. hCtrl -
  521. Supplies handle to the desired list view control.
  522. Return Value:
  523. The index of the selected item, if an item is selected.
  524. -1 if no item is selected.
  525. --*/
  526. {
  527. int i, n;
  528. n = (int)SendMessage (hCtrl, LVM_GETITEMCOUNT, 0, 0L);
  529. if (n != LB_ERR)
  530. {
  531. for (i = 0; i < n; i++)
  532. {
  533. if (SendMessage (hCtrl, LVM_GETITEMSTATE,
  534. i, (LPARAM) LVIS_SELECTED) == LVIS_SELECTED) {
  535. return i;
  536. }
  537. }
  538. }
  539. return -1;
  540. }
  541. BOOL
  542. IsUserAdmin(
  543. VOID
  544. )
  545. /*++
  546. Routine Description:
  547. This routine returns TRUE if the caller's process is a
  548. member of the Administrators local group.
  549. Caller is NOT expected to be impersonating anyone and IS
  550. expected to be able to open their own process and process
  551. token.
  552. Arguments:
  553. None.
  554. Return Value:
  555. TRUE - Caller has Administrators local group.
  556. FALSE - Caller does not have Administrators local group.
  557. --*/
  558. {
  559. BOOL b = FALSE;
  560. SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
  561. PSID AdministratorsGroup;
  562. if(AllocateAndInitializeSid(
  563. &NtAuthority,
  564. 2,
  565. SECURITY_BUILTIN_DOMAIN_RID,
  566. DOMAIN_ALIAS_RID_ADMINS,
  567. 0, 0, 0, 0, 0, 0,
  568. &AdministratorsGroup
  569. ))
  570. {
  571. CheckTokenMembership(NULL, AdministratorsGroup, &b);
  572. FreeSid(AdministratorsGroup);
  573. }
  574. return(b);
  575. } // IsUserAdmin
  576. BOOL
  577. _DriveIsNTFS(
  578. INT iDrive // drive to check on
  579. )
  580. {
  581. TCHAR szDrive[4] = TEXT("A:\\");
  582. TCHAR szDriveNameBuffer[MAX_PATH];
  583. DWORD dwMaxFnameLen;
  584. DWORD dwFSFlags;
  585. TCHAR szDriveFormatName[MAX_PATH];
  586. BOOL fRetVal = FALSE;
  587. szDrive[0] += (TCHAR)iDrive;
  588. if (GetVolumeInformation(szDrive, szDriveNameBuffer, ARRAYSIZE(szDriveNameBuffer), NULL,
  589. &dwMaxFnameLen, &dwFSFlags, szDriveFormatName, ARRAYSIZE(szDriveFormatName)))
  590. {
  591. if (StrStr(szDriveFormatName, TEXT("NTFS")))
  592. {
  593. fRetVal = TRUE;
  594. }
  595. }
  596. return fRetVal;
  597. }
  598. DWORD
  599. GetMaxPagefileSizeInMB(
  600. INT iDrive // drive to check on
  601. )
  602. {
  603. #if defined(_AMD64_)
  604. return MAX_SWAPSIZE_AMD64;
  605. #elif defined(_X86_)
  606. if (USER_SHARED_DATA && (USER_SHARED_DATA->ProcessorFeatures[PF_PAE_ENABLED]) && _DriveIsNTFS(iDrive))
  607. {
  608. return MAX_SWAPSIZE_X86_PAE;
  609. }
  610. else
  611. {
  612. return MAX_SWAPSIZE_X86;
  613. }
  614. #elif defined(_IA64_)
  615. return MAX_SWAPSIZE_IA64;
  616. #else
  617. return 0;
  618. #endif
  619. }
  620. int
  621. MsgBoxParam(
  622. IN HWND hWnd,
  623. IN DWORD wText,
  624. IN DWORD wCaption,
  625. IN DWORD wType,
  626. ...
  627. )
  628. /*++
  629. Routine Description:
  630. Combination of MessageBox and printf
  631. Arguments:
  632. hWnd -
  633. Supplies parent window handle
  634. wText -
  635. Supplies ID of a printf-like format string to display as the
  636. message box text
  637. wCaption -
  638. Supplies ID of a string to display as the message box caption
  639. wType -
  640. Supplies flags to MessageBox()
  641. Return Value:
  642. Whatever MessageBox() returns.
  643. --*/
  644. {
  645. TCHAR szText[ 4 * MAX_PATH ], szCaption[ 2 * MAX_PATH ];
  646. int ival;
  647. va_list parg;
  648. va_start( parg, wType );
  649. if( wText == IDS_INSUFFICIENT_MEMORY )
  650. goto NoMem;
  651. if( !LoadString( hInstance, wText, szCaption, ARRAYSIZE( szCaption ) ) )
  652. goto NoMem;
  653. wvsprintf( szText, szCaption, parg );
  654. if( !LoadString( hInstance, wCaption, szCaption, ARRAYSIZE( szCaption ) ) )
  655. goto NoMem;
  656. if( (ival = MessageBox( hWnd, szText, szCaption, wType ) ) == 0 )
  657. goto NoMem;
  658. va_end( parg );
  659. return( ival );
  660. NoMem:
  661. va_end( parg );
  662. ErrMemDlg( hWnd );
  663. return 0;
  664. }
  665. LPTSTR
  666. CloneString(
  667. IN LPTSTR pszSrc
  668. )
  669. /*++
  670. Routine Description:
  671. Allocates a buffer and copies a string into it
  672. Arguments:
  673. pszSrc -
  674. Supplies string to copy
  675. Return Value:
  676. Valid LPTSTR if successful
  677. NULL if out of memory
  678. --*/
  679. {
  680. LPTSTR pszDst = NULL;
  681. if (pszSrc != NULL) {
  682. pszDst = MemAlloc(LMEM_FIXED, (lstrlen(pszSrc)+1) * SIZEOF(TCHAR));
  683. if (pszDst) {
  684. lstrcpy( pszDst, pszSrc );
  685. }
  686. }
  687. return pszDst;
  688. }
  689. DWORD
  690. SetLBWidthEx(
  691. IN HWND hwndLB,
  692. IN LPTSTR szBuffer,
  693. IN DWORD cxCurWidth,
  694. IN DWORD cxExtra
  695. )
  696. /*++
  697. Routine Description:
  698. Set the width of a listbox, in pixels, acording to the size of the
  699. string passed in
  700. Arguments:
  701. hwndLB -
  702. Supples listbox to resize
  703. szBuffer -
  704. Supplies string to resize listbox to
  705. cxCurWidth -
  706. Supplies current width of the listbox
  707. cxExtra -
  708. Supplies some kind of slop factor
  709. Return Value:
  710. The new width of the listbox
  711. --*/
  712. {
  713. HDC hDC;
  714. SIZE Size;
  715. LONG cx;
  716. HFONT hfont, hfontOld;
  717. // Get the new Win4.0 thin dialog font
  718. hfont = (HFONT)SendMessage(hwndLB, WM_GETFONT, 0, 0);
  719. hDC = GetDC(hwndLB);
  720. // if we got a font back, select it in this clean hDC
  721. if (hfont != NULL)
  722. hfontOld = SelectObject(hDC, hfont);
  723. // If cxExtra is 0, then give our selves a little breathing space.
  724. if (cxExtra == 0) {
  725. GetTextExtentPoint(hDC, TEXT("1234"), 4 /* lstrlen("1234") */, &Size);
  726. cxExtra = Size.cx;
  727. }
  728. // Set scroll width of listbox
  729. GetTextExtentPoint(hDC, szBuffer, lstrlen(szBuffer), &Size);
  730. Size.cx += cxExtra;
  731. // Get the name length and adjust the longest name
  732. if ((DWORD) Size.cx > cxCurWidth)
  733. {
  734. cxCurWidth = Size.cx;
  735. SendMessage (hwndLB, LB_SETHORIZONTALEXTENT, (DWORD)Size.cx, 0L);
  736. }
  737. // retstore the original font if we changed it
  738. if (hfont != NULL)
  739. SelectObject(hDC, hfontOld);
  740. ReleaseDC(NULL, hDC);
  741. return cxCurWidth;
  742. }
  743. VOID
  744. SetDefButton(
  745. IN HWND hwndDlg,
  746. IN int idButton
  747. )
  748. /*++
  749. Routine Description:
  750. Sets the default button for a dialog box or proppage
  751. The old default button, if any, has its default status removed
  752. Arguments:
  753. hwndDlg -
  754. Supplies window handle
  755. idButton -
  756. Supplies ID of button to make default
  757. Return Value:
  758. None
  759. --*/
  760. {
  761. LRESULT lr;
  762. if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID)
  763. {
  764. HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
  765. SendMessage (hwndOldDefButton,
  766. BM_SETSTYLE,
  767. MAKEWPARAM(BS_PUSHBUTTON, 0),
  768. MAKELPARAM(TRUE, 0));
  769. }
  770. SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L );
  771. SendMessage( GetDlgItem(hwndDlg, idButton),
  772. BM_SETSTYLE,
  773. MAKEWPARAM( BS_DEFPUSHBUTTON, 0 ),
  774. MAKELPARAM( TRUE, 0 ));
  775. }
  776. void
  777. HourGlass(
  778. IN BOOL bOn
  779. )
  780. /*++
  781. Routine Description:
  782. Turns hourglass mouse cursor on or off
  783. Arguments:
  784. bOn -
  785. Supplies desired status of hourglass mouse cursor
  786. Return Value:
  787. None
  788. --*/
  789. {
  790. if( !GetSystemMetrics( SM_MOUSEPRESENT ) )
  791. ShowCursor( bOn );
  792. SetCursor( LoadCursor( NULL, bOn ? IDC_WAIT : IDC_ARROW ) );
  793. }
  794. VCREG_RET
  795. OpenRegKey(
  796. IN LPTSTR pszKeyName,
  797. OUT PHKEY phk
  798. )
  799. /*++
  800. Routine Description:
  801. Opens a subkey of HKEY_LOCAL_MACHINE
  802. Arguments:
  803. pszKeyName -
  804. Supplies the name of the subkey to open
  805. phk -
  806. Returns a handle to the key if successfully opened
  807. Returns NULL if an error occurs
  808. Return Value:
  809. VCREG_OK if successful
  810. VCREG_READONLY if the key was opened with read-only access
  811. VCREG_OK if an error occurred
  812. */
  813. {
  814. LONG Error;
  815. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKeyName, 0,
  816. KEY_READ | KEY_WRITE, phk);
  817. if (Error != ERROR_SUCCESS)
  818. {
  819. Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKeyName, 0, KEY_READ, phk);
  820. if (Error != ERROR_SUCCESS)
  821. {
  822. *phk = NULL;
  823. return VCREG_ERROR;
  824. }
  825. /*
  826. * We only have Read access.
  827. */
  828. return VCREG_READONLY;
  829. }
  830. return VCREG_OK;
  831. }
  832. LONG
  833. CloseRegKey(
  834. IN HKEY hkey
  835. )
  836. /*++
  837. Routine Description:
  838. Closes a registry key opened by OpenRegKey()
  839. Arguments:
  840. hkey -
  841. Supplies handle to key to close
  842. Return Value:
  843. Whatever RegCloseKey() returns
  844. --*/
  845. {
  846. return RegCloseKey(hkey);
  847. }
  848. BOOL
  849. IsWorkstationProduct(
  850. )
  851. /*++
  852. Routine Description:
  853. Determines whether the currently running system is a Workstation
  854. product or a Server product.
  855. Arguments:
  856. None.
  857. Return Value:
  858. TRUE if the currently running system is a Workstation product.
  859. FALSE if the currently running system is some other kind of product.
  860. --*/
  861. {
  862. NT_PRODUCT_TYPE ProdType;
  863. RtlGetNtProductType(&ProdType);
  864. return(NtProductWinNt == ProdType);
  865. }