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.

224 lines
6.2 KiB

  1. use strict;
  2. use Win32::Event;
  3. use Win32::IPC;
  4. # declare locals
  5. my( @EventList, @MyHoldEvents, @MyWaitEvents, @EventNames, $EventName, $Drive );
  6. my( $VerboseFlag, $WaitMode, $WaitAnyMode, $SendMode, $HoldMode, $QueryMode );
  7. my( $CIMode, $BadEventCount, $SessionName );
  8. my( $Argument, $ArgCounter, $True, $False, $Event, $NumEvents, $Return );
  9. # parse command line
  10. foreach $Argument ( @ARGV ) {
  11. if ( $Argument =~ /^[\/\-]*\?$/ ) { &UsageAndQuit(); }
  12. # handle verbose flag -v
  13. if ( $Argument =~ /^[\/\-].*v/i ) {
  14. $VerboseFlag = "TRUE";
  15. $Argument =~ s/v//gi;
  16. }
  17. # handle case-insensitive flag -i
  18. if ( $Argument =~ /^[\/\-].*i/i ) {
  19. $CIMode = "TRUE";
  20. $Argument =~ s/i//gi;
  21. }
  22. # handle the event handling flags
  23. if ( $Argument =~ /^[\/\-]w$/i ) { $WaitMode = "TRUE"; }
  24. elsif ( $Argument =~ /^[\/\-]a/i ) { $WaitAnyMode = "TRUE"; }
  25. elsif ( $Argument =~ /^[\/\-]s/i ) { $SendMode = "TRUE"; }
  26. elsif ( $Argument =~ /^[\/\-]h/i ) { $HoldMode = "TRUE"; }
  27. elsif ( $Argument =~ /^[\/\-]q/i ) { $QueryMode = "TRUE"; }
  28. # if no flag set, it's an event name
  29. else { push( @EventList, $Argument ); }
  30. }
  31. $ArgCounter = 0;
  32. if ( $WaitMode ) { $ArgCounter++; }
  33. if ( $WaitAnyMode ) { $ArgCounter++; }
  34. if ( $SendMode ) { $ArgCounter++; }
  35. if ( $HoldMode ) { $ArgCounter++; }
  36. if ( $QueryMode ) { $ArgCounter++; }
  37. if ( $ArgCounter != 1 ) { &UsageAndQuit(); }
  38. # first things first, open all events
  39. undef( @MyHoldEvents );
  40. undef( @MyWaitEvents );
  41. undef( @EventNames );
  42. if ( $CIMode eq "TRUE" ) {
  43. foreach $EventName ( @EventList ) {
  44. $EventName = "\L$EventName";
  45. }
  46. }
  47. # handle intl constraints for event names
  48. # _ntroot
  49. # lang
  50. # _buildarch
  51. # _buildtype
  52. # seems like a lot, hopefully we won't go over a cmdevt name limit
  53. # of 260 chars. this is order 30 chars, so shouldn't be a problem.
  54. #
  55. my( $NTRoot ) = $ENV{'_NTROOT'};
  56. # remote the initial backslash
  57. $NTRoot =~ s/^\\//;
  58. # convert all other backslashes to dots
  59. $NTRoot =~ s/\\/./g;
  60. foreach $EventName ( @EventList ) {
  61. $EventName = $NTRoot . ".$ENV{'lang'}." .
  62. "$ENV{'_BuildArch'}.$ENV{'_BuildType'}.$EventName";
  63. }
  64. # handle terminal server bug (prepend all events with Global and drive letter
  65. $SessionName = $ENV{'SESSIONNAME'};
  66. if ( $SessionName ) {
  67. if($SessionName ne "Console") {
  68. $Drive = $ENV{'_NTDRIVE'};
  69. foreach $EventName ( @EventList ) {
  70. $EventName = "Global\\$Drive$EventName";
  71. }
  72. }
  73. }
  74. # handle the query mode early
  75. if ( $QueryMode ) {
  76. $BadEventCount = 0;
  77. foreach $EventName ( @EventList ) {
  78. $Event = Win32::Event->open( "$EventName.wait" );
  79. unless ( defined( $Event ) ) { $BadEventCount++; }
  80. }
  81. if ( $BadEventCount == 1 ) {
  82. print( "There was $BadEventCount undefined event.\n" );
  83. } else {
  84. print( "There were $BadEventCount undefined events.\n" );
  85. }
  86. exit( $BadEventCount );
  87. }
  88. $True = "TRUE";
  89. undef( $False );
  90. foreach $EventName ( @EventList ) {
  91. $Event = Win32::Event->new( $True, $False, "$EventName.wait" );
  92. unless ( defined( $Event ) ) {
  93. print( "Failed to open event $EventName, exiting.\n" );
  94. exit( 1 );
  95. }
  96. push( @MyWaitEvents, $Event );
  97. $Event = Win32::Event->new( $True, $False, "$EventName.hold" );
  98. unless ( defined( $Event ) ) {
  99. print( "Failed to open event $EventName, exiting.\n" );
  100. exit( 1 );
  101. }
  102. push( @MyHoldEvents, $Event );
  103. push( @EventNames, $EventName );
  104. }
  105. $NumEvents = @MyWaitEvents;
  106. if ( $NumEvents == 0 ) {
  107. print( "No events in event list, exiting ..." );
  108. exit( 1 );
  109. }
  110. if ( ( defined( $WaitMode ) || ( defined( $WaitAnyMode ) ) ) ) {
  111. &WaitRoutine();
  112. }
  113. if ( defined( $HoldMode ) ) { &HoldRoutine(); }
  114. if ( defined( $SendMode ) ) { &SendRoutine(); }
  115. exit( 0 );
  116. sub UsageAndQuit
  117. {
  118. print( "\n$0 [-w] [-a] [-s] [-h] [-q] [-?] name1 name2 ...\n" );
  119. print( "\n\t-w\tWait for all objects from name list\n" );
  120. print( "\t-a\tWait for any objects from name list\n" );
  121. print( "\t-s\tSend all objects in name list\n" );
  122. print( "\t-h\tHold until someone is waiting for all objects\n" );
  123. print( "\t\tin name list\n" );
  124. print( "\t-q\tQuery to see if listed events exist, exit code\n" );
  125. print( "\t\tis the number of uncreated events.\n" );
  126. print( "\t-?\tDisplay usage\n" );
  127. print( "\n\t$0 is a general process synchronization tool.\n" );
  128. print( "\tExample use: let's say we want to start four threads\n" );
  129. print( "\tand we want to make sure they don't finish before we\n" );
  130. print( "\tbegin listening for their exit. Then we just make sure\n" );
  131. print( "\tthat each thread begins with a call to $0 -h EventN\n" );
  132. print( "\tand finishes with a call to $0 -s EventN.\n" );
  133. print( "\tMeanwhile, our master thread can call $0 -w Event1\n" );
  134. print( "\tEvent2 Event3 Event4. As soon as the master issues this,\n" );
  135. print( "\tthe slave threads will resume normal execution.\n" );
  136. print( "\n" );
  137. exit( 1 );
  138. }
  139. sub WaitRoutine
  140. {
  141. my( $Event, $WaitMore );
  142. my( @HaveReceived, $Return, $NumEvents, $i );
  143. $NumEvents = @MyWaitEvents;
  144. for ( $i = 0; $i < $NumEvents; $i++ ) {
  145. $HaveReceived[ $i ] = "FALSE";
  146. }
  147. # set all hold events
  148. foreach $Event ( @MyHoldEvents ) {
  149. $Event->set;
  150. }
  151. # reset all events
  152. foreach $Event ( @MyWaitEvents ) {
  153. $Event->reset;
  154. }
  155. if ( defined( $VerboseFlag ) ) {
  156. print( "Waiting for $NumEvents event" );
  157. if ( $NumEvents != 1 ) { print( "s ( " ); }
  158. else { print( " ( " ); }
  159. for ( $i = 0; $i < $NumEvents; $i++ ) {
  160. print( "$EventNames[ $i ] " );
  161. }
  162. print( ") :" );
  163. }
  164. $WaitMore = "TRUE";
  165. while ( $WaitMore eq "TRUE" ) {
  166. $Return = &Win32::IPC::wait_any( \@MyWaitEvents );
  167. if ( $Return <= 0 ) {
  168. print( "\nTimeout or abandoned mutex, exiting.\n" );
  169. exit( 1 );
  170. }
  171. $Return--;
  172. $HaveReceived[ $Return ] = "TRUE";
  173. if ( defined( $VerboseFlag ) ) {
  174. print( " $EventNames[ $Return ]" );
  175. }
  176. $WaitMore = "FALSE";
  177. for ( $i = 0; $i < $NumEvents; $i++ ) {
  178. if ( $HaveReceived[ $i ] eq "FALSE" ) { $WaitMore = "TRUE"; }
  179. }
  180. }
  181. print( "\n" );
  182. }
  183. sub HoldRoutine
  184. {
  185. $Return = &Win32::IPC::wait_all( \@MyHoldEvents );
  186. if ( $Return < 0 ) {
  187. print( "Encountered an abandoned mutex, exiting.\n" );
  188. exit( 1 );
  189. }
  190. }
  191. sub SendRoutine
  192. {
  193. my( $Event );
  194. foreach $Event ( @MyWaitEvents ) {
  195. $Event->set;
  196. }
  197. }