Locking the SCM s Database

[Previous] [Next]

If you find yourself making several changes to services in the SCM's database, you might want to temporarily stop the SCM from starting any services by obtaining the SCM's lock. A good time to obtain the lock is when you want to query a service's configuration and then change it "atomically." Locking the SCM might also be useful when the service is dependent on other services. To prevent the SCM from starting any more services, call the LockServiceDatabase function, passing it the handle returned from a call to OpenSCManager by using the SC_MANAGER_LOCK access:

 SC_LOCK LockServiceDatabase(SC_HANDLE hSCManager); 

The LockServiceDatabase function returns a value that identifies the lock. Hold on to this value because you'll need to pass it to UnlockServiceDatabase when you wish to release the lock:

 BOOL UnlockServiceDatabase(SC_LOCK scLock); 

Only one process at a time can own the SCM's lock, and of course, you should own the lock for as short a time as possible. If the process that owns the lock terminates, the SCM automatically reclaims the lock so that services can start again.

Note that the lock is not automatically released if you close the handle to the SCM. Consider this example:

SC_HANDLE hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_LOCK); // Lock the SCM's database SC_LOCK scLock = LockServiceDatabase(hSCM); CloseServiceHandle(hSCM); // NOTE: The database is still locked  UnlockServiceDatabase(scLock); // The database is now unlocked 

The QueryServiceLockStatus function returns information that allows you to see the status of the SCM's lock:

 BOOL QueryServiceLockStatus(    SC_HANDLE                  hSCManager,    QUERY_SERVICE_LOCK_STATUS* pqsls,    DWORD                      dwBufSize,    PDWORD                     pdwBytesNeeded); 

If the SCM is locked, the function also returns which user account owns the lock and how long the lock has been owned. All this information is returned via a QUERY_SERVICE_LOCK_STATUS structure:

 typedef struct _QUERY_SERVICE_LOCK_STATUS {    DWORD  fIsLocked;    PTSTR  lpLockOwner;    DWORD  dwLockDuration; } QUERY_SERVICE_LOCK_STATUS, *LPQUERY_SERVICE_LOCK_STATUS; 

As with the QueryServiceConfig function, the buffer that you pass to QueryServiceLockStatus must actually be larger than the size of the structure. Again, this is because the structure contains a string value (lpLockOwner) that will be copied into the buffer immediately after the fixed-size structure.



Programming Server-Side Applications for Microsoft Windows 2000
Programming Server-Side Applications for Microsoft Windows 2000 (Microsoft Programming)
ISBN: 0735607532
EAN: 2147483647
Year: 2000
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net