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.

774 lines
15 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. Mapping.c
  5. Abstract:
  6. Author:
  7. Arthur Hanson (arth) Dec 07, 1994
  8. Environment:
  9. Revision History:
  10. --*/
  11. #include <stdlib.h>
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #include <dsgetdc.h>
  17. #include "debug.h"
  18. #include "llsutil.h"
  19. #include "llssrv.h"
  20. #include "mapping.h"
  21. #include "msvctbl.h"
  22. #include "svctbl.h"
  23. #include "perseat.h"
  24. #define NO_LLS_APIS
  25. #include "llsapi.h"
  26. ULONG MappingListSize = 0;
  27. PMAPPING_RECORD *MappingList = NULL;
  28. RTL_RESOURCE MappingListLock;
  29. /////////////////////////////////////////////////////////////////////////
  30. NTSTATUS
  31. MappingListInit()
  32. /*++
  33. Routine Description:
  34. The table is linear so a binary search can be used on the table. We
  35. assume that adding new Mappings is a relatively rare occurance, since
  36. we need to sort it each time.
  37. The Mapping table is guarded by a read and write semaphore. Multiple
  38. reads can occur, but a write blocks everything.
  39. Arguments:
  40. None.
  41. Return Value:
  42. None.
  43. --*/
  44. {
  45. NTSTATUS status = STATUS_SUCCESS;
  46. try
  47. {
  48. RtlInitializeResource(&MappingListLock);
  49. } except(EXCEPTION_EXECUTE_HANDLER ) {
  50. status = GetExceptionCode();
  51. }
  52. return status;
  53. } // MappingListInit
  54. /////////////////////////////////////////////////////////////////////////
  55. int __cdecl MappingListCompare(const void *arg1, const void *arg2) {
  56. PMAPPING_RECORD Svc1, Svc2;
  57. Svc1 = (PMAPPING_RECORD) *((PMAPPING_RECORD *) arg1);
  58. Svc2 = (PMAPPING_RECORD) *((PMAPPING_RECORD *) arg2);
  59. return lstrcmpi( Svc1->Name, Svc2->Name);
  60. } // MappingListCompare
  61. /////////////////////////////////////////////////////////////////////////
  62. int __cdecl MappingUserListCompare(const void *arg1, const void *arg2) {
  63. LPTSTR User1, User2;
  64. User1 = (LPTSTR) *((LPTSTR *) arg1);
  65. User2 = (LPTSTR) *((LPTSTR *) arg2);
  66. return lstrcmpi( User1, User2);
  67. } // MappingUserListCompare
  68. /////////////////////////////////////////////////////////////////////////
  69. PMAPPING_RECORD
  70. MappingListFind(
  71. LPTSTR MappingName
  72. )
  73. /*++
  74. Routine Description:
  75. Internal routine to actually do binary search on MappingList, this
  76. does not do any locking as we expect the wrapper routine to do this.
  77. The search is a simple binary search.
  78. Arguments:
  79. MappingName -
  80. Return Value:
  81. Pointer to found Mapping table entry or NULL if not found.
  82. --*/
  83. {
  84. LONG begin = 0;
  85. LONG end = (LONG) MappingListSize - 1;
  86. LONG cur;
  87. int match;
  88. PMAPPING_RECORD Mapping;
  89. #if DBG
  90. if (TraceFlags & TRACE_FUNCTION_TRACE)
  91. dprintf(TEXT("LLS TRACE: MappingListFind\n"));
  92. #endif
  93. if ((MappingName == NULL) || (MappingListSize == 0))
  94. return NULL;
  95. while (end >= begin) {
  96. // go halfway in-between
  97. cur = (begin + end) / 2;
  98. Mapping = MappingList[cur];
  99. // compare the two result into match
  100. match = lstrcmpi(MappingName, Mapping->Name);
  101. if (match < 0)
  102. // move new begin
  103. end = cur - 1;
  104. else
  105. begin = cur + 1;
  106. if (match == 0)
  107. return Mapping;
  108. }
  109. return NULL;
  110. } // MappingListFind
  111. /////////////////////////////////////////////////////////////////////////
  112. LPTSTR
  113. MappingUserListFind(
  114. LPTSTR User,
  115. ULONG NumEntries,
  116. LPTSTR *Users
  117. )
  118. /*++
  119. Routine Description:
  120. Internal routine to actually do binary search on MasterServiceList, this
  121. does not do any locking as we expect the wrapper routine to do this.
  122. The search is a simple binary search.
  123. Arguments:
  124. ServiceName -
  125. Return Value:
  126. Pointer to found service table entry or NULL if not found.
  127. --*/
  128. {
  129. LONG begin = 0;
  130. LONG end;
  131. LONG cur;
  132. int match;
  133. LPTSTR pUser;
  134. #if DBG
  135. if (TraceFlags & TRACE_FUNCTION_TRACE)
  136. dprintf(TEXT("LLS TRACE: MappingUserListFind\n"));
  137. #endif
  138. if (NumEntries == 0)
  139. return NULL;
  140. end = (LONG) NumEntries - 1;
  141. while (end >= begin) {
  142. // go halfway in-between
  143. cur = (begin + end) / 2;
  144. pUser = Users[cur];
  145. // compare the two result into match
  146. match = lstrcmpi(User, pUser);
  147. if (match < 0)
  148. // move new begin
  149. end = cur - 1;
  150. else
  151. begin = cur + 1;
  152. if (match == 0)
  153. return pUser;
  154. }
  155. return NULL;
  156. } // MappingUserListFind
  157. /////////////////////////////////////////////////////////////////////////
  158. PMAPPING_RECORD
  159. MappingListUserFind( LPTSTR User )
  160. /*++
  161. Routine Description:
  162. Arguments:
  163. Return Value:
  164. --*/
  165. {
  166. ULONG i = 0;
  167. PMAPPING_RECORD pMap = NULL;
  168. //
  169. // Need to scan list so get read access.
  170. //
  171. RtlAcquireResourceShared(&MappingListLock, TRUE);
  172. if (MappingList == NULL)
  173. goto MappingListUserFindExit;
  174. while ((i < MappingListSize) && (pMap == NULL)) {
  175. if (MappingUserListFind(User, MappingList[i]->NumMembers, MappingList[i]->Members ) != NULL)
  176. pMap = MappingList[i];
  177. i++;
  178. }
  179. MappingListUserFindExit:
  180. RtlReleaseResource(&MappingListLock);
  181. return pMap;
  182. } // MappingListUserFind
  183. /////////////////////////////////////////////////////////////////////////
  184. PMAPPING_RECORD
  185. MappingListAdd(
  186. LPTSTR MappingName,
  187. LPTSTR Comment,
  188. ULONG Licenses,
  189. NTSTATUS *pStatus
  190. )
  191. /*++
  192. Routine Description:
  193. Adds a Mapping to the Mapping table.
  194. Arguments:
  195. MappingName -
  196. Return Value:
  197. Pointer to added Mapping table entry, or NULL if failed.
  198. --*/
  199. {
  200. PMAPPING_RECORD NewMapping;
  201. LPTSTR NewMappingName;
  202. LPTSTR NewComment;
  203. PMAPPING_RECORD CurrentRecord = NULL;
  204. PMAPPING_RECORD *pMappingListTmp;
  205. #if DBG
  206. if (TraceFlags & TRACE_FUNCTION_TRACE)
  207. dprintf(TEXT("LLS TRACE: MappingListAdd\n"));
  208. #endif
  209. //
  210. // We do a double check here to see if the mapping already exists
  211. //
  212. CurrentRecord = MappingListFind(MappingName);
  213. if (CurrentRecord != NULL) {
  214. if (NULL != pStatus)
  215. *pStatus = STATUS_GROUP_EXISTS;
  216. return NULL;
  217. }
  218. //
  219. // Allocate space for table (zero init it).
  220. //
  221. if (MappingList == NULL)
  222. pMappingListTmp = (PMAPPING_RECORD *) LocalAlloc(LPTR, sizeof(PMAPPING_RECORD));
  223. else
  224. pMappingListTmp = (PMAPPING_RECORD *) LocalReAlloc(MappingList, sizeof(PMAPPING_RECORD) * (MappingListSize + 1), LHND);
  225. //
  226. // Make sure we could allocate Mapping table
  227. //
  228. if (pMappingListTmp == NULL) {
  229. return NULL;
  230. } else {
  231. MappingList = pMappingListTmp;
  232. }
  233. NewMapping = LocalAlloc(LPTR, sizeof(MAPPING_RECORD));
  234. if (NewMapping == NULL)
  235. return NULL;
  236. MappingList[MappingListSize] = NewMapping;
  237. NewMappingName = (LPTSTR) LocalAlloc(LPTR, (lstrlen(MappingName) + 1) * sizeof(TCHAR));
  238. if (NewMappingName == NULL) {
  239. LocalFree(NewMapping);
  240. return NULL;
  241. }
  242. // now copy it over...
  243. NewMapping->Name = NewMappingName;
  244. lstrcpy(NewMappingName, MappingName);
  245. //
  246. // Allocate space for Comment
  247. //
  248. NewComment = (LPTSTR) LocalAlloc(LPTR, (lstrlen(Comment) + 1) * sizeof(TCHAR));
  249. if (NewComment == NULL) {
  250. LocalFree(NewMapping);
  251. LocalFree(NewMappingName);
  252. return NULL;
  253. }
  254. // now copy it over...
  255. NewMapping->Comment = NewComment;
  256. lstrcpy(NewComment, Comment);
  257. NewMapping->NumMembers = 0;
  258. NewMapping->Members = NULL;
  259. NewMapping->Licenses = Licenses;
  260. NewMapping->LicenseListSize = 0;
  261. NewMapping->LicenseList = NULL;
  262. NewMapping->Flags = (LLS_FLAG_LICENSED | LLS_FLAG_SUITE_AUTO);
  263. MappingListSize++;
  264. // Have added the entry - now need to sort it in order of the Mapping names
  265. qsort((void *) MappingList, (size_t) MappingListSize, sizeof(PMAPPING_RECORD), MappingListCompare);
  266. return NewMapping;
  267. } // MappingListAdd
  268. /////////////////////////////////////////////////////////////////////////
  269. NTSTATUS
  270. MappingListDelete(
  271. LPTSTR MappingName
  272. )
  273. /*++
  274. Routine Description:
  275. Arguments:
  276. MappingName -
  277. Return Value:
  278. --*/
  279. {
  280. PMAPPING_RECORD Mapping;
  281. ULONG i;
  282. PMAPPING_RECORD *pMappingListTmp;
  283. #if DBG
  284. if (TraceFlags & TRACE_FUNCTION_TRACE)
  285. dprintf(TEXT("LLS TRACE: MappingListDelete\n"));
  286. #endif
  287. //
  288. // Get mapping record based on name given
  289. //
  290. Mapping = MappingListFind(MappingName);
  291. if (Mapping == NULL)
  292. return STATUS_OBJECT_NAME_NOT_FOUND;
  293. //
  294. // Make sure there are no members to the mapping
  295. //
  296. if (Mapping->NumMembers != 0)
  297. return STATUS_MEMBER_IN_GROUP;
  298. //
  299. // Check if this is the last Mapping
  300. //
  301. if (MappingListSize == 1) {
  302. LocalFree(Mapping->Name);
  303. LocalFree(Mapping->Comment);
  304. LocalFree(Mapping);
  305. LocalFree(MappingList);
  306. MappingListSize = 0;
  307. MappingList = NULL;
  308. return STATUS_SUCCESS;
  309. }
  310. //
  311. // Not the last mapping so find it in the list
  312. //
  313. i = 0;
  314. while ((i < MappingListSize) && (lstrcmpi(MappingList[i]->Name, MappingName)))
  315. i++;
  316. //
  317. // Now move everything below it up.
  318. //
  319. i++;
  320. while (i < MappingListSize) {
  321. memcpy(&MappingList[i-1], &MappingList[i], sizeof(PMAPPING_RECORD));
  322. i++;
  323. }
  324. pMappingListTmp = (PMAPPING_RECORD *) LocalReAlloc(MappingList, sizeof(PMAPPING_RECORD) * (MappingListSize - 1), LHND);
  325. //
  326. // Make sure we could allocate Mapping table
  327. //
  328. if (pMappingListTmp != NULL)
  329. MappingList = pMappingListTmp;
  330. //
  331. // if realloc failed, use old table; still decrement size, though
  332. //
  333. MappingListSize--;
  334. //
  335. // Now free up the record
  336. //
  337. LocalFree(Mapping->Name);
  338. LocalFree(Mapping->Comment);
  339. LocalFree(Mapping);
  340. return STATUS_SUCCESS;
  341. } // MappingListDelete
  342. /////////////////////////////////////////////////////////////////////////
  343. PMAPPING_RECORD
  344. MappingUserListAdd(
  345. LPTSTR MappingName,
  346. LPTSTR User
  347. )
  348. /*++
  349. Routine Description:
  350. Arguments:
  351. MappingName -
  352. Return Value:
  353. Pointer to added Mapping table entry, or NULL if failed.
  354. --*/
  355. {
  356. PMAPPING_RECORD Mapping;
  357. LPTSTR NewName;
  358. LPTSTR pUser;
  359. LPTSTR *pMembersTmp;
  360. #if DBG
  361. if (TraceFlags & TRACE_FUNCTION_TRACE)
  362. dprintf(TEXT("LLS TRACE: MappingUserListAdd\n"));
  363. #endif
  364. //
  365. // Get mapping record based on name given
  366. //
  367. Mapping = MappingListFind(MappingName);
  368. if (Mapping == NULL)
  369. return NULL;
  370. //
  371. // We do a double check here to see if another thread just got done
  372. // adding the Mapping, between when we checked last and actually got
  373. // the write lock.
  374. //
  375. pUser = MappingUserListFind(User, Mapping->NumMembers, Mapping->Members);
  376. if (pUser != NULL) {
  377. return Mapping;
  378. }
  379. //
  380. // Allocate space for table (zero init it).
  381. //
  382. if (Mapping->Members == NULL)
  383. pMembersTmp = (LPTSTR *) LocalAlloc(LPTR, sizeof(LPTSTR));
  384. else
  385. pMembersTmp = (LPTSTR *) LocalReAlloc(Mapping->Members, sizeof(LPTSTR) * (Mapping->NumMembers + 1), LHND);
  386. //
  387. // Make sure we could allocate Mapping table
  388. //
  389. if (pMembersTmp == NULL) {
  390. return NULL;
  391. } else {
  392. Mapping->Members = pMembersTmp;
  393. }
  394. NewName = (LPTSTR) LocalAlloc(LPTR, (lstrlen(User) + 1) * sizeof(TCHAR));
  395. if (NewName == NULL)
  396. return NULL;
  397. // now copy it over...
  398. Mapping->Members[Mapping->NumMembers] = NewName;
  399. lstrcpy(NewName, User);
  400. Mapping->NumMembers++;
  401. // Have added the entry - now need to sort it in order of the Mapping names
  402. qsort((void *) Mapping->Members, (size_t) Mapping->NumMembers, sizeof(LPTSTR), MappingUserListCompare);
  403. return Mapping;
  404. } // MappingUserListAdd
  405. /////////////////////////////////////////////////////////////////////////
  406. NTSTATUS
  407. MappingUserListDelete(
  408. LPTSTR MappingName,
  409. LPTSTR User
  410. )
  411. /*++
  412. Routine Description:
  413. Arguments:
  414. MappingName -
  415. Return Value:
  416. Pointer to added Mapping table entry, or NULL if failed.
  417. --*/
  418. {
  419. PMAPPING_RECORD Mapping;
  420. LPTSTR pUser;
  421. ULONG i;
  422. LPTSTR *pMembersTmp;
  423. #if DBG
  424. if (TraceFlags & TRACE_FUNCTION_TRACE)
  425. dprintf(TEXT("LLS TRACE: MappingUserListDelete\n"));
  426. #endif
  427. //
  428. // Get mapping record based on name given
  429. //
  430. Mapping = MappingListFind(MappingName);
  431. if (Mapping == NULL)
  432. return STATUS_OBJECT_NAME_NOT_FOUND;
  433. //
  434. // Find the given user
  435. //
  436. pUser = MappingUserListFind(User, Mapping->NumMembers, Mapping->Members);
  437. if (pUser == NULL)
  438. return STATUS_OBJECT_NAME_NOT_FOUND;
  439. //
  440. // Check if this is the last user
  441. //
  442. if (Mapping->NumMembers == 1) {
  443. LocalFree(pUser);
  444. LocalFree(Mapping->Members);
  445. Mapping->Members = NULL;
  446. Mapping->NumMembers = 0;
  447. return STATUS_SUCCESS;
  448. }
  449. //
  450. // Not the last member so find it in the list
  451. //
  452. i = 0;
  453. while ((i < Mapping->NumMembers) && (lstrcmpi(Mapping->Members[i], User)))
  454. i++;
  455. //
  456. // Now move everything below it up.
  457. //
  458. i++;
  459. while (i < Mapping->NumMembers) {
  460. memcpy(&Mapping->Members[i-1], &Mapping->Members[i], sizeof(LPTSTR));
  461. i++;
  462. }
  463. pMembersTmp = (LPTSTR *) LocalReAlloc(Mapping->Members, sizeof(LPTSTR) * (Mapping->NumMembers - 1), LHND);
  464. //
  465. // Make sure we could allocate Mapping table
  466. //
  467. if (pMembersTmp != NULL) {
  468. Mapping->Members = pMembersTmp;
  469. }
  470. Mapping->NumMembers--;
  471. LocalFree(pUser);
  472. return STATUS_SUCCESS;
  473. } // MappingUserListDelete
  474. #if DBG
  475. /////////////////////////////////////////////////////////////////////////
  476. VOID
  477. MappingListDebugDump( )
  478. /*++
  479. Routine Description:
  480. Arguments:
  481. Return Value:
  482. --*/
  483. {
  484. ULONG i = 0;
  485. //
  486. // Need to scan list so get read access.
  487. //
  488. RtlAcquireResourceShared(&MappingListLock, TRUE);
  489. dprintf(TEXT("Mapping Table, # Entries: %lu\n"), MappingListSize);
  490. if (MappingList == NULL)
  491. goto MappingListDebugDumpExit;
  492. for (i = 0; i < MappingListSize; i++) {
  493. dprintf(TEXT(" Name: %s Flags: 0x%4lX LT: %2lu Lic: %4lu # Mem: %4lu Comment: %s\n"),
  494. MappingList[i]->Name, MappingList[i]->Flags, MappingList[i]->LicenseListSize, MappingList[i]->Licenses, MappingList[i]->NumMembers, MappingList[i]->Comment);
  495. }
  496. MappingListDebugDumpExit:
  497. RtlReleaseResource(&MappingListLock);
  498. return;
  499. } // MappingListDebugDump
  500. /////////////////////////////////////////////////////////////////////////
  501. VOID
  502. MappingListDebugInfoDump( PVOID Data )
  503. /*++
  504. Routine Description:
  505. Arguments:
  506. Return Value:
  507. --*/
  508. {
  509. ULONG i;
  510. PMAPPING_RECORD Mapping = NULL;
  511. RtlAcquireResourceShared(&MappingListLock, TRUE);
  512. dprintf(TEXT("Mapping Table, # Entries: %lu\n"), MappingListSize);
  513. if (Data == NULL)
  514. goto MappingListDebugInfoDumpExit;
  515. if (MappingList == NULL)
  516. goto MappingListDebugInfoDumpExit;
  517. if (lstrlen((LPWSTR) Data) > 0) {
  518. Mapping = MappingListFind((LPTSTR) Data);
  519. if (Mapping != NULL) {
  520. dprintf(TEXT(" Name: %s Flags: 0x%4lX LT: %2lu Lic: %4lu # Mem: %4lu Comment: %s\n"),
  521. Mapping->Name, Mapping->Flags, Mapping->LicenseListSize, Mapping->Licenses, Mapping->NumMembers, Mapping->Comment);
  522. if (Mapping->NumMembers != 0)
  523. dprintf(TEXT("\nMembers\n"));
  524. for (i = 0; i < Mapping->NumMembers; i++)
  525. dprintf(TEXT(" %s\n"), Mapping->Members[i]);
  526. if (Mapping->LicenseListSize != 0)
  527. dprintf(TEXT("\nLicenseTable\n"));
  528. for (i = 0; i < Mapping->LicenseListSize; i++)
  529. dprintf( TEXT(" Flags: 0x%4lX Ref: %2lu LN: %2lu Svc: %s\n"),
  530. Mapping->LicenseList[i]->Flags,
  531. Mapping->LicenseList[i]->RefCount,
  532. Mapping->LicenseList[i]->LicensesNeeded,
  533. Mapping->LicenseList[i]->Service->Name );
  534. } else
  535. dprintf(TEXT("Mapping not found: %s\n"), (LPTSTR) Data);
  536. }
  537. MappingListDebugInfoDumpExit:
  538. RtlReleaseResource(&MappingListLock);
  539. } // MappingListDebugInfoDump
  540. #endif