Exemple #1
1
bool Channel::CreatePipe(const IPC::ChannelHandle &channel_handle) {
  assert(INVALID_HANDLE_VALUE == pipe_);
  std::wstring pipe_name;
  // If we already have a valid pipe for channel just copy it.
  if (channel_handle.pipe.handle) {
    assert(channel_handle.name.empty());
    pipe_name = L"Not Available";  // Just used for LOG
    // Check that the given pipe confirms to the specified mode.  We can
    // only check for PIPE_TYPE_MESSAGE & PIPE_SERVER_END flags since the
    // other flags (PIPE_TYPE_BYTE, and PIPE_CLIENT_END) are defined as 0.
    DWORD flags = 0;
    GetNamedPipeInfo(channel_handle.pipe.handle, &flags, NULL, NULL, NULL);
    assert(!(flags & PIPE_TYPE_MESSAGE));
    if (!DuplicateHandle(GetCurrentProcess(),
                         channel_handle.pipe.handle,
                         GetCurrentProcess(),
                         &pipe_,
                         0,
                         FALSE,
                         DUPLICATE_SAME_ACCESS)) {
      //LOG(WARNING) << "DuplicateHandle failed. Error :" << GetLastError();
      return false;
    }
  } else {
	assert(!channel_handle.pipe.handle);
	pipe_name = PipeName(channel_handle.name, &client_secret_);

	//Ïȳ¢ÊÔ´´½¨
    const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
                            FILE_FLAG_FIRST_PIPE_INSTANCE;
    validate_client_ = !!client_secret_;
    pipe_ = CreateNamedPipeW(pipe_name.c_str(),
                             open_mode,
                             PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
                             1,
                             kReadBufferSize,
                             kReadBufferSize,
                             5000,
                             NULL);
	if (pipe_ == INVALID_HANDLE_VALUE)
	{
		pipe_ = CreateFileW(pipe_name.c_str(),
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION |
			FILE_FLAG_OVERLAPPED,
			NULL);

		waiting_connect_ = false;
	}
  } 

  if (pipe_ == INVALID_HANDLE_VALUE) {
    // If this process is being closed, the pipe may be gone already.
    //LOG(WARNING) << "Unable to create pipe \"" << pipe_name <<
    //                "\" in " << (mode & MODE_SERVER_FLAG ? "server" : "client")
    //                << " mode. Error :" << GetLastError();
    return false;
  }

  // Create the Hello message to be sent when Connect is called
  Message* m = new Message(MSG_ROUTING_NONE,
                                    HELLO_MESSAGE_TYPE,
                                    IPC::Message::PRIORITY_NORMAL);
  m->AddRef();
  // Don't send the secret to the untrusted process, and don't send a secret
  // if the value is zero (for IPC backwards compatability).
  int32 secret = validate_client_ ? 0 : client_secret_;
  if (!m->WriteInt(GetCurrentProcessId()) ||
      (secret && !m->WriteUInt32(secret))) {
    CloseHandle(pipe_);
    pipe_ = INVALID_HANDLE_VALUE;
	m->Release();
    return false;
  }

  output_queue_.push(m);
  return true;
}
Exemple #2
0
/* Creates a pipe server. */
int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
  int i, errno, nameSize;
  uv_pipe_accept_t* req;

  if (handle->flags & UV_HANDLE_BOUND) {
    uv_set_sys_error(WSAEINVAL);
    return -1;
  }

  if (!name) {
    uv_set_sys_error(WSAEINVAL);
    return -1;
  }

  for (i = 0; i < COUNTOF(handle->accept_reqs); i++) {
    req = &handle->accept_reqs[i];
    uv_req_init((uv_req_t*) req);
    req->type = UV_ACCEPT;
    req->data = handle;
    req->pipeHandle = INVALID_HANDLE_VALUE;
    req->next_pending = NULL;
  }

  /* Convert name to UTF16. */
  nameSize = uv_utf8_to_utf16(name, NULL, 0) * sizeof(wchar_t);
  handle->name = (wchar_t*)malloc(nameSize);
  if (!handle->name) {
    uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
  }

  if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(wchar_t))) {
    uv_set_sys_error(GetLastError());
    return -1;
  }

  /*
   * Attempt to create the first pipe with FILE_FLAG_FIRST_PIPE_INSTANCE.
   * If this fails then there's already a pipe server for the given pipe name.
   */
  handle->accept_reqs[0].pipeHandle = CreateNamedPipeW(handle->name,
                                                       PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
                                                       PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
                                                       PIPE_UNLIMITED_INSTANCES,
                                                       65536,
                                                       65536,
                                                       0,
                                                       NULL);

  if (handle->accept_reqs[0].pipeHandle == INVALID_HANDLE_VALUE) {
    errno = GetLastError();
    if (errno == ERROR_ACCESS_DENIED) {
      uv_set_error(UV_EADDRINUSE, errno);
      handle->error = LOOP->last_error;
      handle->flags |= UV_HANDLE_BIND_ERROR;
    } else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) {
      uv_set_error(UV_EACCESS, errno);
    } else {
      uv_set_sys_error(errno);
    }
    goto error;
  }

  if (uv_set_pipe_handle(handle, handle->accept_reqs[0].pipeHandle)) {
    uv_set_sys_error(GetLastError());
    goto error;
  }

  handle->flags |= UV_HANDLE_PIPESERVER;
  handle->flags |= UV_HANDLE_BOUND;

  return 0;

