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.

1865 lines
48 KiB

  1. // *********************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // Common.c
  8. //
  9. // Abstract:
  10. //
  11. // This modules implements common functionality for all the command line tools.
  12. //
  13. //
  14. // Author:
  15. //
  16. // Sunil G.V.N. Murali ([email protected]) 01-Sep-2000
  17. //
  18. // Revision History:
  19. //
  20. // Sunil G.V.N. Murali ([email protected]) 01-Sep-2000 : Created It.
  21. //
  22. // *********************************************************************************
  23. #include "pch.h"
  24. #include "cmdlineres.h"
  25. #include "cmdline.h"
  26. #include <limits.h>
  27. //
  28. // global variable(s) that are exposed to the external world
  29. //
  30. #ifdef _MT
  31. // multi-threaded variable ( thread local storage )
  32. _declspec( thread ) static LPTSTR g_pszInfo = NULL;
  33. _declspec( thread ) static LPTSTR g_pszString = NULL;
  34. _declspec( thread ) static LPWSTR g_pwszResourceString = NULL;
  35. _declspec( thread ) static TARRAY g_arrQuotes = NULL;
  36. #else
  37. static LPTSTR g_pszInfo = NULL; // holds the reason for the last failure
  38. static LPTSTR g_pszString = NULL; // used to get the resource table's string
  39. static LPWSTR g_pwszResourceString = NULL; // temporary unicode buffer
  40. static TARRAY g_arrQuotes = NULL;
  41. #endif
  42. // SPECIAL: process level globals
  43. BOOL g_bWinsockLoaded = FALSE;
  44. DWORD g_dwMajorVersion = 5;
  45. DWORD g_dwMinorVersion = 1;
  46. WORD g_wServicePackMajor = 0;
  47. //
  48. // private functions
  49. //
  50. BOOL SetThreadUILanguage0( DWORD dwReserved );
  51. //
  52. // public functions
  53. //
  54. // ***************************************************************************
  55. // Routine Description:
  56. //
  57. // Arguments:
  58. //
  59. // Return Value:
  60. //
  61. // ***************************************************************************
  62. BOOL SetOsVersion( DWORD dwMajor, DWORD dwMinor, WORD wServicePackMajor )
  63. {
  64. // local variables
  65. static BOOL bSet = FALSE;
  66. // we won't support below Windows 2000
  67. if ( dwMajor < 5 )
  68. {
  69. return FALSE;
  70. }
  71. else if ( bSet == TRUE )
  72. {
  73. // version is already set -- version cannot be changed frequently
  74. return FALSE;
  75. }
  76. // rest of information we need not bother
  77. bSet = TRUE;
  78. g_dwMajorVersion = dwMajor;
  79. g_dwMinorVersion = dwMinor;
  80. g_wServicePackMajor = wServicePackMajor;
  81. // return
  82. return TRUE;
  83. }
  84. // ***************************************************************************
  85. // Routine Description:
  86. //
  87. // Arguments:
  88. //
  89. // Return Value:
  90. //
  91. // ***************************************************************************
  92. BOOL IsWin2KOrLater()
  93. {
  94. // local variables
  95. OSVERSIONINFOEX osvi;
  96. DWORDLONG dwlConditionMask = 0;
  97. // Initialize the OSVERSIONINFOEX structure.
  98. ZeroMemory( &osvi, sizeof( OSVERSIONINFOEX ) );
  99. osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
  100. osvi.dwMajorVersion = g_dwMajorVersion;
  101. osvi.dwMinorVersion = g_dwMinorVersion;
  102. osvi.wServicePackMajor = g_wServicePackMajor;
  103. // Initialize the condition mask.
  104. VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
  105. VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
  106. VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
  107. // Perform the test.
  108. return VerifyVersionInfo( &osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask );
  109. }
  110. // ***************************************************************************
  111. // Routine Description:
  112. //
  113. // Saves the last occured windows error.
  114. //
  115. // Arguments:
  116. //
  117. // None.
  118. //
  119. // Return Value:
  120. //
  121. // VOID
  122. //
  123. // ***************************************************************************
  124. VOID SaveLastError()
  125. {
  126. // local variables
  127. DWORD dwErrorCode = 0;
  128. LPVOID lpMsgBuf = NULL; // pointer to handle error message
  129. // get the last error
  130. dwErrorCode = GetLastError();
  131. // Complex scripts cannot be rendered in the console, so we
  132. // force the English (US) resource.
  133. SetThreadUILanguage0( 0 );
  134. // load the system error message from the windows itself
  135. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  136. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  137. NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  138. (LPTSTR) &lpMsgBuf, 0, NULL );
  139. // display error message on console screen ... ERROR place
  140. if ( lpMsgBuf != NULL )
  141. SetReason( ( LPCTSTR ) lpMsgBuf );
  142. // Free the buffer ... using LocalFree is slow, but still, we are using ...
  143. // later on need to replaced with HeapXXX functions
  144. if ( lpMsgBuf != NULL )
  145. LocalFree( lpMsgBuf );
  146. }
  147. // ***************************************************************************
  148. // Routine Description:
  149. //
  150. // Saves the last occured windows network error and returns the error code obtained.
  151. //
  152. // Arguments:
  153. //
  154. // None
  155. //
  156. // Return Value:
  157. //
  158. // DWORD -- error code
  159. //
  160. // ***************************************************************************
  161. DWORD WNetSaveLastError()
  162. {
  163. // local variables
  164. DWORD dwErrorCode = 0;
  165. __MAX_SIZE_STRING szMessage = NULL_STRING; // handle error message
  166. __MAX_SIZE_STRING szProvider = NULL_STRING; // store the provider for error
  167. // load the system error message from the windows itself
  168. WNetGetLastError( &dwErrorCode, szMessage, SIZE_OF_ARRAY( szMessage ),
  169. szProvider, SIZE_OF_ARRAY( szProvider ) );
  170. // save the error
  171. SetReason( szMessage );
  172. // return the error code obtained
  173. return dwErrorCode;
  174. }
  175. // ***************************************************************************
  176. // Routine Description:
  177. //
  178. // writes the last saved error description in the given file.
  179. //
  180. // Arguments:
  181. //
  182. // [in] fp -- file to write the error description.
  183. //
  184. // Return Value:
  185. //
  186. // VOID
  187. //
  188. // ***************************************************************************
  189. VOID ShowLastError( FILE* fp )
  190. {
  191. // local variables
  192. DWORD dwErrorCode = 0;
  193. LPVOID lpMsgBuf = NULL; // pointer to handle error message
  194. // get the last error
  195. dwErrorCode = GetLastError();
  196. // Complex scripts cannot be rendered in the console, so we
  197. // force the English (US) resource.
  198. SetThreadUILanguage0( 0 );
  199. // load the system error message from the windows itself
  200. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
  201. FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
  202. NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  203. (LPTSTR) &lpMsgBuf, 0, NULL );
  204. // buffer might not have allocated
  205. if ( lpMsgBuf == NULL )
  206. return;
  207. // display error message on console screen ... ERROR place
  208. DISPLAY_MESSAGE( fp, ( LPCTSTR ) lpMsgBuf );
  209. // Free the buffer ... using LocalFree is slow, but still, we are using ...
  210. // later on need to replaced with HeapXXX functions
  211. LocalFree( lpMsgBuf );
  212. }
  213. // ***************************************************************************
  214. // Routine Description:
  215. //
  216. // writes the last saved nerwork error description in the given file.
  217. //
  218. // Arguments:
  219. //
  220. // [in] fp --fle to write the error description.
  221. //
  222. // Return Value:
  223. //
  224. // DWORD --error code
  225. //
  226. // ***************************************************************************
  227. DWORD WNetShowLastError( FILE* fp )
  228. {
  229. // local variables
  230. DWORD dwErrorCode = 0;
  231. __MAX_SIZE_STRING szMessage = NULL_STRING; // handle error message
  232. __MAX_SIZE_STRING szProvider = NULL_STRING; // store the provider for error
  233. // load the system error message from the windows itself
  234. WNetGetLastError( &dwErrorCode, szMessage, SIZE_OF_ARRAY( szMessage ),
  235. szProvider, SIZE_OF_ARRAY( szProvider ) );
  236. // display error message on console screen ... ERROR place
  237. DISPLAY_MESSAGE( fp, szMessage );
  238. // return the error code obtained
  239. return dwErrorCode;
  240. }
  241. // ***************************************************************************
  242. // Routine Description:
  243. //
  244. // Releases all the global values that are used.
  245. //
  246. // Arguments:
  247. //
  248. // None.
  249. //
  250. // Return Value:
  251. //
  252. // VOID
  253. //
  254. // ***************************************************************************
  255. LONG StringLengthInBytes( LPCTSTR pszText )
  256. {
  257. // local variables
  258. LONG lLength = 0;
  259. #ifdef UNICODE
  260. // get the length of the string in bytes
  261. // since this function includes the count for null character also, ignore that information
  262. lLength = WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pszText, -1, NULL, 0, NULL, NULL ) - 1;
  263. #else
  264. lLength = lstrlen( pszText );
  265. #endif
  266. // return the length information
  267. return lLength;
  268. }
  269. // ***************************************************************************
  270. // Routine Description:
  271. //
  272. // Converts the Unicode string to ansi string.
  273. //
  274. // Arguments:
  275. //
  276. // [in] pszSource --Unicode string to be converted,
  277. // [out] pszDestination --Converted String
  278. // [in] dwLength --Length of the string
  279. //
  280. // Return Value:
  281. //
  282. // LPSTR --Converted string
  283. //
  284. // ***************************************************************************
  285. LPSTR GetAsMultiByteString( LPCTSTR pszSource, LPSTR pszDestination, DWORD dwLength )
  286. {
  287. // check the input values
  288. if ( pszSource == NULL || pszDestination == NULL )
  289. {
  290. SetLastError( ERROR_INVALID_PARAMETER );
  291. SaveLastError();
  292. return "";
  293. }
  294. // initialize the values with zeros
  295. // NOTE:- WideCharToMultiByte wont null terminate its result so
  296. // if its not initialized to nulls, you'll get junk after
  297. // the converted string and will result in crashes
  298. ZeroMemory( pszDestination, dwLength * sizeof( char ) );
  299. #ifdef UNICODE
  300. // convert string from UNICODE version to ANSI version
  301. WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pszSource, -1,
  302. pszDestination, dwLength, NULL, NULL );
  303. #else
  304. // just do the copy
  305. lstrcpyn( pszDestination, pszSource, dwLength );
  306. #endif
  307. // return the destination as return value
  308. return pszDestination;
  309. }
  310. // ***************************************************************************
  311. // Routine Description:
  312. //
  313. // Convertes a wide charecter string to Ansi string.
  314. //
  315. // Arguments:
  316. //
  317. // [in] pwszSource --Wide charecter string to convert.
  318. // [out] pszDestination, --Translated String
  319. // [in] dwLength --Size of the String
  320. //
  321. // Return Value:
  322. //
  323. // LPSTR --Translated String.
  324. //
  325. // ***************************************************************************
  326. LPSTR GetAsMultiByteStringEx( LPCWSTR pwszSource, LPSTR pszDestination, DWORD dwLength )
  327. {
  328. // check the input values
  329. if ( pwszSource == NULL || pszDestination == NULL )
  330. {
  331. SetLastError( ERROR_INVALID_PARAMETER );
  332. SaveLastError();
  333. return "";
  334. }
  335. // initialize the values with zeros
  336. // NOTE:- WideCharToMultiByte wont null terminate its result so
  337. // if its not initialized to nulls, you'll get junk after
  338. // the converted string and will result in crashes
  339. ZeroMemory( pszDestination, dwLength * sizeof( char ) );
  340. // convert string from UNICODE version to ANSI version
  341. WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pwszSource, -1,
  342. pszDestination, dwLength, NULL, NULL );
  343. // return the destination as return value
  344. return pszDestination;
  345. }
  346. // ***************************************************************************
  347. // Routine Description:
  348. //
  349. // Translates the Ansi string in to the Unicode string.
  350. //
  351. // Arguments:
  352. //
  353. // [in] pszSource -- Ansi string to be translated,
  354. // [out] pwszDestination -- Translated string.
  355. // [in] dwLength -- Size of the string
  356. //
  357. // Return Value:
  358. //
  359. // LPWSTR --Translated string.
  360. //
  361. // ***************************************************************************
  362. LPWSTR GetAsUnicodeString( LPCTSTR pszSource, LPWSTR pwszDestination, DWORD dwLength )
  363. {
  364. // check the input values
  365. if ( pszSource == NULL || pwszDestination == NULL )
  366. {
  367. SetLastError( ERROR_INVALID_PARAMETER );
  368. SaveLastError();
  369. return L"";
  370. }
  371. // initialize the values with zeros
  372. // NOTE:- MultiByteToWideChar wont null terminate its result so
  373. // if its not initialized to nulls, you'll get junk after
  374. // the converted string and will result in crashes
  375. ZeroMemory( pwszDestination, dwLength * sizeof( wchar_t ) );
  376. #ifdef UNICODE
  377. // just do the copy
  378. lstrcpyn( pwszDestination, pszSource, dwLength );
  379. #else
  380. // convert string from ANSI version to UNICODE version
  381. MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, pszSource, -1, pwszDestination, dwLength );
  382. #endif
  383. // return the destination as return value
  384. return pwszDestination;
  385. }
  386. // ***************************************************************************
  387. // Routine Description:
  388. //
  389. // Convertes ansi string to wide charecter string.
  390. //
  391. // Arguments:
  392. //
  393. // [in] pszSource -- String to be converted.
  394. // [out] pwszDestination -- Converted string
  395. // [in] dwLength -- length of the string
  396. //
  397. // Return Value:
  398. //
  399. // LPWSTR --Converted String
  400. //
  401. // ***************************************************************************
  402. LPWSTR GetAsUnicodeStringEx( LPCSTR pszSource, LPWSTR pwszDestination, DWORD dwLength )
  403. {
  404. // check the input values
  405. if ( pszSource == NULL || pwszDestination == NULL )
  406. {
  407. SetLastError( ERROR_INVALID_PARAMETER );
  408. SaveLastError();
  409. return L"";
  410. }
  411. // initialize the values with zeros
  412. // NOTE:- MultiByteToWideChar wont null terminate its result so
  413. // if its not initialized to nulls, you'll get junk after
  414. // the converted string and will result in crashes
  415. ZeroMemory( pwszDestination, dwLength * sizeof( wchar_t ) );
  416. // convert string from ANSI version to UNICODE version
  417. MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, pszSource, -1, pwszDestination, dwLength );
  418. // return the destination as return value
  419. return pwszDestination;
  420. }
  421. // ***************************************************************************
  422. // Routine Description:
  423. //
  424. // Convertes the given string as a float value.
  425. //
  426. // Arguments:
  427. //
  428. // [in] szValue -- String to convert
  429. //
  430. // Return Value:
  431. //
  432. // double -- converted double
  433. //
  434. // ***************************************************************************
  435. double AsFloat( LPCTSTR szValue )
  436. {
  437. // local variables
  438. double dblValue = 0;
  439. LPTSTR pszStopString = NULL;
  440. __MAX_SIZE_STRING szValueString = NULL_STRING;
  441. // check the input value
  442. if ( szValue == NULL )
  443. {
  444. SetLastError( ERROR_INVALID_PARAMETER );
  445. SaveLastError();
  446. return 0.0f;
  447. }
  448. // convert the string value into double value
  449. lstrcpy( szValueString, szValue ); // copy org value into local buffer
  450. dblValue = _tcstod( szValueString, &pszStopString );
  451. // return converted value
  452. return dblValue;
  453. }
  454. // ***************************************************************************
  455. // Routine Description:
  456. //
  457. // Convertes the string in to the long value based on the given base.
  458. //
  459. // Arguments:
  460. //
  461. // [in] szValue --Srtring to convert
  462. // [in] dwBase --Base value
  463. //
  464. // Return Value:
  465. //
  466. // LONG --converted long value
  467. //
  468. // ***************************************************************************
  469. LONG AsLong( LPCTSTR szValue, DWORD dwBase )
  470. {
  471. // local variables
  472. LONG lValue = 0;
  473. LPTSTR pszStopString = NULL;
  474. __MAX_SIZE_STRING szValueString = NULL_STRING;
  475. // validate the base
  476. // value should be in the range of 2 - 36 only
  477. if ( dwBase < 2 || dwBase > 36 )
  478. return -1;
  479. // check the input value
  480. if ( szValue == NULL )
  481. {
  482. SetLastError( ERROR_INVALID_PARAMETER );
  483. SaveLastError();
  484. return 0L;
  485. }
  486. // convert the string value into long value
  487. lstrcpy( szValueString, szValue ); // copy org value into local buffer
  488. lValue = _tcstol( szValueString, &pszStopString, dwBase );
  489. // return converted value
  490. return lValue;
  491. }
  492. // ***************************************************************************
  493. // Routine Description:
  494. //
  495. // Checks whether the given string is a float string
  496. //
  497. // Arguments:
  498. //
  499. // [in] szValue --String to check
  500. //
  501. // Return Value:
  502. //
  503. // BOOL --True if the given string is a floating point string
  504. // --False Otherwise
  505. //
  506. // ***************************************************************************
  507. BOOL IsFloatingPoint( LPCTSTR szValue )
  508. {
  509. // local variables
  510. double dblValue = 0;
  511. LPTSTR pszStopString = NULL;
  512. __MAX_SIZE_STRING szValueString = NULL_STRING;
  513. // check the input value
  514. if ( szValue == NULL )
  515. {
  516. SetLastError( ERROR_INVALID_PARAMETER );
  517. SaveLastError();
  518. return FALSE;
  519. }
  520. // convert the string value into double value
  521. lstrcpy( szValueString, szValue ); // copy org value into local buffer
  522. dblValue = _tcstod( szValueString, &pszStopString );
  523. // now check whether the value is completely converted to floating point or not
  524. // if not converted completely, then value is not correct
  525. // if completely converted, the value is pure floating point
  526. if ( lstrlen( pszStopString ) != 0 )
  527. return FALSE;
  528. // value is valid floating point
  529. return TRUE;
  530. }
  531. // ***************************************************************************
  532. // Routine Description:
  533. //
  534. // Checks whether the given string is Numeric or not.
  535. //
  536. // Arguments:
  537. //
  538. // [in] szValue --String to check
  539. // [in] dwBase -- The base value
  540. // [in] bSigned -- signed information
  541. // -- true if signed, otherwise false
  542. //
  543. // Return Value:
  544. //
  545. // BOOL --true if it is a numeric with that base
  546. // --false otherwise.
  547. //
  548. // ***************************************************************************
  549. BOOL IsNumeric( LPCTSTR szValue, DWORD dwBase, BOOL bSigned )
  550. {
  551. // local variables
  552. long lValue = 0;
  553. double dblValue = 0;
  554. LPTSTR pszStopString = NULL;
  555. __MAX_SIZE_STRING szValueString = NULL_STRING;
  556. // validate the base
  557. // value should be in the range of 2 - 36 only
  558. if ( dwBase < 2 || dwBase > 36 )
  559. return FALSE;
  560. // check the input value
  561. if ( szValue == NULL )
  562. {
  563. SetLastError( ERROR_INVALID_PARAMETER );
  564. SaveLastError();
  565. return FALSE;
  566. }
  567. // convert the string value into numeric value
  568. lstrcpy( szValueString, szValue ); // copy org value into local buffer
  569. lValue = _tcstol( szValueString, &pszStopString, dwBase );
  570. // now check whether the value is completely converted to numeric value or not
  571. // if not converted completely, then value is not correct
  572. // if completely converted, the value is pure numeric value
  573. if ( lstrlen( pszStopString ) != 0 )
  574. return FALSE;
  575. // check whether the numeric value can be signed or not
  576. if ( bSigned == FALSE && lValue < 0 )
  577. return FALSE; // value cannot be -ve
  578. // furthur check whether converted value is valid or not - overflow might have occurred
  579. // NOTE: because of the limitations of libraries which we have in 'C' we cannot
  580. // check for the overflow exactly using the LONG datatype.
  581. // for that reason we are using 'double' data type to check for overflow
  582. lstrcpy( szValueString, szValue ); // copy org value into local buffer
  583. dblValue = _tcstod( szValueString, &pszStopString );
  584. // validate the number
  585. if ( bSigned == FALSE && dblValue > ((double) ULONG_MAX) )
  586. return FALSE;
  587. else if (bSigned && ( dblValue > ((double) LONG_MAX) || dblValue < ((double) LONG_MIN) ))
  588. return FALSE;
  589. // value is valid numeric
  590. return TRUE;
  591. }
  592. // ***************************************************************************
  593. // Routine Description:
  594. //
  595. // Replicates the szChar string dwCount times and saves the result in pszBuffer.
  596. //
  597. // Arguments:
  598. //
  599. // [in] pszBuffer --String to copy the replicate string
  600. // [in] szChar --String to replicate
  601. // [in] dwCount -- Number of times
  602. //
  603. // Return Value:
  604. //
  605. // LPTSTR --Replicated string
  606. //
  607. // ***************************************************************************
  608. LPTSTR Replicate( LPTSTR pszBuffer, LPCTSTR szChar, DWORD dwCount )
  609. {
  610. // local variables
  611. DWORD dw = 0;
  612. // validate the input buffers
  613. if ( pszBuffer == NULL || szChar == NULL )
  614. return NULL_STRING;
  615. // form the string of required length
  616. lstrcpy( pszBuffer, NULL_STRING );
  617. for( dw = 0; dw < dwCount; dw++ )
  618. {
  619. // append the replication character
  620. lstrcat( pszBuffer, szChar );
  621. }
  622. // return the replicated buffer
  623. return pszBuffer;
  624. }
  625. // ***************************************************************************
  626. // Routine Description:
  627. //
  628. // Adjust the length of a string with spaces depending on the given pad.
  629. //
  630. // Arguments:
  631. //
  632. // [in] szValue -- Given string
  633. // [in] dwLength -- Actual length of the string
  634. // [in] bPadLeft -- Padding property
  635. // -- true if left padding is required
  636. // -- false otherwise
  637. // Return Value:
  638. //
  639. // LPTSTR -- String with actual length.
  640. //
  641. // ***************************************************************************
  642. LPTSTR AdjustStringLength( LPTSTR szValue, DWORD dwLength, BOOL bPadLeft )
  643. {
  644. // local variables
  645. DWORD dw = 0;
  646. DWORD dwTemp = 0;
  647. DWORD dwCurrLength = 0;
  648. LPTSTR pszBuffer = NULL;
  649. LPTSTR pszSpaces = NULL;
  650. // check the input value
  651. if ( szValue == NULL )
  652. {
  653. SetLastError( ERROR_INVALID_PARAMETER );
  654. SaveLastError();
  655. return NULL_STRING;
  656. }
  657. // allocate the buffers
  658. // ( accomadate space double the original buffer/required length - this will save us from crashes )
  659. dwTemp = (( StringLengthInBytes( szValue ) > (LONG) dwLength ) ? StringLengthInBytes( szValue ) : dwLength );
  660. pszSpaces = __calloc( dwTemp * 2, sizeof( TCHAR ) );
  661. pszBuffer = __calloc( dwTemp * 2, sizeof( TCHAR ) );
  662. if ( pszBuffer == NULL || pszSpaces == NULL )
  663. {
  664. __free( pszBuffer );
  665. __free( pszSpaces );
  666. return szValue;
  667. }
  668. // get the current length of the string
  669. // NOTE: the string might contain the meta characters which will count in length
  670. // so get the actual string contents which whill be displayed
  671. lstrcpy( pszBuffer, szValue );
  672. wsprintf( pszSpaces, pszBuffer );
  673. dwCurrLength = StringLengthInBytes( pszSpaces );
  674. // reset the data
  675. lstrcpy( pszBuffer, NULL_STRING );
  676. lstrcpy( pszSpaces, NULL_STRING );
  677. // adjust the string value
  678. if ( dwCurrLength < dwLength )
  679. {
  680. //
  681. // length of the current value is less than the needed
  682. // get the spaces for the rest of the length
  683. Replicate( pszSpaces, _T( " " ), dwLength - dwCurrLength );
  684. // append the spaces either to the end of the value or begining of the value
  685. // based on the padding property
  686. if ( bPadLeft )
  687. {
  688. // spaces first and then value
  689. lstrcpy( pszBuffer, pszSpaces );
  690. lstrcat( pszBuffer, szValue );
  691. }
  692. else
  693. {
  694. // value first and then spaces
  695. lstrcpy( pszBuffer, szValue );
  696. lstrcat( pszBuffer, pszSpaces );
  697. }
  698. }
  699. else
  700. {
  701. // prepare the buffer ... we will avoid '%' characters here
  702. lstrcpy( pszSpaces, szValue );
  703. wsprintf( pszBuffer, pszSpaces );
  704. // copy only the characters of required length
  705. lstrcpyn( pszSpaces, pszBuffer, dwLength + 1 );
  706. // now re-insert the '%' characters
  707. lstrcpy( pszBuffer, _X( pszSpaces ) );
  708. }
  709. // copy the contents back to the original buffer
  710. lstrcpy( szValue, pszBuffer );
  711. // free the buffer
  712. __free( pszBuffer );
  713. __free( pszSpaces );
  714. // return the same buffer back to the caller
  715. return szValue;
  716. }
  717. // ***************************************************************************
  718. // Routine Description:
  719. //
  720. // Trims the string on both sides (left and/or right)
  721. //
  722. // Arguments:
  723. //
  724. // [in] lpsz --String to trim
  725. // [in] dwFlags --Flags for specifying left and/or right trim
  726. //
  727. // Return Value:
  728. //
  729. // LPTSTR -- Trimmed string.
  730. //
  731. // ***************************************************************************
  732. LPTSTR TrimString( LPTSTR lpsz, DWORD dwFlags )
  733. {
  734. // local varibles
  735. DWORD dwBegin = 0, dwEnd = 0;
  736. LPTSTR pszTemp = NULL;
  737. LPTSTR pszBuffer = NULL;
  738. // validate the parameter
  739. if ( lpsz == NULL )
  740. {
  741. SetLastError( ERROR_INVALID_PARAMETER );
  742. SaveLastError();
  743. return NULL_STRING;
  744. }
  745. // check length of the string if it empty string ...
  746. if ( lstrlen( lpsz ) == 0 )
  747. return lpsz;
  748. // get the duplicate copy
  749. pszTemp = _tcsdup( lpsz );
  750. if ( pszTemp == NULL )
  751. {
  752. SetLastError( E_OUTOFMEMORY );
  753. SaveLastError();
  754. return NULL_STRING;
  755. }
  756. // traverse both from the end of the string and begining of the string
  757. dwBegin = 0;
  758. dwEnd = lstrlen( pszTemp ) - 1;
  759. for( ; *( pszTemp + dwBegin ) == _T( ' ' ) || *( pszTemp + dwEnd ) == _T( ' ' ); )
  760. {
  761. // check the character at the current begining .. if space, move the pointer
  762. if ( *( pszTemp + dwBegin ) == _T( ' ' ) && ( dwFlags & TRIM_LEFT ) )
  763. dwBegin++;
  764. // check whether the last character is space or not
  765. // if space, decrement the size
  766. if ( *( pszTemp + dwEnd ) == _T( ' ' ) && ( dwFlags & TRIM_RIGHT ) )
  767. dwEnd--;
  768. }
  769. // do the actual trimming now
  770. pszBuffer = pszTemp; // save the pointer ... needs to freed
  771. *( pszTemp + dwEnd + 1 ) = NULL_CHAR; // remove trailing spaces first
  772. pszTemp += dwBegin; // then leading spaces
  773. lstrcpy( lpsz, pszTemp ); // copy to the source buffer
  774. free( pszBuffer ); // release the duplicated memory
  775. // return the string
  776. return lpsz;
  777. }
  778. // ***************************************************************************
  779. // Routine Description:
  780. //
  781. // Takes the password from the keyboard. While entering the password it shows
  782. // the charecters as '*'
  783. //
  784. // Arguments:
  785. //
  786. // [in] pszPassword --password string to store password
  787. // [in] dwMaxPasswordSize --Maximun size of the password. MAX_PASSWORD_LENGTH.
  788. //
  789. // Return Value:
  790. //
  791. // BOOL --If this function succeds returns true otherwise retuens false.
  792. //
  793. // ***************************************************************************
  794. BOOL GetPassword( LPTSTR pszPassword, DWORD dwMaxPasswordSize )
  795. {
  796. // local variables
  797. TCHAR ch;
  798. DWORD dwIndex = 0;
  799. DWORD dwCharsRead = 0;
  800. DWORD dwCharsWritten = 0;
  801. DWORD dwPrevConsoleMode = 0;
  802. HANDLE hInputConsole = NULL;
  803. TCHAR szBuffer[ 10 ] = NULL_STRING; // actually contains only character at all the times
  804. BOOL bIndirectionInput = FALSE;
  805. TCHAR szTmpBuffer[MAX_PASSWORD_LENGTH] = NULL_STRING;
  806. HANDLE hnd;
  807. // check the input value
  808. if ( pszPassword == NULL )
  809. {
  810. SetLastError( ERROR_INVALID_PARAMETER );
  811. SaveLastError();
  812. return FALSE;
  813. }
  814. // get the handle for the standard input
  815. hInputConsole = GetStdHandle( STD_INPUT_HANDLE );
  816. if ( hInputConsole == NULL )
  817. {
  818. // could not get the handle so return failure
  819. return FALSE;
  820. }
  821. // check for the input redirect
  822. if( ( hInputConsole != (HANDLE)0x00000003 ) && ( hInputConsole != INVALID_HANDLE_VALUE ) )
  823. {
  824. bIndirectionInput = TRUE;
  825. }
  826. // redirect the data from StdIn.txt file into the console
  827. if ( bIndirectionInput == FALSE )
  828. {
  829. // Get the current input mode of the input buffer
  830. GetConsoleMode( hInputConsole, &dwPrevConsoleMode );
  831. // Set the mode such that the control keys are processed by the system
  832. if ( SetConsoleMode( hInputConsole, ENABLE_PROCESSED_INPUT ) == 0 )
  833. {
  834. // could not set the mode, return failure
  835. return FALSE;
  836. }
  837. }
  838. // Read the characters until a carriage return is hit
  839. while( TRUE )
  840. {
  841. if ( bIndirectionInput == TRUE )
  842. {
  843. //read the contents of file
  844. if ( ReadFile( hInputConsole, &ch, 1, &dwCharsRead, NULL ) == FALSE )
  845. {
  846. return FALSE;
  847. }
  848. // check for end of file
  849. if ( dwCharsRead == 0 )
  850. {
  851. break;
  852. }
  853. }
  854. else
  855. {
  856. if ( ReadConsole( hInputConsole, &ch, 1, &dwCharsRead, NULL ) == 0 )
  857. {
  858. // Set the original console settings
  859. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  860. // return failure
  861. return FALSE;
  862. }
  863. }
  864. // Check for carraige return
  865. if ( ch == CARRIAGE_RETURN )
  866. {
  867. // break from the loop
  868. break;
  869. }
  870. // Check id back space is hit
  871. if ( ch == BACK_SPACE )
  872. {
  873. if ( dwIndex != 0 )
  874. {
  875. //
  876. // Remove a asterix from the console
  877. // move the cursor one character back
  878. FORMAT_STRING( szBuffer, _T( "%c" ), BACK_SPACE );
  879. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
  880. &dwCharsWritten, NULL );
  881. // replace the existing character with space
  882. FORMAT_STRING( szBuffer, _T( "%c" ), BLANK_CHAR );
  883. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
  884. &dwCharsWritten, NULL );
  885. // now set the cursor at back position
  886. FORMAT_STRING( szBuffer, _T( "%c" ), BACK_SPACE );
  887. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
  888. &dwCharsWritten, NULL );
  889. // decrement the index
  890. dwIndex--;
  891. }
  892. // process the next character
  893. continue;
  894. }
  895. // if the max password length has been reached then sound a beep
  896. if ( dwIndex == ( dwMaxPasswordSize - 1 ) )
  897. {
  898. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), BEEP_SOUND, 1,
  899. &dwCharsWritten, NULL );
  900. }
  901. else
  902. {
  903. // check for new line character
  904. if ( ch != '\n' )
  905. {
  906. // store the input character
  907. *( pszPassword + dwIndex ) = ch;
  908. dwIndex++;
  909. // display asterix onto the console
  910. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), ASTERIX, 1,
  911. &dwCharsWritten, NULL );
  912. }
  913. }
  914. }
  915. // Add the NULL terminator
  916. *( pszPassword + dwIndex ) = NULL_CHAR;
  917. //Set the original console settings
  918. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  919. // display the character ( new line character )
  920. FORMAT_STRING( szBuffer, _T( "%s" ), _T( "\n\n" ) );
  921. WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 2,
  922. &dwCharsWritten, NULL );
  923. // Return success
  924. return TRUE;
  925. }
  926. // ***************************************************************************
  927. // Routine Description:
  928. //
  929. // Searches for a string in a string.
  930. //
  931. // Arguments:
  932. //
  933. // [in] szString --Null termibated string to search
  934. // [in] szList --Null-terminated string to search for
  935. // [in] bIgnoreCase --True for ignore the case
  936. // --False for case sensitive search
  937. //
  938. // Return Value:
  939. //
  940. // BOOL --True if the string is found otherwise false
  941. //
  942. // ***************************************************************************
  943. BOOL InString( LPCTSTR szString, LPCTSTR szList, BOOL bIgnoreCase )
  944. {
  945. // local variables
  946. __MAX_SIZE_STRING szFmtList = NULL_STRING;
  947. __MAX_SIZE_STRING szFmtString = NULL_STRING;
  948. // check the input value
  949. if ( szString == NULL || szList == NULL )
  950. {
  951. SetLastError( ERROR_INVALID_PARAMETER );
  952. SaveLastError();
  953. return FALSE;
  954. }
  955. // prepare the strings for searching
  956. FORMAT_STRING( szFmtList, _T( "|%s|" ), szList );
  957. FORMAT_STRING( szFmtString, _T( "|%s|" ), szString );
  958. // check whether is comparision is case-sensitive or case-insensitive
  959. if ( bIgnoreCase )
  960. {
  961. // convert the list and string to uppercase
  962. CharUpper( szFmtList );
  963. CharUpper( szFmtString );
  964. }
  965. // search for the string in the list and return result based
  966. return ( _tcsstr( szFmtList, szFmtString ) != NULL );
  967. }
  968. // ***************************************************************************
  969. // Routine Description:
  970. //
  971. // Compares the two given strings.
  972. //
  973. // Arguments:
  974. //
  975. // [in] szString1 --first null-terminated string to be compared
  976. // [in] szString2 --second first null-terminated string to be compared
  977. // [in] bIgnoreCase --True for ignoring the case.
  978. // --False for case sensitive.
  979. // [in] dwCount --Number of charecters to compare.
  980. //
  981. // Return Value:
  982. //
  983. // LONG -- < 0 szString1 substring less than szString2 substring
  984. // -- = 0 szString1 substring identical to szString2 substring
  985. // -- > 0 szString1 substring greater than szString2 substring
  986. //
  987. // ***************************************************************************
  988. LONG StringCompare( LPCTSTR szString1, LPCTSTR szString2, BOOL bIgnoreCase, DWORD dwCount )
  989. {
  990. // local variables
  991. LONG lResult;
  992. // check the input value
  993. if ( szString1 == NULL || szString2 == NULL )
  994. {
  995. SetLastError( ERROR_INVALID_PARAMETER );
  996. SaveLastError();
  997. return 0;
  998. }
  999. //
  1000. // start the comparision
  1001. if ( bIgnoreCase )
  1002. {
  1003. //
  1004. // do case in-sensitive comparision
  1005. // if count info is not available,
  1006. if ( dwCount == 0 )
  1007. lResult = lstrcmpi( szString1, szString2 );
  1008. else // otherwise
  1009. lResult = _tcsnicmp( szString1, szString2, dwCount );
  1010. }
  1011. else // case sensitive
  1012. {
  1013. //
  1014. // do case in-sensitive comparision
  1015. // if count info is not available,
  1016. if ( dwCount == 0 )
  1017. lResult = lstrcmp( szString1, szString2 );
  1018. else // otherwise
  1019. lResult = _tcsncmp( szString1, szString2, dwCount );
  1020. }
  1021. // now return comparision result
  1022. return lResult;
  1023. }
  1024. // ***************************************************************************
  1025. // Routine Description:
  1026. //
  1027. // Returns the resource string from the resource for the given resource ID.
  1028. //
  1029. // Arguments:
  1030. //
  1031. // [in] uID --Windows string resource identifier.
  1032. //
  1033. // Return Value:
  1034. //
  1035. // LPCTSTR --Resource string from the resource.
  1036. //
  1037. // ***************************************************************************
  1038. LPCTSTR GetResString( UINT uID )
  1039. {
  1040. // check whether memory is allocated or not
  1041. // if memory is not allocated, allocate now
  1042. if ( g_pszString == NULL )
  1043. {
  1044. g_pszString = ( LPTSTR ) __calloc( MAX_RES_STRING + 5, sizeof( TCHAR ) );
  1045. if ( g_pszString == NULL )
  1046. return NULL_STRING;
  1047. }
  1048. // load the string from the resource table
  1049. if ( LoadResString( uID, g_pszString, MAX_RES_STRING ) == 0 )
  1050. return NULL_STRING;
  1051. // return the string
  1052. return g_pszString;
  1053. }
  1054. // ***************************************************************************
  1055. // Routine Description:
  1056. //
  1057. // Returns the resourse string from the resource for the given resource ID.
  1058. //
  1059. // Arguments:
  1060. //
  1061. // [in] uID --Windows string resource identifier.
  1062. //
  1063. // Return Value:
  1064. //
  1065. // LPTSTR --Resource string from the resource.
  1066. //
  1067. // ***************************************************************************
  1068. LPTSTR GetResStringEx( UINT uID )
  1069. {
  1070. // local variables
  1071. LPTSTR pszBuffer = NULL;
  1072. // allocate the memory
  1073. pszBuffer = ( LPTSTR ) __calloc( MAX_RES_STRING + 5, sizeof( TCHAR ) );
  1074. if ( pszBuffer == NULL )
  1075. {
  1076. // ran out of memory
  1077. SetLastError( E_OUTOFMEMORY );
  1078. SaveLastError();
  1079. return NULL;
  1080. }
  1081. // load the string from the resource table
  1082. if ( LoadResString( uID, pszBuffer, MAX_RES_STRING ) == 0 )
  1083. return NULL;
  1084. // return the string
  1085. return pszBuffer;
  1086. }
  1087. // ***************************************************************************
  1088. // Routine Description:
  1089. //
  1090. // Loads the Resource String corresponding to the given ID.
  1091. //
  1092. // Arguments:
  1093. //
  1094. // [in] uID --Windows string resource identifier.
  1095. // LPTSTR pszValue --Nullterminated string to get the resource string.
  1096. // DWORD dwBufferMax --Size of the pszvalue.
  1097. //
  1098. // Return Value:
  1099. //
  1100. // DWORD --if success,Returns the size of the resource string.
  1101. // --otherwise returns 0.
  1102. //
  1103. // ***************************************************************************
  1104. DWORD LoadResString( UINT uID, LPTSTR pszValue, DWORD dwBufferMax )
  1105. {
  1106. // local variables
  1107. DWORD dwResult = 0;
  1108. static DWORD dwCurrentSize = 0;
  1109. static BOOL bThreadLocale = FALSE;
  1110. //
  1111. // because we operate in multi-lingual mode, it is good to set the appropriate
  1112. // thread locale and get the strings from resource table
  1113. //
  1114. if ( bThreadLocale == FALSE )
  1115. {
  1116. SetThreadUILanguage0( 0 );
  1117. bThreadLocale = TRUE;
  1118. }
  1119. // check the input value
  1120. if ( pszValue == NULL )
  1121. {
  1122. SetLastError( ERROR_INVALID_PARAMETER );
  1123. SaveLastError();
  1124. return 0;
  1125. }
  1126. // allocate memory for unicode buffer
  1127. if ( g_pwszResourceString == NULL )
  1128. {
  1129. dwCurrentSize = dwBufferMax; // save the size of the buffer
  1130. g_pwszResourceString = ( LPWSTR ) __calloc( dwBufferMax + 5, sizeof( wchar_t ) );
  1131. if ( g_pwszResourceString == NULL )
  1132. {
  1133. // ran out of memory
  1134. SetLastError( E_OUTOFMEMORY );
  1135. SaveLastError();
  1136. return 0;
  1137. }
  1138. }
  1139. else if ( dwCurrentSize < dwBufferMax )
  1140. {
  1141. // the existing size is less than the required, re-allocate buffer
  1142. dwCurrentSize = dwBufferMax;
  1143. g_pwszResourceString = ( LPWSTR ) __realloc( g_pwszResourceString,
  1144. (dwBufferMax + 1) * sizeof( wchar_t ) );
  1145. if ( g_pwszResourceString == NULL )
  1146. {
  1147. // ran out of memory
  1148. SetLastError( E_OUTOFMEMORY );
  1149. SaveLastError();
  1150. return 0;
  1151. }
  1152. }
  1153. // ( try ) loading the string from resource file string table
  1154. dwResult = LoadStringW( NULL, uID, g_pwszResourceString, dwBufferMax );
  1155. // check the result of loading string from string table
  1156. // if success, make the string into compatible string and copy it to the
  1157. // specified buffer
  1158. if ( dwResult != 0 )
  1159. {
  1160. // get the compatible string
  1161. GetCompatibleStringFromUnicode( g_pwszResourceString, pszValue, dwBufferMax );
  1162. }
  1163. // return
  1164. return dwResult;
  1165. }
  1166. // ***************************************************************************
  1167. // Routine Description:
  1168. //
  1169. // Writes the Message corrsponding to the given id in the given file.
  1170. //
  1171. // Arguments:
  1172. //
  1173. // [in] fp --File to write the string.
  1174. // [in] uID --Windows string resource identifier.
  1175. //
  1176. // Return Value:
  1177. //
  1178. // VOID
  1179. //
  1180. // ***************************************************************************
  1181. VOID ShowResMessage( FILE* fp, UINT uID )
  1182. {
  1183. // local variables
  1184. __RESOURCE_STRING szValue = NULL_STRING;
  1185. // check the input value
  1186. if ( fp == NULL )
  1187. {
  1188. SetLastError( ERROR_INVALID_PARAMETER );
  1189. SaveLastError();
  1190. return;
  1191. }
  1192. // load the string from the resource table
  1193. if ( LoadResString( uID, szValue, MAX_RES_STRING ) )
  1194. {
  1195. DISPLAY_MESSAGE( fp, szValue ); // display the message to the specified file
  1196. }
  1197. }
  1198. // ***************************************************************************
  1199. // Routine Description:
  1200. // Displays the given input message
  1201. // Arguments:
  1202. // [in] fp - file pointer
  1203. // [in] szMessage - Message to be shown
  1204. //
  1205. // Return Value:
  1206. //
  1207. // ***************************************************************************
  1208. VOID ShowMessage( FILE* fp, LPCTSTR szMessage )
  1209. {
  1210. // local variables
  1211. DWORD dw = 0;
  1212. DWORD dwTemp = 0;
  1213. DWORD dwLength = 0;
  1214. DWORD dwBufferSize = 0;
  1215. BOOL bResult = FALSE;
  1216. BOOL bCustom = FALSE;
  1217. HANDLE hOutput = NULL;
  1218. DWORD dwStdHandle = 0;
  1219. LPTSTR pszTemp = NULL;
  1220. LPCTSTR pszMessageBuffer = NULL;
  1221. char szBuffer[ 256 ] = "\0";
  1222. // check the input value
  1223. if ( fp == NULL || szMessage == NULL )
  1224. {
  1225. SetLastError( ERROR_INVALID_PARAMETER );
  1226. SaveLastError();
  1227. return;
  1228. }
  1229. // determine the length(s)
  1230. dwLength = lstrlen( szMessage );
  1231. dwBufferSize = SIZE_OF_ARRAY( szBuffer );
  1232. // determine the file handle
  1233. bCustom = FALSE;
  1234. if ( fp == stdout )
  1235. {
  1236. dwStdHandle = STD_OUTPUT_HANDLE;
  1237. }
  1238. else if ( fp == stderr )
  1239. {
  1240. dwStdHandle = STD_ERROR_HANDLE;
  1241. }
  1242. else
  1243. {
  1244. // currently default the unknown files to stderr
  1245. bCustom = TRUE;
  1246. dwStdHandle = STD_OUTPUT_HANDLE;
  1247. }
  1248. // get the handle to the stdout ( console )
  1249. hOutput = GetStdHandle( dwStdHandle );
  1250. if ( bCustom == FALSE && (((DWORD_PTR) hOutput) & 1) )
  1251. {
  1252. //
  1253. // sting might have contained '%' (extra) chars added by QuoteMeta
  1254. if ( FindOneOf( szMessage, _T( "%" ), 0 ) != NULL )
  1255. {
  1256. // allocate memory for formatting
  1257. pszTemp = __calloc( lstrlen( szMessage ) + 10, sizeof( TCHAR ) );
  1258. if ( pszTemp != NULL )
  1259. {
  1260. // we are not checking for non-null case which is out of memory error
  1261. // just to avoid too many complications
  1262. wsprintf( pszTemp, szMessage );
  1263. // make the temporary pointer point to the formatted text
  1264. pszMessageBuffer = pszTemp;
  1265. }
  1266. }
  1267. // check whether we did any formatting or not
  1268. if ( pszMessageBuffer == NULL )
  1269. {
  1270. // make the temporary pointer point to the original text
  1271. pszMessageBuffer = szMessage;
  1272. }
  1273. // display the output
  1274. bResult = WriteConsole( hOutput, pszMessageBuffer, dwLength, &dwTemp, NULL );
  1275. // free the memory allocated if allocated
  1276. if ( pszTemp != NULL )
  1277. {
  1278. __free( pszTemp );
  1279. pszTemp = NULL;
  1280. }
  1281. }
  1282. else
  1283. {
  1284. // show the text in shunks of buffer size
  1285. dw = 0;
  1286. while ( dwLength > dw )
  1287. {
  1288. // get the string in 'multibyte' format
  1289. GetAsMultiByteString( szMessage + dw, szBuffer, dwBufferSize - 1 );
  1290. // WideCharToMultiByte( CP_ACP, 0,
  1291. // szMessage + dw, dwBufferSize, szBuffer, dwBufferSize, NULL, NULL );
  1292. // determine the remaining buffer length
  1293. dw += dwBufferSize - 1;
  1294. // display string onto the specified file
  1295. // bResult = WriteFile( hOutput, szBuffer, lstrlenA( szBuffer ), &dwTemp, NULL );
  1296. // if ( bResult == FALSE )
  1297. // {
  1298. // break;
  1299. // }
  1300. fprintf( fp, szBuffer );
  1301. fflush( fp );
  1302. }
  1303. }
  1304. }
  1305. // ***************************************************************************
  1306. // Routine Description:
  1307. //
  1308. // Gets the Last error description
  1309. //
  1310. // Arguments:
  1311. //
  1312. // None
  1313. //
  1314. // Return Value:
  1315. //
  1316. // LPCTSTR The error description string
  1317. //
  1318. // ***************************************************************************
  1319. LPCTSTR GetReason()
  1320. {
  1321. // check whether buffer is allocated or not ... if not, empty string
  1322. if ( g_pszInfo == NULL )
  1323. return NULL_STRING;
  1324. // returh the reason for the last failure
  1325. return g_pszInfo;
  1326. }
  1327. // ***************************************************************************
  1328. // Routine Description:
  1329. //
  1330. // Sets teh last occured error as the given string.
  1331. //
  1332. // Arguments:
  1333. //
  1334. // [in] szReason -- Null terminated string taht holds the error description.
  1335. //
  1336. // Return Value:
  1337. //
  1338. // VOID
  1339. //
  1340. // ***************************************************************************
  1341. VOID SetReason( LPCTSTR szReason )
  1342. {
  1343. // check the input value
  1344. if ( szReason == NULL )
  1345. {
  1346. SetLastError( ERROR_INVALID_PARAMETER );
  1347. SaveLastError();
  1348. return;
  1349. }
  1350. // check whether memory is allocated or not
  1351. // if memory is not allocated, allocate now
  1352. if ( g_pszInfo == NULL )
  1353. {
  1354. g_pszInfo = ( LPTSTR ) __calloc( MAX_STRING_LENGTH + 5, sizeof( TCHAR ) );
  1355. if ( g_pszInfo == NULL )
  1356. return;
  1357. }
  1358. // set the reason .. max. allowed characters only
  1359. lstrcpyn( g_pszInfo, szReason, MAX_STRING_LENGTH + 1 );
  1360. }
  1361. // ***************************************************************************
  1362. // Routine Description:
  1363. //
  1364. // Arguments:
  1365. //
  1366. // Return Value:
  1367. //
  1368. // ***************************************************************************
  1369. LPCTSTR FindChar( LPCTSTR pszText, TCHAR ch, DWORD dwFrom )
  1370. {
  1371. // local variables
  1372. DWORD i = 0;
  1373. DWORD dwLength = 0;
  1374. // check the inputs
  1375. if ( pszText == NULL )
  1376. return NULL;
  1377. // get the lengths
  1378. dwLength = lstrlen( pszText );
  1379. // check the length of the text that has to be find. if it is
  1380. // more than the original it is obvious that it cannot be found
  1381. if ( dwLength == 0 || dwFrom >= dwLength )
  1382. return NULL;
  1383. // traverse thru the original text
  1384. for( i = dwFrom; i < dwLength; i++ )
  1385. {
  1386. // traverse thru the find string until characters were matching (or) string reached NULL
  1387. if ( pszText[ i ] == ch )
  1388. return pszText + i;
  1389. }
  1390. // string not found
  1391. return NULL;
  1392. }
  1393. // ***************************************************************************
  1394. // Routine Description:
  1395. //
  1396. // Arguments:
  1397. //
  1398. // Return Value:
  1399. //
  1400. // ***************************************************************************
  1401. LPCTSTR FindString( LPCTSTR pszText, LPCTSTR pszTextToFind, DWORD dwFrom )
  1402. {
  1403. // local variables
  1404. DWORD i = 0, j = 0;
  1405. DWORD dwLength = 0;
  1406. DWORD dwFindLength = 0;
  1407. // check the inputs
  1408. if ( pszText == NULL || pszTextToFind == NULL )
  1409. return NULL;
  1410. // get the lengths
  1411. dwLength = lstrlen( pszText );
  1412. dwFindLength = lstrlen( pszTextToFind );
  1413. // check the length of the text that has to be find. if it is
  1414. // more than the original it is obvious that it cannot be found
  1415. if ( (dwLength + dwFrom < dwFindLength) || dwFindLength == 0 || dwLength == 0 )
  1416. return NULL;
  1417. // traverse thru the original text
  1418. for( i = dwFrom; i < dwLength; i++ )
  1419. {
  1420. // traverse thru the find string until characters were matching (or) string reached NULL
  1421. for( j = 0; pszText[ i + j ] == pszTextToFind[ j ] && j < dwFindLength; j++ );
  1422. // check whether completer string is matched or not
  1423. if ( j == dwFindLength )
  1424. return pszText + i;
  1425. }
  1426. // string not found
  1427. return NULL;
  1428. }
  1429. // ***************************************************************************
  1430. // Routine Description:
  1431. //
  1432. // Arguments:
  1433. //
  1434. // Return Value:
  1435. //
  1436. // ***************************************************************************
  1437. LPCTSTR FindOneOf( LPCTSTR pszText, LPCTSTR pszTextToFind, DWORD dwFrom )
  1438. {
  1439. // local variables
  1440. DWORD i = 0, j = 0;
  1441. DWORD dwLength = 0;
  1442. DWORD dwFindLength = 0;
  1443. // check the inputs
  1444. if ( pszText == NULL || pszTextToFind == NULL )
  1445. return NULL;
  1446. // get the lengths
  1447. dwLength = lstrlen( pszText );
  1448. dwFindLength = lstrlen( pszTextToFind );
  1449. // check the length of the text that has to be find. if it is
  1450. // more than the original it is obvious that it cannot be found
  1451. if ( dwLength == 0 || dwFindLength == 0 || dwFrom >= dwLength )
  1452. return NULL;
  1453. // traverse thru the original text
  1454. for( i = dwFrom; i < dwLength; i++ )
  1455. {
  1456. // traverse thru the find string until characters were matching (or) string reached NULL
  1457. for( j = 0; pszText[ i ] != pszTextToFind[ j ] && j < dwFindLength; j++ );
  1458. // check whether completer string is matched or not
  1459. if ( j != dwFindLength )
  1460. return pszText + i;
  1461. }
  1462. // string not found
  1463. return NULL;
  1464. }
  1465. // ***************************************************************************
  1466. // Routine Description:
  1467. //
  1468. // Arguments:
  1469. //
  1470. // Return Value:
  1471. //
  1472. // ***************************************************************************
  1473. LPCTSTR QuoteMeta( LPCTSTR pszText, DWORD dwQuoteIndex )
  1474. {
  1475. // local variables
  1476. DWORD dw = 0;
  1477. DWORD dwIndex = 0;
  1478. DWORD dwLength = 0;
  1479. LPCTSTR pszTemp = NULL;
  1480. LPTSTR pszQuoteText = NULL;
  1481. TCHAR pszQuoteChars[] = _T( "%" );
  1482. // check the inputs
  1483. if ( pszText == NULL || dwQuoteIndex == 0 )
  1484. return NULL_STRING;
  1485. // create the quote data storage location
  1486. if ( g_arrQuotes == NULL )
  1487. {
  1488. g_arrQuotes = CreateDynamicArray();
  1489. if ( g_arrQuotes == NULL )
  1490. {
  1491. SetLastError( E_OUTOFMEMORY );
  1492. SaveLastError();
  1493. return NULL_STRING;
  1494. }
  1495. }
  1496. // check whether needed indexes exist or not
  1497. dwIndex = DynArrayGetCount( g_arrQuotes );
  1498. if ( dwIndex < dwQuoteIndex )
  1499. {
  1500. // add the needed no. of columns
  1501. dw = DynArrayAddColumns( g_arrQuotes, dwQuoteIndex - dwIndex + 1 );
  1502. // check whether columns were added or not
  1503. if ( dw != dwQuoteIndex - dwIndex + 1 )
  1504. {
  1505. SetLastError( E_OUTOFMEMORY );
  1506. SaveLastError();
  1507. return NULL_STRING;
  1508. }
  1509. }
  1510. // check whether the special chacters do exist in the text or not
  1511. // if not, simply return
  1512. if ( FindOneOf( pszText, pszQuoteChars, 0 ) == NULL )
  1513. return pszText;
  1514. // determine the length of the text that needs to be quoted
  1515. dwLength = lstrlen( pszText );
  1516. if ( dwLength == 0 )
  1517. return pszText;
  1518. // allocate the buffer ... it should twice the original
  1519. pszQuoteText = __calloc( (dwLength + 5) * 2, sizeof( TCHAR ) );
  1520. if ( pszQuoteText == NULL )
  1521. {
  1522. SetLastError( E_OUTOFMEMORY );
  1523. SaveLastError();
  1524. return NULL_STRING;
  1525. }
  1526. // do the quoting ...
  1527. dwIndex = 0;
  1528. for( dw = 0; dw < dwLength; dw++ )
  1529. {
  1530. // check whether the current character is quote char or not
  1531. // NOTE: for time being this function only suppresses the '%' character escape sequences
  1532. if ( FindChar( pszQuoteChars, pszText[ dw ], 0 ) != NULL )
  1533. pszQuoteText[ dwIndex++ ] = _T( '%' );
  1534. // copy the character
  1535. pszQuoteText[ dwIndex++ ] = pszText[ dw ];
  1536. }
  1537. // put the null character
  1538. pszQuoteText[ dwIndex ] = _T( '\0' );
  1539. // save the quoted text in dynamic array
  1540. if ( DynArraySetString( g_arrQuotes, dwQuoteIndex, pszQuoteText, 0 ) == FALSE )
  1541. {
  1542. SetLastError( E_OUTOFMEMORY );
  1543. SaveLastError();
  1544. __free( pszQuoteText );
  1545. return NULL_STRING;
  1546. }
  1547. // release the memory allocated for quoted text
  1548. __free( pszQuoteText );
  1549. // get the text from the array
  1550. pszTemp = DynArrayItemAsString( g_arrQuotes, dwQuoteIndex );
  1551. if ( pszTemp == NULL )
  1552. {
  1553. SetLastError( STG_E_UNKNOWN );
  1554. SaveLastError();
  1555. return NULL_STRING;
  1556. }
  1557. // return
  1558. return pszTemp;
  1559. }
  1560. // ***************************************************************************
  1561. // Routine Description:
  1562. //
  1563. // Complex scripts cannot be rendered in the console, so we
  1564. // force the English (US) resource.
  1565. //
  1566. // Arguments:
  1567. // [ in ] dwReserved => must be zero
  1568. //
  1569. // Return Value:
  1570. // TRUE / FALSE
  1571. //
  1572. // ***************************************************************************
  1573. BOOL SetThreadUILanguage0( DWORD dwReserved )
  1574. {
  1575. // local variables
  1576. HMODULE hKernel32Lib = NULL;
  1577. const CHAR cstrFunctionName[] = "SetThreadUILanguage";
  1578. typedef BOOLEAN (WINAPI * FUNC_SetThreadUILanguage)( DWORD dwReserved );
  1579. FUNC_SetThreadUILanguage pfnSetThreadUILanguage = NULL;
  1580. // try loading the kernel32 dynamic link library
  1581. hKernel32Lib = LoadLibrary( _T( "kernel32.dll" ) );
  1582. if ( hKernel32Lib != NULL )
  1583. {
  1584. // library loaded successfully ... now load the addresses of functions
  1585. pfnSetThreadUILanguage = (FUNC_SetThreadUILanguage) GetProcAddress( hKernel32Lib, cstrFunctionName );
  1586. // we will keep the library loaded in memory only if all the functions were loaded successfully
  1587. if ( pfnSetThreadUILanguage == NULL )
  1588. {
  1589. // some (or) all of the functions were not loaded ... unload the library
  1590. FreeLibrary( hKernel32Lib );
  1591. hKernel32Lib = NULL;
  1592. pfnSetThreadUILanguage = NULL;
  1593. return FALSE;
  1594. }
  1595. }
  1596. // call the function
  1597. ((FUNC_SetThreadUILanguage) pfnSetThreadUILanguage)( dwReserved );
  1598. // unload the library and return success
  1599. FreeLibrary( hKernel32Lib );
  1600. hKernel32Lib = NULL;
  1601. pfnSetThreadUILanguage = NULL;
  1602. return TRUE;
  1603. }
  1604. // ***************************************************************************
  1605. // Routine Description:
  1606. //
  1607. // Releases all the global values that are used.
  1608. //
  1609. // Arguments:
  1610. //
  1611. // None.
  1612. //
  1613. // Return Value:
  1614. //
  1615. // VOID
  1616. //
  1617. // ***************************************************************************
  1618. VOID ReleaseGlobals()
  1619. {
  1620. // local variables
  1621. DWORD dw = 0;
  1622. //
  1623. // memory is allocated then free memory
  1624. // free memory for variable that holds the reason for failure
  1625. if ( g_pszInfo != NULL )
  1626. {
  1627. __free( g_pszInfo );
  1628. }
  1629. // free memory for variable that used to get the string in resource table
  1630. if ( g_pszString != NULL )
  1631. {
  1632. __free( g_pszString );
  1633. }
  1634. // free memory for variable that used to get the string in resource table in UNICODE
  1635. if ( g_pwszResourceString != NULL )
  1636. {
  1637. __free( g_pwszResourceString );
  1638. }
  1639. // free the memory allocs for quote metas
  1640. DestroyDynamicArray( &g_arrQuotes );
  1641. // if winsock module is loaded, release it
  1642. if ( g_bWinsockLoaded == TRUE )
  1643. WSACleanup();
  1644. }