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.

913 lines
23 KiB

  1. #ifndef _WIN32_WINNT
  2. #define _WIN32_WINNT 0x0500
  3. #endif
  4. #include <windows.h>
  5. #include <string.h>
  6. #include <tchar.h>
  7. #include <assert.h>
  8. #include <time.h>
  9. #include <msi.h>
  10. #include <msiquery.h>
  11. #include "dbcaum.h"
  12. #include "..\..\shared\apppool.h"
  13. #include "..\..\shared\common.h"
  14. #define DIM(x) (sizeof x)/(sizeof x[0])
  15. #define ROOT_REGPATH "Software\\Microsoft\\UDDI"
  16. #define INSTROOT_REGPATH "InstallRoot"
  17. #define RESROOT_REGPATH "ResourceRoot"
  18. #define BOOTSTRAP_DIR "bootstrap"
  19. //
  20. // Forward declarations.
  21. //
  22. static int AddSharedDllRef( LPCSTR szFullPath );
  23. static int ReleaseSharedDll ( LPCSTR szFullPath );
  24. static bool AddAccessRights( TCHAR *lpszFileName, TCHAR *szUserName, DWORD dwAccessMask );
  25. static LONG GetServiceStartupAccount( const TCHAR *pwszServiceName, TCHAR *pwszServiceAccount, int iLen );
  26. static void GetUDDIDBServiceName( const TCHAR *pwszInstanceName, TCHAR *pwszServiceName, int iLen );
  27. static void AddAccessRightsVerbose( TCHAR *pwszFileName, TCHAR *pwszUserName, DWORD dwMask );
  28. //--------------------------------------------------------------------------
  29. BOOL APIENTRY DllMain( HANDLE hModule,
  30. DWORD ul_reason_for_call,
  31. LPVOID lpReserved
  32. )
  33. {
  34. return TRUE;
  35. }
  36. //--------------------------------------------------------------------------
  37. //
  38. // Install custom action used by the DB component installer to recycle the app pool
  39. // This function is exported
  40. //
  41. UINT _stdcall Install( MSIHANDLE hInstall )
  42. {
  43. ENTER();
  44. //
  45. // stop and start the app pool
  46. //
  47. CUDDIAppPool apppool;
  48. apppool.Recycle();
  49. return ERROR_SUCCESS;
  50. }
  51. UINT __stdcall InstallTaxonomy( LPCSTR szSrcResource, LPCSTR szDestResource )
  52. {
  53. //
  54. // Now we parse the path out of the Source and copy the Destination right by it
  55. //
  56. CHAR szPath[ _MAX_PATH + 1 ] = {0};
  57. PCHAR pSlash = strrchr( szSrcResource, '\\' );
  58. if ( pSlash )
  59. {
  60. strncpy( szPath, szSrcResource, pSlash - szSrcResource + 1 );
  61. int iLen = _MAX_PATH - strlen( szPath );
  62. strncat( szPath, szDestResource, iLen );
  63. }
  64. else
  65. {
  66. strncpy( szPath, szDestResource, _MAX_PATH + 1 );
  67. }
  68. szPath[ _MAX_PATH ] = 0;
  69. #if defined( DBG ) || defined( _DEBUG )
  70. TCHAR wszPath[ _MAX_PATH + 1 ];
  71. int iwszCount = _MAX_PATH;
  72. int ipszCount = strlen( szPath );
  73. memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
  74. ::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
  75. Log( _T( "Installing taxonomy file: %s." ), wszPath );
  76. #endif
  77. if ( !CopyFileA( szSrcResource, szPath, FALSE ) )
  78. return ERROR_INSTALL_FAILURE;
  79. DeleteFileA( szSrcResource );
  80. return ERROR_SUCCESS;
  81. }
  82. UINT __stdcall InstallResource( LPCSTR szCultureID, LPCSTR szDefCulture,
  83. LPCSTR szSrcResource, LPCSTR szDestResource )
  84. {
  85. //
  86. // Get the properties and then do the file manipulation
  87. //
  88. if ( _stricmp( szCultureID, szDefCulture ) )
  89. {
  90. //
  91. // Now we parse the path out of the Source and copy the Destination right by it
  92. //
  93. CHAR szPath[ _MAX_PATH + 1 ] = {0};
  94. PCHAR pSlash = strrchr( szSrcResource, '\\' );
  95. if ( pSlash )
  96. {
  97. strncpy( szPath, szSrcResource, pSlash - szSrcResource + 1 );
  98. int iLen = _MAX_PATH - strlen( szPath );
  99. strncat( szPath, szDestResource, iLen );
  100. }
  101. else
  102. {
  103. strncpy( szPath, szDestResource, _MAX_PATH + 1 );
  104. }
  105. szPath[ _MAX_PATH ] = 0;
  106. #if defined( DBG ) || defined( _DEBUG )
  107. TCHAR wszPath[ _MAX_PATH + 1 ];
  108. int iwszCount = _MAX_PATH;
  109. int ipszCount = strlen( szPath );
  110. memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
  111. ::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
  112. Log( _T( "Installing resource file: %s." ), wszPath );
  113. #endif
  114. if ( !CopyFileA( szSrcResource, szPath, FALSE ) )
  115. return ERROR_INSTALL_FAILURE;
  116. AddSharedDllRef( szPath );
  117. }
  118. DeleteFileA( szSrcResource );
  119. return ERROR_SUCCESS;
  120. }
  121. UINT __stdcall RemoveResource( LPCSTR szDestResource )
  122. {
  123. HKEY hUddiKey = NULL;
  124. try
  125. {
  126. CHAR szPath[ _MAX_PATH + 1 ] = {0};
  127. DWORD cbPath = DIM( szPath );
  128. size_t iLen = 0;
  129. LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, ROOT_REGPATH, &hUddiKey );
  130. if ( iRes != ERROR_SUCCESS )
  131. return ERROR_INSTALL_FAILURE;
  132. iRes = RegQueryValueExA( hUddiKey, RESROOT_REGPATH, NULL, NULL, (LPBYTE)szPath, &cbPath );
  133. if ( iRes != ERROR_SUCCESS )
  134. return ERROR_INSTALL_FAILURE;
  135. RegCloseKey( hUddiKey );
  136. hUddiKey = NULL;
  137. iLen = strlen( szPath );
  138. if ( ( iLen < _MAX_PATH ) && ( szPath[ iLen - 1 ] != '\\' ) )
  139. {
  140. strncat( szPath, "\\", 2 );
  141. }
  142. iLen = _MAX_PATH - strlen( szPath );
  143. strncat( szPath, szDestResource, iLen );
  144. szPath[ _MAX_PATH ] = 0;
  145. #if defined( DBG ) || defined( _DEBUG )
  146. TCHAR wszPath[ _MAX_PATH + 1 ];
  147. int iwszCount = _MAX_PATH;
  148. int ipszCount = strlen( szPath );
  149. memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
  150. ::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
  151. Log( _T( "Removing resource file: %s." ), wszPath );
  152. #endif
  153. if ( ReleaseSharedDll( szPath ) == 0 )
  154. DeleteFileA( szPath );
  155. }
  156. catch (...)
  157. {
  158. if ( hUddiKey )
  159. RegCloseKey( hUddiKey );
  160. return ERROR_INSTALL_FAILURE;
  161. }
  162. return ERROR_SUCCESS;
  163. }
  164. UINT __stdcall RemoveTaxonomy( LPCSTR szDestResource )
  165. {
  166. HKEY hUddiKey = NULL;
  167. try
  168. {
  169. CHAR szPath[ _MAX_PATH + 1 ] = {0};
  170. DWORD cbPath = DIM( szPath );
  171. size_t iLen = 0;
  172. LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, ROOT_REGPATH, &hUddiKey );
  173. if ( iRes != ERROR_SUCCESS )
  174. return ERROR_INSTALL_FAILURE;
  175. iRes = RegQueryValueExA( hUddiKey, INSTROOT_REGPATH, NULL, NULL, (LPBYTE)szPath, &cbPath );
  176. if ( iRes != ERROR_SUCCESS )
  177. return ERROR_INSTALL_FAILURE;
  178. RegCloseKey( hUddiKey );
  179. hUddiKey = NULL;
  180. iLen = strlen( szPath );
  181. if ( ( iLen < _MAX_PATH ) && ( szPath[ iLen - 1 ] != '\\' ) )
  182. {
  183. strncat( szPath, "\\", 2 );
  184. }
  185. //
  186. // Append \bootstrap\<resource filename> to InstallRoot
  187. //
  188. iLen = _MAX_PATH - strlen( szPath );
  189. strncat( szPath, BOOTSTRAP_DIR, iLen );
  190. strncat( szPath, "\\", 2 );
  191. iLen = _MAX_PATH - strlen( szPath );
  192. strncat( szPath, szDestResource, iLen );
  193. szPath[ _MAX_PATH ] = 0;
  194. #if defined( DBG ) || defined( _DEBUG )
  195. TCHAR wszPath[ _MAX_PATH + 1 ];
  196. int iwszCount = _MAX_PATH;
  197. int ipszCount = strlen( szPath );
  198. memset( wszPath, 0, _MAX_PATH * sizeof( TCHAR ) );
  199. ::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, szPath, ipszCount, wszPath, iwszCount );
  200. Log( _T( "Removing taxonomy file: %s." ), wszPath );
  201. #endif
  202. DeleteFileA( szPath );
  203. }
  204. catch (...)
  205. {
  206. if ( hUddiKey )
  207. RegCloseKey( hUddiKey );
  208. return ERROR_INSTALL_FAILURE;
  209. }
  210. return ERROR_SUCCESS;
  211. }
  212. UINT __stdcall GrantExecutionRights( LPCSTR pszInstanceNameOnly )
  213. {
  214. ENTER();
  215. TCHAR wszInstanceName[ 256 ];
  216. int iwszCount = 256;
  217. int ipszCount = strlen( pszInstanceNameOnly );
  218. memset( wszInstanceName, 0, 256 * sizeof( TCHAR ) );
  219. ::MultiByteToWideChar( CP_THREAD_ACP, MB_ERR_INVALID_CHARS, pszInstanceNameOnly, ipszCount, wszInstanceName, iwszCount );
  220. Log( _T( "Instance Name only = %s" ), wszInstanceName );
  221. TCHAR wszServiceName[ 128 ];
  222. GetUDDIDBServiceName( wszInstanceName, wszServiceName, 128 );
  223. TCHAR wszServiceAccount[ 128 ];
  224. GetServiceStartupAccount( wszServiceName, wszServiceAccount, 128 );
  225. //
  226. // Get the UDDI installation point. ie, C:\Inetpub\uddi\
  227. //
  228. HKEY hKey = NULL;
  229. LONG lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\Microsoft\\UDDI\\Setup\\DBServer" ), 0, KEY_QUERY_VALUE, &hKey );
  230. if( ERROR_SUCCESS != lRet )
  231. {
  232. Log( _T( "Call to RegOpenKeyEx failed." ) );
  233. return ERROR_SUCCESS;
  234. }
  235. DWORD dwType = 0;
  236. TCHAR wszUDDIRoot[ _MAX_PATH ];
  237. DWORD dwSize = _MAX_PATH * sizeof( TCHAR );
  238. memset( wszUDDIRoot, 0, dwSize );
  239. lRet = RegQueryValueEx( hKey, _T( "TargetDir" ), NULL, &dwType, (LPBYTE)wszUDDIRoot, &dwSize );
  240. RegCloseKey( hKey );
  241. if( ERROR_SUCCESS != lRet )
  242. {
  243. Log( _T( "Call to RegQueryValueEx failed." ) );
  244. return ERROR_SUCCESS;
  245. }
  246. //
  247. // Build the full path to the 3 files whose ACLs are being modified.
  248. //
  249. dwSize = _MAX_PATH + _MAX_FNAME;
  250. TCHAR wszResetKeyExe[ _MAX_PATH + _MAX_FNAME ];
  251. TCHAR wszRecalcStatsExe[ _MAX_PATH + _MAX_FNAME ];
  252. TCHAR wszXPDLL[ _MAX_PATH + _MAX_FNAME ];
  253. memset( wszResetKeyExe, 0, dwSize * sizeof( TCHAR ) );
  254. memset( wszRecalcStatsExe, 0, dwSize * sizeof( TCHAR ) ) ;
  255. memset( wszXPDLL, 0, dwSize * sizeof( TCHAR ) ) ;
  256. _tcscat( wszResetKeyExe, wszUDDIRoot );
  257. _tcscat( wszResetKeyExe, _T( "bin\\resetkey.exe" ) );
  258. _tcscat( wszRecalcStatsExe, wszUDDIRoot );
  259. _tcscat( wszRecalcStatsExe, _T( "bin\\recalcstats.exe" ) );
  260. _tcscat( wszXPDLL, wszUDDIRoot );
  261. _tcscat( wszXPDLL, _T( "bin\\uddi.xp.dll" ) );
  262. //
  263. // If the service startup account is a local account, it will be prefixed
  264. // with ".\" For example: ".\Administrator".
  265. //
  266. // For some reason, LookupAccountName (which we rely on just below) wants
  267. // local accounts not to be prefixed with ".\".
  268. //
  269. TCHAR wszAccount[ 256 ];
  270. memset( wszAccount, 0, 256 * sizeof( TCHAR ) );
  271. if( 0 == _tcsnicmp( _T( ".\\" ), wszServiceAccount, 2 ) )
  272. {
  273. _tcsncpy( wszAccount, &wszServiceAccount[ 2 ], _tcslen( wszServiceAccount ) - 2 );
  274. }
  275. else
  276. {
  277. _tcsncpy( wszAccount, wszServiceAccount, _tcslen( wszServiceAccount ) );
  278. }
  279. Log( _T( "Account we will attempt to grant execute privilege = %s." ), wszAccount );
  280. //
  281. // We add an "execute" ACE to the ACL only if:
  282. //
  283. // 1. There is some content in the wszAccount variable.
  284. // 2. The content is not "LocalSystem". We don't need to add an ACE if this is the case.
  285. //
  286. if( ( 0 != _tcslen( wszAccount ) ) && ( 0 != _tcsicmp( wszAccount, _T( "LocalSystem" ) ) ) )
  287. {
  288. DWORD dwAccessMask = GENERIC_EXECUTE;
  289. AddAccessRightsVerbose( wszResetKeyExe, wszAccount, dwAccessMask );
  290. AddAccessRightsVerbose( wszRecalcStatsExe, wszAccount, dwAccessMask );
  291. AddAccessRightsVerbose( wszXPDLL, wszAccount, dwAccessMask );
  292. }
  293. return ERROR_SUCCESS;
  294. }
  295. //*************************************************************************************
  296. // Helper functions. Manage the Shared Dll counters
  297. //
  298. int AddSharedDllRef( LPCSTR szFullPath )
  299. {
  300. LPCSTR szRegPath = "Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs";
  301. HKEY hReg = NULL;
  302. DWORD dwCount = 0;
  303. if ( IsBadStringPtrA( szFullPath, MAX_PATH ) )
  304. return E_INVALIDARG;
  305. try
  306. {
  307. DWORD cbData = sizeof dwCount;
  308. LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, szRegPath, &hReg );
  309. if ( iRes != ERROR_SUCCESS )
  310. return iRes;
  311. iRes = RegQueryValueExA( hReg, szFullPath, NULL, NULL, (LPBYTE)&dwCount, &cbData );
  312. if ( iRes != ERROR_SUCCESS && iRes != ERROR_FILE_NOT_FOUND && iRes != ERROR_PATH_NOT_FOUND )
  313. {
  314. RegCloseKey( hReg );
  315. return iRes;
  316. }
  317. dwCount++;
  318. cbData = sizeof dwCount;
  319. iRes = RegSetValueExA( hReg, szFullPath, 0, REG_DWORD, (LPBYTE)&dwCount, cbData );
  320. RegCloseKey( hReg );
  321. }
  322. catch (...)
  323. {
  324. if ( hReg )
  325. RegCloseKey( hReg );
  326. return E_FAIL;
  327. }
  328. return dwCount;
  329. }
  330. int ReleaseSharedDll ( LPCSTR szFullPath )
  331. {
  332. LPCSTR szRegPath = "Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs";
  333. HKEY hReg = NULL;
  334. DWORD dwCount = 0;
  335. if ( IsBadStringPtrA( szFullPath, MAX_PATH ) )
  336. return E_INVALIDARG;
  337. try
  338. {
  339. DWORD cbData = sizeof dwCount;
  340. LONG iRes = RegOpenKeyA( HKEY_LOCAL_MACHINE, szRegPath, &hReg );
  341. if ( iRes != ERROR_SUCCESS )
  342. return iRes;
  343. iRes = RegQueryValueExA( hReg, szFullPath, NULL, NULL, (LPBYTE)&dwCount, &cbData );
  344. if ( iRes != ERROR_SUCCESS )
  345. {
  346. RegCloseKey( hReg );
  347. return iRes;
  348. }
  349. if ( dwCount > 1 )
  350. {
  351. dwCount--;
  352. cbData = sizeof dwCount;
  353. iRes = RegSetValueExA( hReg, szFullPath, 0, REG_DWORD, (LPBYTE)&dwCount, cbData );
  354. }
  355. else
  356. {
  357. dwCount = 0;
  358. iRes = RegDeleteValueA( hReg, szFullPath );
  359. }
  360. RegCloseKey( hReg );
  361. }
  362. catch (...)
  363. {
  364. if ( hReg )
  365. RegCloseKey( hReg );
  366. return E_FAIL;
  367. }
  368. return dwCount;
  369. }
  370. bool AddAccessRights( TCHAR *lpszFileName, TCHAR *szUserName, DWORD dwAccessMask )
  371. {
  372. //
  373. // SID variables.
  374. //
  375. SID_NAME_USE snuType;
  376. TCHAR * szDomain = NULL;
  377. DWORD cbDomain = 0;
  378. //
  379. // User name variables.
  380. //
  381. LPVOID pUserSID = NULL;
  382. DWORD cbUserSID = 0;
  383. DWORD cbUserName = 0;
  384. //
  385. // File SD variables.
  386. //
  387. PSECURITY_DESCRIPTOR pFileSD = NULL;
  388. DWORD cbFileSD = 0;
  389. //
  390. // New SD variables.
  391. //
  392. PSECURITY_DESCRIPTOR pNewSD = NULL;
  393. //
  394. // ACL variables.
  395. //
  396. PACL pACL = NULL;
  397. BOOL fDaclPresent;
  398. BOOL fDaclDefaulted;
  399. ACL_SIZE_INFORMATION AclInfo;
  400. //
  401. // New ACL variables.
  402. //
  403. PACL pNewACL = NULL;
  404. DWORD cbNewACL = 0;
  405. //
  406. // Temporary ACE.
  407. //
  408. LPVOID pTempAce = NULL;
  409. UINT CurrentAceIndex;
  410. bool fResult = false;
  411. BOOL fAPISuccess;
  412. // error code
  413. DWORD lastErr = 0;
  414. try
  415. {
  416. //
  417. // Call this API once to get the buffer sizes ( it will return ERROR_INSUFFICIENT_BUFFER )
  418. //
  419. fAPISuccess = LookupAccountName( NULL, szUserName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType );
  420. if( fAPISuccess )
  421. {
  422. throw E_FAIL; // we throw some fake error to skip through to the exit door
  423. }
  424. else if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  425. {
  426. lastErr = GetLastError();
  427. LogError( TEXT( "LookupAccountName() failed" ), lastErr );
  428. throw lastErr;
  429. }
  430. //
  431. // allocate the buffers
  432. //
  433. pUserSID = calloc( cbUserSID, 1 );
  434. if( !pUserSID )
  435. {
  436. lastErr = GetLastError();
  437. LogError( TEXT( "Alloc() for UserSID failed" ), lastErr );
  438. throw lastErr;
  439. }
  440. szDomain = ( TCHAR * ) calloc( cbDomain + sizeof TCHAR, sizeof TCHAR );
  441. if( !szDomain )
  442. {
  443. lastErr = GetLastError();
  444. LogError( TEXT( "Alloc() for szDomain failed" ), lastErr );
  445. throw lastErr;
  446. }
  447. //
  448. // The LookupAccountName function accepts the name of a system and an account as input.
  449. // It retrieves a security identifier ( SID ) for the account and
  450. // the name of the domain on which the account was found
  451. //
  452. fAPISuccess = LookupAccountName( NULL /* = local computer */, szUserName, pUserSID, &cbUserSID, szDomain, &cbDomain, &snuType );
  453. if( !fAPISuccess )
  454. {
  455. lastErr = GetLastError();
  456. LogError( TEXT( "LookupAccountName() failed" ), lastErr );
  457. throw lastErr;
  458. }
  459. //
  460. // call this API once to get the buffer sizes
  461. // API should have failed with insufficient buffer.
  462. //
  463. fAPISuccess = GetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pFileSD, 0, &cbFileSD );
  464. if( fAPISuccess )
  465. {
  466. throw E_FAIL;
  467. }
  468. else if( GetLastError() != ERROR_INSUFFICIENT_BUFFER )
  469. {
  470. lastErr = GetLastError();
  471. LogError( TEXT( "GetFileSecurity() failed" ), lastErr );
  472. throw lastErr;
  473. }
  474. //
  475. // allocate the buffers
  476. //
  477. pFileSD = calloc( cbFileSD, 1 );
  478. if( !pFileSD )
  479. {
  480. lastErr = GetLastError();
  481. LogError( TEXT( "Alloc() for pFileSD failed" ), lastErr );
  482. throw lastErr;
  483. }
  484. //
  485. // call the api to get the actual data
  486. //
  487. fAPISuccess = GetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pFileSD, cbFileSD, &cbFileSD );
  488. if( !fAPISuccess )
  489. {
  490. lastErr = GetLastError();
  491. LogError( TEXT( "GetFileSecurity() failed" ), lastErr );
  492. throw lastErr;
  493. }
  494. //
  495. // Initialize new SD.
  496. //
  497. pNewSD = calloc( cbFileSD, 1 ); // Should be same size as FileSD.
  498. if( !pNewSD )
  499. {
  500. lastErr = GetLastError();
  501. LogError( TEXT( "Alloc() for pNewDS failed" ), GetLastError() );
  502. throw lastErr;
  503. }
  504. if( !InitializeSecurityDescriptor( pNewSD, SECURITY_DESCRIPTOR_REVISION ) )
  505. {
  506. lastErr = GetLastError();
  507. LogError( TEXT( "InitializeSecurityDescriptor() failed" ), lastErr );
  508. throw lastErr;
  509. }
  510. //
  511. // Get DACL from SD.
  512. //
  513. if( !GetSecurityDescriptorDacl( pFileSD, &fDaclPresent, &pACL, &fDaclDefaulted ) )
  514. {
  515. lastErr = GetLastError();
  516. LogError( TEXT( "GetSecurityDescriptorDacl() failed" ), lastErr );
  517. throw lastErr;
  518. }
  519. //
  520. // Get size information for DACL.
  521. //
  522. AclInfo.AceCount = 0; // Assume NULL DACL.
  523. AclInfo.AclBytesFree = 0;
  524. AclInfo.AclBytesInUse = sizeof( ACL ); // If not NULL DACL, gather size information from DACL.
  525. if( fDaclPresent && pACL )
  526. {
  527. if( !GetAclInformation( pACL, &AclInfo, sizeof( ACL_SIZE_INFORMATION ), AclSizeInformation ) )
  528. {
  529. lastErr = GetLastError();
  530. LogError( TEXT( "GetAclInformation() failed" ), lastErr );
  531. throw lastErr;
  532. }
  533. }
  534. //
  535. // Compute size needed for the new ACL.
  536. //
  537. cbNewACL = AclInfo.AclBytesInUse + sizeof( ACCESS_ALLOWED_ACE ) + GetLengthSid( pUserSID );
  538. //
  539. // Allocate memory for new ACL.
  540. //
  541. pNewACL = ( PACL ) calloc( cbNewACL, 1 );
  542. if( !pNewACL )
  543. {
  544. lastErr = GetLastError();
  545. LogError( TEXT( "HeapAlloc() failed" ), lastErr );
  546. throw lastErr;
  547. }
  548. //
  549. // Initialize the new ACL.
  550. //
  551. if( !InitializeAcl( pNewACL, cbNewACL, ACL_REVISION2 ) )
  552. {
  553. lastErr = GetLastError();
  554. LogError( TEXT( "InitializeAcl() failed" ), lastErr );
  555. throw lastErr;
  556. }
  557. //
  558. // Add the access-allowed ACE to the new DACL.
  559. //
  560. ACE_HEADER aceheader = {0};
  561. aceheader.AceFlags = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
  562. aceheader.AceSize = sizeof( ACE_HEADER );
  563. aceheader.AceType = ACCESS_ALLOWED_OBJECT_ACE_TYPE;
  564. if( !AddAccessAllowedAceEx( pNewACL, ACL_REVISION2, aceheader.AceFlags, dwAccessMask, pUserSID ) )
  565. {
  566. lastErr = GetLastError();
  567. LogError( TEXT( "AddAccessAllowedAce() failed" ), lastErr );
  568. throw lastErr;
  569. }
  570. //
  571. // If DACL is present, copy it to a new DACL.
  572. //
  573. if( fDaclPresent )
  574. {
  575. //
  576. // Copy the file's ACEs to the new ACL
  577. //
  578. if( AclInfo.AceCount )
  579. {
  580. for( CurrentAceIndex = 0; CurrentAceIndex < AclInfo.AceCount; CurrentAceIndex++ )
  581. {
  582. //
  583. // Get an ACE.
  584. //
  585. if( !GetAce( pACL, CurrentAceIndex, &pTempAce ) )
  586. {
  587. lastErr = GetLastError();
  588. LogError( TEXT( "GetAce() failed" ), lastErr );
  589. throw lastErr;
  590. }
  591. //
  592. // Add the ACE to the new ACL.
  593. //
  594. if( !AddAce( pNewACL, ACL_REVISION, MAXDWORD, pTempAce, ( ( PACE_HEADER ) pTempAce )->AceSize ) )
  595. {
  596. lastErr = GetLastError();
  597. LogError( TEXT( "AddAce() failed" ), lastErr );
  598. throw lastErr;
  599. }
  600. }
  601. }
  602. }
  603. //
  604. // Set the new DACL to the file SD.
  605. //
  606. if( !SetSecurityDescriptorDacl( pNewSD, TRUE, pNewACL, FALSE ) )
  607. {
  608. lastErr = GetLastError();
  609. LogError( TEXT( "SetSecurityDescriptorDacl() failed" ), lastErr );
  610. lastErr;
  611. }
  612. //
  613. // Set the SD to the File.
  614. //
  615. if( !SetFileSecurity( lpszFileName, DACL_SECURITY_INFORMATION, pNewSD ) )
  616. {
  617. lastErr = GetLastError();
  618. LogError( TEXT( "SetFileSecurity() failed" ), lastErr );
  619. throw lastErr;
  620. }
  621. fResult = TRUE;
  622. }
  623. catch (...)
  624. {
  625. fResult = FALSE;
  626. }
  627. //
  628. // Free allocated memory
  629. //
  630. if( pUserSID )
  631. free( pUserSID );
  632. if( szDomain )
  633. free( szDomain );
  634. if( pFileSD )
  635. free( pFileSD );
  636. if( pNewSD )
  637. free( pNewSD );
  638. if( pNewACL )
  639. free( pNewACL );
  640. return fResult;
  641. }
  642. //
  643. // This function takes in the name of a Service (ie, MSSQL$DAVESEBESTA), and
  644. // fills a buffer with the name of the startup account for said Service.
  645. //
  646. // It does this by opening the Service Control Manager, getting a handle to
  647. // said Service, and then querying the properties of the service.
  648. //
  649. // returns: ERROR_SUCCESS if everything goes well.
  650. //
  651. LONG
  652. GetServiceStartupAccount( const TCHAR *pwszServiceName, TCHAR *pwszServiceAccount, int iLen )
  653. {
  654. memset( pwszServiceAccount, 0, iLen * sizeof( TCHAR ) );
  655. //
  656. // 1. Open the Service Control Manager.
  657. //
  658. SC_HANDLE hSCM = OpenSCManager( NULL, NULL, SC_MANAGER_CONNECT );
  659. if( NULL == hSCM )
  660. {
  661. Log( _T( "Could not open the Service Control Manager." ) );
  662. return ERROR_SUCCESS;
  663. }
  664. else
  665. {
  666. Log( _T( "Successfully opened a handle to the Service Control Manager." ) );
  667. }
  668. //
  669. // 2. Get a handle to the Service.
  670. //
  671. DWORD dwAccess = SERVICE_QUERY_CONFIG;
  672. SC_HANDLE hSvc = OpenService( hSCM, pwszServiceName, dwAccess );
  673. if( NULL == hSvc )
  674. {
  675. Log( _T( "Could not open a handle to the service %s." ), pwszServiceName );
  676. CloseServiceHandle( hSCM );
  677. return ERROR_SUCCESS;
  678. }
  679. else
  680. {
  681. Log( _T( "Successfully opened a handle to the service %s." ), pwszServiceName );
  682. }
  683. //
  684. // 3. Call QueryServiceConfig. This get us, among other things, the name of
  685. // the account that is used to start the Service.
  686. //
  687. DWORD dwSizeNeeded = 0;
  688. BOOL b = QueryServiceConfig( hSvc, NULL, 0, &dwSizeNeeded );
  689. DWORD d = GetLastError();
  690. if( !b && ( ERROR_INSUFFICIENT_BUFFER == d ) )
  691. {
  692. Log( _T( "About to allocate memory for service config info..." ) );
  693. }
  694. else
  695. {
  696. Log( _T( "Something went wrong during the call to QueryServiceConfig." ) );
  697. CloseServiceHandle( hSvc );
  698. CloseServiceHandle( hSCM );
  699. return ERROR_SUCCESS;
  700. }
  701. LPQUERY_SERVICE_CONFIG pSvcQuery = (LPQUERY_SERVICE_CONFIG)malloc( dwSizeNeeded );
  702. if( NULL == pSvcQuery )
  703. {
  704. Log( _T( "Ran out of memory." ) );
  705. CloseServiceHandle( hSvc );
  706. CloseServiceHandle( hSCM );
  707. return ERROR_SUCCESS;
  708. }
  709. b = QueryServiceConfig( hSvc, pSvcQuery, dwSizeNeeded, &dwSizeNeeded );
  710. if( !b )
  711. {
  712. Log( _T( "Call to QueryServiceConfig failed." ) );
  713. free( (void *)pSvcQuery );
  714. CloseServiceHandle( hSvc );
  715. CloseServiceHandle( hSCM );
  716. return ERROR_SUCCESS;
  717. }
  718. Log( _T( "Service startup account = %s" ), pSvcQuery->lpServiceStartName );
  719. //
  720. // 4. Copy the account into our output buffer, free up memory, and exit.
  721. //
  722. _tcsncpy( pwszServiceAccount, pSvcQuery->lpServiceStartName, iLen );
  723. free( (void *)pSvcQuery );
  724. CloseServiceHandle( hSvc );
  725. CloseServiceHandle( hSCM );
  726. return ERROR_SUCCESS;
  727. }
  728. //
  729. // Use the instance name to determine the name of the SQL Service.
  730. //
  731. // From the database instance name, you can infer the name of the Service
  732. // for that particular instance.
  733. //
  734. // Instance Name Service Name
  735. // ===========================================
  736. // (default) MSSQLSERVER
  737. // NULL MSSQLSERVER
  738. // <anything else> MSSQL$<anything else>
  739. //
  740. void
  741. GetUDDIDBServiceName( const TCHAR *pwszInstanceName, TCHAR *pwszServiceName, int iLen )
  742. {
  743. memset( pwszServiceName, 0, iLen * sizeof( TCHAR ) );
  744. _tcscpy( pwszServiceName, _T( "MSSQL" ) );
  745. if( ( 0 == _tcslen( pwszInstanceName ) ) ||
  746. ( 0 == _tcsicmp( pwszInstanceName, _T( "----" ) ) ) ||
  747. ( 0 == _tcsicmp( pwszInstanceName, _T( "(default)" ) ) ) )
  748. {
  749. _tcsncat( pwszServiceName, _T( "SERVER" ), iLen );
  750. }
  751. else
  752. {
  753. _tcsncat( pwszServiceName, _T( "$" ), iLen );
  754. _tcsncat( pwszServiceName, pwszInstanceName, iLen );
  755. }
  756. Log( _T( "Database service name = %s" ), pwszServiceName );
  757. }
  758. void
  759. AddAccessRightsVerbose( TCHAR *pwszFileName, TCHAR *pwszUserName, DWORD dwMask )
  760. {
  761. BOOL b = AddAccessRights( pwszFileName, pwszUserName, dwMask );
  762. if( !b )
  763. {
  764. Log( _T( "ACL for file %s was NOT modified." ), pwszFileName );
  765. }
  766. else
  767. {
  768. Log( _T( "User: %s now has execute permissions on file: %s." ), pwszUserName, pwszFileName );
  769. }
  770. }