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.

893 lines
23 KiB

  1. #include <common.h>
  2. //
  3. // from autlogon.c
  4. //
  5. extern BOOL g_QuietMode;
  6. extern WCHAR g_TempString[];
  7. extern WCHAR g_ErrorString[];
  8. extern WCHAR g_FailureLocation[];
  9. #ifdef PRIVATE_VERSION
  10. extern BOOL g_RemoteOperation;
  11. extern WCHAR g_RemoteComputerName[];
  12. #endif
  13. //+----------------------------------------------------------------------------
  14. //
  15. // Wow64 stuff
  16. //
  17. //+----------------------------------------------------------------------------
  18. #ifdef _X86_
  19. typedef BOOL (*PFNISWOW64PROCESS)(HANDLE, PBOOL);
  20. #endif
  21. //+----------------------------------------------------------------------------
  22. //
  23. // DisplayMessage
  24. //
  25. //+----------------------------------------------------------------------------
  26. VOID
  27. DisplayMessage(
  28. WCHAR *MessageText)
  29. {
  30. if (!g_QuietMode)
  31. {
  32. wprintf(L"%s", MessageText);
  33. }
  34. }
  35. //+----------------------------------------------------------------------------
  36. //
  37. // GetErrorString
  38. //
  39. //+----------------------------------------------------------------------------
  40. WCHAR*
  41. GetErrorString(
  42. DWORD dwErrorCode)
  43. {
  44. LPVOID lpMsgBuf=NULL;
  45. SecureZeroMemory(g_ErrorString, MAX_STRING * sizeof(WCHAR));
  46. FormatMessage(
  47. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  48. FORMAT_MESSAGE_FROM_SYSTEM |
  49. FORMAT_MESSAGE_IGNORE_INSERTS,
  50. NULL,
  51. dwErrorCode,
  52. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  53. (LPTSTR) &lpMsgBuf,
  54. 0,
  55. NULL);
  56. // Free the bufferoa
  57. if (lpMsgBuf != NULL)
  58. {
  59. wcsncpy(g_ErrorString, lpMsgBuf, MAX_STRING - 1);
  60. LocalFree(lpMsgBuf);
  61. }
  62. return g_ErrorString;
  63. }
  64. DWORD
  65. GetRegValueSZ(
  66. WCHAR *ValueName,
  67. WCHAR *RegValue,
  68. size_t RegValueLength)
  69. {
  70. DWORD dwRetCode = ERROR_SUCCESS;
  71. HKEY hKey=NULL;
  72. DWORD dwMaxValueData = (MAX_STRING * sizeof(WCHAR)); // Longest Value data
  73. HANDLE hHeap=NULL;
  74. BYTE *bData=NULL;
  75. DWORD cbData;
  76. DWORD dwType;
  77. // get a handle to the local or remote computer
  78. // (as specified by our global flag)
  79. dwRetCode = GetRegistryHandle(&hKey, KEY_READ);
  80. if( ERROR_SUCCESS != dwRetCode )
  81. {
  82. goto cleanup;
  83. }
  84. // create a heap
  85. hHeap = HeapCreate(0, 0, 0);
  86. if( NULL == hHeap )
  87. {
  88. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  89. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  90. L"GetRegValueSZ: HeapCreate: %s\n",
  91. GetErrorString(dwRetCode));
  92. goto cleanup;
  93. }
  94. // allocate some space on the heap for our regvalue we'll read in
  95. bData = (BYTE*)HeapAlloc(hHeap, 0, dwMaxValueData);
  96. if (bData == NULL)
  97. {
  98. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  99. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  100. L"GetRegValueSZ: HeapAlloc: %s\n",
  101. GetErrorString(dwRetCode));
  102. goto cleanup;
  103. }
  104. cbData = dwMaxValueData;
  105. // read the regkey using the handle we open above
  106. dwRetCode = RegQueryValueEx(
  107. hKey,
  108. ValueName,
  109. NULL,
  110. &dwType,
  111. bData,
  112. &cbData);
  113. if( ERROR_SUCCESS != dwRetCode )
  114. {
  115. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  116. L"GetRegValueSZ: RegQueryValueEx: %s",
  117. GetErrorString(dwRetCode));
  118. goto cleanup;
  119. }
  120. // if it's not a type reg_sz, then something's wrong, so
  121. // report the error, which will cause us to stop.
  122. if( dwType != REG_SZ )
  123. {
  124. dwRetCode = ERROR_BADKEY;
  125. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  126. L"GetRegValueSZ: RegQueryValueEx: %s: %s\n",
  127. ValueName,
  128. GetErrorString(dwRetCode));
  129. goto cleanup;
  130. }
  131. //
  132. // copy the (0 terminated) buffer to the registry value
  133. // If empty, just 0 the buffer for the caller
  134. //
  135. if( cbData )
  136. {
  137. if( cbData / sizeof(WCHAR) > RegValueLength )
  138. {
  139. *RegValue = 0;
  140. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  141. }
  142. else
  143. {
  144. wcscpy(RegValue, (WCHAR *)bData);
  145. }
  146. }
  147. else
  148. {
  149. *RegValue = 0;
  150. }
  151. cleanup:
  152. if( NULL != bData )
  153. {
  154. SecureZeroMemory(bData, sizeof(bData));
  155. if( NULL != hHeap )
  156. {
  157. HeapFree(hHeap, 0, bData);
  158. HeapDestroy(hHeap);
  159. }
  160. }
  161. if( NULL != hKey )
  162. {
  163. RegCloseKey(hKey);
  164. }
  165. return dwRetCode;
  166. }
  167. DWORD
  168. GetRegValueDWORD(
  169. WCHAR* ValueName,
  170. DWORD* RegValue)
  171. {
  172. DWORD dwRetCode = ERROR_SUCCESS;
  173. HKEY hKey=NULL;
  174. DWORD dwMaxValueData = (MAX_STRING * sizeof(WCHAR)); // Longest Value data
  175. HANDLE hHeap=NULL;
  176. BYTE *bData=NULL;
  177. DWORD cbData;
  178. DWORD dwType;
  179. // get a handle to the local or remote computer
  180. // (as specified by our global flag)
  181. dwRetCode = GetRegistryHandle(&hKey, KEY_READ);
  182. if( ERROR_SUCCESS != dwRetCode )
  183. {
  184. goto cleanup;
  185. }
  186. // create a heap
  187. hHeap = HeapCreate(0, 0, 0);
  188. if( NULL == hHeap )
  189. {
  190. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  191. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  192. L"GetRegValueSZ: HeapCreate: %s\n",
  193. GetErrorString(dwRetCode));
  194. goto cleanup;
  195. }
  196. // allocate some space on the heap for our regvalue we'll read in
  197. bData = (BYTE*)HeapAlloc(hHeap, 0, dwMaxValueData);
  198. if (bData == NULL)
  199. {
  200. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  201. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  202. L"GetRegValueSZ: HeapAlloc: %s\n",
  203. GetErrorString(dwRetCode));
  204. goto cleanup;
  205. }
  206. cbData = dwMaxValueData;
  207. // read the regkey using the handle we open above
  208. dwRetCode = RegQueryValueEx(
  209. hKey,
  210. ValueName,
  211. NULL,
  212. &dwType,
  213. bData,
  214. &cbData);
  215. if( ERROR_SUCCESS != dwRetCode )
  216. {
  217. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  218. L"GetRegValueSZ: RegQueryValueEx: %s",
  219. GetErrorString(dwRetCode));
  220. goto cleanup;
  221. }
  222. // if it's not a type reg_sz, then something's wrong, so
  223. // report the error, which will cause us to stop.
  224. if( dwType != REG_DWORD )
  225. {
  226. dwRetCode = ERROR_BADKEY;
  227. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  228. L"GetRegValueSZ: RegQueryValueEx: %s: %s\n",
  229. ValueName,
  230. GetErrorString(dwRetCode));
  231. goto cleanup;
  232. }
  233. //
  234. // copy the buffer to the registry value
  235. // If empty, just 0 the buffer for the caller
  236. //
  237. *RegValue = *(DWORD*)bData;
  238. cleanup:
  239. if( NULL != bData )
  240. {
  241. SecureZeroMemory(bData, sizeof(bData));
  242. if( NULL != hHeap )
  243. {
  244. HeapFree(hHeap, 0, bData);
  245. HeapDestroy(hHeap);
  246. }
  247. }
  248. if( NULL != hKey )
  249. {
  250. RegCloseKey(hKey);
  251. }
  252. return dwRetCode;
  253. }
  254. DWORD
  255. ClearRegValue(
  256. WCHAR* ValueName)
  257. {
  258. DWORD dwRetCode = ERROR_SUCCESS;
  259. HKEY hKey=NULL;
  260. dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
  261. if( ERROR_SUCCESS != dwRetCode )
  262. {
  263. goto cleanup;
  264. }
  265. dwRetCode = RegDeleteValue(hKey, ValueName);
  266. if( ERROR_SUCCESS != dwRetCode )
  267. {
  268. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  269. L"ClearRegPassword: RegDeleteValue: %s: %s\n",
  270. ValueName,
  271. GetErrorString(dwRetCode));
  272. goto cleanup;
  273. }
  274. cleanup:
  275. if( NULL != hKey)
  276. {
  277. RegCloseKey(hKey);
  278. }
  279. return dwRetCode;
  280. }
  281. DWORD
  282. SetRegValueSZ(
  283. WCHAR *ValueName,
  284. WCHAR *ValueData)
  285. {
  286. DWORD dwRetCode = ERROR_SUCCESS;
  287. HKEY hKey=NULL;
  288. dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
  289. if( ERROR_SUCCESS != dwRetCode )
  290. {
  291. goto cleanup;
  292. }
  293. dwRetCode = RegSetValueEx(
  294. hKey,
  295. ValueName,
  296. 0,
  297. REG_SZ,
  298. (LPSTR) ValueData,
  299. wcslen(ValueData)*sizeof(WCHAR));
  300. if( ERROR_SUCCESS != dwRetCode )
  301. {
  302. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  303. L"SetRegValueSZ: RegSetValueEx: %s: %s\n",
  304. ValueName,
  305. GetErrorString(dwRetCode));
  306. goto cleanup;
  307. }
  308. cleanup:
  309. if( NULL != hKey)
  310. {
  311. RegCloseKey(hKey);
  312. }
  313. return dwRetCode;
  314. }
  315. DWORD
  316. SetRegValueDWORD(
  317. WCHAR *ValueName,
  318. DWORD ValueData)
  319. {
  320. DWORD dwRetCode = ERROR_SUCCESS;
  321. HKEY hKey=NULL;
  322. dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
  323. if( ERROR_SUCCESS != dwRetCode )
  324. {
  325. goto cleanup;
  326. }
  327. dwRetCode = RegSetValueEx(
  328. hKey,
  329. ValueName,
  330. 0,
  331. REG_DWORD,
  332. (const BYTE*) (&ValueData),
  333. sizeof(DWORD));
  334. if( ERROR_SUCCESS != dwRetCode )
  335. {
  336. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  337. L"SetRegValueSZ: RegSetValueEx: %s: %s\n",
  338. ValueName,
  339. GetErrorString(dwRetCode));
  340. goto cleanup;
  341. }
  342. cleanup:
  343. if( NULL != hKey)
  344. {
  345. RegCloseKey(hKey);
  346. }
  347. return dwRetCode;
  348. }
  349. DWORD
  350. GetRegistryHandle(
  351. HKEY *phKey,
  352. REGSAM samDesired)
  353. {
  354. #ifdef PRIVATE_VERSION
  355. HKEY RemoteRegistryHandle = NULL;
  356. #endif
  357. DWORD dwRetCode = ERROR_SUCCESS;
  358. #ifdef _X86_
  359. //
  360. // if we run this tool on a 64bit system, we may need to write to
  361. // the 64bit hive
  362. //
  363. static PFNISWOW64PROCESS pfnIsWow64Process = NULL;
  364. static BOOL fIsWow64Process = FALSE;
  365. if( pfnIsWow64Process == NULL )
  366. {
  367. HINSTANCE hInstDLL = LoadLibrary(L"kernel32.dll");
  368. if( hInstDLL )
  369. {
  370. pfnIsWow64Process =
  371. (PFNISWOW64PROCESS)GetProcAddress(hInstDLL, "IsWow64Process");
  372. if( pfnIsWow64Process )
  373. {
  374. pfnIsWow64Process(GetCurrentProcess(),
  375. &fIsWow64Process);
  376. }
  377. // else we assume we run on a downlevel platform
  378. FreeLibrary(hInstDLL);
  379. }
  380. }
  381. if( fIsWow64Process )
  382. {
  383. samDesired |= KEY_WOW64_64KEY;
  384. }
  385. #endif
  386. //
  387. // If not PRIVATE mode, ignore the access requested passed in and
  388. // request all access, even though we don't need it. This will force the
  389. // caller to need to be admin to use this tool. We don't want someone using
  390. // this tool to view the autologon passwords of all machines across the domain
  391. // as a normal domain user...
  392. //
  393. #ifndef PRIVATE_VERSION
  394. samDesired = KEY_ALL_ACCESS;
  395. #endif
  396. #ifdef PRIVATE_VERSION
  397. //
  398. // If we're connecting against a remote computer
  399. //
  400. if( g_RemoteOperation )
  401. {
  402. // open a handle to the remote registry
  403. dwRetCode = RegConnectRegistry(g_RemoteComputerName,
  404. HKEY_LOCAL_MACHINE,
  405. &RemoteRegistryHandle);
  406. if( ERROR_SUCCESS != dwRetCode )
  407. {
  408. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  409. L"GetRegistryHandle: RegConnectRegistry: %s: %s\n",
  410. g_RemoteComputerName,
  411. GetErrorString(dwRetCode));
  412. goto cleanup;
  413. }
  414. // open the WINLOGON key on the remote machine
  415. dwRetCode = RegOpenKeyEx(RemoteRegistryHandle,
  416. WINLOGON_REGKEY,
  417. 0,
  418. samDesired,
  419. phKey);
  420. if( ERROR_SUCCESS != dwRetCode )
  421. {
  422. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  423. L"GetRegistryHandle: RegOpenKeyEx: %s: %s\n",
  424. g_RemoteComputerName,
  425. GetErrorString(dwRetCode));
  426. goto cleanup;
  427. }
  428. }
  429. else
  430. #endif
  431. {
  432. // open the WINLOGON key on the local machine
  433. dwRetCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  434. WINLOGON_REGKEY,
  435. 0,
  436. samDesired,
  437. phKey);
  438. if( ERROR_SUCCESS != dwRetCode )
  439. {
  440. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  441. L"GetRegistryHandle: RegOpenKeyEx: %s\n",
  442. GetErrorString(dwRetCode));
  443. goto cleanup;
  444. }
  445. }
  446. cleanup:
  447. #ifdef PRIVATE_VERSION
  448. if( NULL != RemoteRegistryHandle )
  449. {
  450. RegCloseKey(RemoteRegistryHandle);
  451. }
  452. #endif
  453. return dwRetCode;
  454. }
  455. //+---------------------------------------------------------------------------------------------------------
  456. //
  457. // LSASecret munging routines
  458. //
  459. //+---------------------------------------------------------------------------------------------------------
  460. DWORD
  461. GetPolicyHandle(LSA_HANDLE *LsaPolicyHandle)
  462. {
  463. LSA_OBJECT_ATTRIBUTES ObjectAttributes;
  464. NTSTATUS ntsResult;
  465. #ifdef PRIVATE_VERSION
  466. LSA_UNICODE_STRING TargetMachine;
  467. USHORT TargetMachineLength;
  468. #endif
  469. DWORD dwRetCode = ERROR_SUCCESS;
  470. // Object attributes are reserved, so initialize to zeroes.
  471. SecureZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
  472. #ifdef PRIVATE_VERSION
  473. if( g_RemoteOperation )
  474. {
  475. //Initialize an LSA_UNICODE_STRING
  476. TargetMachineLength = (USHORT)wcslen(g_RemoteComputerName);
  477. TargetMachine.Buffer = g_RemoteComputerName;
  478. TargetMachine.Length = TargetMachineLength * sizeof(WCHAR);
  479. TargetMachine.MaximumLength = (TargetMachineLength+1) * sizeof(WCHAR);
  480. // Get a handle to the Policy object.
  481. ntsResult = LsaOpenPolicy(
  482. &TargetMachine, //local machine
  483. &ObjectAttributes,
  484. POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
  485. LsaPolicyHandle);
  486. }
  487. else
  488. #endif
  489. {
  490. // Get a handle to the Policy object.
  491. ntsResult = LsaOpenPolicy(
  492. NULL, //local machine
  493. &ObjectAttributes,
  494. POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
  495. LsaPolicyHandle);
  496. }
  497. if( STATUS_SUCCESS != ntsResult )
  498. {
  499. // An error occurred. Display it as a win32 error code.
  500. dwRetCode = LsaNtStatusToWinError(ntsResult);
  501. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  502. L"GetPolicyHandle: LsaOpenPolicy: %s\n",
  503. GetErrorString(dwRetCode));
  504. goto cleanup;
  505. }
  506. cleanup:
  507. return dwRetCode;
  508. }
  509. DWORD
  510. SetSecret(
  511. WCHAR *Secret,
  512. BOOL bClearSecret,
  513. WCHAR* SecretName)
  514. {
  515. DWORD dwRetCode = ERROR_SUCCESS;
  516. NTSTATUS ntsResult;
  517. USHORT SecretNameLength, SecretDataLength;
  518. LSA_HANDLE LsaPolicyHandle=NULL;
  519. LSA_UNICODE_STRING lusSecretName, lusSecretData;
  520. //Initialize an LSA_UNICODE_STRING
  521. SecretNameLength = (USHORT)wcslen(SecretName);
  522. lusSecretName.Buffer = SecretName;
  523. lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
  524. lusSecretName.MaximumLength = (SecretNameLength+1) * sizeof(WCHAR);
  525. dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
  526. if( ERROR_SUCCESS != dwRetCode )
  527. {
  528. goto cleanup;
  529. }
  530. // if bClearSecret is set, then delete the secret
  531. // otherwise set the secret to Secret
  532. if( bClearSecret )
  533. {
  534. ntsResult = LsaStorePrivateData(
  535. LsaPolicyHandle,
  536. &lusSecretName,
  537. NULL);
  538. if( STATUS_SUCCESS != ntsResult ) {
  539. dwRetCode = LsaNtStatusToWinError(ntsResult);
  540. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  541. L"SetSecret: LsaStorePrivateData: %s\n",
  542. GetErrorString(dwRetCode));
  543. goto cleanup;
  544. }
  545. }
  546. else
  547. {
  548. //Initialize the Secret LSA_UNICODE_STRING
  549. SecretDataLength = (USHORT)wcslen(Secret);
  550. lusSecretData.Buffer = Secret;
  551. lusSecretData.Length = SecretDataLength * sizeof(WCHAR);
  552. lusSecretData.MaximumLength = (SecretDataLength+1) * sizeof(WCHAR);
  553. ntsResult = LsaStorePrivateData(
  554. LsaPolicyHandle,
  555. &lusSecretName,
  556. &lusSecretData);
  557. if( STATUS_SUCCESS != ntsResult ) {
  558. dwRetCode = LsaNtStatusToWinError(ntsResult);
  559. goto cleanup;
  560. }
  561. }
  562. cleanup:
  563. if( NULL != LsaPolicyHandle )
  564. {
  565. LsaClose(LsaPolicyHandle);
  566. }
  567. return dwRetCode;
  568. }
  569. DWORD
  570. GetSecret(
  571. WCHAR* Secret,
  572. size_t SecretLength,
  573. WCHAR* SecretName)
  574. {
  575. DWORD dwRetCode = ERROR_SUCCESS;
  576. NTSTATUS ntsResult;
  577. USHORT SecretNameLength;
  578. LSA_HANDLE LsaPolicyHandle=NULL;
  579. LSA_UNICODE_STRING lusSecretName;
  580. LSA_UNICODE_STRING *PrivateData=NULL;
  581. //Initialize an LSA_UNICODE_STRING
  582. SecretNameLength = (USHORT)wcslen(SecretName);
  583. lusSecretName.Buffer = SecretName;
  584. lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
  585. lusSecretName.MaximumLength= (SecretNameLength+1) * sizeof(WCHAR);
  586. dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
  587. if( ERROR_SUCCESS != dwRetCode )
  588. {
  589. goto cleanup;
  590. }
  591. ntsResult = LsaRetrievePrivateData(
  592. LsaPolicyHandle,
  593. &lusSecretName,
  594. &PrivateData);
  595. if( STATUS_SUCCESS != ntsResult )
  596. {
  597. if( STATUS_OBJECT_NAME_NOT_FOUND == ntsResult)
  598. {
  599. dwRetCode = ntsResult;
  600. goto cleanup;
  601. }
  602. else
  603. {
  604. dwRetCode = LsaNtStatusToWinError(ntsResult);
  605. _snwprintf(g_FailureLocation, MAX_STRING - 1,
  606. L"GetSecret: LsaRetrievePrivateData: %s \n",
  607. GetErrorString(dwRetCode));
  608. goto cleanup;
  609. }
  610. }
  611. // copy the (not 0 terminated) buffer data to Secret
  612. if( (PrivateData->Length)/sizeof(WCHAR) < SecretLength )
  613. {
  614. wcsncpy(Secret, PrivateData->Buffer, (PrivateData->Length)/sizeof(WCHAR));
  615. Secret[(PrivateData->Length)/sizeof(WCHAR)] = 0;
  616. }
  617. else
  618. {
  619. Secret[0] = 0;
  620. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  621. }
  622. cleanup:
  623. if( NULL != PrivateData )
  624. {
  625. SecureZeroMemory(PrivateData->Buffer, PrivateData->Length);
  626. LsaFreeMemory(PrivateData);
  627. }
  628. if( NULL != LsaPolicyHandle )
  629. {
  630. LsaClose(LsaPolicyHandle);
  631. }
  632. return dwRetCode;
  633. }
  634. //+----------------------------------------------------------------------------
  635. //
  636. // Other helpers
  637. //
  638. //+----------------------------------------------------------------------------
  639. NET_API_STATUS
  640. GetMajorNTVersion(
  641. DWORD* Version,
  642. WCHAR* Server)
  643. {
  644. SERVER_INFO_101* pInf;
  645. NET_API_STATUS status;
  646. status = NetServerGetInfo(Server, 101, (BYTE**)&pInf);
  647. if(!status)
  648. {
  649. if(pInf->sv101_platform_id == PLATFORM_ID_NT)
  650. {
  651. *Version = pInf->sv101_version_major;
  652. }
  653. else
  654. {
  655. *Version = 0;
  656. }
  657. NetApiBufferFree(pInf);
  658. }
  659. else
  660. {
  661. *Version = 0;
  662. }
  663. return status;
  664. }
  665. //+----------------------------------------------------------------------------
  666. //
  667. // GetConsoleStr - reads a console string and other stuff...
  668. //
  669. // "borrowed" from ds\netapi\netcmd\common\mutil.c
  670. //
  671. //+----------------------------------------------------------------------------
  672. #define CR 0xD
  673. #define LF 0xA
  674. #define BACKSPACE 0x8
  675. DWORD
  676. GetConsoleStr(
  677. WCHAR* buf,
  678. DWORD buflen,
  679. BOOL hide,
  680. WCHAR* message,
  681. PDWORD len
  682. )
  683. {
  684. WCHAR ch;
  685. WCHAR *bufPtr = buf;
  686. DWORD c;
  687. BOOL err;
  688. DWORD mode;
  689. DWORD cchBuffer;
  690. DWORD dwRetCode = ERROR_SUCCESS;
  691. DWORD dwLen = 0;
  692. BOOL hidden = FALSE;
  693. if( hide )
  694. {
  695. //
  696. // Init mode in case GetConsoleMode() fails
  697. //
  698. mode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT |
  699. ENABLE_MOUSE_INPUT;
  700. if( !GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode) )
  701. {
  702. dwRetCode = GetLastError();
  703. goto cleanup;
  704. }
  705. if( !SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  706. (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode) )
  707. {
  708. dwRetCode = GetLastError();
  709. goto cleanup;
  710. }
  711. hidden = TRUE;
  712. }
  713. //
  714. // prints the message
  715. //
  716. if( message )
  717. {
  718. if( !WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
  719. message, wcslen(message),
  720. &cchBuffer, NULL) )
  721. {
  722. dwRetCode = GetLastError();
  723. goto cleanup;
  724. }
  725. }
  726. while (TRUE)
  727. {
  728. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
  729. if (!err || c != 1)
  730. {
  731. ch = 0xffff;
  732. }
  733. if ((ch == CR) || (ch == 0xffff)) /* end of the line */
  734. {
  735. if( (ch == CR) && !hide)
  736. {
  737. //
  738. // LF comes when echo enabled. Ignore it
  739. //
  740. ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
  741. }
  742. break;
  743. }
  744. if (ch == BACKSPACE) /* back up one or two */
  745. {
  746. /*
  747. * IF bufPtr == buf then the next two lines are
  748. * a no op.
  749. */
  750. if (bufPtr != buf)
  751. {
  752. bufPtr--;
  753. dwLen--;
  754. }
  755. }
  756. else
  757. {
  758. *bufPtr = ch;
  759. if (dwLen < buflen)
  760. bufPtr++ ; /* don't overflow buf */
  761. dwLen++; /* always increment len */
  762. }
  763. }
  764. if( hidden )
  765. {
  766. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  767. }
  768. //
  769. // NULL terminate
  770. //
  771. *bufPtr = 0;
  772. if( hide )
  773. {
  774. //
  775. // fake the echo for CR/LF
  776. //
  777. putchar(L'\n');
  778. }
  779. if( dwLen > buflen )
  780. {
  781. dwRetCode = ERROR_INSUFFICIENT_BUFFER;
  782. goto cleanup;
  783. }
  784. //
  785. // set the optional out parameter
  786. //
  787. if( len )
  788. {
  789. *len = dwLen;
  790. }
  791. cleanup:
  792. return dwRetCode;
  793. }