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.

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