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.

530 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1998
  5. //
  6. // File: svcctx.cpp
  7. //
  8. // Contents: Implementation of CServiceContext and NT Marta Service Functions
  9. //
  10. // History: 3-31-1999 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. #include <svcctx.h>
  16. //+---------------------------------------------------------------------------
  17. //
  18. // Member: CServiceContext::CServiceContext, public
  19. //
  20. // Synopsis: Constructor
  21. //
  22. //----------------------------------------------------------------------------
  23. CServiceContext::CServiceContext ()
  24. {
  25. m_cRefs = 1;
  26. m_hService = NULL;
  27. m_fNameInitialized = FALSE;
  28. }
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Member: CServiceContext::~CServiceContext, public
  32. //
  33. // Synopsis: Destructor
  34. //
  35. //----------------------------------------------------------------------------
  36. CServiceContext::~CServiceContext ()
  37. {
  38. if ( ( m_hService != NULL ) && ( m_fNameInitialized == TRUE ) )
  39. {
  40. CloseServiceHandle( m_hService );
  41. }
  42. assert( m_cRefs == 0 );
  43. }
  44. //+---------------------------------------------------------------------------
  45. //
  46. // Member: CServiceContext::InitializeByName, public
  47. //
  48. // Synopsis: initialize the context given the name of the service
  49. //
  50. //----------------------------------------------------------------------------
  51. DWORD
  52. CServiceContext::InitializeByName (LPCWSTR pObjectName, ACCESS_MASK AccessMask)
  53. {
  54. DWORD Result;
  55. LPWSTR pwszMachine = NULL;
  56. LPWSTR pwszService = NULL;
  57. SC_HANDLE hSCM = NULL;
  58. SC_HANDLE hService = NULL;
  59. Result = ServiceContextParseServiceName(
  60. pObjectName,
  61. &pwszMachine,
  62. &pwszService
  63. );
  64. if ( Result == ERROR_SUCCESS )
  65. {
  66. hSCM = OpenSCManagerW( pwszMachine, NULL, AccessMask );
  67. if ( hSCM == NULL )
  68. {
  69. delete pwszMachine;
  70. delete pwszService;
  71. return( GetLastError() );
  72. }
  73. if ( AccessMask & GENERIC_WRITE )
  74. {
  75. AccessMask |= ( WRITE_DAC | WRITE_OWNER );
  76. }
  77. m_hService = OpenServiceW( hSCM, pwszService, AccessMask );
  78. if ( m_hService != NULL )
  79. {
  80. m_fNameInitialized = TRUE;
  81. }
  82. else
  83. {
  84. Result = GetLastError();
  85. }
  86. CloseServiceHandle( hSCM );
  87. delete pwszMachine;
  88. delete pwszService;
  89. }
  90. return( Result );
  91. }
  92. //+---------------------------------------------------------------------------
  93. //
  94. // Member: CServiceContext::InitializeByHandle, public
  95. //
  96. // Synopsis: initialize the context given a service handle
  97. //
  98. //----------------------------------------------------------------------------
  99. DWORD
  100. CServiceContext::InitializeByHandle (HANDLE Handle)
  101. {
  102. m_hService = (SC_HANDLE)Handle;
  103. assert( m_fNameInitialized == FALSE );
  104. return( ERROR_SUCCESS );
  105. }
  106. //+---------------------------------------------------------------------------
  107. //
  108. // Member: CServiceContext::AddRef, public
  109. //
  110. // Synopsis: add a reference to the context
  111. //
  112. //----------------------------------------------------------------------------
  113. DWORD
  114. CServiceContext::AddRef ()
  115. {
  116. m_cRefs += 1;
  117. return( m_cRefs );
  118. }
  119. //+---------------------------------------------------------------------------
  120. //
  121. // Member: CServiceContext::Release, public
  122. //
  123. // Synopsis: release a reference to the context
  124. //
  125. //----------------------------------------------------------------------------
  126. DWORD
  127. CServiceContext::Release ()
  128. {
  129. m_cRefs -= 1;
  130. if ( m_cRefs == 0 )
  131. {
  132. delete this;
  133. return( 0 );
  134. }
  135. return( m_cRefs );
  136. }
  137. //+---------------------------------------------------------------------------
  138. //
  139. // Member: CServiceContext::GetServiceProperties, public
  140. //
  141. // Synopsis: get properties about the context
  142. //
  143. //----------------------------------------------------------------------------
  144. DWORD
  145. CServiceContext::GetServiceProperties (
  146. PMARTA_OBJECT_PROPERTIES pObjectProperties
  147. )
  148. {
  149. if ( pObjectProperties->cbSize < sizeof( MARTA_OBJECT_PROPERTIES ) )
  150. {
  151. return( ERROR_INVALID_PARAMETER );
  152. }
  153. assert( pObjectProperties->dwFlags == 0 );
  154. return( ERROR_SUCCESS );
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Member: CServiceContext::GetServiceRights, public
  159. //
  160. // Synopsis: get the service security descriptor
  161. //
  162. //----------------------------------------------------------------------------
  163. DWORD
  164. CServiceContext::GetServiceRights (
  165. SECURITY_INFORMATION SecurityInfo,
  166. PSECURITY_DESCRIPTOR* ppSecurityDescriptor
  167. )
  168. {
  169. BOOL fResult;
  170. UCHAR SDBuff[1];
  171. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  172. DWORD cb = 0;
  173. assert( m_hService != NULL );
  174. fResult = QueryServiceObjectSecurity(
  175. m_hService,
  176. SecurityInfo,
  177. (PSECURITY_DESCRIPTOR) SDBuff,
  178. 0,
  179. &cb
  180. );
  181. if ( ( fResult == FALSE ) && ( cb > 0 ) )
  182. {
  183. assert( ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) ||
  184. ( GetLastError() == STATUS_BUFFER_TOO_SMALL ) );
  185. pSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, cb );
  186. if ( pSecurityDescriptor == NULL )
  187. {
  188. return( ERROR_OUTOFMEMORY );
  189. }
  190. fResult = QueryServiceObjectSecurity(
  191. m_hService,
  192. SecurityInfo,
  193. pSecurityDescriptor,
  194. cb,
  195. &cb
  196. );
  197. }
  198. else
  199. {
  200. assert( fResult == FALSE );
  201. return( GetLastError() );
  202. }
  203. if ( fResult == TRUE )
  204. {
  205. *ppSecurityDescriptor = pSecurityDescriptor;
  206. }
  207. else
  208. {
  209. return( GetLastError() );
  210. }
  211. return( ERROR_SUCCESS );
  212. }
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Member: CServiceContext::SetServiceRights, public
  216. //
  217. // Synopsis: set the window security descriptor
  218. //
  219. //----------------------------------------------------------------------------
  220. DWORD
  221. CServiceContext::SetServiceRights (
  222. SECURITY_INFORMATION SecurityInfo,
  223. PSECURITY_DESCRIPTOR pSecurityDescriptor
  224. )
  225. {
  226. assert( m_hService != NULL );
  227. if ( SetServiceObjectSecurity(
  228. m_hService,
  229. SecurityInfo,
  230. pSecurityDescriptor
  231. ) == FALSE )
  232. {
  233. return( GetLastError() );
  234. }
  235. return( ERROR_SUCCESS );
  236. }
  237. //+---------------------------------------------------------------------------
  238. //
  239. // Function: ServiceContextParseServiceName
  240. //
  241. // Synopsis: parse the service name and machine
  242. //
  243. //----------------------------------------------------------------------------
  244. DWORD
  245. ServiceContextParseServiceName (
  246. LPCWSTR pwszName,
  247. LPWSTR* ppMachine,
  248. LPWSTR* ppService
  249. )
  250. {
  251. return( StandardContextParseName( pwszName, ppMachine, ppService ) );
  252. }
  253. //+---------------------------------------------------------------------------
  254. //
  255. // Function: StandardContextParseName
  256. //
  257. // Synopsis: parse the name and machine
  258. //
  259. //----------------------------------------------------------------------------
  260. DWORD
  261. StandardContextParseName (
  262. LPCWSTR pwszName,
  263. LPWSTR* ppMachine,
  264. LPWSTR* ppRest
  265. )
  266. {
  267. LPWSTR pwszMachine = NULL;
  268. LPWSTR pwszNameLocal = NULL;
  269. LPWSTR pwszRest = NULL;
  270. DWORD cwName = 0;
  271. DWORD cw = 0;
  272. DWORD rc = ERROR_SUCCESS;
  273. //
  274. // VishnuP: 392334 AV because IN parameter pwszName could be constant and is written
  275. // to inside here. Irrespective of whether it is a constant, this IN parameter is coming
  276. // from GetNamedSecurityInfo and should not be mangled.
  277. // So, create a local copy of the IN parameter and mangle it if needeed.
  278. //
  279. cwName = wcslen( pwszName );
  280. pwszNameLocal = new WCHAR [ cwName + 1 ];
  281. if ( pwszNameLocal == NULL )
  282. {
  283. rc = ERROR_OUTOFMEMORY ;
  284. goto CleanUp;
  285. }
  286. wcscpy( pwszNameLocal, pwszName);
  287. if ( cwName > 2 )
  288. {
  289. if ( ( pwszNameLocal[0] == L'\\' ) && ( pwszNameLocal[1] == L'\\' ) )
  290. {
  291. LPWSTR pwsz, tmp;
  292. pwsz = (LPWSTR)&pwszNameLocal[2];
  293. while ( ( *pwsz != L'\0' ) && ( *pwsz != L'\\' ) )
  294. {
  295. pwsz++;
  296. cw++;
  297. }
  298. if ( *pwsz == L'\0' )
  299. {
  300. rc = ERROR_INVALID_PARAMETER ;
  301. goto CleanUp;
  302. }
  303. *pwsz = L'\0';
  304. tmp = pwsz;
  305. pwsz++;
  306. pwszMachine = new WCHAR [ cw + 1 ];
  307. if ( pwszMachine == NULL )
  308. {
  309. rc = ERROR_OUTOFMEMORY ;
  310. goto CleanUp;
  311. }
  312. cw = wcslen( pwsz );
  313. if ( cw == 0 )
  314. {
  315. delete pwszMachine;
  316. rc = ERROR_INVALID_PARAMETER ;
  317. goto CleanUp;
  318. }
  319. pwszRest = new WCHAR [ cw + 1 ];
  320. if ( pwszRest == NULL )
  321. {
  322. delete pwszMachine;
  323. rc = ERROR_OUTOFMEMORY ;
  324. goto CleanUp;
  325. }
  326. wcscpy( pwszMachine, &pwszNameLocal[2] );
  327. wcscpy( pwszRest, pwsz );
  328. *tmp = L'\\';
  329. }
  330. }
  331. else if ( ( pwszNameLocal[0] == L'\\' ) || ( pwszNameLocal[1] == L'\\' ) )
  332. {
  333. rc = ERROR_INVALID_PARAMETER ;
  334. goto CleanUp;
  335. }
  336. if ( pwszRest == NULL )
  337. {
  338. assert( pwszMachine == NULL );
  339. pwszRest = new WCHAR [ cwName + 1 ];
  340. if ( pwszRest == NULL )
  341. {
  342. rc = ERROR_OUTOFMEMORY ;
  343. goto CleanUp;
  344. }
  345. wcscpy( pwszRest, pwszNameLocal );
  346. }
  347. *ppMachine = pwszMachine;
  348. *ppRest = pwszRest;
  349. CleanUp:
  350. if (pwszNameLocal)
  351. delete pwszNameLocal;
  352. return( rc );
  353. }
  354. //
  355. // Functions from service.h which dispatch unto the CServiceContext class
  356. //
  357. DWORD
  358. MartaAddRefServiceContext(
  359. IN MARTA_CONTEXT Context
  360. )
  361. {
  362. return( ( (CServiceContext *)Context )->AddRef() );
  363. }
  364. DWORD
  365. MartaCloseServiceContext(
  366. IN MARTA_CONTEXT Context
  367. )
  368. {
  369. return( ( (CServiceContext *)Context )->Release() );
  370. }
  371. DWORD
  372. MartaGetServiceProperties(
  373. IN MARTA_CONTEXT Context,
  374. IN OUT PMARTA_OBJECT_PROPERTIES pProperties
  375. )
  376. {
  377. return( ( (CServiceContext *)Context )->GetServiceProperties( pProperties ) );
  378. }
  379. DWORD
  380. MartaGetServiceTypeProperties(
  381. IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
  382. )
  383. {
  384. if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
  385. {
  386. return( ERROR_INVALID_PARAMETER );
  387. }
  388. assert( pProperties->dwFlags == 0 );
  389. return( ERROR_SUCCESS );
  390. }
  391. DWORD
  392. MartaGetServiceRights(
  393. IN MARTA_CONTEXT Context,
  394. IN SECURITY_INFORMATION SecurityInfo,
  395. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  396. )
  397. {
  398. return( ( (CServiceContext *)Context )->GetServiceRights(
  399. SecurityInfo,
  400. ppSecurityDescriptor
  401. ) );
  402. }
  403. DWORD
  404. MartaOpenServiceNamedObject(
  405. IN LPCWSTR pObjectName,
  406. IN ACCESS_MASK AccessMask,
  407. OUT PMARTA_CONTEXT pContext
  408. )
  409. {
  410. DWORD Result;
  411. CServiceContext* pServiceContext;
  412. pServiceContext = new CServiceContext;
  413. if ( pServiceContext == NULL )
  414. {
  415. return( ERROR_OUTOFMEMORY );
  416. }
  417. Result = pServiceContext->InitializeByName( pObjectName, AccessMask );
  418. if ( Result != ERROR_SUCCESS )
  419. {
  420. pServiceContext->Release();
  421. return( Result );
  422. }
  423. *pContext = pServiceContext;
  424. return( ERROR_SUCCESS );
  425. }
  426. DWORD
  427. MartaOpenServiceHandleObject(
  428. IN HANDLE Handle,
  429. IN ACCESS_MASK AccessMask,
  430. OUT PMARTA_CONTEXT pContext
  431. )
  432. {
  433. DWORD Result;
  434. CServiceContext* pServiceContext;
  435. pServiceContext = new CServiceContext;
  436. if ( pServiceContext == NULL )
  437. {
  438. return( ERROR_OUTOFMEMORY );
  439. }
  440. Result = pServiceContext->InitializeByHandle( Handle );
  441. if ( Result != ERROR_SUCCESS )
  442. {
  443. pServiceContext->Release();
  444. return( Result );
  445. }
  446. *pContext = pServiceContext;
  447. return( ERROR_SUCCESS );
  448. }
  449. DWORD
  450. MartaSetServiceRights(
  451. IN MARTA_CONTEXT Context,
  452. IN SECURITY_INFORMATION SecurityInfo,
  453. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  454. )
  455. {
  456. return( ( (CServiceContext *)Context )->SetServiceRights(
  457. SecurityInfo,
  458. pSecurityDescriptor
  459. ) );
  460. }