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; }
/* 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; }
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; }
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; }
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; }
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©FLAG_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); } }
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; }
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; }
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); }