(file) Return to WineWinsockAsyncTest.c CVS log (file) (dir) Up to [RizwankCVS] / wine1 / wine

  1 cs130_ryutaro 1.4 #include <stdio.h>
  2                   #include "winsock2.h"
  3                   #include "windows.h"
  4                   
  5                   #include <wine/test.h>
  6                   #include <winbase.h>
  7                   
  8                   /* The #pragma directives offer a way for each compiler to offer machine- 
  9                      and operating-system-specific features while retaining overall 
 10                      compatibility with the C and C++ languages.
 11                      The next line places a library-search record, ws2_32, in the object file. */
 12                   //  #pragma comment ( lib, "ws2_32" )
 13                   
 14                   /* constants */
 15                   #define ASYNC_EVENT (WM_USER +5)     // the message we'll use for our async notification
 16                   #define PORT_NUM 27015
 17                   #define PACKET_SZ 32
 18                   #define FILE_SZ 100
 19                   #define SERVER_START_TIME 3000
 20                   #define MAX_WAIT_TIME 30000 // 30 seconds expressed in milliseconds
 21                   #define NUM_THREADS_TO_WAIT 2
 22 cs130_ryutaro 1.4 
 23                   enum  // define all the exit codes for a thread
 24                     {
 25                       TH_START_ERROR = 1001,
 26                       TH_SOCKET_ERROR,
 27                       TH_SOCKADDR_ERROR,
 28                       TH_BIND_ERROR,
 29                       TH_CONNECT_ERROR,
 30                       TH_LISTEN_ERROR,
 31                       TH_ACCEPT_ERROR,
 32                       TH_SELECT_ERROR,
 33                       TH_RECV_ERROR,
 34                       TH_SEND_ERROR,
 35                       TH_WINDOW_ERROR,
 36                       TH_MSG_ERROR
 37                   
 38                     } ThreadExitCodes;
 39                   
 40                   /* static func prototypes */
 41                   static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData );
 42                   static SOCKET socket_w( int af, int type, int protocol );
 43 cs130_ryutaro 1.4 static LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
 44                   static HWND WineCreateWindow( HINSTANCE hInstance);
 45                   static void WineThreadCleanUp();
 46                   static void WineCreateFile();
 47                   static DWORD WINAPI WineRunServer();
 48                   static DWORD WINAPI WineRunClient();
 49                   
 50                   /* struct def */
 51                   typedef struct 
 52                   {
 53                     DWORD id;
 54                     HANDLE handle;
 55                     int bytesRecvd;
 56                     int bytesSent;
 57                     char packet[PACKET_SZ];
 58                   } thread_t;
 59                   
 60                   /* global vars */
 61                   static char FileBuf[FILE_SZ];
 62                   static thread_t ServerThread;
 63                   static thread_t ClientThread;
 64 cs130_ryutaro 1.4 
 65                   /* 
 66                      Wrapper for WSAStartup(). 
 67                      The WSAStartup function must be the first Windows Sockets function 
 68                      called by an application or DLL. It allows an application or DLL to 
 69                      specify the version of Windows Sockets required and retrieve details 
 70                      of the specific Windows Sockets implementation. 
 71                   
 72                      Paremeters:
 73                      wVersionRequested 
 74                      [in] Highest version of Windows Sockets support that the caller can use. 
 75                      The high-order byte specifies the minor version (revision) number; 
 76                      the low-order byte specifies the major version number. 
 77                      lpWSAData 
 78                      [out] Pointer to the WSADATA data structure that is to receive details of 
 79                      the Windows Sockets implementation. 
 80                   
 81                      Error code          |        Meaning 
 82                      WSASYSNOTREADY      | Indicates that the underlying network subsystem is 
 83                      not ready for network communication. 
 84                      WSAVERNOTSUPPORTED  | The version of Windows Sockets support requested is 
 85 cs130_ryutaro 1.4    not provided by this particular Windows Sockets 
 86                      implementation. 
 87                      WSAEINPROGRESS      | A blocking Windows Sockets 1.1 operation is in progress. 
 88                      WSAEPROCLIM         | Limit on the number of tasks supported by the Windows 
 89                      Sockets implementation has been reached. 
 90                      WSAEFAULT           | The lpWSAData is not a valid pointer. 
 91                   */
 92                   static int WSAStartup_w( WORD wVersionRequired, LPWSADATA lpWSAData )
 93                   {
 94                     int errCode = 0;
 95                   	
 96                     // WSAVERNOTSUPPORTED test
 97                     WSADATA tmpLpWSAData;
 98                     errCode = WSAStartup( MAKEWORD( 0, 0 ), &tmpLpWSAData );
 99                     if( errCode != WSAVERNOTSUPPORTED ) {
100                   
101                       // print out the Error Code to be thorough
102                       trace( "WSAVERNOTSUPPORTED test failed with error code: %d\n", errCode );		
103                       errCode = 0;
104                     }
105                   
106 cs130_ryutaro 1.4   // WSEFAULT test
107                     errCode = WSAStartup( wVersionRequired, ( LPWSADATA ) 0 );
108                     if( errCode != WSAEFAULT ) {
109                   
110                       // print out the Error Code to be thorough
111                       trace( "WSAFAULT test failed with error code: %d\n", errCode );		
112                       errCode = 0;
113                     }
114                   
115                     // lastly regular case - should succeed
116                     errCode = WSAStartup( wVersionRequired, lpWSAData );
117                     if( errCode != 0 ) {
118                   
119                       // print out the Error Code to be thorough
120                       errCode = WSAGetLastError();		
121                       trace( "WSAStartup() failed with error code: %d\n", errCode );		
122                     }
123                   
124                     return errCode;
125                   }
126                   
127 cs130_ryutaro 1.4 /* 
128                      Wrapper for socket().
129                      socket() function creates a socket that is bound to a specific service provider.
130                   
131                      Parameters:
132                      af
133                      [in] Address family specification. 
134                      type 
135                      [in] Type specification for the new socket. Types are:
136                      SOCK_STREAM - Uses TCP
137                      SOCK_DGRAM  - Uses UDP 
138                      protocol 
139                      [in] Protocol to be used with the socket that is specific to the indicated address 
140                      family. 
141                   
142                      If no error occurs, socket returns a descriptor referencing the new socket. Otherwise, 
143                      a value of INVALID_SOCKET is returned, and a specific error code can be retrieved by 
144                      calling WSAGetLastError.
145                   
146                      Error code              |        Meaning 
147                      WSANOTINITIALISED       | A successful WSAStartup call must occur before using this function. 
148 cs130_ryutaro 1.4    WSAENETDOWN             | The network subsystem or the associated service provider has failed. 
149                      WSAEAFNOSUPPORT         | The specified address family is not supported. 
150                      WSAEINPROGRESS          | A blocking Windows Sockets 1.1 call is in progress, or the service 
151                      provider is still processing a callback function. 
152                      WSAEMFILE               | No more socket descriptors are available. 
153                      WSAENOBUFS              | No buffer space is available. The socket cannot be created. 
154                      WSAEPROTONOSUPPORT      | The specified protocol is not supported. 
155                      WSAEPROTOTYPE           | The specified protocol is the wrong type for this socket. 
156                      WSAESOCKTNOSUPPORT      | The specified socket type is not supported in this address family. 
157                   
158                      NOTE: WSAEPROTOTYPE  tried to do test for this error by specifying type=SOCK_DGRAM and
159                      protocol=IPPROTO_TCP but the return error code was WSEPROTONOSUPPORT
160                   */
161                   static SOCKET socket_w( int af, int type, int protocol )
162                   {
163                     // Create a socket.
164                     SOCKET m_socket;
165                   
166                     // WSAEAFNOSUPPORT test	
167                     m_socket = socket( -999, SOCK_STREAM, IPPROTO_TCP );
168                     if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEAFNOSUPPORT ){
169 cs130_ryutaro 1.4     trace( "WSAEAFNOSUPPORT test failed: %d %d\n", m_socket, WSAGetLastError() );
170                     }
171                   
172                     // WSAEPROTONOSUPPORT test
173                     m_socket = socket( AF_INET, SOCK_STREAM, -999 );
174                     if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAEPROTONOSUPPORT ){
175                       trace( "WSAEPROTONOSUPPORT test failed: %d %d\n", m_socket, WSAGetLastError() );
176                     }
177                   
178                     // WSAESOCKTNOSUPPORT test
179                     m_socket = socket( AF_INET, -999, IPPROTO_TCP );
180                     if( m_socket != INVALID_SOCKET || WSAGetLastError() != WSAESOCKTNOSUPPORT ){
181                       trace( "WSAEPROTONOSUPPORT test failed: %d %d\n", m_socket, WSAGetLastError() );
182                     }
183                   
184                     m_socket = socket( af, type, protocol );
185                     if( m_socket == INVALID_SOCKET ){
186                       trace( "Error at socket(): %d\n", WSAGetLastError() );
187                     }
188                   
189                     return m_socket;
190 cs130_ryutaro 1.4 }
191                   
192                   /* 
193                      Call back event handler for asynchronous client 
194                   */
195                   static LRESULT CALLBACK WndProcedure( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
196                   {
197                     int eventCode = 0; 
198                     switch( msg )
199                       {
200                       case ASYNC_EVENT: 
201                         eventCode = WSAGETSELECTEVENT( lParam );
202                         SOCKET socket = (SOCKET) wParam;
203                         SOCKET acceptSock;
204                         int bytesRecv = 0;
205                         int i = 0, j = 0;
206                         char* buf;
207                         if( GetCurrentThreadId() == ServerThread.id )
208                   	buf = ServerThread.packet;
209                         else
210                   	buf = ClientThread.packet;
211 cs130_ryutaro 1.4 
212                         switch( eventCode )
213                   	{
214                   	case FD_ACCEPT:					
215                   	  trace( "%ld accept called\n", GetCurrentThreadId() );
216                   	  acceptSock = accept( socket, NULL, NULL );
217                   	  if( acceptSock == INVALID_SOCKET ){
218                   	    trace( "accept error %d\n", WSAGetLastError() );
219                   	    closesocket( socket );
220                   	    ExitThread( TH_ACCEPT_ERROR );
221                   	  }
222                   	  trace( "%ld: connection accepted\n", GetCurrentThreadId() );
223                   	  break;
224                   
225                   	case FD_CONNECT:
226                   
227                   	  // a call to connect() has completed
228                   	  trace("%ld CONNECTED!\n", GetCurrentThreadId() );
229                   	  break;
230                   
231                   	case FD_CLOSE:				
232 cs130_ryutaro 1.4 
233                   	  // a connection has been closed					
234                   	  closesocket( socket );
235                   	  trace( "%ld: Closed socket\n", GetCurrentThreadId());
236                   	  WSACleanup();
237                   	  ExitThread( 0 );
238                   	  break;
239                   
240                   	case FD_READ:
241                   
242                   	  // WinSock has data waiting to be read									
243                   	  bytesRecv = recv( socket, buf, PACKET_SZ, 0 );
244                   
245                   	  trace( "%ld received %d bytes: ", GetCurrentThreadId(), bytesRecv );
246                   	  while( i < PACKET_SZ && buf[i] != (char)EOF ){
247                   	    printf( "%c", buf[i] );
248                   	    i++;
249                   	  }
250                   	  printf( "\n" );
251                   
252                   	  // Now send it back if you're the server
253 cs130_ryutaro 1.4 	  if( GetCurrentThreadId() == ServerThread.id ){
254                   
255                   	    if( send( socket, buf, bytesRecv, 0 ) == SOCKET_ERROR ){
256                   
257                   	      // check if the network buffer is full and can send no more
258                   	      // data. If so then break from the loop
259                   	      if( WSAGetLastError() == WSAEWOULDBLOCK ){
260                   		// break from the loop – buffer is full
261                   		trace( "woud block send!\n" );
262                   		break;
263                   	      }
264                   	      else{ // another error
265                   		trace(" some send error\n" );
266                   		return 0;
267                   	      }
268                   	    }
269                   
270                   	    trace( "%ld sent back %d bytes: ", GetCurrentThreadId(), bytesRecv );
271                   	    j = 0;
272                   	    while( j < bytesRecv ){
273                   	      printf( "%c", buf[j] );
274 cs130_ryutaro 1.4 	      j++;
275                   	    }
276                   	    printf( "\n" );
277                   
278                   	  }
279                   	  else{
280                   
281                   	    // Client: close the connection when it received back FILE_SZ
282                   	    ClientThread.bytesRecvd += bytesRecv;
283                   	    if( ClientThread.bytesRecvd >= FILE_SZ ){
284                   	      trace( "%ld closing socket\n", GetCurrentThreadId() );		
285                   	      closesocket( socket );
286                   	      WSACleanup();
287                   	      ExitThread( 0 );
288                   	    }
289                   	  }
290                   	  break;
291                   
292                   	case FD_WRITE:
293                   
294                   	  // don't do anything here for server
295 cs130_ryutaro 1.4 	  if( GetCurrentThreadId() == ServerThread.id )
296                   	    break;
297                   
298                   	  // enter an infinite loop
299                   	  BOOL notDone = TRUE;
300                   	  while( notDone ){
301                   
302                   	    // determine how many bytes to send
303                   	    int bytesToSend = 0;
304                   	    if( sizeof( FileBuf ) - ClientThread.bytesSent < PACKET_SZ ){
305                   
306                   	      // the bytes remaining to send is smaller than packet size
307                   	      bytesToSend = (int) ( sizeof( FileBuf ) - ClientThread.bytesSent );
308                   	      notDone = FALSE;
309                   
310                   	    }
311                   	    else{
312                   
313                   	      // the bytes remaining is greater than or equal to PACKET_SZ
314                   	      bytesToSend = PACKET_SZ;
315                   
316 cs130_ryutaro 1.4 	    }
317                   							
318                   	    memcpy( buf, FileBuf + ClientThread.bytesSent, bytesToSend ); 
319                   	    ClientThread.bytesSent += bytesToSend;
320                   						
321                   	    // send the packet off to the Server if it is filled
322                   	    if( send( socket, buf, bytesToSend, 0 ) == SOCKET_ERROR ){
323                   
324                   	      // check if the network buffer is full and can send no more
325                   	      // data. If so then break from the loop
326                   	      if( WSAGetLastError() == WSAEWOULDBLOCK ){
327                   		// break from the loop – buffer is full
328                   		break;
329                   	      }
330                   	      else{ // another error
331                   		return 0;
332                   	      }
333                   	    }
334                   						
335                   	    trace( "%ld sent: ", GetCurrentThreadId() );
336                   	    j = 0;
337 cs130_ryutaro 1.4 	    while( j < PACKET_SZ &&  buf[j] != (char)EOF ){
338                   	      printf( "%c", buf[j] );
339                   	      j++;
340                   	    }
341                   	    printf( "\n" );
342                   	  }
343                   	  break;
344                   	}
345                       }
346                     return DefWindowProc( hWnd, msg, wParam, lParam );
347                   }
348                   
349                   /* 
350                      Creates a hidden window object.
351                   
352                      input:
353                      none
354                      output:
355                      window handle
356                   */
357                   static HWND WineCreateWindow( HINSTANCE hInstance )
358 cs130_ryutaro 1.4 {
359                     // initialize the window class attributes.
360                     WNDCLASS windowClass;
361                     //windowClass = new WNDCLASS;
362                     windowClass.lpszClassName = "Hidden_Winsock_Window";
363                     windowClass.style = CS_HREDRAW | CS_VREDRAW;
364                     windowClass.lpfnWndProc = WndProcedure;
365                     windowClass.cbClsExtra = 0;
366                     windowClass.cbWndExtra = 0;
367                     windowClass.hInstance = hInstance;
368                     windowClass.hIcon = NULL;
369                     windowClass.hCursor = NULL;
370                     windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
371                     windowClass.lpszMenuName = NULL;
372                     RegisterClass(&windowClass);
373                   
374                     // create window
375                     return CreateWindow( 
376                   		      "Hidden_Winsock_Window", 
377                   		      "Winsock Window", 
378                   		      WS_OVERLAPPEDWINDOW,
379 cs130_ryutaro 1.4 		      CW_USEDEFAULT, 
380                   		      CW_USEDEFAULT,
381                   		      CW_USEDEFAULT,
382                   		      CW_USEDEFAULT,
383                   		      NULL,
384                   		      NULL,
385                   		      hInstance,
386                   		      NULL 
387                   		      );
388                   }
389                   
390                   /* server */
391                   static DWORD WINAPI WineRunServer()
392                   {
393                     // Retrieve an instance
394                     HINSTANCE hInstance = GetModuleHandle( NULL );
395                   
396                     // Create a window
397                     HWND hwnd = WineCreateWindow( hInstance );
398                     if( hwnd == NULL ){
399                       trace( "Window could not be created %ld\n", GetLastError() );
400 cs130_ryutaro 1.4     ExitThread( TH_WINDOW_ERROR );
401                     }
402                   	
403                     // start winsock	
404                     WSADATA wsaData;
405                     if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
406                   
407                       // print out the Error Code to be thorough
408                       trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );		
409                       ExitThread( TH_START_ERROR );
410                     }
411                   
412                     // Create a socket.
413                     SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );	if( sock == INVALID_SOCKET ){
414                       trace( "socket error: %d\n", WSAGetLastError() ); 
415                       ExitThread( TH_SOCKET_ERROR );
416                     }
417                   
418                     // Bind the socket.
419                     SOCKADDR_IN sockAddr;
420                     sockAddr.sin_family = AF_INET;
421 cs130_ryutaro 1.4   sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
422                     sockAddr.sin_port = htons( PORT_NUM );
423                     if( bind( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
424                       trace( "bind failed weith error code %d\n", WSAGetLastError() );
425                       closesocket( sock );
426                       ExitThread( TH_BIND_ERROR );
427                   
428                     }
429                   
430                     // Listen on the socket.
431                     if ( listen( sock, 1 ) == SOCKET_ERROR ){
432                       trace( "listen error with error code %d.\n", WSAGetLastError() );
433                       closesocket( sock );		ExitThread( TH_LISTEN_ERROR );	}
434                   
435                     // make the socket asynchronous and notify of read, write, connect and close events
436                     if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_ACCEPT |FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
437                   
438                       trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
439                       closesocket( sock );
440                       ExitThread( TH_SELECT_ERROR );
441                   
442 cs130_ryutaro 1.4   }
443                   
444                     trace( "listening and going to loop %ld\n", GetCurrentThreadId() );
445                   	
446                     BOOL retVal;
447                     MSG msg;
448                     while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){ 
449                   
450                       if( retVal == -1 ){
451                   
452                         // handle the error and possibly exit
453                         trace( "GetMessage error %ld\n", GetLastError() );
454                         closesocket( sock );
455                         ExitThread( TH_MSG_ERROR );
456                       }
457                   
458                       // Translate and dispatch the message
459                       TranslateMessage( &msg ); 
460                       DispatchMessage( &msg );
461                   
462                     }
463 cs130_ryutaro 1.4 
464                     return 0;
465                   }
466                   
467                   /* client */
468                   static DWORD WINAPI WineRunClient()
469                   {
470                     // Retrieve an instance
471                     HINSTANCE hInstance = GetModuleHandle( NULL );
472                   
473                     // Create a window
474                     HWND hwnd = WineCreateWindow( hInstance );
475                     if( hwnd == NULL ){
476                       trace( "Window could not be created %ld\n", GetLastError() );
477                       ExitThread( TH_WINDOW_ERROR );
478                     }
479                   
480                     // start winsock	
481                     WSADATA wsaData;
482                     if( WSAStartup_w( MAKEWORD( 2, 2 ), &wsaData ) != 0 ){
483                   
484 cs130_ryutaro 1.4     // print out the Error Code to be thorough
485                       trace( "WSAStartup() failed with error code: %d\n", WSAGetLastError() );		
486                       ExitThread( TH_START_ERROR );
487                     }
488                   
489                     // Create a socket.  -- This is a TCP test
490                     SOCKET sock = socket_w( AF_INET, SOCK_STREAM, IPPROTO_TCP );
491                     if ( sock == INVALID_SOCKET ) {
492                       trace( "socket returned with error code: %d\n", WSAGetLastError() );
493                       ExitThread( TH_SOCKET_ERROR );
494                     }
495                   
496                     // make the socket asynchronous and notify of read, write, connect and close events
497                     // this is the client socket
498                     if( WSAAsyncSelect( sock, hwnd, ASYNC_EVENT, FD_WRITE | FD_CONNECT | FD_READ | FD_CLOSE ) == SOCKET_ERROR ){
499                       trace( "WSAAsyncSelect Failed %d\n", WSAGetLastError() );
500                       closesocket( sock );
501                       ExitThread( TH_SELECT_ERROR );
502                     }
503                   
504                     /* connect */
505 cs130_ryutaro 1.4   SOCKADDR_IN sockAddr;
506                     sockAddr.sin_family = AF_INET;
507                     sockAddr.sin_addr.s_addr = inet_addr( "127.0.0.1" );
508                     sockAddr.sin_port = htons( PORT_NUM );
509                     if( connect( sock, (SOCKADDR*) &sockAddr, sizeof( sockAddr ) ) == SOCKET_ERROR ){
510                       if( WSAGetLastError() != WSAEWOULDBLOCK ){
511                         trace( "Failed to connect.: %d\n", WSAGetLastError() );
512                         closesocket( sock );
513                         ExitThread( TH_CONNECT_ERROR );
514                       }
515                     }
516                   
517                     BOOL retVal;
518                     MSG msg;
519                     while( ( retVal = GetMessage( &msg, NULL, 0, 0 ) ) != 0 ){ 
520                   
521                       if( retVal == -1 ){
522                   
523                         // handle the error and possibly exit
524                         trace( "GetMessage error %ld\n", GetLastError() );
525                         closesocket( sock );
526 cs130_ryutaro 1.4       ExitThread( TH_MSG_ERROR );
527                       }
528                   
529                       // Translate and dispatch the message
530                       TranslateMessage( &msg ); 
531                       DispatchMessage( &msg );
532                   
533                     }
534                     return 0;
535                   }
536                   
537                   /* close thread handles and finish up winsock dll */
538                   static void WineThreadCleanUp()
539                   {
540                     if( ServerThread.handle )
541                       CloseHandle( ServerThread.handle );
542                   
543                     if( ClientThread.handle )
544                       CloseHandle( ClientThread.handle );	
545                   }
546                   
547 cs130_ryutaro 1.4 /* creates the buffer that the client sends */
548                   static void WineCreateFile()
549                   {
550                     /* initialize just in case */
551                     memset( FileBuf, 0, sizeof( FileBuf ) );
552                   
553                     /* just customize this any way you want */
554                     memset( FileBuf, 'W', PACKET_SZ );
555                     memset( FileBuf + PACKET_SZ, 'I', PACKET_SZ );
556                     memset( FileBuf + ( 2 * PACKET_SZ ), 'N', PACKET_SZ );
557                     memset( FileBuf + ( 3 * PACKET_SZ ), 'E', 3 );
558                     FileBuf[FILE_SZ - 1] = (char) EOF;
559                   }
560                   
561                   START_TEST( WineWinsockAsyncTest )
562                   {
563                     // Create the file that we are going to send.
564                     WineCreateFile();
565                   
566                     // Initialize server and client threads
567                     memset( &ServerThread, 0, sizeof( ServerThread ) );
568 cs130_ryutaro 1.4   memset( &ClientThread, 0, sizeof( ClientThread ) );
569                   
570                     // create server thread	
571                     ServerThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunServer, 
572                   				      NULL, 0, &ServerThread.id );
573                   
574                     if( ServerThread.handle == NULL ){
575                   
576                       trace( "CreateThread failed %ld\n", GetLastError() );
577                       WineThreadCleanUp();
578                       return;
579                     }
580                   
581                     trace( "%ld: server thread %ld created\n", GetCurrentThreadId(), ServerThread.id );
582                   
583                     // Wait for three seconds to let server start
584                     DWORD waitRet = WaitForSingleObject( ServerThread.handle, SERVER_START_TIME );
585                     if( waitRet == WAIT_FAILED ){
586                   		
587                       // WaitForSingleObject failed for whatever reason
588                       trace( "WaitForSingleObject failed with error code %ld\n", GetLastError() );	
589 cs130_ryutaro 1.4     WineThreadCleanUp();
590                       return;
591                   
592                     }
593                   
594                     // get the exit code of the server - error if not STILL_ACTIVE
595                     DWORD threadStatus = 0;
596                     if( GetExitCodeThread( ServerThread.handle, &threadStatus ) == 0 ){
597                   		
598                       trace( "GetExitCodeThread failed with error code %ld\n",GetLastError() );
599                       WineThreadCleanUp();
600                       return;
601                   
602                     }
603                   
604                     trace( "%ld: server started successfully now creating client thread\n",  GetCurrentThreadId() );
605                   
606                     // Create client thread in suspended state
607                     ClientThread.handle = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)WineRunClient, 
608                   				      NULL, 0, &ClientThread.id );
609                   
610 cs130_ryutaro 1.4   if( ClientThread.handle == NULL ){
611                   
612                       trace( "CreateThread failed %ld\n", GetLastError() );
613                       WineThreadCleanUp();
614                       return;
615                     }	
616                   	
617                     trace( "%ld: client thread %ld created. Now wait.\n", GetCurrentThreadId(), ClientThread.id );
618                   
619                     // Wait for this server to suspsend itself
620                     HANDLE threadHandles[NUM_THREADS_TO_WAIT] = { ServerThread.handle, ClientThread.handle };
621                     waitRet = WaitForMultipleObjects( NUM_THREADS_TO_WAIT, threadHandles, TRUE, MAX_WAIT_TIME );
622                     if( waitRet == WAIT_FAILED ){
623                   		
624                       // WaitForSingleObject failed for whatever reason
625                       trace( "WaitForMultipleObjects failed with error code %ld\n", GetLastError() );	
626                       WineThreadCleanUp();
627                       return;
628                   
629                     }
630                     else if( waitRet == WAIT_TIMEOUT ){
631 cs130_ryutaro 1.4 
632                       trace( "Timed out while waiting for threads to finish\n" );
633                       WineThreadCleanUp();
634                       return;
635                   
636                     }
637                   
638                     // clean up the threads
639                     WineThreadCleanUp();
640                   
641                     trace( "%ld: main thread exiting...\n", GetCurrentThreadId() );
642                   }

Rizwan Kassim
Powered by
ViewCVS 0.9.2