/* Construct the pipe name */ static rtl_uString * get_pipe_path( rtl_uString *pAppPath ) { rtl_uString *pPath = NULL, *pTmp = NULL, *pUserInstallation = NULL; rtl_uString *pResult = NULL, *pBasePath = NULL, *pAbsUserInstallation = NULL; rtlBootstrapHandle handle; rtl_uString *pMd5hash = NULL; sal_Unicode pUnicode[RTL_USTR_MAX_VALUEOFINT32]; /* setup bootstrap filename */ rtl_uString_newFromAscii( &pPath, "file://" ); rtl_uString_newConcat( &pPath, pPath, pAppPath ); rtl_uString_newConcat( &pPath, pPath, pTmp ); rtl_uString_newFromAscii( &pTmp, SAL_CONFIGFILE( "bootstrap" ) ); rtl_uString_newConcat( &pPath, pPath, pTmp ); /* read userinstallation value */ handle = rtl_bootstrap_args_open( pPath ); rtl_uString_newFromAscii( &pTmp, "UserInstallation" ); rtl_bootstrap_get_from_handle( handle, pTmp, &pUserInstallation, NULL ); rtl_bootstrap_args_close( handle ); /* turn it into an absolute path - unwinding symlinks etc. */ if ( osl_getProcessWorkingDir (&pBasePath) || osl_getAbsoluteFileURL( pBasePath, pUserInstallation, &pAbsUserInstallation ) ) rtl_uString_newFromString (&pAbsUserInstallation, pUserInstallation); /* create the pipe name */ pMd5hash = get_md5hash( pAbsUserInstallation ); if ( !pMd5hash ) rtl_uString_new( &pMd5hash ); if ( access( PIPEDEFAULTPATH, W_OK ) == 0 ) rtl_uString_newFromAscii( &pResult, PIPEDEFAULTPATH ); else if ( access( PIPEALTERNATEPATH, W_OK ) == 0 ) rtl_uString_newFromAscii( &pResult, PIPEALTERNATEPATH ); else { fprintf( stderr, "ERROR: no valid pipe path found.\n" ); exit( 1 ); } rtl_uString_newFromAscii( &pTmp, "/OSL_PIPE_" ); rtl_uString_newConcat( &pResult, pResult, pTmp ); rtl_ustr_valueOfInt32( pUnicode, (int)getuid(), 10 ); rtl_uString_newFromStr( &pTmp, pUnicode ); rtl_uString_newConcat( &pResult, pResult, pTmp ); rtl_uString_newFromAscii( &pTmp, "_SingleOfficeIPC_" ); rtl_uString_newConcat( &pResult, pResult, pTmp ); rtl_uString_newConcat( &pResult, pResult, pMd5hash ); /* cleanup */ rtl_uString_release( pMd5hash ); rtl_uString_release( pPath ); rtl_uString_release( pTmp ); if ( pBasePath ) { rtl_uString_release( pBasePath ); } rtl_uString_release( pUserInstallation ); rtl_uString_release( pAbsUserInstallation ); return pResult; }
/* Send args to the OOo instance (using the 'fd' file descriptor) */ static sal_Bool send_args( int fd, rtl_uString *pCwdPath ) { rtl_uString *pBuffer = NULL, *pTmp = NULL; sal_Int32 nCapacity = 1000; rtl_String *pOut = NULL; sal_Bool bResult; size_t nLen; rtl_uString *pEscapedCwdPath = escape_path( pCwdPath ); sal_uInt32 nArg = 0; sal_uInt32 nArgCount = rtl_getAppCommandArgCount(); rtl_uString_new_WithLength( &pBuffer, nCapacity ); rtl_uString_new( &pTmp ); rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), RTL_CONSTASCII_STRINGPARAM( "InternalIPC::Arguments" ) ); if ( rtl_uString_getLength( pEscapedCwdPath ) ) { rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), RTL_CONSTASCII_STRINGPARAM( "1" ) ); rtl_uStringbuffer_insert( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), rtl_uString_getStr( pEscapedCwdPath ), rtl_uString_getLength( pEscapedCwdPath ) ); } else { rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), RTL_CONSTASCII_STRINGPARAM( "0" ) ); } for ( nArg = 0; nArg < nArgCount; ++nArg ) { rtl_uString *pEscapedTmp = NULL; rtl_uStringbuffer_insert_ascii( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), ",", 1 ); rtl_getAppCommandArg( nArg, &pTmp ); pEscapedTmp = escape_path( pTmp ); rtl_uStringbuffer_insert( &pBuffer, &nCapacity, rtl_uString_getLength( pBuffer ), rtl_uString_getStr( pEscapedTmp ), rtl_uString_getLength( pEscapedTmp ) ); rtl_uString_release( pEscapedTmp ); } if ( !rtl_convertUStringToString( &pOut, rtl_uString_getStr( pBuffer ), rtl_uString_getLength( pBuffer ), RTL_TEXTENCODING_UTF8, ( RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR ) ) ) { fprintf( stderr, "ERROR: cannot convert arguments to UTF-8\n" ); exit( 1 ); } nLen = rtl_string_getLength( pOut ) + 1; bResult = ( write( fd, rtl_string_getStr( pOut ), nLen ) == (ssize_t) nLen ); if ( bResult ) { char resp[ strlen( "InternalIPC::ProcessingDone" ) ]; ssize_t n = read( fd, resp, SAL_N_ELEMENTS( resp ) ); bResult = n == (ssize_t) SAL_N_ELEMENTS( resp ) && (memcmp( resp, "InternalIPC::ProcessingDone", SAL_N_ELEMENTS( resp ) ) == 0); } /* cleanup */ rtl_uString_release( pEscapedCwdPath ); rtl_uString_release( pBuffer ); rtl_uString_release( pTmp ); rtl_string_release( pOut ); return bResult; }
static oslFileError osl_create_temp_file_impl_( const rtl_uString* pustr_base_directory, oslFileHandle* file_handle, rtl_uString** ppustr_temp_file_name) { rtl_uString* rand_name = 0; sal_uInt32 len_base_dir = 0; rtl_uString* tmp_file_path = 0; rtl_uString* tmp_file_url = 0; sal_Int32 capacity = 0; oslFileError osl_error = osl_File_E_None; sal_Int32 offset_file_name; const sal_Unicode* puchr; OSL_PRECOND(pustr_base_directory, "Invalid Parameter"); OSL_PRECOND(file_handle, "Invalid Parameter"); OSL_PRECOND(ppustr_temp_file_name, "Invalid Parameter"); len_base_dir = rtl_uString_getLength(pustr_base_directory); rtl_uStringbuffer_newFromStr_WithLength( &tmp_file_path, rtl_uString_getStr((rtl_uString*)pustr_base_directory), len_base_dir); rtl_uStringbuffer_ensureCapacity( &tmp_file_path, &capacity, (len_base_dir + 1 + RAND_NAME_LENGTH)); offset_file_name = len_base_dir; puchr = rtl_uString_getStr(tmp_file_path); /* ensure that the last character is a '/' */ if ((sal_Unicode)'/' != puchr[len_base_dir - 1]) { rtl_uStringbuffer_insert_ascii( &tmp_file_path, &capacity, len_base_dir, "/", 1); offset_file_name++; } while(1) /* try until success */ { osl_gen_random_name_impl_(&rand_name); rtl_uStringbuffer_insert( &tmp_file_path, &capacity, offset_file_name, rtl_uString_getStr(rand_name), rtl_uString_getLength(rand_name)); osl_error = osl_getFileURLFromSystemPath( tmp_file_path, &tmp_file_url); if (osl_File_E_None == osl_error) { /* RW permission for the user only! */ mode_t old_mode = umask(077); osl_error = osl_openFile( tmp_file_url, file_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write | osl_File_OpenFlag_Create); umask(old_mode); } /* in case of error osl_File_E_EXIST we simply try again else we give up */ if ((osl_File_E_None == osl_error) || (osl_error != osl_File_E_EXIST)) { if (rand_name) rtl_uString_release(rand_name); if (tmp_file_url) rtl_uString_release(tmp_file_url); break; } } /* while(1) */ if (osl_File_E_None == osl_error) rtl_uString_assign(ppustr_temp_file_name, tmp_file_path); if (tmp_file_path) rtl_uString_release(tmp_file_path); return osl_error; }
oslFileError SAL_CALL osl_createTempFile( rtl_uString* pustrDirectoryURL, oslFileHandle* pHandle, rtl_uString** ppustrTempFileURL) { rtl_uString* base_directory = 0; rtl_uString* temp_file_name = 0; oslFileHandle temp_file_handle; sal_Bool b_delete_on_close; oslFileError osl_error; osl_error = osl_setup_createTempFile_impl_( pustrDirectoryURL, pHandle, ppustrTempFileURL, &base_directory, &b_delete_on_close); if (osl_File_E_None != osl_error) return osl_error; osl_error = osl_create_temp_file_impl_( base_directory, &temp_file_handle, &temp_file_name); if (osl_File_E_None == osl_error) { rtl_uString* temp_file_url = 0; /* assuming this works */ osl_getFileURLFromSystemPath(temp_file_name, &temp_file_url); if (b_delete_on_close) { osl_error = osl_removeFile(temp_file_url); if (osl_File_E_None == osl_error) *pHandle = temp_file_handle; else osl_closeFile(temp_file_handle); } else { if (pHandle) *pHandle = temp_file_handle; else osl_closeFile(temp_file_handle); rtl_uString_assign(ppustrTempFileURL, temp_file_url); } if (temp_file_url) rtl_uString_release(temp_file_url); if (temp_file_name) rtl_uString_release(temp_file_name); } if (base_directory) rtl_uString_release(base_directory); return osl_error; }
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; }
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; }
/* * Class: com_sun_star_lib_connections_pipe_PipeConnection * Method: connect * Signature: (Lcom/sun/star/beans/NativeService;)V */ SAL_DLLPUBLIC_EXPORT void #if defined WNT PipeConnection_create #else JNICALL Java_com_sun_star_lib_connections_pipe_PipeConnection_createJNI #endif (JNIEnv * env, jobject obj_this, jstring name) { enum { START = 0, INMONITOR, GOTNAME, CREATED }; short state = START; jclass tclass; jfieldID fid; oslSecurity psec = osl_getCurrentSecurity(); oslPipe npipe = NULL; rtl_uString * pname = NULL; if ((*env)->MonitorEnter(env, obj_this) != 0) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot synchronize on the object"); goto error; } state = INMONITOR; /* check connection state */ npipe = getPipe(env, obj_this); if ((*env)->ExceptionOccurred(env) != NULL) goto error; if (npipe != NULL) { ThrowException(env, "com/sun/star/io/IOException", "native pipe is already connected"); goto error; } /* save the pipe name */ tclass = (*env)->GetObjectClass(env, obj_this); if (tclass == NULL) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot find class"); goto error; } fid = (*env)->GetFieldID(env, tclass, "_aDescription", "Ljava/lang/String;"); if (fid == NULL) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot find field"); goto error; } (*env)->SetObjectField(env, obj_this, fid, (jobject)name); /* convert pipe name to rtl_uString */ pname = jstring2ustring(env, name); if (pname == NULL) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot convert name"); goto error; } state = GOTNAME; /* try to connect */ npipe = osl_createPipe(pname, osl_Pipe_OPEN, psec); if (npipe == NULL) { ThrowException(env, "java/lang/RuntimeException", "cannot create native pipe"); goto error; } state = CREATED; /* save the pipe */ tclass = (*env)->GetObjectClass(env, obj_this); if (tclass == NULL) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot find class"); goto error; } fid = (*env)->GetFieldID(env, tclass, "_nPipeHandle", "J"); if (fid == NULL) { ThrowException(env, "java/lang/RuntimeException", "native pipe cannot find field"); goto error; } (*env)->SetLongField( env, obj_this, fid, SAL_INT_CAST(jlong, (sal_IntPtr) npipe)); /* done */ rtl_uString_release(pname); (*env)->MonitorExit(env, obj_this); osl_freeSecurityHandle(psec); return; error: switch (state) { case CREATED: osl_closePipe(npipe); osl_releasePipe(npipe); case GOTNAME: rtl_uString_release(pname); case INMONITOR: (*env)->MonitorExit(env, obj_this); case START: osl_freeSecurityHandle(psec); default: break; } return; }
SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv ) { sal_Bool bSentArgs = sal_False; const char* pUsePlugin; rtl_uString *pPipePath = NULL; Args *args; int status = 0; struct splash* splash = NULL; struct sigaction sigpipe_action; struct sigaction sigterm_action; /* turn SIGPIPE into an error */ memset(&sigpipe_action, 0, sizeof(struct sigaction)); sigpipe_action.sa_handler = SIG_IGN; sigemptyset(&sigpipe_action.sa_mask); sigaction(SIGPIPE, &sigpipe_action, 0); memset(&sigterm_action, 0, sizeof(struct sigaction)); sigterm_action.sa_handler = &sigterm_handler; sigemptyset(&sigterm_action.sa_mask); sigaction(SIGTERM, &sigterm_action, 0); args = args_parse (); args->pAppPath = get_app_path( argv[0] ); if ( !args->pAppPath ) { fprintf( stderr, "ERROR: Can't read app link\n" ); exit( 1 ); } ustr_debug( "App path", args->pAppPath ); #ifndef ENABLE_QUICKSTART_LIBPNG /* we can't load and render it anyway */ args->bInhibitSplash = sal_True; #endif pUsePlugin = getenv( "SAL_USE_VCLPLUGIN" ); if ( pUsePlugin && !strcmp(pUsePlugin, "svp") ) args->bInhibitSplash = sal_True; if ( !args->bInhibitPipe ) { int fd = 0; pPipePath = get_pipe_path( args->pAppPath ); if ( ( fd = connect_pipe( pPipePath ) ) >= 0 ) { // Wait for answer char resp[ strlen( "InternalIPC::SendArguments" ) + 1]; ssize_t n = read( fd, resp, SAL_N_ELEMENTS( resp ) ); if (n == (ssize_t) SAL_N_ELEMENTS( resp ) && (memcmp( resp, "InternalIPC::SendArguments", SAL_N_ELEMENTS( resp ) - 1) == 0)) { rtl_uString *pCwdPath = NULL; osl_getProcessWorkingDir( &pCwdPath ); // Then send args bSentArgs = send_args( fd, pCwdPath ); } close( fd ); } #if OSL_DEBUG_LEVEL > 1 else ustr_debug( "Failed to connect to pipe", pPipePath ); #endif } if ( !bSentArgs ) { /* we have to prepare for, and exec the binary */ int nPercent = 0; ChildInfo *info; sal_Bool bAllArgs = sal_True; sal_Bool bShortWait, bRestart; /* sanity check pieces */ system_checks(); /* load splash image and create window */ if ( !args->bInhibitSplash ) { splash = splash_create(args->pAppPath, argc, argv); } /* pagein */ if (!args->bInhibitPagein) exec_pagein (args); /* javaldx */ #if HAVE_FEATURE_JAVA if (!args->bInhibitJavaLdx) exec_javaldx (args); #endif do { bRestart = sal_False; /* fast updates if we have somewhere to update it to */ bShortWait = splash ? sal_True : sal_False; /* Periodically update the splash & the percent according to what status_fd says, poll quickly only while starting */ info = child_spawn (args, bAllArgs, bShortWait); g_pProcess = info->child; while (!child_exited_wait (info, bShortWait)) { ProgressStatus eResult; splash_draw_progress( splash, nPercent ); eResult = read_percent( info, &nPercent ); if (eResult != ProgressContinue) { splash_destroy(splash); splash = NULL; bShortWait = sal_False; } #if OSL_DEBUG_LEVEL > 1 fprintf( stderr, "Polling, result is %s\n", ( eResult == ProgressContinue )? "continue" : ( ( eResult == ProgressRestart )? "restart" : "exit" ) ); #endif } #if OSL_DEBUG_LEVEL > 1 fprintf (stderr, "Exited with code '%d'\n", child_get_exit_code (info)); #endif status = child_get_exit_code(info); g_pProcess = 0; // reset switch (status) { case EXITHELPER_CRASH_WITH_RESTART: // re-start with just -env: parameters #if OSL_DEBUG_LEVEL > 1 fprintf (stderr, "oosplash: re-start with just -env: params !\n"); #endif bRestart = sal_True; bAllArgs = sal_False; break; case EXITHELPER_NORMAL_RESTART: // re-start with all arguments #if OSL_DEBUG_LEVEL > 1 fprintf (stderr, "oosplash: re-start with all params !\n"); #endif bRestart = sal_True; bAllArgs = sal_True; break; default: break; } child_info_destroy (info); } while (bRestart); } /* cleanup */ if ( pPipePath ) rtl_uString_release( pPipePath ); args_free (args); return status; }
static void exec_javaldx (Args *args) { char newpath[4096]; sal_uInt32 nArgs; rtl_uString *pApp; rtl_uString **ppArgs; rtl_uString *pTmp, *pTmp2; oslProcess javaldx = NULL; oslFileHandle fileOut= 0; oslProcessError err; ppArgs = (rtl_uString **)calloc( args->nArgsEnv + 2, sizeof( rtl_uString* ) ); for ( nArgs = 0; nArgs < args->nArgsEnv; ++nArgs ) ppArgs[nArgs] = args->ppArgs[nArgs]; /* Use absolute path to redirectrc */ pTmp = NULL; rtl_uString_newFromAscii( &pTmp, "-env:INIFILENAME=vnd.sun.star.pathname:" ); rtl_uString_newConcat( &pTmp, pTmp, args->pAppPath ); pTmp2 = NULL; rtl_uString_newFromAscii( &pTmp2, "redirectrc" ); rtl_uString_newConcat( &pTmp, pTmp, pTmp2 ); ppArgs[nArgs] = pTmp; rtl_uString_release (pTmp2); nArgs++; /* And also to javaldx */ pApp = NULL; rtl_uString_newFromAscii( &pApp, "file://" ); rtl_uString_newConcat( &pApp, pApp, args->pAppPath ); pTmp = NULL; rtl_uString_newFromAscii( &pTmp, "javaldx" ); rtl_uString_newConcat( &pApp, pApp, pTmp ); rtl_uString_release( pTmp ); err = osl_executeProcess_WithRedirectedIO( pApp, ppArgs, nArgs, osl_Process_NORMAL, NULL, // security NULL, // work dir NULL, 0, &javaldx, // process handle NULL, &fileOut, NULL); rtl_uString_release( ppArgs[nArgs-1] ); rtl_uString_release( pApp ); free( ppArgs ); if( err != osl_Process_E_None) { fprintf (stderr, "Warning: failed to launch javaldx - java may not function correctly\n"); if (javaldx) osl_freeProcessHandle(javaldx); if (fileOut) osl_closeFile(fileOut); return; } else { char *chomp; sal_uInt64 bytes_read; /* Magically osl_readLine doesn't work with pipes with E_SPIPE - so be this lame instead: */ while (osl_readFile (fileOut, newpath, SAL_N_ELEMENTS (newpath), &bytes_read) == osl_File_E_INTR); if (bytes_read <= 0) { fprintf (stderr, "Warning: failed to read path from javaldx\n"); if (javaldx) osl_freeProcessHandle(javaldx); if (fileOut) osl_closeFile(fileOut); return; } newpath[bytes_read] = '\0'; if ((chomp = strstr (newpath, "\n"))) *chomp = '\0'; } #if OSL_DEBUG_LEVEL > 1 fprintf (stderr, "Adding javaldx path of '%s'\n", newpath); #endif extend_library_path (newpath); if (javaldx) osl_freeProcessHandle(javaldx); if (fileOut) osl_closeFile(fileOut); }
static ChildInfo * child_spawn ( Args *args, sal_Bool bAllArgs, sal_Bool bWithStatus ) { rtl_uString *pApp = NULL, *pTmp = NULL; rtl_uString **ppArgs; sal_uInt32 nArgs, i; ChildInfo *info; int status_pipe[2]; oslProcessError nError; info = calloc (1, sizeof (ChildInfo)); /* create pipe */ if ( pipe( status_pipe ) < 0 ) { fprintf( stderr, "ERROR: no file handles\n"); exit( 1 ); } info->status_fd = status_pipe[0]; /* application name */ rtl_uString_newFromAscii( &pApp, "file://" ); rtl_uString_newConcat( &pApp, pApp, args->pAppPath ); rtl_uString_newFromAscii( &pTmp, "soffice.bin" ); rtl_uString_newConcat( &pApp, pApp, pTmp ); rtl_uString_release( pTmp ); pTmp = NULL; /* copy args */ nArgs = bAllArgs ? args->nArgsTotal : args->nArgsEnv; ppArgs = (rtl_uString **)calloc( nArgs + 1, sizeof( rtl_uString* ) ); for ( i = 0; i < nArgs; ++i ) ppArgs[i] = args->ppArgs[i]; if( bWithStatus ) { char buffer[64]; /* add the pipe arg */ snprintf (buffer, 63, "--splash-pipe=%d", status_pipe[1]); rtl_uString_newFromAscii( &pTmp, buffer ); ppArgs[nArgs] = pTmp; ++nArgs; } /* start the main process */ nError = osl_executeProcess( pApp, ppArgs, nArgs, osl_Process_NORMAL, NULL, NULL, NULL, 0, &info->child ); if (pTmp) rtl_uString_release( pTmp ); free (ppArgs); if ( nError != osl_Process_E_None ) { fprintf( stderr, "ERROR %d forking process", nError ); ustr_debug( "", pApp ); rtl_uString_release( pApp ); _exit (1); } rtl_uString_release( pApp ); close( status_pipe[1] ); return info; }
sal_Bool SAL_CALL osl_loadUserProfile(oslSecurity Security) { /* CreateProcessAsUser does not load the specified user's profile into the HKEY_USERS registry key. This means that access to information in the HKEY_CURRENT_USER registry key may not produce results consistent with a normal interactive logon. It is your responsibility to load the user's registry hive into HKEY_USERS with the LoadUserProfile function before calling CreateProcessAsUser. */ BOOL bOk = FALSE; RegCloseKey(HKEY_CURRENT_USER); if (Privilege(SE_RESTORE_NAME, TRUE)) { HMODULE hUserEnvLib = NULL; LPFNLOADUSERPROFILE fLoadUserProfile = NULL; LPFNUNLOADUSERPROFILE fUnloadUserProfile = NULL; HANDLE hAccessToken = ((oslSecurityImpl*)Security)->m_hToken; DWORD nError = 0; /* try to create user profile */ if ( !hAccessToken ) { /* retrieve security handle if not done before e.g. osl_getCurrentSecurity() */ HANDLE hProcess = GetCurrentProcess(); if (hProcess != NULL) { OpenProcessToken(hProcess, TOKEN_IMPERSONATE, &hAccessToken); CloseHandle(hProcess); } } hUserEnvLib = LoadLibraryA("userenv.dll"); if (hUserEnvLib) { fLoadUserProfile = (LPFNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "LoadUserProfileW"); fUnloadUserProfile = (LPFNUNLOADUSERPROFILE)GetProcAddress(hUserEnvLib, "UnloadUserProfile"); if (fLoadUserProfile && fUnloadUserProfile) { rtl_uString *buffer = 0; PROFILEINFOW pi; getUserNameImpl(Security, &buffer, sal_False); ZeroMemory( &pi, sizeof(pi) ); pi.dwSize = sizeof(pi); pi.lpUserName = rtl_uString_getStr(buffer); pi.dwFlags = PI_NOUI; if (fLoadUserProfile(hAccessToken, &pi)) { fUnloadUserProfile(hAccessToken, pi.hProfile); bOk = TRUE; } else nError = GetLastError(); rtl_uString_release(buffer); } FreeLibrary(hUserEnvLib); } if (hAccessToken && (hAccessToken != ((oslSecurityImpl*)Security)->m_hToken)) CloseHandle(hAccessToken); } return (sal_Bool)bOk; }