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

  1. /*
  2. * OPREQ.C
  3. *
  4. * RSM Service : Operator Requests
  5. *
  6. * Author: ErvinP
  7. *
  8. * (c) 2001 Microsoft Corporation
  9. *
  10. */
  11. #include <windows.h>
  12. #include <stdlib.h>
  13. #include <wtypes.h>
  14. #include <objbase.h>
  15. #include <ntmsapi.h>
  16. #include "internal.h"
  17. #include "resource.h"
  18. #include "debug.h"
  19. OPERATOR_REQUEST *NewOperatorRequest( DWORD dwRequest,
  20. LPCWSTR lpMessage,
  21. LPNTMS_GUID lpArg1Id,
  22. LPNTMS_GUID lpArg2Id)
  23. {
  24. OPERATOR_REQUEST *newOpReq;
  25. newOpReq = GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, sizeof(OPERATOR_REQUEST));
  26. if (newOpReq){
  27. newOpReq->completedEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  28. if (newOpReq->completedEvent){
  29. InitializeListHead(&newOpReq->sessionOpReqsListEntry);
  30. newOpReq->opRequestCommand = dwRequest;
  31. newOpReq->state = NTMS_OPSTATE_UNKNOWN;
  32. WStrNCpy((WCHAR *)newOpReq->appMessage, (WCHAR *)lpMessage, sizeof(newOpReq->appMessage)/sizeof(WCHAR));
  33. memcpy(&newOpReq->arg1Guid, lpArg1Id, sizeof(NTMS_GUID));
  34. memcpy(&newOpReq->arg2Guid, lpArg2Id, sizeof(NTMS_GUID));
  35. #if 0 // BUGBUG - do this in RSM Monitor app ?
  36. /*
  37. * Initialize the NOTIFYICONDATA structure
  38. * for the message display (used in the Shell_NotifyIcon call).
  39. * Make it hidden initially.
  40. * BUGBUG - make this work with RSM monitor (need hWnd and callback msg id)
  41. */
  42. newOpReq->notifyData.cbSize = sizeof(NOTIFYICONDATA);
  43. newOpReq->notifyData.hWnd = NULL;
  44. newOpReq->notifyData.uID = (ULONG_PTR)newOpReq;
  45. newOpReq->notifyData.uFlags = NIF_ICON | NIF_TIP | NIF_STATE;
  46. newOpReq->notifyData.uCallbackMessage = 0;
  47. newOpReq->notifyData.hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_OPREQ_ICON));
  48. LoadString(g_hInstanceMonitor, IDS_OPTIP, newOpReq->notifyData.szTip, sizeof(newOpReq->notifyData.szTip)/sizeof(TCHAR));
  49. newOpReq->notifyData.dwState = NIS_HIDDEN;
  50. newOpReq->notifyData.dwStateMask = NIS_HIDDEN;
  51. LoadString(g_hInstanceMonitor, IDS_OPINFO, newOpReq->notifyData.szInfo, sizeof(newOpReq->notifyData.szInfo)/sizeof(TCHAR));
  52. newOpReq->notifyData.uTimeout = 60000; // 1 minute
  53. LoadString(g_hInstanceMonitor, IDS_OPTIP, newOpReq->notifyData.szInfoTitle, sizeof(newOpReq->notifyData.szInfoTitle)/sizeof(TCHAR));
  54. newOpReq->notifyData.dwInfoFlags = NIIF_INFO;
  55. Shell_NotifyIcon(NIM_ADD, &newOpReq->notifyData);
  56. #endif
  57. /*
  58. * Create a unique identifier for this op request
  59. */
  60. CoCreateGuid(&newOpReq->opReqGuid);
  61. }
  62. else {
  63. FreeOperatorRequest(newOpReq);
  64. newOpReq = NULL;
  65. }
  66. }
  67. ASSERT(newOpReq);
  68. return newOpReq;
  69. }
  70. VOID FreeOperatorRequest(OPERATOR_REQUEST *opReq)
  71. {
  72. ASSERT(IsListEmpty(&opReq->sessionOpReqsListEntry));
  73. if (opReq->completedEvent) CloseHandle(opReq->completedEvent);
  74. // BUGBUG ? if (opReq->notifyData.hIcon) DestroyIcon(opReq->notifyData.hIcon);
  75. GlobalFree(opReq);
  76. }
  77. BOOL EnqueueOperatorRequest(SESSION *thisSession, OPERATOR_REQUEST *opReq)
  78. {
  79. DWORD threadId;
  80. BOOL ok = FALSE;
  81. #if 0 // BUGBUG - do this in RSM Monitor app ?
  82. /*
  83. * Make the notification display visible on the tray
  84. */
  85. newOpReq->notifyData.uFlags = NIF_MESSAGE | NIF_INFO | NIF_STATE;
  86. newOpReq->notifyData.dwState = 0;
  87. newOpReq->notifyData.uTimeout = 60000; // 1 minute
  88. Shell_NotifyIcon(NIM_MODIFY, &newOpReq->notifyData);
  89. #endif
  90. // BUGBUG FINISH - make rsm monitor put up dialog UI for op req msg
  91. opReq->invokingSession = thisSession;
  92. GetSystemTime(&opReq->timeSubmitted);
  93. EnterCriticalSection(&thisSession->lock);
  94. // BUGBUG - I don't think we need an op request thread
  95. opReq->hThread = CreateThread(NULL, 0, OperatorRequestThread, opReq, 0, &threadId);
  96. if (opReq->hThread){
  97. InsertTailList(&thisSession->operatorRequestList, &opReq->sessionOpReqsListEntry);
  98. opReq->state = NTMS_OPSTATE_SUBMITTED;
  99. ok = TRUE;
  100. }
  101. else {
  102. ASSERT(opReq->hThread);
  103. }
  104. LeaveCriticalSection(&thisSession->lock);
  105. return ok;
  106. }
  107. /*
  108. * DequeueOperatorRequest
  109. *
  110. * Callable 3 ways:
  111. * dequeue given op request (specificOpReq non-null)
  112. * dequeue op request with given GUID (specificOpReqGuid non-null)
  113. * dequeue first op request (both NULL)
  114. */
  115. OPERATOR_REQUEST *DequeueOperatorRequest( SESSION *thisSession,
  116. OPERATOR_REQUEST *specificOpReq,
  117. LPNTMS_GUID specificOpReqGuid)
  118. {
  119. OPERATOR_REQUEST *opReq;
  120. LIST_ENTRY *listEntry;
  121. /*
  122. * If an op request is passed in, dequeue that one.
  123. * Else, dequeue the first.
  124. */
  125. EnterCriticalSection(&thisSession->lock);
  126. if (specificOpReq){
  127. ASSERT(!IsListEmpty(&specificOpReq->sessionOpReqsListEntry));
  128. ASSERT(!IsListEmpty(&thisSession->operatorRequestList));
  129. RemoveEntryList(&specificOpReq->sessionOpReqsListEntry);
  130. InitializeListHead(&specificOpReq->sessionOpReqsListEntry);
  131. opReq = specificOpReq;
  132. }
  133. else if (specificOpReqGuid){
  134. opReq = FindOperatorRequest(thisSession, specificOpReqGuid);
  135. if (opReq){
  136. RemoveEntryList(&opReq->sessionOpReqsListEntry);
  137. }
  138. }
  139. else {
  140. if (IsListEmpty(&thisSession->operatorRequestList)){
  141. opReq = NULL;
  142. }
  143. else {
  144. listEntry = RemoveHeadList(&thisSession->operatorRequestList);
  145. opReq = CONTAINING_RECORD(listEntry, OPERATOR_REQUEST, sessionOpReqsListEntry);
  146. }
  147. }
  148. LeaveCriticalSection(&thisSession->lock);
  149. return opReq;
  150. }
  151. /*
  152. * FindOperatorRequest
  153. *
  154. * ** Must be called with session lock held
  155. */
  156. OPERATOR_REQUEST *FindOperatorRequest(SESSION *thisSession, LPNTMS_GUID opReqGuid)
  157. {
  158. OPERATOR_REQUEST *opReq = NULL;
  159. LIST_ENTRY *listEntry;
  160. listEntry = &thisSession->operatorRequestList;
  161. while ((listEntry = listEntry->Flink) != &thisSession->operatorRequestList){
  162. OPERATOR_REQUEST *thisOpReq = CONTAINING_RECORD(listEntry, OPERATOR_REQUEST, sessionOpReqsListEntry);
  163. if (RtlEqualMemory(&thisOpReq->opReqGuid, opReqGuid, sizeof(NTMS_GUID))){
  164. opReq = thisOpReq;
  165. break;
  166. }
  167. }
  168. return opReq;
  169. }
  170. /*
  171. * CompleteOperatorRequest
  172. *
  173. * Complete and free the op request, synchronizing with any threads
  174. * waiting on its completion.
  175. */
  176. HRESULT CompleteOperatorRequest( SESSION *thisSession,
  177. LPNTMS_GUID lpRequestId,
  178. enum NtmsOpreqState completeState)
  179. {
  180. HRESULT result;
  181. if (lpRequestId){
  182. OPERATOR_REQUEST *opReq;
  183. opReq = DequeueOperatorRequest(thisSession, NULL, lpRequestId);
  184. if (opReq){
  185. /*
  186. * Remove the notification display from the tray
  187. */
  188. // BUGBUG - do this in RSM Monitor app ?
  189. // Shell_NotifyIcon(NIM_DELETE, &opReq->notifyData);
  190. /*
  191. * Make sure there are no threads waiting on the
  192. * operator request before freeing it.
  193. */
  194. EnterCriticalSection(&thisSession->lock);
  195. /*
  196. * Kill the op request thread
  197. */
  198. TerminateThread(opReq->hThread, ERROR_SUCCESS);
  199. CloseHandle(opReq->hThread);
  200. /*
  201. * There may be some threads waiting in WaitForNtmsOperatorRequest
  202. * for this op request to complete. Need to flush them
  203. * before freeing the op request.
  204. */
  205. opReq->state = completeState;
  206. SetEvent(opReq->completedEvent);
  207. /*
  208. * Drop the lock and wait for the waiting threads to exit.
  209. */
  210. while (opReq->numWaitingThreads > 0){
  211. LeaveCriticalSection(&thisSession->lock);
  212. Sleep(1);
  213. EnterCriticalSection(&thisSession->lock);
  214. }
  215. LeaveCriticalSection(&thisSession->lock);
  216. FreeOperatorRequest(opReq);
  217. result = ERROR_SUCCESS;
  218. }
  219. else {
  220. result = ERROR_OBJECT_NOT_FOUND;
  221. }
  222. }
  223. else {
  224. ASSERT(lpRequestId);
  225. result = ERROR_INVALID_PARAMETER;
  226. }
  227. return result;
  228. }
  229. // BUGBUG - I don't think we need an op request thread
  230. DWORD __stdcall OperatorRequestThread(void *context)
  231. {
  232. OPERATOR_REQUEST *opReq = (OPERATOR_REQUEST *)context;
  233. return NO_ERROR;
  234. }