none
how to write a windows service program that can communicate with another process using mailslot? RRS feed

  • Question

  • Hi everyone,

    i am learning the windows service program,and recently i want  to write a service demo that the service create a mailslot and i write the mailslot in another win32 console program.But i always failed,can you tell me how to solve this program?

    the service program is below 

    #include <windows.h>
    #include <tchar.h>
    #include <strsafe.h>
    #include "sample.h"
    #include <fstream>
    #include <stdio.h>
    #pragma comment(lib, "advapi32.lib")
    
    #define SVCNAME TEXT("SvcName")
    //mailslot 
    
    HANDLE hSlot;
    LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\D:\\sample_mailslot");
    LPTSTR Message = TEXT("Message for mailslot in primary domain."); 
    
    SERVICE_STATUS          gSvcStatus; 
    SERVICE_STATUS_HANDLE   gSvcStatusHandle; 
    HANDLE                  ghSvcStopEvent = NULL;
    
    VOID SvcInstall(void);
    VOID WINAPI SvcCtrlHandler( DWORD ); 
    VOID WINAPI SvcMain( DWORD, LPTSTR * ); 
    
    VOID ReportSvcStatus( DWORD, DWORD, DWORD );
    VOID SvcInit( DWORD, LPTSTR * ); 
    VOID SvcReportEvent( LPTSTR );
    
    
    //
    // Purpose: 
    //   Entry point for the process
    //
    // Parameters:
    //   None
    // 
    // Return value:
    //   None
    //
    void __cdecl _tmain(int argc, TCHAR *argv[]) 
    { 
        // If command-line parameter is "install", install the service. 
        // Otherwise, the service is probably being started by the SCM.
    
        if( lstrcmpi( argv[1], TEXT("install")) == 0 )
        {
            SvcInstall();
            return;
        }
    
        // TO_DO: Add any additional services for the process to this table.
        SERVICE_TABLE_ENTRY DispatchTable[] = 
        { 
            { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, 
            { NULL, NULL } 
        }; 
     
        // This call returns when the service has stopped. 
        // The process should simply terminate when the call returns.
    
        if (!StartServiceCtrlDispatcher( DispatchTable )) 
        { 
            SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); 
        } 
    } 
    
    //
    // Purpose: 
    //   Installs a service in the SCM database
    //
    // Parameters:
    //   None
    // 
    // Return value:
    //   None
    //
    VOID SvcInstall()
    {
        SC_HANDLE schSCManager;
        SC_HANDLE schService;
        TCHAR szPath[MAX_PATH];
    
        if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
        {
            printf("Cannot install service (%d)\n", GetLastError());
            return;
        }
    
        // Get a handle to the SCM database. 
     
        schSCManager = OpenSCManager( 
            NULL,                    // local computer
            NULL,                    // ServicesActive database 
            SC_MANAGER_ALL_ACCESS);  // full access rights 
     
        if (NULL == schSCManager) 
        {
            printf("OpenSCManager failed (%d)\n", GetLastError());
            return;
        }
    
        // Create the service
    
        schService = CreateService( 
            schSCManager,              // SCM database 
            SVCNAME,                   // name of service 
            SVCNAME,                   // service name to display 
            SERVICE_ALL_ACCESS,        // desired access 
            SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, // service type 
            SERVICE_DEMAND_START,      // start type 
            SERVICE_ERROR_NORMAL,      // error control type 
            szPath,                    // path to service's binary 
            NULL,                      // no load ordering group 
            NULL,                      // no tag identifier 
            NULL,                      // no dependencies 
            NULL,                      // LocalSystem account 
            NULL);                     // no password 
     
        if (schService == NULL) 
        {
            printf("CreateService failed (%d)\n", GetLastError()); 
            CloseServiceHandle(schSCManager);
            return;
        }
        else printf("Service installed successfully\n"); 
    
        CloseServiceHandle(schService); 
        CloseServiceHandle(schSCManager);
    }
    
    //
    // Purpose: 
    //   Entry point for the service
    //
    // Parameters:
    //   dwArgc - Number of arguments in the lpszArgv array
    //   lpszArgv - Array of strings. The first string is the name of
    //     the service and subsequent strings are passed by the process
    //     that called the StartService function to start the service.
    // 
    // Return value:
    //   None.
    //
    VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
    {
        // Register the handler function for the service
    
        gSvcStatusHandle = RegisterServiceCtrlHandler( 
            SVCNAME, 
            SvcCtrlHandler);
    
        if( !gSvcStatusHandle )
        { 
            SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); 
            return; 
        } 
    
        // These SERVICE_STATUS members remain as set here
    
        gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 
        gSvcStatus.dwServiceSpecificExitCode = 0;    
    
        // Report initial status to the SCM
    
        ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
    
        // Perform service-specific initialization and work.
    
        SvcInit( dwArgc, lpszArgv );
    }
    
    //
    // Purpose: 
    //   The service code
    //
    // Parameters:
    //   dwArgc - Number of arguments in the lpszArgv array
    //   lpszArgv - Array of strings. The first string is the name of
    //     the service and subsequent strings are passed by the process
    //     that called the StartService function to start the service.
    // 
    // Return value:
    //   None
    //
    VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
    {
        // TO_DO: Declare and set any required variables.
        //   Be sure to periodically call ReportSvcStatus() with 
        //   SERVICE_START_PENDING. If initialization fails, call
        //   ReportSvcStatus with SERVICE_STOPPED.
    
        // Create an event. The control handler function, SvcCtrlHandler,
        // signals this event when it receives the stop control code.
    	static int i =0;
    		std::ofstream  fout("D:\\log.txt");
        ghSvcStopEvent = CreateEvent(
                             NULL,    // default security attributes
                             TRUE,    // manual reset event
                             FALSE,   // not signaled
                             NULL);   // no name
    
        if ( ghSvcStopEvent == NULL)
        {
            ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
            return;
        }
    	fout << i++;
        // Report running status when initialization is complete.
    
        ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
    	fout << i++;
        // TO_DO: Perform work until service stops.
    	//----------------------------------------------------------------------------------------------------------------
    	
    		DWORD cbMessage, cMessage, cbRead; 
    	BOOL fResult; 
    	LPTSTR lpszBuffer; 
    	TCHAR achID[80]; 
    	DWORD cAllMessages; 
    	HANDLE hEvent;
    	OVERLAPPED ov;
    
    	cbMessage = cMessage = cbRead = 0; 
    	 SECURITY_ATTRIBUTES security;
    	 security.bInheritHandle = true;
    	 security.lpSecurityDescriptor =NULL;
    	 security.nLength = sizeof(SECURITY_ATTRIBUTES);
    	hSlot = CreateMailslot(
    		lpszSlotName,		// mailslot
    		0,							
    		MAILSLOT_WAIT_FOREVER,         // no timeout 
    		(LPSECURITY_ATTRIBUTES) &security); 
    
    	if (hSlot == INVALID_HANDLE_VALUE) 
    	{ 
    		fout << "CreateMailslot failed with %d\n"<<GetLastError()<<std::endl;
    		 ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
    		return ; 
    	} 
    	else 	fout <<"Mailslot created successfully.\n"<<std::endl;
    
    	while(1)
    	{
    	
    		fResult = GetMailslotInfo(hSlot, // mailslot 
    			(LPDWORD) NULL,             
    			&cbMessage,                  
    			&cMessage,                    
    			(LPDWORD) NULL);             
    
    		if (!fResult) 
    		{ 
    			fout << "GetMailslotInfo failed with %d.\n"<<GetLastError()<<std::endl;
    			 ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
    			return ; 
    		} 
    		fout <<cbMessage<<std::endl;
    		if (cbMessage == MAILSLOT_NO_MESSAGE) 
    		{ 
    		
    			fout <<"no MESSAGE"<<std::endl;
    			Sleep(20000);
    			continue;
    		} 
    
    		cAllMessages = cMessage; 
    
    		while (cMessage != 0) 
    		{ 
    		
    			fout << L"\nMessage #%d of %d\n"<<cAllMessages - cMessage + 1<<cAllMessages<<std::endl;
    		
    			lpszBuffer = (LPTSTR) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
    				lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage); 
    			if( NULL == lpszBuffer )
    			{
    				break ;
    			}
    		
    			fResult = ReadFile(hSlot,	
    				lpszBuffer,		 
    				cbMessage,			
    				&cbRead,			
    				NULL); 
    
    			if (!fResult) 
    			{ 
    				fout <<"ReadFile failed with %d.\n"<< GetLastError()<<std::endl;
    				GlobalFree((HGLOBAL) lpszBuffer); 
    				break ; 
    			} 
    
    			
    			lstrcat(lpszBuffer, (LPTSTR) achID); 
    			fout <<"Contents of the mailslot: %s\n"<< lpszBuffer<<std::endl;
    			HeapFree(GetProcessHeap(),0,lpszBuffer); 
    		
    			fResult = GetMailslotInfo(hSlot,  
    				(LPDWORD) NULL,     
    				&cbMessage,              
    				&cMessage,                
    				(LPDWORD) NULL);           
    
    			if (!fResult) 
    			{ 
    				fout <<"GetMailslotInfo failed (%d)\n"<< GetLastError()<<std::endl;
    				break ; 
    			} 
    		} 
    	}
    	//---------------------------------------------------------------------------------------------------------------------------------
        while(1)
        {
            // Check whether to stop the service.
    
            WaitForSingleObject(ghSvcStopEvent, INFINITE);
    
            ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
            return;
        }
    }
    
    //
    // Purpose: 
    //   Sets the current service status and reports it to the SCM.
    //
    // Parameters:
    //   dwCurrentState - The current state (see SERVICE_STATUS)
    //   dwWin32ExitCode - The system error code
    //   dwWaitHint - Estimated time for pending operation, 
    //     in milliseconds
    // 
    // Return value:
    //   None
    //
    VOID ReportSvcStatus( DWORD dwCurrentState,
                          DWORD dwWin32ExitCode,
                          DWORD dwWaitHint)
    {
        static DWORD dwCheckPoint = 1;
    
        // Fill in the SERVICE_STATUS structure.
    
        gSvcStatus.dwCurrentState = dwCurrentState;
        gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
        gSvcStatus.dwWaitHint = dwWaitHint;
    
        if (dwCurrentState == SERVICE_START_PENDING)
            gSvcStatus.dwControlsAccepted = 0;
        else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    
        if ( (dwCurrentState == SERVICE_RUNNING) ||
               (dwCurrentState == SERVICE_STOPPED) )
            gSvcStatus.dwCheckPoint = 0;
        else gSvcStatus.dwCheckPoint = dwCheckPoint++;
    
        // Report the status of the service to the SCM.
        SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
    }
    
    //
    // Purpose: 
    //   Called by SCM whenever a control code is sent to the service
    //   using the ControlService function.
    //
    // Parameters:
    //   dwCtrl - control code
    // 
    // Return value:
    //   None
    //
    VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
    {
       // Handle the requested control code. 
    
       switch(dwCtrl) 
       {  
          case SERVICE_CONTROL_S
             ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
    
             // Signal the service to stop.
    
             SetEvent(ghSvcStopEvent);
             ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
             
             return;
     
          case SERVICE_CONTROL_INTERROGATE: 
             break; 
     
          default: 
             break;
       } 
       
    }
    
    //
    // Purpose: 
    //   Logs messages to the event log
    //
    // Parameters:
    //   szFunction - name of function that failed
    // 
    // Return value:
    //   None
    //
    // Remarks:
    //   The service must have an entry in the Application event log.
    //
    VOID SvcReportEvent(LPTSTR szFunction) 
    { 
        HANDLE hEventSource;
        LPCTSTR lpszStrings[2];
        TCHAR Buffer[80];
    
        hEventSource = RegisterEventSource(NULL, SVCNAME);
    
        if( NULL != hEventSource )
        {
            StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError());
    
            lpszStrings[0] = SVCNAME;
            lpszStrings[1] = Buffer;
    
            ReportEvent(hEventSource,        // event log handle
                        EVENTLOG_ERROR_TYPE, // event type
                        0,                   // event category
                        SVC_ERROR,           // event identifier
                        NULL,                // no security identifier
                        2,                   // size of lpszStrings array
                        0,                   // no binary data
                        lpszStrings,         // array of strings
                        NULL);               // no binary data
    
            DeregisterEventSource(hEventSource);
        }
    }
    

    And i write a client program that write data in the mailslot created by above program.

    the client program is 

    
    #include <windows.h>
    #include <stdio.h>
    
    HANDLE hSlot;
    LPTSTR lpszSlotName = TEXT("\\\\.\\mailslot\\D:\\sample_mailslot");		
    LPTSTR lpszMessage = TEXT("Test Message for mailslot "); 
    
    
    void main()
    { 
    	BOOL fResult; 
    	HANDLE hFile; 
    	DWORD cbWritten; 
    
    	DWORD cbMessage;
    
    	hFile = CreateFile(lpszSlotName, 
    		 GENERIC_READ | GENERIC_WRITE,		
    		 FILE_SHARE_READ | FILE_SHARE_WRITE ,
    		(LPSECURITY_ATTRIBUTES) NULL, 
    		OPEN_EXISTING,		
    		 FILE_FLAG_SEQUENTIAL_SCAN, 
    		(HANDLE) NULL); 
    
    	if (hFile == INVALID_HANDLE_VALUE) 
    	{ 
    		printf("CreateFile failed with %d.\n", GetLastError()); 
    		return ; 
    	}
    
    	fResult = WriteFile(hFile, 
    		lpszMessage, 
    		(DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),  
    		&cbWritten, 
    		(LPOVERLAPPED) NULL); 
    
    	if (!fResult) 
    	{ 
    		printf("WriteFile failed with %d.\n", GetLastError()); 
    		return ; 
    	} 
    
    	printf("Slot written to successfully.\n"); 
    	CloseHandle(hFile); 
    	return ;
    }
    when i run both the program,the service is running succeed,but the client program is failed,and i retrieve the error code is ERROR_ACCESS_DENIED when execute the below code. 
    hFile = CreateFile(lpszSlotName, 
    		 GENERIC_READ | GENERIC_WRITE,		
    		 FILE_SHARE_READ | FILE_SHARE_WRITE ,
    		(LPSECURITY_ATTRIBUTES) NULL, 
    		OPEN_EXISTING,		
    		 FILE_FLAG_SEQUENTIAL_SCAN, 
    		(HANDLE) NULL); 
    anyone tell me how to solve this problem.I would very appreciate this if anyone can help me.

    Respectfully,

    KunBlack



    Thursday, May 22, 2014 3:04 AM