error:
  if (handle->name) {
    free(handle->name);
    handle->name = NULL;
  }

  if (handle->accept_reqs[0].pipeHandle != INVALID_HANDLE_VALUE) {
    CloseHandle(handle->accept_reqs[0].pipeHandle);
    handle->accept_reqs[0].pipeHandle = INVALID_HANDLE_VALUE;
  }

  return -1;
}
Exemple #3
0
oslPipe SAL_CALL osl_acceptPipe(oslPipe pPipe)
{
	oslPipe  pAcceptedPipe = NULL;
	
	HANDLE		 Event;
    OVERLAPPED   os;

	OSL_ASSERT(pPipe);

	if (IS_NT)
	{
		DWORD nBytesTransfered;
		rtl_uString* path = NULL;
		rtl_uString* temp = NULL;

		OSL_ASSERT (pPipe->m_File != INVALID_HANDLE_VALUE);

		Event = pPipe->m_AcceptEvent;
		rtl_zeroMemory(&os, sizeof(OVERLAPPED));
		os.hEvent = pPipe->m_AcceptEvent;
		ResetEvent(pPipe->m_AcceptEvent);

		if ( !ConnectNamedPipe(pPipe->m_File, &os))
		{
			switch ( GetLastError() )
			{
			case ERROR_PIPE_CONNECTED:	// Client already connected to pipe
			case ERROR_NO_DATA:			// Client was connected but has already closed pipe end
										// should only appear in nonblocking mode but in fact does
										// in blocking asynchronous mode.
				break;
			case ERROR_PIPE_LISTENING:	// Only for nonblocking mode but see ERROR_NO_DATA
			case ERROR_IO_PENDING:		// This is normal if not client is connected yet
			case ERROR_MORE_DATA:		// Should not happen
				// blocking call to accept
				if( !GetOverlappedResult( pPipe->m_File, &os, &nBytesTransfered, TRUE ) )
				{
					// Possible error could be that between ConnectNamedPipe and GetOverlappedResult a connect
					// took place.

					switch ( GetLastError() )
					{
					case ERROR_PIPE_CONNECTED:	// Pipe was already connected
					case ERROR_NO_DATA:			// Pipe was connected but client has already closed -> ver fast client ;-)
						break;					// Everything's fine !!!
					default:
						// Something went wrong
						return 0;
					}
				}
				break;
			default:					// All other error say that somethings going wrong.
				return 0;
			}
		}

		
		pAcceptedPipe = __osl_createPipeImpl();
		OSL_ASSERT(pAcceptedPipe);

		osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
		rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
		pAcceptedPipe->m_File = pPipe->m_File;

		rtl_uString_newFromAscii(&temp, PIPESYSTEM);
		rtl_uString_newConcat(&path, temp, pPipe->m_Name);
		rtl_uString_release(temp);

		// prepare for next accept
		pPipe->m_File = 
        	CreateNamedPipeW(path->buffer, 
				PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
				PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
				PIPE_UNLIMITED_INSTANCES,
				4096, 4096,
				NMPWAIT_WAIT_FOREVER, 
				pAcceptedPipe->m_Security);
		rtl_uString_release( path );
	}
	else /* Win9x */
	{
		pAcceptedPipe = __osl_createPipeImpl();
		OSL_ASSERT(pAcceptedPipe);

		osl_incrementInterlockedCount(&(pAcceptedPipe->m_Reference));
		rtl_uString_assign(&pAcceptedPipe->m_Name, pPipe->m_Name);
		pAcceptedPipe->m_File = pPipe->m_File;

		pAcceptedPipe->m_File = AcceptSimplePipeConnection( pPipe->m_File );
	}

	return pAcceptedPipe;
}
Exemple #4
0
oslPipe SAL_CALL osl_createPipe(rtl_uString *strPipeName, oslPipeOptions Options, 
					   oslSecurity Security)
{
	rtl_uString* name = NULL;
	rtl_uString* path = NULL;
	rtl_uString* temp = NULL;
	oslPipe pPipe;

   	PSECURITY_ATTRIBUTES  pSecAttr = NULL;

	rtl_uString_newFromAscii(&path, PIPESYSTEM);
	rtl_uString_newFromAscii(&name, PIPEPREFIX);

	if ( /*IS_NT &&*/ Security)
	{
		rtl_uString *Ident = NULL;
		rtl_uString *Delim = NULL;

		OSL_VERIFY(osl_getUserIdent(Security, &Ident));
		rtl_uString_newFromAscii(&Delim, "_");

		rtl_uString_newConcat(&temp, name, Ident);
		rtl_uString_newConcat(&name, temp, Delim);

		rtl_uString_release(Ident);
		rtl_uString_release(Delim);
	}
	else
	{
		if (Options & osl_Pipe_CREATE)
		{
	    	PSECURITY_DESCRIPTOR pSecDesc;

	    	pSecDesc = (PSECURITY_DESCRIPTOR) rtl_allocateMemory(SECURITY_DESCRIPTOR_MIN_LENGTH);

	    	/* add a NULL disc. ACL to the security descriptor */
		    OSL_VERIFY(InitializeSecurityDescriptor(pSecDesc, SECURITY_DESCRIPTOR_REVISION));
	    	OSL_VERIFY(SetSecurityDescriptorDacl(pSecDesc, TRUE, (PACL) NULL, FALSE));

			pSecAttr = rtl_allocateMemory(sizeof(SECURITY_ATTRIBUTES));
	    	pSecAttr->nLength = sizeof(SECURITY_ATTRIBUTES);
	    	pSecAttr->lpSecurityDescriptor = pSecDesc;
	    	pSecAttr->bInheritHandle = TRUE;
		}
	}

	rtl_uString_assign(&temp, name);
	rtl_uString_newConcat(&name, temp, strPipeName);

	/* alloc memory */
	pPipe= __osl_createPipeImpl();
	osl_incrementInterlockedCount(&(pPipe->m_Reference));

	/* build system pipe name */
	rtl_uString_assign(&temp, path);
	rtl_uString_newConcat(&path, temp, name);
	rtl_uString_release(temp);
	temp = NULL;

	if (Options & osl_Pipe_CREATE)
	{
		SetLastError( ERROR_SUCCESS );

		if ( IS_NT )
			pPipe->m_NamedObject = CreateMutexW( NULL, FALSE, name->buffer );
		else
		{
			LPSTR	pszTempBuffer = NULL;
			int		nCharsNeeded;

			nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, NULL, 0, NULL, NULL );
			pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
			nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, name->buffer, name->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
			pszTempBuffer[nCharsNeeded-1] = 0;

			pPipe->m_NamedObject = CreateMutexA( NULL, FALSE, pszTempBuffer );
		}

		if ( pPipe->m_NamedObject != INVALID_HANDLE_VALUE && pPipe->m_NamedObject != NULL )
		{
			if ( GetLastError() != ERROR_ALREADY_EXISTS )
			{
				pPipe->m_Security = pSecAttr;
				rtl_uString_assign(&pPipe->m_Name, name);

				if (IS_NT)
				{
					/* try to open system pipe */
					pPipe->m_File = CreateNamedPipeW(
						path->buffer, 
						PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
						PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
						PIPE_UNLIMITED_INSTANCES,
						4096, 4096,
						NMPWAIT_WAIT_FOREVER, 
						pPipe->m_Security);

					if (pPipe->m_File != INVALID_HANDLE_VALUE)
					{
						rtl_uString_release( name );
						rtl_uString_release( path );

						return pPipe;
					}
				}
				else /* Win 9x */
				{
					LPSTR	pszTempBuffer = NULL;
					int		nCharsNeeded;

					nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
					pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
					nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
					pszTempBuffer[nCharsNeeded-1] = 0;

					pPipe->m_File = CreateSimplePipe( pszTempBuffer );

					if ( IsValidHandle(pPipe->m_File) )
					{
						rtl_uString_release( name );
						rtl_uString_release( path );

						return pPipe;
					}
				}
			}
			else
			{
				CloseHandle( pPipe->m_NamedObject );
				pPipe->m_NamedObject = INVALID_HANDLE_VALUE;
			}
		}
	}
	else
	{
		if (IS_NT)
		{
			BOOL	fPipeAvailable;

			do
			{
				/* free instance should be available first */
				fPipeAvailable = WaitNamedPipeW(path->buffer, NMPWAIT_WAIT_FOREVER);

				/* first try to open system pipe */
				if ( fPipeAvailable )
				{
					pPipe->m_File = CreateFileW(
							path->buffer,
							GENERIC_READ|GENERIC_WRITE, 
							FILE_SHARE_READ | FILE_SHARE_WRITE,
							NULL,
							OPEN_EXISTING, 
							FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
							NULL);

					if ( pPipe->m_File != INVALID_HANDLE_VALUE )
					{
						// We got it !
						rtl_uString_release( name );
						rtl_uString_release( path );

						return (pPipe);
					}
					else
					{
						// Pipe instance maybe catched by another client -> try again
					}
				}
			} while ( fPipeAvailable );
		}
		else /* Win 9x */
		{
			LPSTR	pszTempBuffer = NULL;
			int		nCharsNeeded;

			nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, NULL, 0, NULL, NULL );
			pszTempBuffer = alloca( nCharsNeeded * sizeof(CHAR) );
			nCharsNeeded = WideCharToMultiByte( CP_ACP, 0, path->buffer, path->length, pszTempBuffer, nCharsNeeded, NULL, NULL );
			pszTempBuffer[nCharsNeeded-1] = 0;

			pPipe->m_File = OpenSimplePipe( pszTempBuffer );

			if ( IsValidHandle(pPipe->m_File) )
			{
				// We got it !
				rtl_uString_release( name );
				rtl_uString_release( path );

				return (pPipe);
			}
		}
	}

	/* if we reach here something went wrong */
	__osl_destroyPipeImpl(pPipe);

	return NULL;
}
Exemple #5
0
DWORD service_start(struct service_entry *service, DWORD service_argc, LPCWSTR *service_argv)
{
    DWORD err;
    LPWSTR name;
    HANDLE process_handle = NULL;

    err = scmdatabase_lock_startup(service->db);
    if (err != ERROR_SUCCESS)
        return err;

    if (service->control_pipe != INVALID_HANDLE_VALUE)
    {
        scmdatabase_unlock_startup(service->db);
        return ERROR_SERVICE_ALREADY_RUNNING;
    }

    service->control_mutex = CreateMutexW(NULL, TRUE, NULL);

    if (!service->status_changed_event)
        service->status_changed_event = CreateEventW(NULL, FALSE, FALSE, NULL);
    if (!service->overlapped_event)
        service->overlapped_event = CreateEventW(NULL, TRUE, FALSE, NULL);

    name = service_get_pipe_name();
    service->control_pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
                            PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL );
    HeapFree(GetProcessHeap(), 0, name);
    if (service->control_pipe==INVALID_HANDLE_VALUE)
    {
        WINE_ERR("failed to create pipe for %s, error = %d\n",
                 wine_dbgstr_w(service->name), GetLastError());
        err = GetLastError();
    }
    else
    {
        err = service_start_process(service, &process_handle);
        if (err == ERROR_SUCCESS)
        {
            if (!service_send_start_message(service, process_handle, service_argv, service_argc))
                err = ERROR_SERVICE_REQUEST_TIMEOUT;
        }

        if (err == ERROR_SUCCESS)
            err = service_wait_for_startup(service, process_handle);

        if (process_handle)
            CloseHandle(process_handle);
    }

    if (err == ERROR_SUCCESS)
        ReleaseMutex(service->control_mutex);
    else
    {
        CloseHandle(service->overlapped_event);
        service->overlapped_event = NULL;
        CloseHandle(service->status_changed_event);
        service->status_changed_event = NULL;
        CloseHandle(service->control_mutex);
        service->control_mutex = NULL;
        if (service->control_pipe != INVALID_HANDLE_VALUE)
            CloseHandle(service->control_pipe);
        service->control_pipe = INVALID_HANDLE_VALUE;

        service->status.dwProcessId = 0;
        service_lock_exclusive(service);
        service->status.dwCurrentState = SERVICE_STOPPED;
        service_unlock(service);
    }
    scmdatabase_unlock_startup(service->db);

    WINE_TRACE("returning %d\n", err);

    return err;
}
Exemple #6
0
DWORD WINAPI server_thread(LPVOID parameter)
{
	while (1)
	{
	HANDLE hPipe = CreateNamedPipeW( 
		(wchar_t*)parameter,             // pipe name 
		PIPE_ACCESS_DUPLEX,      // read/write access 
		PIPE_TYPE_MESSAGE |		  // message type pipe 
		PIPE_READMODE_MESSAGE |   // message-read mode 
		PIPE_WAIT,                // blocking mode 
		PIPE_UNLIMITED_INSTANCES, // max. instances  
		500, // output buffer size 
		500, // input buffer size 
		0,                        // client time-out 
		NULL);                    // default security attribute 

	if (hPipe == INVALID_HANDLE_VALUE)
		break; // wtf ... create pipe fail?

	printf("pipe created, waitting for connection.....");
	fflush(stdout);
	if (!ConnectNamedPipe(hPipe, NULL) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED))
		ExitProcess(-2);

	printf("connected\n");



	// read command and execute
	char *data = NULL;
	while (1)
	{
		// free
		if (data) {delete data; data = NULL;}

		// read command header
		thumbnail_cmd cmd;
		DWORD cbBytesRead = 0;
		BOOL fSuccess = ReadFile( hPipe, &cmd, sizeof(thumbnail_cmd), &cbBytesRead, NULL);
		if (!fSuccess || cbBytesRead == 0)
			break;

		// read command data if there is
		if (cmd.data_size>0)
		{
			data = new char[cmd.data_size];
			fSuccess = ReadFile( hPipe, data, cmd.data_size, &cbBytesRead, NULL);
			if (!fSuccess || cbBytesRead == 0)
				break;
		}

		// process command
		void * odata = NULL;
		thumbnail_cmd ocmd;
		if (process_command(cmd, data, &ocmd, &odata)<0)
			continue;

		// send result back
		fSuccess = WriteFile(hPipe, &ocmd, sizeof(thumbnail_cmd), &cbBytesRead, NULL);
		if (!fSuccess || cbBytesRead == 0)
			break;

		if (ocmd.data_size>0 && odata)
		{
			fSuccess = WriteFile( hPipe, odata, ocmd.data_size, &cbBytesRead, NULL);
			delete odata;
			if (!fSuccess || cbBytesRead == 0)
				break;
		}
	}

	printf("shutting down...");
	DisconnectNamedPipe(hPipe); 
	CloseHandle(hPipe);
	printf("OK\n");
	}
	return 0;
}
static DWORD WINAPI ServiceStartThread(LPVOID lpvThreadParm)
{
  HANDLE hPipe=INVALID_HANDLE_VALUE;
  HANDLE hEvents[2]={NULL,NULL};
  OVERLAPPED os;
  SECURITY_ATTRIBUTES sa;
  DWORD transferred;
  DWORD dCode;
  DWORD dFlags;
  DWORD dCount;
  struct FileRec *files=NULL;
  struct FileRecs *sfiles=NULL;
  void *add_data=NULL;
  struct SmallInfoRec *alldata=NULL;
  struct StrRec *rec=NULL;
  HANDLE hThread;
  DWORD ThreadID;
  BOOL connected=FALSE;
  DWORD index=(DWORD)(DWORD_PTR)lpvThreadParm;

  // Service initialization
  hServerStopEvent[index]=CreateEventW(NULL,TRUE,FALSE,NULL);
  if(!hServerStopEvent[index])
    goto cleanup;
  hEvents[0]=hServerStopEvent[index];
  // create the event object object use in overlapped i/o
  hEvents[1]=CreateEventW(NULL,TRUE,FALSE,NULL);
  if(!hEvents[1])
    goto cleanup;
  sa.nLength=sizeof(sa);
  sa.lpSecurityDescriptor=pipe_sd;
  sa.bInheritHandle=FALSE;
  // open our named pipe...
  hPipe=CreateNamedPipeW(PIPE_NAMEW,FILE_FLAG_OVERLAPPED|PIPE_ACCESS_DUPLEX,PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT,GetThreadCount(),0,0,1000,&sa);
  if(hPipe==INVALID_HANDLE_VALUE)
    goto cleanup;
  // End of initialization
  if(!index) ResetStartEvent();
  // Service is now running, perform work until shutdown
  for(;;connected?(DisconnectNamedPipe(hPipe),connected=FALSE):0)
  {
    //check stack
    if(!HeapValidate(GetProcessHeap(),0,NULL)) { LogSys(L"HeapValidate",NULL,NULL); break; }
    //clean up
    if(files) { free(files); files=NULL; }
    if(sfiles) { free(sfiles); sfiles=NULL; }
    if(add_data) { free(add_data); add_data=NULL; }
    if(rec) { free(rec); rec=NULL; }
    if(alldata) { free(alldata); alldata=NULL; }
    TRANSFER_INIT
    if(!ConnectNamedPipe(hPipe,&os))
    {
      DWORD Error=GetLastError();
      if(Error==ERROR_IO_PENDING)
      {
        if(WaitForMultipleObjects(2,hEvents,FALSE,INFINITE)!=WAIT_OBJECT_0+1)
          break;
        if(!GetOverlappedResult(hPipe,&os,&transferred,FALSE)) Error=GetLastError();
        else Error=ERROR_SUCCESS;
      }
      if(Error!=ERROR_PIPE_CONNECTED&&Error!=ERROR_SUCCESS)
      {
        if(WaitForSingleObject(hEvents[0],200)==WAIT_OBJECT_0) break;
        continue;
      }
    }
    connected=TRUE;
    // grab whatever's coming through the pipe...
    TRANSFER_DATA(ReadFile,&dCode,sizeof(dCode))
    TRANSFER_DATA(ReadFile,&dFlags,sizeof(dFlags))
    //check network
    if(dCode==OPERATION_COPY)
    {
      if(dFlags&COPYFLAG_ADDITIONAL_DATA)
      {
        DWORD dAddSize;
        TRANSFER_DATA(ReadFile,&dAddSize,sizeof(dAddSize))
        add_data=malloc(dAddSize);
        if(add_data)
        {
          TRANSFER_DATA(ReadFile,add_data,dAddSize)
        }
        else continue;
      }
      TRANSFER_DATA(ReadFile,&dCount,sizeof(dCount))
      if(dCount>2)
      {
        files=(struct FileRec *)malloc(sizeof(struct FileRec)*dCount);
        if(files)
        {
          TRANSFER_DATA(ReadFile,files,sizeof(struct FileRec)*dCount)
          sfiles=(struct FileRecs *)malloc(sizeof(struct FileRecs));
          if(sfiles)
          {
            HANDLE wait_event=CreateEventW(NULL,TRUE,FALSE,NULL);
            sfiles->event=wait_event;
            sfiles->flags=dFlags;
            sfiles->count=dCount;
            sfiles->files=files;
            sfiles->add=add_data;
            hThread=CreateThread(NULL,0,CopyThread,sfiles,CREATE_SUSPENDED,&ThreadID);
            if(hThread)
            {
              SetThreadPriority(hThread,GetWorkPriority());
              if(IsSystem) PipeToThread(hPipe,hThread);
              ResumeThread(hThread);
              if(wait_event)
              {
                struct InfoRec RetData;
                WaitForSingleObject(wait_event,INFINITE);
                CloseHandle(wait_event);
                RetData.info.ThreadId=ThreadID;
                GetInfo(ThreadID,&RetData);
                TRANSFER_DATA(WriteFile,&RetData.info,sizeof(RetData.info))
              }
              CloseHandle(hThread);
              files=NULL;
              sfiles=NULL;
              add_data=NULL;
            } else CloseHandle(wait_event);
          }
        }
Exemple #8
0
CPipe::CPipe(char *szName, DWORD dWait){
	int	iTemp;
	int	iFlag = 1;
	WCHAR	wbuffer[MAX_PATH+1];
	dTHX;
	
	hPipe = 0;                 
	dBufferSize = BUFFER_SIZE;
	dBytes = 0;
			              	
	char szPipeName[PIPE_NAME_SIZE + 1];				
	dwOpenMode = PIPE_ACCESS_DUPLEX;		
	dwPipeMode = 	PIPE_TYPE_BYTE	 |      
					PIPE_READMODE_BYTE	 |  
					PIPE_WAIT;				
	nMaxInstances =	PIPE_UNLIMITED_INSTANCES;
	nOutBufferSize = dBufferSize;			
	nInBufferSize  = dBufferSize;
	nDefaultTimeOut = PIPE_TIMEOUT;			
	lpSecurityAttributes= NULL; 
	iError = 0;
	strcpy((char *)szError, "");
	
	cBuffer = new char [dBufferSize];
	if (! cBuffer){
		dBufferSize = 0;
	}

	memset((void *)szError, 0, ERROR_TEXT_SIZE);
	memset((void *)szPipeName, 0, PIPE_NAME_SIZE + 1);
	if (strncmp((char *)szName, "\\\\", 2) == 0){
		iPipeType = CLIENT;
		iTemp = 0;
	}else{
		iPipeType = SERVER;
		strcpy(szPipeName, PIPE_NAME_PREFIX);
		iTemp = strlen(PIPE_NAME_PREFIX);
	}
	strncat(szPipeName, szName, PIPE_NAME_SIZE - iTemp);
	if (USING_WIDE()) {
	    A2WHELPER(szPipeName, wbuffer, sizeof(wbuffer));
	}
	if(iPipeType == SERVER){
	    if (USING_WIDE()) {
		hPipe = CreateNamedPipeW(wbuffer,
					dwOpenMode, 
					dwPipeMode, 
					nMaxInstances, 
					nOutBufferSize, 
					nInBufferSize, 
					nDefaultTimeOut,
					lpSecurityAttributes);
	    }
	    else {
		hPipe = CreateNamedPipeA(szPipeName,
					dwOpenMode, 
					dwPipeMode, 
					nMaxInstances, 
					nOutBufferSize, 
					nInBufferSize, 
					nDefaultTimeOut,
					lpSecurityAttributes);
	    }
	}else{
		while(iFlag){
		    if (USING_WIDE()) {
			hPipe = CreateFileW(wbuffer,
					    GENERIC_READ | GENERIC_WRITE, 
					    FILE_SHARE_READ	| FILE_SHARE_WRITE,
					    NULL,
					    OPEN_EXISTING,
					    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
					    NULL);
		    }
		    else {
			hPipe = CreateFileA(szPipeName,
					    GENERIC_READ | GENERIC_WRITE, 
					    FILE_SHARE_READ	| FILE_SHARE_WRITE,
					    NULL,
					    OPEN_EXISTING,
					    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
					    NULL);
		    }

		    if (GetLastError() == ERROR_PIPE_BUSY){
			if (USING_WIDE())
			    iFlag = WaitNamedPipeW(wbuffer, dWait);
			else
			    iFlag = WaitNamedPipeA(szPipeName, dWait);
		    }else{
			    iFlag = 0;
		    }
		}
	}
	if (cBuffer == 0){
		iError = 998;
		strcpy((char *)szError, "Could not allocate a buffer for the pipe connection");
	}
	if (hPipe == INVALID_HANDLE_VALUE){
		iError = 999;
		strcpy((char *)szError, "Could not connect");
		delete this;
	}
}									  
BOOL
IpcCreateNamedPipe(IN LPCWSTR ObjectName,
                   IN BOOL FirstInstance,
                   IN DWORD OutBufferSize,
                   IN DWORD InBufferSize,
                   IN DWORD DefaultTimeout,
                   OUT PNAMED_PIPE NamedPipe)
{
    DWORD OpenMode;
    DWORD PipeMode;
    PSID sid;
    SECURITY_DESCRIPTOR sd = { 0 };
    SECURITY_ATTRIBUTES sa = { 0 };

    IpcMakePipeName(NamedPipe->ObjectName,
                    0x100,
                    ObjectName);

    NamedPipe->EventHandle = CreateEventW(NULL,
                                          TRUE,
                                          TRUE,
                                          NULL);

    if (!NamedPipe->EventHandle)
    {
        return FALSE;
    }

    OpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED;
    OpenMode |= FirstInstance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0;

    PipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;
    PipeMode |= PIPE_WAIT;
    PipeMode |= PIPE_REJECT_REMOTE_CLIENTS;

    if (!ScCreateSecurityAttributes(&sa, &sd, &sid))
    {
        NamedPipe->ObjectHandle = 0;
        CloseHandle(NamedPipe->EventHandle);
        NamedPipe->EventHandle = 0;
        return FALSE;
    }

    NamedPipe->ObjectHandle = CreateNamedPipeW(NamedPipe->ObjectName,
                                               OpenMode,
                                               PipeMode,
                                               PIPE_UNLIMITED_INSTANCES,
                                               OutBufferSize,
                                               InBufferSize,
                                               DefaultTimeout,
                                               &sa);

    ScDestroySecurityAttributes(sid);

    if (NamedPipe->ObjectHandle == INVALID_HANDLE_VALUE ||
        GetLastError() == ERROR_ACCESS_DENIED)
    {
        NamedPipe->ObjectHandle = 0;
        CloseHandle(NamedPipe->EventHandle);
        NamedPipe->EventHandle = 0;
        return FALSE;
    }

    return TRUE;
}
Exemple #10
0
JNIEXPORT jint JNICALL Java_org_eclipse_cdt_utils_spawner_Spawner_exec0
  (JNIEnv * env, jobject process, jobjectArray cmdarray, jobjectArray envp, jstring dir, jintArray channels) 
{
	HANDLE stdHandles[3];
    PROCESS_INFORMATION pi = {0}, *piCopy;
    STARTUPINFOW si;
	DWORD flags = 0;
    const wchar_t  * cwd = NULL;
	LPVOID envBlk = NULL;
    int ret = 0;
    int nCmdLineLength= 0;
	wchar_t * szCmdLine= 0;
	int nBlkSize = MAX_ENV_SIZE; 
	wchar_t * szEnvBlock = NULL;
	jsize nCmdTokens = 0;
	jsize nEnvVars = 0;
	int i;
	DWORD pid = GetCurrentProcessId();
	int nPos;
	pProcInfo_t pCurProcInfo;

	// This needs to be big enough to contain the name of the event used when calling CreateEventW bellow. 
	// It is made of a prefix (7 characters max) plus the value of a pointer that gets output in characters.
	// This will be bigger in the case of 64 bit.
	static const int MAX_EVENT_NAME_LENGTH = 50;
	wchar_t eventBreakName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventWaitName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventTerminateName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventKillName[MAX_EVENT_NAME_LENGTH];
	wchar_t eventCtrlcName[MAX_EVENT_NAME_LENGTH];
#ifdef DEBUG_MONITOR
	wchar_t buffer[4000];
#endif
	int nLocalCounter;
	wchar_t inPipeName[PIPE_NAME_LENGTH];
	wchar_t outPipeName[PIPE_NAME_LENGTH];
	wchar_t errPipeName[PIPE_NAME_LENGTH];

    nCmdLineLength= MAX_CMD_SIZE;
    szCmdLine= (wchar_t *)malloc(nCmdLineLength * sizeof(wchar_t));
    szCmdLine[0]= _T('\0');
	if((HIBYTE(LOWORD(GetVersion()))) & 0x80)
		{
		ThrowByName(env, "java/io/IOException", "Does not support Windows 3.1/95/98/Me");
		return 0;
		}

    if (cmdarray == 0) 
		{
		ThrowByName(env, "java/lang/NullPointerException", "No command line specified");
		return 0;
		}

   ZeroMemory(stdHandles, sizeof(stdHandles));

	// Create pipe names
   EnterCriticalSection(&cs);
   swprintf(inPipeName,  L"\\\\.\\pipe\\stdin%08i%010i",  pid, nCounter); 
   swprintf(outPipeName, L"\\\\.\\pipe\\stdout%08i%010i", pid, nCounter); 
   swprintf(errPipeName, L"\\\\.\\pipe\\stderr%08i%010i", pid, nCounter); 
   nLocalCounter = nCounter;
   ++nCounter;
   LeaveCriticalSection(&cs);

   if ((INVALID_HANDLE_VALUE == (stdHandles[0] = CreateNamedPipeW(inPipeName, PIPE_ACCESS_OUTBOUND,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
	   (INVALID_HANDLE_VALUE == (stdHandles[1] = CreateNamedPipeW(outPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))) ||
	   (INVALID_HANDLE_VALUE == (stdHandles[2] = CreateNamedPipeW(errPipeName, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
									  PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
									  PIPE_UNLIMITED_INSTANCES, PIPE_SIZE, PIPE_SIZE, PIPE_TIMEOUT, NULL))))		{
		CloseHandle(stdHandles[0]);
        CloseHandle(stdHandles[1]);
        CloseHandle(stdHandles[2]);
		ThrowByName(env, "java/io/IOException", "CreatePipe");
		return 0;
   } 

#ifdef DEBUG_MONITOR
	swprintf(buffer, _T("Opened pipes: %s, %s, %s\n"), inPipeName, outPipeName, errPipeName);
	OutputDebugStringW(buffer);
#endif
	

	nCmdTokens = env->GetArrayLength(cmdarray);
    nEnvVars   = env->GetArrayLength(envp);

	pCurProcInfo = createProcInfo();

	if(NULL == pCurProcInfo)
		{
		ThrowByName(env, "java/io/IOException", "Too many processes");
		return 0;
		}

	// Construct starter's command line
	swprintf(eventBreakName, L"SABreak%04x%08x", pid, nLocalCounter);
	swprintf(eventWaitName, L"SAWait%004x%08x", pid, nLocalCounter);
	swprintf(eventTerminateName, L"SATerm%004x%08x", pid, nLocalCounter);
	swprintf(eventKillName, L"SAKill%04x%08x", pid, nLocalCounter);
	swprintf(eventCtrlcName, L"SACtrlc%04x%08x", pid, nLocalCounter);

	pCurProcInfo->eventBreak     = CreateEventW(NULL, FALSE, FALSE, eventBreakName);
    if(NULL == pCurProcInfo->eventBreak || GetLastError() == ERROR_ALREADY_EXISTS)
        {
        ThrowByName(env, "java/io/IOException", "Cannot create event");
        return 0;
        }
	pCurProcInfo->eventWait      = CreateEventW(NULL, TRUE,  FALSE, eventWaitName);
	pCurProcInfo->eventTerminate = CreateEventW(NULL, FALSE, FALSE, eventTerminateName);
	pCurProcInfo->eventKill      = CreateEventW(NULL, FALSE, FALSE, eventKillName);
	pCurProcInfo->eventCtrlc     = CreateEventW(NULL, FALSE, FALSE, eventCtrlcName);

	swprintf(szCmdLine, L"\"%sstarter.exe\" %i %i %s %s %s %s %s ", path, pid, nLocalCounter, eventBreakName, eventWaitName, eventTerminateName, eventKillName, eventCtrlcName);
	nPos = wcslen(szCmdLine);

	// Prepare command line
	for(i = 0; i < nCmdTokens; ++i) 
    	{
		jstring item = (jstring)env->GetObjectArrayElement(cmdarray, i);
		jsize    len = env->GetStringLength(item);
		int nCpyLen;
		const wchar_t *  str = (const wchar_t *)env->GetStringChars(item, 0);	
		if(NULL != str) 
			{
			int requiredSize= nPos+len+2;
			if (requiredSize > 32*1024) {
				ThrowByName(env, "java/io/IOException", "Command line too long");
				return 0;
			}				
			ensureSize(&szCmdLine, &nCmdLineLength, requiredSize);
			if (NULL == szCmdLine) {
				ThrowByName(env, "java/io/IOException", "Not enough memory");
				return 0;
			}
			    
			if(0 > (nCpyLen = copyTo(szCmdLine + nPos, str, len, nCmdLineLength - nPos)))
                {
				ThrowByName(env, "java/io/IOException", "Command line too long");
				return 0;
			}
			nPos += nCpyLen;
			szCmdLine[nPos] = _T(' ');
			++nPos;
			env->ReleaseStringChars(item, (const jchar *)str);
		}
	}
	szCmdLine[nPos] = _T('\0');

#ifdef DEBUG_MONITOR
	swprintf(buffer, _T("There are %i environment variables \n"), nEnvVars);
	OutputDebugStringW(buffer);
#endif
	// Prepare environment block
    if (nEnvVars > 0) 
		{
		nPos = 0;
		szEnvBlock = (wchar_t *)malloc(nBlkSize * sizeof(wchar_t));
		for(i = 0; i < nEnvVars; ++i) 
			{
			jstring item = (jstring)env->GetObjectArrayElement(envp, i);
			jsize    len = env->GetStringLength(item);
			const wchar_t *  str = (const wchar_t *)env->GetStringChars(item, 0);	
			if(NULL != str)
				{
				while((nBlkSize - nPos) <= (len + 2)) // +2 for two '\0'
					{
					nBlkSize += MAX_ENV_SIZE;
					szEnvBlock = (wchar_t *)realloc(szEnvBlock, nBlkSize * sizeof(wchar_t));
					if(NULL == szEnvBlock) 
						{
						ThrowByName(env, "java/io/IOException", "Not enough memory");
						return 0;
						}
#ifdef DEBUG_MONITOR
					swprintf(buffer, _T("Realloc environment block; new length is  %i \n"), nBlkSize);
					OutputDebugStringW(buffer);
#endif

					}
#ifdef DEBUG_MONITOR
				swprintf(buffer, _T("%s\n"), str);
				OutputDebugStringW(buffer);
#endif
				wcsncpy(szEnvBlock + nPos, str, len);
				nPos += len;
				szEnvBlock[nPos] = _T('\0');
				++nPos;
				env->ReleaseStringChars(item, (const jchar *)str);
				}
			}
			szEnvBlock[nPos] = _T('\0');
		}



    if (dir != 0) 
		{ 
		const wchar_t * str = (const wchar_t *)env->GetStringChars(dir, 0);
		if(NULL != str)
			{
			cwd = wcsdup(str);
			env->ReleaseStringChars(dir, (const jchar *)str);
			}
		}


    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags |= STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE;  // Processes in the Process Group are hidden



    SetHandleInformation(stdHandles[0], HANDLE_FLAG_INHERIT, FALSE);
    SetHandleInformation(stdHandles[1],  HANDLE_FLAG_INHERIT, FALSE);
    SetHandleInformation(stdHandles[2],  HANDLE_FLAG_INHERIT, FALSE);

	flags = CREATE_NEW_CONSOLE;
	flags |= CREATE_NO_WINDOW;
	flags |= CREATE_UNICODE_ENVIRONMENT;

#ifdef DEBUG_MONITOR
	OutputDebugStringW(szCmdLine);
#endif
	// launches starter; we need it to create another console group to correctly process 
	// emulation of SYSint signal (Ctrl-C)
    ret = CreateProcessW(0,                /* executable name */
                        szCmdLine,        /* command line */
                        0,                /* process security attribute */
                        0,                /* thread security attribute */
                        FALSE,            /* inherits system handles */
                        flags,            /* normal attached process */
                        szEnvBlock,		  /* environment block */
                        cwd,              /* change to the new current directory */
                        &si,              /* (in)  startup information */
                        &pi);             /* (out) process information */

	if(NULL != cwd)
		free((void *)cwd);

	if(NULL != szEnvBlock)
		free(szEnvBlock);

    if(NULL != szCmdLine) 
        free(szCmdLine);
      
    if (!ret) // Launching error
		{
		char * lpMsgBuf;	    
		CloseHandle(stdHandles[0]);
		CloseHandle(stdHandles[1]);
		CloseHandle(stdHandles[2]); 
		FormatMessageA( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			GetLastError(),
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(char *)&lpMsgBuf,
			0,
			NULL 
		);
		ThrowByName(env, "java/io/IOException", lpMsgBuf);
		// Free the buffer.
		LocalFree( lpMsgBuf );
		cleanUpProcBlock(pCurProcInfo);
		ret = -1;
		}
    else
		{
    	int file_handles[3];
		HANDLE h[2];
		int what;

		EnterCriticalSection(&cs);

		pCurProcInfo -> pid = pi.dwProcessId;
        h[0] = pCurProcInfo -> eventWait;
		h[1] = pi.hProcess;
		
		what = WaitForMultipleObjects(2, h, FALSE, INFINITE); 
		if(what != WAIT_OBJECT_0) // CreateProcess failed
			{
#ifdef DEBUG_MONITOR
			swprintf(buffer, _T("Process %i failed\n"), pi.dwProcessId);
			OutputDebugStringW(buffer);
#endif
			cleanUpProcBlock(pCurProcInfo);
			ThrowByName(env, "java/io/IOException", "Launching failed");
#ifdef DEBUG_MONITOR
			OutputDebugStringW(_T("Process failed\n"));
#endif
			}
		else 
			{
			ret = (long)(pCurProcInfo -> uid);
			
			// Prepare stream handlers to return to java program
			file_handles[0] = (int)stdHandles[0];
			file_handles[1] = (int)stdHandles[1];
			file_handles[2] = (int)stdHandles[2];
			env->SetIntArrayRegion(channels, 0, 3, (jint *)file_handles);

			// do the cleanup so launch the according thread
			// create a copy of the PROCESS_INFORMATION as this might get destroyed
			piCopy = (PROCESS_INFORMATION *)malloc(sizeof(PROCESS_INFORMATION));
			memcpy(piCopy, &pi, sizeof(PROCESS_INFORMATION));
			_beginthread(waitProcTermination, 0, (void *)piCopy);

#ifdef DEBUG_MONITOR
			OutputDebugStringW(_T("Process started\n"));
#endif
			}				
		LeaveCriticalSection(&cs);

		}

	CloseHandle(pi.hThread);

    return ret;

}
Exemple #11
0
static void
_RunRemoteTest(const char* szTestName)
{
    BOOL bSuccessful = FALSE;
    char szBuffer[1024];
    DWORD cbRead;
    DWORD cbWritten;
    HANDLE hCommandPipe = INVALID_HANDLE_VALUE;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    HANDLE hOutputPipe = INVALID_HANDLE_VALUE;
    PWSTR p;
    SC_HANDLE hSC = NULL;
    SC_HANDLE hService = NULL;
    SERVICE_STATUS ServiceStatus;
    WCHAR wszFilePath[MAX_PATH + 20];
    WIN32_FIND_DATAW fd;

    // Do a dummy EnumPrintersW call.
    // This guarantees that the Spooler Service has actually loaded localspl.dll, which is a requirement for our injected DLL to work properly.
    EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_NAME, NULL, 1, NULL, 0, &cbRead, &cbWritten);

    // Get the full path to our EXE file.
    if (!GetModuleFileNameW(NULL, wszFilePath, MAX_PATH))
    {
        skip("GetModuleFileNameW failed with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Replace the extension.
    p = wcsrchr(wszFilePath, L'.');
    if (!p)
    {
        skip("File path has no file extension: %S\n", wszFilePath);
        goto Cleanup;
    }

    wcscpy(p, L".dll");

    // Check if the corresponding DLL file exists.
    hFind = FindFirstFileW(wszFilePath, &fd);
    if (hFind == INVALID_HANDLE_VALUE)
    {
        skip("My DLL file \"%S\" does not exist!\n", wszFilePath);
        goto Cleanup;
    }

    // Change the extension back to .exe and add the parameters.
    wcscpy(p, L".exe service dummy");

    // Open a handle to the service manager.
    hSC = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (!hSC)
    {
        skip("OpenSCManagerW failed with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Ensure that the spooler service is running.
    hService = OpenServiceW(hSC, L"spooler", SERVICE_QUERY_STATUS);
    if (!hService)
    {
        skip("OpenServiceW failed for the spooler service with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    if (!QueryServiceStatus(hService, &ServiceStatus))
    {
        skip("QueryServiceStatus failed for the spooler service with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    if (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
    {
        skip("Spooler Service is not running!\n");
        goto Cleanup;
    }

    CloseServiceHandle(hService);

    // Try to open the service if we've created it in a previous run.
    hService = OpenServiceW(hSC, SERVICE_NAME, SERVICE_ALL_ACCESS);
    if (!hService)
    {
        if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
        {
            // Create the service.
            hService = CreateServiceW(hSC, SERVICE_NAME, NULL, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, wszFilePath, NULL, NULL, NULL, NULL, NULL);
            if (!hService)
            {
                skip("CreateServiceW failed with error %lu!\n", GetLastError());
                goto Cleanup;
            }
        }
        else
        {
            skip("OpenServiceW failed with error %lu!\n", GetLastError());
            goto Cleanup;
        }
    }

    // Create pipes for the communication with the injected DLL.
    hCommandPipe = CreateNamedPipeW(COMMAND_PIPE_NAME, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, 1, 1024, 1024, 10000, NULL);
    if (hCommandPipe == INVALID_HANDLE_VALUE)
    {
        skip("CreateNamedPipeW failed for the command pipe with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    hOutputPipe = CreateNamedPipeW(OUTPUT_PIPE_NAME, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 1024, 1024, 10000, NULL);
    if (hOutputPipe == INVALID_HANDLE_VALUE)
    {
        skip("CreateNamedPipeW failed for the output pipe with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Start the service with "service" and a dummy parameter (to distinguish it from a call by rosautotest to localspl_apitest:service)
    if (!StartServiceW(hService, 0, NULL))
    {
        skip("StartServiceW failed with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Wait till it has injected the DLL and the DLL expects its test name.
    if (!ConnectNamedPipe(hCommandPipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED)
    {
        skip("ConnectNamedPipe failed for the command pipe with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Send the test name.
    if (!WriteFile(hCommandPipe, szTestName, strlen(szTestName) + sizeof(char), &cbWritten, NULL))
    {
        skip("WriteFile failed with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Now wait for the DLL to connect to the output pipe.
    if (!ConnectNamedPipe(hOutputPipe, NULL))
    {
        skip("ConnectNamedPipe failed for the output pipe with error %lu!\n", GetLastError());
        goto Cleanup;
    }

    // Get all testing messages from the pipe and output them on stdout.
    while (ReadFile(hOutputPipe, szBuffer, sizeof(szBuffer), &cbRead, NULL) && cbRead)
        fwrite(szBuffer, sizeof(char), cbRead, stdout);

    bSuccessful = TRUE;

Cleanup:
    if (hCommandPipe != INVALID_HANDLE_VALUE)
        CloseHandle(hCommandPipe);

    if (hOutputPipe != INVALID_HANDLE_VALUE)
        CloseHandle(hOutputPipe);

    if (hFind != INVALID_HANDLE_VALUE)
        FindClose(hFind);

    if (hService)
        CloseServiceHandle(hService);

    if (hSC)
        CloseServiceHandle(hSC);

    // If we successfully received test output through the named pipe, we have also output a summary line already.
    // Prevent the testing framework from outputting another "0 tests executed" line in this case.
    if (bSuccessful)
        ExitProcess(0);
}