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.

724 lines
14 KiB

  1. /*
  2. * serial.c - Access serialization routines module.
  3. */
  4. /* Headers
  5. **********/
  6. #include "project.h"
  7. #pragma hdrstop
  8. #include "init.h"
  9. /* Types
  10. ********/
  11. /* process information */
  12. typedef struct _processinfo
  13. {
  14. HANDLE hModule;
  15. }
  16. PROCESSINFO;
  17. DECLARE_STANDARD_TYPES(PROCESSINFO);
  18. #ifdef DEBUG
  19. /* debug flags */
  20. typedef enum _serialdebugflags
  21. {
  22. SERIAL_DFL_BREAK_ON_PROCESS_ATTACH = 0x0001,
  23. SERIAL_DFL_BREAK_ON_THREAD_ATTACH = 0x0002,
  24. ALL_SERIAL_DFLAGS = (SERIAL_DFL_BREAK_ON_PROCESS_ATTACH |
  25. SERIAL_DFL_BREAK_ON_THREAD_ATTACH)
  26. }
  27. SERIALDEBUGFLAGS;
  28. #endif /* DEBUG */
  29. /* Module Variables
  30. *******************/
  31. /*
  32. * RAIDRAID: (16273) The use of Mnrcs in a shared data section is broken under
  33. * NT. To run under NT, this code should be changed to use a shared mutex
  34. * referenced by hMutex in Mpi.
  35. */
  36. /* critical section used for access serialization */
  37. PRIVATE_DATA NONREENTRANTCRITICALSECTION Mnrcs =
  38. {
  39. { 0 },
  40. #ifdef DEBUG
  41. INVALID_THREAD_ID,
  42. #endif /* DEBUG */
  43. FALSE
  44. };
  45. /* number of attached processes */
  46. PRIVATE_DATA ULONG MulcProcesses = 0;
  47. /* information about current process */
  48. /*
  49. * Initialize Mpi so it is actually put in the .instanc section instead of the
  50. * .bss section.
  51. */
  52. PRIVATE_DATA PROCESSINFO Mpi =
  53. {
  54. NULL
  55. };
  56. #ifdef DEBUG
  57. /* debug flags */
  58. PRIVATE_DATA DWORD MdwSerialModuleFlags = 0;
  59. /* .ini file switch descriptions */
  60. PRIVATE_DATA CBOOLINISWITCH cbisBreakOnProcessAttach =
  61. {
  62. IST_BOOL,
  63. TEXT( "BreakOnProcessAttach"),
  64. &MdwSerialModuleFlags,
  65. SERIAL_DFL_BREAK_ON_PROCESS_ATTACH
  66. };
  67. PRIVATE_DATA CBOOLINISWITCH cbisBreakOnThreadAttach =
  68. {
  69. IST_BOOL,
  70. TEXT("BreakOnThreadAttach"),
  71. &MdwSerialModuleFlags,
  72. SERIAL_DFL_BREAK_ON_THREAD_ATTACH
  73. };
  74. PRIVATE_DATA const PCVOID MrgcpcvisSerialModule[] =
  75. {
  76. &cbisBreakOnProcessAttach,
  77. &cbisBreakOnThreadAttach
  78. };
  79. #endif /* DEBUG */
  80. /***************************** Private Functions *****************************/
  81. /* Module Prototypes
  82. ********************/
  83. #ifdef DEBUG
  84. PRIVATE_CODE BOOL IsValidPCSERIALCONTROL(PCSERIALCONTROL);
  85. PRIVATE_CODE BOOL IsValidPCPROCESSINFO(PCPROCESSINFO);
  86. PRIVATE_CODE BOOL IsValidPCCRITICAL_SECTION(PCCRITICAL_SECTION);
  87. PRIVATE_CODE BOOL IsValidThreadId(DWORD);
  88. PRIVATE_CODE BOOL IsValidPCNONREENTRANTCRITICALSECTION(PCNONREENTRANTCRITICALSECTION);
  89. #endif
  90. #ifdef DEBUG
  91. /*
  92. ** IsValidPCSERIALCONTROL()
  93. **
  94. **
  95. **
  96. ** Arguments:
  97. **
  98. ** Returns:
  99. **
  100. ** Side Effects: none
  101. */
  102. PRIVATE_CODE BOOL IsValidPCSERIALCONTROL(PCSERIALCONTROL pcserctrl)
  103. {
  104. return(IS_VALID_READ_PTR(pcserctrl, CSERIALCONTROL) &&
  105. (! pcserctrl->AttachProcess ||
  106. IS_VALID_CODE_PTR(pcserctrl->AttachProcess, AttachProcess)) &&
  107. (! pcserctrl->DetachProcess ||
  108. IS_VALID_CODE_PTR(pcserctrl->DetachProcess, DetachProcess)) &&
  109. (! pcserctrl->AttachThread ||
  110. IS_VALID_CODE_PTR(pcserctrl->AttachThread, AttachThread)) &&
  111. (! pcserctrl->DetachThread||
  112. IS_VALID_CODE_PTR(pcserctrl->DetachThread, DetachThread)));
  113. }
  114. /*
  115. ** IsValidPCPROCESSINFO()
  116. **
  117. **
  118. **
  119. ** Arguments:
  120. **
  121. ** Returns:
  122. **
  123. ** Side Effects: none
  124. */
  125. PRIVATE_CODE BOOL IsValidPCPROCESSINFO(PCPROCESSINFO pcpi)
  126. {
  127. return(IS_VALID_READ_PTR(pcpi, CPROCESSINFO) &&
  128. IS_VALID_HANDLE(pcpi->hModule, MODULE));
  129. }
  130. /*
  131. ** IsValidPCCRITICAL_SECTION()
  132. **
  133. **
  134. **
  135. ** Arguments:
  136. **
  137. ** Returns:
  138. **
  139. ** Side Effects: none
  140. */
  141. PRIVATE_CODE BOOL IsValidPCCRITICAL_SECTION(PCCRITICAL_SECTION pccritsec)
  142. {
  143. return(IS_VALID_READ_PTR(pccritsec, CCRITICAL_SECTION));
  144. }
  145. /*
  146. ** IsValidThreadId()
  147. **
  148. **
  149. **
  150. ** Arguments:
  151. **
  152. ** Returns:
  153. **
  154. ** Side Effects: none
  155. */
  156. PRIVATE_CODE BOOL IsValidThreadId(DWORD dwThreadId)
  157. {
  158. return(dwThreadId != INVALID_THREAD_ID);
  159. }
  160. /*
  161. ** IsValidPCNONREENTRANTCRITICALSECTION()
  162. **
  163. **
  164. **
  165. ** Arguments:
  166. **
  167. ** Returns:
  168. **
  169. ** Side Effects: none
  170. */
  171. PRIVATE_CODE BOOL IsValidPCNONREENTRANTCRITICALSECTION(
  172. PCNONREENTRANTCRITICALSECTION pcnrcs)
  173. {
  174. /* bEntered may be any value. */
  175. return(IS_VALID_READ_PTR(pcnrcs, CNONREENTRANTCRITICALSECTION) &&
  176. IS_VALID_STRUCT_PTR(&(pcnrcs->critsec), CCRITICAL_SECTION) &&
  177. EVAL(pcnrcs->dwOwnerThread == INVALID_THREAD_ID ||
  178. IsValidThreadId(pcnrcs->dwOwnerThread)));
  179. }
  180. #endif
  181. /****************************** Public Functions *****************************/
  182. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  183. #ifdef DEBUG
  184. /*
  185. ** SetSerialModuleIniSwitches()
  186. **
  187. **
  188. **
  189. ** Arguments:
  190. **
  191. ** Returns:
  192. **
  193. ** Side Effects: none
  194. */
  195. PUBLIC_CODE BOOL SetSerialModuleIniSwitches(void)
  196. {
  197. BOOL bResult;
  198. bResult = SetIniSwitches(MrgcpcvisSerialModule,
  199. ARRAY_ELEMENTS(MrgcpcvisSerialModule));
  200. ASSERT(FLAGS_ARE_VALID(MdwSerialModuleFlags, ALL_SERIAL_DFLAGS));
  201. return(bResult);
  202. }
  203. #endif
  204. /*
  205. ** AttachProcess()
  206. **
  207. **
  208. **
  209. ** Arguments:
  210. **
  211. ** Returns:
  212. **
  213. ** Side Effects: none
  214. */
  215. PUBLIC_CODE BOOL AttachProcess(HMODULE hmod)
  216. {
  217. BOOL bResult;
  218. ReinitializeNonReentrantCriticalSection(&Mnrcs);
  219. bResult = EnterNonReentrantCriticalSection(&Mnrcs);
  220. if (bResult)
  221. {
  222. #ifdef DEBUG
  223. ASSERT(SetAllIniSwitches());
  224. TRACE_OUT((TEXT("AttachProcess(): Called for module %#lx."),
  225. hmod));
  226. if (IS_FLAG_SET(MdwSerialModuleFlags, SERIAL_DFL_BREAK_ON_PROCESS_ATTACH))
  227. {
  228. WARNING_OUT((TEXT("AttachProcess(): Breaking on process attach, as requested.")));
  229. DebugBreak();
  230. }
  231. #endif /* DEBUG */
  232. Mpi.hModule = hmod;
  233. ASSERT(MulcProcesses < ULONG_MAX);
  234. if (! MulcProcesses++)
  235. {
  236. TRACE_OUT((TEXT("AttachProcess(): First process attached. Calling InitializeDLL().")));
  237. bResult = InitializeDLL();
  238. }
  239. else
  240. {
  241. #ifdef PRIVATE_HEAP
  242. bResult = TRUE;
  243. #else
  244. /*
  245. * Initialize the per-instance memory manager heap for
  246. * subsequent processes.
  247. */
  248. bResult = InitMemoryManagerModule();
  249. #endif
  250. }
  251. if (bResult)
  252. {
  253. ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  254. if (g_cserctrl.AttachProcess)
  255. bResult = g_cserctrl.AttachProcess(hmod);
  256. }
  257. TRACE_OUT((TEXT("AttachProcess(): There are now %lu processes attached."),
  258. MulcProcesses));
  259. LeaveNonReentrantCriticalSection(&Mnrcs);
  260. }
  261. return(bResult);
  262. }
  263. /*
  264. ** DetachProcess()
  265. **
  266. **
  267. **
  268. ** Arguments:
  269. **
  270. ** Returns:
  271. **
  272. ** Side Effects: none
  273. */
  274. PUBLIC_CODE BOOL DetachProcess(HMODULE hmod)
  275. {
  276. BOOL bResult;
  277. bResult = EnterNonReentrantCriticalSection(&Mnrcs);
  278. if (bResult)
  279. {
  280. ASSERT(hmod == Mpi.hModule);
  281. ASSERT(MulcProcesses > 0);
  282. TRACE_OUT((TEXT("DetachProcess(): Called for module %#lx."),
  283. hmod));
  284. ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  285. if (g_cserctrl.DetachProcess)
  286. bResult = g_cserctrl.DetachProcess(hmod);
  287. if (--MulcProcesses)
  288. {
  289. bResult = TRUE;
  290. #ifndef PRIVATE_HEAP
  291. /*
  292. * Terminate the per-instance memory manager heap.
  293. */
  294. ExitMemoryManagerModule();
  295. #endif
  296. }
  297. else
  298. {
  299. TRACE_OUT((TEXT("DetachProcess(): Last process detached. Calling TerminateDLL().")));
  300. bResult = TerminateDLL();
  301. }
  302. TRACE_OUT((TEXT("DetachProcess(): There are now %lu processes attached."),
  303. MulcProcesses));
  304. LeaveNonReentrantCriticalSection(&Mnrcs);
  305. }
  306. /*
  307. * TODO: Clean up all this Mnrcs nonsense. It's all leftover goo
  308. * from Windows 95 and shared data sections (which we don't ues any
  309. * more).
  310. */
  311. DeleteCriticalSection(&Mnrcs.critsec);
  312. return(bResult);
  313. }
  314. /*
  315. ** AttachThread()
  316. **
  317. **
  318. **
  319. ** Arguments:
  320. **
  321. ** Returns:
  322. **
  323. ** Side Effects: none
  324. */
  325. PUBLIC_CODE BOOL AttachThread(HMODULE hmod)
  326. {
  327. BOOL bResult;
  328. bResult = EnterNonReentrantCriticalSection(&Mnrcs);
  329. if (bResult)
  330. {
  331. #ifdef DEBUG
  332. ASSERT(SetAllIniSwitches());
  333. TRACE_OUT((TEXT("AttachThread() called for module %#lx, thread ID %#lx."),
  334. hmod,
  335. GetCurrentThreadId()));
  336. if (IS_FLAG_SET(MdwSerialModuleFlags, SERIAL_DFL_BREAK_ON_THREAD_ATTACH))
  337. {
  338. WARNING_OUT((TEXT("AttachThread(): Breaking on thread attach, as requested.")));
  339. DebugBreak();
  340. }
  341. #endif
  342. ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  343. if (g_cserctrl.AttachThread)
  344. bResult = g_cserctrl.AttachThread(hmod);
  345. else
  346. bResult = TRUE;
  347. LeaveNonReentrantCriticalSection(&Mnrcs);
  348. }
  349. return(bResult);
  350. }
  351. /*
  352. ** DetachThread()
  353. **
  354. **
  355. **
  356. ** Arguments:
  357. **
  358. ** Returns:
  359. **
  360. ** Side Effects: none
  361. */
  362. PUBLIC_CODE BOOL DetachThread(HMODULE hmod)
  363. {
  364. BOOL bResult;
  365. bResult = EnterNonReentrantCriticalSection(&Mnrcs);
  366. if (bResult)
  367. {
  368. TRACE_OUT((TEXT("DetachThread() called for module %#lx, thread ID %#lx."),
  369. hmod,
  370. GetCurrentThreadId()));
  371. ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  372. if (g_cserctrl.DetachThread)
  373. bResult = g_cserctrl.DetachThread(hmod);
  374. else
  375. bResult = TRUE;
  376. LeaveNonReentrantCriticalSection(&Mnrcs);
  377. }
  378. return(bResult);
  379. }
  380. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  381. /*
  382. ** ReinitializeNonReentrantCriticalSection()
  383. **
  384. **
  385. **
  386. ** Arguments:
  387. **
  388. ** Returns:
  389. **
  390. ** Side Effects: none
  391. */
  392. PUBLIC_CODE void ReinitializeNonReentrantCriticalSection(
  393. PNONREENTRANTCRITICALSECTION pnrcs)
  394. {
  395. ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  396. InitializeCriticalSectionAndSpinCount(&(pnrcs->critsec), 0);
  397. return;
  398. }
  399. /*
  400. ** EnterNonReentrantCriticalSection()
  401. **
  402. **
  403. **
  404. ** Arguments:
  405. **
  406. ** Returns:
  407. **
  408. ** Side Effects: none
  409. */
  410. PUBLIC_CODE BOOL EnterNonReentrantCriticalSection(
  411. PNONREENTRANTCRITICALSECTION pnrcs)
  412. {
  413. BOOL bEntered;
  414. #ifdef DEBUG
  415. BOOL bBlocked;
  416. ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  417. /* Is the critical section already owned by another thread? */
  418. /* Use pnrcs->bEntered and pnrcs->dwOwnerThread unprotected here. */
  419. bBlocked = (pnrcs->bEntered &&
  420. GetCurrentThreadId() != pnrcs->dwOwnerThread);
  421. if (bBlocked)
  422. WARNING_OUT((TEXT("EnterNonReentrantCriticalSection(): Blocking thread %lx. Critical section is already owned by thread %#lx."),
  423. GetCurrentThreadId(),
  424. pnrcs->dwOwnerThread));
  425. #endif
  426. EnterCriticalSection(&(pnrcs->critsec));
  427. bEntered = (! pnrcs->bEntered);
  428. if (bEntered)
  429. {
  430. pnrcs->bEntered = TRUE;
  431. #ifdef DEBUG
  432. pnrcs->dwOwnerThread = GetCurrentThreadId();
  433. if (bBlocked)
  434. WARNING_OUT((TEXT("EnterNonReentrantCriticalSection(): Unblocking thread %lx. Critical section is now owned by this thread."),
  435. pnrcs->dwOwnerThread));
  436. #endif
  437. }
  438. else
  439. {
  440. LeaveCriticalSection(&(pnrcs->critsec));
  441. ERROR_OUT((TEXT("EnterNonReentrantCriticalSection(): Thread %#lx attempted to reenter non-reentrant code."),
  442. GetCurrentThreadId()));
  443. }
  444. return(bEntered);
  445. }
  446. /*
  447. ** LeaveNonReentrantCriticalSection()
  448. **
  449. **
  450. **
  451. ** Arguments:
  452. **
  453. ** Returns:
  454. **
  455. ** Side Effects: none
  456. */
  457. PUBLIC_CODE void LeaveNonReentrantCriticalSection(
  458. PNONREENTRANTCRITICALSECTION pnrcs)
  459. {
  460. ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  461. if (EVAL(pnrcs->bEntered))
  462. {
  463. pnrcs->bEntered = FALSE;
  464. #ifdef DEBUG
  465. pnrcs->dwOwnerThread = INVALID_THREAD_ID;
  466. #endif
  467. LeaveCriticalSection(&(pnrcs->critsec));
  468. }
  469. return;
  470. }
  471. #ifdef DEBUG
  472. /*
  473. ** NonReentrantCriticalSectionIsOwned()
  474. **
  475. **
  476. **
  477. ** Arguments:
  478. **
  479. ** Returns:
  480. **
  481. ** Side Effects: none
  482. */
  483. PUBLIC_CODE BOOL NonReentrantCriticalSectionIsOwned(
  484. PCNONREENTRANTCRITICALSECTION pcnrcs)
  485. {
  486. return(pcnrcs->bEntered);
  487. }
  488. #endif
  489. /*
  490. ** BeginExclusiveAccess()
  491. **
  492. **
  493. **
  494. ** Arguments:
  495. **
  496. ** Returns:
  497. **
  498. ** Side Effects: none
  499. */
  500. PUBLIC_CODE BOOL BeginExclusiveAccess(void)
  501. {
  502. return(EnterNonReentrantCriticalSection(&Mnrcs));
  503. }
  504. /*
  505. ** EndExclusiveAccess()
  506. **
  507. **
  508. **
  509. ** Arguments:
  510. **
  511. ** Returns:
  512. **
  513. ** Side Effects: none
  514. */
  515. PUBLIC_CODE void EndExclusiveAccess(void)
  516. {
  517. LeaveNonReentrantCriticalSection(&Mnrcs);
  518. return;
  519. }
  520. #ifdef DEBUG
  521. /*
  522. ** AccessIsExclusive()
  523. **
  524. **
  525. **
  526. ** Arguments:
  527. **
  528. ** Returns:
  529. **
  530. ** Side Effects: none
  531. */
  532. PUBLIC_CODE BOOL AccessIsExclusive(void)
  533. {
  534. return(NonReentrantCriticalSectionIsOwned(&Mnrcs));
  535. }
  536. #endif /* DEBUG */
  537. /*
  538. ** GetThisModulesHandle()
  539. **
  540. **
  541. **
  542. ** Arguments:
  543. **
  544. ** Returns:
  545. **
  546. ** Side Effects: none
  547. */
  548. PUBLIC_CODE HMODULE GetThisModulesHandle(void)
  549. {
  550. ASSERT(IS_VALID_STRUCT_PTR((PCPROCESSINFO)&Mpi, CPROCESSINFO));
  551. return(Mpi.hModule);
  552. }