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.

767 lines
18 KiB

  1. /******************************************************************************
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. util.cpp
  5. Abstract:
  6. This file contains the implementation of common utility functions.
  7. Revision History:
  8. Seong Kook Khang (SKKhang) 07/07/99
  9. created
  10. ******************************************************************************/
  11. #include "stdwin.h"
  12. #include "resource.h"
  13. #include "rstrpriv.h"
  14. /////////////////////////////////////////////////////////////////////////////
  15. //
  16. // Utility Functions
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #define CAL_TYPE_GREGORIAN_LOCALZED 1
  20. #define CAL_TYPE_GREGORIAN_ENGLISH 2
  21. #define CAL_TYPE_ERA_JAPAN 3
  22. #define CAL_TYPE_ERA_TAIWAN 4
  23. #define CAL_TYPE_ERA_KOREA 5
  24. #define CAL_TYPE_ARABIC_HIJRI 6
  25. #define CAL_TYPE_THAI 7
  26. #define CAL_TYPE_HEBREW 8
  27. #define CAL_TYPE_GREGORIAN_MIDDLE_EAST_FRENCH 9
  28. #define CAL_TYPE_GREGORIAN_ARABIC 10
  29. #define CAL_TYPE_GREGORIAN_TRANSLITERATED_ENGLISH 11
  30. #define CAL_TYPE_GREGORIAN_TRANSLITERATED_FRENCH 12
  31. #define CAL_RSTRUI_GREGORIAN 1
  32. #define CAL_RSTRUI_OTHER 2
  33. static int s_nCalType = CAL_RSTRUI_GREGORIAN ;
  34. int SRUtil_SetCalendarTypeBasedOnLocale(LCID locale)
  35. {
  36. LPCWSTR cszErr;
  37. int nRet;
  38. WCHAR szCalType[8];
  39. int nCalType;
  40. nRet = ::GetLocaleInfo( locale,
  41. LOCALE_ICALENDARTYPE,
  42. szCalType,
  43. sizeof(szCalType)/sizeof(WCHAR));
  44. if ( nRet == 0 )
  45. {
  46. cszErr = ::GetSysErrStr();
  47. // ErrorTrace(TRACE_ID, "GetLocaleInfo(%d) failed - %s", locale, cszErr);
  48. goto Exit;
  49. }
  50. nCalType = ::_wtoi( szCalType );
  51. if ( CAL_TYPE_GREGORIAN_LOCALZED == nCalType ||
  52. CAL_TYPE_GREGORIAN_ENGLISH == nCalType ||
  53. CAL_TYPE_GREGORIAN_MIDDLE_EAST_FRENCH == nCalType ||
  54. CAL_TYPE_GREGORIAN_ARABIC == nCalType ||
  55. CAL_TYPE_GREGORIAN_TRANSLITERATED_ENGLISH == nCalType ||
  56. CAL_TYPE_GREGORIAN_TRANSLITERATED_FRENCH == nCalType )
  57. {
  58. s_nCalType = CAL_RSTRUI_GREGORIAN ;
  59. }
  60. else
  61. {
  62. s_nCalType = CAL_RSTRUI_OTHER ;
  63. }
  64. Exit:
  65. return nRet ;
  66. }
  67. /******************************************************************************/
  68. LPSTR IStrDupA( LPCSTR szSrc )
  69. {
  70. TraceFunctEnter("IStrDupA");
  71. int ccLen = 0 ;
  72. LPSTR szNew = NULL;
  73. if ( szSrc == NULL || szSrc[0] == '\0' )
  74. goto Exit;
  75. ccLen = ::lstrlenA( szSrc );
  76. szNew = new char[ccLen+2];
  77. if ( szNew != NULL )
  78. {
  79. ::lstrcpyA( szNew, szSrc );
  80. }
  81. Exit:
  82. TraceFunctLeave();
  83. return( szNew );
  84. }
  85. /******************************************************************************/
  86. LPWSTR IStrDupW( LPCWSTR wszSrc )
  87. {
  88. TraceFunctEnter("IStrDupW");
  89. int ccLen = 0 ;
  90. LPWSTR wszNew = NULL ;
  91. if ( wszSrc == NULL || wszSrc[0] == L'\0' )
  92. goto Exit;
  93. ccLen = ::lstrlenW( wszSrc );
  94. wszNew = new WCHAR[ccLen+2];
  95. if ( wszNew != NULL )
  96. {
  97. ::lstrcpyW( wszNew, wszSrc );
  98. }
  99. Exit:
  100. TraceFunctLeave();
  101. return( wszNew );
  102. }
  103. /****************************************************************************/
  104. BOOL
  105. SRFormatMessage( LPWSTR szMsg, UINT uFmtId, ... )
  106. {
  107. TraceFunctEnter("SRFormatMessage");
  108. BOOL fRet = FALSE;
  109. va_list marker;
  110. WCHAR szFmt[MAX_STR_MSG];
  111. va_start( marker, uFmtId );
  112. ::LoadString( g_hInst, uFmtId, szFmt, MAX_STR_MSG );
  113. if ( 0 == ::FormatMessage( FORMAT_MESSAGE_FROM_STRING,
  114. szFmt,
  115. 0,
  116. 0,
  117. szMsg,
  118. MAX_STR_MSG,
  119. &marker ) )
  120. {
  121. LPCWSTR cszErr = ::GetSysErrStr();
  122. ErrorTrace(0, "::FormatMessage failed - %ls", cszErr);
  123. goto Exit;
  124. }
  125. va_end( marker );
  126. fRet = TRUE;
  127. Exit:
  128. TraceFunctLeave();
  129. return( fRet );
  130. }
  131. /****************************************************************************/
  132. BOOL ShowSRErrDlg( UINT uMsgId, ... )
  133. {
  134. TraceFunctEnter("ShowSRErrDlg");
  135. BOOL fRet = FALSE;
  136. LPCWSTR cszErr;
  137. va_list marker;
  138. WCHAR szTitle[MAX_STR_TITLE];
  139. WCHAR szFmt[MAX_STR_MSG];
  140. WCHAR szMsg[MAX_STR_MSG];
  141. if ( ::LoadString( g_hInst, IDS_RESTOREUI_TITLE, szTitle, MAX_STR_TITLE ) == 0 )
  142. {
  143. cszErr = ::GetSysErrStr();
  144. ErrorTrace(0, "::LoadString(%u) failed - %ls", IDS_RESTOREUI_TITLE, cszErr);
  145. goto Exit;
  146. }
  147. if ( ::LoadString( g_hInst, uMsgId, szFmt, MAX_STR_MSG ) == 0 )
  148. {
  149. cszErr = ::GetSysErrStr();
  150. ErrorTrace(0, "::LoadString(%u) failed - %ls", uMsgId, cszErr);
  151. goto Exit;
  152. }
  153. va_start( marker, uMsgId );
  154. ::wvsprintf( szMsg, szFmt, marker );
  155. va_end( marker );
  156. ::MessageBox( NULL, szMsg, szTitle, MB_OK );
  157. fRet = TRUE;
  158. Exit:
  159. TraceFunctLeave();
  160. return( fRet );
  161. }
  162. /****************************************************************************/
  163. BOOL SRGetRegDword( HKEY hKey, LPCWSTR cszSubKey, LPCWSTR cszValue, DWORD *pdwData )
  164. {
  165. TraceFunctEnter("SRGetRegDword");
  166. BOOL fRet = FALSE;
  167. DWORD dwType;
  168. DWORD dwRes;
  169. DWORD cbData;
  170. dwType = REG_DWORD;
  171. cbData = sizeof(DWORD);
  172. dwRes = ::SHGetValue( hKey, cszSubKey, cszValue, &dwType, pdwData, &cbData );
  173. if ( dwRes != ERROR_SUCCESS )
  174. {
  175. LPCWSTR cszErr = ::GetSysErrStr( dwRes );
  176. ErrorTrace(0, "::SHGetValue failed - %ls", cszErr);
  177. goto Exit;
  178. }
  179. fRet = TRUE;
  180. Exit:
  181. TraceFunctLeave();
  182. return( fRet );
  183. }
  184. /******************************************************************************/
  185. /*
  186. static WCHAR s_wszPath[MAX_PATH];
  187. LPWSTR PathElem2Str( PathElement *pElem )
  188. {
  189. TraceFunctEnter("PathElem2Str");
  190. int cch = pElem->pe_length / sizeof(USHORT) - 1;
  191. ::StrCpyNW( s_wszPath, pElem->pe_unichars, cch+1 );
  192. // for ( int i = 0; i < ccLen; i++ )
  193. // wszElem[i] = pElem->pe_unichars[i];
  194. s_wszPath[cch] = '\0';
  195. TraceFunctLeave();
  196. return( s_wszPath );
  197. }
  198. LPWSTR ParsedPath2Str( ParsedPath *pPath, LPCWSTR wszDrive )
  199. {
  200. TraceFunctEnter("ParsedPath2Str");
  201. LPWSTR wszAppend;
  202. PathElement *pElem;
  203. int cch;
  204. if ( pPath != NULL )
  205. {
  206. ::lstrcpyW( s_wszPath, wszDrive );
  207. wszAppend = s_wszPath + ::lstrlenW( s_wszPath );
  208. for ( pElem = pPath->pp_elements; pElem->pe_length > 0; pElem = IFSNextElement( pElem ) )
  209. {
  210. DebugTrace(0, "pElem->pe_length=%d", pElem->pe_length);
  211. *wszAppend++ = L'\\';
  212. cch = pElem->pe_length / sizeof(USHORT) - 1;
  213. ::StrCpyNW( wszAppend, pElem->pe_unichars, cch+1 );
  214. wszAppend += cch;
  215. }
  216. *wszAppend = L'\0';
  217. }
  218. else
  219. {
  220. *s_wszPath = L'\0';
  221. }
  222. TraceFunctLeave();
  223. return( s_wszPath );
  224. }
  225. */
  226. /******************************************************************************/
  227. //
  228. // Check if we have enough free space in Windows directory and this is
  229. // greater than the minimum requirments for carrying out a restore, this
  230. // also reads and caches the registry data. If registry data cannot be
  231. // read defaults in the code will be used
  232. //
  233. BOOL IsFreeSpaceOnWindowsDrive( void )
  234. {
  235. TraceFunctEnter("IsFreeSpaceOnWindowsDrive");
  236. static BOOL fFirstTime = TRUE ;
  237. static DWORD dwMinValidSpace = RSTRMAP_MIN_WIN_DISK_SPACE_MB * (1024 * 1024) ;
  238. static WCHAR szWinPath[MAX_PATH+1];
  239. ULARGE_INTEGER i64FreeBytesToCaller;
  240. ULARGE_INTEGER i64FreeBytes ;
  241. ULARGE_INTEGER i64TotalBytes ;
  242. BOOL fResult = FALSE ;
  243. BOOL fRetVal = TRUE ;
  244. DWORD dwError;
  245. LPCWSTR cszErr;
  246. long lRetVal = 0;
  247. HKEY hKey = NULL;
  248. DWORD dwVal = 0;
  249. DWORD dwType = 0;
  250. DWORD cbData = sizeof(DWORD);
  251. //
  252. // Read registry and get the size of FreezeSize and set the min
  253. // size for disk on data store
  254. //
  255. if ( fFirstTime )
  256. {
  257. #ifdef LEGACY_CODE
  258. if ( !::GetWindowsDirectory( szWinPath, MAX_PATH ) )
  259. {
  260. cszErr = GetSysErrStr();
  261. ErrorTrace(TRACE_ID, "::GetWindowsDirectory failed - %s", cszErr);
  262. goto Exit;
  263. }
  264. DebugTrace(TRACE_ID, "Opening: %s", s_cszReservedDiskSpaceKey);
  265. //
  266. // Open HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\StateMgr\ReservedDiskSpace
  267. // for reading
  268. //
  269. lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  270. s_cszReservedDiskSpaceKey,
  271. 0,
  272. KEY_READ,
  273. &hKey);
  274. if( ERROR_SUCCESS == lRetVal)
  275. {
  276. DebugTrace(TRACE_ID, "Querying: %s", s_cszUIFreezeSize);
  277. //
  278. // Read "FreezeSize"
  279. //
  280. lRetVal = RegQueryValueEx(hKey,
  281. s_cszUIFreezeSize,
  282. 0,
  283. &dwType,
  284. (LPBYTE)&dwVal,
  285. &cbData);
  286. if( ERROR_SUCCESS == lRetVal)
  287. {
  288. if ( dwVal < RSTRMAP_LOW_WIN_DISK_SPACE_MB )
  289. {
  290. dwVal = RSTRMAP_LOW_WIN_DISK_SPACE_MB;
  291. };
  292. dwMinValidSpace = dwVal * (1024 * 1024) ;
  293. }
  294. else
  295. {
  296. ErrorTrace(TRACE_ID, "RegQueryValueEx failed; hr=0x%x", GetLastError());
  297. }
  298. }
  299. else
  300. {
  301. ErrorTrace(TRACE_ID, "RegOpenKeyEx failed; hr=0x%x", GetLastError());
  302. }
  303. #endif //def LEGACY_CODE
  304. fFirstTime = FALSE ;
  305. }
  306. fRetVal = TRUE ;
  307. fResult = GetDiskFreeSpaceEx(szWinPath,
  308. (PULARGE_INTEGER) &i64FreeBytesToCaller,
  309. (PULARGE_INTEGER) &i64TotalBytes,
  310. (PULARGE_INTEGER) &i64FreeBytes);
  311. if ( fResult )
  312. {
  313. //
  314. // Now check if disk free space is greater than min space (high 4GB)
  315. //
  316. if (i64FreeBytes.HighPart > 0 )
  317. {
  318. goto Exit;
  319. }
  320. else if (i64FreeBytesToCaller.LowPart > dwMinValidSpace )
  321. {
  322. goto Exit;
  323. }
  324. else
  325. {
  326. fRetVal = FALSE ;
  327. goto Exit;
  328. }
  329. }
  330. else
  331. {
  332. //
  333. // If the function fails its Ok to try to go on as the Restore Undo
  334. // should handle it if things get very full
  335. //
  336. dwError = ::GetLastError();
  337. ErrorTrace(TRACE_ID, "GetDiskFreeSpaceEx failed. ec=%d", dwError);
  338. goto Exit;
  339. };
  340. Exit:
  341. TraceFunctLeave();
  342. return fRetVal ;
  343. }
  344. //
  345. // Get the default language for the current user
  346. //
  347. LANGID GetDefaultUILang(void)
  348. {
  349. OSVERSIONINFO Osv ;
  350. BOOL IsWindowsNT ;
  351. LANGID wUILang = MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US);
  352. Osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO) ;
  353. if(!GetVersionEx(&Osv))
  354. {
  355. goto Exit ;
  356. }
  357. IsWindowsNT = (BOOL) (Osv.dwPlatformId == VER_PLATFORM_WIN32_NT) ;
  358. //
  359. // Get the UI language by one of three methods, depending on the system
  360. //
  361. if(!IsWindowsNT)
  362. {
  363. //
  364. // Case 1: Running on Windows 9x. Get the system UI language from registry:
  365. //
  366. CHAR szData[32] ;
  367. DWORD dwErr, dwSize = sizeof(szData) ;
  368. HKEY hKey ;
  369. dwErr = RegOpenKeyEx(
  370. HKEY_USERS,
  371. TEXT(".Default\\Control Panel\\desktop\\ResourceLocale"),
  372. 0,
  373. KEY_READ,
  374. &hKey
  375. ) ;
  376. if(ERROR_SUCCESS != dwErr)
  377. {
  378. goto Exit ;
  379. }
  380. dwErr = RegQueryValueEx(
  381. hKey,
  382. TEXT(""),
  383. NULL, //reserved
  384. NULL, //type
  385. (LPBYTE) szData,
  386. &dwSize
  387. ) ;
  388. if(ERROR_SUCCESS != dwErr)
  389. {
  390. goto Exit ;
  391. }
  392. dwErr = RegCloseKey(hKey) ;
  393. // Convert string to number
  394. wUILang = (LANGID) strtol(szData, NULL, 16) ;
  395. }
  396. Exit:
  397. return wUILang ;
  398. }
  399. /////////////////////////////////////////////////////////////////////////////
  400. //
  401. // CSRStr
  402. //
  403. /////////////////////////////////////////////////////////////////////////////
  404. CSRStr::CSRStr()
  405. {
  406. TraceFunctEnter("CSRStr::CSRStr()");
  407. m_cchW = 0;
  408. m_strW = NULL;
  409. m_cchA = 0;
  410. m_strA = NULL;
  411. TraceFunctLeave();
  412. }
  413. CSRStr::CSRStr( LPCWSTR wszSrc )
  414. {
  415. TraceFunctEnter("CSRStr::CSRStr(LPCWSTR)");
  416. m_strW = NULL;
  417. m_strA = NULL;
  418. SetStr( wszSrc );
  419. TraceFunctLeave();
  420. }
  421. CSRStr::CSRStr( LPCSTR szSrc )
  422. {
  423. TraceFunctEnter("CSRStr::CSRStr(LPCSTR)");
  424. m_strW = NULL;
  425. m_strA = NULL;
  426. SetStr( szSrc );
  427. TraceFunctLeave();
  428. }
  429. CSRStr::~CSRStr()
  430. {
  431. TraceFunctEnter("CSRStr::~CSRStr");
  432. Empty();
  433. TraceFunctLeave();
  434. }
  435. int CSRStr::LengthW()
  436. {
  437. TraceFunctEnter("CSRStr::CountW");
  438. if ( m_cchW == 0 && m_strA != NULL )
  439. ConvertA2W();
  440. TraceFunctLeave();
  441. return( m_cchW );
  442. }
  443. int CSRStr::LengthA()
  444. {
  445. TraceFunctEnter("CSRStr::CountA");
  446. if ( m_cchA == 0 && m_strW != NULL )
  447. ConvertW2A();
  448. TraceFunctLeave();
  449. return( m_cchA );
  450. }
  451. CSRStr::operator LPCWSTR()
  452. {
  453. TraceFunctEnter("CSRStr::operator LPCWSTR");
  454. if ( m_strW == NULL && m_strA != NULL )
  455. ConvertA2W();
  456. TraceFunctLeave();
  457. return( m_strW );
  458. }
  459. CSRStr::operator LPCSTR()
  460. {
  461. TraceFunctEnter("CSRStr::operator LPCSTR");
  462. if ( m_strA == NULL && m_strW != NULL )
  463. ConvertW2A();
  464. TraceFunctLeave();
  465. return( m_strA );
  466. }
  467. void CSRStr::Empty()
  468. {
  469. TraceFunctEnter("CSRStr::Empty");
  470. if ( m_strW != NULL )
  471. {
  472. delete [] m_strW;
  473. m_strW = NULL;
  474. m_cchW = 0;
  475. }
  476. if ( m_strA != NULL )
  477. {
  478. delete [] m_strA;
  479. m_strA = NULL;
  480. m_cchA = 0;
  481. }
  482. TraceFunctLeave();
  483. }
  484. BOOL CSRStr::SetStr( LPCWSTR wszSrc, int cch )
  485. {
  486. TraceFunctEnter("CSRStr::SetStr(LPCWSTR,int)");
  487. BOOL fRet = FALSE;
  488. Empty();
  489. if ( wszSrc == NULL )
  490. goto Exit;
  491. if ( cch == -1 )
  492. cch = ::lstrlenW( wszSrc );
  493. if ( cch > 0 )
  494. {
  495. m_strW = new WCHAR[cch+2];
  496. if ( m_strW == NULL )
  497. {
  498. ErrorTrace(TRACE_ID, "Insufficient memory...");
  499. goto Exit;
  500. }
  501. ::StrCpyNW( m_strW, wszSrc, cch+1 );
  502. m_strW[cch] = L'\0';
  503. m_cchW = cch;
  504. }
  505. fRet = TRUE;
  506. Exit:
  507. TraceFunctLeave();
  508. return( fRet );
  509. }
  510. BOOL CSRStr::SetStr( LPCSTR szSrc, int cch )
  511. {
  512. TraceFunctEnter("CSRStr::SetStr(LPCSTR,int)");
  513. BOOL fRet = FALSE;
  514. Empty();
  515. if ( szSrc == NULL )
  516. goto Exit;
  517. if ( cch == -1 )
  518. cch = ::lstrlenA( szSrc );
  519. if ( cch > 0 )
  520. {
  521. m_strA = new char[cch+2];
  522. if ( m_strA == NULL )
  523. {
  524. ErrorTrace(TRACE_ID, "Insufficient memory...");
  525. goto Exit;
  526. }
  527. ::lstrcpynA( m_strA, szSrc, cch+1 );
  528. m_strA[cch] = L'\0';
  529. m_cchA = cch;
  530. }
  531. fRet = TRUE;
  532. Exit:
  533. TraceFunctLeave();
  534. return( fRet );
  535. }
  536. const CSRStr& CSRStr::operator =( LPCWSTR wszSrc )
  537. {
  538. TraceFunctEnter("CSRStr::operator =(LPCWSTR)");
  539. SetStr( wszSrc );
  540. TraceFunctLeave();
  541. return( *this );
  542. }
  543. const CSRStr& CSRStr::operator =( LPCSTR szSrc )
  544. {
  545. TraceFunctEnter("CSRStr::operator =(LPCSTR)");
  546. SetStr( szSrc );
  547. TraceFunctLeave();
  548. return( *this );
  549. }
  550. BOOL CSRStr::ConvertA2W()
  551. {
  552. TraceFunctEnter("CSRStr::ConvertA2W");
  553. BOOL fRet = FALSE;
  554. LPCWSTR cszErr;
  555. int cch;
  556. cch = ::MultiByteToWideChar( CP_ACP, 0, m_strA, m_cchA, NULL, 0 );
  557. if ( cch == 0 )
  558. {
  559. cszErr = ::GetSysErrStr();
  560. ErrorTrace(TRACE_ID, "::MultiByteToWideChar failed - %s", cszErr);
  561. goto Exit;
  562. }
  563. m_strW = new WCHAR[cch+2];
  564. if ( m_strW == NULL )
  565. {
  566. ErrorTrace(TRACE_ID, "Insufficient memory...");
  567. goto Exit;
  568. }
  569. m_cchW = ::MultiByteToWideChar( CP_ACP, 0, m_strA, m_cchA, m_strW, cch );
  570. if ( m_cchW != cch )
  571. {
  572. ErrorTrace(TRACE_ID, "::MultiByteToWideChar returns inconsistent length - %d / %d", cch, m_cchW);
  573. delete [] m_strW;
  574. m_strW = NULL;
  575. m_cchW = 0;
  576. goto Exit;
  577. }
  578. m_strW[m_cchW] = L'\0';
  579. fRet = TRUE;
  580. Exit:
  581. TraceFunctLeave();
  582. return( fRet );
  583. }
  584. BOOL CSRStr::ConvertW2A()
  585. {
  586. TraceFunctEnter("CSRStr::ConvertW2A");
  587. BOOL fRet = FALSE;
  588. LPCWSTR cszErr;
  589. int cch;
  590. cch = ::WideCharToMultiByte( CP_ACP, 0, m_strW, m_cchW, NULL, 0, NULL, NULL );
  591. if ( cch == 0 )
  592. {
  593. cszErr = GetSysErrStr();
  594. ErrorTrace(TRACE_ID, "::WideCharToMultiByte failed - %s", cszErr);
  595. goto Exit;
  596. }
  597. m_strA = new char[cch+2];
  598. if ( m_strA == NULL )
  599. {
  600. ErrorTrace(TRACE_ID, "Insufficient memory...");
  601. goto Exit;
  602. }
  603. m_cchA = ::WideCharToMultiByte( CP_ACP, 0, m_strW, m_cchW, m_strA, cch, NULL, NULL );
  604. if ( m_cchA != cch )
  605. {
  606. ErrorTrace(TRACE_ID, "::WideCharToMultiByte returns inconsistent length - %d / %d", cch, m_cchA);
  607. delete [] m_strA;
  608. m_strA = NULL;
  609. m_cchA = 0;
  610. goto Exit;
  611. }
  612. m_strA[m_cchA] = '\0';
  613. fRet = TRUE;
  614. Exit:
  615. TraceFunctLeave();
  616. return( fRet );
  617. }
  618. // end of file