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.

531 lines
14 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. LocalFree(pSecurityDescriptor);
  210. return( GetLastError() );
  211. }
  212. return( ERROR_SUCCESS );
  213. }
  214. //+---------------------------------------------------------------------------
  215. //
  216. // Member: CServiceContext::SetServiceRights, public
  217. //
  218. // Synopsis: set the window security descriptor
  219. //
  220. //----------------------------------------------------------------------------
  221. DWORD
  222. CServiceContext::SetServiceRights (
  223. SECURITY_INFORMATION SecurityInfo,
  224. PSECURITY_DESCRIPTOR pSecurityDescriptor
  225. )
  226. {
  227. assert( m_hService != NULL );
  228. if ( SetServiceObjectSecurity(
  229. m_hService,
  230. SecurityInfo,
  231. pSecurityDescriptor
  232. ) == FALSE )
  233. {
  234. return( GetLastError() );
  235. }
  236. return( ERROR_SUCCESS );
  237. }
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Function: ServiceContextParseServiceName
  241. //
  242. // Synopsis: parse the service name and machine
  243. //
  244. //----------------------------------------------------------------------------
  245. DWORD
  246. ServiceContextParseServiceName (
  247. LPCWSTR pwszName,
  248. LPWSTR* ppMachine,
  249. LPWSTR* ppService
  250. )
  251. {
  252. return( StandardContextParseName( pwszName, ppMachine, ppService ) );
  253. }
  254. //+---------------------------------------------------------------------------
  255. //
  256. // Function: StandardContextParseName
  257. //
  258. // Synopsis: parse the name and machine
  259. //
  260. //----------------------------------------------------------------------------
  261. DWORD
  262. StandardContextParseName (
  263. LPCWSTR pwszName,
  264. LPWSTR* ppMachine,
  265. LPWSTR* ppRest
  266. )
  267. {
  268. LPWSTR pwszMachine = NULL;
  269. LPWSTR pwszNameLocal = NULL;
  270. LPWSTR pwszRest = NULL;
  271. DWORD cwName = 0;
  272. DWORD cw = 0;
  273. DWORD rc = ERROR_SUCCESS;
  274. //
  275. // VishnuP: 392334 AV because IN parameter pwszName could be constant and is written
  276. // to inside here. Irrespective of whether it is a constant, this IN parameter is coming
  277. // from GetNamedSecurityInfo and should not be mangled.
  278. // So, create a local copy of the IN parameter and mangle it if needeed.
  279. //
  280. cwName = wcslen( pwszName );
  281. pwszNameLocal = new WCHAR [ cwName + 1 ];
  282. if ( pwszNameLocal == NULL )
  283. {
  284. rc = ERROR_OUTOFMEMORY ;
  285. goto CleanUp;
  286. }
  287. wcscpy( pwszNameLocal, pwszName);
  288. if ( cwName > 2 )
  289. {
  290. if ( ( pwszNameLocal[0] == L'\\' ) && ( pwszNameLocal[1] == L'\\' ) )
  291. {
  292. LPWSTR pwsz, tmp;
  293. pwsz = (LPWSTR)&pwszNameLocal[2];
  294. while ( ( *pwsz != L'\0' ) && ( *pwsz != L'\\' ) )
  295. {
  296. pwsz++;
  297. cw++;
  298. }
  299. if ( *pwsz == L'\0' )
  300. {
  301. rc = ERROR_INVALID_PARAMETER ;
  302. goto CleanUp;
  303. }
  304. *pwsz = L'\0';
  305. tmp = pwsz;
  306. pwsz++;
  307. pwszMachine = new WCHAR [ cw + 1 ];
  308. if ( pwszMachine == NULL )
  309. {
  310. rc = ERROR_OUTOFMEMORY ;
  311. goto CleanUp;
  312. }
  313. cw = wcslen( pwsz );
  314. if ( cw == 0 )
  315. {
  316. delete pwszMachine;
  317. rc = ERROR_INVALID_PARAMETER ;
  318. goto CleanUp;
  319. }
  320. pwszRest = new WCHAR [ cw + 1 ];
  321. if ( pwszRest == NULL )
  322. {
  323. delete pwszMachine;
  324. rc = ERROR_OUTOFMEMORY ;
  325. goto CleanUp;
  326. }
  327. wcscpy( pwszMachine, &pwszNameLocal[2] );
  328. wcscpy( pwszRest, pwsz );
  329. *tmp = L'\\';
  330. }
  331. }
  332. else if ( ( pwszNameLocal[0] == L'\\' ) || ( pwszNameLocal[1] == L'\\' ) )
  333. {
  334. rc = ERROR_INVALID_PARAMETER ;
  335. goto CleanUp;
  336. }
  337. if ( pwszRest == NULL )
  338. {
  339. assert( pwszMachine == NULL );
  340. pwszRest = new WCHAR [ cwName + 1 ];
  341. if ( pwszRest == NULL )
  342. {
  343. rc = ERROR_OUTOFMEMORY ;
  344. goto CleanUp;
  345. }
  346. wcscpy( pwszRest, pwszNameLocal );
  347. }
  348. *ppMachine = pwszMachine;
  349. *ppRest = pwszRest;
  350. CleanUp:
  351. if (pwszNameLocal)
  352. delete pwszNameLocal;
  353. return( rc );
  354. }
  355. //
  356. // Functions from service.h which dispatch unto the CServiceContext class
  357. //
  358. DWORD
  359. MartaAddRefServiceContext(
  360. IN MARTA_CONTEXT Context
  361. )
  362. {
  363. return( ( (CServiceContext *)Context )->AddRef() );
  364. }
  365. DWORD
  366. MartaCloseServiceContext(
  367. IN MARTA_CONTEXT Context
  368. )
  369. {
  370. return( ( (CServiceContext *)Context )->Release() );
  371. }
  372. DWORD
  373. MartaGetServiceProperties(
  374. IN MARTA_CONTEXT Context,
  375. IN OUT PMARTA_OBJECT_PROPERTIES pProperties
  376. )
  377. {
  378. return( ( (CServiceContext *)Context )->GetServiceProperties( pProperties ) );
  379. }
  380. DWORD
  381. MartaGetServiceTypeProperties(
  382. IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
  383. )
  384. {
  385. if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
  386. {
  387. return( ERROR_INVALID_PARAMETER );
  388. }
  389. assert( pProperties->dwFlags == 0 );
  390. return( ERROR_SUCCESS );
  391. }
  392. DWORD
  393. MartaGetServiceRights(
  394. IN MARTA_CONTEXT Context,
  395. IN SECURITY_INFORMATION SecurityInfo,
  396. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  397. )
  398. {
  399. return( ( (CServiceContext *)Context )->GetServiceRights(
  400. SecurityInfo,
  401. ppSecurityDescriptor
  402. ) );
  403. }
  404. DWORD
  405. MartaOpenServiceNamedObject(
  406. IN LPCWSTR pObjectName,
  407. IN ACCESS_MASK AccessMask,
  408. OUT PMARTA_CONTEXT pContext
  409. )
  410. {
  411. DWORD Result;
  412. CServiceContext* pServiceContext;
  413. pServiceContext = new CServiceContext;
  414. if ( pServiceContext == NULL )
  415. {
  416. return( ERROR_OUTOFMEMORY );
  417. }
  418. Result = pServiceContext->InitializeByName( pObjectName, AccessMask );
  419. if ( Result != ERROR_SUCCESS )
  420. {
  421. pServiceContext->Release();
  422. return( Result );
  423. }
  424. *pContext = pServiceContext;
  425. return( ERROR_SUCCESS );
  426. }
  427. DWORD
  428. MartaOpenServiceHandleObject(
  429. IN HANDLE Handle,
  430. IN ACCESS_MASK AccessMask,
  431. OUT PMARTA_CONTEXT pContext
  432. )
  433. {
  434. DWORD Result;
  435. CServiceContext* pServiceContext;
  436. pServiceContext = new CServiceContext;
  437. if ( pServiceContext == NULL )
  438. {
  439. return( ERROR_OUTOFMEMORY );
  440. }
  441. Result = pServiceContext->InitializeByHandle( Handle );
  442. if ( Result != ERROR_SUCCESS )
  443. {
  444. pServiceContext->Release();
  445. return( Result );
  446. }
  447. *pContext = pServiceContext;
  448. return( ERROR_SUCCESS );
  449. }
  450. DWORD
  451. MartaSetServiceRights(
  452. IN MARTA_CONTEXT Context,
  453. IN SECURITY_INFORMATION SecurityInfo,
  454. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  455. )
  456. {
  457. return( ( (CServiceContext *)Context )->SetServiceRights(
  458. SecurityInfo,
  459. pSecurityDescriptor
  460. ) );
  461. }