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.

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