Esempio n. 1
0
static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process)
{
    PROCESS_INFORMATION pi;
    STARTUPINFOW si;
    LPWSTR path = NULL;
    DWORD size;
    BOOL r;

    service_lock_exclusive(service_entry);

    if (service_entry->config.dwServiceType == SERVICE_KERNEL_DRIVER)
    {
        static const WCHAR winedeviceW[] = {'\\','w','i','n','e','d','e','v','i','c','e','.','e','x','e',' ',0};
        DWORD len = GetSystemDirectoryW( NULL, 0 ) + sizeof(winedeviceW)/sizeof(WCHAR) + strlenW(service_entry->name);

        if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
            return ERROR_NOT_ENOUGH_SERVER_MEMORY;
        GetSystemDirectoryW( path, len );
        lstrcatW( path, winedeviceW );
        lstrcatW( path, service_entry->name );
    }
    else
    {
        size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,NULL,0);
        path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
        if (!path)
            return ERROR_NOT_ENOUGH_SERVER_MEMORY;
        ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,path,size);
    }

    ZeroMemory(&si, sizeof(STARTUPINFOW));
    si.cb = sizeof(STARTUPINFOW);
    if (!(service_entry->config.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
    {
        static WCHAR desktopW[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n','\\','D','e','f','a','u','l','t',0};
        si.lpDesktop = desktopW;
    }

    service_entry->status.dwCurrentState = SERVICE_START_PENDING;

    service_unlock(service_entry);

    r = CreateProcessW(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
    HeapFree(GetProcessHeap(),0,path);
    if (!r)
    {
        service_lock_exclusive(service_entry);
        service_entry->status.dwCurrentState = SERVICE_STOPPED;
        service_unlock(service_entry);
        return GetLastError();
    }

    service_entry->status.dwProcessId = pi.dwProcessId;
    *process = pi.hProcess;
    CloseHandle( pi.hThread );

    return ERROR_SUCCESS;
}
Esempio n. 2
0
static DWORD service_wait_for_startup(struct service_entry *service_entry, HANDLE process_handle)
{
    HANDLE handles[2] = { service_entry->status_changed_event, process_handle };
    DWORD state, ret;

    WINE_TRACE("%p\n", service_entry);

    ret = WaitForMultipleObjects( 2, handles, FALSE, service_pipe_timeout );
    if (ret != WAIT_OBJECT_0)
        return ERROR_SERVICE_REQUEST_TIMEOUT;
    service_lock_shared(service_entry);
    state = service_entry->status.dwCurrentState;
    service_unlock(service_entry);
    if (state == SERVICE_START_PENDING)
    {
        WINE_TRACE("Service state changed to SERVICE_START_PENDING\n");
        return ERROR_SUCCESS;
    }
    else if (state == SERVICE_RUNNING)
    {
        WINE_TRACE("Service started successfully\n");
        return ERROR_SUCCESS;
    }

    return ERROR_SERVICE_REQUEST_TIMEOUT;
}
static int set_avtransport_uri(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}
	char *uri = upnp_get_string(event, "CurrentURI");
	if (uri == NULL) {
		return -1;
	}

	service_lock();
	char *meta = upnp_get_string(event, "CurrentURIMetaData");
	// Transport URI/Meta set now, current URI/Meta when it starts playing.
	int requires_meta_update = replace_transport_uri_and_meta(uri, meta);

	if (transport_state_ == TRANSPORT_PLAYING) {
		// Uh, wrong state.
		// Usually, this should not be called while we are PLAYING, only
		// STOPPED or PAUSED. But if actually some controller sets this
		// while playing, probably the best is to update the current
		// current URI/Meta as well to reflect the state best.
		replace_current_uri_and_meta(uri, meta);
	}

	output_set_uri(uri, (requires_meta_update
			     ? update_meta_from_stream
			     : NULL));
	service_unlock();

	free(uri);
	free(meta);

	return 0;
}
static int set_avtransport_uri(struct action_event *event)
{
	int rc = 0;

	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}
	char *uri = upnp_get_string(event, "CurrentURI");
	if (uri == NULL) {
		LEAVE();
		return -1;
	}

	service_lock();

	char *meta = upnp_get_string(event, "CurrentURIMetaData");
	int requires_meta_update = replace_transport_uri_and_meta(uri, meta);

	output_set_uri(uri, (requires_meta_update
			     ? update_meta_from_stream
			     : NULL));

	notify_changed_uris();
	service_unlock();

	free(uri);
	free(meta);

	LEAVE();
	return rc;
}
static int set_next_avtransport_uri(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	char *next_uri = upnp_get_string(event, "NextURI");
	if (next_uri == NULL) {
		return -1;
	}

	int rc = 0;
	service_lock();

	output_set_next_uri(next_uri);
	replace_var(TRANSPORT_VAR_NEXT_AV_URI, next_uri);

	char *next_uri_meta = upnp_get_string(event, "NextURIMetaData");
	if (next_uri_meta == NULL) {
		rc = -1;
	} else {
		replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, next_uri_meta);
	}

	service_unlock();

	free(next_uri);
	free(next_uri_meta);

	return rc;
}
static int stop(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_STOPPED:
		// nothing to change.
		break;
	case TRANSPORT_PLAYING:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
	case TRANSPORT_PAUSED_PLAYBACK:
		output_stop();
		change_transport_state(TRANSPORT_STOPPED);
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed; allowed=%s",
			       get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));

		break;
	}
	service_unlock();

	return 0;
}
static int pause_stream(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	int rc = 0;
	service_lock();
	switch (transport_state_) {
        case TRANSPORT_PAUSED_PLAYBACK:
		// Nothing to change.
		break;

	case TRANSPORT_PLAYING:
		if (output_pause()) {
			upnp_set_error(event, 704, "Pause failed");
			rc = -1;
		} else {
			change_transport_state(TRANSPORT_PAUSED_PLAYBACK);
		}
		break;

        default:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed; allowed=%s",
			       get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
		rc = -1;
        }
	service_unlock();

	return rc;
}
// We constantly update the track time to event about it to our clients.
static void *thread_update_track_time(void *userdata) {
	const gint64 one_sec_unit = 1000000000LL;
	char tbuf[32];
	gint64 last_duration = -1, last_position = -1;
	for (;;) {
		usleep(500000);  // 500ms
		service_lock();
		gint64 duration, position;
		const int pos_result = output_get_position(&duration, &position);
		if (pos_result == 0) {
			if (duration != last_duration) {
				print_upnp_time(tbuf, sizeof(tbuf), duration);
				replace_var(TRANSPORT_VAR_CUR_TRACK_DUR, tbuf);
				last_duration = duration;
			}
			if (position / one_sec_unit != last_position) {
				print_upnp_time(tbuf, sizeof(tbuf), position);
				replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf);
				last_position = position / one_sec_unit;
			}
		}
		service_unlock();
	}
	return NULL;  // not reached.
}
static int seek(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	char *unit = upnp_get_string(event, "Unit");
	if (strcmp(unit, "REL_TIME") == 0) {
		// This is the only thing we support right now.
		char *target = upnp_get_string(event, "Target");
		gint64 nanos = parse_upnp_time(target);
		service_lock();
		if (output_seek(nanos) == 0) {
			// TODO(hzeller): Seeking might take some time,
			// pretend to already be there. Should we go into
			// TRANSITION mode ?
			// (gstreamer will go into PAUSE, then PLAYING)
			replace_var(TRANSPORT_VAR_REL_TIME_POS, target);
		}
		service_unlock();
		free(target);
	}
	free(unit);

	return 0;
}
Esempio n. 10
0
static int set_mute(struct action_event *event) {
	const char *value = upnp_get_string(event, "DesiredMute");
	service_lock();
	const int do_mute = atoi(value);
	set_mute_toggle(do_mute);
	change_var_and_notify(event, CONTROL_VAR_MUTE, do_mute ? "1" : "0");
	service_unlock();
	return 0;
}
static int set_streaming_playlist(struct action_event *event)  
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	char *playlistdata = upnp_get_string(event, "PlaylistData");
	if (playlistdata == NULL) {
		return -1;
	}
	int playlistdatalength = atoi(upnp_get_string(event, "PlaylistDataLength"));
	/*char *playlistmimetype = upnp_get_string(event, "PlaylistMIMEType");
	if (playlistmimetype == NULL) {
		free(playlistdata);
		return -1;
	} */
	char *playliststep = upnp_get_string(event, "PlaylistStep");  //Initial Continue Stop Reset
	if (playliststep == NULL) {
		free(playlistdata);
	//	free(playlistmimetype);
		return -1;
	}

	int rc = 0;
	service_lock();
	if(strcmp(playliststep, "Initial") == 0){
		//TODO:
		rc = write_playlist(event, playlistdata, playlistdatalength, "w");
		
	}

	if(strcmp(playliststep, "Continue") == 0){
		rc = write_playlist(event, playlistdata, playlistdatalength, "a");
		
	}

	if(strcmp(playliststep, "Stop") == 0){
		//TODO:  Indicates that the current streaming playlist operation will end when all pending playlist data at then device is consumed.
		if(playlistdata)
			rc = write_playlist(event, playlistdata, playlistdatalength,  "a");
		output_set_playlist(M3U_STREAMINGPLAYLIST_PATH);
	}

	if(strcmp(playliststep, "Reset") == 0){
		//TODO: Indicates that processing of the current streaming playlist ends immediately. any pending playlist data for the streaming playlist is discarded.
		output_set_playlist(M3U_STREAMINGPLAYLIST_PATH);
	}

	if(!rc)
		replace_var(TRANSPORT_VAR_AAT_PLAYLIST_STEP, playliststep);
	service_unlock();
	if(playlistdata)
		free(playlistdata);
	free(playliststep);
	return rc;

}
static void shared_meta_time_change(uint32_t total, uint32_t current)
{
	char tbuf[32];
	service_lock();
	print_upnp_time(tbuf, sizeof(tbuf), total);
	replace_var(TRANSPORT_VAR_CUR_TRACK_DUR, tbuf);
	print_upnp_time(tbuf, sizeof(tbuf), current);
	replace_var(TRANSPORT_VAR_REL_TIME_POS, tbuf);
	service_unlock();
}
Esempio n. 13
0
static int set_volume_db(struct action_event *event) {
	const char *str_decibel_in = upnp_get_string(event, "DesiredVolume");
	service_lock();
	float raw_decibel_in = atof(str_decibel_in);
	float decibel = change_volume_decibel(event, raw_decibel_in);

	output_set_volume(exp(decibel / 20 * log(10)));
	service_unlock();

	return 0;
}
Esempio n. 14
0
void release_service(struct service_entry *service)
{
    if (InterlockedDecrement(&service->ref_count) == 0 && is_marked_for_delete(service))
    {
        scmdatabase_lock_exclusive(service->db);
        service_lock_exclusive(service);
        scmdatabase_remove_service(service->db, service);
        service_unlock(service);
        scmdatabase_unlock(service->db);
        free_service_entry(service);
    }
}
// Callback from our output if the song meta data changed.
static void update_meta_from_stream(const struct SongMetaData *meta) {
	if (meta->title == NULL || strlen(meta->title) == 0) {
		return;
	}
	const char *original_xml = get_var(TRANSPORT_VAR_AV_URI_META);
	char *didl = SongMetaData_to_DIDL(meta, original_xml);
	service_lock();
	replace_var(TRANSPORT_VAR_AV_URI_META, didl);
	replace_var(TRANSPORT_VAR_CUR_TRACK_META, didl);
	service_unlock();
	free(didl);
}
// Callback from our output if the song meta data changed.
static void update_meta_from_stream(const struct SongMetaData *meta) {
	if (meta->title == NULL || strlen(meta->title) == 0) {
		return;
	}
	const char *original_xml = transport_values[TRANSPORT_VAR_AV_URI_META];
	char *didl = SongMetaData_to_DIDL(original_xml, meta);
	service_lock();
	replace_var(TRANSPORT_VAR_AV_URI_META, didl);
	replace_var(TRANSPORT_VAR_CUR_TRACK_META, didl);
	notify_changed_uris();
	service_unlock();
	free(didl);
}
static int play(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}

	int rc = 0;
	service_lock();
	switch (transport_state_) {
	// even if already playing, we must restart playback when Play
	// action is executed. Kinsky, for example, would not send Stop
	// when changing tracks and playback is already in progress -
	// it will just set new URI, and send Play command
	case TRANSPORT_PLAYING:
	case TRANSPORT_STOPPED:
		// If we were stopped before, we start a new song now. So just
		// set the time to zero now; otherwise we will see the old
		// value of the previous song until it updates some fractions
		// of a second later.
		replace_var(TRANSPORT_VAR_REL_TIME_POS, kZeroTime);

		/* >>> fall through */

	case TRANSPORT_PAUSED_PLAYBACK:
		if (output_play(&inform_play_transition_from_output)) {
			upnp_set_error(event, 704, "Playing failed");
			rc = -1;
		} else {
			change_transport_state(TRANSPORT_PLAYING);
			const char *av_uri = get_var(TRANSPORT_VAR_AV_URI);
			const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META);
			replace_current_uri_and_meta(av_uri, av_meta);
		}
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed; allowed=%s",
			       get_var(TRANSPORT_VAR_CUR_TRANSPORT_ACTIONS));
		rc = -1;
		break;
	}
	service_unlock();

	return rc;
}
Esempio n. 18
0
void service_terminate(struct service_entry *service)
{
    service_lock_exclusive(service);
    TerminateProcess(service->process, 0);
    CloseHandle(service->process);
    service->process = NULL;
    CloseHandle(service->status_changed_event);
    service->status_changed_event = NULL;
    CloseHandle(service->control_mutex);
    service->control_mutex = NULL;
    CloseHandle(service->control_pipe);
    service->control_pipe = INVALID_HANDLE_VALUE;

    service->status.dwProcessId = 0;
    service->status.dwCurrentState = SERVICE_STOPPED;
    service_unlock(service);
}
static int play(struct action_event *event)
{
	int rc = 0;

	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_PLAYING:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_PLAYING);
		// Set TransportPlaySpeed to '1'
		break;
	case TRANSPORT_STOPPED:
	case TRANSPORT_PAUSED_PLAYBACK:
		if (output_play(&inform_done_playing)) {
			upnp_set_error(event, 704, "Playing failed");
			rc = -1;
		} else {
			change_and_notify_transport(TRANSPORT_PLAYING);
		}
		// Set TransportPlaySpeed to '1'
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");
		rc = -1;

		break;
	}
	service_unlock();

	LEAVE();
	return rc;
}
//TODO:FIXME
static int set_playmode(struct action_event *event)
{
	if (obtain_instanceid(event, NULL) < 0) {
		return -1;
	}
	char *playmode = upnp_get_string(event, "NewPlayMode");
	if (playmode == NULL) {
		return -1;
	}
//TODO: support this playmode?  error 712
	
// This is the only thing we support right now.
	service_lock();
	replace_var(TRANSPORT_VAR_CUR_PLAY_MODE, playmode);
	service_unlock();
	free(playmode);
	return 0;
}
void timerPlay(char *uri)
{

	service_lock();
	output_stop();
	change_transport_state(TRANSPORT_STOPPED);
	output_set_uri(uri, NULL);
	replace_var(TRANSPORT_VAR_REL_TIME_POS, kZeroTime);
	if (output_play(&inform_play_transition_from_output)) {
		
	} else {
		change_transport_state(TRANSPORT_PLAYING);
		const char *av_uri = get_var(TRANSPORT_VAR_AV_URI);
		const char *av_meta = get_var(TRANSPORT_VAR_AV_URI_META);
		replace_current_uri_and_meta(av_uri, av_meta);
	}
	
	service_unlock();
}
static void inform_done_playing(enum PlayFeedback fb) {
	printf("---------------------------------- Done playing....%d\n", fb);
	service_lock();
	switch (fb) {
	case PLAY_STOPPED:
		replace_transport_uri_and_meta("", "");
		change_and_notify_transport(TRANSPORT_STOPPED);
		notify_changed_uris();
		break;
	case PLAY_STARTED_NEXT_STREAM:
		replace_transport_uri_and_meta(
			   transport_values[TRANSPORT_VAR_NEXT_AV_URI],
			   transport_values[TRANSPORT_VAR_NEXT_AV_URI_META]);
		replace_var(TRANSPORT_VAR_NEXT_AV_URI, "");
		replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, "");
		notify_changed_uris();
		break;
	}
	service_unlock();
}
static void inform_play_transition_from_output(enum PlayFeedback fb) {
	service_lock();
	switch (fb) {
	case PLAY_STOPPED:
		replace_transport_uri_and_meta("", "");
		replace_current_uri_and_meta("", "");
		change_transport_state(TRANSPORT_STOPPED);
		break;

	case PLAY_STARTED_NEXT_STREAM: {
		const char *av_uri = get_var(TRANSPORT_VAR_NEXT_AV_URI);
		const char *av_meta = get_var(TRANSPORT_VAR_NEXT_AV_URI_META);
		replace_transport_uri_and_meta(av_uri, av_meta);
		replace_current_uri_and_meta(av_uri, av_meta);
		replace_var(TRANSPORT_VAR_NEXT_AV_URI, "");
		replace_var(TRANSPORT_VAR_NEXT_AV_URI_META, "");
		break;
	}
	}
	service_unlock();
}
Esempio n. 24
0
static int set_volume(struct action_event *event) {
	const char *volume = upnp_get_string(event, "DesiredVolume");
	service_lock();
	int volume_level = atoi(volume);  // range 0..100
	if (volume_level < volume_range.min) volume_level = volume_range.min;
	if (volume_level > volume_range.max) volume_level = volume_range.max;
	const float decibel = volume_level_to_decibel(volume_level);

	char db_volume[10];
	snprintf(db_volume, sizeof(db_volume), "%d", (int) (256 * decibel));

	Log_info("control", "Setting %d volume-db to %d" , volume_level,(int)decibel);

	const double fraction = exp(decibel / 20 * log(10));

	change_volume(volume, db_volume);
	output_set_volume(fraction, volume_level);
	set_mute_toggle(volume_level == 0);
	service_unlock();

	return 0;
}
Esempio n. 25
0
static int set_volume(struct action_event *event) {
	const char *volume = upnp_get_string(event, "DesiredVolume");
	service_lock();
	int volume_level = atoi(volume);  // range 0..100
	if (volume_level < volume_range.min) volume_level = volume_range.min;
	if (volume_level > volume_range.max) volume_level = volume_range.max;
	const float decibel = volume_level_to_decibel(volume_level);

	char db_volume[10];
	snprintf(db_volume, sizeof(db_volume), "%d", (int) (256 * decibel));

	const double fraction = exp(decibel / 20 * log(10));
	fprintf(stderr, "Setting volume to #%d = %.2fdb (%.4f)\n",
		volume_level, decibel, fraction);

	change_volume_and_notify(event, volume, db_volume);
	output_set_volume(fraction);
	set_mute_toggle(volume_level == 0);
	service_unlock();

	return 0;
}
static int pause_stream(struct action_event *event)
{
	int rc = 0;
	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}

	service_lock();
	switch (transport_state_) {
        case TRANSPORT_PAUSED_PLAYBACK:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_PAUSED_PLAYBACK);
		break;

	case TRANSPORT_PLAYING:
		if (output_pause()) {
			upnp_set_error(event, 704, "Pause failed");
			rc = -1;
		} else {
			change_and_notify_transport(TRANSPORT_PAUSED_PLAYBACK);
		}
		// Set TransportPlaySpeed to '1'
		break;

        default:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");
		rc = -1;
        }
	service_unlock();

	LEAVE();

	return rc;
}
static int set_next_avtransport_uri(struct action_event *event)
{
	int rc = 0;
	char *value;

	ENTER();

	if (obtain_instanceid(event, NULL)) {
		LEAVE();
		return -1;
	}

	value = upnp_get_string(event, "NextURI");
	if (value == NULL) {
		LEAVE();
		return -1;
	}

	service_lock();

	output_set_next_uri(value);
	change_var_and_notify(TRANSPORT_VAR_NEXT_AV_URI, value);

	printf("%s: NextURI='%s'\n", __FUNCTION__, value);
	free(value);
	value = upnp_get_string(event, "NextURIMetaData");
	if (value == NULL) {
		rc = -1;
	} else {
		change_var_and_notify(TRANSPORT_VAR_NEXT_AV_URI_META, value);
		free(value);
	}

	service_unlock();

	LEAVE();
	return rc;
}
static int stop(struct action_event *event)
{
	ENTER();

	if (obtain_instanceid(event, NULL)) {
		return -1;
	}

	service_lock();
	switch (transport_state_) {
	case TRANSPORT_STOPPED:
		// For clients that didn't get it.
		change_and_notify_transport(TRANSPORT_STOPPED);
		break;
	case TRANSPORT_PLAYING:
	case TRANSPORT_TRANSITIONING:
	case TRANSPORT_PAUSED_RECORDING:
	case TRANSPORT_RECORDING:
	case TRANSPORT_PAUSED_PLAYBACK:
		output_stop();
		change_and_notify_transport(TRANSPORT_STOPPED);
		// Set TransportPlaySpeed to '1'
		break;

	case TRANSPORT_NO_MEDIA_PRESENT:
		/* action not allowed in these states - error 701 */
		upnp_set_error(event, UPNP_TRANSPORT_E_TRANSITION_NA,
			       "Transition not allowed");

		break;
	}
	service_unlock();

	LEAVE();

	return 0;
}
Esempio n. 29
0
static DWORD service_wait_for_startup(struct service_entry *service_entry, HANDLE process_handle)
{
    WINE_TRACE("%p\n", service_entry);

    for (;;)
    {
        DWORD dwCurrentStatus;
        HANDLE handles[2] = { service_entry->status_changed_event, process_handle };
        DWORD ret;
        ret = WaitForMultipleObjects(sizeof(handles)/sizeof(handles[0]), handles, FALSE, 20000);
        if (ret != WAIT_OBJECT_0)
            return ERROR_SERVICE_REQUEST_TIMEOUT;
        service_lock_shared(service_entry);
        dwCurrentStatus = service_entry->status.dwCurrentState;
        service_unlock(service_entry);
        if (dwCurrentStatus == SERVICE_RUNNING)
        {
            WINE_TRACE("Service started successfully\n");
            return ERROR_SUCCESS;
        }
        if (dwCurrentStatus != SERVICE_START_PENDING)
            return ERROR_SERVICE_REQUEST_TIMEOUT;
    }
}
Esempio n. 30
0
static DWORD service_start_process(struct service_entry *service_entry, HANDLE *process)
{
    PROCESS_INFORMATION pi;
    STARTUPINFOW si;
    LPWSTR path = NULL;
    DWORD size;
    BOOL r;

    service_lock_exclusive(service_entry);

    if (!env)
    {
        HANDLE htok;

        if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY|TOKEN_DUPLICATE, &htok))
            CreateEnvironmentBlock(&env, htok, FALSE);

        if (!env)
            WINE_ERR("failed to create services environment\n");
    }

    size = ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,NULL,0);
    path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
    if (!path)
    {
        service_unlock(service_entry);
        return ERROR_NOT_ENOUGH_SERVER_MEMORY;
    }
    ExpandEnvironmentStringsW(service_entry->config.lpBinaryPathName,path,size);

    if (service_entry->config.dwServiceType == SERVICE_KERNEL_DRIVER)
    {
        static const WCHAR winedeviceW[] = {'\\','w','i','n','e','d','e','v','i','c','e','.','e','x','e',' ',0};
        WCHAR system_dir[MAX_PATH];
        DWORD type, len;

        GetSystemDirectoryW( system_dir, MAX_PATH );
        if (is_win64)
        {
            if (!GetBinaryTypeW( path, &type ))
            {
                HeapFree( GetProcessHeap(), 0, path );
                service_unlock(service_entry);
                return GetLastError();
            }
            if (type == SCS_32BIT_BINARY) GetSystemWow64DirectoryW( system_dir, MAX_PATH );
        }

        len = strlenW( system_dir ) + sizeof(winedeviceW)/sizeof(WCHAR) + strlenW(service_entry->name);
        HeapFree( GetProcessHeap(), 0, path );
        if (!(path = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
        {
            service_unlock(service_entry);
            return ERROR_NOT_ENOUGH_SERVER_MEMORY;
        }
        lstrcpyW( path, system_dir );
        lstrcatW( path, winedeviceW );
        lstrcatW( path, service_entry->name );
    }

    ZeroMemory(&si, sizeof(STARTUPINFOW));
    si.cb = sizeof(STARTUPINFOW);
    if (!(service_entry->config.dwServiceType & SERVICE_INTERACTIVE_PROCESS))
    {
        static WCHAR desktopW[] = {'_','_','w','i','n','e','s','e','r','v','i','c','e','_','w','i','n','s','t','a','t','i','o','n','\\','D','e','f','a','u','l','t',0};
        si.lpDesktop = desktopW;
    }

    service_entry->status.dwCurrentState = SERVICE_START_PENDING;

    service_unlock(service_entry);

    r = CreateProcessW(NULL, path, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, env, NULL, &si, &pi);
    HeapFree(GetProcessHeap(),0,path);
    if (!r)
    {
        service_lock_exclusive(service_entry);
        service_entry->status.dwCurrentState = SERVICE_STOPPED;
        service_unlock(service_entry);
        return GetLastError();
    }

    service_entry->status.dwProcessId = pi.dwProcessId;
    service_entry->process = pi.hProcess;
    *process = pi.hProcess;
    CloseHandle( pi.hThread );

    return ERROR_SUCCESS;
}