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.

587 lines
18 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. guestact.c
  5. Abstract:
  6. functions to enable/disable the guest account
  7. Author:
  8. Bob Watson (a-robw)
  9. Revision History:
  10. 23 Dec 94
  11. --*/
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <ntsam.h>
  16. #include <windows.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <c2dll.h>
  20. #include <c2inc.h>
  21. #include <c2utils.h>
  22. #include "c2funcs.h"
  23. #include "c2funres.h"
  24. // define action codes here. They are only meaningful in the
  25. // context of this module.
  26. #define AC_GUEST_ACCT_NOCHANGE 0
  27. #define AC_GUEST_ACCT_UPDATE 1
  28. // Account states
  29. #define GUEST_ACCT_NOT_FOUND 0
  30. #define GUEST_ACCT_ENABLED 1
  31. #define GUEST_ACCT_DISABLED 2
  32. static WCHAR szGuest[] = L"Guest";
  33. #define GUEST_STRLEN 5
  34. #define SECURE C2DLL_C2
  35. static
  36. LONG
  37. IsGuestAccountEnabled(
  38. )
  39. {
  40. SAM_HANDLE hsamObject;
  41. SAM_HANDLE hsamDomain;
  42. PSID psidDomain;
  43. SAM_ENUMERATE_HANDLE hSamEnum;
  44. PSAM_RID_ENUMERATION pRidEnum;
  45. PVOID pvEnumBuffer;
  46. ULONG ulEnumCount;
  47. ULONG i;
  48. LONG lReturn = GUEST_ACCT_NOT_FOUND;
  49. int nCompare;
  50. ULONG lTotalAvailable, lTotalReturned, lReturnedEntryCount;
  51. NTSTATUS ntstat;
  52. LPVOID pBuffer;
  53. PDOMAIN_DISPLAY_USER pdduData;
  54. PDOMAIN_DISPLAY_USER pdduThisUser;
  55. SET_WAIT_CURSOR;
  56. // connect to SAM on this machine
  57. ntstat = SamConnect((PUNICODE_STRING)NULL, &hsamObject,
  58. SAM_SERVER_ALL_ACCESS, (POBJECT_ATTRIBUTES)NULL);
  59. if (ntstat == STATUS_SUCCESS) {
  60. // Ask SAM for the domains on this server.
  61. hSamEnum = 0;
  62. ntstat = SamEnumerateDomainsInSamServer(
  63. hsamObject,
  64. &hSamEnum,
  65. &pvEnumBuffer,
  66. 1024,
  67. &ulEnumCount);
  68. if ((ntstat == STATUS_SUCCESS) || (ntstat == STATUS_MORE_ENTRIES)) {
  69. // look up only the first entry
  70. pRidEnum = (PSAM_RID_ENUMERATION) pvEnumBuffer;
  71. // get SID of domain
  72. ntstat = SamLookupDomainInSamServer (
  73. hsamObject,
  74. &pRidEnum->Name,
  75. &psidDomain);
  76. if (ntstat == STATUS_SUCCESS) {
  77. // open handle to this domain
  78. ntstat = SamOpenDomain (
  79. hsamObject,
  80. DOMAIN_EXECUTE,
  81. psidDomain,
  82. &hsamDomain);
  83. if (ntstat == STATUS_SUCCESS) {
  84. // get password policy for this domain
  85. pBuffer = NULL;
  86. ntstat = SamQueryDisplayInformation (
  87. hsamDomain,
  88. DomainDisplayUser,
  89. 0, 100, 32768,
  90. &lTotalAvailable,
  91. &lTotalReturned,
  92. &lReturnedEntryCount,
  93. (PVOID *)&pBuffer);
  94. if (ntstat == STATUS_SUCCESS) {
  95. pdduData = (PDOMAIN_DISPLAY_USER)pBuffer;
  96. for (i=0; i<lReturnedEntryCount; i++) {
  97. pdduThisUser = &pdduData[i];
  98. nCompare = CompareStringW (
  99. GetUserDefaultLCID(),
  100. (NORM_IGNORECASE | SORT_STRINGSORT),
  101. szGuest,
  102. GUEST_STRLEN,
  103. pdduThisUser->LogonName.Buffer,
  104. (pdduThisUser->LogonName.Length / sizeof(WCHAR)));
  105. if (nCompare == 2) {
  106. // guest account found
  107. if ((pdduThisUser->AccountControl & USER_ACCOUNT_DISABLED) ==
  108. USER_ACCOUNT_DISABLED) {
  109. lReturn = GUEST_ACCT_DISABLED;
  110. } else {
  111. lReturn = GUEST_ACCT_ENABLED;
  112. }
  113. break; // bail out since the guest acct was found
  114. }
  115. }
  116. ntstat = SamFreeMemory (pBuffer);
  117. }
  118. // close handle
  119. SamCloseHandle (hsamDomain);
  120. }
  121. }
  122. SamFreeMemory(pvEnumBuffer);
  123. }
  124. SamCloseHandle (hsamObject);
  125. }
  126. SetLastError (RtlNtStatusToDosError(ntstat));
  127. SET_ARROW_CURSOR;
  128. return lReturn;
  129. }
  130. static
  131. BOOL
  132. EnableGuestAccount (
  133. BOOL bEnable // TRUE = enable, FALSE = disable
  134. )
  135. {
  136. SAM_HANDLE hsamObject;
  137. SAM_HANDLE hsamDomain;
  138. SAM_HANDLE hsamUser;
  139. PSID psidDomain;
  140. SAM_ENUMERATE_HANDLE hSamEnum;
  141. PSAM_RID_ENUMERATION pRidEnum;
  142. PVOID pvEnumBuffer;
  143. ULONG ulEnumCount;
  144. ULONG i;
  145. BOOL bReturn = FALSE;
  146. BOOL bAccount;
  147. int nCompare;
  148. ULONG lTotalAvailable, lTotalReturned, lReturnedEntryCount;
  149. NTSTATUS ntstat;
  150. LPVOID pBuffer;
  151. PDOMAIN_DISPLAY_USER pdduData;
  152. PDOMAIN_DISPLAY_USER pdduThisUser;
  153. PUSER_CONTROL_INFORMATION puciData;
  154. SET_WAIT_CURSOR;
  155. // connect to SAM on this machine
  156. ntstat = SamConnect((PUNICODE_STRING)NULL, &hsamObject,
  157. SAM_SERVER_ALL_ACCESS, (POBJECT_ATTRIBUTES)NULL);
  158. if (ntstat == STATUS_SUCCESS) {
  159. // Ask SAM for the domains on this server.
  160. hSamEnum = 0;
  161. ntstat = SamEnumerateDomainsInSamServer(
  162. hsamObject,
  163. &hSamEnum,
  164. &pvEnumBuffer,
  165. 1024,
  166. &ulEnumCount);
  167. if ((ntstat == STATUS_SUCCESS) || (ntstat == STATUS_MORE_ENTRIES)) {
  168. // look up only the first entry
  169. pRidEnum = (PSAM_RID_ENUMERATION) pvEnumBuffer;
  170. // get SID of domain
  171. ntstat = SamLookupDomainInSamServer (
  172. hsamObject,
  173. &pRidEnum->Name,
  174. &psidDomain);
  175. if (ntstat == STATUS_SUCCESS) {
  176. // open handle to this domain
  177. ntstat = SamOpenDomain (
  178. hsamObject,
  179. DOMAIN_EXECUTE,
  180. psidDomain,
  181. &hsamDomain);
  182. if (ntstat == STATUS_SUCCESS) {
  183. // get password policy for this domain
  184. pBuffer = NULL;
  185. ntstat = SamQueryDisplayInformation (
  186. hsamDomain,
  187. DomainDisplayUser,
  188. 0, 100, 32768,
  189. &lTotalAvailable,
  190. &lTotalReturned,
  191. &lReturnedEntryCount,
  192. (PVOID *)&pBuffer);
  193. if (ntstat == STATUS_SUCCESS) {
  194. pdduData = (PDOMAIN_DISPLAY_USER)pBuffer;
  195. for (i=0; i<lReturnedEntryCount; i++) {
  196. pdduThisUser = &pdduData[i];
  197. nCompare = CompareStringW (
  198. GetUserDefaultLCID(),
  199. (NORM_IGNORECASE | SORT_STRINGSORT),
  200. szGuest,
  201. GUEST_STRLEN,
  202. pdduThisUser->LogonName.Buffer,
  203. (pdduThisUser->LogonName.Length / sizeof(WCHAR)));
  204. if (nCompare == 2) {
  205. // guest account found
  206. bAccount = !((pdduThisUser->AccountControl & USER_ACCOUNT_DISABLED) ==
  207. USER_ACCOUNT_DISABLED);
  208. if (bAccount == bEnable) {
  209. // account is already in the desired
  210. // state so bail out here
  211. bReturn = TRUE;
  212. break;
  213. } else {
  214. // account needs to be updated so open
  215. // the user data
  216. ntstat = SamOpenUser (
  217. hsamDomain,
  218. USER_ALL_ACCESS,
  219. pdduThisUser->Rid,
  220. &hsamUser);
  221. if (ntstat == STATUS_SUCCESS) {
  222. ntstat = SamQueryInformationUser (
  223. hsamUser,
  224. UserControlInformation,
  225. (PVOID *)&puciData);
  226. if (ntstat == STATUS_SUCCESS) {
  227. // enable/disable account
  228. if (bEnable) {
  229. // clear disable bit
  230. puciData->UserAccountControl &=
  231. ~USER_ACCOUNT_DISABLED;
  232. } else {
  233. // set disable bit
  234. puciData->UserAccountControl |=
  235. USER_ACCOUNT_DISABLED;
  236. }
  237. // update value
  238. ntstat = SamSetInformationUser (
  239. hsamUser,
  240. UserControlInformation,
  241. (PVOID)puciData);
  242. if (ntstat == STATUS_SUCCESS) {
  243. bReturn = TRUE;
  244. }
  245. SamFreeMemory (puciData);
  246. }
  247. SamCloseHandle (hsamUser);
  248. }
  249. }
  250. break; // bail out since the guest acct was found
  251. }
  252. }
  253. ntstat = SamFreeMemory (pBuffer);
  254. }
  255. // close handle
  256. SamCloseHandle (hsamDomain);
  257. }
  258. }
  259. SamFreeMemory(pvEnumBuffer);
  260. }
  261. SamCloseHandle (hsamObject);
  262. }
  263. SetLastError (RtlNtStatusToDosError(ntstat));
  264. SET_ARROW_CURSOR;
  265. return bReturn;
  266. }
  267. BOOL CALLBACK
  268. C2GuestAccountDlgProc(
  269. IN HWND hDlg, // window handle of the dialog box
  270. IN UINT message, // type of message
  271. IN WPARAM wParam,
  272. IN LPARAM lParam
  273. )
  274. /*++
  275. Routine Description:
  276. Window procedure for Guest Account enable/disable
  277. Arguments:
  278. Standard DlgProc arguments
  279. ReturnValue:
  280. TRUE the message was handled by this routine
  281. FALSE DefDialogProc should handle the message
  282. --*/
  283. {
  284. static PULONG plNewState; // save address of caller's data
  285. switch (message) {
  286. case WM_INITDIALOG:
  287. // save pointer
  288. plNewState = (PULONG)lParam;
  289. CheckDlgButton (hDlg, IDC_DISABLE_GUEST_ACCOUNT,
  290. (*plNewState == GUEST_ACCT_DISABLED ? CHECKED : UNCHECKED));
  291. SetFocus (GetDlgItem (hDlg, IDOK)); // set focus to OK Button
  292. return FALSE; // we don't want Windows to set the focus
  293. case WM_COMMAND:
  294. switch (LOWORD(wParam)){
  295. case IDOK:
  296. if (HIWORD(wParam) == BN_CLICKED) {
  297. if (IsDlgButtonChecked(hDlg, IDC_DISABLE_GUEST_ACCOUNT) == CHECKED) {
  298. *plNewState = GUEST_ACCT_DISABLED;
  299. } else {
  300. *plNewState = GUEST_ACCT_ENABLED;
  301. }
  302. EndDialog (hDlg, (int)LOWORD(wParam));
  303. return TRUE;
  304. } else {
  305. return FALSE;
  306. }
  307. case IDCANCEL:
  308. if (HIWORD(wParam) == BN_CLICKED) {
  309. // exit and return button that caused exit
  310. EndDialog (hDlg, (int)LOWORD(wParam));
  311. return TRUE;
  312. } else {
  313. return FALSE;
  314. }
  315. case IDC_C2:
  316. if (HIWORD(wParam) == BN_CLICKED) {
  317. CheckDlgButton (hDlg, IDC_DISABLE_GUEST_ACCOUNT,
  318. CHECKED);
  319. return TRUE;
  320. } else {
  321. return FALSE;
  322. }
  323. case IDC_HELP:
  324. PostMessage (GetParent(hDlg), UM_SHOW_CONTEXT_HELP, 0, 0);
  325. return TRUE;
  326. default:
  327. return FALSE;
  328. }
  329. default:
  330. return (FALSE); // Didn't process the message
  331. }
  332. }
  333. LONG
  334. C2QueryGuestAccount (
  335. IN LPARAM lParam
  336. )
  337. /*++
  338. Routine Description:
  339. Function called to find out the current state of this configuration
  340. item. This function reads the current state of the item and
  341. sets the C2 Compliance flag and the Status string to reflect
  342. the current value of the configuration item.
  343. Arguments:
  344. Pointer to the Dll data block passed as an LPARAM.
  345. ReturnValue:
  346. ERROR_SUCCESS if the function succeeds otherwise a
  347. WIN32 error is returned if an error occurs
  348. --*/
  349. {
  350. PC2DLL_DATA pC2Data;
  351. LONG lGuestAccount;
  352. UINT nMsgId;
  353. if (lParam != 0) {
  354. pC2Data = (PC2DLL_DATA)lParam;
  355. lGuestAccount = IsGuestAccountEnabled();
  356. switch (lGuestAccount) {
  357. case GUEST_ACCT_ENABLED:
  358. pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
  359. nMsgId = IDS_GUEST_ACCOUNT_ENABLED;
  360. break;
  361. case GUEST_ACCT_DISABLED:
  362. pC2Data->lC2Compliance = SECURE;
  363. nMsgId = IDS_GUEST_ACCOUNT_DISABLED;
  364. break;
  365. case GUEST_ACCT_NOT_FOUND:
  366. default:
  367. pC2Data->lC2Compliance = SECURE;
  368. nMsgId = IDS_GUEST_ACCOUNT_NOT_FOUND;
  369. break;
  370. }
  371. lstrcpy (pC2Data->szStatusName,
  372. GetStringResource (GetDllInstance(), nMsgId));
  373. return ERROR_SUCCESS;
  374. } else {
  375. return ERROR_BAD_ARGUMENTS;
  376. }
  377. }
  378. LONG
  379. C2SetGuestAccount (
  380. IN LPARAM lParam
  381. )
  382. /*++
  383. Routine Description:
  384. Function called to change the current state of this configuration
  385. item based on an action code passed in the DLL data block. If
  386. this function successfully sets the state of the configuration
  387. item, then the C2 Compliance flag and the Status string to reflect
  388. the new value of the configuration item.
  389. Arguments:
  390. Pointer to the Dll data block passed as an LPARAM.
  391. ReturnValue:
  392. ERROR_SUCCESS if the function succeeds otherwise a
  393. WIN32 error is returned if an error occurs
  394. --*/
  395. {
  396. PC2DLL_DATA pC2Data;
  397. BOOL bGuestAccount = 0;
  398. UINT nMsgId;
  399. if (lParam != 0) {
  400. pC2Data = (PC2DLL_DATA)lParam;
  401. if (pC2Data->lActionCode == AC_GUEST_ACCT_UPDATE) {
  402. if (EnableGuestAccount(
  403. (pC2Data->lActionValue == GUEST_ACCT_ENABLED ? TRUE : FALSE))) {
  404. switch (pC2Data->lActionValue) {
  405. case GUEST_ACCT_ENABLED:
  406. pC2Data->lC2Compliance = C2DLL_NOT_SECURE;
  407. nMsgId = IDS_GUEST_ACCOUNT_ENABLED;
  408. break;
  409. case GUEST_ACCT_DISABLED:
  410. pC2Data->lC2Compliance = SECURE;
  411. nMsgId = IDS_GUEST_ACCOUNT_DISABLED;
  412. break;
  413. case GUEST_ACCT_NOT_FOUND:
  414. default:
  415. pC2Data->lC2Compliance = SECURE;
  416. nMsgId = IDS_GUEST_ACCOUNT_NOT_FOUND;
  417. break;
  418. }
  419. lstrcpy (pC2Data->szStatusName,
  420. GetStringResource (GetDllInstance(), nMsgId));
  421. }
  422. pC2Data->lActionCode = 0;
  423. pC2Data->lActionValue = 0;
  424. }
  425. return ERROR_SUCCESS;
  426. } else {
  427. return ERROR_BAD_ARGUMENTS;
  428. }
  429. }
  430. LONG
  431. C2DisplayGuestAccount (
  432. IN LPARAM lParam
  433. )
  434. /*++
  435. Routine Description:
  436. Function called to display more information on the configuration
  437. item and provide the user with the option to change the current
  438. setting (if appropriate). If the User "OK's" out of the UI,
  439. then the action code field in the DLL data block is set to the
  440. appropriate (and configuration item-specific) action code so the
  441. "Set" function can be called to perform the desired action. If
  442. the user Cancels out of the UI, then the Action code field is
  443. set to 0 (no action) and no action is performed.
  444. Arguments:
  445. Pointer to the Dll data block passed as an LPARAM.
  446. ReturnValue:
  447. ERROR_SUCCESS if the function succeeds otherwise a
  448. WIN32 error is returned if an error occurs
  449. --*/
  450. {
  451. PC2DLL_DATA pC2Data;
  452. LONG lNewValue = 0;
  453. if (lParam != 0) {
  454. pC2Data = (PC2DLL_DATA)lParam;
  455. lNewValue = IsGuestAccountEnabled();
  456. if (lNewValue != GUEST_ACCT_NOT_FOUND) {
  457. // the guest account was found on the system so
  458. // show enable/disable dialog box
  459. if (DialogBoxParam (
  460. GetDllInstance(),
  461. MAKEINTRESOURCE (IDD_GUEST_ACCOUNT),
  462. pC2Data->hWnd,
  463. C2GuestAccountDlgProc,
  464. (LPARAM)&lNewValue) == IDOK) {
  465. pC2Data->lActionValue = lNewValue;
  466. pC2Data->lActionCode = AC_GUEST_ACCT_UPDATE;
  467. } else {
  468. // no action
  469. pC2Data->lActionCode = AC_GUEST_ACCT_NOCHANGE;
  470. }
  471. } else {
  472. // no guest account found on the system so show message box
  473. DisplayDllMessageBox (
  474. pC2Data->hWnd,
  475. IDS_GUEST_ACCOUNT_NOT_FOUND,
  476. IDS_GUEST_ACCOUNT_CAPTION,
  477. MBOK_INFO);
  478. pC2Data->lActionCode = AC_GUEST_ACCT_NOCHANGE;
  479. }
  480. } else {
  481. return ERROR_BAD_ARGUMENTS;
  482. }
  483. return ERROR_SUCCESS;
  484. }
  485. 
  486.