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.

1785 lines
52 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. autologon.c
  5. Abstract:
  6. This is a command-line utility munges that settings related to the
  7. Windows NT/2000 Autologon functionality
  8. if PRIVATE_VERSION is defined, password info will be displayed on the output
  9. For general distribution, this should not be defined
  10. Author:
  11. Jason Garms (jasong) 12 October 2000
  12. History:
  13. Cristian Ilac (crisilac) 11 November 2001 Made spec changes
  14. Jason Garms (jasong) 12 October 2000 Created
  15. --*/
  16. #include "common.h"
  17. #include <wincred.h>
  18. //+----------------------------------------------------------------------------
  19. //
  20. // Prototypes
  21. //
  22. //+----------------------------------------------------------------------------
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Command functions
  26. //
  27. //+----------------------------------------------------------------------------
  28. typedef DWORD (*CommandFn)();
  29. DWORD
  30. DumpCmd();
  31. DWORD
  32. MigratePassword();
  33. DWORD
  34. Delete();
  35. DWORD
  36. EnableAutoLogon();
  37. #ifdef PRIVATE_VERSION
  38. DWORD
  39. DumpAutoLogonInfo();
  40. #endif
  41. //+----------------------------------------------------------------------------
  42. //
  43. // Data/Options set functions
  44. //
  45. //+----------------------------------------------------------------------------
  46. DWORD
  47. SetCommand(
  48. UINT uCommand);
  49. DWORD
  50. SetQuietMode(
  51. WCHAR* pszData);
  52. DWORD
  53. SetUserName(
  54. WCHAR* pszData);
  55. DWORD
  56. SetCount(
  57. WCHAR* pszData);
  58. #ifdef PRIVATE_VERSION
  59. DWORD
  60. SetMachineName(
  61. WCHAR* pszData);
  62. #endif
  63. //+----------------------------------------------------------------------------
  64. //
  65. // Other functions
  66. //
  67. //+----------------------------------------------------------------------------
  68. DWORD
  69. CheckWinVersion();
  70. DWORD
  71. GetPassword();
  72. //+----------------------------------------------------------------------------
  73. //
  74. // Global command table
  75. //
  76. //+----------------------------------------------------------------------------
  77. #define COMMAND_HELP 0
  78. #define COMMAND_MIGRATE 1
  79. #define COMMAND_LSA_DELETE 2
  80. #define COMMAND_LSA_ENABLE 3
  81. #ifdef PRIVATE_VERSION
  82. #define COMMAND_DUMP 4
  83. #define COMMAND_NOT_SET 5
  84. #else
  85. #define COMMAND_NOT_SET 4
  86. #endif
  87. #define COMMAND_SIZE COMMAND_NOT_SET
  88. CommandFn g_Commands[COMMAND_SIZE] = {
  89. DumpCmd,
  90. MigratePassword,
  91. Delete,
  92. EnableAutoLogon,
  93. #ifdef PRIVATE_VERSION
  94. DumpAutoLogonInfo
  95. #endif
  96. };
  97. //+----------------------------------------------------------------------------//
  98. //
  99. // Global data
  100. //
  101. //+----------------------------------------------------------------------------
  102. WCHAR g_UserName[MAX_STRING] = {0};
  103. WCHAR g_DomainName[MAX_STRING] = {0};
  104. WCHAR g_Password[MAX_STRING] = {0};
  105. DWORD g_AutoLogonCount = 0;
  106. WCHAR g_TempString[MAX_STRING] = {0};
  107. WCHAR g_ErrorString[MAX_STRING] = {0};
  108. WCHAR g_FailureLocation[MAX_STRING] = {0};
  109. BOOL g_QuietMode = FALSE;
  110. BOOL g_FullHelp = FALSE;
  111. BOOL g_SetDefaultPIN = FALSE;
  112. UINT g_uCommand = COMMAND_NOT_SET;
  113. #ifdef PRIVATE_VERSION
  114. BOOL g_RemoteOperation = FALSE;
  115. WCHAR g_RemoteComputerName[MAX_STRING] = {0};
  116. #endif
  117. // various strings
  118. WCHAR g_PasswordSecretName[] = L"DefaultPassword";
  119. WCHAR g_PinSecretName[] = L"DefaultPIN";
  120. WCHAR g_AutoAdminLogonName[] = L"AutoAdminLogon";
  121. WCHAR g_DefaultUserName[] = L"DefaultUserName";
  122. WCHAR g_DefaultDomainName[] = L"DefaultDomainName";
  123. WCHAR g_AutoLogonCountName[] = L"AutoLogonCount";
  124. //+----------------------------------------------------------------------------
  125. //
  126. // Functions
  127. //
  128. //+----------------------------------------------------------------------------
  129. int
  130. __cdecl
  131. wmain(
  132. int argc,
  133. WCHAR *argv[]
  134. )
  135. {
  136. UINT uCommandPosition = 0;
  137. DWORD dwRetCode = ERROR_SUCCESS;
  138. //
  139. // loop through all command line arguments and check for known ones
  140. // - if one argument is identified continue the loop
  141. // - if unknown arguments are passed break the loop and fail
  142. //
  143. while( ++uCommandPosition < (UINT)argc )
  144. {
  145. if( !_wcsicmp(argv[uCommandPosition], L"/?") )
  146. {
  147. g_FullHelp = TRUE;
  148. dwRetCode = SetCommand(COMMAND_HELP);
  149. if( ERROR_SUCCESS == dwRetCode )
  150. {
  151. continue;
  152. }
  153. else
  154. {
  155. break;
  156. }
  157. }
  158. if( !_wcsicmp(argv[uCommandPosition], L"/Q") ||
  159. !_wcsicmp(argv[uCommandPosition], L"/Quiet")
  160. )
  161. {
  162. dwRetCode = SetQuietMode(argv[uCommandPosition]);
  163. if( ERROR_SUCCESS == dwRetCode )
  164. {
  165. continue;
  166. }
  167. else
  168. {
  169. break;
  170. }
  171. }
  172. if( !_wcsicmp(argv[uCommandPosition], L"/M") ||
  173. !_wcsicmp(argv[uCommandPosition], L"/Migrate") )
  174. {
  175. dwRetCode = SetCommand(COMMAND_MIGRATE);
  176. if( ERROR_SUCCESS == dwRetCode )
  177. {
  178. continue;
  179. }
  180. else
  181. {
  182. break;
  183. }
  184. }
  185. if( !_wcsicmp(argv[uCommandPosition], L"/D") ||
  186. !_wcsicmp(argv[uCommandPosition], L"/Delete") )
  187. {
  188. dwRetCode = SetCommand(COMMAND_LSA_DELETE);
  189. if( ERROR_SUCCESS == dwRetCode )
  190. {
  191. continue;
  192. }
  193. else
  194. {
  195. break;
  196. }
  197. }
  198. if( !_wcsicmp(argv[uCommandPosition], L"/S") ||
  199. !_wcsicmp(argv[uCommandPosition], L"/Set") )
  200. {
  201. dwRetCode = SetCommand(COMMAND_LSA_ENABLE);
  202. if( ERROR_SUCCESS == dwRetCode )
  203. {
  204. continue;
  205. }
  206. else
  207. {
  208. break;
  209. }
  210. }
  211. if( !_wcsnicmp(argv[uCommandPosition], L"/U:", wcslen(L"/U:")) ||
  212. !_wcsicmp(argv[uCommandPosition], L"/U") ||
  213. !_wcsnicmp(argv[uCommandPosition], L"/UserName:", wcslen(L"/UserName:")) ||
  214. !_wcsicmp(argv[uCommandPosition], L"/Username") )
  215. {
  216. dwRetCode = SetUserName(argv[uCommandPosition]);
  217. if( ERROR_FILE_NOT_FOUND == dwRetCode )
  218. {
  219. //
  220. // it may be because there was a column followed by spaces
  221. // Try to recover
  222. //
  223. if( uCommandPosition + 1 < (UINT)argc )
  224. {
  225. //
  226. // only if not another parameter
  227. //
  228. if( argv[uCommandPosition + 1][0] != '/' )
  229. {
  230. dwRetCode = SetUserName(argv[++uCommandPosition]);
  231. }
  232. else
  233. {
  234. DisplayMessage(L"Command line: Missing Username.\n");
  235. }
  236. }
  237. }
  238. if( ERROR_SUCCESS == dwRetCode )
  239. {
  240. continue;
  241. }
  242. else
  243. {
  244. break;
  245. }
  246. }
  247. if( !_wcsnicmp(argv[uCommandPosition], L"/C:", wcslen(L"/C:")) ||
  248. !_wcsicmp(argv[uCommandPosition], L"/C") ||
  249. !_wcsnicmp(argv[uCommandPosition], L"/Count:", wcslen(L"/Count:")) ||
  250. !_wcsicmp(argv[uCommandPosition], L"/Count") )
  251. {
  252. dwRetCode = SetCount(argv[uCommandPosition]);
  253. if( ERROR_FILE_NOT_FOUND == dwRetCode )
  254. {
  255. //
  256. // it may be because there was no column or a column
  257. // followed by spaces. Try to recover by moving on.
  258. //
  259. if( uCommandPosition + 1 < (UINT)argc )
  260. {
  261. //
  262. // only if not another parameter
  263. //
  264. if( argv[uCommandPosition + 1][0] != '/' )
  265. {
  266. dwRetCode = SetCount(argv[++uCommandPosition]);
  267. }
  268. else
  269. {
  270. DisplayMessage(L"Command line: Missing count.\n");
  271. }
  272. }
  273. }
  274. if( ERROR_SUCCESS == dwRetCode )
  275. {
  276. continue;
  277. }
  278. else
  279. {
  280. break;
  281. }
  282. }
  283. if( !_wcsicmp(argv[uCommandPosition], L"/P") ||
  284. !_wcsicmp(argv[uCommandPosition], L"/Pin") )
  285. {
  286. g_SetDefaultPIN = TRUE;
  287. dwRetCode = SetCommand(COMMAND_LSA_ENABLE);
  288. if( ERROR_SUCCESS == dwRetCode )
  289. {
  290. continue;
  291. }
  292. else
  293. {
  294. break;
  295. }
  296. }
  297. #ifdef PRIVATE_VERSION
  298. if( !_wcsnicmp(argv[uCommandPosition], L"/T:", wcslen(L"/T:")) ||
  299. !_wcsicmp(argv[uCommandPosition], L"/T") ||
  300. !_wcsnicmp(argv[uCommandPosition], L"/Target:", wcslen(L"/Target:")) ||
  301. !_wcsicmp(argv[uCommandPosition], L"/Target") )
  302. {
  303. dwRetCode = SetMachineName(argv[uCommandPosition]);
  304. if( ERROR_FILE_NOT_FOUND == dwRetCode )
  305. {
  306. //
  307. // it may be because there was no column or a column
  308. // followed by spaces. Try to recover by moving on.
  309. //
  310. if( uCommandPosition + 1 < (UINT)argc )
  311. {
  312. //
  313. // only if not another parameter
  314. //
  315. if( argv[uCommandPosition + 1][0] != '/' )
  316. {
  317. dwRetCode = SetMachineName(argv[++uCommandPosition]);
  318. }
  319. else
  320. {
  321. DisplayMessage(L"Command line: Missing machine name.\n");
  322. }
  323. }
  324. }
  325. if( ERROR_SUCCESS == dwRetCode )
  326. {
  327. continue;
  328. }
  329. else
  330. {
  331. break;
  332. }
  333. }
  334. if( !_wcsicmp(argv[uCommandPosition], L"/L") ||
  335. !_wcsicmp(argv[uCommandPosition], L"/List") )
  336. {
  337. dwRetCode = SetCommand(COMMAND_DUMP);
  338. if( ERROR_SUCCESS == dwRetCode )
  339. {
  340. continue;
  341. }
  342. else
  343. {
  344. break;
  345. }
  346. }
  347. #endif
  348. //
  349. // unknown argument, set the help as command and break
  350. // we have to use this parameter as the command might
  351. // have already been set
  352. //
  353. _snwprintf(g_TempString, MAX_STRING - 1,
  354. L"Invalid command: %s\n",
  355. argv[uCommandPosition]);
  356. DisplayMessage(g_TempString);
  357. SetCommand(COMMAND_NOT_SET);
  358. break;
  359. }
  360. //
  361. // Display usage if no command switch is present
  362. //
  363. if( ERROR_SUCCESS != dwRetCode )
  364. {
  365. DumpCmd();
  366. }
  367. else
  368. {
  369. if( COMMAND_NOT_SET == g_uCommand ) {
  370. SetCommand(COMMAND_HELP);
  371. }
  372. dwRetCode = g_Commands[g_uCommand]();
  373. //
  374. // bad arguments passed to the command, display help
  375. //
  376. if( ERROR_BAD_ARGUMENTS == dwRetCode )
  377. {
  378. DumpCmd();
  379. }
  380. }
  381. return dwRetCode;
  382. }
  383. //+----------------------------------------------------------------------------
  384. //
  385. // MigratePassword
  386. //
  387. // - reads the registry password, deletes it and sets the LSA secret
  388. // - works only on certain win versions
  389. // - if no password present fails
  390. // - if any ops fail does not roll back
  391. // - if pwd read fails - nothing happens
  392. // - if LSA secret set fails - pretty much nothing happens as well.
  393. // - if RegDelete fails - there is no need to delete the LSA secret...
  394. //
  395. //+----------------------------------------------------------------------------
  396. DWORD
  397. MigratePassword()
  398. {
  399. WCHAR Password[MAX_STRING];
  400. DWORD dwRetCode = ERROR_SUCCESS;
  401. BOOL fMigratedPIN = FALSE;
  402. if( ERROR_SUCCESS != CheckWinVersion() ) {
  403. dwRetCode = ERROR_OLD_WIN_VERSION;
  404. goto cleanup;
  405. }
  406. //
  407. // get the DefaultPIN registry key from the local
  408. // or remote system and store it in a local string
  409. // As this is not something we document we do not display any errors
  410. // We also do not display any success messages. The only case where
  411. // we have to display smth PIN related is when we can migrate the PIN
  412. // but there is no password. We can't fail and we have to display something.
  413. //
  414. dwRetCode = GetRegValueSZ(g_PinSecretName, Password, MAX_STRING - 1);
  415. if( ERROR_SUCCESS != dwRetCode )
  416. {
  417. //
  418. // we won't migrate the PIN and silently move on
  419. // this is something we do not document for the tool
  420. //
  421. #ifdef PRIVATE_VERSION
  422. if( ERROR_FILE_NOT_FOUND != dwRetCode )
  423. {
  424. DisplayMessage(L"Migrate: DefaultPIN key cannot be read.\n");
  425. }
  426. #endif
  427. dwRetCode = ERROR_SUCCESS;
  428. goto MigratePassword;
  429. }
  430. //
  431. // Set the DefaultPassword LSASecret to the value we retrieved
  432. // from the registry
  433. //
  434. dwRetCode = SetSecret(Password, FALSE, g_PinSecretName);
  435. if( ERROR_SUCCESS != dwRetCode )
  436. {
  437. #ifdef PRIVATE_VERSION
  438. _snwprintf(g_TempString, MAX_STRING - 1,
  439. L"Migrate: Could not set DefaultPIN LSASecret: %s\n",
  440. GetErrorString(dwRetCode));
  441. DisplayMessage(g_TempString);
  442. #endif
  443. dwRetCode = ERROR_SUCCESS;
  444. goto MigratePassword;
  445. }
  446. // Delete the DefaultPassword registry key
  447. dwRetCode = ClearRegValue(g_PinSecretName);
  448. if( ERROR_SUCCESS != dwRetCode )
  449. {
  450. //
  451. // delete the secret if could not remove the password.
  452. //
  453. (void)SetSecret(NULL, TRUE, g_PinSecretName);
  454. #ifdef PRIVATE_VERSION
  455. _snwprintf(g_TempString, MAX_STRING - 1,
  456. L"Migrate: Could not delete DefaultPIN key: %s\n",
  457. GetErrorString(dwRetCode));
  458. DisplayMessage(g_TempString);
  459. #endif
  460. dwRetCode = ERROR_SUCCESS;
  461. goto MigratePassword;
  462. }
  463. #ifdef PRIVATE_VERSION
  464. DisplayMessage(L"Pin migrated from Registry to LSASecret\n");
  465. #endif
  466. fMigratedPIN = TRUE;
  467. MigratePassword:
  468. // Get the DefaultPassword registry key from the local
  469. // or remote system and store it in a local string
  470. dwRetCode = GetRegValueSZ(g_PasswordSecretName, Password, MAX_STRING - 1);
  471. if( ERROR_FILE_NOT_FOUND == dwRetCode )
  472. {
  473. if( fMigratedPIN )
  474. {
  475. DisplayMessage(L"Migrate: Migrated PIN, DefaultPassword does not exist.\n");
  476. dwRetCode = ERROR_SUCCESS;
  477. }
  478. else
  479. {
  480. DisplayMessage(L"Migrate failed: DefaultPassword does not exist.\n");
  481. }
  482. goto cleanup;
  483. }
  484. if( ERROR_SUCCESS != dwRetCode )
  485. {
  486. _snwprintf(g_TempString, MAX_STRING - 1,
  487. L"Migrate failed: Could not read DefaultPassword: %s\n",
  488. GetErrorString(dwRetCode));
  489. DisplayMessage(g_TempString);
  490. goto cleanup;
  491. }
  492. //
  493. // Set the DefaultPassword LSASecret to the value we retrieved
  494. // from the registry
  495. //
  496. dwRetCode = SetSecret(Password, FALSE, g_PasswordSecretName);
  497. if( ERROR_SUCCESS != dwRetCode )
  498. {
  499. _snwprintf(g_TempString, MAX_STRING - 1,
  500. L"Migrate failed: Could not set DefaultPassword LSASecret: %s\n",
  501. GetErrorString(dwRetCode));
  502. DisplayMessage(g_TempString);
  503. goto cleanup;
  504. }
  505. // Delete the DefaultPassword registry key
  506. dwRetCode = ClearRegValue(g_PasswordSecretName);
  507. if( ERROR_SUCCESS != dwRetCode )
  508. {
  509. //
  510. // delete the secret if could not remove the password.
  511. //
  512. (void)SetSecret(NULL, TRUE, g_PasswordSecretName);
  513. _snwprintf(g_TempString, MAX_STRING - 1,
  514. L"Migrate Failed: Could not delete DefaultPassword key: %s\n",
  515. GetErrorString(dwRetCode));
  516. DisplayMessage(g_TempString);
  517. goto cleanup;
  518. }
  519. DisplayMessage(L"Password migrated from Registry to LSASecret\n");
  520. cleanup:
  521. // zero out the password so it's not left in memory
  522. SecureZeroMemory(Password, MAX_STRING * sizeof(WCHAR));
  523. return dwRetCode;
  524. }
  525. //+----------------------------------------------------------------------------
  526. //
  527. // Delete
  528. //
  529. // - Deletes the secret and the autoadmin logon value
  530. // - Silently ignores the file not found cases
  531. //
  532. //+----------------------------------------------------------------------------
  533. DWORD
  534. Delete()
  535. {
  536. DWORD dwRetCode = ERROR_SUCCESS;
  537. //
  538. // make sure we're running against a correct version of NT
  539. //
  540. if (CheckWinVersion() != ERROR_SUCCESS) {
  541. dwRetCode = ERROR_OLD_WIN_VERSION;
  542. goto cleanup;
  543. }
  544. dwRetCode = ClearRegValue(g_PasswordSecretName);
  545. if( (ERROR_SUCCESS != dwRetCode) &&
  546. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  547. {
  548. _snwprintf(g_TempString, MAX_STRING - 1,
  549. L"Delete: Registry default password delete failed: %s\n",
  550. GetErrorString(dwRetCode));
  551. DisplayMessage(g_TempString);
  552. goto cleanup;
  553. }
  554. dwRetCode = SetSecret(NULL, TRUE, g_PasswordSecretName);
  555. if( (ERROR_SUCCESS != dwRetCode) &&
  556. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  557. {
  558. _snwprintf(g_TempString, MAX_STRING - 1,
  559. L"Delete: LSA Secret delete failed: %s\n",
  560. GetErrorString(dwRetCode));
  561. DisplayMessage(g_TempString);
  562. goto cleanup;
  563. }
  564. dwRetCode = ClearRegValue(g_PinSecretName);
  565. if( (ERROR_SUCCESS != dwRetCode) &&
  566. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  567. {
  568. #ifdef PRIVATE_VERSION
  569. _snwprintf(g_TempString, MAX_STRING - 1,
  570. L"Delete: Registry default pin delete failed: %s\n",
  571. GetErrorString(dwRetCode));
  572. DisplayMessage(g_TempString);
  573. #endif
  574. }
  575. dwRetCode = SetSecret(NULL, TRUE, g_PinSecretName);
  576. if( (ERROR_SUCCESS != dwRetCode) &&
  577. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  578. {
  579. #ifdef PRIVATE_VERSION
  580. _snwprintf(g_TempString, MAX_STRING - 1,
  581. L"Delete: LSA Secret(PIN) delete failed: %s\n",
  582. GetErrorString(dwRetCode));
  583. DisplayMessage(g_TempString);
  584. #endif
  585. }
  586. //
  587. // disable the autologon - if it fails don't recover - the autologon
  588. // will pretty much fail anyway
  589. //
  590. dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"0");
  591. if( ERROR_SUCCESS != dwRetCode )
  592. {
  593. _snwprintf(g_TempString, MAX_STRING - 1,
  594. L"Delete: AutoAdminLogon reg value reset failed: %s\n",
  595. GetErrorString(dwRetCode));
  596. DisplayMessage(g_TempString);
  597. goto cleanup;
  598. }
  599. dwRetCode = ClearRegValue(g_AutoLogonCountName);
  600. if( (ERROR_SUCCESS != dwRetCode) &&
  601. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  602. {
  603. _snwprintf(g_TempString, MAX_STRING - 1,
  604. L"AutoLogonCount : Set Failed: %s\n",
  605. GetErrorString(dwRetCode));
  606. DisplayMessage(g_TempString);
  607. goto cleanup;
  608. }
  609. dwRetCode = ERROR_SUCCESS;
  610. DisplayMessage(L"AutoAdminLogon disabled.\n");
  611. cleanup:
  612. return dwRetCode;
  613. }
  614. //+----------------------------------------------------------------------------
  615. //
  616. // EnableAutoLogon
  617. //
  618. // - gets the username/pwd
  619. // - sets the username/domain
  620. // - sets the autlogon count if specified and != 0
  621. // - sets the LSA secret
  622. // - sets the autoadminlogon
  623. // - if autoadminlogon fails then tries to delete the LSA secret
  624. //
  625. //+----------------------------------------------------------------------------
  626. DWORD
  627. EnableAutoLogon()
  628. {
  629. DWORD dwRetCode = ERROR_SUCCESS;
  630. WCHAR* pBackSlash = NULL;
  631. WCHAR* pAtSign = NULL;
  632. //
  633. // make sure we're running against a correct version of NT
  634. //
  635. if (CheckWinVersion() != ERROR_SUCCESS) {
  636. dwRetCode = ERROR_OLD_WIN_VERSION;
  637. goto cleanup;
  638. }
  639. //
  640. // fill in the user name: try both NameUserPrincipal and NameSamCompatible
  641. //
  642. if( !*g_UserName )
  643. {
  644. ULONG uSize = MAX_STRING - 1;
  645. if( !GetUserNameEx(NameUserPrincipal,
  646. g_UserName,
  647. &uSize) )
  648. {
  649. uSize = MAX_STRING - 1;
  650. if( !GetUserNameEx(NameSamCompatible,
  651. g_UserName,
  652. &uSize) )
  653. {
  654. dwRetCode = GetLastError();
  655. _snwprintf(g_TempString, MAX_STRING - 1,
  656. L"Set: Could not get the logged on user name: %s\n",
  657. GetErrorString(dwRetCode));
  658. DisplayMessage(g_TempString);
  659. goto cleanup;
  660. }
  661. }
  662. }
  663. //
  664. // Make sure we have correct information passed in
  665. //
  666. if( !g_SetDefaultPIN && !*g_UserName )
  667. {
  668. DisplayMessage(L"Set: Failed: Username does not exist.\n");
  669. dwRetCode = ERROR_BAD_ARGUMENTS;
  670. goto cleanup;
  671. }
  672. //
  673. // this call uses CredMan on XP
  674. //
  675. dwRetCode = GetPassword();
  676. if( ERROR_SUCCESS != dwRetCode )
  677. {
  678. _snwprintf(g_TempString, MAX_STRING - 1,
  679. L"Set: Failed to get the password: %s\n",
  680. GetErrorString(dwRetCode));
  681. DisplayMessage(g_TempString);
  682. goto cleanup;
  683. }
  684. if( !g_SetDefaultPIN )
  685. {
  686. //
  687. // if a domain specified in the form of domain\username extract it
  688. // Proper formats are
  689. // Case 1: /username:JohnDoe
  690. // Case 2: /username: [email protected]
  691. // Case 3: /username:Domain\JohnDoe
  692. //
  693. //
  694. // is '\' present?
  695. //
  696. pBackSlash = wcschr(g_UserName, '\\');
  697. if( NULL != pBackSlash )
  698. {
  699. //
  700. // Case 3, copy into both user and domain buffer
  701. // Domain is first as we don't want to overwrite the buffer
  702. // Yes, wcsncpy works from beggining to the end ;-)
  703. //
  704. wcsncpy(g_DomainName, g_UserName,
  705. __min(MAX_STRING - 1, (pBackSlash - g_UserName)) );
  706. g_DomainName[MAX_STRING - 1] = 0;
  707. wcsncpy(g_UserName, pBackSlash + 1, MAX_STRING - 1);
  708. g_UserName[MAX_STRING - 1] = 0;
  709. }
  710. else
  711. {
  712. //
  713. // if we have @ in the user name delete the domain
  714. //
  715. pAtSign = wcschr(g_UserName, '@');
  716. g_DomainName[0] = 0;
  717. }
  718. }
  719. //
  720. // Deletes the reg password value
  721. //
  722. if( g_SetDefaultPIN )
  723. {
  724. dwRetCode = ClearRegValue(g_PinSecretName);
  725. }
  726. else
  727. {
  728. dwRetCode = ClearRegValue(g_PasswordSecretName);
  729. }
  730. if( (ERROR_SUCCESS != dwRetCode) &&
  731. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  732. {
  733. _snwprintf(g_TempString, MAX_STRING - 1,
  734. L"RegPassword : Reset Failed: %s\n",
  735. GetErrorString(dwRetCode));
  736. DisplayMessage(g_TempString);
  737. goto cleanup;
  738. }
  739. if( !g_SetDefaultPIN )
  740. {
  741. //
  742. // sets the username
  743. //
  744. dwRetCode = SetRegValueSZ(g_DefaultUserName, g_UserName);
  745. if( ERROR_SUCCESS != dwRetCode )
  746. {
  747. _snwprintf(g_TempString, MAX_STRING - 1,
  748. L"UserName : Set Failed: %s\n",
  749. GetErrorString(dwRetCode));
  750. DisplayMessage(g_TempString);
  751. goto cleanup;
  752. }
  753. _snwprintf(g_TempString, MAX_STRING - 1,
  754. L"UserName : %s\n",
  755. g_UserName);
  756. DisplayMessage(g_TempString);
  757. }
  758. if( !g_SetDefaultPIN )
  759. {
  760. //
  761. // sets the domain, if any or pAtSign is not NULL
  762. //
  763. if( *g_DomainName || pAtSign )
  764. {
  765. SetRegValueSZ(g_DefaultDomainName, g_DomainName);
  766. if( ERROR_SUCCESS != dwRetCode )
  767. {
  768. _snwprintf(g_TempString, MAX_STRING - 1,
  769. L"DomainName : Set Failed: %s\n",
  770. GetErrorString(dwRetCode));
  771. DisplayMessage(g_TempString);
  772. goto cleanup;
  773. }
  774. _snwprintf(g_TempString, MAX_STRING - 1,
  775. L"DomainName : %s\n",
  776. g_DomainName);
  777. DisplayMessage(g_TempString);
  778. }
  779. }
  780. //
  781. // set the AutoLogonCount if not 0
  782. //
  783. if( g_AutoLogonCount )
  784. {
  785. dwRetCode = SetRegValueDWORD(g_AutoLogonCountName, g_AutoLogonCount);
  786. if( ERROR_SUCCESS != dwRetCode )
  787. {
  788. _snwprintf(g_TempString, MAX_STRING - 1,
  789. L"AutoLogonCount : Set Failed: %s\n",
  790. GetErrorString(dwRetCode));
  791. DisplayMessage(g_TempString);
  792. goto cleanup;
  793. }
  794. _snwprintf(g_TempString, MAX_STRING - 1,
  795. L"AutoLogonCount : %#x\n",
  796. g_AutoLogonCount);
  797. DisplayMessage(g_TempString);
  798. }
  799. else
  800. {
  801. dwRetCode = ClearRegValue(g_AutoLogonCountName);
  802. if( (ERROR_SUCCESS != dwRetCode) &&
  803. (ERROR_FILE_NOT_FOUND != dwRetCode) )
  804. {
  805. _snwprintf(g_TempString, MAX_STRING - 1,
  806. L"AutoLogonCount : Clear Failed: %s\n",
  807. GetErrorString(dwRetCode));
  808. DisplayMessage(g_TempString);
  809. goto cleanup;
  810. }
  811. _snwprintf(g_TempString, MAX_STRING - 1,
  812. L"AutoLogonCount : (Disabled)\n");
  813. DisplayMessage(g_TempString);
  814. }
  815. //
  816. // set the password
  817. //
  818. if( g_SetDefaultPIN )
  819. {
  820. dwRetCode = SetSecret(g_Password, FALSE, g_PinSecretName);
  821. }
  822. else
  823. {
  824. dwRetCode = SetSecret(g_Password, FALSE, g_PasswordSecretName);
  825. }
  826. if( ERROR_SUCCESS != dwRetCode)
  827. {
  828. _snwprintf(g_TempString, MAX_STRING - 1,
  829. L"LSASecret : Set Failed: %s\n",
  830. GetErrorString(dwRetCode));
  831. DisplayMessage(g_TempString);
  832. goto cleanup;
  833. }
  834. #ifdef PRIVATE_VERSION
  835. _snwprintf(g_TempString, MAX_STRING - 1,
  836. L"LSASecret : %s\n",
  837. g_Password);
  838. #else
  839. _snwprintf(g_TempString, MAX_STRING - 1,
  840. L"LSASecret : (set)\n");
  841. #endif
  842. DisplayMessage(g_TempString);
  843. if( !g_SetDefaultPIN )
  844. {
  845. //
  846. // set the AutoAdminLogon regvalue to 1
  847. //
  848. dwRetCode = SetRegValueSZ(g_AutoAdminLogonName, L"1");
  849. if( ERROR_SUCCESS != dwRetCode )
  850. {
  851. //
  852. // (try to) clear the secret if this fails
  853. //
  854. (void)SetSecret(NULL, TRUE, g_PasswordSecretName);
  855. _snwprintf(g_TempString, MAX_STRING - 1,
  856. L"AutoAdminLogon: Set Failed: %s\n",
  857. GetErrorString(dwRetCode));
  858. DisplayMessage(g_TempString);
  859. goto cleanup;
  860. }
  861. DisplayMessage(L"AutoAdminLogon : 1\n");
  862. }
  863. cleanup:
  864. SecureZeroMemory(g_Password, MAX_STRING * sizeof(WCHAR));
  865. return dwRetCode;
  866. }
  867. //+----------------------------------------------------------------------------
  868. //
  869. // DumpCmd
  870. //
  871. // - Help
  872. //
  873. //+----------------------------------------------------------------------------
  874. DWORD
  875. DumpCmd()
  876. {
  877. if (g_QuietMode)
  878. {
  879. return ERROR_SUCCESS;
  880. }
  881. wprintf(L"\nAUTOLOGON v1.00 : (c) 2001, Microsoft Corporation\n\n");
  882. wprintf(L"DESCRIPTION:\n");
  883. wprintf(L" Used to configure encrypted autologon functionality\n\n");
  884. wprintf(L"USAGE:\n");
  885. wprintf(L" AUTOLOGON [/?] [/Quiet] [/Migrate] [/Delete] [/Set]\n");
  886. wprintf(L" [/Username:username] [/Count:count]\n");
  887. wprintf(L" Options:\n");
  888. wprintf(L" /? Display complete help documentation\n");
  889. wprintf(L" /Quiet Enable quiet mode, which supresses all output\n");
  890. wprintf(L" /Migrate Migrate cleartext password from registry to LSASecret\n");
  891. wprintf(L" /Delete Deletes the default password and disable AutoAdminLogon \n");
  892. wprintf(L" /Set Set the DefaultPassword LSASecret and enable AutoAdminLogon\n");
  893. wprintf(L" /Username The username to set in Default UserName.\n");
  894. wprintf(L" /Count Set the logoncount\n");
  895. #ifdef PRIVATE_VERSION
  896. wprintf(L" /Pin Set the DefaultPin LSASecret\n");
  897. wprintf(L" /List List autologon settings\n");
  898. wprintf(L" /Target The remote computer name\n");
  899. #endif
  900. if( g_FullHelp )
  901. {
  902. wprintf(L"\nNOTES:\n");
  903. wprintf(L" 1.The /Migrate /Delete /Set commands are exclusive.\n");
  904. wprintf(L" You will always be prompted for a password.\n");
  905. wprintf(L" If a username is not specified the currently logged on user is assumed.\n");
  906. wprintf(L" If no count is specified a count of 0 is implicitely assumed.\n\n");
  907. wprintf(L" 2.You need to be running as a member of the local administrators group for\n");
  908. wprintf(L" this utility to work properly.\n\n");
  909. wprintf(L" 3.When setting a password that has special characters in it, such as \"|>&\n");
  910. wprintf(L" make sure that you escape these characters. Also, passwords with spaces \n");
  911. wprintf(L" should be enclosed in double quotes.\n\n");
  912. wprintf(L" 4.Setting the logoncount to 0 means an autologon will be performed until\n");
  913. wprintf(L" the secret is deleted.\n\n");
  914. }
  915. return ERROR_SUCCESS;
  916. }
  917. //+----------------------------------------------------------------------------
  918. //
  919. // DumpAutoLogonInfo
  920. //
  921. // - Dumps relevant data
  922. //
  923. //+----------------------------------------------------------------------------
  924. #ifdef PRIVATE_VERSION
  925. DWORD
  926. DumpAutoLogonInfo()
  927. {
  928. WCHAR wcsTempString[MAX_STRING];
  929. DWORD dwRetCode = ERROR_SUCCESS;
  930. //
  931. // make sure we're running against a correct version of NT
  932. //
  933. if (CheckWinVersion() != ERROR_SUCCESS) {
  934. dwRetCode = ERROR_OLD_WIN_VERSION;
  935. goto cleanup;
  936. }
  937. //
  938. // Get the username
  939. //
  940. dwRetCode = GetRegValueSZ(g_DefaultUserName, wcsTempString, MAX_STRING - 1);
  941. switch (dwRetCode) {
  942. // catch this case and continue
  943. case ERROR_FILE_NOT_FOUND:
  944. _snwprintf(g_TempString, MAX_STRING - 1,
  945. L"DefaultUserName : (regvalue does not exist)\n");
  946. DisplayMessage(g_TempString);
  947. break;
  948. // On success, print the regkey and continue to next item
  949. case ERROR_SUCCESS:
  950. _snwprintf(g_TempString, MAX_STRING - 1,
  951. L"DefaultUserName : %s\n",
  952. wcsTempString);
  953. DisplayMessage(g_TempString);
  954. break;
  955. // catch all the generic errors and end
  956. default:
  957. _snwprintf(g_TempString, MAX_STRING - 1,
  958. L"DefaultUserName : Failed to query regkey: %s\n",
  959. GetErrorString(dwRetCode));
  960. DisplayMessage(g_TempString);
  961. goto cleanup;
  962. }
  963. //
  964. // Get the DefaultDomainName
  965. //
  966. dwRetCode = GetRegValueSZ(g_DefaultDomainName, wcsTempString, MAX_STRING - 1);
  967. switch (dwRetCode) {
  968. // catch this case and continue
  969. case ERROR_FILE_NOT_FOUND:
  970. _snwprintf(g_TempString, MAX_STRING - 1,
  971. L"DefaultDomainName: (regvalue does not exist)\n");
  972. DisplayMessage(g_TempString);
  973. break;
  974. // On success, print the regkey and continue to next item
  975. case ERROR_SUCCESS:
  976. _snwprintf(g_TempString, MAX_STRING - 1,
  977. L"DefaultDomainName: %s\n",
  978. wcsTempString);
  979. DisplayMessage(g_TempString);
  980. break;
  981. // catch all the generic errors and end
  982. default:
  983. _snwprintf(g_TempString, MAX_STRING - 1,
  984. L"DefaultDomainName: Failed to query regkey: %s\n",
  985. GetErrorString(dwRetCode));
  986. DisplayMessage(g_TempString);
  987. goto cleanup;
  988. }
  989. //
  990. // Get the DefaultPassword
  991. //
  992. dwRetCode = GetRegValueSZ(g_PasswordSecretName,
  993. wcsTempString, MAX_STRING - 1);
  994. switch (dwRetCode) {
  995. // catch this case and continue
  996. case ERROR_FILE_NOT_FOUND:
  997. _snwprintf(g_TempString, MAX_STRING - 1,
  998. L"DefaultPassword : (regvalue does not exist)\n");
  999. DisplayMessage(g_TempString);
  1000. break;
  1001. // On success, print the regkey and continue to next item
  1002. case ERROR_SUCCESS:
  1003. _snwprintf(g_TempString, MAX_STRING - 1,
  1004. L"DefaultPassword : %s\n",
  1005. wcsTempString);
  1006. DisplayMessage(g_TempString);
  1007. break;
  1008. // catch all the generic errors and end
  1009. default:
  1010. _snwprintf(g_TempString, MAX_STRING - 1,
  1011. L"DefaultPassword : Failed to query regkey: %s\n",
  1012. GetErrorString(dwRetCode));
  1013. goto cleanup;
  1014. }
  1015. //
  1016. // Get the DefaultPin - display it only if there
  1017. //
  1018. dwRetCode = GetRegValueSZ(g_PinSecretName,
  1019. wcsTempString, MAX_STRING - 1);
  1020. switch (dwRetCode) {
  1021. // catch this case and continue
  1022. case ERROR_FILE_NOT_FOUND:
  1023. break;
  1024. // On success, print the regkey and continue to next item
  1025. case ERROR_SUCCESS:
  1026. _snwprintf(g_TempString, MAX_STRING - 1,
  1027. L"DefaultPIN : %s\n",
  1028. wcsTempString);
  1029. DisplayMessage(g_TempString);
  1030. break;
  1031. // catch all the generic errors and continue
  1032. default:
  1033. break;
  1034. }
  1035. //
  1036. // Get the AutoAdminLogonCount
  1037. //
  1038. dwRetCode = GetRegValueDWORD(g_AutoLogonCountName, &g_AutoLogonCount);
  1039. switch (dwRetCode) {
  1040. // catch this case and continue
  1041. case ERROR_FILE_NOT_FOUND:
  1042. _snwprintf(g_TempString, MAX_STRING - 1,
  1043. L"AutoLogonCount : (regvalue does not exist)\n");
  1044. DisplayMessage(g_TempString);
  1045. break;
  1046. // On success, print the regkey and continue to next item
  1047. case ERROR_SUCCESS:
  1048. _snwprintf(g_TempString, MAX_STRING - 1,
  1049. L"AutoLogonCount : %#x\n",
  1050. g_AutoLogonCount);
  1051. DisplayMessage(g_TempString);
  1052. break;
  1053. // catch all the generic errors and end
  1054. default:
  1055. _snwprintf(g_TempString, MAX_STRING - 1,
  1056. L"AutoLogonCount : Failed to query regkey: %s\n",
  1057. GetErrorString(dwRetCode));
  1058. goto cleanup;
  1059. }
  1060. //
  1061. // Get the LSASecret DefaultPassword
  1062. //
  1063. dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PasswordSecretName);
  1064. switch (dwRetCode) {
  1065. // catch this case and continue
  1066. case STATUS_OBJECT_NAME_NOT_FOUND:
  1067. _snwprintf(g_TempString, MAX_STRING - 1,
  1068. L"LSASecret : (secret does not exist)\n");
  1069. DisplayMessage(g_TempString);
  1070. break;
  1071. // catch this case and continue
  1072. case ERROR_ACCESS_DENIED:
  1073. _snwprintf(g_TempString, MAX_STRING - 1,
  1074. L"LSASecret : (access denied)\n");
  1075. DisplayMessage(g_TempString);
  1076. break;
  1077. // On success, print the regkey and continue to next item
  1078. case ERROR_SUCCESS:
  1079. _snwprintf(g_TempString, MAX_STRING - 1,
  1080. L"LSASecret : %s\n",
  1081. wcsTempString);
  1082. DisplayMessage(g_TempString);
  1083. break;
  1084. // catch all the generic errors and end
  1085. default:
  1086. _snwprintf(g_TempString, MAX_STRING - 1,
  1087. L"LSASecret : Failed to query LSASecret: %s\n",
  1088. GetErrorString(dwRetCode));
  1089. DisplayMessage(g_TempString);
  1090. goto cleanup;
  1091. }
  1092. //
  1093. // Get the LSASecret DefaultPin
  1094. //
  1095. dwRetCode = GetSecret(wcsTempString, MAX_STRING - 1, g_PinSecretName);
  1096. switch (dwRetCode) {
  1097. // catch this case and continue
  1098. case STATUS_OBJECT_NAME_NOT_FOUND:
  1099. _snwprintf(g_TempString, MAX_STRING - 1,
  1100. L"LSASecret(PIN) : (secret does not exist)\n");
  1101. DisplayMessage(g_TempString);
  1102. break;
  1103. // catch this case and continue
  1104. case ERROR_ACCESS_DENIED:
  1105. _snwprintf(g_TempString, MAX_STRING - 1,
  1106. L"LSASecret(PIN) : (access denied)\n");
  1107. DisplayMessage(g_TempString);
  1108. break;
  1109. // On success, print the regkey and continue to next item
  1110. case ERROR_SUCCESS:
  1111. _snwprintf(g_TempString, MAX_STRING - 1,
  1112. L"LSASecret(PIN) : %s\n",
  1113. wcsTempString);
  1114. DisplayMessage(g_TempString);
  1115. break;
  1116. // catch all the generic errors and end
  1117. default:
  1118. _snwprintf(g_TempString, MAX_STRING - 1,
  1119. L"LSASecret(PIN) : Failed to query LSASecret: %s\n",
  1120. GetErrorString(dwRetCode));
  1121. DisplayMessage(g_TempString);
  1122. goto cleanup;
  1123. }
  1124. //
  1125. // Get the AutoAdminLogon
  1126. //
  1127. dwRetCode = GetRegValueSZ(g_AutoAdminLogonName, wcsTempString, MAX_STRING - 1);
  1128. switch (dwRetCode) {
  1129. // catch this case and continue
  1130. case ERROR_FILE_NOT_FOUND:
  1131. _snwprintf(g_TempString, MAX_STRING - 1,
  1132. L"AutoAdminLogon : (regvalue does not exist)\n");
  1133. DisplayMessage(g_TempString);
  1134. break;
  1135. // On success, print the regkey and continue to next item
  1136. case ERROR_SUCCESS:
  1137. _snwprintf(g_TempString, MAX_STRING - 1,
  1138. L"AutoAdminLogon : %s\n",
  1139. wcsTempString);
  1140. DisplayMessage(g_TempString);
  1141. break;
  1142. // catch all the generic errors and end
  1143. default:
  1144. _snwprintf(g_TempString, MAX_STRING - 1,
  1145. L"AutoAdminLogon : Failed to query regkey: %s\n",
  1146. GetErrorString(dwRetCode));
  1147. goto cleanup;
  1148. }
  1149. cleanup:
  1150. SecureZeroMemory(g_TempString, MAX_STRING * sizeof(WCHAR));
  1151. SecureZeroMemory(wcsTempString, MAX_STRING * sizeof(WCHAR));
  1152. return dwRetCode;
  1153. }
  1154. #endif
  1155. //+----------------------------------------------------------------------------
  1156. //
  1157. // SetCommand
  1158. //
  1159. // - Sets the command
  1160. // - if there are two successive calls to this it will fail - as in two
  1161. // commands passed in the command line
  1162. // - a call greater with than COMMAND line resets the command to COMMAND_HELP
  1163. //
  1164. //+----------------------------------------------------------------------------
  1165. DWORD
  1166. SetCommand(UINT uCommand)
  1167. {
  1168. DWORD dwRetCode = ERROR_SUCCESS;
  1169. if( COMMAND_NOT_SET == uCommand )
  1170. {
  1171. g_uCommand = COMMAND_NOT_SET;
  1172. goto cleanup;
  1173. }
  1174. //
  1175. // if already set, fail
  1176. //
  1177. if( COMMAND_NOT_SET != g_uCommand )
  1178. {
  1179. dwRetCode = ERROR_BAD_ARGUMENTS;
  1180. goto cleanup;
  1181. }
  1182. if( g_uCommand > COMMAND_SIZE )
  1183. {
  1184. //
  1185. // assert?
  1186. //
  1187. g_uCommand = COMMAND_HELP;
  1188. }
  1189. else
  1190. {
  1191. g_uCommand = uCommand;
  1192. }
  1193. cleanup:
  1194. return dwRetCode;
  1195. }
  1196. //+----------------------------------------------------------------------------
  1197. //
  1198. // SetQuietMode
  1199. //
  1200. //+----------------------------------------------------------------------------
  1201. DWORD
  1202. SetQuietMode(WCHAR* pszData)
  1203. {
  1204. UNREFERENCED_PARAMETER(pszData);
  1205. g_QuietMode = TRUE;
  1206. return ERROR_SUCCESS;
  1207. }
  1208. //+----------------------------------------------------------------------------
  1209. //
  1210. // SetUserName
  1211. //
  1212. // - Sets the username
  1213. // - Proper formats are combinations of
  1214. // /username:"user name"
  1215. // /username username
  1216. // /username: " user name"
  1217. //
  1218. // - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
  1219. // move on to the next parameter
  1220. //+----------------------------------------------------------------------------
  1221. DWORD
  1222. SetUserName(WCHAR* pszData)
  1223. {
  1224. DWORD dwRetCode = ERROR_SUCCESS;
  1225. WCHAR* pCh = NULL;
  1226. //
  1227. // is ":" present?
  1228. //
  1229. pCh = wcschr(pszData, ':');
  1230. if( NULL == pCh )
  1231. {
  1232. pCh = pszData;
  1233. }
  1234. else
  1235. {
  1236. pCh++;
  1237. }
  1238. //
  1239. // scan past any leading spaces - we KNOW this is NULL terminated
  1240. //
  1241. while( iswspace(*pCh) )
  1242. {
  1243. pCh++;
  1244. }
  1245. //
  1246. // column followed by spaces only
  1247. //
  1248. if( !*pCh )
  1249. {
  1250. dwRetCode = ERROR_FILE_NOT_FOUND;
  1251. goto cleanup;
  1252. }
  1253. //
  1254. // if we're still at the leading '/' then it means we have the
  1255. // /U username case
  1256. //
  1257. if( '/' == *pCh )
  1258. {
  1259. dwRetCode = ERROR_FILE_NOT_FOUND;
  1260. goto cleanup;
  1261. }
  1262. wcsncpy(g_UserName, pCh, MAX_STRING - 1);
  1263. g_UserName[MAX_STRING - 1] = 0;
  1264. cleanup:
  1265. return dwRetCode;
  1266. }
  1267. #ifdef PRIVATE_VERSION
  1268. //+----------------------------------------------------------------------------
  1269. //
  1270. // SetMachineName
  1271. //
  1272. //+----------------------------------------------------------------------------
  1273. DWORD
  1274. SetMachineName(WCHAR* pszData)
  1275. {
  1276. DWORD dwRetCode = ERROR_SUCCESS;
  1277. WCHAR* pCh = NULL;
  1278. //
  1279. // is ":" present?
  1280. //
  1281. pCh = wcschr(pszData, ':');
  1282. if( NULL == pCh )
  1283. {
  1284. pCh = pszData;
  1285. }
  1286. else
  1287. {
  1288. pCh++;
  1289. }
  1290. //
  1291. // scan past any leading spaces - we KNOW this is NULL terminated
  1292. //
  1293. while( iswspace(*pCh) )
  1294. {
  1295. pCh++;
  1296. }
  1297. //
  1298. // column followed by spaces only
  1299. //
  1300. if( !*pCh )
  1301. {
  1302. dwRetCode = ERROR_FILE_NOT_FOUND;
  1303. goto cleanup;
  1304. }
  1305. //
  1306. // if we're still at the leading '/' then it means we have the
  1307. // /U username case
  1308. //
  1309. if( '/' == *pCh )
  1310. {
  1311. dwRetCode = ERROR_FILE_NOT_FOUND;
  1312. goto cleanup;
  1313. }
  1314. g_RemoteOperation = TRUE;
  1315. wcsncpy(g_RemoteComputerName, pCh, MAX_STRING - 1);
  1316. g_RemoteComputerName[MAX_STRING - 1] = 0;
  1317. cleanup:
  1318. return dwRetCode;
  1319. }
  1320. #endif
  1321. //+----------------------------------------------------------------------------
  1322. //
  1323. // SetCount
  1324. //
  1325. // - Sets the count
  1326. // - Proper formats are combinations of
  1327. // /Count:300
  1328. // /Count 300
  1329. // /Count: 300
  1330. //
  1331. // - returns ERROR_FILE_NOT_FOUND when the arg is missing so the caller can
  1332. // move on to the next parameter
  1333. //+----------------------------------------------------------------------------
  1334. DWORD
  1335. SetCount(WCHAR* pszData)
  1336. {
  1337. DWORD dwRetCode = ERROR_SUCCESS;
  1338. WCHAR* pEndString = NULL;
  1339. UINT Count = 0;
  1340. //
  1341. // is ":" present?
  1342. //
  1343. WCHAR* pCh = wcschr(pszData, ':');
  1344. if( NULL == pCh )
  1345. {
  1346. pCh = pszData;
  1347. }
  1348. else
  1349. {
  1350. pCh++;
  1351. }
  1352. //
  1353. // scan past any leading spaces - we KNOW this is NULL terminated
  1354. //
  1355. while ( iswspace(*pCh) )
  1356. {
  1357. pCh++;
  1358. }
  1359. //
  1360. // column followed by spaces only
  1361. //
  1362. if( !*pCh )
  1363. {
  1364. dwRetCode = ERROR_FILE_NOT_FOUND;
  1365. goto cleanup;
  1366. }
  1367. Count = wcstoul(pCh, &pEndString, 0);
  1368. if( *pEndString )
  1369. {
  1370. if( pEndString != pCh )
  1371. {
  1372. //
  1373. // If the input is incorrect
  1374. //
  1375. dwRetCode = ERROR_BAD_ARGUMENTS;
  1376. DisplayMessage(L"Count: Failed: Not a number.\n");
  1377. }
  1378. else
  1379. {
  1380. //
  1381. // this means we run into a "/C 100" case and we have to move
  1382. // to the next argument
  1383. //
  1384. dwRetCode = ERROR_FILE_NOT_FOUND;
  1385. }
  1386. goto cleanup;
  1387. }
  1388. //
  1389. // Ignore if 0
  1390. //
  1391. if( Count )
  1392. {
  1393. g_AutoLogonCount = (DWORD)Count;
  1394. }
  1395. cleanup:
  1396. return dwRetCode;
  1397. }
  1398. //+----------------------------------------------------------------------------
  1399. //
  1400. // CredMan call data
  1401. //
  1402. // We have to dinamically load the dll and call into it as it is not present
  1403. // Win2k, NT4
  1404. //
  1405. //+----------------------------------------------------------------------------
  1406. //
  1407. // CredMan function
  1408. //
  1409. typedef DWORD (*PCredUIFunction) (
  1410. PCTSTR pszTargetName,
  1411. PCtxtHandle Reserved,
  1412. DWORD dwAuthError,
  1413. PCTSTR pszUserName,
  1414. ULONG ulUserNameMaxChars,
  1415. PCTSTR pszPassword,
  1416. ULONG ulPasswordMaxChars,
  1417. PBOOL pfSave,
  1418. DWORD dwFlags
  1419. );
  1420. //+----------------------------------------------------------------------------
  1421. //
  1422. // GetPassword
  1423. //
  1424. // - tries to load credui dll and if not there
  1425. // falls back on regular console functions
  1426. //
  1427. //+----------------------------------------------------------------------------
  1428. DWORD GetPassword()
  1429. {
  1430. DWORD dwRetCode = ERROR_INVALID_FUNCTION;
  1431. BOOL fSave = FALSE;
  1432. PCredUIFunction pCredUICmdLinePromptForCredentials = NULL;
  1433. HMODULE hModule = NULL;
  1434. do
  1435. {
  1436. //
  1437. // Try see if CredMan is present
  1438. //
  1439. hModule = LoadLibrary(L"credui.dll");
  1440. if( NULL == hModule )
  1441. {
  1442. break;
  1443. }
  1444. //
  1445. // get function pointer
  1446. //
  1447. pCredUICmdLinePromptForCredentials =
  1448. (PCredUIFunction)GetProcAddress(
  1449. hModule,
  1450. "CredUICmdLinePromptForCredentialsW");
  1451. if( NULL == pCredUICmdLinePromptForCredentials )
  1452. {
  1453. break;
  1454. }
  1455. //
  1456. // CREDUI_FLAGS_DO_NOT_PERSIST - autologon pwd should not be persisted
  1457. // CREDUI_FLAGS_VALIDATE_USERNAME - just a precaution
  1458. // CREDUI_FLAGS_EXCLUDE_CERTIFICATES - we don't want this for autologon
  1459. // CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS - prevents 'connect to'
  1460. // string to be displayed and since target is AutoAdminLogon
  1461. // it boils down to a nice prompt. Note that this flag will skip
  1462. // the user name, but we assume the username is already filled in
  1463. //
  1464. dwRetCode = pCredUICmdLinePromptForCredentials(
  1465. L"AutoAdminLogon", // PCTSTR pszTargetName
  1466. NULL, // PCtxtHandle Reserved
  1467. NO_ERROR, // DWORD dwAuthError
  1468. g_UserName, // PCTSTR pszUserName
  1469. MAX_STRING - 1, // ULONG ulUserNameMaxChars
  1470. g_Password, // PCTSTR pszPassword
  1471. MAX_STRING - 1, // ULONG ulPasswordMaxChars
  1472. &fSave, // PBOOL pfSave,
  1473. // DWORD dwFlags
  1474. CREDUI_FLAGS_DO_NOT_PERSIST |
  1475. CREDUI_FLAGS_VALIDATE_USERNAME |
  1476. CREDUI_FLAGS_EXCLUDE_CERTIFICATES |
  1477. CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS
  1478. );
  1479. } while( FALSE );
  1480. //
  1481. // if CredMan is not present then just try the console input;
  1482. // pass similar strings (though non localized)
  1483. //
  1484. if( ERROR_INVALID_FUNCTION == dwRetCode )
  1485. {
  1486. //
  1487. // if user has not been specified
  1488. //
  1489. if( !*g_UserName )
  1490. {
  1491. dwRetCode = GetConsoleStr(g_UserName, MAX_STRING - 1,
  1492. FALSE,
  1493. L"Enter the user name for AutoAdminLogon: ",
  1494. NULL);
  1495. if( ERROR_SUCCESS != dwRetCode )
  1496. {
  1497. goto cleanup;
  1498. }
  1499. }
  1500. dwRetCode = GetConsoleStr(g_Password, MAX_STRING - 1,
  1501. TRUE,
  1502. L"Enter the password for AutoAdminLogon: ",
  1503. NULL);
  1504. if( ERROR_SUCCESS != dwRetCode )
  1505. {
  1506. goto cleanup;
  1507. }
  1508. }
  1509. goto cleanup;
  1510. cleanup:
  1511. if( hModule )
  1512. {
  1513. FreeLibrary(hModule);
  1514. }
  1515. return dwRetCode;
  1516. }
  1517. //+----------------------------------------------------------------------------
  1518. //
  1519. // CheckWinVersion
  1520. // - currently any OS post NT4/SP7 supports this.
  1521. // - the remote case (which we do not support yet) assumes remote NT4
  1522. // as being pre-SP7...
  1523. //
  1524. //+----------------------------------------------------------------------------
  1525. DWORD
  1526. CheckWinVersion()
  1527. {
  1528. DWORD dwMachineVerNumber = 0;
  1529. DWORD dwRetCode = ERROR_SUCCESS;
  1530. OSVERSIONINFOEX versionInfoEx;
  1531. NET_API_STATUS status;
  1532. // Make sure it's a Win2k box
  1533. #ifdef PRIVATE_VERSION
  1534. if (g_RemoteOperation) {
  1535. status = GetMajorNTVersion(&dwMachineVerNumber,
  1536. g_RemoteComputerName);
  1537. }
  1538. else
  1539. #endif
  1540. {
  1541. status = GetMajorNTVersion(&dwMachineVerNumber,
  1542. NULL);
  1543. }
  1544. switch (dwMachineVerNumber) {
  1545. case 3:
  1546. dwRetCode = ERROR_OLD_WIN_VERSION;
  1547. _snwprintf(g_TempString, MAX_STRING - 1,
  1548. L"Error: Running NT3.x\n");
  1549. DisplayMessage(g_TempString);
  1550. break;
  1551. case 4:
  1552. //
  1553. // Verify SP7 - only locally for now
  1554. //
  1555. #ifdef PRIVATE_VERSION
  1556. if( !g_RemoteOperation )
  1557. #endif
  1558. {
  1559. //
  1560. // GetVersionInfoEx call for getting the SP information
  1561. //
  1562. SecureZeroMemory(&versionInfoEx, sizeof(OSVERSIONINFOEX));
  1563. versionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
  1564. if( !GetVersionEx((LPOSVERSIONINFO)(&versionInfoEx)) )
  1565. {
  1566. dwRetCode = GetLastError();
  1567. _snwprintf(g_TempString, MAX_STRING - 1,
  1568. L"Error: Running NT4, can't query SP version: %s\n",
  1569. GetErrorString(dwRetCode));
  1570. DisplayMessage(g_TempString);
  1571. }
  1572. if( versionInfoEx.wServicePackMajor < 7 )
  1573. {
  1574. dwRetCode = ERROR_OLD_WIN_VERSION;
  1575. _snwprintf(g_TempString, MAX_STRING - 1,
  1576. L"Error: Running NT4 pre SP7\n");
  1577. DisplayMessage(g_TempString);
  1578. break;
  1579. }
  1580. }
  1581. break;
  1582. case 5:
  1583. break;
  1584. default:
  1585. _snwprintf(g_TempString, MAX_STRING - 1,
  1586. L"Error: Unknown target machine version (%#x).\n",
  1587. status);
  1588. DisplayMessage(g_TempString);
  1589. dwRetCode = ERROR_OLD_WIN_VERSION;
  1590. break;
  1591. }
  1592. return dwRetCode;
  1593. }