示例#1
0
STATUS
ME_alloc_shared(i4          flag,
                SIZE_TYPE   pages,
                char        *key,
                PTR         *memory,
                SIZE_TYPE   *allocated_pages,
                CL_ERR_DESC *err_code)
{
	STATUS          status;
	SIZE_TYPE       memsize;
#ifdef LP64
	LARGE_INTEGER	numbytes;
#endif
	HANDLE          name;
	HANDLE          map;
	PTR             temp;
	char            map_key[MAX_LOC+1];
	char            *install_code;
	char		*ObjectPrefix;

    SECURITY_ATTRIBUTES sa;
    
	CLEAR_ERR(err_code);
	GVshobj(&ObjectPrefix);

	if (key == NULL || *key == '\0') {
		return (ME_BAD_PARAM);
	}
	memsize = pages * ME_MPAGESIZE;
        /*
        **  Moved ME_makekey to be called each time ME_alloc_shared is called
        **  as this obtains a handle to the file which will be required later
        **  if this is an attach to shared memory.
        **  This file handle is closed during an MEshared_free.
        */
        if ((name = ME_makekey(key)) == (HANDLE) -1)
        {
            status = GetLastError();
            SETWIN32ERR(err_code, status, ER_alloc);
            return (FAIL);
        }

	/* 
	**  The file mapping key used to be the name of the file.
	**  This caused problems when Jasmine and Ingres were installed
	**  on the same machine.  Create a unique key name, and use
	**  that for File Mapping instead.
	*/

	NMgtAt("II_INSTALLATION", &install_code);
    STpolycat(4, ObjectPrefix, SystemVarPrefix, install_code,
		      key, map_key);

	if (flag & ME_CREATE_MASK) {
	        iimksecdacl( &sa );
		FlushFileBuffers(name);
#ifdef LP64
		numbytes.QuadPart = Int32x32To64(pages, ME_MPAGESIZE);
		map = CreateFileMapping(name,
		                        &sa,
		                        PAGE_READWRITE,
		                        numbytes.HighPart,
		                        numbytes.LowPart,
		                        map_key);
#else
		map = CreateFileMapping(name,
		                        &sa,
		                        PAGE_READWRITE,
		                        0,
		                        memsize,
		                        map_key);
#endif  /* LP64 */

		if (map == NULL) {
			status = GetLastError();
			SETWIN32ERR(err_code, status, ER_alloc);
			FlushFileBuffers(name);
			CloseHandle(name);
			switch (status) {
			case ERROR_ALREADY_EXISTS:
				return ME_ALREADY_EXISTS;
			case ERROR_NOT_ENOUGH_MEMORY:
				return ME_OUT_OF_MEM;
			default:
				return FAIL;
			}
		}

		if (map != NULL && GetLastError() == ERROR_ALREADY_EXISTS) {
			FlushFileBuffers(name);
			CloseHandle(map);
			CloseHandle(name);
			return (ME_ALREADY_EXISTS);
		}
	} else {
		map = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
		                      FALSE,
		                      map_key);

		if (map == NULL) {
			status = GetLastError();
			SETWIN32ERR(err_code, status, ER_alloc);
			FlushFileBuffers(name);
			CloseHandle(name);
			switch (status) {
			case ERROR_FILE_NOT_FOUND:
				return ME_NO_SUCH_SEGMENT;
			case ERROR_NOT_ENOUGH_MEMORY:
				return ME_OUT_OF_MEM;
			default:
				return FAIL;
			}
		}
	}

	/*
	 * Finally.  Now get a memory address for the sucker.
	 * 
	 * If ME_ADDR_SPEC is set, we'll attempt to hardwire the address; else
	 * we'll take whatever the system gives us.
	 */

	if (flag & ME_ADDR_SPEC) {
		temp = MapViewOfFileEx(map,
		                       FILE_MAP_WRITE | FILE_MAP_READ,
		                       0,
		                       0,
		                       0,
		                       *memory);
		if ((temp == NULL) || (temp != *memory)) {
			status = GetLastError();
			SETWIN32ERR(err_code, status, ER_alloc);
			return (FAIL);
		}
	} else {
		*memory = MapViewOfFile(map,
		                        FILE_MAP_WRITE | FILE_MAP_READ,
		                        0,
		                        0,
		                        0);
		if (*memory == NULL) {
			status = GetLastError();
			SETWIN32ERR(err_code, status, ER_alloc);
			return (FAIL);
		}
	}

        /*
        **  If this is not an attach to shared memory assume that pages value
        **  is valid.
        */
        if ((flag & ME_CREATE_MASK) ||
            !(flag & (ME_SSHARED_MASK | ME_MSHARED_MASK)))
        {
	    pages = (SIZE_TYPE)(memsize / ME_MPAGESIZE);
        }
        else
        {
        BY_HANDLE_FILE_INFORMATION sFileInfo;

            /*
            **  If attaching to shared memory ignore the page argument and
            **  calculate size of shared segment in pages from file size.
            **  Assume that a single shared memory file will not exceed 4G.
            */

            if (GetFileInformationByHandle (name, &sFileInfo) == 0)
            {
                status = GetLastError();
                SETWIN32ERR(err_code, status, ER_alloc);
                return (FAIL);
            }
            else
            {
                pages = sFileInfo.nFileSizeLow / ME_MPAGESIZE;
            }
        }


	if (allocated_pages)
		*allocated_pages = pages;

        /*
        **  if this is an attach where pages is 0 ME_reg_seg will register
        **  pages calculated from the size of the file.
        */
	if (ME_reg_seg(*memory,
	               pages,
	               map,
	               name) != OK) {
		UnmapViewOfFile(memory);
		*memory = (PTR) NULL;
		return (FAIL);
	}

	return (OK);
}
示例#2
0
/*
** Name: GClanman_async_thread
** Description:
**	This thread handles all the asynchronous I/O for a protocol driver.
** 	It will be woken up when GClanman() places a request on it's input
**	Q.  Then, this thread will move the request from the input Q to its
**	processing Q and continue to process the request until complete.
**	When complete, the request is finally moved to the completion
**	Q.
** History:
**	04-Nov-93 (edg)
**	    Written.
**	29-jun-2000 (somsa01)
**	    Use GCc_listen_port for the server ncb_name. Also, make sure
**	    that we update GCc_client_name if we need a unique one.
**      06-Aug-2009 (Bruce Lunsford) Sir 122426
**	    Since _beginthreadex() is now used to start this thread,
**	    use _endthreadex() to end it.
*/
VOID
GClanman_async_thread( VOID * parms)
{
	int             status = OK;
	char            callname[NCBNAMSZ+1];
	DWORD		wait_stat;
	HANDLE		hSave;
	int		processing_requests = 0;
	int		pending_requests = 0;
	QUEUE		*q;
	SECURITY_ATTRIBUTES sa;

	iimksec (&sa);

	GCTRACE(4)("LMAN THREAD: started.\n");
top:
	/*
	** Wait for a request to come in from the primary gcc thread....
	*/

	GCTRACE(4)("LMAN THREAD: waiting for event ... \n");

	wait_stat = WaitForSingleObject( hEventThreadInQ, INFINITE );

	GCTRACE(3)("LMAN THREAD: wait returned %d, handle = %d\n", 
		    wait_stat, hEventThreadInQ );

	/*
	** If wait failed, chances are it's a major hosure.  Continue on any
	** way -- there's a possibility that something useful may get done.
	*/
	if (wait_stat == WAIT_FAILED)
	{
	    GCTRACE(1)("LMAN THREAD: wait failed %d\n", 
	    		GetLastError() );
	}

	/*
	** Now get get the incoming requests and add up how many requests
	** we're processing.
	*/
	processing_requests = GCget_incoming_reqs( Tptr, hMutexThreadInQ );

	GCTRACE(2)("LMAN THREAD: Got %d new requests to process\n",
		    processing_requests);

	/*
	** Loop until there's no more requests being processed.
	*/
	while( processing_requests )
	{
            pending_requests = 0;
	    /*
	    ** Now loop thru the inprocess request list.
	    */
	    for ( q = Tptr->process_head.q_next;
	    	  q != &Tptr->process_head;
		  q = q->q_next )
	    {
	        REQUEST_Q *rq = (REQUEST_Q *)q;
		GCC_P_PLIST *parm_list = rq->plist;
		PCB *pcb = (PCB *)parm_list->pcb;

		parm_list->generic_status = OK;
		CLEAR_ERR(&parm_list->system_status);

		switch (parm_list->function_invoked) 
		{

		    /******************************************************
		    ** Handle CONNECT
		    *******************************************************/
		    case GCC_CONNECT:

		    GCTRACE(4)("LMAN THREAD: process CONNECT\n");
		    if ( pcb == NULL || pcb->state.conn == INITIAL )
		    {
		        GCTRACE(3)("LMAN THREAD: initial CONNECT\n");
		        /*
			** Allocate the protocol control block.
			*/
		  	pcb = (PCB *) malloc( sizeof(PCB) );
		    	parm_list->pcb = (char *)pcb;
			if (pcb == NULL) 
			{
			    status = errno;
			    SETWIN32ERR(&parm_list->system_status, status, ER_alloc);
			    pcb->state.conn = COMPLETED;
			    parm_list->generic_status = GC_CONNECT_FAIL;
			    break;
		   	}
			memset( pcb, 0, sizeof( *pcb ) );
		        GCTRACE(3)("LMAN THREAD: CONNECT allocated pcb\n");
			/*
			** Create send/recv event handles for ncb.
			*/
    			if ((pcb->s_ncb.ncb_event = 
				CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL)
    			{
        		    status = GetLastError();
			    pcb->state.conn = COMPLETED;
			    SETWIN32ERR(&parm_list->system_status, status, ER_create);
			    parm_list->generic_status = GC_CONNECT_FAIL;
			    break;
    		        }
       		 	if ((pcb->r_ncb.ncb_event = 
				CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL)
    			{
        		    status = GetLastError();
			    CloseHandle( pcb->s_ncb.ncb_event );
			    pcb->state.conn = COMPLETED;
			    SETWIN32ERR(&parm_list->system_status, status, ER_create);
			    parm_list->generic_status = GC_CONNECT_FAIL;
			    break;
    			}
		        GCTRACE(3)("LMAN THREAD: CONNECT created events\n");

			pcb->state.conn = INITIAL;

		    } /* end if pcb NULL */

		    /*
		    ** If the PCB state is not INITIAL, just break because
		    ** we're just waiting for connect to complete.
		    */
		    if ( pcb->state.conn != INITIAL )
		        break;

		    /*
		    ** Use the send ncb in pcb for the connect -- add name.
		    */
		    pcb->s_ncb.ncb_command = NCBADDNAME;
		    pcb->s_ncb.ncb_buffer = Dummy_Buf;
		    pcb->s_ncb.ncb_length = sizeof(Dummy_Buf);
		    pcb->s_ncb.ncb_lana_num = lana_num;

		    for (;;)
		    {
			STprintf( GCc_client_name, "%s%-d", 
				  MyName, GCc_client_count++ );
			STcopy( GCc_client_name, pcb->s_ncb.ncb_name );

			GCTRACE(3)("LMAN THREAD: CONNECT doing ADDNAME %s\n",
				   pcb->s_ncb.ncb_name );

			/*
			** Copy to local NCB struct -- Netbios seems to fark
			** up if we don't.
			*/
			memcpy( &Name_Ncb, &pcb->s_ncb, sizeof( Name_Ncb ) );

			Netbios( &Name_Ncb );

			if (Name_Ncb.ncb_retcode == NRC_GOODRET)
			    break;
			else if (Name_Ncb.ncb_retcode == NRC_DUPNAME)
			    continue;
			else
			{
			    status = (STATUS)Name_Ncb.ncb_retcode;
			    CloseHandle( Name_Ncb.ncb_event );
			    pcb->s_ncb.ncb_event = NULL;
			    CloseHandle( pcb->r_ncb.ncb_event );
			    pcb->r_ncb.ncb_event = NULL;
			    pcb->state.conn = COMPLETED;
			    SETWIN32ERR(&parm_list->system_status, status,
					ER_netbios);
			    parm_list->generic_status = GC_CONNECT_FAIL;
			    break;
			}
		    }

		    if (parm_list->generic_status == GC_CONNECT_FAIL)
			break;

		    /*
		    ** just in case ...
		    */
		    ResetEvent( pcb->s_ncb.ncb_event );

		    /*
		    ** OK, now make the call
		    */
		    hSave = pcb->s_ncb.ncb_event;    /* save handle */
		    memset( &pcb->s_ncb, 0, sizeof(NCB) );
		    pcb->s_ncb.ncb_event = hSave;    /* restore handle */
		    pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr;    
		    pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng;    
		    pcb->s_ncb.ncb_command = NCBCALL | ASYNCH;
		    pcb->s_ncb.ncb_lana_num = lana_num;
		    STcopy( GCc_client_name, pcb->s_ncb.ncb_name );
		    STpolycat( 3, parm_list->function_parms.connect.node_id,
		    	       "_", parm_list->function_parms.connect.port_id,
			       callname );
		    CVupper( callname );

		    
		    /*
		    ** Loopback check to prevent mangling the name (?)
		    */
		    if ( STcompare( parm_list->function_parms.connect.port_id,
		    		    GCc_listen_port ) == 0 )
		    {
		        STcopy( GCc_listen_port, pcb->s_ncb.ncb_callname );
		    }
		    else
		    {
		        STcopy( callname, pcb->s_ncb.ncb_callname );
		    }

		    GCTRACE(3)("LMAN THREAD: CONNECT doing CALL to %s\n",
		    		pcb->s_ncb.ncb_callname );

		    if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET )
		    {
		        status = (STATUS)pcb->s_ncb.ncb_retcode;
			CloseHandle( pcb->s_ncb.ncb_event );
			pcb->s_ncb.ncb_event = NULL;
			CloseHandle( pcb->r_ncb.ncb_event );
			pcb->r_ncb.ncb_event = NULL;
			pcb->state.conn = COMPLETED;
			SETWIN32ERR(&parm_list->system_status, status, ER_netbios);
			parm_list->generic_status = GC_CONNECT_FAIL;
			break;
		    }

		    GCTRACE(3)("LMAN THREAD: Async CALL OK\n" );

		    pcb->state.conn = COMPLETING;

		    break;


		    /*******************************************************
		    ** Handle SEND
		    *******************************************************/
		    case GCC_SEND:

		    GCTRACE(4)("LMAN THREAD: process SEND\n");

		    if ( pcb->state.send != INITIAL )
		    {
		        break;
		    }
		    pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr;    
		    pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng;    
		    pcb->s_ncb.ncb_lana_num = lana_num;
		    pcb->s_ncb.ncb_command = NCBSEND | ASYNCH;
		    if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET )
		    {
		        status = (STATUS)pcb->s_ncb.ncb_retcode;
			pcb->state.send = COMPLETED;
			SETWIN32ERR(&parm_list->system_status, status, ER_netbios);
			parm_list->generic_status = GC_SEND_FAIL;
		    }

		    pcb->state.send = COMPLETING;

		    break;


		    /*******************************************************
		    ** Handle RECEIVE
		    *******************************************************/
		    case GCC_RECEIVE:

		    GCTRACE(4)("LMAN THREAD: process RECEIVE\n");

		    if ( pcb->state.recv != INITIAL )
		    {
                        pending_requests++;
		        break;
		    }
		    pcb->r_ncb.ncb_buffer = parm_list->buffer_ptr;    
		    pcb->r_ncb.ncb_length = (WORD)parm_list->buffer_lng;    
		    pcb->r_ncb.ncb_lana_num = lana_num;
		    pcb->r_ncb.ncb_command = NCBRECV | ASYNCH;

		    if ( Netbios( &pcb->r_ncb ) != NRC_GOODRET )
		    {
		        status = (STATUS)pcb->r_ncb.ncb_retcode;
			pcb->state.recv = COMPLETED;
			SETWIN32ERR(&parm_list->system_status, status, ER_netbios);
			parm_list->generic_status = GC_RECEIVE_FAIL;
		    }

		    pcb->state.recv = COMPLETING;

		    break;

		    /*******************************************************
		    ** Handle DISCONNECT
		    *******************************************************/
		    case GCC_DISCONNECT:

		    GCTRACE(4)("LMAN THREAD: process DISCONNECT\n");

		    if ( pcb && pcb->state.disc == INITIAL ) 
		    {
		        pcb->s_ncb.ncb_buffer = parm_list->buffer_ptr;    
		        pcb->s_ncb.ncb_length = (WORD)parm_list->buffer_lng;    
		        pcb->s_ncb.ncb_command = NCBHANGUP | ASYNCH;
		    	pcb->s_ncb.ncb_lana_num = lana_num;
			if ( pcb->s_ncb.ncb_lsn == 0 )
			    pcb->s_ncb.ncb_lsn = pcb->r_ncb.ncb_lsn;
		        if ( Netbios( &pcb->s_ncb ) != NRC_GOODRET )
		        {
		            status = (STATUS)pcb->s_ncb.ncb_retcode;
		    	    pcb->state.disc = COMPLETED;
			    SETWIN32ERR(&parm_list->system_status, status, ER_netbios);
			    parm_list->generic_status = GC_DISCONNECT_FAIL;
			    break;
		        }
		        pcb->state.disc = COMPLETING;
		    }

		    break;

		} /* end switch */

	    } /* end for process q loop */

	    /*
	    ** Now go thru the inprocess Q and look for any requests that
	    ** have been completed.  This will be indicated by one of:
	    ** parm_list->pcb == NULL (bad connect or after disconnect) or
	    ** pcb->state == COMPLETED, or WaitForSingleObject indicates
	    ** completion.
	    */

	    GCTRACE(4)("LMAN THREAD: processing completed. . . \n");

	    q = Tptr->process_head.q_next;
	    while( q != &Tptr->process_head )
	    {
	        REQUEST_Q *rq = (REQUEST_Q *)q;
	        GCC_P_PLIST *pl = rq->plist;
		PCB *pcb = (PCB *)pl->pcb;
		bool completed = FALSE;

		switch ( pl->function_invoked )
		{
		    case GCC_CONNECT:
		        if ( pcb == NULL || pcb->state.conn == COMPLETED || 
			     WaitForSingleObject( pcb->s_ncb.ncb_event, 0) ==
			         WAIT_OBJECT_0 )
			{
			    if (pcb) 
			    {
			        ResetEvent( pcb->s_ncb.ncb_event );
			        pcb->r_ncb.ncb_lsn = pcb->s_ncb.ncb_lsn;
				if ( pcb->s_ncb.ncb_lsn == 0 ||
				     pcb->s_ncb.ncb_retcode != NRC_GOODRET )
				{
				    pl->generic_status = GC_CONNECT_FAIL;
				    status = (STATUS)pcb->s_ncb.ncb_retcode;
				    SETWIN32ERR( &pl->system_status, status , ER_revent);
				    CloseHandle( pcb->s_ncb.ncb_event );
				    CloseHandle( pcb->r_ncb.ncb_event );
				    free( pcb );
				    pl->pcb = NULL;
				}
			    }

			    completed = TRUE;
			}
		        break;
		    case GCC_SEND:
		        if ( pcb == NULL || pcb->state.send == COMPLETED || 
			     WaitForSingleObject( pcb->s_ncb.ncb_event, 0) ==
			         WAIT_OBJECT_0 )
			{
			    ResetEvent( pcb->s_ncb.ncb_event );
			    if ( pcb->s_ncb.ncb_lsn == 0 ||
			         pcb->s_ncb.ncb_retcode != NRC_GOODRET )
			    {
				    pl->generic_status = GC_SEND_FAIL;
				    status = (STATUS)pcb->s_ncb.ncb_retcode;
				    SETWIN32ERR( &pl->system_status, status , ER_revent);
			    }
			    else
			    {
			        GCTRACE(2)(
				"LMAN THREAD: Send COMP pl len %d pcb len %d\n",
			            pl->buffer_lng, pcb->s_ncb.ncb_length);
					
			        pl->buffer_lng = pcb->s_ncb.ncb_length;
			    }
			    completed = TRUE;
			}
		        break;
		    case GCC_RECEIVE:
		        if ( pcb == NULL || pcb->state.recv == COMPLETED || 
			     WaitForSingleObject( pcb->r_ncb.ncb_event, 0) ==
			         WAIT_OBJECT_0 )
			{
			    ResetEvent( pcb->r_ncb.ncb_event );
			    if ( pcb->s_ncb.ncb_lsn == 0 ||
			         pcb->r_ncb.ncb_retcode != NRC_GOODRET )
			    {
				    pl->generic_status = GC_RECEIVE_FAIL;
				    status = (STATUS)pcb->r_ncb.ncb_retcode;
				    SETWIN32ERR( &pl->system_status, status , ER_revent);
			    }
			    else
			    {
			        pl->buffer_lng = pcb->r_ncb.ncb_length;
			    }
			    completed = TRUE;
			}
		        break;
		    case GCC_DISCONNECT:
		        if ( pcb == NULL || pcb->state.disc == COMPLETED || 
			     WaitForSingleObject( pcb->s_ncb.ncb_event, 0) ==
			         WAIT_OBJECT_0 )
			{
			    if (pcb) 
			    {
				if ( pcb->s_ncb.ncb_lsn == 0 ||
				     pcb->s_ncb.ncb_retcode != NRC_GOODRET )
				{
				    pl->generic_status = GC_DISCONNECT_FAIL;
				    status = (STATUS)pcb->s_ncb.ncb_retcode;
				    SETWIN32ERR( &pl->system_status, status , ER_revent);
				}
				pcb->s_ncb.ncb_command = NCBDELNAME;
				Netbios( &pcb->s_ncb );
				CloseHandle( pcb->s_ncb.ncb_event );
				CloseHandle( pcb->r_ncb.ncb_event );
				free( pcb );
				pl->pcb = NULL;
			    }
			    completed = TRUE;
			}
		        break;
		} /* end switch */

		if ( completed )
		{
		    QUEUE *nq = q->q_next;

	    	    GCTRACE(3)("LMAN THREAD:  Complete! PCB = %x PARM = %x \n",
		    		pcb, pl);

		    GCcomplete_request( q );

		    q = nq;
		    processing_requests--;

	    	    GCTRACE(3)("LMAN THREAD: processed completed \n");
	    	    GCTRACE(3)("                 : total now = %d \n",
		    		processing_requests);

		} /* end if req completed */
		else
		{
		    q = q->q_next;
		}

	    } /* end for -- look for complete req */

	    /*
	    ** Do a quick, non-blocking check to see if any new requests
	    ** came in during processing.
	    */
	    GCTRACE(4)("LMAN THREAD: quick look for new reqs \n");
	    if ( WaitForSingleObject( hEventThreadInQ, 0 ) == WAIT_OBJECT_0 )
	    {
		processing_requests += GCget_incoming_reqs( Tptr, 
					   hMutexThreadInQ );
	    }
	    GCTRACE(4)("LMAN THREAD: process reqs now = %d\n",
	    		processing_requests);

            if (processing_requests && pending_requests == processing_requests)
            {
                i4 Sleeptime = 1;
                Sleep(Sleeptime);
            }

	} /* end while processing requests */

	if (In_Shutdown)
	{
		_endthreadex(0);
		return;
	}

	/*
	** we're done for now, go back to the top and sleep.
	*/
	GCTRACE(3)("LMAN THREAD: No more reqs, going back to top\n" );
	goto top;
}
示例#3
0
/*
** Name: GClanman_open
** Description:
**	Open the listen channel for LANMAN.   Called from GClanman().  This
**	routine should only be called once at server startup.
** History:
**	11-nov-93 (edg)
**	    created.
**	03-may-1996 (canor01)
**	    Allow for more than the default number of sessions.
**	29-jun-2000 (somsa01)
**	    Use GCc_listen_port for the ncb_name, making sure that we
**	    update GCc_listen_port if we need a unique one.
**      06-Aug-2009 (Bruce Lunsford) Sir 122426
**          Remove mutexing around calls to GCA service completion routine
**          as it is no longer necessary, since GCA is thread-safe...removes
**          calls to GCwaitCompletion + GCrestart. Should improve peformance.
*/
STATUS
GClanman_open( GCC_P_PLIST *parm_list )
{
	STATUS	status;
	LANA_ENUM	lanas;
	i4		subport = 0;

	/*
	** Find available adapters
	*/
	memset( &Listen_Ncb, 0, sizeof(NCB) );
	Listen_Ncb.ncb_buffer = &lanas;
	Listen_Ncb.ncb_length = sizeof(LANA_ENUM);
	Listen_Ncb.ncb_command = NCBENUM;
	Netbios( &Listen_Ncb );
	if ( lanas.length == 0 )
	{
		status = (STATUS)Listen_Ncb.ncb_retcode;
		GCTRACE(1)("GClanman_open: No LANA adapters %d\n",
			    status );
		parm_list->generic_status = GC_OPEN_FAIL;
		SETWIN32ERR(&parm_list->system_status, status, ER_listen);
		goto err_exit;
	}
	/* use first available LANA */
	lana_num = lanas.lana[0];

	/*
	** Use Listen_Ncb to 1st do a reset to start things out ...
	*/
	memset( &Listen_Ncb, 0, sizeof(NCB) );
	Listen_Ncb.ncb_buffer = Dummy_Buf;
	Listen_Ncb.ncb_length = sizeof(Dummy_Buf);
	Listen_Ncb.ncb_lana_num = lana_num;
	Listen_Ncb.ncb_callname[0] = 255; /* max number of sessions */
	Listen_Ncb.ncb_callname[2] = 255; /* max number of names */
	Listen_Ncb.ncb_command = NCBRESET;
	Netbios( &Listen_Ncb );

	/*
	** Add Name we'll be listening on.
	*/
	memset( &Listen_Ncb, 0, sizeof(NCB) );
	Listen_Ncb.ncb_buffer = Dummy_Buf;
	Listen_Ncb.ncb_length = sizeof(Dummy_Buf);
	Listen_Ncb.ncb_lana_num = lana_num;
	Listen_Ncb.ncb_command = NCBADDNAME;

	for (;;)
	{
	    if (subport)
		STprintf(Listen_Ncb.ncb_name, "%s%d", GCc_listen_port, subport);
	    else
		STcopy( GCc_listen_port, Listen_Ncb.ncb_name );

	    Netbios( &Listen_Ncb );

	    if (Listen_Ncb.ncb_retcode == NRC_GOODRET)
		break;
	    else if (Listen_Ncb.ncb_retcode == NRC_DUPNAME && (++subport) < 8)
		continue;
	    else
	    {
		status = (STATUS)Listen_Ncb.ncb_retcode;
		GCTRACE(1)("GClanman_open: Error ADDNAME returned %d\n",
			    status );
		parm_list->generic_status = GC_OPEN_FAIL;
		SETWIN32ERR(&parm_list->system_status, status, ER_listen);
		goto err_exit;
	    }
	}

	/*
	** Set listen port in parm list.
	*/
	STcopy(Listen_Ncb.ncb_name, GCc_listen_port);
	if (subport)
	{
	    STprintf(parm_list->pce->pce_port, "%s%d",
		     parm_list->function_parms.open.port_id, subport);
	}
	parm_list->function_parms.open.lsn_port = GCc_listen_port;

err_exit:
	/*
	** Should completion be driven here?
	*/
	(*parm_list->compl_exit) (parm_list->compl_id);
	return OK;
}
示例#4
0
/*
** Name: GClanman_listen
** Description:
**	This is the listen thread for lanman.  It runs a syncronous accept()
**	on the listen socket.  When complete it Q's the completetion to
**	the completed event Q.  When accept completes, this thread returns.
**	A new one will be created when GClanman() gets the request to
**	repost the listen.
** History:
**	11-nov-93 (edg)
**	    created.
**	29-jun-2000 (somsa01)
**	    Use GCc_listen_port for the ncb_name.
**	16-mar-2001 (somsa01)
**	    Set node_id to ncb_callname.
**      06-Aug-2009 (Bruce Lunsford) Sir 122426
**          Convert GCC completion queue mutex to a critical section
**          to improve performance (less overhead).
**	    Since _beginthreadex() is now used to start this thread,
**	    use _endthreadex() to end it.
*/
VOID
GClanman_listen( VOID *parms )
{
    GCC_P_PLIST		*parm_list = (GCC_P_PLIST *)parms;
    PCB			*pcb;
    STATUS		status = OK;
    REQUEST_Q		*rq;
    SECURITY_ATTRIBUTES	sa;

    iimksec (&sa);

    /*
    ** Initialize the listen node_id to NULL.
    */
    parm_list->function_parms.listen.node_id = NULL;

    /*
    ** Initialize fields of the Listen_Ncb
    */
    memset( &Listen_Ncb, 0, sizeof(NCB) );
    Listen_Ncb.ncb_buffer = parm_list->buffer_ptr;
    Listen_Ncb.ncb_length = (USHORT)parm_list->buffer_lng;
    Listen_Ncb.ncb_command = NCBLISTEN;
    Listen_Ncb.ncb_lana_num = lana_num;
    *Listen_Ncb.ncb_callname = (unsigned char)NULL;
    STmove( "*", ' ', NCBNAMSZ, Listen_Ncb.ncb_callname );
    *Listen_Ncb.ncb_name = (unsigned char)NULL;
    STcopy( GCc_listen_port, Listen_Ncb.ncb_name );


    /*
    ** Now we can do the NCBLISTEN request.  Block until it completes.
    */
    Netbios( &Listen_Ncb );
    if ( Listen_Ncb.ncb_retcode != NRC_GOODRET )
    {
	status = (int)Listen_Ncb.ncb_retcode;
	goto sys_err;
    }

    /*
    ** Allocate Protcol Control Block specific to this driver and put into
    ** parm list
    */
    pcb = (PCB *) malloc( sizeof(PCB) );
    if (pcb == NULL) 
    {
	status = errno;
	goto sys_err;
    }
    memset( pcb, 0, sizeof( *pcb ) );
    parm_list->pcb = (char *)pcb;

    /*
    ** Set node_id to the node name of the partner.
    */
    parm_list->function_parms.listen.node_id = STalloc(Listen_Ncb.ncb_callname);

    /*
    ** Now assign the pcb's send and receive NCB's the local session number
    ** returned by listen for further communications.
    */
    pcb->s_ncb.ncb_lsn = pcb->r_ncb.ncb_lsn = Listen_Ncb.ncb_lsn;

    /*
    ** Now create handles for the read and write event handles in the
    ** NCB.  These are created with manual reset as cautioned by the 
    ** programmer's guide so a ResetEvent MUST be done on them.
    */
    if ((pcb->s_ncb.ncb_event = CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL)
    {
        status = GetLastError();
	goto sys_err;
    }
    if ((pcb->r_ncb.ncb_event = CreateEvent( &sa, TRUE, FALSE, NULL ))== NULL)
    {
        status = GetLastError();
	CloseHandle( pcb->s_ncb.ncb_event );
	pcb->s_ncb.ncb_event = NULL;
	goto sys_err;
    }

sys_err:
    if (status != OK) 
    {
        SETWIN32ERR(&parm_list->system_status, status, ER_create);
	parm_list->generic_status = GC_LISTEN_FAIL;
    }

    /*
    ** Now allocate a request q structure, stick it into complete q, and
    ** raise the GCC_COMPLETE event.
    */
    if ( (rq = (REQUEST_Q *)MEreqmem(0, sizeof(*rq), TRUE, NULL ) ) != NULL )
    {
        rq->plist = parm_list;
	/*
	** Get critical section for completion Q.
	*/
	EnterCriticalSection( &GccCompleteQCritSect );

	/*
	** Now insert the completed request into the completed Q.
	*/
	QUinsert( &rq->req_q, &IIGCc_proto_threads.completed_head );

	/*
	** Exit/leave critical section for completion Q
	*/
	LeaveCriticalSection( &GccCompleteQCritSect );

	/*
	** raise the completion event to wake up GCexec.
	*/
	if ( !SetEvent( hAsyncEvents[GCC_COMPLETE] ) )
	{
	   /*
	   ** ruh roh.  We're screwed if this event can't be signaled.
	   */
	   status = GetLastError();
	   GCTRACE(1)("GClanman_listen, SetEvent error = %d\n", status );
	}

    }
    else
    {
        /*
	** ruh-roh.  MEreqmem failed.  Selious tlouble.  Not sure what to
	** do about it at this point since if it failed we can't notify
	** the completion routine.  For now, just return (exit thread)
	** which will probably have the effect of blocking all incoming
	** connections.
	*/
    }
    _endthreadex(0);
}
示例#5
0
/*
** Name: GClanman
** Description:
**	Main entry point for the window's NT lan manager protocol driver.  This
** 	driver is essentially just a dispatcher -- it runs in the primary
**	GCC thread and mostly just Q's things to do to the constantly running
**	aynchronous request thread.  It may also start a listen thread if
**	it is a LISTEN request.
**
**	The following functions are handled:
**	    GCC_OPEN	- call GClanman_open
**	    GCC_LISTEN  - start listen thread
**	    GCC_SEND    - Q request for asynch thread
**	    GCC_RECEIVE - Q request for asynch thread
**	    GCC_CONNECT - Q request for asynch thread
**	    GCC_DISCONN - Q request for asynch thread
** History:
**	11-Nov-93 (edg)
**	    Original.
**      06-Aug-2009 (Bruce Lunsford) Sir 122426
**          Remove mutexing around calls to GCA service completion routine
**          as it is no longer necessary, since GCA is thread-safe...removes
**          calls to GCwaitCompletion + GCrestart. Should improve peformance.
**	    Convert CreateThread() to _beginthreadex() which is recommended
**	    when using C runtime.
*/
STATUS
GClanman( i4 function_code, GCC_P_PLIST * parm_list)
{
	STATUS          generror = 0;
	int             status = 0;
	int             tid;
	HANDLE          hThread;
    	REQUEST_Q 	*rq;
	SECURITY_ATTRIBUTES sa;

	iimksec (&sa);

	CLEAR_ERR(&parm_list->system_status);

	/*
	** set error based on function code and determine whether we got a
	** valid function.
	*/
	switch (function_code) {
	case GCC_OPEN:
		is_comm_svr = TRUE;
		GCTRACE(2) ("GClanman: Function = OPEN\n" );
		return GClanman_open( parm_list );

	case GCC_LISTEN:
		GCTRACE(2) ("GClanman: Function = LISTEN\n" );
		generror = GC_LISTEN_FAIL;
                /*
                ** For Lanman, the peer is always remote.
                */
                parm_list->options = 0;

		/*
		** Spawn off a thread to handle the listen request
		*/
		hThread = (HANDLE)_beginthreadex(&sa,
			       GC_STACK_SIZE,
			       (LPTHREAD_START_ROUTINE) GClanman_listen,
			       parm_list,
			       (unsigned long)NULL,
			       &tid);
		if (hThread) 
		{
			CloseHandle(hThread);
			return (OK);
		}
		status = errno;
		SETWIN32ERR(&parm_list->system_status, status, ER_create);
		goto err_exit;
		break;

	case GCC_CONNECT:
	    GCTRACE(2) ("GClanman: Function = CONNECT\n" );
	    generror = GC_CONNECT_FAIL;
	    break;
	case GCC_SEND:
	    GCTRACE(2) ("GClanman: Function = SEND\n" );
	    generror = GC_SEND_FAIL;
	    break;
	case GCC_RECEIVE:
	    GCTRACE(2) ("GClanman: Function = RECEIVE\n" );
	    generror = GC_RECEIVE_FAIL;
	    break;
	case GCC_DISCONNECT:
	    GCTRACE(2) ("GClanman: Function = DISCONNECT\n" );
	    generror = GC_DISCONNECT_FAIL;
	    break;

	default:
	    return FAIL;
	}			/* end switch */
	/*
	** CONNECT, SEND, RECEIVE and DISCONNECT are all dispatched
	** to the asynch thread.
   	** Now allocate a request q structure, stick it into incoming q,
   	** and raise the INCOMING REQUEST event.
   	*/
	GCTRACE(2)("GClanman: Q'ing request ...\n");

    	if ( (rq = (REQUEST_Q *)MEreqmem(0, sizeof(*rq), TRUE, NULL ) ) != NULL )
    	{
            rq->plist = parm_list;
	    /*
	    ** get mutex for completion Q
	    */
	    GCTRACE(2)("GClanman: wait for input mutex ...\n");
	    WaitForSingleObject( hMutexThreadInQ, INFINITE );

	    /*
	    ** Now insert the completed request into the inconming Q.
	    */
	    GCTRACE(2)("GClanman: inserting incoming req ...\n");
	    QUinsert( &rq->req_q, &Tptr->incoming_head );

	    /*
	    ** release mutex for completion Q
	    */
	    GCTRACE(2)("GClanman: releasing Mutex incoming req ...\n");
	    ReleaseMutex( hMutexThreadInQ );

	    /*
	    ** raise the incoming event to wake up the thread.
	    */
	    GCTRACE(2)("GClanman: Setting event ...\n");
	    if ( !SetEvent( hEventThreadInQ ) )
	    {
	   	    status = GetLastError();
		    SETWIN32ERR(&parm_list->system_status, status, ER_sevent);
	   	    GCTRACE(1)("GClanman, SetEvent error = %d\n", 
		    		status );
	    }

	    return OK;

   	}
    	else
    	{
	        /*
		** MEreqmem failed
		*/
		SETWIN32ERR(&parm_list->system_status, errno, ER_alloc);
    	}

	/*
	 * * Drive the completion routine on error
	 */
err_exit:
	parm_list->generic_status = generror;
	(*parm_list->compl_exit) (parm_list->compl_id);
	return OK;
}
示例#6
0
/******************************************************************************
**
** Name: DI_list - Use WIN32 NT directory listing interface to list files
**
** Description:
**	List all files/directories in a given directory depending on
**	list_type argument.
**
** Inputs:
**      path                 Pointer to the path name.
**      pathlength           Length of path name.
**	    list_type	         type of object to list (DIRECTORY or FILE)
**	    func		         function to call for each object found.
**	    arg_list	         arguments to call the function with.
**
** Outputs:
**      err_code             Pointer to a variable used
**                           to return operating system
**                           errors.
**
**    Returns:
**        DI_BADDIR          Path specification error.
**        DI_ENDFILE         Error returned from client handler or
**                           all files listed.
**        DI_BADPARAM        Parameter(s) in error.
**        DI_DIRNOTFOUND     Path not found.
**        DI_BADLIST         Error trying to list objects.
**
**    Exceptions:
**        none
**
** Side Effects:
**        none
**
** History:
**	07-jul-1995 (canor01)
**	    convert filename returned from FindFirstFile() to lowercase, since
**	    other DI functions (via unix) expect lowercase.
**      18-jul-1995 (reijo01)
**          Changed SETWIN32ERR so that it will populate the CL_ERR_DESC with
**              the proper values.
**      08-dec-1997 (canor01)
**          Implement LRU for open files (initial copy from Unix).
**	28-jan-1998 (canor01)
**	    Correct a problem with previous implementation.  If closing
**	    files succeeds, retry, else bail out with error.
**	04-mar-1998 (canor01)
**	    Parameters to DIlru_flush were changed on Unix side.  Change
**	    them here too.
**
******************************************************************************/
static STATUS
DI_list(char       *path,
        u_i4       pathlength,
        i4         list_type,
        STATUS     (*func) (),
        PTR        arg_list,
        CL_SYS_ERR *err_code)
{
	STATUS          ret_val = OK;
	STATUS          dos_call;

	char            input_path[DI_PATH_MAX];
	HANDLE          handle;
	ULONG           count = 1;
	WIN32_FIND_DATA findbuf;

	/* default returns */

	CLEAR_ERR(err_code);

	/* Check input parameters */

	if ((pathlength > DI_PATH_MAX) ||
	    (pathlength == 0))
		return DI_BADPARAM;

	/* get null terminated path to the directory */

	memcpy(input_path, path, pathlength);
	memcpy(input_path + pathlength, "\\*.*", 5);

	/* break out on errors */

	while ( (handle = FindFirstFile(input_path, &findbuf)) == 
		INVALID_HANDLE_VALUE )
	{
		switch (dos_call = GetLastError()) 
		{
            	case ERROR_NO_SYSTEM_RESOURCES:
                case ERROR_TOO_MANY_OPEN_FILES:
                case ERROR_NO_MORE_FILES:
                case ERROR_NOT_ENOUGH_MEMORY:
                case ERROR_OUTOFMEMORY:
                case ERROR_HANDLE_DISK_FULL:
                case ERROR_OUT_OF_STRUCTURES:
                case ERROR_NONPAGED_SYSTEM_RESOURCES:
                case ERROR_PAGED_SYSTEM_RESOURCES:
            		if (DIlru_flush( err_code ) != OK)
            		{
                	    ret_val = DI_BADLIST;
            		}
			else
			{
			    continue;
			}
                	break;
		case ERROR_PATH_NOT_FOUND:
			SETWIN32ERR(err_code, dos_call, ER_list);
			ret_val = DI_DIRNOTFOUND;
			break;
		default:
			SETWIN32ERR(err_code, dos_call, ER_list);
			ret_val = DI_BADLIST;
			break;
		}
		if ( ret_val != OK )
		    return(ret_val);
	}

	/* now loop through all entries in the directory */

	ret_val = DI_ENDFILE;

	do {
		if (!memcmp(findbuf.cFileName, ".", 2) ||
		    !memcmp(findbuf.cFileName, "..", 3)) 
		{
			continue;
		}

		/*
		 * This next check is a leftover from OS/2.  Should dump it
		 * at some point, or enlarge the functionality of this
		 * routine. If we're looking for a directory, verify it is
		 * one...
		 */

		if (list_type == DIRECTORY) 
		{
			if (~findbuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
				continue;
			}
		}

		/* 
		* other functions expect lowercase name, but DOS
		* returns uppercase
                *
                * bug fix 89213.  
                * Unlike DOS, NT returns upper and lower case
                * names.
		*/
		if ((*func) (arg_list,
		             findbuf.cFileName,
		             STlength(findbuf.cFileName),
		             err_code)) 
		{
			ret_val = DI_ENDFILE;
			break;
		}
	} while (FindNextFile(handle, &findbuf));

	if (!FindClose(handle)) 	
	{
		SETWIN32ERR(err_code, GetLastError(), ER_list);
		ret_val = DI_BADLIST;
	}

	return (ret_val);
}