I've got just a few loose ends to tie up about our new security off behavior, and then we'll move on to other topics.

System.Security.SecurityManager.SecurityEnabled

As part of the work to move to the new security off model, we've removed the ability to turn off security pragmatically through the SecurityEnabled property of the SecurityManager object.  The getter will still tell you the current state of the security system, however the setter was turned into a no-op.

By making the decision to make the property setter into a no-op, the symptom that a broken application will see is that a SecurityException will be thrown in a location that was likely not built with handling that exception in mind.  As a temporary fix, while running the application, you can also run CasPol in the background to create the environment that the application expects to run in.  Of course, as a long term solution, the application should be modified to work with the security system on.  We could have chosen to throw a NotImplementedException whenever the setter was accessed, but breaking in that way prevents the caspol workaround since the application will still throw an unhandled exception. 

Security On For Win9x

Last time I showed how you could use Windows NT security to prevent security from ever being turned off.  Of course using Windows NT's security model requires, well, Windows NT.  To achieve the same effect on Windows 98 or Windows ME we'll have to take a different route.

The goal is still the same -- prevent CasPol from acquiring the security off mutex while keeping that object in a state that the CLR doesn't recognize it as valid for turning off security.  Since we can't acquire an ACL on the mutex, we'll need to come up with another way to prevent it from being acquired in the first place.  One way falls out from the fact that in Windows mutexes, events, semaphores, waitable timers, job, and file mapping objects all share the same namespace.  This means that no two of those types of objects can have the same name.  So, if we pick one of those available on Win9x ... say an event, we can prevent CasPol from creating a mutex with the same name.  And since we won't be holding a mutex with the security off name, the CLR won't disable security.

int _tmain()
{
    // create a security off event
    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, _T("CLR_CASOFF_MUTEX"));
    if(hEvent == NULL)
    {
        std::cout << "Could not acquire event, security may already be off." << std::endl;
        return 0;
    }
    
    // wait to unlock
    std::cout << "Security is locked on.  Press any key to unlock." << std::endl;
    _getch();

    CloseHandle(hEvent);
    return 0;
}