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.

780 lines
17 KiB

  1. /*++
  2. Copyright (c) 1994 Microsoft Corporation
  3. Module Name:
  4. server.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) 07-Dec-1994
  8. Revision History:
  9. --*/
  10. #include <stdlib.h>
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <dsgetdc.h>
  16. #include "llsapi.h"
  17. #include "debug.h"
  18. #include "llsutil.h"
  19. #include "llssrv.h"
  20. #include "registry.h"
  21. #include "ntlsapi.h"
  22. #include "mapping.h"
  23. #include "msvctbl.h"
  24. #include "svctbl.h"
  25. #include "purchase.h"
  26. #include "perseat.h"
  27. #include "server.h"
  28. #define NO_LLS_APIS
  29. #include "llsapi.h"
  30. /////////////////////////////////////////////////////////////////////////
  31. /////////////////////////////////////////////////////////////////////////
  32. /////////////////////////////////////////////////////////////////////////
  33. ULONG ServerListSize = 0;
  34. PSERVER_RECORD *ServerList = NULL;
  35. PSERVER_RECORD *ServerTable = NULL;
  36. RTL_RESOURCE ServerListLock;
  37. /////////////////////////////////////////////////////////////////////////
  38. NTSTATUS
  39. ServerListInit()
  40. /*++
  41. Routine Description:
  42. Arguments:
  43. None.
  44. Return Value:
  45. None.
  46. --*/
  47. {
  48. NTSTATUS status = STATUS_SUCCESS;
  49. try
  50. {
  51. RtlInitializeResource(&ServerListLock);
  52. } except(EXCEPTION_EXECUTE_HANDLER ) {
  53. status = GetExceptionCode();
  54. }
  55. if (!NT_SUCCESS(status))
  56. return status;
  57. //
  58. // Add ourself as the first server (master server)
  59. //
  60. RtlEnterCriticalSection(&ConfigInfoLock);
  61. ServerListAdd( ConfigInfo.ComputerName, NULL);
  62. RtlLeaveCriticalSection(&ConfigInfoLock);
  63. LocalServerServiceListUpdate();
  64. return STATUS_SUCCESS;
  65. } // ServerListInit
  66. /////////////////////////////////////////////////////////////////////////
  67. int __cdecl ServerListCompare(const void *arg1, const void *arg2) {
  68. PSERVER_RECORD Svc1, Svc2;
  69. Svc1 = (PSERVER_RECORD) *((PSERVER_RECORD *) arg1);
  70. Svc2 = (PSERVER_RECORD) *((PSERVER_RECORD *) arg2);
  71. return lstrcmpi( Svc1->Name, Svc2->Name );
  72. } // ServerListCompare
  73. /////////////////////////////////////////////////////////////////////////
  74. int __cdecl ServerServiceListCompare(const void *arg1, const void *arg2) {
  75. PSERVER_SERVICE_RECORD Svc1, Svc2;
  76. Svc1 = (PSERVER_SERVICE_RECORD) *((PSERVER_SERVICE_RECORD *) arg1);
  77. Svc2 = (PSERVER_SERVICE_RECORD) *((PSERVER_SERVICE_RECORD *) arg2);
  78. return lstrcmpi( MasterServiceTable[Svc1->Service]->Name, MasterServiceTable[Svc2->Service]->Name );
  79. } // ServerServiceListCompare
  80. /////////////////////////////////////////////////////////////////////////
  81. PSERVER_SERVICE_RECORD
  82. ServerServiceListFind(
  83. LPTSTR Name,
  84. ULONG ServiceTableSize,
  85. PSERVER_SERVICE_RECORD *ServiceList
  86. )
  87. /*++
  88. Routine Description:
  89. Internal routine to actually do binary search on ServerServiceList, this
  90. does not do any locking as we expect the wrapper routine to do this.
  91. The search is a simple binary search.
  92. Arguments:
  93. Return Value:
  94. Pointer to found service table entry or NULL if not found.
  95. --*/
  96. {
  97. LONG begin = 0;
  98. LONG end;
  99. LONG cur;
  100. int match;
  101. PMASTER_SERVICE_RECORD Service;
  102. #if DBG
  103. if (TraceFlags & TRACE_FUNCTION_TRACE)
  104. dprintf(TEXT("LLS TRACE: ServerServiceListFind\n"));
  105. #endif
  106. if (ServiceTableSize == 0)
  107. return NULL;
  108. end = (LONG) ServiceTableSize - 1;
  109. while (end >= begin) {
  110. // go halfway in-between
  111. cur = (begin + end) / 2;
  112. Service = MasterServiceTable[ServiceList[cur]->Service];
  113. // compare the two result into match
  114. match = lstrcmpi(Name, Service->Name);
  115. if (match < 0)
  116. // move new begin
  117. end = cur - 1;
  118. else
  119. begin = cur + 1;
  120. if (match == 0)
  121. return ServiceList[cur];
  122. }
  123. return NULL;
  124. } // ServerServiceListFind
  125. /////////////////////////////////////////////////////////////////////////
  126. PSERVER_RECORD
  127. ServerListFind(
  128. LPTSTR Name
  129. )
  130. /*++
  131. Routine Description:
  132. Internal routine to actually do binary search on ServerList, this
  133. does not do any locking as we expect the wrapper routine to do this.
  134. The search is a simple binary search.
  135. Arguments:
  136. ServiceName -
  137. Return Value:
  138. Pointer to found server table entry or NULL if not found.
  139. --*/
  140. {
  141. LONG begin = 0;
  142. LONG end = (LONG) ServerListSize - 1;
  143. LONG cur;
  144. int match;
  145. PSERVER_RECORD Server;
  146. #if DBG
  147. if (TraceFlags & TRACE_FUNCTION_TRACE)
  148. dprintf(TEXT("LLS TRACE: ServerListFind\n"));
  149. #endif
  150. if ((ServerListSize == 0) || (Name == NULL))
  151. return NULL;
  152. while (end >= begin) {
  153. // go halfway in-between
  154. cur = (begin + end) / 2;
  155. Server = ServerList[cur];
  156. // compare the two result into match
  157. match = lstrcmpi(Name, Server->Name);
  158. if (match < 0)
  159. // move new begin
  160. end = cur - 1;
  161. else
  162. begin = cur + 1;
  163. if (match == 0)
  164. return Server;
  165. }
  166. return NULL;
  167. } // ServerListFind
  168. /////////////////////////////////////////////////////////////////////////
  169. PSERVER_SERVICE_RECORD
  170. ServerServiceListAdd(
  171. LPTSTR Name,
  172. ULONG ServiceIndex,
  173. PULONG pServiceTableSize,
  174. PSERVER_SERVICE_RECORD **pServiceList
  175. )
  176. /*++
  177. Routine Description:
  178. Arguments:
  179. ServiceName -
  180. Return Value:
  181. Pointer to added service table entry, or NULL if failed.
  182. --*/
  183. {
  184. LPTSTR NewName;
  185. PSERVER_SERVICE_RECORD Service = NULL;
  186. PSERVER_SERVICE_RECORD *ServiceList;
  187. ULONG ServiceListSize;
  188. #if DBG
  189. if (TraceFlags & TRACE_FUNCTION_TRACE)
  190. dprintf(TEXT("LLS TRACE: ServerServiceListAdd\n"));
  191. #endif
  192. if ((Name == NULL) || (*Name == TEXT('\0')) || (pServiceTableSize == NULL) || (pServiceList == NULL)) {
  193. #if DBG
  194. dprintf(TEXT("Error LLS: ServerServiceListAdd Bad Parms\n"));
  195. #endif
  196. ASSERT(FALSE);
  197. return NULL;
  198. }
  199. ServiceListSize = *pServiceTableSize;
  200. ServiceList = *pServiceList;
  201. //
  202. // Try to find the name
  203. //
  204. Service = ServerServiceListFind(Name, ServiceListSize, ServiceList);
  205. if (Service != NULL) {
  206. Service->Service = ServiceIndex;
  207. return Service;
  208. }
  209. //
  210. // No record - so create a new one
  211. //
  212. if (ServiceList == NULL) {
  213. ServiceList = (PSERVER_SERVICE_RECORD *) LocalAlloc(LPTR, sizeof(PSERVER_SERVICE_RECORD));
  214. } else {
  215. ServiceList = (PSERVER_SERVICE_RECORD *) LocalReAlloc(ServiceList, sizeof(PSERVER_SERVICE_RECORD) * (ServiceListSize + 1), LHND);
  216. }
  217. //
  218. // Make sure we could allocate server table
  219. //
  220. if (ServiceList == NULL) {
  221. goto ServerServiceListAddExit;
  222. }
  223. //
  224. // Allocate space for Record.
  225. //
  226. Service = (PSERVER_SERVICE_RECORD) LocalAlloc(LPTR, sizeof(SERVER_SERVICE_RECORD));
  227. if (Service == NULL) {
  228. ASSERT(FALSE);
  229. LocalFree(ServiceList);
  230. return NULL;
  231. }
  232. ServiceList[ServiceListSize] = Service;
  233. //
  234. // Initialize other stuff
  235. //
  236. Service->Service = ServiceIndex;
  237. Service->MaxSessionCount = 0;
  238. Service->MaxSetSessionCount = 0;
  239. Service->HighMark = 0;
  240. Service->Flags = 0;
  241. ServiceListSize++;
  242. // Have added the entry - now need to sort it in order of the service names
  243. qsort((void *) ServiceList, (size_t) ServiceListSize, sizeof(PSERVER_SERVICE_RECORD), ServerServiceListCompare);
  244. ServerServiceListAddExit:
  245. if (ServiceList != NULL)
  246. {
  247. *pServiceTableSize = ServiceListSize;
  248. *pServiceList = ServiceList;
  249. }
  250. return Service;
  251. } // ServerServiceListAdd
  252. /////////////////////////////////////////////////////////////////////////
  253. PSERVER_RECORD
  254. ServerListAdd(
  255. LPTSTR Name,
  256. LPTSTR Master
  257. )
  258. /*++
  259. Routine Description:
  260. Arguments:
  261. ServiceName -
  262. Return Value:
  263. Pointer to added service table entry, or NULL if failed.
  264. --*/
  265. {
  266. LPTSTR NewName;
  267. PSERVER_RECORD Server;
  268. PSERVER_RECORD pMaster;
  269. PSERVER_RECORD *pServerListTmp, *pServerTableTmp;
  270. #if DBG
  271. if (TraceFlags & TRACE_FUNCTION_TRACE)
  272. dprintf(TEXT("LLS TRACE: ServerListAdd\n"));
  273. #endif
  274. if ((Name == NULL) || (*Name == TEXT('\0'))) {
  275. #if DBG
  276. dprintf(TEXT("Error LLS: ServerListAdd Bad Parms\n"));
  277. #endif
  278. ASSERT(FALSE);
  279. return NULL;
  280. }
  281. //
  282. // Try to find the name
  283. //
  284. Server = ServerListFind(Name);
  285. if (Server != NULL) {
  286. return Server;
  287. }
  288. //
  289. // No record - so create a new one
  290. //
  291. if (ServerList == NULL) {
  292. pServerListTmp = (PSERVER_RECORD *) LocalAlloc(LPTR, sizeof(PSERVER_RECORD));
  293. pServerTableTmp = (PSERVER_RECORD *) LocalAlloc(LPTR, sizeof(PSERVER_RECORD));
  294. } else {
  295. pServerListTmp = (PSERVER_RECORD *) LocalReAlloc(ServerList, sizeof(PSERVER_RECORD) * (ServerListSize + 1), LHND);
  296. pServerTableTmp = (PSERVER_RECORD *) LocalReAlloc(ServerTable, sizeof(PSERVER_RECORD) * (ServerListSize + 1), LHND);
  297. }
  298. //
  299. // Make sure we could allocate server table
  300. //
  301. if ((pServerListTmp == NULL) || (pServerTableTmp == NULL)) {
  302. if (pServerListTmp != NULL)
  303. LocalFree(pServerListTmp);
  304. if (pServerTableTmp != NULL)
  305. LocalFree(pServerTableTmp);
  306. return NULL;
  307. } else {
  308. ServerList = pServerListTmp;
  309. ServerTable = pServerTableTmp;
  310. }
  311. //
  312. // Allocate space for Record.
  313. //
  314. Server = (PSERVER_RECORD) LocalAlloc(LPTR, sizeof(SERVER_RECORD));
  315. if (Server == NULL) {
  316. ASSERT(FALSE);
  317. return NULL;
  318. }
  319. ServerList[ServerListSize] = Server;
  320. ServerTable[ServerListSize] = Server;
  321. NewName = (LPTSTR) LocalAlloc(LPTR, (lstrlen(Name) + 1) * sizeof(TCHAR));
  322. if (NewName == NULL) {
  323. ASSERT(FALSE);
  324. LocalFree(Server);
  325. return NULL;
  326. }
  327. // now copy it over...
  328. Server->Name = NewName;
  329. lstrcpy(NewName, Name);
  330. //
  331. // Initialize other stuff
  332. //
  333. Server->Index = ServerListSize + 1;
  334. Server->LastReplicated = 0;
  335. Server->IsReplicating = FALSE;
  336. //
  337. // Fixup slave/master chain
  338. //
  339. Server->MasterServer = 0;
  340. Server->NextServer = 0;
  341. if (Master != NULL) {
  342. pMaster = ServerListFind(Master);
  343. if (pMaster != NULL) {
  344. Server->MasterServer = pMaster->Index;
  345. Server->NextServer = pMaster->SlaveServer;
  346. pMaster->SlaveServer = Server->Index;
  347. } else {
  348. ASSERT(FALSE);
  349. }
  350. }
  351. Server->SlaveServer = 0;
  352. Server->ServiceTableSize = 0;
  353. Server->Services = NULL;
  354. ServerListSize++;
  355. // Have added the entry - now need to sort it in order of the service names
  356. qsort((void *) ServerList, (size_t) ServerListSize, sizeof(PSERVER_RECORD), ServerListCompare);
  357. return Server;
  358. } // ServerListAdd
  359. /////////////////////////////////////////////////////////////////////////
  360. VOID
  361. LocalServerServiceListUpdate(
  362. )
  363. /*++
  364. Routine Description:
  365. Arguments:
  366. Return Value:
  367. --*/
  368. {
  369. PSERVER_RECORD Server;
  370. PMASTER_SERVICE_RECORD Service;
  371. PSERVER_SERVICE_RECORD ServerService;
  372. ULONG i, Index;
  373. #if DBG
  374. if (TraceFlags & TRACE_FUNCTION_TRACE)
  375. dprintf(TEXT("LLS TRACE: LocalServerServiceListUpdate\n"));
  376. #endif
  377. //
  378. // Find our local server in the Server table
  379. //
  380. RtlEnterCriticalSection(&ConfigInfoLock);
  381. RtlAcquireResourceShared(&ServerListLock, TRUE);
  382. Server = ServerListFind( ConfigInfo.ComputerName );
  383. RtlReleaseResource(&ServerListLock);
  384. RtlLeaveCriticalSection(&ConfigInfoLock);
  385. ASSERT(Server != NULL);
  386. if (Server == NULL)
  387. return;
  388. RtlAcquireResourceShared(&LocalServiceListLock, TRUE);
  389. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  390. for (i = 0; i < LocalServiceListSize; i++) {
  391. Service = MasterServiceListFind(LocalServiceList[i]->DisplayName);
  392. if (Service == NULL) {
  393. RtlConvertSharedToExclusive(&MasterServiceListLock);
  394. Service = MasterServiceListAdd(LocalServiceList[i]->FamilyDisplayName, LocalServiceList[i]->DisplayName, 0);
  395. RtlConvertExclusiveToShared(&MasterServiceListLock);
  396. }
  397. if (Service != NULL) {
  398. ServerService = ServerServiceListAdd( Service->Name, Service->Index, &Server->ServiceTableSize, &Server->Services );
  399. ASSERT(ServerService != NULL);
  400. if (ServerService != NULL) {
  401. //
  402. // Update high mark if needed
  403. //
  404. if ( LocalServiceList[i]->HighMark > ServerService->HighMark )
  405. {
  406. ServerService->HighMark = LocalServiceList[i]->HighMark;
  407. }
  408. //
  409. // Subtract any old licenses we might have
  410. //
  411. Service->MaxSessionCount -= ServerService->MaxSessionCount;
  412. //
  413. // Now update to current Licenses
  414. //
  415. ServerService->MaxSessionCount = LocalServiceList[i]->ConcurrentLimit;
  416. if (LocalServiceList[i]->ConcurrentLimit > ServerService->MaxSetSessionCount)
  417. ServerService->MaxSetSessionCount = LocalServiceList[i]->ConcurrentLimit;
  418. Service->MaxSessionCount += ServerService->MaxSessionCount;
  419. ServerService->Flags &= ~LLS_FLAG_PRODUCT_PERSEAT;
  420. if (LocalServiceList[i]->Mode == 0)
  421. ServerService->Flags |= LLS_FLAG_PRODUCT_PERSEAT;
  422. }
  423. }
  424. }
  425. RtlReleaseResource(&MasterServiceListLock);
  426. RtlReleaseResource(&LocalServiceListLock);
  427. } // LocalServerServiceListUpdate
  428. /////////////////////////////////////////////////////////////////////////
  429. VOID
  430. LocalServerServiceListHighMarkUpdate(
  431. )
  432. /*++
  433. Routine Description:
  434. We've got to do this separatly because it locks the Service Table
  435. and it needs to be done in reverse. I.E. We need to run through
  436. the Service Table to get the display names and then look it up in
  437. the ServerServicesList instead of running through the
  438. ServerServicesList.
  439. Arguments:
  440. Return Value:
  441. --*/
  442. {
  443. PSERVER_RECORD Server;
  444. PSERVER_SERVICE_RECORD ServerService;
  445. PMASTER_SERVICE_RECORD Service;
  446. ULONG i;
  447. //
  448. // Find our local server in the Server table
  449. //
  450. RtlEnterCriticalSection(&ConfigInfoLock);
  451. RtlAcquireResourceShared(&ServerListLock, TRUE);
  452. Server = ServerListFind( ConfigInfo.ComputerName );
  453. RtlReleaseResource(&ServerListLock);
  454. RtlLeaveCriticalSection(&ConfigInfoLock);
  455. ASSERT(Server != NULL);
  456. if (Server == NULL)
  457. return;
  458. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  459. RtlAcquireResourceShared(&ServiceListLock, TRUE);
  460. for (i = 0; i < ServiceListSize; i++) {
  461. ServerService = ServerServiceListFind( ServiceList[i]->DisplayName, Server->ServiceTableSize, Server->Services );
  462. if (ServerService != NULL) {
  463. Service = MasterServiceListFind(ServiceList[i]->DisplayName);
  464. ASSERT(Service != NULL);
  465. if (Service != NULL) {
  466. //
  467. // Subtract any old info we might have
  468. //
  469. if (Service->HighMark != 0)
  470. {
  471. Service->HighMark -= ServerService->HighMark;
  472. }
  473. //
  474. // Now update to current Licenses
  475. //
  476. ServerService->HighMark = ServiceList[i]->HighMark;
  477. Service->HighMark += ServerService->HighMark;
  478. }
  479. }
  480. }
  481. RtlReleaseResource(&ServiceListLock);
  482. RtlReleaseResource(&MasterServiceListLock);
  483. } // LocalServerServiceListHighMarkUpdate
  484. #if DBG
  485. /////////////////////////////////////////////////////////////////////////
  486. VOID
  487. ServerListDebugDump( )
  488. /*++
  489. Routine Description:
  490. Arguments:
  491. Return Value:
  492. --*/
  493. {
  494. ULONG i = 0;
  495. //
  496. // Need to scan list so get read access.
  497. //
  498. RtlAcquireResourceShared(&ServerListLock, TRUE);
  499. dprintf(TEXT("Server Table, # Entries: %lu\n"), ServerListSize);
  500. if (ServerList == NULL)
  501. goto ServerListDebugDumpExit;
  502. for (i = 0; i < ServerListSize; i++) {
  503. dprintf(TEXT("%3lu) [%3lu] LR: %s #Svc: %4lu M: %3lu S: %3lu N: %3lu Server: %s\n"),
  504. i + 1, ServerList[i]->Index, TimeToString(ServerList[i]->LastReplicated), ServerList[i]->ServiceTableSize,
  505. ServerList[i]->MasterServer, ServerList[i]->SlaveServer, ServerList[i]->NextServer, ServerList[i]->Name);
  506. }
  507. ServerListDebugDumpExit:
  508. RtlReleaseResource(&ServerListLock);
  509. return;
  510. } // ServerListDebugDump
  511. /////////////////////////////////////////////////////////////////////////
  512. VOID
  513. ServerListDebugInfoDump( PVOID Data )
  514. /*++
  515. Routine Description:
  516. Arguments:
  517. Return Value:
  518. --*/
  519. {
  520. ULONG i = 0;
  521. PSERVER_RECORD Server = NULL;
  522. //
  523. // Need to scan list so get read access.
  524. //
  525. RtlAcquireResourceShared(&ServerListLock, TRUE);
  526. dprintf(TEXT("Server Table, # Entries: %lu\n"), ServerListSize);
  527. if (ServerList == NULL)
  528. goto ServerListDebugInfoDumpExit;
  529. if (Data == NULL)
  530. goto ServerListDebugInfoDumpExit;
  531. Server = ServerListFind( (LPTSTR) Data );
  532. if (Server == NULL) {
  533. dprintf(TEXT("Server not found: %s\n"), (LPTSTR) Data );
  534. goto ServerListDebugInfoDumpExit;
  535. }
  536. //
  537. // Show server
  538. //
  539. dprintf(TEXT("[%3lu] LR: %s #Svc: %4lu M: %3lu S: %3lu N: %3lu Server: %s\n"),
  540. Server->Index, TimeToString(Server->LastReplicated), Server->ServiceTableSize,
  541. Server->MasterServer, Server->SlaveServer, Server->NextServer, Server->Name);
  542. //
  543. // Now all the services for this server
  544. //
  545. RtlAcquireResourceShared(&MasterServiceListLock, TRUE);
  546. for (i = 0; i < Server->ServiceTableSize; i++) {
  547. dprintf(TEXT(" %3lu) Flags: 0x%4lX MS: %3lu HM: %3lu SHM: %3lu Service: %s\n"),
  548. i + 1, Server->Services[i]->Flags, Server->Services[i]->MaxSessionCount, Server->Services[i]->HighMark,
  549. Server->Services[i]->MaxSetSessionCount, MasterServiceTable[Server->Services[i]->Service]->Name);
  550. }
  551. RtlReleaseResource(&MasterServiceListLock);
  552. ServerListDebugInfoDumpExit:
  553. RtlReleaseResource(&ServerListLock);
  554. return;
  555. } // ServerListDebugInfoDump
  556. #endif