John
John

Reputation: 6668

Need to synchronize Windows Service with non-admin user process

I am using a (.NET2.0) service to periodically carry out privileged actions and return the result to shared memory, via IPC, with a non-admin user's (.NET2.0) process.

I have been using globally named mutexes while developing from my administrator account but when I come to try the application on a limited account I get the error:

Additional information: Access to the path 'Global\timersyncu33sc3c2sd42frandomlynamedmutexoijfvgf9v3f32' is denied.

Is there some other way a non-privileged user can interact with a Service? Or should I just share the period of polling and update time and hope those values get written/read atomically?

Upvotes: 0

Views: 476

Answers (2)

John
John

Reputation: 6668

I found the following method of granting access to my limited users as they log on and fire up their GUI. Note the function getUsername(/*somehow*/); had several incarnations and I'm not listing the implementation that worked on XP, I'm sure there are other ways though 3 of the 4 I found didn't work for me.

void grantMutexToCurUser(Mutex ^%fpMutex) {
    try {
        fpMutex = Mutex::OpenExisting( ServerGUIBridge::NAMEDMUTEXFORTIMERSYNC,
            static_cast<MutexRights>(
            MutexRights::ReadPermissions | MutexRights::ChangePermissions) );

        MutexSecurity^ mSec = fpMutex->GetAccessControl();
        String^ user;

        try {
            user = getUsername(/*somehow*/);
            Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Granting mutex access to: " 
                + user , "grantMutexToCurUser" );
        } catch (Exception ^ex) {
            Trace::WriteLine( "getUsername: " + ex->Message, "grantMutexToCurUser" );
        }

        // First, the rule that denied the current user the right to enter and
        // release the mutex must be removed.
        MutexAccessRule^ rule = gcnew MutexAccessRule( user,
            static_cast<MutexRights>(MutexRights::Synchronize
            | MutexRights::Modify), AccessControlType::Deny );
        mSec->RemoveAccessRule( rule );

        // Now grant the user the correct rights.
        rule = gcnew MutexAccessRule( user,
            static_cast<MutexRights>(MutexRights::Synchronize
            | MutexRights::Modify), AccessControlType::Allow );
        mSec->AddAccessRule( rule );

        fpMutex->SetAccessControl( mSec );

        // Open the mutex with (MutexRights.Synchronize | MutexRights.Modify), the
        // rights required to enter and release the mutex.
        fpMutex = Mutex::OpenExisting( ewfmon::ServerGUIBridge::NAMEDMUTEXFORTIMERSYNC );
        //noThrowRelease(fpMutex);
    }
    catch ( UnauthorizedAccessException^ ex ) 
    {
        Trace::WriteLine( DateTime::Now.ToLongTimeString() + " - Unable to change permissions: "
            + ex->Message, "grantMutexToCurUser" );
    }
}

Upvotes: 0

Muhammad Hasan Khan
Muhammad Hasan Khan

Reputation: 35146

I would talk to the service using WCF. This eliminates the privileges/identity problem. However since your code is in .NET 2.0 you could use Remoting or NamedPipes to talk to the service.

Upvotes: 1

Related Questions