Source code of Windows XP (NT5)
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.

397 lines
9.9 KiB

  1. /*****************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990 **/
  4. /*****************************************************************/
  5. // data.c
  6. //
  7. // This file contains most of the data declarations and set up routines
  8. // used by the messenger service.
  9. //
  10. //
  11. // Revision History:
  12. // 02-Sep-1993 wlees
  13. // Provide synchronization between rpc routines and Pnp reconfiguration
  14. #include "msrv.h" // Message server declarations
  15. #include <rpc.h> // RPC_HANDLE
  16. #include <winsvc.h> // Defines for using service API
  17. #include <smbtypes.h> // needed for smb.h
  18. #include <smb.h> // Server Message Block definition
  19. #include <netlib.h> // UNUSED macro
  20. #include <align.h> // ROUND_UP_POINTER
  21. #include "msgdbg.h" // MSG_LOG
  22. #include <svcs.h> // Intrinsic service data
  23. GLOBAL_DATA GlobalData;
  24. HANDLE wakeupEvent = 0; // Master copy of wakeup event
  25. HANDLE GrpMailslotHandle = INVALID_HANDLE_VALUE; // Event to signal mailslot has data
  26. PHANDLE wakeupSem; // Semaphores to clear on NCB completion
  27. //
  28. // Other Global Data
  29. //
  30. // The other misc. global data that the messenger uses.
  31. //
  32. DWORD MsgsvcDebugLevel; // Debug level flag used by MSG_LOG
  33. LPTSTR MessageFileName;
  34. //
  35. // The local machine name and length/
  36. //
  37. TCHAR machineName[NCBNAMSZ+sizeof(TCHAR)];
  38. SHORT MachineNameLen;
  39. SHORT mgid; // The message group i.d. counter
  40. //
  41. // The following is used to keep store the state of the messenger service
  42. // Either it is RUNNING or STOPPING.
  43. //
  44. DWORD MsgrState;
  45. //
  46. // Handle returned by RegisterServiceCtrlHandle and needed to
  47. // set the service status via SetServiceStatus
  48. //
  49. SERVICE_STATUS_HANDLE MsgrStatusHandle;
  50. //
  51. // This string is used to mark the location of the time string in
  52. // a message header so that the display thread can find after it reads
  53. // it from the queue.
  54. //
  55. LPSTR GlobalTimePlaceHolder = "***";
  56. LPWSTR GlobalTimePlaceHolderUnicode = L"***";
  57. //
  58. // This is the string used in the title bar of the Message Box used
  59. // to display messages.
  60. // GlobalMessageBoxTitle will either point to the default string, or
  61. // to the string allocated in the FormatMessage Function.
  62. //
  63. WCHAR DefaultMessageBoxTitle[]= L"Messenger Service";
  64. LPWSTR GlobalAllocatedMsgTitle=NULL;
  65. LPWSTR GlobalMessageBoxTitle=DefaultMessageBoxTitle;
  66. //
  67. // This is where well-known SIDs and pointers to RpcServer routines are
  68. // stored.
  69. //
  70. PSVCHOST_GLOBAL_DATA MsgsvcGlobalData;
  71. //
  72. // Functions
  73. //
  74. // The following routines are defined for creating and destroying the
  75. // data (arrays, etc.) defined above.
  76. //
  77. /* MsgInitSupportSeg
  78. *
  79. * Allocates and initializes the segment containing the Support
  80. * arrays.
  81. *
  82. */
  83. NET_API_STATUS
  84. MsgInitSupportSeg(VOID)
  85. {
  86. unsigned int size;
  87. DWORD i;
  88. char far * memPtr;
  89. DWORD status;
  90. //
  91. // Calculate the buffer size.
  92. // *ALIGNMENT* (Note the extra four bytes for alignment)
  93. //
  94. size = ((SD_NUMNETS() + 1) * sizeof(HANDLE));
  95. wakeupSem = (PHANDLE) LocalAlloc(LMEM_ZEROINIT, size);
  96. if (wakeupSem == NULL) {
  97. status = GetLastError();
  98. MSG_LOG(ERROR,"[MSG]InitSupportSeg:LocalAlloc Failure %X\n", status);
  99. return(status);
  100. }
  101. return (NERR_Success);
  102. }
  103. VOID
  104. MsgFreeSupportSeg(VOID)
  105. {
  106. HANDLE status;
  107. status = LocalFree (wakeupSem);
  108. if (status != 0) {
  109. MSG_LOG(ERROR,"FreeSupportSeg:LocalFree Failed %X\n",
  110. GetLastError());
  111. }
  112. wakeupSem = NULL;
  113. return;
  114. }
  115. BOOL
  116. MsgDatabaseLock(
  117. IN MSG_LOCK_REQUEST request,
  118. IN LPSTR idString
  119. )
  120. /*++
  121. Routine Description:
  122. This routine handles all access to the Messenger Service database
  123. lock. This lock is used to protect access in the shared data segment.
  124. Reading the Database is handled with shared access. This allows several
  125. threads to read the database at the same time.
  126. Writing (or modifying) the database is handled with exclusive access.
  127. This access is not granted if other threads have read access. However,
  128. shared access can be made into exclusive access as long as no other
  129. threads have shared or exclusive access.
  130. Arguments:
  131. request - This indicates what should be done with the lock. Lock
  132. requests are listed in dataman.h
  133. idString - This is a string that identifies who is requesting the lock.
  134. This is used for debugging purposes so I can see where in the code
  135. a request is coming from.
  136. Return Value:
  137. none:
  138. --*/
  139. {
  140. BOOL fRet = TRUE;
  141. NTSTATUS status;
  142. static RTL_RESOURCE MSG_DatabaseLock;
  143. static BOOL s_fInitialized;
  144. switch(request) {
  145. case MSG_INITIALIZE:
  146. if (!s_fInitialized)
  147. {
  148. status = MsgInitResource(&MSG_DatabaseLock);
  149. if (!NT_SUCCESS(status))
  150. {
  151. MSG_LOG1(ERROR,
  152. "MsgDatabaseLock: MsgInitResource failed %#x\n",
  153. status);
  154. fRet = FALSE;
  155. }
  156. else
  157. {
  158. s_fInitialized = TRUE;
  159. }
  160. }
  161. break;
  162. case MSG_GET_SHARED:
  163. MSG_LOG(LOCKS,"%s:Asking for MSG Database Lock shared...\n",idString);
  164. fRet = RtlAcquireResourceShared( &MSG_DatabaseLock, TRUE );
  165. MSG_LOG(LOCKS,"%s:Acquired MSG Database Lock shared\n",idString);
  166. break;
  167. case MSG_GET_EXCLUSIVE:
  168. MSG_LOG(LOCKS,"%s:Asking for MSG Database Lock exclusive...\n",idString);
  169. fRet = RtlAcquireResourceExclusive( &MSG_DatabaseLock, TRUE );
  170. MSG_LOG(LOCKS,"%s:Acquired MSG Database Lock exclusive\n",idString);
  171. break;
  172. case MSG_RELEASE:
  173. MSG_LOG(LOCKS,"%s:Releasing MSG Database Lock...\n",idString);
  174. RtlReleaseResource( &MSG_DatabaseLock );
  175. MSG_LOG(LOCKS,"%s:Released MSG Database Lock\n",idString);
  176. break;
  177. default:
  178. break;
  179. }
  180. return fRet;
  181. }
  182. BOOL
  183. MsgConfigurationLock(
  184. IN MSG_LOCK_REQUEST request,
  185. IN LPSTR idString
  186. )
  187. /*++
  188. Routine Description:
  189. This routine handles all access to the Messenger Service Pnp Configuration
  190. lock. This lock is used to protect access in the shared data segment.
  191. Reading the Database is handled with shared access. This allows several
  192. threads to read the database at the same time.
  193. Writing (or modifying) the database is handled with exclusive access.
  194. This access is not granted if other threads have read access. However,
  195. shared access can be made into exclusive access as long as no other
  196. threads have shared or exclusive access.
  197. Arguments:
  198. request - This indicates what should be done with the lock. Lock
  199. requests are listed in dataman.h
  200. idString - This is a string that identifies who is requesting the lock.
  201. This is used for debugging purposes so I can see where in the code
  202. a request is coming from.
  203. Return Value:
  204. none:
  205. --*/
  206. {
  207. BOOL fRet = TRUE;
  208. NTSTATUS status;
  209. static RTL_RESOURCE MSG_ConfigurationLock;
  210. static BOOL s_fInitialized;
  211. switch(request) {
  212. case MSG_INITIALIZE:
  213. if (!s_fInitialized)
  214. {
  215. status = MsgInitResource(&MSG_ConfigurationLock);
  216. if (!NT_SUCCESS(status))
  217. {
  218. MSG_LOG1(ERROR,
  219. "MsgConfigurationLock: MsgInitResource failed %#x\n",
  220. status);
  221. fRet = FALSE;
  222. }
  223. else
  224. {
  225. s_fInitialized = TRUE;
  226. }
  227. }
  228. break;
  229. case MSG_GET_SHARED:
  230. MSG_LOG(LOCKS,"%s:Asking for MSG Configuration Lock shared...\n",idString);
  231. fRet = RtlAcquireResourceShared( &MSG_ConfigurationLock, TRUE );
  232. MSG_LOG(LOCKS,"%s:Acquired MSG Configuration Lock shared\n",idString);
  233. break;
  234. case MSG_GET_EXCLUSIVE:
  235. MSG_LOG(LOCKS,"%s:Asking for MSG Configuration Lock exclusive...\n",idString);
  236. fRet = RtlAcquireResourceExclusive( &MSG_ConfigurationLock, TRUE );
  237. MSG_LOG(LOCKS,"%s:Acquired MSG Configuration Lock exclusive\n",idString);
  238. break;
  239. case MSG_RELEASE:
  240. MSG_LOG(LOCKS,"%s:Releasing MSG Configuration Lock...\n",idString);
  241. RtlReleaseResource( &MSG_ConfigurationLock );
  242. MSG_LOG(LOCKS,"%s:Released MSG Configuration Lock\n",idString);
  243. break;
  244. default:
  245. break;
  246. }
  247. return fRet;
  248. }
  249. NTSTATUS
  250. MsgInitCriticalSection(
  251. PRTL_CRITICAL_SECTION pCritsec
  252. )
  253. {
  254. NTSTATUS ntStatus;
  255. //
  256. // RtlInitializeCriticalSection will raise an exception
  257. // if it runs out of resources
  258. //
  259. try
  260. {
  261. ntStatus = RtlInitializeCriticalSection(pCritsec);
  262. if (!NT_SUCCESS(ntStatus))
  263. {
  264. MSG_LOG1(ERROR,
  265. "MsgInitCriticalSection: RtlInitializeCriticalSection failed %#x\n",
  266. ntStatus);
  267. }
  268. }
  269. except(EXCEPTION_EXECUTE_HANDLER)
  270. {
  271. MSG_LOG1(ERROR,
  272. "MsgInitCriticalSection: Exception %#x caught initializing critsec\n",
  273. GetExceptionCode());
  274. ntStatus = STATUS_NO_MEMORY;
  275. }
  276. return ntStatus;
  277. }
  278. NTSTATUS
  279. MsgInitResource(
  280. PRTL_RESOURCE pResource
  281. )
  282. {
  283. NTSTATUS ntStatus = STATUS_SUCCESS;
  284. //
  285. // RtlInitializeResource will raise an exception
  286. // if it runs out of resources
  287. //
  288. try
  289. {
  290. RtlInitializeResource(pResource);
  291. }
  292. except(EXCEPTION_EXECUTE_HANDLER)
  293. {
  294. MSG_LOG1(ERROR,
  295. "MsgInitResource: Exception %#x caught initializing resource\n",
  296. GetExceptionCode());
  297. ntStatus = STATUS_NO_MEMORY;
  298. }
  299. return ntStatus;
  300. }