Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

284 lines
9.1 KiB

/*
* OPREQ.C
*
* RSM Service : Operator Requests
*
* Author: ErvinP
*
* (c) 2001 Microsoft Corporation
*
*/
#include <windows.h>
#include <stdlib.h>
#include <wtypes.h>
#include <objbase.h>
#include <ntmsapi.h>
#include "internal.h"
#include "resource.h"
#include "debug.h"
OPERATOR_REQUEST *NewOperatorRequest( DWORD dwRequest,
LPCWSTR lpMessage,
LPNTMS_GUID lpArg1Id,
LPNTMS_GUID lpArg2Id)
{
OPERATOR_REQUEST *newOpReq;
newOpReq = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, sizeof(OPERATOR_REQUEST));
if (newOpReq){
newOpReq->completedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (newOpReq->completedEvent){
InitializeListHead(&newOpReq->sessionOpReqsListEntry);
newOpReq->opRequestCommand = dwRequest;
newOpReq->state = NTMS_OPSTATE_UNKNOWN;
WStrNCpy((WCHAR *)newOpReq->appMessage, (WCHAR *)lpMessage, sizeof(newOpReq->appMessage)/sizeof(WCHAR));
memcpy(&newOpReq->arg1Guid, lpArg1Id, sizeof(NTMS_GUID));
memcpy(&newOpReq->arg2Guid, lpArg2Id, sizeof(NTMS_GUID));
#if 0 // BUGBUG - do this in RSM Monitor app ?
/*
* Initialize the NOTIFYICONDATA structure
* for the message display (used in the Shell_NotifyIcon call).
* Make it hidden initially.
* BUGBUG - make this work with RSM monitor (need hWnd and callback msg id)
*/
newOpReq->notifyData.cbSize = sizeof(NOTIFYICONDATA);
newOpReq->notifyData.hWnd = NULL;
newOpReq->notifyData.uID = (ULONG_PTR)newOpReq;
newOpReq->notifyData.uFlags = NIF_ICON | NIF_TIP | NIF_STATE;
newOpReq->notifyData.uCallbackMessage = 0;
newOpReq->notifyData.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_OPREQ_ICON));
LoadString(g_hInstanceMonitor, IDS_OPTIP, newOpReq->notifyData.szTip, sizeof(newOpReq->notifyData.szTip)/sizeof(TCHAR));
newOpReq->notifyData.dwState = NIS_HIDDEN;
newOpReq->notifyData.dwStateMask = NIS_HIDDEN;
LoadString(g_hInstanceMonitor, IDS_OPINFO, newOpReq->notifyData.szInfo, sizeof(newOpReq->notifyData.szInfo)/sizeof(TCHAR));
newOpReq->notifyData.uTimeout = 60000; // 1 minute
LoadString(g_hInstanceMonitor, IDS_OPTIP, newOpReq->notifyData.szInfoTitle, sizeof(newOpReq->notifyData.szInfoTitle)/sizeof(TCHAR));
newOpReq->notifyData.dwInfoFlags = NIIF_INFO;
Shell_NotifyIcon(NIM_ADD, &newOpReq->notifyData);
#endif
/*
* Create a unique identifier for this op request
*/
CoCreateGuid(&newOpReq->opReqGuid);
}
else {
FreeOperatorRequest(newOpReq);
newOpReq = NULL;
}
}
ASSERT(newOpReq);
return newOpReq;
}
VOID FreeOperatorRequest(OPERATOR_REQUEST *opReq)
{
ASSERT(IsListEmpty(&opReq->sessionOpReqsListEntry));
if (opReq->completedEvent) CloseHandle(opReq->completedEvent);
// BUGBUG ? if (opReq->notifyData.hIcon) DestroyIcon(opReq->notifyData.hIcon);
GlobalFree(opReq);
}
BOOL EnqueueOperatorRequest(SESSION *thisSession, OPERATOR_REQUEST *opReq)
{
DWORD threadId;
BOOL ok = FALSE;
#if 0 // BUGBUG - do this in RSM Monitor app ?
/*
* Make the notification display visible on the tray
*/
newOpReq->notifyData.uFlags = NIF_MESSAGE | NIF_INFO | NIF_STATE;
newOpReq->notifyData.dwState = 0;
newOpReq->notifyData.uTimeout = 60000; // 1 minute
Shell_NotifyIcon(NIM_MODIFY, &newOpReq->notifyData);
#endif
// BUGBUG FINISH - make rsm monitor put up dialog UI for op req msg
opReq->invokingSession = thisSession;
GetSystemTime(&opReq->timeSubmitted);
EnterCriticalSection(&thisSession->lock);
// BUGBUG - I don't think we need an op request thread
opReq->hThread = CreateThread(NULL, 0, OperatorRequestThread, opReq, 0, &threadId);
if (opReq->hThread){
InsertTailList(&thisSession->operatorRequestList, &opReq->sessionOpReqsListEntry);
opReq->state = NTMS_OPSTATE_SUBMITTED;
ok = TRUE;
}
else {
ASSERT(opReq->hThread);
}
LeaveCriticalSection(&thisSession->lock);
return ok;
}
/*
* DequeueOperatorRequest
*
* Callable 3 ways:
* dequeue given op request (specificOpReq non-null)
* dequeue op request with given GUID (specificOpReqGuid non-null)
* dequeue first op request (both NULL)
*/
OPERATOR_REQUEST *DequeueOperatorRequest( SESSION *thisSession,
OPERATOR_REQUEST *specificOpReq,
LPNTMS_GUID specificOpReqGuid)
{
OPERATOR_REQUEST *opReq;
LIST_ENTRY *listEntry;
/*
* If an op request is passed in, dequeue that one.
* Else, dequeue the first.
*/
EnterCriticalSection(&thisSession->lock);
if (specificOpReq){
ASSERT(!IsListEmpty(&specificOpReq->sessionOpReqsListEntry));
ASSERT(!IsListEmpty(&thisSession->operatorRequestList));
RemoveEntryList(&specificOpReq->sessionOpReqsListEntry);
InitializeListHead(&specificOpReq->sessionOpReqsListEntry);
opReq = specificOpReq;
}
else if (specificOpReqGuid){
opReq = FindOperatorRequest(thisSession, specificOpReqGuid);
if (opReq){
RemoveEntryList(&opReq->sessionOpReqsListEntry);
}
}
else {
if (IsListEmpty(&thisSession->operatorRequestList)){
opReq = NULL;
}
else {
listEntry = RemoveHeadList(&thisSession->operatorRequestList);
opReq = CONTAINING_RECORD(listEntry, OPERATOR_REQUEST, sessionOpReqsListEntry);
}
}
LeaveCriticalSection(&thisSession->lock);
return opReq;
}
/*
* FindOperatorRequest
*
* ** Must be called with session lock held
*/
OPERATOR_REQUEST *FindOperatorRequest(SESSION *thisSession, LPNTMS_GUID opReqGuid)
{
OPERATOR_REQUEST *opReq = NULL;
LIST_ENTRY *listEntry;
listEntry = &thisSession->operatorRequestList;
while ((listEntry = listEntry->Flink) != &thisSession->operatorRequestList){
OPERATOR_REQUEST *thisOpReq = CONTAINING_RECORD(listEntry, OPERATOR_REQUEST, sessionOpReqsListEntry);
if (RtlEqualMemory(&thisOpReq->opReqGuid, opReqGuid, sizeof(NTMS_GUID))){
opReq = thisOpReq;
break;
}
}
return opReq;
}
/*
* CompleteOperatorRequest
*
* Complete and free the op request, synchronizing with any threads
* waiting on its completion.
*/
HRESULT CompleteOperatorRequest( SESSION *thisSession,
LPNTMS_GUID lpRequestId,
enum NtmsOpreqState completeState)
{
HRESULT result;
if (lpRequestId){
OPERATOR_REQUEST *opReq;
opReq = DequeueOperatorRequest(thisSession, NULL, lpRequestId);
if (opReq){
/*
* Remove the notification display from the tray
*/
// BUGBUG - do this in RSM Monitor app ?
// Shell_NotifyIcon(NIM_DELETE, &opReq->notifyData);
/*
* Make sure there are no threads waiting on the
* operator request before freeing it.
*/
EnterCriticalSection(&thisSession->lock);
/*
* Kill the op request thread
*/
TerminateThread(opReq->hThread, ERROR_SUCCESS);
CloseHandle(opReq->hThread);
/*
* There may be some threads waiting in WaitForNtmsOperatorRequest
* for this op request to complete. Need to flush them
* before freeing the op request.
*/
opReq->state = completeState;
SetEvent(opReq->completedEvent);
/*
* Drop the lock and wait for the waiting threads to exit.
*/
while (opReq->numWaitingThreads > 0){
LeaveCriticalSection(&thisSession->lock);
Sleep(1);
EnterCriticalSection(&thisSession->lock);
}
LeaveCriticalSection(&thisSession->lock);
FreeOperatorRequest(opReq);
result = ERROR_SUCCESS;
}
else {
result = ERROR_OBJECT_NOT_FOUND;
}
}
else {
ASSERT(lpRequestId);
result = ERROR_INVALID_PARAMETER;
}
return result;
}
// BUGBUG - I don't think we need an op request thread
DWORD __stdcall OperatorRequestThread(void *context)
{
OPERATOR_REQUEST *opReq = (OPERATOR_REQUEST *)context;
return NO_ERROR;
}