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.

547 lines
12 KiB

  1. //+----------------------------------------------------------------------------//+----------------------------------------------------------------------------
  2. //
  3. // Copyright (C) 2001, Microsoft Corporation
  4. //
  5. // File: dfsumr.c
  6. //
  7. // Contents:
  8. //
  9. //
  10. // Functions:
  11. //
  12. // Author - Rohan Phillips (Rohanp)
  13. //-----------------------------------------------------------------------------
  14. #include "ntifs.h"
  15. #include <windef.h>
  16. #include <DfsReferralData.h>
  17. #include <midatlax.h>
  18. #include <rxcontx.h>
  19. #include <dfsumr.h>
  20. #include <umrx.h>
  21. #include <dfsumrctrl.h>
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE, DfsInitializeUmrResources)
  24. #pragma alloc_text(PAGE, DfsDeInitializeUmrResources)
  25. #pragma alloc_text(PAGE, DfsWaitForPendingClients)
  26. #pragma alloc_text(PAGE, DfsStartupUMRx)
  27. #pragma alloc_text(PAGE, DfsTeardownUMRx)
  28. #pragma alloc_text(PAGE, DfsProcessUMRxPacket)
  29. #pragma alloc_text(PAGE, AddUmrRef)
  30. #pragma alloc_text(PAGE, ReleaseUmrRef)
  31. #pragma alloc_text(PAGE, IsUmrEnabled)
  32. #pragma alloc_text(PAGE, LockUmrShared)
  33. #pragma alloc_text(PAGE, GetUMRxEngineFromRxContext)
  34. #endif
  35. #define DFS_INIT_REFLOCK 0x00000001
  36. #define DFS_INIT_UMRXENG 0x00000002
  37. #define DFS_INIT_CONTEXT 0x00000004
  38. //
  39. // Number of usecs that the thread disabling the reflection should wait
  40. // between checks. negative value for relative time.
  41. // 1,000,000 usecs => 1 sec
  42. //
  43. #define DFS_UMR_DISABLE_DELAY -100000
  44. BOOL ReflectionEngineInitialized = FALSE;
  45. ULONG cUserModeReflectionsInProgress = 0;
  46. NTSTATUS g_CheckStatus = 0xFFFFFFFF;
  47. DWORD InitilizationStatus = 0;
  48. PERESOURCE gReflectionLock = NULL;
  49. PUMRX_ENGINE g_pUMRxEngine = NULL;
  50. PERESOURCE
  51. CreateResource(void ) ;
  52. void
  53. ReleaseResource(PERESOURCE pResource ) ;
  54. //+-------------------------------------------------------------------------
  55. //
  56. // Function: DfsInitializeUmrResources
  57. //
  58. // Arguments:
  59. //
  60. // Returns: Status
  61. // ERROR_SUCCESS on success
  62. // ERROR status code otherwise
  63. //
  64. //
  65. // Description: Initializes all resources neder for the usermode reflector
  66. //
  67. //--------------------------------------------------------------------------
  68. NTSTATUS
  69. DfsInitializeUmrResources(void)
  70. {
  71. NTSTATUS Status = STATUS_SUCCESS;
  72. PAGED_CODE();
  73. gReflectionLock = CreateResource();
  74. if(gReflectionLock != NULL)
  75. {
  76. InitilizationStatus |= DFS_INIT_REFLOCK;
  77. }
  78. else
  79. {
  80. Status = STATUS_INSUFFICIENT_RESOURCES;
  81. goto Exit;
  82. }
  83. g_pUMRxEngine = CreateUMRxEngine();
  84. if(g_pUMRxEngine != NULL)
  85. {
  86. InitilizationStatus |= DFS_INIT_UMRXENG;
  87. }
  88. else
  89. {
  90. Status = STATUS_INSUFFICIENT_RESOURCES;
  91. goto Exit;
  92. }
  93. Status = DfsInitializeContextResources();
  94. if(Status == STATUS_SUCCESS)
  95. {
  96. InitilizationStatus |= DFS_INIT_CONTEXT;
  97. }
  98. Exit:
  99. return Status;
  100. }
  101. //+-------------------------------------------------------------------------
  102. //
  103. // Function: DfsDeInitializeUmrResources
  104. //
  105. // Arguments:
  106. //
  107. // Returns: Status
  108. // ERROR_SUCCESS on success
  109. // ERROR status code otherwise
  110. //
  111. //
  112. // Description: Releases all resources neder for the usermode reflector
  113. //
  114. //--------------------------------------------------------------------------
  115. void
  116. DfsDeInitializeUmrResources(void)
  117. {
  118. PAGED_CODE();
  119. if(InitilizationStatus & DFS_INIT_REFLOCK)
  120. {
  121. ReleaseResource(gReflectionLock);
  122. gReflectionLock = NULL;
  123. }
  124. if(InitilizationStatus & DFS_INIT_UMRXENG)
  125. {
  126. if(g_pUMRxEngine != NULL)
  127. {
  128. FinalizeUMRxEngine (g_pUMRxEngine);
  129. g_pUMRxEngine = NULL;
  130. }
  131. }
  132. if(InitilizationStatus & DFS_INIT_CONTEXT)
  133. {
  134. DfsDeInitializeContextResources();
  135. }
  136. }
  137. PERESOURCE
  138. CreateResource(void )
  139. {
  140. PERESOURCE pResource = NULL;
  141. PAGED_CODE();
  142. pResource = ExAllocatePoolWithTag( NonPagedPool,
  143. sizeof( ERESOURCE ),
  144. 'DfsR');
  145. if( pResource )
  146. {
  147. if( !NT_SUCCESS( ExInitializeResourceLite( pResource ) ) )
  148. {
  149. ExFreePool( pResource ) ;
  150. pResource = NULL ;
  151. }
  152. }
  153. return pResource ;
  154. }
  155. void
  156. ReleaseResource(PERESOURCE pResource )
  157. {
  158. PAGED_CODE();
  159. ASSERT( pResource != 0 ) ;
  160. if( pResource )
  161. {
  162. ExDeleteResourceLite( pResource ) ;
  163. ExFreePool( pResource ) ;
  164. }
  165. }
  166. //+-------------------------------------------------------------------------
  167. //
  168. // Function: DfsEnableReflectionEngine
  169. //
  170. // Arguments:
  171. //
  172. // Returns: Status
  173. // ERROR_SUCCESS on success
  174. // ERROR status code otherwise
  175. //
  176. //
  177. // Description: Changes the reflector state to stopped
  178. //
  179. //--------------------------------------------------------------------------
  180. NTSTATUS
  181. DfsEnableReflectionEngine(void)
  182. {
  183. NTSTATUS Status = STATUS_SUCCESS;
  184. PAGED_CODE();
  185. ReflectionEngineInitialized = TRUE;
  186. if(g_pUMRxEngine)
  187. {
  188. InterlockedExchange(&g_pUMRxEngine->Q.State,
  189. UMRX_ENGINE_STATE_STOPPED);
  190. }
  191. return Status;
  192. }
  193. //+-------------------------------------------------------------------------
  194. //
  195. // Function: DfsWaitForPendingClients
  196. //
  197. // Arguments:
  198. //
  199. // Returns: Status
  200. // ERROR_SUCCESS on success
  201. // ERROR status code otherwise
  202. //
  203. //
  204. // Description: Waits for all clients to exit relector before returning
  205. //
  206. //--------------------------------------------------------------------------
  207. NTSTATUS
  208. DfsWaitForPendingClients(void)
  209. {
  210. BOOLEAN fDone = FALSE;
  211. NTSTATUS Status = STATUS_SUCCESS;
  212. LARGE_INTEGER liDelay;
  213. liDelay.QuadPart = DFS_UMR_DISABLE_DELAY;
  214. PAGED_CODE();
  215. while (!fDone)
  216. {
  217. ExAcquireResourceExclusiveLite(&g_pUMRxEngine->Q.Lock,TRUE);
  218. if (ReflectionEngineInitialized)
  219. {
  220. if (0 == g_pUMRxEngine->cUserModeReflectionsInProgress)
  221. {
  222. fDone = TRUE;
  223. }
  224. else
  225. {
  226. }
  227. }
  228. else
  229. {
  230. fDone = TRUE;
  231. }
  232. ExReleaseResourceForThreadLite(&g_pUMRxEngine->Q.Lock,ExGetCurrentResourceThread());
  233. if (!fDone)
  234. {
  235. KeDelayExecutionThread(UserMode, FALSE, &liDelay);
  236. }
  237. }
  238. return Status;
  239. }
  240. //+-------------------------------------------------------------------------
  241. //
  242. // Function: DfsStartupUMRx
  243. //
  244. // Arguments:
  245. //
  246. // Returns: Status
  247. // ERROR_SUCCESS on success
  248. // ERROR status code otherwise
  249. //
  250. //
  251. // Description: Starts the reflector engine
  252. //
  253. //--------------------------------------------------------------------------
  254. NTSTATUS
  255. DfsStartupUMRx(void)
  256. {
  257. NTSTATUS Status = STATUS_SUCCESS;
  258. PAGED_CODE();
  259. ExAcquireResourceExclusiveLite(gReflectionLock,TRUE);
  260. Status = UMRxEngineRestart(g_pUMRxEngine);
  261. if(Status == STATUS_SUCCESS)
  262. {
  263. ReflectionEngineInitialized = TRUE;
  264. }
  265. ExReleaseResourceForThreadLite(gReflectionLock,ExGetCurrentResourceThread());
  266. return Status;
  267. }
  268. //+-------------------------------------------------------------------------
  269. //
  270. // Function: DfsTeardownUMRx
  271. //
  272. // Arguments:
  273. //
  274. // Returns: Status
  275. // ERROR_SUCCESS on success
  276. // ERROR status code otherwise
  277. //
  278. //
  279. // Description: Stops the reflector engine
  280. //
  281. //--------------------------------------------------------------------------
  282. NTSTATUS
  283. DfsTeardownUMRx(void)
  284. {
  285. NTSTATUS Status = STATUS_SUCCESS;
  286. PAGED_CODE();
  287. if(g_pUMRxEngine)
  288. {
  289. Status = UMRxEngineReleaseThreads(g_pUMRxEngine);
  290. }
  291. ReflectionEngineInitialized = FALSE;
  292. return Status;
  293. }
  294. //+-------------------------------------------------------------------------
  295. //
  296. // Function: DfsProcessUMRxPacket
  297. //
  298. // Arguments:
  299. //
  300. // Returns: Status
  301. // ERROR_SUCCESS on success
  302. // ERROR status code otherwise
  303. //
  304. //
  305. // Description: Processes a packet from usermode
  306. //
  307. //--------------------------------------------------------------------------
  308. NTSTATUS
  309. DfsProcessUMRxPacket(
  310. IN PVOID InputBuffer,
  311. IN ULONG InputBufferLength,
  312. OUT PVOID OutputBuffer,
  313. IN ULONG OutputBufferLength,
  314. IN OUT PIO_STATUS_BLOCK pIoStatusBlock)
  315. {
  316. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  317. BOOLEAN fReturnImmediately = FALSE;
  318. IO_STATUS_BLOCK Iosb;
  319. PAGED_CODE();
  320. if ((InputBuffer == NULL) && (OutputBuffer == NULL))
  321. {
  322. UMRxEngineCompleteQueuedRequests(
  323. g_pUMRxEngine,
  324. STATUS_INSUFFICIENT_RESOURCES,
  325. FALSE);
  326. Status = STATUS_SUCCESS;
  327. goto Exit;
  328. }
  329. //
  330. // Recd a response packet from umode - process it
  331. //
  332. Status = UMRxCompleteUserModeRequest(
  333. g_pUMRxEngine,
  334. (PUMRX_USERMODE_WORKITEM) InputBuffer,
  335. InputBufferLength,
  336. TRUE,
  337. &Iosb,
  338. &fReturnImmediately
  339. );
  340. if( !NT_SUCCESS(Iosb.Status) )
  341. {
  342. }
  343. if (fReturnImmediately)
  344. {
  345. pIoStatusBlock->Status = STATUS_SUCCESS;
  346. pIoStatusBlock->Information = 0;
  347. goto Exit;
  348. }
  349. //
  350. // Remove a request from the Engine and process it
  351. //
  352. Status = UMRxEngineProcessRequest(
  353. g_pUMRxEngine,
  354. (PUMRX_USERMODE_WORKITEM) OutputBuffer,
  355. OutputBufferLength,
  356. &OutputBufferLength
  357. );
  358. if( !NT_SUCCESS(Status) )
  359. {
  360. //
  361. // error processing request
  362. //
  363. }
  364. pIoStatusBlock->Information = OutputBufferLength;
  365. Exit:
  366. pIoStatusBlock->Status = Status;
  367. return Status;
  368. }
  369. //+-------------------------------------------------------------------------
  370. //
  371. // Function: AddUmrRef
  372. //
  373. // Arguments:
  374. //
  375. // Returns: Number of clients using reflector
  376. //
  377. //
  378. // Description: Increments the number of clients using the reflector
  379. //
  380. //--------------------------------------------------------------------------
  381. LONG
  382. AddUmrRef(void)
  383. {
  384. LONG cRefs = 0;
  385. PAGED_CODE();
  386. cRefs = InterlockedIncrement(&g_pUMRxEngine->cUserModeReflectionsInProgress);
  387. //DFS_TRACE_HIGH (KUMR_DETAIL, "AddUmrRef %d\n", cRefs);
  388. ASSERT(cRefs > 0);
  389. return cRefs;
  390. }
  391. //+-------------------------------------------------------------------------
  392. //
  393. // Function: ReleaseUmrRef
  394. //
  395. // Arguments:
  396. //
  397. // Returns: Number of clients using reflector
  398. //
  399. //
  400. // Description: Deccrements the number of clients using the reflector
  401. //
  402. //--------------------------------------------------------------------------
  403. LONG
  404. ReleaseUmrRef(void)
  405. {
  406. LONG cRefs = 0;
  407. PAGED_CODE();
  408. cRefs = InterlockedDecrement(&g_pUMRxEngine->cUserModeReflectionsInProgress);
  409. //DFS_TRACE_HIGH (KUMR_DETAIL, "ReleaseUmrRef %d\n", cRefs);
  410. //ASSERT(cRefs >= 0); //this is a harmless assert. It's removed for now.
  411. return cRefs;
  412. }
  413. //+-------------------------------------------------------------------------
  414. //
  415. // Function: GetUMRxEngineFromRxContext
  416. //
  417. // Arguments:
  418. //
  419. // Returns: A pointer to the reflector engine
  420. //
  421. //
  422. // Description: returns a pointer to the reflector engine
  423. //
  424. //--------------------------------------------------------------------------
  425. PUMRX_ENGINE
  426. GetUMRxEngineFromRxContext(void)
  427. {
  428. PAGED_CODE();
  429. return g_pUMRxEngine;
  430. }
  431. BOOL IsUmrEnabled(void)
  432. {
  433. PAGED_CODE();
  434. return ReflectionEngineInitialized;
  435. }
  436. BOOLEAN LockUmrShared(void)
  437. {
  438. BOOLEAN fAcquired = FALSE;
  439. PAGED_CODE();
  440. fAcquired = ExAcquireResourceSharedLite(&g_pUMRxEngine->Q.Lock, FALSE);
  441. return fAcquired;
  442. }
  443. void UnLockUmrShared(void)
  444. {
  445. PAGED_CODE();
  446. ExReleaseResourceForThreadLite (&g_pUMRxEngine->Q.Lock,ExGetCurrentResourceThread());
  447. }