serial.c
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 11k
Category:

Windows Kernel

Development Platform:

Visual C++

  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. #pragma data_seg(DATA_SEG_PER_INSTANCE)
  32. /* critical section used for access serialization */
  33. PRIVATE_DATA NONREENTRANTCRITICALSECTION s_nrcs =
  34. {
  35.    { 0 },
  36. #ifdef DEBUG
  37.    INVALID_THREAD_ID,
  38. #endif   /* DEBUG */
  39.    FALSE
  40. };
  41. /* information about current process */
  42. /*
  43.  * Initialize s_pi so it is actually put in the .instanc section instead of the
  44.  * .bss section.
  45.  */
  46. PRIVATE_DATA PROCESSINFO s_pi =
  47. {
  48.    NULL
  49. };
  50. #pragma data_seg()
  51. #ifdef DEBUG
  52. #pragma data_seg(DATA_SEG_SHARED)
  53. /* debug flags */
  54. PRIVATE_DATA DWORD s_dwSerialModuleFlags = 0;
  55. #pragma data_seg(DATA_SEG_READ_ONLY)
  56. /* .ini file switch descriptions */
  57. PRIVATE_DATA CBOOLINISWITCH s_cbisBreakOnProcessAttach =
  58. {
  59.    IST_BOOL,
  60.    "BreakOnProcessAttach",
  61.    &s_dwSerialModuleFlags,
  62.    SERIAL_DFL_BREAK_ON_PROCESS_ATTACH
  63. };
  64. PRIVATE_DATA CBOOLINISWITCH s_cbisBreakOnThreadAttach =
  65. {
  66.    IST_BOOL,
  67.    "BreakOnThreadAttach",
  68.    &s_dwSerialModuleFlags,
  69.    SERIAL_DFL_BREAK_ON_THREAD_ATTACH
  70. };
  71. PRIVATE_DATA const PCVOID s_rgcpcvisSerialModule[] =
  72. {
  73.    &s_cbisBreakOnProcessAttach,
  74.    &s_cbisBreakOnThreadAttach
  75. };
  76. #pragma data_seg()
  77. #endif   /* DEBUG */
  78. /***************************** Private Functions *****************************/
  79. /* Module Prototypes
  80.  ********************/
  81. #ifdef DEBUG
  82. PRIVATE_CODE BOOL IsValidPCSERIALCONTROL(PCSERIALCONTROL);
  83. PRIVATE_CODE BOOL IsValidPCPROCESSINFO(PCPROCESSINFO);
  84. PRIVATE_CODE BOOL IsValidPCCRITICAL_SECTION(PCCRITICAL_SECTION);
  85. PRIVATE_CODE BOOL IsValidThreadId(DWORD);
  86. PRIVATE_CODE BOOL IsValidPCNONREENTRANTCRITICALSECTION(PCNONREENTRANTCRITICALSECTION);
  87. #endif
  88. #ifdef DEBUG
  89. PRIVATE_CODE BOOL IsValidPCSERIALCONTROL(PCSERIALCONTROL pcserctrl)
  90. {
  91.    return(IS_VALID_READ_PTR(pcserctrl, CSERIALCONTROL) &&
  92.           (! pcserctrl->AttachProcess ||
  93.            IS_VALID_CODE_PTR(pcserctrl->AttachProcess, AttachProcess)) &&
  94.           (! pcserctrl->DetachProcess ||
  95.            IS_VALID_CODE_PTR(pcserctrl->DetachProcess, DetachProcess)) &&
  96.           (! pcserctrl->AttachThread ||
  97.            IS_VALID_CODE_PTR(pcserctrl->AttachThread, AttachThread)) &&
  98.           (! pcserctrl->DetachThread||
  99.            IS_VALID_CODE_PTR(pcserctrl->DetachThread, DetachThread)));
  100. }
  101. PRIVATE_CODE BOOL IsValidPCPROCESSINFO(PCPROCESSINFO pcpi)
  102. {
  103.    return(IS_VALID_READ_PTR(pcpi, CPROCESSINFO) &&
  104.           IS_VALID_HANDLE(pcpi->hModule, MODULE));
  105. }
  106. PRIVATE_CODE BOOL IsValidPCCRITICAL_SECTION(PCCRITICAL_SECTION pccritsec)
  107. {
  108.    return(IS_VALID_READ_PTR(pccritsec, CCRITICAL_SECTION));
  109. }
  110. PRIVATE_CODE BOOL IsValidThreadId(DWORD dwThreadId)
  111. {
  112.    return(dwThreadId != INVALID_THREAD_ID);
  113. }
  114. PRIVATE_CODE BOOL IsValidPCNONREENTRANTCRITICALSECTION(
  115.                                           PCNONREENTRANTCRITICALSECTION pcnrcs)
  116. {
  117.    /* bEntered may be any value. */
  118.    return(IS_VALID_READ_PTR(pcnrcs, CNONREENTRANTCRITICALSECTION) &&
  119.           IS_VALID_STRUCT_PTR(&(pcnrcs->critsec), CCRITICAL_SECTION) &&
  120.           EVAL(pcnrcs->dwOwnerThread == INVALID_THREAD_ID ||
  121.                IsValidThreadId(pcnrcs->dwOwnerThread)));
  122. }
  123. #endif
  124. /****************************** Public Functions *****************************/
  125. #pragma warning(disable:4100) /* "unreferenced formal parameter" warning */
  126. #ifdef DEBUG
  127. PUBLIC_CODE BOOL SetSerialModuleIniSwitches(void)
  128. {
  129.    BOOL bResult;
  130.    bResult = SetIniSwitches(s_rgcpcvisSerialModule,
  131.                             ARRAY_ELEMENTS(s_rgcpcvisSerialModule));
  132.    ASSERT(FLAGS_ARE_VALID(s_dwSerialModuleFlags, ALL_SERIAL_DFLAGS));
  133.    return(bResult);
  134. }
  135. #endif
  136. PUBLIC_CODE BOOL AttachProcess(HMODULE hmod)
  137. {
  138.    BOOL bResult;
  139.    ASSERT(IS_VALID_HANDLE(hmod, MODULE));
  140.    InitializeNonReentrantCriticalSection(&s_nrcs);
  141.    bResult = EnterNonReentrantCriticalSection(&s_nrcs);
  142.    if (bResult)
  143.    {
  144. #ifdef DEBUG
  145.       ASSERT(SetAllIniSwitches());
  146.       TRACE_OUT(("AttachProcess(): Called for module %#lx.",
  147.                  hmod));
  148.       if (IS_FLAG_SET(s_dwSerialModuleFlags, SERIAL_DFL_BREAK_ON_PROCESS_ATTACH))
  149.       {
  150.          WARNING_OUT(("AttachProcess(): Breaking on process attach, as requested."));
  151. #ifndef MAINWIN
  152.          DebugBreak();
  153. #endif
  154.       }
  155. #endif   /* DEBUG */
  156.       s_pi.hModule = hmod;
  157.       ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  158.       if (g_cserctrl.AttachProcess)
  159.          bResult = g_cserctrl.AttachProcess(hmod);
  160.       LeaveNonReentrantCriticalSection(&s_nrcs);
  161.    }
  162.    return(bResult);
  163. }
  164. PUBLIC_CODE BOOL DetachProcess(HMODULE hmod)
  165. {
  166.    BOOL bResult;
  167.    ASSERT(IS_VALID_HANDLE(hmod, MODULE));
  168.    bResult = EnterNonReentrantCriticalSection(&s_nrcs);
  169.    if (bResult)
  170.    {
  171.       ASSERT(hmod == s_pi.hModule);
  172.       TRACE_OUT(("DetachProcess(): Called for module %#lx.",
  173.                  hmod));
  174.       ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  175.       if (g_cserctrl.DetachProcess)
  176.          bResult = g_cserctrl.DetachProcess(hmod);
  177.       LeaveNonReentrantCriticalSection(&s_nrcs);
  178.       DeleteNonReentrantCriticalSection(&s_nrcs);
  179.    }
  180.    return(bResult);
  181. }
  182. PUBLIC_CODE BOOL AttachThread(HMODULE hmod)
  183. {
  184.    BOOL bResult;
  185.    ASSERT(IS_VALID_HANDLE(hmod, MODULE));
  186.    bResult = EnterNonReentrantCriticalSection(&s_nrcs);
  187.    if (bResult)
  188.    {
  189. #ifdef DEBUG
  190.       ASSERT(SetAllIniSwitches());
  191.       TRACE_OUT(("AttachThread() called for module %#lx, thread ID %#lx.",
  192.                  hmod,
  193.                  GetCurrentThreadId()));
  194.       if (IS_FLAG_SET(s_dwSerialModuleFlags, SERIAL_DFL_BREAK_ON_THREAD_ATTACH))
  195.       {
  196.          WARNING_OUT(("AttachThread(): Breaking on thread attach, as requested."));
  197. #ifndef MAINWIN
  198.          DebugBreak();
  199. #endif 
  200.       }
  201. #endif
  202.       ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  203.       if (g_cserctrl.AttachThread)
  204.          bResult = g_cserctrl.AttachThread(hmod);
  205.       else
  206.          bResult = TRUE;
  207.       LeaveNonReentrantCriticalSection(&s_nrcs);
  208.    }
  209.    return(bResult);
  210. }
  211. PUBLIC_CODE BOOL DetachThread(HMODULE hmod)
  212. {
  213.    BOOL bResult;
  214.    ASSERT(IS_VALID_HANDLE(hmod, MODULE));
  215.    bResult = EnterNonReentrantCriticalSection(&s_nrcs);
  216.    if (bResult)
  217.    {
  218.       TRACE_OUT(("DetachThread() called for module %#lx, thread ID %#lx.",
  219.                  hmod,
  220.                  GetCurrentThreadId()));
  221.       ASSERT(IS_VALID_STRUCT_PTR(&g_cserctrl, CSERIALCONTROL));
  222.       if (g_cserctrl.DetachThread)
  223.          bResult = g_cserctrl.DetachThread(hmod);
  224.       else
  225.          bResult = TRUE;
  226.       LeaveNonReentrantCriticalSection(&s_nrcs);
  227.    }
  228.    return(bResult);
  229. }
  230. #pragma warning(default:4100) /* "unreferenced formal parameter" warning */
  231. PUBLIC_CODE void InitializeNonReentrantCriticalSection(
  232.                                           PNONREENTRANTCRITICALSECTION pnrcs)
  233. {
  234.    ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  235.    InitializeCriticalSection(&(pnrcs->critsec));
  236.    pnrcs->bEntered = FALSE;
  237. #ifdef DEBUG
  238.    pnrcs->dwOwnerThread = INVALID_THREAD_ID;
  239. #endif
  240.    return;
  241. }
  242. PUBLIC_CODE BOOL EnterNonReentrantCriticalSection(
  243.                                           PNONREENTRANTCRITICALSECTION pnrcs)
  244. {
  245.    BOOL bEntered;
  246. #ifdef DEBUG
  247.    BOOL bBlocked;
  248.    ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  249.    /* Is the critical section already owned by another thread? */
  250.    /* Use pnrcs->bEntered and pnrcs->dwOwnerThread unprotected here. */
  251.    bBlocked = (pnrcs->bEntered &&
  252.                GetCurrentThreadId() != pnrcs->dwOwnerThread);
  253.    if (bBlocked)
  254.       TRACE_OUT(("EnterNonReentrantCriticalSection(): Blocking thread %lx.  Critical section is already owned by thread %#lx.",
  255.                  GetCurrentThreadId(),
  256.                  pnrcs->dwOwnerThread));
  257. #endif
  258.    EnterCriticalSection(&(pnrcs->critsec));
  259.    bEntered = (! pnrcs->bEntered);
  260.    if (bEntered)
  261.    {
  262.       pnrcs->bEntered = TRUE;
  263. #ifdef DEBUG
  264.       pnrcs->dwOwnerThread = GetCurrentThreadId();
  265.       if (bBlocked)
  266.          TRACE_OUT(("EnterNonReentrantCriticalSection(): Unblocking thread %lx.  Critical section is now owned by this thread.",
  267.                     pnrcs->dwOwnerThread));
  268. #endif
  269.    }
  270.    else
  271.    {
  272.       LeaveCriticalSection(&(pnrcs->critsec));
  273.       ERROR_OUT(("EnterNonReentrantCriticalSection(): Thread %#lx attempted to reenter non-reentrant code.",
  274.                  GetCurrentThreadId()));
  275.    }
  276.    return(bEntered);
  277. }
  278. PUBLIC_CODE void LeaveNonReentrantCriticalSection(
  279.                                           PNONREENTRANTCRITICALSECTION pnrcs)
  280. {
  281.    ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  282.    if (EVAL(pnrcs->bEntered))
  283.    {
  284.       pnrcs->bEntered = FALSE;
  285. #ifdef DEBUG
  286.       pnrcs->dwOwnerThread = INVALID_THREAD_ID;
  287. #endif
  288.       LeaveCriticalSection(&(pnrcs->critsec));
  289.    }
  290.    return;
  291. }
  292. PUBLIC_CODE void DeleteNonReentrantCriticalSection(
  293.                                           PNONREENTRANTCRITICALSECTION pnrcs)
  294. {
  295.    ASSERT(IS_VALID_STRUCT_PTR(pnrcs, CNONREENTRANTCRITICALSECTION));
  296.    ASSERT(! pnrcs->bEntered);
  297.    ASSERT(pnrcs->dwOwnerThread == INVALID_THREAD_ID);
  298.    DeleteCriticalSection(&(pnrcs->critsec));
  299.    return;
  300. }
  301. #ifdef DEBUG
  302. PUBLIC_CODE BOOL NonReentrantCriticalSectionIsOwned(
  303.                                           PCNONREENTRANTCRITICALSECTION pcnrcs)
  304. {
  305.    ASSERT(IS_VALID_STRUCT_PTR(pcnrcs, CNONREENTRANTCRITICALSECTION));
  306.    return(pcnrcs->bEntered);
  307. }
  308. PUBLIC_CODE DWORD GetNonReentrantCriticalSectionOwner(
  309.                                           PCNONREENTRANTCRITICALSECTION pcnrcs)
  310. {
  311.    ASSERT(IS_VALID_STRUCT_PTR(pcnrcs, CNONREENTRANTCRITICALSECTION));
  312.    return(pcnrcs->dwOwnerThread);
  313. }
  314. #endif
  315. PUBLIC_CODE BOOL BeginExclusiveAccess(void)
  316. {
  317.    return(EnterNonReentrantCriticalSection(&s_nrcs));
  318. }
  319. PUBLIC_CODE void EndExclusiveAccess(void)
  320. {
  321.    LeaveNonReentrantCriticalSection(&s_nrcs);
  322.    return;
  323. }
  324. #ifdef DEBUG
  325. PUBLIC_CODE BOOL AccessIsExclusive(void)
  326. {
  327.    return(NonReentrantCriticalSectionIsOwned(&s_nrcs) &&
  328.           GetNonReentrantCriticalSectionOwner(&s_nrcs) == GetCurrentThreadId());
  329. }
  330. #endif   /* DEBUG */
  331. PUBLIC_CODE HMODULE GetThisModulesHandle(void)
  332. {
  333.    ASSERT(IS_VALID_STRUCT_PTR((PCPROCESSINFO)&s_pi, CPROCESSINFO));
  334.    return(s_pi.hModule);
  335. }