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.

804 lines
24 KiB

  1. /************************************************************************
  2. Copyright (c) 2000 - 2000 Microsoft Corporation
  3. Module Name :
  4. helpers.cpp
  5. Abstract :
  6. General helper functions.
  7. Author :
  8. Revision History :
  9. ***********************************************************************/
  10. #include "qmgrlibp.h"
  11. #include <bitsmsg.h>
  12. #include <sddl.h>
  13. #include <shlwapi.h>
  14. #include "helpers.tmh"
  15. FILETIME GetTimeAfterDelta( UINT64 uDelta )
  16. {
  17. FILETIME ftCurrentTime;
  18. GetSystemTimeAsFileTime( &ftCurrentTime );
  19. UINT64 uCurrentTime = FILETIMEToUINT64( ftCurrentTime );
  20. uCurrentTime += uDelta;
  21. return UINT64ToFILETIME( uCurrentTime );
  22. }
  23. //---------------------------------------------------------------------
  24. // QmgrFileExists
  25. // Checks if a file exists.
  26. //
  27. // Returns: TRUE if false exists, FALSE otherwise
  28. //---------------------------------------------------------------------
  29. BOOL QMgrFileExists(LPCTSTR szFile)
  30. {
  31. DWORD dwAttr = GetFileAttributes(szFile);
  32. if (dwAttr == 0xFFFFFFFF) //failed
  33. return FALSE;
  34. return (BOOL)(!(dwAttr & FILE_ATTRIBUTE_DIRECTORY));
  35. }
  36. //
  37. // Class for managing global static data that is different per installation
  38. //
  39. class GlobalInfo *g_GlobalInfo = NULL;
  40. GlobalInfo::GlobalInfo( TCHAR * QmgrDirectory,
  41. LARGE_INTEGER PerformanceCounterFrequency,
  42. HKEY QmgrRegistryRoot,
  43. UINT64 JobInactivityTimeout,
  44. UINT64 TimeQuantaLength,
  45. UINT32 DefaultNoProgressTimeout,
  46. UINT32 DefaultMinimumRetryDelay,
  47. SECURITY_DESCRIPTOR *MetadataSecurityDescriptor,
  48. DWORD MetadataSecurityDescriptorLength,
  49. SidHandle AdministratorsSid,
  50. SidHandle LocalSystemSid,
  51. SidHandle NetworkUsersSid,
  52. SidHandle AnonymousSid
  53. ) :
  54. m_QmgrDirectory( QmgrDirectory ),
  55. m_PerformanceCounterFrequency( PerformanceCounterFrequency ),
  56. m_QmgrRegistryRoot( QmgrRegistryRoot ),
  57. m_JobInactivityTimeout( JobInactivityTimeout ),
  58. m_TimeQuantaLength( TimeQuantaLength ),
  59. m_DefaultNoProgressTimeout( DefaultNoProgressTimeout ),
  60. m_DefaultMinimumRetryDelay( DefaultMinimumRetryDelay ),
  61. m_MetadataSecurityDescriptor( MetadataSecurityDescriptor ),
  62. m_MetadataSecurityDescriptorLength( MetadataSecurityDescriptorLength ),
  63. m_AdministratorsSid( AdministratorsSid ),
  64. m_LocalSystemSid( LocalSystemSid ),
  65. m_NetworkUsersSid( NetworkUsersSid ),
  66. m_AnonymousSid( AnonymousSid )
  67. {
  68. }
  69. GlobalInfo::~GlobalInfo()
  70. {
  71. delete[] (TCHAR*)m_QmgrDirectory;
  72. delete (SECURITY_DESCRIPTOR*)m_MetadataSecurityDescriptor;
  73. if ( m_QmgrRegistryRoot )
  74. CloseHandle( m_QmgrRegistryRoot );
  75. }
  76. DWORD
  77. GlobalInfo::RegGetDWORD(
  78. HKEY hKey,
  79. const TCHAR * pValue,
  80. DWORD dwDefault )
  81. {
  82. DWORD dwValue;
  83. DWORD dwType = REG_DWORD;
  84. DWORD dwSize = sizeof(dwValue);
  85. LONG lResult =
  86. RegQueryValueEx( //SEC: REVIEWED 2002-03-28
  87. hKey,
  88. pValue,
  89. NULL,
  90. &dwType,
  91. (LPBYTE)&dwValue,
  92. &dwSize );
  93. if ( ERROR_SUCCESS != lResult ||
  94. dwType != REG_DWORD ||
  95. dwSize != sizeof(dwValue)
  96. )
  97. {
  98. LogWarning( "Unable to read the registry value %!ts!, using default value of %u",
  99. pValue, dwDefault );
  100. return dwDefault;
  101. }
  102. LogInfo( "Retrieved registry value %u from key value %!ts!",
  103. dwValue, pValue );
  104. return dwValue;
  105. }
  106. SidHandle
  107. BITSAllocateAndInitializeSid(
  108. BYTE nSubAuthorityCount, // count of subauthorities
  109. DWORD dwSubAuthority0, // subauthority 0
  110. DWORD dwSubAuthority1 ) // subauthority 1
  111. {
  112. ASSERT( nSubAuthorityCount <= 2 );
  113. SID_IDENTIFIER_AUTHORITY Authority = SECURITY_NT_AUTHORITY;
  114. PSID pSid = NULL;
  115. if(! AllocateAndInitializeSid( //SEC: REVIEWED 2002-03-28
  116. &Authority,
  117. nSubAuthorityCount,
  118. dwSubAuthority0,
  119. dwSubAuthority1,
  120. 0, 0, 0, 0, 0, 0,
  121. &pSid) )
  122. {
  123. HRESULT hResult = HRESULT_FROM_WIN32(GetLastError());
  124. LogError( "AllocateAndInitializeSid failed, error %!winerr!\n" , hResult );
  125. throw ComError( hResult );
  126. }
  127. SidHandle NewSid( DuplicateSid( pSid ) );
  128. FreeSid( pSid );
  129. pSid = NULL;
  130. if ( !NewSid.get())
  131. {
  132. LogError( "Unable to duplicate sid, error %!winerr!\n" , E_OUTOFMEMORY );
  133. throw ComError( E_OUTOFMEMORY );
  134. }
  135. return NewSid;
  136. }
  137. StringHandle
  138. BITSSHGetFolderPath(
  139. HWND hwndOwner,
  140. int nFolder,
  141. HANDLE hToken,
  142. DWORD dwFlags )
  143. {
  144. auto_ptr<WCHAR> Folder( new WCHAR[ MAX_PATH ] );
  145. HRESULT hResult =
  146. SHGetFolderPath(
  147. hwndOwner,
  148. nFolder,
  149. hToken,
  150. dwFlags,
  151. Folder.get() );
  152. if (FAILED(hResult))
  153. {
  154. LogError( "SHGetFolderPathFailed, error %!winerr!", hResult );
  155. throw ComError( hResult );
  156. }
  157. return StringHandle( Folder.get() );
  158. }
  159. HRESULT GlobalInfo::Init()
  160. /*
  161. Initialize the global info for BITS.
  162. */
  163. {
  164. GlobalInfo *pGlobalInfo = NULL;
  165. HKEY hQmgrKey = NULL;
  166. HKEY hQmgrPolicyKey = NULL;
  167. PACL pDacl = NULL;
  168. LogInfo( "Starting init of global info\n" );
  169. try
  170. {
  171. DWORD dwResult;
  172. HRESULT hResult = E_FAIL;
  173. DWORD dwReturnLength;
  174. LARGE_INTEGER PerformanceCounterFrequency;
  175. BOOL bResult = QueryPerformanceFrequency( &PerformanceCounterFrequency );
  176. if ( !bResult )
  177. throw ComError( E_FAIL );
  178. SidHandle AdministratorsSid =
  179. BITSAllocateAndInitializeSid(
  180. 2,
  181. SECURITY_BUILTIN_DOMAIN_RID,
  182. DOMAIN_ALIAS_RID_ADMINS );
  183. SidHandle LocalSystemSid =
  184. BITSAllocateAndInitializeSid(
  185. 1,
  186. SECURITY_LOCAL_SYSTEM_RID, 0 );
  187. SidHandle NetworkUsersSid =
  188. BITSAllocateAndInitializeSid(
  189. 1,
  190. SECURITY_NETWORK_RID, 0);
  191. SidHandle AnonymousSid =
  192. BITSAllocateAndInitializeSid(
  193. 1,
  194. SECURITY_ANONYMOUS_LOGON_RID, 0);
  195. // initialize the metadata's security descriptor.
  196. auto_ptr<char> TempSDDataPtr( new char[SECURITY_DESCRIPTOR_MIN_LENGTH] );
  197. PSECURITY_DESCRIPTOR pTempSD = (PSECURITY_DESCRIPTOR)TempSDDataPtr.get();
  198. InitializeSecurityDescriptor(pTempSD, SECURITY_DESCRIPTOR_REVISION); //SEC: REVIEWED 2002-03-28
  199. auto_ptr<EXPLICIT_ACCESS> ExplicitAccessPtr( new EXPLICIT_ACCESS[2] );
  200. EXPLICIT_ACCESS *ExplicitAccess = ExplicitAccessPtr.get();
  201. memset( ExplicitAccess, 0, sizeof(EXPLICIT_ACCESS) * 2); //SEC: REVIEWED 2002-03-28
  202. ExplicitAccess[0].grfAccessPermissions = GENERIC_ALL;
  203. ExplicitAccess[0].grfAccessMode = SET_ACCESS;
  204. ExplicitAccess[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  205. ExplicitAccess[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  206. ExplicitAccess[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  207. ExplicitAccess[0].Trustee.ptstrName = (LPTSTR) AdministratorsSid.get();
  208. ExplicitAccess[1].grfAccessPermissions = GENERIC_ALL;
  209. ExplicitAccess[1].grfAccessMode = SET_ACCESS;
  210. ExplicitAccess[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
  211. ExplicitAccess[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  212. ExplicitAccess[1].Trustee.TrusteeType = TRUSTEE_IS_USER;
  213. ExplicitAccess[1].Trustee.ptstrName = (LPTSTR) LocalSystemSid.get();
  214. dwResult = SetEntriesInAcl( //SEC: REVIEWED 2002-03-28
  215. 2,
  216. ExplicitAccess,
  217. NULL,
  218. &pDacl );
  219. if ( ERROR_SUCCESS != dwResult )
  220. {
  221. hResult = HRESULT_FROM_WIN32( dwResult );
  222. LogError( "SetEntiesInAcl, error %!winerr!\n", hResult );
  223. throw ComError( hResult );
  224. }
  225. if (!SetSecurityDescriptorDacl( //SEC: REVIEWED 2002-03-28
  226. pTempSD,
  227. TRUE, // fDaclPresent flag
  228. pDacl,
  229. FALSE)) // not a default DACL
  230. {
  231. hResult = HRESULT_FROM_WIN32( GetLastError() );
  232. LogError( "SetSecurityDescriptorDacl, error %!winerr!", hResult );
  233. throw ComError( hResult );
  234. }
  235. DWORD dwRequiredSecurityDescriptorLength = 0;
  236. MakeSelfRelativeSD( pTempSD, NULL, &dwRequiredSecurityDescriptorLength );
  237. auto_ptr<SECURITY_DESCRIPTOR> pMetadataSecurityDescriptor(
  238. (SECURITY_DESCRIPTOR*)new char[dwRequiredSecurityDescriptorLength] );
  239. if (!pMetadataSecurityDescriptor.get())
  240. {
  241. throw ComError( E_OUTOFMEMORY );
  242. }
  243. if (!MakeSelfRelativeSD( pTempSD, pMetadataSecurityDescriptor.get(), &dwRequiredSecurityDescriptorLength ) )
  244. {
  245. hResult = HRESULT_FROM_WIN32(GetLastError());
  246. LogError( "MakeSelfRelativeSD, error %!winerr!", hResult );
  247. throw ComError( hResult );
  248. }
  249. LocalFree( pDacl );
  250. pDacl = NULL;
  251. SECURITY_ATTRIBUTES MetadataSecurityAttributes;
  252. MetadataSecurityAttributes.nLength = sizeof(MetadataSecurityAttributes);
  253. MetadataSecurityAttributes.lpSecurityDescriptor = pMetadataSecurityDescriptor.get();
  254. MetadataSecurityAttributes.bInheritHandle = FALSE;
  255. // Build path where the metadata will be stored.
  256. StringHandle AllUsersDirectory =
  257. BITSSHGetFolderPath(
  258. NULL,
  259. CSIDL_COMMON_APPDATA,
  260. NULL,
  261. SHGFP_TYPE_CURRENT );
  262. size_t Length = lstrlen( AllUsersDirectory ) + lstrlen(C_QMGR_DIRECTORY) + 1; //SEC: REVIEWED 2002-03-28
  263. auto_ptr<TCHAR> QmgrDirectory( new TCHAR[ Length ] );
  264. // Create the Application Data\Microsoft\Network directory if needed.
  265. // Its access permissions should be inherited from the parent.
  266. //
  267. THROW_HRESULT( StringCchCopy( QmgrDirectory.get(), Length, AllUsersDirectory ));
  268. THROW_HRESULT( StringCchCat( QmgrDirectory.get(), Length, C_QMGR_PARENT_DIRECTORY ));
  269. dwResult = GetFileAttributes( QmgrDirectory.get() );
  270. if ( (-1 == dwResult) || !(dwResult & FILE_ATTRIBUTE_DIRECTORY))
  271. {
  272. LogError( "parent directory doesn't exist, attempt to create %!ts!.\n", QmgrDirectory.get() );
  273. bResult = CreateDirectory(QmgrDirectory.get(), NULL ); //SEC: REVIEWED 2002-08-16
  274. if ( !bResult )
  275. {
  276. hResult = HRESULT_FROM_WIN32( GetLastError() );
  277. LogError( "Unable to create parent directory, error %!winerr!\n", hResult );
  278. throw ComError( hResult );
  279. }
  280. }
  281. // Create the BITS directory if needed.
  282. // Its permissions should be restrictive because we don't want non-admins to be able to read our files.
  283. //
  284. THROW_HRESULT( StringCchCopy( QmgrDirectory.get(), Length, AllUsersDirectory ));
  285. THROW_HRESULT( StringCchCat( QmgrDirectory.get(), Length, C_QMGR_DIRECTORY ));
  286. dwResult = GetFileAttributes( QmgrDirectory.get() );
  287. if ( (-1 == dwResult) || !(dwResult & FILE_ATTRIBUTE_DIRECTORY))
  288. {
  289. LogError( "BITS directory doesn't exist, attempt to create %!ts!.\n", QmgrDirectory.get() );
  290. bResult = CreateDirectory(QmgrDirectory.get(), &MetadataSecurityAttributes); //SEC: REVIEWED 2002-03-28
  291. if ( !bResult )
  292. {
  293. hResult = HRESULT_FROM_WIN32( GetLastError() );
  294. LogError( "Unable to create BITS directory, error %!winerr!\n", hResult );
  295. throw ComError( hResult );
  296. }
  297. }
  298. // Open the main policy registry key
  299. dwResult =
  300. (DWORD)RegOpenKey(
  301. HKEY_LOCAL_MACHINE,
  302. C_QMGR_POLICY_REG_KEY,
  303. &hQmgrPolicyKey);
  304. if ( ERROR_SUCCESS != dwResult )
  305. {
  306. LogWarning("Unable to open the main policy registry key\n");
  307. }
  308. // Open the main qmgr registry key
  309. dwResult =
  310. (DWORD)RegCreateKeyEx(
  311. HKEY_LOCAL_MACHINE, // root key
  312. C_QMGR_REG_KEY, // subkey
  313. 0, // reserved
  314. NULL, // class name
  315. REG_OPTION_NON_VOLATILE, // option
  316. KEY_ALL_ACCESS, // security // SEC: REVIEWED 2002-03-28
  317. &MetadataSecurityAttributes,// security attribute
  318. &hQmgrKey,
  319. NULL);
  320. if ( ERROR_SUCCESS != dwResult )
  321. {
  322. hResult = HRESULT_FROM_WIN32( dwResult );
  323. LogError( "Unable to open main BITS key, error %!winerr!\n", hResult );
  324. throw ComError( hResult );
  325. }
  326. UINT64 JobInactivityTimeout;
  327. // Get the inactivity timeout value for job;
  328. {
  329. DWORD dwValue;
  330. DWORD dwType = REG_DWORD;
  331. DWORD dwSize = sizeof(dwValue);
  332. LONG lResult;
  333. if ( hQmgrPolicyKey )
  334. {
  335. lResult =
  336. RegQueryValueEx( //SEC: REVIEWED 2002-03-28
  337. hQmgrPolicyKey,
  338. C_QMGR_JOB_INACTIVITY_TIMEOUT,
  339. NULL,
  340. &dwType,
  341. (LPBYTE)&dwValue,
  342. &dwSize );
  343. }
  344. if ( !hQmgrPolicyKey ||
  345. ERROR_SUCCESS != lResult ||
  346. dwType != REG_DWORD ||
  347. dwSize != sizeof(dwValue)
  348. )
  349. {
  350. JobInactivityTimeout =
  351. RegGetDWORD( hQmgrKey, C_QMGR_JOB_INACTIVITY_TIMEOUT, C_QMGR_JOB_INACTIVITY_TIMEOUT_DEFAULT);
  352. JobInactivityTimeout *= NanoSec100PerSec;
  353. }
  354. else
  355. {
  356. LogInfo("Retrieved job inactivity timeout of %u days from policy", dwValue );
  357. JobInactivityTimeout = dwValue * NanoSec100PerSec * 60/*secs per min*/ * 60/*mins per hour*/ * 24 /* hours per day*/;
  358. }
  359. }
  360. UINT64 TimeQuantaLength =
  361. RegGetDWORD( hQmgrKey, C_QMGR_TIME_QUANTA_LENGTH, C_QMGR_TIME_QUANTA_LENGTH_DEFAULT );
  362. TimeQuantaLength *= NanoSec100PerSec;
  363. UINT32 DefaultNoProgressTimeout = // global data is in seconds.
  364. RegGetDWORD( hQmgrKey, C_QMGR_NO_PROGRESS_TIMEOUT, C_QMGR_NO_PROGRESS_TIMEOUT_DEFAULT );
  365. UINT32 DefaultMinimumRetryDelay = // global data is in seconds
  366. RegGetDWORD( hQmgrKey, C_QMGR_MINIMUM_RETRY_DELAY, C_QMGR_MINIMUM_RETRY_DELAY_DEFAULT );
  367. pGlobalInfo =
  368. new GlobalInfo( QmgrDirectory.get(),
  369. PerformanceCounterFrequency,
  370. hQmgrKey,
  371. JobInactivityTimeout,
  372. TimeQuantaLength,
  373. DefaultNoProgressTimeout,
  374. DefaultMinimumRetryDelay,
  375. pMetadataSecurityDescriptor.get(),
  376. dwRequiredSecurityDescriptorLength,
  377. AdministratorsSid,
  378. LocalSystemSid,
  379. NetworkUsersSid,
  380. AnonymousSid
  381. );
  382. if ( !pGlobalInfo )
  383. throw ComError( E_OUTOFMEMORY );
  384. QmgrDirectory.release();
  385. pMetadataSecurityDescriptor.release();
  386. if ( hQmgrPolicyKey )
  387. CloseHandle( hQmgrPolicyKey );
  388. }
  389. catch( ComError Error )
  390. {
  391. LogError( "An exception occured creating global info, error %!winerr!", Error.Error() );
  392. if ( hQmgrKey )
  393. CloseHandle( hQmgrKey );
  394. hQmgrKey = NULL;
  395. if ( hQmgrPolicyKey )
  396. CloseHandle( hQmgrPolicyKey );
  397. hQmgrPolicyKey = NULL;
  398. // LocalFree has if guard
  399. LocalFree( pDacl );
  400. return Error.Error();
  401. }
  402. LogInfo( "Finished init of global info" );
  403. g_GlobalInfo = pGlobalInfo;
  404. return S_OK;
  405. }
  406. HRESULT GlobalInfo::Uninit()
  407. {
  408. delete g_GlobalInfo;
  409. g_GlobalInfo = NULL;
  410. return S_OK;
  411. }
  412. LONG
  413. ExternalFuncExceptionFilter(
  414. struct _EXCEPTION_POINTERS *ExceptionInfo
  415. )
  416. {
  417. // This function is called by the exception filter that wraps external functions.
  418. // The purpose is to treat unhandled exceptions as unhandled instead of propagating
  419. // across the network
  420. // If this exception is a MSVCRT exception, bash the exception code
  421. // so that MSVCRT won't call ExitProcess.
  422. if ( ExceptionInfo &&
  423. ExceptionInfo->ExceptionRecord &&
  424. ('msc' | 0xE0000000) == ExceptionInfo->ExceptionRecord->ExceptionCode )
  425. {
  426. ExceptionInfo->ExceptionRecord->ExceptionCode = ('BIT' | 0xE0000000);
  427. }
  428. LONG Result = UnhandledExceptionFilter( ExceptionInfo );
  429. if ( EXCEPTION_CONTINUE_SEARCH == Result )
  430. {
  431. // Need to act like the dispatcher. Call kernel again specifying second change semantics
  432. NtRaiseException( ExceptionInfo->ExceptionRecord, ExceptionInfo->ContextRecord, FALSE );
  433. }
  434. // exception handler returns RPC_E_SERVERFAULT
  435. return EXCEPTION_EXECUTE_HANDLER;
  436. }
  437. SidHandle & SidHandle::operator=( const SidHandle & r )
  438. {
  439. if (m_pValue == r.m_pValue )
  440. {
  441. return *this;
  442. }
  443. if (InterlockedDecrement(m_pRefs) == 0)
  444. {
  445. delete m_pRefs;
  446. delete m_pValue;
  447. }
  448. m_pValue = r.m_pValue;
  449. m_pRefs = r.m_pRefs;
  450. InterlockedIncrement(m_pRefs);
  451. return *this;
  452. }
  453. StringHandle::StringData StringHandle::s_EmptyString =
  454. {
  455. 0, 1, { L'\0' } // Initialize with 1 ref so it is never deleted
  456. };
  457. bool
  458. CSidSorter::operator()(
  459. const SidHandle & handle1,
  460. const SidHandle & handle2
  461. ) const
  462. {
  463. const PSID psid1 = handle1.get();
  464. const PSID psid2 = handle2.get();
  465. if ( !psid1 || !psid2 )
  466. return (INT_PTR)psid1 < (INT_PTR)psid2;
  467. if (*GetSidSubAuthorityCount( psid1 ) < *GetSidSubAuthorityCount( psid2 ))
  468. {
  469. return true;
  470. }
  471. // at this point, we known psd1 is >= psd2. // Stop if psid1 is
  472. // longer so that the preceding for loop doesn't overstep the sid
  473. // array on psd2.
  474. if ( *GetSidSubAuthorityCount( psid1 ) > *GetSidSubAuthorityCount( psid2 ) )
  475. return false;
  476. // arrays have equal length
  477. for (UCHAR i=0; i < *GetSidSubAuthorityCount( psid1 ); ++i)
  478. {
  479. if (*GetSidSubAuthority( psid1, i ) < *GetSidSubAuthority( psid2, i ))
  480. return true; // sid1 is less then sid2
  481. else if ( *GetSidSubAuthority( psid1, i ) > *GetSidSubAuthority( psid2, i ) )
  482. return false; // sid1 is greater then sid2
  483. // subauthorities are the same, move on to the next subauthority
  484. }
  485. // arrays are identical
  486. return false;
  487. }
  488. //------------------------------------------------------------------------
  489. PSID DuplicateSid( PSID _Sid )
  490. /*++
  491. Routine Description:
  492. Clones a SID. The new SID is allocated using the global operator new.
  493. At entry:
  494. _Sid is the SID to clone.
  495. At exit:
  496. the return is NULL if an error occurs, otherwise a pointer to the new SID.
  497. --*/
  498. {
  499. DWORD Length = GetLengthSid( _Sid );
  500. SID * psid;
  501. try
  502. {
  503. psid = (SID *) new char[Length];
  504. }
  505. catch( ComError Error )
  506. {
  507. return NULL;
  508. }
  509. if (!CopySid( Length, psid, _Sid )) // SEC: REVIEWED 2002-03-28
  510. {
  511. delete[] psid;
  512. return NULL;
  513. }
  514. return psid;
  515. }
  516. LPCWSTR
  517. TruncateString( LPCWSTR String, SIZE_T MaxLength, auto_ptr<WCHAR> & AutoPointer )
  518. {
  519. if ( wcslen( String ) <= MaxLength ) // SEC: REVIEWED 2002-03-28
  520. return String;
  521. AutoPointer = auto_ptr<WCHAR>( new WCHAR[ MaxLength + 1 ] );
  522. wcsncpy( AutoPointer.get(), String, MaxLength ); // SEC: REVIEWED 2002-03-28
  523. AutoPointer.get()[ MaxLength ] = L'\0';
  524. return AutoPointer.get();
  525. }
  526. PLATFORM_PRODUCT_VERSION g_PlatformVersion;
  527. DWORD g_PlatformMajorVersion;
  528. DWORD g_PlatformMinorVersion;
  529. bool bIsWin9x;
  530. BOOL DetectProductVersion()
  531. {
  532. OSVERSIONINFO VersionInfo;
  533. VersionInfo.dwOSVersionInfoSize = sizeof( VersionInfo );
  534. if ( !GetVersionEx( &VersionInfo ) )
  535. return FALSE;
  536. g_PlatformMajorVersion = VersionInfo.dwMajorVersion;
  537. g_PlatformMinorVersion = VersionInfo.dwMinorVersion;
  538. switch( VersionInfo.dwPlatformId )
  539. {
  540. case VER_PLATFORM_WIN32_WINDOWS:
  541. g_PlatformVersion = ( VersionInfo.dwMajorVersion > 0 ) ?
  542. WIN98_PLATFORM : WIN95_PLATFORM;
  543. bIsWin9x = true;
  544. return TRUE;
  545. case VER_PLATFORM_WIN32_NT:
  546. bIsWin9x = false;
  547. if ( VersionInfo.dwMajorVersion < 5 )
  548. return FALSE;
  549. if ( VersionInfo.dwMajorVersion > 5 )
  550. {
  551. g_PlatformVersion = WINDOWSXP_PLATFORM;
  552. return TRUE;
  553. }
  554. g_PlatformVersion = ( VersionInfo.dwMinorVersion > 0 ) ?
  555. WINDOWSXP_PLATFORM : WINDOWS2000_PLATFORM;
  556. return TRUE;
  557. default:
  558. return FALSE;
  559. }
  560. }
  561. StringHandle
  562. CombineUrl(
  563. LPCWSTR BaseUrl,
  564. LPCWSTR RelativeUrl,
  565. DWORD Flags
  566. )
  567. {
  568. DWORD Length = 0;
  569. HRESULT hr;
  570. hr = UrlCombine( BaseUrl,
  571. RelativeUrl,
  572. 0,
  573. &Length,
  574. Flags
  575. );
  576. if (hr != E_POINTER)
  577. {
  578. ASSERT( FAILED(hr) );
  579. throw ComError( hr );
  580. }
  581. auto_ptr<WCHAR> AbsoluteUrl ( new WCHAR[ Length ] );
  582. THROW_HRESULT( UrlCombine( BaseUrl,
  583. RelativeUrl,
  584. AbsoluteUrl.get(),
  585. &Length,
  586. Flags
  587. ));
  588. //
  589. // The string handle constructor clones the auto_ptr.
  590. //
  591. return AbsoluteUrl.get();
  592. }
  593. bool IsAnyDebuggerPresent()
  594. {
  595. if (IsDebuggerPresent())
  596. {
  597. return true;
  598. }
  599. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo = { 0 };
  600. NtQuerySystemInformation(
  601. SystemKernelDebuggerInformation,
  602. &KdInfo,
  603. sizeof(KdInfo),
  604. NULL);
  605. if (KdInfo.KernelDebuggerEnabled)
  606. {
  607. return true;
  608. }
  609. return false;
  610. }
  611. LPWSTR MidlCopyString( LPCWSTR source, size_t Length )
  612. {
  613. if (Length == -1)
  614. {
  615. Length = 1+wcslen( source ); // SEC: REVIEWED 2002-03-28
  616. }
  617. LPWSTR copy = reinterpret_cast<LPWSTR>( CoTaskMemAlloc( Length * sizeof( wchar_t )));
  618. if (!copy)
  619. {
  620. return NULL;
  621. }
  622. if (FAILED(StringCchCopy( copy, Length, source )))
  623. {
  624. CoTaskMemFree( copy );
  625. return NULL;
  626. }
  627. return copy;
  628. }
  629. LPWSTR CopyString( LPCWSTR source, size_t Length )
  630. {
  631. if (Length == -1)
  632. {
  633. Length = 1+wcslen( source ); // SEC: REVIEWED 2002-03-28
  634. }
  635. CAutoString copy( new wchar_t[ Length ]);
  636. THROW_HRESULT( StringCchCopy( copy.get(), Length, source ));
  637. return copy.release();
  638. }