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.

665 lines
16 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1998
  5. //
  6. // File: krnctx.cpp
  7. //
  8. // Contents: Implementation of CKernelContext and NT Marta Kernel Functions
  9. //
  10. // History: 3-31-1999 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <aclpch.hxx>
  14. #pragma hdrstop
  15. #include <krnctx.h>
  16. #include <wmistr.h>
  17. #include <wmiumkm.h>
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Member: CKernelContext::CKernelContext, public
  21. //
  22. // Synopsis: Constructor
  23. //
  24. //----------------------------------------------------------------------------
  25. CKernelContext::CKernelContext ()
  26. {
  27. m_cRefs = 1;
  28. m_hObject = NULL;
  29. m_fNameInitialized = FALSE;
  30. }
  31. //+---------------------------------------------------------------------------
  32. //
  33. // Member: CKernelContext::~CKernelContext, public
  34. //
  35. // Synopsis: Destructor
  36. //
  37. //----------------------------------------------------------------------------
  38. CKernelContext::~CKernelContext ()
  39. {
  40. if ( ( m_hObject != NULL ) && ( m_fNameInitialized == TRUE ) )
  41. {
  42. CloseHandle( m_hObject );
  43. }
  44. assert( m_cRefs == 0 );
  45. }
  46. //+---------------------------------------------------------------------------
  47. //
  48. // Member: CKernelContext::InitializeByName, public
  49. //
  50. // Synopsis: initialize the context given the name of the Kernel
  51. //
  52. //----------------------------------------------------------------------------
  53. DWORD
  54. CKernelContext::InitializeByName (LPCWSTR pObjectName, ACCESS_MASK AccessMask)
  55. {
  56. DWORD LastError;
  57. m_fNameInitialized = TRUE;
  58. m_hObject = OpenMutexW( AccessMask, FALSE, pObjectName );
  59. if ( m_hObject != NULL )
  60. {
  61. return( ERROR_SUCCESS );
  62. }
  63. LastError = GetLastError();
  64. if ( LastError == ERROR_INVALID_HANDLE )
  65. {
  66. m_hObject = OpenEventW( AccessMask, FALSE, pObjectName );
  67. if ( m_hObject != NULL )
  68. {
  69. return( ERROR_SUCCESS );
  70. }
  71. }
  72. else
  73. {
  74. goto ErrorReturn;
  75. }
  76. LastError = GetLastError();
  77. if ( LastError == ERROR_INVALID_HANDLE )
  78. {
  79. m_hObject = OpenSemaphoreW( AccessMask, FALSE, pObjectName );
  80. if ( m_hObject != NULL )
  81. {
  82. return( ERROR_SUCCESS );
  83. }
  84. }
  85. else
  86. {
  87. goto ErrorReturn;
  88. }
  89. LastError = GetLastError();
  90. if ( LastError == ERROR_INVALID_HANDLE )
  91. {
  92. m_hObject = OpenFileMappingW( AccessMask, FALSE, pObjectName );
  93. if ( m_hObject != NULL )
  94. {
  95. return( ERROR_SUCCESS );
  96. }
  97. }
  98. else
  99. {
  100. goto ErrorReturn;
  101. }
  102. LastError = GetLastError();
  103. if ( LastError == ERROR_INVALID_HANDLE )
  104. {
  105. m_hObject = OpenJobObjectW( AccessMask, FALSE, pObjectName );
  106. if ( m_hObject != NULL )
  107. {
  108. return( ERROR_SUCCESS );
  109. }
  110. }
  111. else
  112. {
  113. goto ErrorReturn;
  114. }
  115. LastError = GetLastError();
  116. if ( LastError == ERROR_INVALID_HANDLE )
  117. {
  118. m_hObject = OpenWaitableTimerW( AccessMask, FALSE, pObjectName );
  119. if ( m_hObject != NULL )
  120. {
  121. return( ERROR_SUCCESS );
  122. }
  123. }
  124. LastError = GetLastError();
  125. ErrorReturn:
  126. m_fNameInitialized = FALSE;
  127. return( LastError );
  128. }
  129. //+---------------------------------------------------------------------------
  130. //
  131. // Member: CKernelContext::InitializeByWmiName, public
  132. //
  133. // Synopsis: initlialize a WMI kernel context
  134. //
  135. //----------------------------------------------------------------------------
  136. DWORD
  137. CKernelContext::InitializeByWmiName (
  138. LPCWSTR pObjectName,
  139. ACCESS_MASK AccessMask
  140. )
  141. {
  142. DWORD Result;
  143. HANDLE hObject;
  144. Result = OpenWmiGuidObject( (LPWSTR)pObjectName, AccessMask, &hObject );
  145. if ( Result == ERROR_SUCCESS )
  146. {
  147. m_hObject = hObject;
  148. m_fNameInitialized = TRUE;
  149. }
  150. return( Result );
  151. }
  152. //+---------------------------------------------------------------------------
  153. //
  154. // Member: CKernelContext::InitializeByHandle, public
  155. //
  156. // Synopsis: initialize the context given a Kernel handle
  157. //
  158. //----------------------------------------------------------------------------
  159. DWORD
  160. CKernelContext::InitializeByHandle (HANDLE Handle)
  161. {
  162. m_hObject = Handle;
  163. assert( m_fNameInitialized == FALSE );
  164. return( ERROR_SUCCESS );
  165. }
  166. //+---------------------------------------------------------------------------
  167. //
  168. // Member: CKernelContext::AddRef, public
  169. //
  170. // Synopsis: add a reference to the context
  171. //
  172. //----------------------------------------------------------------------------
  173. DWORD
  174. CKernelContext::AddRef ()
  175. {
  176. m_cRefs += 1;
  177. return( m_cRefs );
  178. }
  179. //+---------------------------------------------------------------------------
  180. //
  181. // Member: CKernelContext::Release, public
  182. //
  183. // Synopsis: release a reference to the context
  184. //
  185. //----------------------------------------------------------------------------
  186. DWORD
  187. CKernelContext::Release ()
  188. {
  189. m_cRefs -= 1;
  190. if ( m_cRefs == 0 )
  191. {
  192. delete this;
  193. return( 0 );
  194. }
  195. return( m_cRefs );
  196. }
  197. //+---------------------------------------------------------------------------
  198. //
  199. // Member: CKernelContext::GetKernelProperties, public
  200. //
  201. // Synopsis: get properties about the context
  202. //
  203. //----------------------------------------------------------------------------
  204. DWORD
  205. CKernelContext::GetKernelProperties (
  206. PMARTA_OBJECT_PROPERTIES pObjectProperties
  207. )
  208. {
  209. if ( pObjectProperties->cbSize < sizeof( MARTA_OBJECT_PROPERTIES ) )
  210. {
  211. return( ERROR_INVALID_PARAMETER );
  212. }
  213. assert( pObjectProperties->dwFlags == 0 );
  214. return( ERROR_SUCCESS );
  215. }
  216. //+---------------------------------------------------------------------------
  217. //
  218. // Member: CKernelContext::GetKernelRights, public
  219. //
  220. // Synopsis: get the Kernel security descriptor
  221. //
  222. //----------------------------------------------------------------------------
  223. DWORD
  224. CKernelContext::GetKernelRights (
  225. SECURITY_INFORMATION SecurityInfo,
  226. PSECURITY_DESCRIPTOR* ppSecurityDescriptor
  227. )
  228. {
  229. BOOL fResult;
  230. PSECURITY_DESCRIPTOR pSecurityDescriptor = NULL;
  231. DWORD cb = 0;
  232. assert( m_hObject != NULL );
  233. fResult = GetKernelObjectSecurity(
  234. m_hObject,
  235. SecurityInfo,
  236. pSecurityDescriptor,
  237. 0,
  238. &cb
  239. );
  240. if ( ( fResult == FALSE ) && ( cb > 0 ) )
  241. {
  242. assert( ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) ||
  243. ( GetLastError() == STATUS_BUFFER_TOO_SMALL ) );
  244. pSecurityDescriptor = (PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, cb );
  245. if ( pSecurityDescriptor == NULL )
  246. {
  247. return( ERROR_OUTOFMEMORY );
  248. }
  249. fResult = GetKernelObjectSecurity(
  250. m_hObject,
  251. SecurityInfo,
  252. pSecurityDescriptor,
  253. cb,
  254. &cb
  255. );
  256. }
  257. else
  258. {
  259. assert( fResult == FALSE );
  260. return( GetLastError() );
  261. }
  262. if ( fResult == TRUE )
  263. {
  264. *ppSecurityDescriptor = pSecurityDescriptor;
  265. }
  266. else
  267. {
  268. return( GetLastError() );
  269. }
  270. return( ERROR_SUCCESS );
  271. }
  272. //+---------------------------------------------------------------------------
  273. //
  274. // Member: CKernelContext::SetKernelRights, public
  275. //
  276. // Synopsis: set the window security descriptor
  277. //
  278. //----------------------------------------------------------------------------
  279. DWORD
  280. CKernelContext::SetKernelRights (
  281. SECURITY_INFORMATION SecurityInfo,
  282. PSECURITY_DESCRIPTOR pSecurityDescriptor
  283. )
  284. {
  285. assert( m_hObject != NULL );
  286. if ( SetKernelObjectSecurity(
  287. m_hObject,
  288. SecurityInfo,
  289. pSecurityDescriptor
  290. ) == FALSE )
  291. {
  292. return( GetLastError() );
  293. }
  294. return( ERROR_SUCCESS );
  295. }
  296. //
  297. // Functions from Kernel.h which dispatch unto the CKernelContext class
  298. //
  299. DWORD
  300. MartaAddRefKernelContext(
  301. IN MARTA_CONTEXT Context
  302. )
  303. {
  304. return( ( (CKernelContext *)Context )->AddRef() );
  305. }
  306. DWORD
  307. MartaCloseKernelContext(
  308. IN MARTA_CONTEXT Context
  309. )
  310. {
  311. return( ( (CKernelContext *)Context )->Release() );
  312. }
  313. DWORD
  314. MartaGetKernelProperties(
  315. IN MARTA_CONTEXT Context,
  316. IN OUT PMARTA_OBJECT_PROPERTIES pProperties
  317. )
  318. {
  319. return( ( (CKernelContext *)Context )->GetKernelProperties( pProperties ) );
  320. }
  321. DWORD
  322. MartaGetKernelTypeProperties(
  323. IN OUT PMARTA_OBJECT_TYPE_PROPERTIES pProperties
  324. )
  325. {
  326. if ( pProperties->cbSize < sizeof( MARTA_OBJECT_TYPE_PROPERTIES ) )
  327. {
  328. return( ERROR_INVALID_PARAMETER );
  329. }
  330. assert( pProperties->dwFlags == 0 );
  331. return( ERROR_SUCCESS );
  332. }
  333. DWORD
  334. MartaGetKernelRights(
  335. IN MARTA_CONTEXT Context,
  336. IN SECURITY_INFORMATION SecurityInfo,
  337. OUT PSECURITY_DESCRIPTOR * ppSecurityDescriptor
  338. )
  339. {
  340. return( ( (CKernelContext *)Context )->GetKernelRights(
  341. SecurityInfo,
  342. ppSecurityDescriptor
  343. ) );
  344. }
  345. DWORD
  346. MartaOpenKernelNamedObject(
  347. IN LPCWSTR pObjectName,
  348. IN ACCESS_MASK AccessMask,
  349. OUT PMARTA_CONTEXT pContext
  350. )
  351. {
  352. DWORD Result;
  353. CKernelContext* pKernelContext;
  354. pKernelContext = new CKernelContext;
  355. if ( pKernelContext == NULL )
  356. {
  357. return( ERROR_OUTOFMEMORY );
  358. }
  359. Result = pKernelContext->InitializeByName( pObjectName, AccessMask );
  360. if ( Result != ERROR_SUCCESS )
  361. {
  362. pKernelContext->Release();
  363. return( Result );
  364. }
  365. *pContext = pKernelContext;
  366. return( ERROR_SUCCESS );
  367. }
  368. DWORD
  369. MartaOpenKernelHandleObject(
  370. IN HANDLE Handle,
  371. IN ACCESS_MASK AccessMask,
  372. OUT PMARTA_CONTEXT pContext
  373. )
  374. {
  375. DWORD Result;
  376. CKernelContext* pKernelContext;
  377. pKernelContext = new CKernelContext;
  378. if ( pKernelContext == NULL )
  379. {
  380. return( ERROR_OUTOFMEMORY );
  381. }
  382. Result = pKernelContext->InitializeByHandle( Handle );
  383. if ( Result != ERROR_SUCCESS )
  384. {
  385. pKernelContext->Release();
  386. return( Result );
  387. }
  388. *pContext = pKernelContext;
  389. return( ERROR_SUCCESS );
  390. }
  391. DWORD
  392. MartaSetKernelRights(
  393. IN MARTA_CONTEXT Context,
  394. IN SECURITY_INFORMATION SecurityInfo,
  395. IN PSECURITY_DESCRIPTOR pSecurityDescriptor
  396. )
  397. {
  398. return( ( (CKernelContext *)Context )->SetKernelRights(
  399. SecurityInfo,
  400. pSecurityDescriptor
  401. ) );
  402. }
  403. //
  404. // Routines provided by AlanWar for accessing WmiGuid objects
  405. //
  406. HANDLE RWmiGuidHandle = NULL;
  407. _inline HANDLE WmipAllocEvent(
  408. VOID
  409. )
  410. {
  411. HANDLE EventHandle;
  412. EventHandle = (HANDLE)InterlockedExchangePointer(( PVOID *)&RWmiGuidHandle, NULL );
  413. if ( EventHandle == NULL ) {
  414. EventHandle = CreateEvent( NULL, FALSE, FALSE, NULL );
  415. }
  416. return( EventHandle );
  417. }
  418. _inline void WmipFreeEvent(
  419. HANDLE EventHandle
  420. )
  421. {
  422. if ( InterlockedCompareExchangePointer( &RWmiGuidHandle,
  423. EventHandle,
  424. NULL) != NULL ) {
  425. CloseHandle( EventHandle );
  426. }
  427. }
  428. ULONG RWmipSendWmiKMRequest(
  429. ULONG Ioctl,
  430. PVOID Buffer,
  431. ULONG InBufferSize,
  432. ULONG MaxBufferSize,
  433. ULONG *ReturnSize
  434. )
  435. /*+++
  436. Routine Description:
  437. This routine does the work of sending WMI requests to the WMI kernel
  438. mode device. Any retry errors returned by the WMI device are handled
  439. in this routine.
  440. Arguments:
  441. Ioctl is the IOCTL code to send to the WMI device
  442. Buffer is the input and output buffer for the call to the WMI device
  443. InBufferSize is the size of the buffer passed to the device
  444. MaxBufferSize is the maximum number of bytes that can be written
  445. into the buffer
  446. *ReturnSize on return has the actual number of bytes written in buffer
  447. Return Value:
  448. ERROR_SUCCESS or an error code
  449. ---*/
  450. {
  451. OVERLAPPED Overlapped;
  452. ULONG Status;
  453. BOOL IoctlSuccess;
  454. HANDLE WmipKMHandle = NULL;
  455. //
  456. // If device is not open for then open it now. The
  457. // handle is closed in the process detach dll callout (DlllMain)
  458. WmipKMHandle = CreateFile(WMIDataDeviceName,
  459. GENERIC_READ | GENERIC_WRITE,
  460. 0,
  461. NULL,
  462. OPEN_EXISTING,
  463. FILE_ATTRIBUTE_NORMAL |
  464. FILE_FLAG_OVERLAPPED,
  465. NULL);
  466. if (WmipKMHandle == (HANDLE)-1)
  467. {
  468. WmipKMHandle = NULL;
  469. return(GetLastError());
  470. }
  471. Overlapped.hEvent = WmipAllocEvent();
  472. if (Overlapped.hEvent == NULL)
  473. {
  474. return(ERROR_NOT_ENOUGH_MEMORY);
  475. }
  476. do
  477. {
  478. IoctlSuccess = DeviceIoControl(WmipKMHandle,
  479. Ioctl,
  480. Buffer,
  481. InBufferSize,
  482. Buffer,
  483. MaxBufferSize,
  484. ReturnSize,
  485. &Overlapped);
  486. if (GetLastError() == ERROR_IO_PENDING)
  487. {
  488. IoctlSuccess = GetOverlappedResult(WmipKMHandle,
  489. &Overlapped,
  490. ReturnSize,
  491. TRUE);
  492. }
  493. if (! IoctlSuccess)
  494. {
  495. Status = GetLastError();
  496. } else {
  497. Status = ERROR_SUCCESS;
  498. }
  499. } while (Status == ERROR_WMI_TRY_AGAIN);
  500. NtClose( WmipKMHandle );
  501. WmipFreeEvent(Overlapped.hEvent);
  502. return(Status);
  503. }
  504. //+---------------------------------------------------------------------------
  505. //
  506. // Function: OpenWmiGuidObject
  507. //
  508. // Synopsis: Gets a handle to the specified WmiGuid object
  509. //
  510. // Arguments: [IN pwszObject] -- Object to open
  511. // [IN AccessMask] -- Type of open to do
  512. // [OUT pHandle] -- Where the handle to the object
  513. // is returned
  514. //
  515. // Returns: ERROR_SUCCESS -- Success
  516. //
  517. //----------------------------------------------------------------------------
  518. DWORD
  519. OpenWmiGuidObject(IN LPWSTR pwszObject,
  520. IN ACCESS_MASK AccessMask,
  521. OUT PHANDLE pHandle)
  522. {
  523. DWORD dwErr;
  524. UNICODE_STRING GuidString;
  525. WMIOPENGUIDBLOCK WmiOpenGuidBlock;
  526. WCHAR GuidObjectNameBuffer[WmiGuidObjectNameLength+1];
  527. PWCHAR GuidObjectName = GuidObjectNameBuffer;
  528. ULONG ReturnSize;
  529. OBJECT_ATTRIBUTES ObjectAttributes;
  530. ULONG Length;
  531. Length = (wcslen(WmiGuidObjectDirectory) + wcslen(pwszObject) + 1) * sizeof(WCHAR);
  532. if ( Length > sizeof(GuidObjectNameBuffer) )
  533. {
  534. GuidObjectName = (PWCHAR)LocalAlloc( LPTR, Length );
  535. if ( GuidObjectName == NULL )
  536. {
  537. return ERROR_NOT_ENOUGH_MEMORY;
  538. }
  539. }
  540. wcscpy(GuidObjectName, WmiGuidObjectDirectory);
  541. wcscat(GuidObjectName, pwszObject);
  542. RtlInitUnicodeString(&GuidString, GuidObjectName);
  543. memset(&ObjectAttributes, 0, sizeof(OBJECT_ATTRIBUTES));
  544. ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
  545. ObjectAttributes.ObjectName = &GuidString;
  546. WmiOpenGuidBlock.ObjectAttributes = &ObjectAttributes;
  547. WmiOpenGuidBlock.DesiredAccess = AccessMask;
  548. dwErr = RWmipSendWmiKMRequest(IOCTL_WMI_OPEN_GUID,
  549. (PVOID)&WmiOpenGuidBlock,
  550. sizeof(WMIOPENGUIDBLOCK),
  551. sizeof(WMIOPENGUIDBLOCK),
  552. &ReturnSize);
  553. if (dwErr == ERROR_SUCCESS)
  554. {
  555. *pHandle = WmiOpenGuidBlock.Handle.Handle;
  556. }
  557. else
  558. {
  559. *pHandle = NULL;
  560. }
  561. if ( GuidObjectName != GuidObjectNameBuffer )
  562. {
  563. LocalFree( GuidObjectName );
  564. }
  565. return(dwErr);
  566. }