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.

872 lines
25 KiB

  1. // *********************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // RmtConnectivity.c
  8. //
  9. // Abstract:
  10. //
  11. // This modules implements remote connectivity functionality for all the
  12. // command line tools.
  13. //
  14. // Author:
  15. //
  16. // Sunil G.V.N. Murali ([email protected]) 13-Nov-2000
  17. //
  18. // Revision History:
  19. //
  20. // Sunil G.V.N. Murali ([email protected]) 13-Sep-2000 : Created It.
  21. //
  22. // *********************************************************************************
  23. #include "pch.h"
  24. #include "cmdline.h"
  25. #include "cmdlineres.h"
  26. //
  27. // constants / defines / enumerations
  28. //
  29. #define STR_INPUT_PASSWORD GetResString( IDS_STR_INPUT_PASSWORD )
  30. #define ERROR_LOCAL_CREDENTIALS GetResString( IDS_ERROR_LOCAL_CREDENTIALS )
  31. // share names
  32. #define SHARE_IPC _T( "IPC$" )
  33. #define SHARE_ADMIN _T( "ADMIN$" )
  34. #define SHARE_CDRIVE _T( "C$" )
  35. #define SHARE_DDRIVE _T( "D$" )
  36. // externs
  37. extern BOOL g_bWinsockLoaded;
  38. // ***************************************************************************
  39. // Routine Description:
  40. // Validates the server name
  41. //
  42. // Arguments:
  43. // [ in ] pszServer : server name
  44. //
  45. // Return Value:
  46. // TRUE if valid, FALSE if not valid
  47. // ***************************************************************************
  48. BOOL IsValidIPAddress( LPCTSTR pszAddress )
  49. {
  50. // local variables
  51. DWORD dw = 0;
  52. LONG lValue = 0;
  53. LPTSTR pszTemp = NULL;
  54. DWORD dwOctets[ 4 ] = { 0, 0, 0, 0 };
  55. __MAX_SIZE_STRING szBuffer = NULL_STRING;
  56. // check the buffer
  57. if ( pszAddress == NULL )
  58. {
  59. SetLastError( DNS_ERROR_INVALID_TYPE );
  60. SaveLastError();
  61. return FALSE;
  62. }
  63. // parse and get the octet values
  64. lstrcpy( szBuffer, pszAddress );
  65. pszTemp = _tcstok( szBuffer, _T( "." ) );
  66. while ( pszTemp != NULL )
  67. {
  68. // check whether the current octet is numeric or not
  69. if ( IsNumeric( pszTemp, 10, FALSE ) == FALSE )
  70. return FALSE;
  71. // get the value of the octet and check the range
  72. lValue = AsLong( pszTemp, 10 );
  73. if ( lValue < 0 || lValue >= 255 )
  74. return FALSE;
  75. // fetch next octet
  76. dwOctets[ dw++ ] = lValue;
  77. pszTemp = _tcstok( NULL, _T( "." ) );
  78. }
  79. // check and return
  80. if ( dw != 4 )
  81. {
  82. SetLastError( DNS_ERROR_INVALID_TYPE );
  83. SaveLastError();
  84. return FALSE;
  85. }
  86. // now check the special condition
  87. // ?? time being this is not implemented ??
  88. // return the validity of the ip address
  89. return TRUE;
  90. }
  91. // ***************************************************************************
  92. // Routine Description:
  93. // Validates the server name
  94. //
  95. // Arguments:
  96. // [ in ] pszServer : server name
  97. //
  98. // Return Value:
  99. // TRUE if valid, FALSE if not valid
  100. // ***************************************************************************
  101. BOOL IsValidServer( LPCTSTR pszServer )
  102. {
  103. // local variables
  104. LONG lIndex = 0;
  105. LPTSTR pszTemp = NULL;
  106. LPCTSTR pszComputerName = NULL;
  107. TCHAR pszInvalidChars[] = _T( " \\/[]:|<>+=;,?$#()!@^\"`{}*%" );
  108. // check for NULL ... if NULL return
  109. if ( pszServer == NULL )
  110. return TRUE;
  111. // check the length of the string
  112. if ( lstrlen( pszServer ) == 0 )
  113. return TRUE;
  114. // check whether this is a valid ip address or not
  115. if ( IsValidIPAddress( pszServer ) == TRUE )
  116. return TRUE; // it's valid ip address ... so is valid server name
  117. // now check the server name for invalid characters
  118. // \/[]:|<>+=;,?$#()!@^"`{}*%
  119. pszTemp = __calloc( lstrlen( pszServer ) + 5, sizeof( TCHAR ) );
  120. if ( pszTemp == NULL )
  121. {
  122. SetLastError( E_OUTOFMEMORY );
  123. SaveLastError();
  124. return FALSE;
  125. }
  126. // copy the contents into the internal buffer and check for the invalid characters
  127. lstrcpy( pszTemp, pszServer );
  128. for( lIndex = 0; lIndex < lstrlen( pszInvalidChars ); lIndex++ )
  129. {
  130. if ( _tcschr( pszTemp, pszInvalidChars[ lIndex ] ) != NULL )
  131. {
  132. SetLastError( ERROR_BAD_NETPATH );
  133. SaveLastError();
  134. __free( pszTemp );
  135. return FALSE;
  136. }
  137. }
  138. // copy the server name again ... and check if the computer name by any chance is a number
  139. lstrcpy( pszTemp, pszServer );
  140. pszComputerName = _tcstok( pszTemp, _T( "." ) );
  141. if ( pszComputerName == NULL )
  142. pszComputerName = pszServer;
  143. // check for the numeric system name ..
  144. if ( pszComputerName[ 0 ] != _T('-') && IsNumeric(pszComputerName, 10, FALSE) == TRUE )
  145. {
  146. SetLastError( ERROR_INVALID_COMPUTERNAME );
  147. SaveLastError();
  148. __free( pszTemp );
  149. return FALSE;
  150. }
  151. // valid server name
  152. __free( pszTemp );
  153. return TRUE;
  154. }
  155. // ***************************************************************************
  156. // Routine Description:
  157. // Get HostName from ipaddress.
  158. //
  159. // Arguments:
  160. //
  161. // Return Value:
  162. //
  163. // ***************************************************************************
  164. BOOL GetHostByIPAddr( LPCTSTR pszServer, LPTSTR pszHostName, BOOL bNeedFQDN )
  165. {
  166. // local variables
  167. WSADATA wsaData;
  168. DWORD dwErr = 0;
  169. DWORD dwLength = 0;
  170. ULONG ulInetAddr = 0;
  171. HOSTENT* pHostEnt = NULL;
  172. BOOL bReturnValue = FALSE;
  173. LPSTR pszTemp = NULL;
  174. WORD wVersionRequested = 0;
  175. // check whether winsock module is loaded into process memory or not
  176. // if not load it now
  177. if ( g_bWinsockLoaded == FALSE )
  178. {
  179. // initiate the use of Ws2_32.dll by a process ( VERSION: 2.2 )
  180. wVersionRequested = MAKEWORD( 2, 2 );
  181. dwErr = WSAStartup( wVersionRequested, &wsaData );
  182. if ( dwErr != 0 )
  183. {
  184. SetLastError( WSAGetLastError() );
  185. __free( pszTemp );
  186. return FALSE;
  187. }
  188. // remember that winsock library is loaded
  189. g_bWinsockLoaded = TRUE;
  190. }
  191. // allocate the a buffer to store the server name in multibyte format
  192. dwLength = lstrlen( pszServer );
  193. pszTemp = ( LPSTR ) __calloc( dwLength + 5, sizeof( CHAR ) );
  194. if ( pszTemp == NULL )
  195. {
  196. SetLastError( E_OUTOFMEMORY );
  197. SaveLastError();
  198. return FALSE;
  199. }
  200. // convert the server name into multibyte string. this is because curren winsock implementation
  201. // works only with multibyte string and there is no support for unicode
  202. GetAsMultiByteString( pszServer, pszTemp, dwLength );
  203. // inet_addr function converts a string containing an Internet Protocol (Ipv4)
  204. // dotted address into a proper address for the IN_ADDR structure.
  205. ulInetAddr = inet_addr( pszTemp );
  206. if ( ulInetAddr == INADDR_NONE )
  207. {
  208. __free( pszTemp );
  209. SetLastError( STG_E_UNKNOWN );
  210. SaveLastError();
  211. return FALSE;
  212. }
  213. // gethostbyaddr function retrieves the host information corresponding to a network address.
  214. pHostEnt = gethostbyaddr( (LPSTR) &ulInetAddr, sizeof( ulInetAddr ), PF_INET );
  215. if ( pHostEnt == NULL )
  216. {
  217. // ?? DONT KNOW WHAT TO DO IF THIS FUNCTION FAILS ??
  218. // ?? CURRENTLY SIMPLY RETURNS FALSE ??
  219. return FALSE;
  220. }
  221. // release the memory allocated so far
  222. __free( pszTemp );
  223. // check whether user wants the FQDN name or NetBIOS name
  224. // if NetBIOS name is required, then remove the domain name
  225. pszTemp = pHostEnt->h_name;
  226. if ( bNeedFQDN == FALSE )
  227. pszTemp = strtok( pHostEnt->h_name, "." );
  228. // we got info in char type ... convert it into current build's compatible type
  229. GetCompatibleStringFromMultiByte( pszTemp, pszHostName, MAX_COMPUTERNAME_LENGTH );
  230. // return
  231. return TRUE;
  232. }
  233. // ***************************************************************************
  234. // Routine Description:
  235. // Connects to the remote Server. This is stub function.
  236. //
  237. // Arguments:
  238. // [ in ] pszServer : server name
  239. // [ in ] pszUser : user
  240. // [ in ] pszPassword : password
  241. //
  242. // Return Value:
  243. // NO_ERROR if succeeds other appropriate error code if failed
  244. //
  245. // ***************************************************************************
  246. DWORD ConnectServer( LPCTSTR pszServer, LPCTSTR pszUser, LPCTSTR pszPassword )
  247. {
  248. // invoke the original function and return the result
  249. return ConnectServer2( pszServer, pszUser, pszPassword, _T( "IPC$" ) );
  250. }
  251. // ***************************************************************************
  252. // Routine Description:
  253. // Connects to the remote Server
  254. //
  255. // Arguments:
  256. // [ in ] pszServer : server name
  257. // [ in ] pszUser : user
  258. // [ in ] pszPassword : password
  259. // [ in ] pszShare : share name to connect to
  260. //
  261. // Return Value:
  262. // NO_ERROR if succeeds other appropriate error code if failed
  263. //
  264. // ***************************************************************************
  265. DWORD ConnectServer2( LPCTSTR pszServer, LPCTSTR pszUser,
  266. LPCTSTR pszPassword, LPCTSTR pszShare )
  267. {
  268. // local variables
  269. DWORD dwSize = 0;
  270. DWORD dwConnect = 0;
  271. NETRESOURCE resource;
  272. __MAX_SIZE_STRING szUNCPath = NULL_STRING;
  273. __MAX_SIZE_STRING szMachine = NULL_STRING;
  274. // if the server name refers to the local system,
  275. // and also, if user credentials were not supplied, then treat
  276. // connection is successfull
  277. // if user credentials information is passed for local system,
  278. // return ERROR_LOCAL_CREDENTIALS
  279. if ( IsLocalSystem( pszServer ) == TRUE )
  280. {
  281. if ( pszUser == NULL || lstrlen( pszUser ) == 0 )
  282. return NO_ERROR; // local sustem
  283. else
  284. {
  285. SetLastError( E_LOCAL_CREDENTIALS );
  286. SetReason( ERROR_LOCAL_CREDENTIALS );
  287. return E_LOCAL_CREDENTIALS;
  288. }
  289. }
  290. // check whether the server name is in UNC format or not
  291. // if yes, extract the server name
  292. lstrcpy( szMachine, pszServer ); // assume server is not in UNC format
  293. if ( IsUNCFormat( pszServer ) == TRUE )
  294. lstrcpy( szMachine, pszServer + 2 );
  295. // validate the server name
  296. if ( IsValidServer( szMachine ) == FALSE )
  297. return GetLastError();
  298. //
  299. // prepare the machine name into UNC format
  300. lstrcpy( szUNCPath, NULL_STRING );
  301. if ( pszShare == NULL || lstrlen( pszShare ) == 0 )
  302. {
  303. FORMAT_STRING( szUNCPath, _T( "\\\\%s" ), szMachine );
  304. }
  305. else
  306. {
  307. FORMAT_STRING2( szUNCPath, _T( "\\\\%s\\%s" ), szMachine, pszShare );
  308. }
  309. // initialize the resource structure with null
  310. ZeroMemory( &resource, sizeof( resource ) );
  311. resource.dwType = RESOURCETYPE_ANY;
  312. resource.lpProvider = NULL;
  313. resource.lpLocalName = NULL;
  314. resource.lpRemoteName = szUNCPath;
  315. // try establishing connection to the remote server
  316. dwConnect = WNetAddConnection2( &resource, pszPassword, pszUser, 0 );
  317. // check the result
  318. // and if error has occured, get the appropriate message
  319. switch( dwConnect )
  320. {
  321. case NO_ERROR:
  322. {
  323. dwConnect = 0;
  324. SetReason( NULL_STRING ); // clear the error message
  325. // check for the OS compatibilty
  326. if ( IsCompatibleOperatingSystem( GetTargetVersion( szMachine ) ) == FALSE )
  327. {
  328. // since the connection already established close the connection
  329. CloseConnection( szMachine );
  330. // set the error text
  331. SetReason( ERROR_OS_INCOMPATIBLE );
  332. dwConnect = ERROR_EXTENDED_ERROR;
  333. }
  334. // ...
  335. break;
  336. }
  337. case ERROR_EXTENDED_ERROR:
  338. WNetSaveLastError(); // save the extended error
  339. break;
  340. default:
  341. // set the last error
  342. SaveLastError();
  343. break;
  344. }
  345. // return the result of the connection establishment
  346. return dwConnect;
  347. }
  348. // ***************************************************************************
  349. // Routine Description:
  350. //
  351. // Closes the remote connection.
  352. //
  353. // Arguments:
  354. // [in] szServer --remote machine to close the connection
  355. //
  356. // Return Value:
  357. //
  358. // DWORD --NO_ERROR if succeeds.
  359. // --Possible error codes.
  360. //
  361. // ***************************************************************************
  362. DWORD CloseConnection( LPCTSTR szServer )
  363. {
  364. // forcibly close the connection
  365. return CloseConnection2( szServer, NULL, CI_CLOSE_BY_FORCE | CI_SHARE_IPC );
  366. }
  367. // ***************************************************************************
  368. // Routine Description:
  369. // Closes the established connection on the remote system.
  370. //
  371. // Arguments:
  372. // [ in ] szServer - Null terminated string that specifies the remote
  373. // system name. NULL specifie the local system.
  374. //
  375. // Return Value:
  376. //
  377. // ***************************************************************************
  378. DWORD CloseConnection2( LPCTSTR szServer, LPCTSTR pszShare, DWORD dwFlags )
  379. {
  380. // local variables
  381. BOOL bForce = FALSE;
  382. DWORD dwCancel = 0;
  383. __STRING_256 szMachine = NULL_STRING;
  384. __STRING_256 szUNCServer = NULL_STRING;
  385. // check the server contents ... it might be referring to the local system
  386. if ( szServer == NULL || lstrlen( szServer ) == 0 )
  387. return NO_ERROR;
  388. // check whether the server name is in UNC format or not
  389. // if yes, extract the server name
  390. lstrcpy( szMachine, szServer ); // assume server is not in UNC format
  391. if ( IsUNCFormat( szServer ) == TRUE )
  392. lstrcpy( szMachine, szServer + 2 );
  393. // determine if share name has to appended or not for this server name
  394. if ( dwFlags & CI_SHARE_IPC )
  395. {
  396. // --> \\server\ipc$
  397. FORMAT_STRING2( szUNCServer, _T( "\\\\%s\\%s" ), szMachine, SHARE_IPC );
  398. }
  399. else if ( dwFlags & CI_SHARE_ADMIN )
  400. {
  401. // --> \\server\admin$
  402. FORMAT_STRING2( szUNCServer, _T( "\\\\%s\\%s" ), szMachine, SHARE_ADMIN );
  403. }
  404. else if ( dwFlags & CI_SHARE_CDRIVE )
  405. {
  406. // --> \\server\c$
  407. FORMAT_STRING2( szUNCServer, _T( "\\\\%s\\%s" ), szMachine, SHARE_CDRIVE );
  408. }
  409. else if ( dwFlags & CI_SHARE_DDRIVE )
  410. {
  411. // --> \\server\d$
  412. FORMAT_STRING2( szUNCServer, _T( "\\\\%s\\%s" ), szMachine, SHARE_DDRIVE );
  413. }
  414. else if ( dwFlags & CI_SHARE_CUSTOM && pszShare != NULL )
  415. {
  416. // --> \\server\share
  417. FORMAT_STRING2( szUNCServer, _T( "\\\\%s\\%s" ), szMachine, pszShare );
  418. }
  419. else
  420. {
  421. // --> \\server
  422. FORMAT_STRING( szUNCServer, _T( "\\\\%s" ), szMachine );
  423. }
  424. // determine whether to close this connection forcibly or not
  425. if ( dwFlags & CI_CLOSE_BY_FORCE )
  426. bForce = TRUE;
  427. //
  428. // cancel the connection
  429. dwCancel = WNetCancelConnection2( szUNCServer, 0, bForce );
  430. // check the result
  431. // and if error has occured, get the appropriate message
  432. switch( dwCancel )
  433. {
  434. case NO_ERROR:
  435. dwCancel = 0;
  436. SetReason( NULL_STRING ); // clear the error message
  437. break;
  438. case ERROR_EXTENDED_ERROR:
  439. WNetSaveLastError(); // save the extended error
  440. break;
  441. default:
  442. // set the last error
  443. SaveLastError();
  444. break;
  445. }
  446. // return the result of the cancelling the connection
  447. return dwCancel;
  448. }
  449. // ***************************************************************************
  450. // Routine Description:
  451. // Determines whether server name is specified in UNC format or not
  452. //
  453. // Arguments:
  454. // [ in ] pszServer : server name
  455. //
  456. // Return Value:
  457. // TRUE : if specified in UNC format
  458. // FALSE : if not specified in UNC format
  459. //
  460. // ***************************************************************************
  461. BOOL IsUNCFormat( LPCTSTR pszServer )
  462. {
  463. return ( StringCompare( pszServer, _T( "\\\\" ), TRUE, 2 ) == 0 );
  464. }
  465. // ***************************************************************************
  466. // Routine Description:
  467. // Determines whether server is referring to the local or remote system
  468. //
  469. // Arguments:
  470. // [ in ] pszServer : server name
  471. //
  472. // Return Value:
  473. // TRUE : for local system
  474. // FALSE : for remote system
  475. //
  476. // ***************************************************************************
  477. BOOL IsLocalSystem( LPCTSTR pszServer )
  478. {
  479. // local variables
  480. DWORD dwSize = 0;
  481. __STRING_128 szTemp = NULL_STRING;
  482. __STRING_128 szHostName = NULL_STRING;
  483. // if the server name is empty, it is a local system
  484. if ( pszServer == NULL || lstrlen( pszServer ) == 0 )
  485. return TRUE;
  486. // get the local system name and check
  487. dwSize = SIZE_OF_ARRAY( szTemp );
  488. GetComputerNameEx( ComputerNamePhysicalNetBIOS, szTemp, &dwSize );
  489. if ( StringCompare( szTemp, pszServer, TRUE, 0 ) == 0 )
  490. return TRUE;
  491. //Check pszSever having IP address
  492. if( IsValidIPAddress( pszServer ) == TRUE )
  493. {
  494. // resolve the ipaddress to host name
  495. if( GetHostByIPAddr( pszServer, szHostName, FALSE ) == FALSE )
  496. return FALSE;
  497. // check if resolved ipaddress matches with the current host name
  498. if ( StringCompare( szTemp, szHostName, TRUE, 0 ) == 0 )
  499. return TRUE; // local system
  500. else
  501. return FALSE; // not a local system
  502. }
  503. // get the local system fully qualified name and check
  504. dwSize = SIZE_OF_ARRAY( szTemp );
  505. GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified, szTemp, &dwSize );
  506. if ( StringCompare( szTemp, pszServer, TRUE, 0 ) == 0 )
  507. return TRUE;
  508. // finally ... it might not be local system name
  509. // NOTE: there are chances for us to not be able to identify whether
  510. // the system name specified is a local system or remote system
  511. return FALSE;
  512. }
  513. // ***************************************************************************
  514. // Routine Description:
  515. //
  516. // Establishes a connection to the remote system.
  517. //
  518. // Arguments:
  519. //
  520. // [in] szServer --Nullterminated string to establish the conection.
  521. // --NULL connects to the local system.
  522. // [in] szUserName --Null terminated string that specifies the user name.
  523. // --NULL takes the default user name.
  524. // [in] dwUserLength --Length of the username.
  525. // [in] szPassword --Null terminated string that specifies the password
  526. // --NULL takes the default user name's password.
  527. // [in] dwPasswordLength --Length of the password.
  528. // [in] bNeedPassword --True if password is required to establish the connection.
  529. // --False if it is not required.
  530. //
  531. // Return Value:
  532. //
  533. // BOOL --True if it establishes
  534. // --False if it fails.
  535. //
  536. // ***************************************************************************
  537. BOOL EstablishConnection( LPCTSTR szServer, LPTSTR szUserName, DWORD dwUserLength,
  538. LPTSTR szPassword, DWORD dwPasswordLength, BOOL bNeedPassword )
  539. {
  540. // local variables
  541. DWORD dwSize = 0;
  542. BOOL bDefault = FALSE;
  543. DWORD dwConnectResult = 0;
  544. __MAX_SIZE_STRING szBuffer = NULL_STRING;
  545. // clear the error .. if any
  546. SetLastError( NO_ERROR );
  547. // sometime users want the utility to prompt for the password
  548. // check what user wants the utility to do
  549. if ( bNeedPassword == TRUE && szPassword != NULL && lstrcmp( szPassword, _T( "*" ) ) == 0 )
  550. {
  551. // user wants the utility to prompt for the password
  552. // so skip this part and let the flow directly jump the password acceptance part
  553. }
  554. else
  555. {
  556. // try to establish connection to the remote system with the credentials supplied
  557. bDefault = FALSE;
  558. if ( lstrlen( szUserName ) == 0 )
  559. {
  560. // user name is empty
  561. // so, it is obvious that password will also be empty
  562. // even if password is specified, we have to ignore that
  563. bDefault = TRUE;
  564. dwConnectResult = ConnectServer( szServer, NULL, NULL );
  565. }
  566. else
  567. {
  568. // credentials were supplied
  569. // but password might not be specified ... so check and act accordingly
  570. dwConnectResult = ConnectServer( szServer,
  571. szUserName, ( bNeedPassword == FALSE ? szPassword : NULL ) );
  572. // determine whether to close the connection or retain the connection
  573. if ( bNeedPassword == FALSE )
  574. {
  575. // connection might have already established .. so to be on safer side
  576. // we inform the caller not to close the connection
  577. bDefault = TRUE;
  578. }
  579. }
  580. // check the result ... if successful in establishing connection ... return
  581. if ( dwConnectResult == NO_ERROR )
  582. {
  583. // if connected with default params, pass additional information to the caller
  584. if ( bDefault == TRUE )
  585. SetLastError( I_NO_CLOSE_CONNECTION );
  586. return TRUE;
  587. }
  588. // now check the kind of error occurred
  589. switch( dwConnectResult )
  590. {
  591. case ERROR_LOGON_FAILURE:
  592. case ERROR_INVALID_PASSWORD:
  593. break;
  594. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  595. // user credentials conflict ... client has to handle this situation
  596. // wrt to this module, connection to the remote system is success
  597. SetLastError( dwConnectResult );
  598. return TRUE;
  599. case E_LOCAL_CREDENTIALS:
  600. // user credentials not accepted for local system
  601. SetLastError( E_LOCAL_CREDENTIALS );
  602. SetReason( ERROR_LOCAL_CREDENTIALS );
  603. return TRUE;
  604. case ERROR_DUP_NAME:
  605. case ERROR_NETWORK_UNREACHABLE:
  606. case ERROR_HOST_UNREACHABLE:
  607. case ERROR_PROTOCOL_UNREACHABLE:
  608. case ERROR_INVALID_NETNAME:
  609. // change the error code so that user gets correct message
  610. SetLastError( ERROR_NO_NETWORK );
  611. SaveLastError();
  612. SetLastError( dwConnectResult ); // reset the error code
  613. return FALSE;
  614. default:
  615. return FALSE; // no use of accepting the password .. return failure
  616. break;
  617. }
  618. // if failed in establishing connection to the remote terminal
  619. // even if the password is specifed, then there is nothing to do ... simply return failure
  620. if ( bNeedPassword == FALSE )
  621. return FALSE;
  622. }
  623. // check whether user name is specified or not
  624. // if not, get the local system's current user name under whose credentials, the process
  625. // is running
  626. if ( lstrlen( szUserName ) == 0 )
  627. {
  628. // get the user name
  629. if ( GetUserNameEx( NameSamCompatible, szUserName, &dwUserLength ) == FALSE )
  630. {
  631. // error occured while trying to get the current user info
  632. SaveLastError();
  633. return FALSE;
  634. }
  635. }
  636. // format the user name
  637. // if ( _tcschr( szUserName, _T( '\\' ) ) == NULL )
  638. // {
  639. // // server not present in user name ... prepare ... this is only for display purpose
  640. // FORMAT_STRING2( szBuffer, _T( "%s\\%s" ), szServer, szUserName );
  641. // lstrcpy( szUserName, szBuffer );
  642. // }
  643. // accept the password from the user
  644. FORMAT_STRING( szBuffer, STR_INPUT_PASSWORD, szUserName );
  645. WriteConsole( GetStdHandle( STD_ERROR_HANDLE ),
  646. szBuffer, lstrlen( szBuffer ), &dwSize, NULL );
  647. GetPassword( szPassword, MAX_PASSWORD_LENGTH );
  648. // now again try to establish the connection using the currently
  649. // supplied credentials
  650. dwConnectResult = ConnectServer( szServer, szUserName, szPassword );
  651. if ( dwConnectResult == NO_ERROR )
  652. return TRUE; // connection established successfully
  653. // now check the kind of error occurred
  654. switch( dwConnectResult )
  655. {
  656. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  657. // user credentials conflict ... client has to handle this situation
  658. // wrt to this module, connection to the remote system is success
  659. SetLastError( dwConnectResult );
  660. return TRUE;
  661. case E_LOCAL_CREDENTIALS:
  662. // user credentials not accepted for local system
  663. SetLastError( E_LOCAL_CREDENTIALS );
  664. SetReason( ERROR_LOCAL_CREDENTIALS );
  665. return TRUE;
  666. case ERROR_DUP_NAME:
  667. case ERROR_NETWORK_UNREACHABLE:
  668. case ERROR_HOST_UNREACHABLE:
  669. case ERROR_PROTOCOL_UNREACHABLE:
  670. case ERROR_INVALID_NETNAME:
  671. // change the error code so that user gets correct message
  672. SetLastError( ERROR_NO_NETWORK );
  673. SaveLastError();
  674. SetLastError( dwConnectResult ); // reset the error code
  675. return FALSE;
  676. }
  677. // return the failure
  678. return FALSE;
  679. }
  680. // ***************************************************************************
  681. // Routine Description:
  682. // Establishes a connection to the remote system.
  683. //
  684. // Arguments:
  685. //
  686. // Return Value:
  687. //
  688. // ***************************************************************************
  689. BOOL EstablishConnection2( PTCONNECTIONINFO pci )
  690. {
  691. // local variables
  692. LPCTSTR pszShare = NULL;
  693. // clear the error .. if any
  694. SetLastError( NO_ERROR );
  695. // identify the share to which user wishes to connect to
  696. if ( pci->dwFlags & CI_SHARE_IPC )
  697. pszShare = SHARE_IPC;
  698. else if ( pci->dwFlags & CI_SHARE_ADMIN )
  699. pszShare = SHARE_ADMIN;
  700. else if ( pci->dwFlags & CI_SHARE_CDRIVE )
  701. pszShare = SHARE_CDRIVE;
  702. else if ( pci->dwFlags & CI_SHARE_DDRIVE )
  703. pszShare = SHARE_DDRIVE;
  704. return TRUE;
  705. }
  706. // ***************************************************************************
  707. // Routine Description:
  708. //
  709. // Arguments:
  710. //
  711. // Return Value:
  712. //
  713. // ***************************************************************************
  714. DWORD GetTargetVersion( LPCTSTR pszServer )
  715. {
  716. // local variables
  717. DWORD dwVersion = 0;
  718. LPTSTR pszUNCPath = NULL;
  719. NET_API_STATUS netstatus;
  720. SERVER_INFO_101* pSrvInfo = NULL;
  721. // check the inputs
  722. if ( pszServer == NULL )
  723. return 0;
  724. // allocate memory for having server in UNC format
  725. pszUNCPath = (LPTSTR) __calloc( lstrlen( pszServer ) + 5, sizeof( TCHAR ) );
  726. if ( pszUNCPath == NULL )
  727. {
  728. SetLastError( E_OUTOFMEMORY );
  729. SaveLastError();
  730. return 0;
  731. }
  732. // prepare the server name in UNC format
  733. lstrcpy( pszUNCPath, pszServer );
  734. if ( lstrlen( pszServer ) != 0 && IsUNCFormat( pszServer ) == FALSE )
  735. {
  736. FORMAT_STRING( pszUNCPath, _T( "\\\\%s" ), pszServer );
  737. }
  738. // get the version info
  739. netstatus = NetServerGetInfo( pszUNCPath, 101, (LPBYTE*) &pSrvInfo );
  740. // release the memory
  741. __free( pszUNCPath );
  742. // check the result .. if not success return
  743. if ( netstatus != NERR_Success )
  744. return 0;
  745. // prepare the version
  746. dwVersion = 0;
  747. if ( ( pSrvInfo->sv101_type & SV_TYPE_NT ) )
  748. {
  749. // --> "sv101_version_major" least significant 4 bits of the byte,
  750. // the major release version number of the operating system.
  751. // --> "sv101_version_minor" the minor release version number of the operating system
  752. dwVersion = (pSrvInfo->sv101_version_major & MAJOR_VERSION_MASK) * 1000;
  753. dwVersion += pSrvInfo->sv101_version_minor;
  754. }
  755. // release the buffer allocated by network api
  756. NetApiBufferFree( pSrvInfo );
  757. // return
  758. return dwVersion;
  759. }
  760. // ***************************************************************************
  761. // Routine Description:
  762. //
  763. // Arguments:
  764. //
  765. // Return Value:
  766. //
  767. // ***************************************************************************
  768. BOOL IsCompatibleOperatingSystem( DWORD dwVersion )
  769. {
  770. // OS version above windows 2000 is compatible
  771. return (dwVersion >= 5000);
  772. }