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.

1561 lines
52 KiB

  1. /****************************************************************************/
  2. // tsrvwsx.c
  3. //
  4. // WinStation Extension entry points.
  5. //
  6. // Copyright (C) 1997-2000 Microsoft Corporation
  7. /****************************************************************************/
  8. #include <TSrv.h>
  9. #include <hydrix.h>
  10. #include <wstmsg.h>
  11. #include <ctxver.h>
  12. #include <wsxmgr.h>
  13. #include <TSrvCon.h>
  14. #include <TSrvCom.h>
  15. #include <TSrvTerm.h>
  16. #include <TSrvWsx.h>
  17. #include <TSrvVC.h>
  18. #include <_TSrvWsx.h>
  19. #include <_TSrvTerm.h>
  20. #include "rdppnutl.h"
  21. // Data declarations
  22. ICASRVPROCADDR g_IcaSrvProcAddr;
  23. //*************************************************************
  24. // WsxInitialize()
  25. //
  26. // Purpose: Initializes the extension DLL
  27. //
  28. // Parameters: IN [pIcaSrvProcAddr] - Ptr to callback table
  29. //
  30. // Return: TRUE - success
  31. // FALSE - failure
  32. //
  33. // Notes: Function is called after the DLL is loaded. The
  34. // only work we do here is to initialize our callback
  35. // table and launch our main processing thread
  36. //
  37. // History: 07-17-97 BrianTa Created
  38. //*************************************************************
  39. BOOL WsxInitialize(IN PICASRVPROCADDR pIcaSrvProcAddr)
  40. {
  41. BOOL fSuccess;
  42. DWORD dwThreadId;
  43. PWSXVALIDATE(PWSX_INITIALIZE, WsxInitialize);
  44. TRACE((DEBUG_TSHRSRV_DEBUG,
  45. "TShrSRV: WsxInitialize entry\n"));
  46. fSuccess = FALSE;
  47. // Gross pointer validation
  48. if (pIcaSrvProcAddr)
  49. {
  50. // Gross version check
  51. if (pIcaSrvProcAddr->cbProcAddr == (ULONG) sizeof(ICASRVPROCADDR))
  52. {
  53. g_IcaSrvProcAddr = *pIcaSrvProcAddr;
  54. fSuccess = TRUE;
  55. }
  56. }
  57. // If the table was at least marginally Ok, then attempt to
  58. // launch TSrvMainThread
  59. if (fSuccess)
  60. {
  61. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: ICASRV callback table saved\n"));
  62. // Remove all existing TS printers. We don't care about the return value
  63. // here because a failure is not fatal.
  64. RDPPNUTL_RemoveAllTSPrinters();
  65. g_hMainThread = CreateThread(NULL, // security attributes
  66. 0, // stack size
  67. TSrvMainThread, // thread function
  68. NULL, // argument
  69. 0, // creation flags
  70. &dwThreadId); // thread identifier
  71. if (g_hMainThread)
  72. {
  73. TRACE((DEBUG_TSHRSRV_DEBUG, "TShrSRV: TSrvMainThread created\n"));
  74. }
  75. else
  76. {
  77. fSuccess = FALSE;
  78. TRACE((DEBUG_TSHRSRV_ERROR,
  79. "TShrSRV: Unable to create TSrvMainThread - 0x%x\n",
  80. GetLastError()));
  81. }
  82. }
  83. else
  84. {
  85. TRACE((DEBUG_TSHRSRV_ERROR, "TShrSRV: Bad ICASRV callback table - not saved\n"));
  86. }
  87. TRACE((DEBUG_TSHRSRV_DEBUG,
  88. "TShrSRV: WsxInitialize exit - 0x%x\n", fSuccess));
  89. return (fSuccess);
  90. }
  91. //*************************************************************
  92. // WsxWinStationInitialize()
  93. //
  94. // Purpose: Performs Winstation extension initialization
  95. //
  96. // Parameters: OUT [ppvContext] - * to store our WinStation
  97. // context structure
  98. //
  99. // Return: STATUS_SUCCESS - success
  100. // STATUS_NO_MEMORY - failure
  101. //
  102. // Notes: Function is called when the WinStation
  103. // is being initialized
  104. //
  105. // History: 07-17-97 BrianTa Created
  106. //*************************************************************
  107. NTSTATUS WsxWinStationInitialize(OUT PVOID *ppvContext)
  108. {
  109. NTSTATUS ntStatus;
  110. PWSX_CONTEXT pWsxContext;
  111. UINT cAddins;
  112. PWSXVALIDATE(PWSX_WINSTATIONINITIALIZE, WsxWinStationInitialize);
  113. TRACE((DEBUG_TSHRSRV_DEBUG,
  114. "TShrSRV: WsxWinStationInitialize entry\n"));
  115. TS_ASSERT(ppvContext);
  116. if (TSrvIsReady(TRUE)) {
  117. ntStatus = STATUS_NO_MEMORY;
  118. //
  119. // Get the VC code to allocate the context, since it needs to do some
  120. // funky critical section stuff around its data copy. We just
  121. // tell it how much space to allow for our WSX_CONTEXT structure.
  122. //
  123. *ppvContext = TSrvAllocVCContext(sizeof(WSX_CONTEXT), &cAddins);
  124. if (*ppvContext)
  125. {
  126. //
  127. // The memory was allocated OK.
  128. // Just need to set up a couple of things.
  129. //
  130. pWsxContext = *ppvContext;
  131. pWsxContext->CheckMark = WSX_CONTEXT_CHECKMARK;
  132. pWsxContext->cVCAddins = cAddins;
  133. if (RtlInitializeCriticalSection(&pWsxContext->cs) == STATUS_SUCCESS) {
  134. ntStatus = STATUS_SUCCESS;
  135. pWsxContext->fCSInitialized = TRUE;
  136. }
  137. else {
  138. TRACE((DEBUG_TSHRSRV_ERROR,
  139. "TShrSRV: WsxInitialization could not init crit section %lx\n",
  140. ntStatus));
  141. pWsxContext->fCSInitialized = FALSE;
  142. }
  143. }
  144. }
  145. else {
  146. ntStatus = STATUS_DEVICE_NOT_READY;
  147. TRACE((DEBUG_TSHRSRV_DEBUG,
  148. "TShrSRV: WsxInitialization is not done - 0x%x\n", ntStatus));
  149. }
  150. TRACE((DEBUG_TSHRSRV_DEBUG,
  151. "TShrSRV: WsxWinStationInitialize exit - 0x%x\n", ntStatus));
  152. return (ntStatus);
  153. }
  154. //*************************************************************
  155. // WsxWinStationReInitialize()
  156. //
  157. // Purpose: Performs Winstation extension Reinitialization
  158. //
  159. // Parameters: IN OUT [pvContext] - * to store our WinStation
  160. // context structure
  161. // IN [pvWsxInfo] - context info for copy
  162. //
  163. // Return: STATUS_SUCCESS - success
  164. // STATUS_DEVICE_NOT_READY - failure
  165. //
  166. // Notes: Function is called when the WinStation
  167. // is being initialized
  168. //
  169. // History: 04-11-2000 JoyC Created
  170. //*************************************************************
  171. NTSTATUS WsxWinStationReInitialize(
  172. IN OUT PVOID pvContext,
  173. IN PVOID pvWsxInfo)
  174. {
  175. NTSTATUS ntStatus;
  176. PWSX_CONTEXT pWsxContext;
  177. PWSX_INFO pWsxInfo;
  178. PWSXVALIDATE(PWSX_WINSTATIONREINITIALIZE, WsxWinStationReInitialize);
  179. TRACE((DEBUG_TSHRSRV_DEBUG,
  180. "TShrSRV: WsxWinStationReInitialize entry\n"));
  181. TS_ASSERT(pvContext);
  182. TS_ASSERT(pvWsxInfo);
  183. if (TSrvIsReady(TRUE)) {
  184. pWsxContext = (PWSX_CONTEXT)pvContext;
  185. pWsxInfo = (PWSX_INFO)pvWsxInfo;
  186. ASSERT(pWsxInfo->Version == WSX_INFO_VERSION_1);
  187. if (pWsxInfo->Version == WSX_INFO_VERSION_1) {
  188. pWsxContext->hIca = pWsxInfo->hIca;
  189. pWsxContext->hStack = pWsxInfo->hStack;
  190. }
  191. ntStatus = STATUS_SUCCESS;
  192. }
  193. else {
  194. ntStatus = STATUS_DEVICE_NOT_READY;
  195. TRACE((DEBUG_TSHRSRV_DEBUG,
  196. "TShrSRV: WsxReInitialization is not done - 0x%x\n", ntStatus));
  197. }
  198. TRACE((DEBUG_TSHRSRV_DEBUG,
  199. "TShrSRV: WsxWinStationReInitialize exit - 0x%x\n", ntStatus));
  200. return (ntStatus);
  201. }
  202. //*************************************************************
  203. // WsxBrokenConnection()
  204. //
  205. // Purpose: Broken connection notification
  206. //
  207. // Parameters: IN [ppWsxContext] - * to our WinStation
  208. // context structure
  209. // IN [hStack] - Primary stack
  210. //
  211. //
  212. // Return: STATUS_SUCCESS - Success
  213. //
  214. // History: 07-17-97 BrianTa Created
  215. //*************************************************************
  216. NTSTATUS WsxBrokenConnection(
  217. IN PVOID pvContext,
  218. IN HANDLE hStack,
  219. IN PICA_BROKEN_CONNECTION pBroken)
  220. {
  221. NTSTATUS ntStatus;
  222. PWSX_CONTEXT pWsxContext;
  223. ULONG ulReason;
  224. ULONG Event;
  225. PWSXVALIDATE(PWSX_BROKENCONNECTION, WsxBrokenConnection);
  226. TRACE((DEBUG_TSHRSRV_DEBUG,
  227. "TShrSRV: WsxBrokenConnection entry\n"));
  228. ntStatus = STATUS_SUCCESS;
  229. TS_ASSERT(pvContext);
  230. if (pvContext)
  231. {
  232. pWsxContext = pvContext;
  233. TRACE((DEBUG_TSHRSRV_DEBUG,
  234. "TShrSRV: Broken connection pWsxContext %p, pTSrvInfo %p\n",
  235. pWsxContext, pWsxContext->pTSrvInfo));
  236. if (pWsxContext->CheckMark != WSX_CONTEXT_CHECKMARK)
  237. {
  238. TS_ASSERT(pWsxContext->CheckMark == WSX_CONTEXT_CHECKMARK);
  239. // We cannot continue, the struct is corrupted.
  240. return STATUS_INVALID_HANDLE;
  241. }
  242. TRACE((DEBUG_TSHRSRV_DEBUG,
  243. "TShrSRV: hStack %p, Reason 0x%x, Source 0x%x\n",
  244. pWsxContext->hStack, pBroken->Reason, pBroken->Source));
  245. if (pWsxContext->pTSrvInfo)
  246. {
  247. switch (pBroken->Reason)
  248. {
  249. case Broken_Unexpected:
  250. ulReason = GCC_REASON_UNKNOWN;
  251. break;
  252. case Broken_Disconnect:
  253. case Broken_Terminate:
  254. TS_ASSERT(pBroken->Source == BrokenSource_User ||
  255. pBroken->Source == BrokenSource_Server);
  256. ulReason = ((pBroken->Source == BrokenSource_User)
  257. ? GCC_REASON_USER_INITIATED
  258. : GCC_REASON_SERVER_INITIATED);
  259. break;
  260. default:
  261. TS_ASSERT(!"Invalid pBroken->reason");
  262. ulReason = GCC_REASON_UNKNOWN;
  263. break;
  264. }
  265. // Terminate the connection and release the domain
  266. pWsxContext->pTSrvInfo->ulReason = ulReason;
  267. pWsxContext->pTSrvInfo->hIca = pWsxContext->hIca;
  268. TSrvDoDisconnect(pWsxContext->pTSrvInfo, ulReason);
  269. // Release our info reference. Grab the context lock so no one
  270. // can try to retrieve pTSrvInfo while we're nulling it.
  271. EnterCriticalSection( &pWsxContext->cs );
  272. TSrvDereferenceInfo(pWsxContext->pTSrvInfo);
  273. pWsxContext->pTSrvInfo = NULL;
  274. LeaveCriticalSection( &pWsxContext->cs );
  275. }
  276. }
  277. TRACE((DEBUG_TSHRSRV_DEBUG,
  278. "TShrSRV: WsxBrokenConnection memory dump\n"));
  279. // The HeapWalk API has a lot of flaws and is going away after NT5.
  280. // We can use other tools (e.g. gflag) to detect heap corruption.
  281. // TSHeapWalk(TS_HEAP_DUMP_ALL, TS_HTAG_0, NULL);
  282. TRACE((DEBUG_TSHRSRV_DEBUG,
  283. "TShrSRV: WsxBrokenConnection exit - 0x%x\n", ntStatus));
  284. return (ntStatus);
  285. }
  286. //*************************************************************
  287. // WsxWinStationRundown()
  288. //
  289. // Purpose: Performs Winstation extension cleanup
  290. //
  291. // Parameters: IN [ppvContext] - * to our WinStation
  292. // context structure
  293. //
  294. // Return: STATUS_SUCCESS - Success
  295. // Other - Failure
  296. //
  297. // Notes: Function is called when the WinStation
  298. // is being cleaned up
  299. //
  300. // History: 07-17-97 BrianTa Created
  301. //*************************************************************
  302. NTSTATUS WsxWinStationRundown(IN PVOID pvContext)
  303. {
  304. NTSTATUS ntStatus;
  305. PWSX_CONTEXT pWsxContext;
  306. PWSXVALIDATE(PWSX_WINSTATIONRUNDOWN, WsxWinStationRundown);
  307. TRACE((DEBUG_TSHRSRV_DEBUG,
  308. "TShrSRV: WsxWinStationRundown entry\n"));
  309. ntStatus = STATUS_SUCCESS;
  310. TRACE((DEBUG_TSHRSRV_DEBUG,
  311. "TShrSRV: pWsxContext=%p\n", pvContext));
  312. TS_ASSERT(pvContext);
  313. if (pvContext)
  314. {
  315. pWsxContext = pvContext;
  316. if (pWsxContext->CheckMark != WSX_CONTEXT_CHECKMARK)
  317. {
  318. TS_ASSERT(pWsxContext->CheckMark == WSX_CONTEXT_CHECKMARK);
  319. // We cannot continue, the struct is corrupted.
  320. return STATUS_INVALID_HANDLE;
  321. }
  322. // Release context memory
  323. if (pWsxContext)
  324. {
  325. TRACE((DEBUG_TSHRSRV_DEBUG,
  326. "TShrSRV: pTSrvInfo - %p\n", pWsxContext->pTSrvInfo));
  327. if (pWsxContext->pTSrvInfo)
  328. {
  329. // Terminate the connection and release the domain
  330. pWsxContext->pTSrvInfo->hIca = pWsxContext->hIca;
  331. pWsxContext->pTSrvInfo->hStack = pWsxContext->hStack;
  332. TSrvDoDisconnect(pWsxContext->pTSrvInfo, GCC_REASON_UNKNOWN);
  333. // Release our info reference. Grab the context lock to prevent
  334. // another thread from trying to retrieve pTsrInfo while we
  335. // are nuking it.
  336. EnterCriticalSection( &pWsxContext->cs );
  337. TSrvDereferenceInfo(pWsxContext->pTSrvInfo);
  338. pWsxContext->pTSrvInfo = NULL;
  339. LeaveCriticalSection( &pWsxContext->cs );
  340. }
  341. // Release VC addins info for this session
  342. TSrvReleaseVCAddins(pWsxContext);
  343. pWsxContext->CheckMark = 0; // Reset before freeing.
  344. if (pWsxContext->fCSInitialized) {
  345. RtlDeleteCriticalSection(&pWsxContext->cs);
  346. }
  347. TSHeapFree(pWsxContext);
  348. }
  349. }
  350. TRACE((DEBUG_TSHRSRV_DEBUG,
  351. "TShrSRV: WsxWinStationRundown memory dump\n"));
  352. // The HeapWalk API has a lot of flaws and is going away after NT5.
  353. // We can use other tools (e.g. gflag) to detect heap corruption.
  354. //TSHeapWalk(TS_HEAP_DUMP_ALL, TS_HTAG_0, NULL);
  355. TRACE((DEBUG_TSHRSRV_DEBUG,
  356. "TShrSRV: WsxWinStationRundown exit - 0x%x\n", ntStatus));
  357. return (ntStatus);
  358. }
  359. //*************************************************************
  360. // WsxInitializeClientData()
  361. //
  362. // Purpose: InitializeClientData
  363. //
  364. // Parameters: IN [ppWsxContext] - * to our WinStation
  365. // context structure
  366. // IN [hStack] - Primary stack
  367. // ...
  368. //
  369. // Return: STATUS_SUCCESS - Success
  370. //
  371. // History: 07-17-97 BrianTa Created
  372. //*************************************************************
  373. NTSTATUS WsxInitializeClientData(
  374. IN PWSX_CONTEXT pWsxContext,
  375. IN HANDLE hStack,
  376. IN HANDLE hIca,
  377. IN HANDLE hIcaThinwireChannel,
  378. OUT PBYTE pVideoModuleName,
  379. OUT ULONG cbVideoModuleNameLen,
  380. OUT PUSERCONFIG pUserConfig,
  381. OUT PUSHORT HRes,
  382. OUT PUSHORT VRes,
  383. OUT PUSHORT fColorCaps,
  384. OUT WINSTATIONDOCONNECTMSG * DoConnect)
  385. {
  386. NTSTATUS ntStatus;
  387. ULONG ulBytesReturned;
  388. WINSTATIONCLIENT *pClient;
  389. PWSXVALIDATE(PWSX_INITIALIZECLIENTDATA, WsxInitializeClientData);
  390. TRACE((DEBUG_TSHRSRV_DEBUG,
  391. "TShrSRV: WsxInitializeClientData entry\n"));
  392. TS_ASSERT(pWsxContext);
  393. TS_ASSERT(hStack);
  394. pClient = TSHeapAlloc(HEAP_ZERO_MEMORY,
  395. sizeof(WINSTATIONCLIENT),
  396. TS_HTAG_TSS_WINSTATION_CLIENT);
  397. if (pClient != NULL) {
  398. ntStatus = IcaStackIoControl(
  399. hStack,
  400. IOCTL_ICA_STACK_QUERY_CLIENT,
  401. NULL,
  402. 0,
  403. pClient,
  404. sizeof(WINSTATIONCLIENT),
  405. &ulBytesReturned);
  406. if (NT_SUCCESS(ntStatus)) {
  407. WCHAR pszKeyboardLayout[KL_NAMELENGTH + 8];
  408. *HRes = pClient->HRes;
  409. *VRes = pClient->VRes;
  410. *fColorCaps = pClient->ColorDepth;
  411. // Use the client AutoLogon information if allowed by this WinStation's
  412. // configuration
  413. if (pUserConfig->fInheritAutoLogon) {
  414. wcscpy(pUserConfig->UserName, pClient->UserName);
  415. wcscpy(pUserConfig->Password, pClient->Password);
  416. wcscpy(pUserConfig->Domain, pClient->Domain);
  417. // Don't allow the client to override prompting for a password if the
  418. // Winstation is configured to always require password prompting
  419. if (!pUserConfig->fPromptForPassword)
  420. pUserConfig->fPromptForPassword = pClient->fPromptForPassword;
  421. }
  422. // Use the client/user config if allowed. Note that this can be
  423. // overridden (after logon) by the initial program info for a particular
  424. // user ID.
  425. if (pUserConfig->fInheritInitialProgram)
  426. {
  427. pUserConfig->fMaximize = pClient->fMaximizeShell;
  428. wcscpy(pUserConfig->InitialProgram, pClient->InitialProgram);
  429. wcscpy(pUserConfig->WorkDirectory, pClient->WorkDirectory);
  430. }
  431. pUserConfig->fHideTitleBar = 0;
  432. pUserConfig->KeyboardLayout = pClient->KeyboardLayout;
  433. if (pWsxContext->pTSrvInfo && pWsxContext->pTSrvInfo->fConsoleStack) {
  434. memcpy(pVideoModuleName, "RDPCDD", sizeof("RDPCDD"));
  435. memcpy(DoConnect->DisplayDriverName, L"RDPCDD", sizeof(L"RDPCDD"));
  436. DoConnect->ProtocolType = PROTOCOL_RDP;
  437. } else {
  438. memcpy(pVideoModuleName, "RDPDD", sizeof("RDPDD"));
  439. memcpy(DoConnect->DisplayDriverName, L"RDPDD", sizeof(L"RDPDD"));
  440. }
  441. wcscpy(DoConnect->ProtocolName, L"RDP");
  442. wcscpy(DoConnect->AudioDriverName, L"rdpsnd");
  443. DoConnect->fINetClient = FALSE;
  444. DoConnect->fClientDoubleClickSupport = FALSE;
  445. DoConnect->fHideTitleBar = (BOOLEAN) pUserConfig->fHideTitleBar;
  446. DoConnect->fMouse = (BOOLEAN) pClient->fMouse;
  447. DoConnect->fEnableWindowsKey = (BOOLEAN) pClient->fEnableWindowsKey;
  448. DoConnect->fInitialProgram =
  449. (BOOLEAN)(pUserConfig->InitialProgram[0] != UNICODE_NULL);
  450. // Initialize DoConnect resolution fileds
  451. DoConnect->HRes = pClient->HRes;
  452. DoConnect->VRes = pClient->VRes;
  453. if (pUserConfig->fInheritColorDepth)
  454. DoConnect->ColorDepth = pClient->ColorDepth;
  455. else
  456. DoConnect->ColorDepth = (USHORT)pUserConfig->ColorDepth;
  457. }
  458. TSHeapFree(pClient);
  459. TRACE((DEBUG_TSHRSRV_DEBUG,
  460. "TShrSRV: WsxInitializeClientData exit = 0x%x\n",
  461. ntStatus));
  462. }
  463. else {
  464. ntStatus = STATUS_NO_MEMORY;
  465. }
  466. return ntStatus;
  467. }
  468. //***********************************************************************************
  469. // WsxEscape()
  470. //
  471. // Purpose: General Purpose API for communication between TERMSRV and RDPWSX
  472. // Presently used to support long UserName and Password during autologon
  473. // Parameters: IN [pWsxContext] - * to our WinStation context structure
  474. // IN [InfoType] - Type of service requested
  475. // IN [pInBuffer] - Pointer to a buffer which is sent
  476. // IN [InBufferSize] - Size of the input buffer
  477. // OUT [pOutBuffer] - Pointer to the Output Buffer
  478. // IN [OutBufferSize] - Size of the Output Buffer which is sent
  479. // OUT [pBytesReturned] - Actual Number of bytes copied to OutBuffer
  480. //
  481. // Return: STATUS_SUCCESS - Success
  482. //
  483. // History: 08-30-2000 SriramSa Created
  484. //************************************************************************************
  485. NTSTATUS WsxEscape(
  486. IN PWSX_CONTEXT pWsxContext,
  487. IN INFO_TYPE InfoType,
  488. IN PVOID pInBuffer,
  489. IN ULONG InBufferSize,
  490. OUT PVOID pOutBuffer,
  491. IN ULONG OutBufferSize,
  492. OUT PULONG pBytesReturned)
  493. {
  494. NTSTATUS ntStatus = STATUS_INVALID_PARAMETER;
  495. ULONG ulBytesReturned;
  496. pExtendedClientCredentials pNewCredentials = NULL;
  497. PTS_AUTORECONNECTINFO pAutoReconnectInfo = NULL;
  498. PTSRVINFO pTSrvInfo = NULL;
  499. BYTE fGetServerToClientInfo = FALSE;
  500. PWSXVALIDATE(PWSX_ESCAPE, WsxEscape);
  501. TRACE((DEBUG_TSHRSRV_DEBUG,
  502. "TShrSRV: WsxEscape entry\n"));
  503. TS_ASSERT( pWsxContext );
  504. switch (InfoType)
  505. {
  506. case GET_LONG_USERNAME:
  507. {
  508. // validate the parameters
  509. TS_ASSERT( pOutBuffer != NULL ) ;
  510. TS_ASSERT( OutBufferSize >= sizeof(ExtendedClientCredentials)) ;
  511. if ((pOutBuffer == NULL) ||
  512. (OutBufferSize < sizeof(ExtendedClientCredentials))) {
  513. ntStatus = ERROR_INSUFFICIENT_BUFFER ;
  514. return ntStatus ;
  515. }
  516. pNewCredentials = (pExtendedClientCredentials) (pOutBuffer);
  517. ntStatus = IcaStackIoControl(
  518. pWsxContext->hStack,
  519. IOCTL_ICA_STACK_QUERY_CLIENT_EXTENDED,
  520. NULL,
  521. 0,
  522. pNewCredentials,
  523. sizeof(ExtendedClientCredentials),
  524. &ulBytesReturned);
  525. *pBytesReturned = sizeof(*pNewCredentials);
  526. }
  527. break;
  528. //
  529. // Get autoreconnect info sent from client to server
  530. //
  531. case GET_CS_AUTORECONNECT_INFO:
  532. {
  533. // validate the parameters
  534. TS_ASSERT( pOutBuffer != NULL ) ;
  535. TS_ASSERT( OutBufferSize >= sizeof(TS_AUTORECONNECTINFO)) ;
  536. if ((pOutBuffer == NULL) ||
  537. (OutBufferSize < sizeof(TS_AUTORECONNECTINFO))) {
  538. ntStatus = ERROR_INSUFFICIENT_BUFFER ;
  539. return ntStatus ;
  540. }
  541. pAutoReconnectInfo = (PTS_AUTORECONNECTINFO)pOutBuffer;
  542. fGetServerToClientInfo = FALSE;
  543. ntStatus = IcaStackIoControl(
  544. pWsxContext->hStack,
  545. IOCTL_ICA_STACK_QUERY_AUTORECONNECT,
  546. &fGetServerToClientInfo,
  547. sizeof(fGetServerToClientInfo),
  548. pAutoReconnectInfo,
  549. sizeof(TS_AUTORECONNECTINFO),
  550. &ulBytesReturned);
  551. *pBytesReturned = ulBytesReturned;
  552. }
  553. break;
  554. //
  555. // Get autoreconnect info sent from SERVER to CLIENT
  556. // i.e. the RDPWD handled ARC cookie
  557. //
  558. case GET_SC_AUTORECONNECT_INFO:
  559. {
  560. // validate the parameters
  561. TS_ASSERT( pOutBuffer != NULL ) ;
  562. TS_ASSERT( OutBufferSize >= sizeof(TS_AUTORECONNECTINFO));
  563. if ((pOutBuffer == NULL) ||
  564. (OutBufferSize < sizeof(TS_AUTORECONNECTINFO))) {
  565. ntStatus = ERROR_INSUFFICIENT_BUFFER ;
  566. return ntStatus;
  567. }
  568. pAutoReconnectInfo = (PTS_AUTORECONNECTINFO)pOutBuffer;
  569. fGetServerToClientInfo = TRUE;
  570. ntStatus = IcaStackIoControl(
  571. pWsxContext->hStack,
  572. IOCTL_ICA_STACK_QUERY_AUTORECONNECT,
  573. &fGetServerToClientInfo,
  574. sizeof(fGetServerToClientInfo),
  575. pAutoReconnectInfo,
  576. sizeof(TS_AUTORECONNECTINFO),
  577. &ulBytesReturned);
  578. *pBytesReturned = ulBytesReturned;
  579. }
  580. break;
  581. case GET_CLIENT_RANDOM:
  582. {
  583. pTSrvInfo = pWsxContext->pTSrvInfo;
  584. if (NULL == pTSrvInfo) {
  585. ntStatus = ERROR_ACCESS_DENIED;
  586. return ntStatus;
  587. }
  588. // validate the parameters
  589. TS_ASSERT( pOutBuffer != NULL ) ;
  590. TS_ASSERT( OutBufferSize >= RANDOM_KEY_LENGTH) ;
  591. TS_ASSERT( pTSrvInfo );
  592. if ((pOutBuffer == NULL) ||
  593. (OutBufferSize < sizeof(TS_AUTORECONNECTINFO))) {
  594. ntStatus = ERROR_INSUFFICIENT_BUFFER ;
  595. return ntStatus ;
  596. }
  597. memcpy(pOutBuffer,
  598. pTSrvInfo->SecurityInfo.KeyPair.clientRandom,
  599. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom));
  600. *pBytesReturned =
  601. sizeof(pTSrvInfo->SecurityInfo.KeyPair.clientRandom);
  602. ntStatus = STATUS_SUCCESS;
  603. }
  604. break;
  605. }
  606. return ntStatus;
  607. }
  608. //*************************************************************
  609. // WsxLogonNotify()
  610. //
  611. // Purpose: Logon Notification
  612. //
  613. // Parameters: IN [pWsxContext] - * to our WinStation
  614. // context structure
  615. // IN [LogonId] - Logon Id
  616. // IN [ClientToken] - NT client token
  617. // IN [pDomain] - Domain
  618. // IN [pUserName] - UserName
  619. //
  620. // Return: STATUS_SUCCESS - Success
  621. // Other - Failure
  622. //
  623. // History: 12-04-97 BrianTa Created
  624. //
  625. // Notes: This is mainly being used to drive an
  626. // IOCTL_TSHARE_USER_LOGON to the WD so it's in the loop.
  627. //*************************************************************
  628. WsxLogonNotify(
  629. IN PWSX_CONTEXT pWsxContext,
  630. IN ULONG LogonId,
  631. IN HANDLE ClientToken,
  632. IN PWCHAR pDomain,
  633. IN PWCHAR pUserName)
  634. {
  635. NTSTATUS ntStatus;
  636. LOGONINFO LogonInfo;
  637. ULONG ulBytesReturned;
  638. PWSXVALIDATE(PWSX_LOGONNOTIFY, WsxLogonNotify);
  639. TRACE((DEBUG_TSHRSRV_DEBUG,
  640. "TShrSRV: WsxLogonNotify entry\n"));
  641. TS_ASSERT(pWsxContext);
  642. TS_ASSERT(pWsxContext->hStack);
  643. TS_ASSERT(pDomain);
  644. TS_ASSERT(wcslen(pDomain) < sizeof(LogonInfo.Domain) / sizeof(WCHAR));
  645. TS_ASSERT(pUserName);
  646. TS_ASSERT(wcslen(pUserName) < sizeof(LogonInfo.UserName) / sizeof(WCHAR));
  647. TRACE((DEBUG_TSHRSRV_NORMAL,
  648. "TShrSrv: %p:%p - Logon session %d\n",
  649. pWsxContext, pWsxContext->pTSrvInfo, LogonId));
  650. //
  651. // Save the Logon ID
  652. //
  653. pWsxContext->LogonId = LogonId;
  654. //
  655. // Tell the WD
  656. //
  657. LogonInfo.SessionId = LogonId;
  658. wcscpy((PWCHAR)LogonInfo.Domain, pDomain);
  659. wcscpy((PWCHAR)LogonInfo.UserName, pUserName);
  660. //
  661. // Specify that autoreconnect should be started
  662. //
  663. LogonInfo.Flags = LI_USE_AUTORECONNECT;
  664. ntStatus = IcaStackIoControl(
  665. pWsxContext->hStack,
  666. IOCTL_TSHARE_USER_LOGON,
  667. &LogonInfo,
  668. sizeof(LogonInfo),
  669. NULL,
  670. 0,
  671. &ulBytesReturned);
  672. //
  673. // Check memory
  674. //
  675. TRACE((DEBUG_TSHRSRV_DEBUG,
  676. "TShrSRV: WsxLogonNotify memory dump\n"));
  677. // The HeapWalk API has a lot of flaws and is going away after NT5.
  678. // We can use other tools (e.g. gflag) to detect heap corruption.
  679. //TSHeapWalk(TS_HEAP_DUMP_INFO | TS_HEAP_DUMP_TOTALS, TS_HTAG_0, NULL);
  680. TRACE((DEBUG_TSHRSRV_DEBUG,
  681. "TShrSRV: WsxLogonNotify exit - 0x%x\n", STATUS_SUCCESS));
  682. return (STATUS_SUCCESS);
  683. }
  684. //*************************************************************
  685. // WsxDuplicateContext()
  686. //
  687. // Purpose: Create and return copy of context
  688. //
  689. // Parameters: IN [pWsxContext] - * to our context
  690. // OUT [ppWsxDupContext] - ** to dupped context
  691. //
  692. // Return: STATUS_SUCCESS - success
  693. // STATUS_NO_MEMORY - failure
  694. //
  695. // History: 07-17-97 BrianTa Created
  696. //*************************************************************
  697. NTSTATUS WsxDuplicateContext(
  698. IN PVOID pvContext,
  699. OUT PVOID *ppvDupContext)
  700. {
  701. NTSTATUS ntStatus;
  702. PWSX_CONTEXT pWsxContext, pDupWsxContext;
  703. PWSXVALIDATE(PWSX_DUPLICATECONTEXT, WsxDuplicateContext);
  704. TRACE((DEBUG_TSHRSRV_DEBUG,
  705. "TShrSRV: WsxDuplicateContext entry\n"));
  706. TRACE((DEBUG_TSHRSRV_DEBUG,
  707. "TShrSRV: pvContext=%p\n", pvContext));
  708. ASSERT(pvContext != NULL);
  709. ASSERT(ppvDupContext != NULL);
  710. ntStatus = STATUS_NO_MEMORY;
  711. *ppvDupContext = TSHeapAlloc(HEAP_ZERO_MEMORY,
  712. sizeof(WSX_CONTEXT),
  713. TS_HTAG_TSS_WSXCONTEXT);
  714. if (*ppvDupContext)
  715. {
  716. TRACE((DEBUG_TSHRSRV_DEBUG,
  717. "TShrSRV: Dup extension context allocated %p for a size of 0x%x bytes\n",
  718. *ppvDupContext, sizeof(WSX_CONTEXT)));
  719. pDupWsxContext = (PWSX_CONTEXT) *ppvDupContext;
  720. pWsxContext = (PWSX_CONTEXT) pvContext;
  721. pDupWsxContext->CheckMark = WSX_CONTEXT_CHECKMARK;
  722. pDupWsxContext->pTSrvInfo = pWsxContext->pTSrvInfo;
  723. pDupWsxContext->hIca = pWsxContext->hIca;
  724. pDupWsxContext->hStack = pWsxContext->hStack;
  725. ntStatus = RtlInitializeCriticalSection(&pDupWsxContext->cs);
  726. if (ntStatus == STATUS_SUCCESS) {
  727. pDupWsxContext->fCSInitialized = TRUE;
  728. EnterCriticalSection( &pWsxContext->cs );
  729. pWsxContext->pTSrvInfo = NULL;
  730. LeaveCriticalSection( &pWsxContext->cs );
  731. }
  732. else {
  733. TRACE((DEBUG_TSHRSRV_ERROR,
  734. "TShrSRV: WsxDuplicateContext could not init crit section 0x%x\n",
  735. ntStatus));
  736. pDupWsxContext->fCSInitialized = FALSE;
  737. }
  738. }
  739. else
  740. {
  741. TRACE((DEBUG_TSHRSRV_DEBUG,
  742. "TShrSRV: Extension could not allocate dup context of 0x%x bytes\n",
  743. sizeof(WSX_CONTEXT)));
  744. }
  745. TRACE((DEBUG_TSHRSRV_DEBUG,
  746. "TShrSRV: WsxDuplicateContext exit - 0x%x\n", ntStatus));
  747. return (ntStatus);
  748. }
  749. //*************************************************************
  750. // WsxCopyContext()
  751. //
  752. // Purpose: Create and return copy of context
  753. //
  754. // Parameters: OUT [pWsxDstContext] - * to destination context
  755. // IN [pWsxSrcContext] - * to source context
  756. //
  757. // Return: STATUS_SUCCESS - success
  758. //
  759. // History: 07-17-97 BrianTa Created
  760. //*************************************************************
  761. NTSTATUS WsxCopyContext(
  762. OUT PVOID pvDstContext,
  763. IN PVOID pvSrcContext)
  764. {
  765. PTSRVINFO pTSrvInfo;
  766. PWSX_CONTEXT pWsxDstContext;
  767. PWSX_CONTEXT pWsxSrcContext;
  768. PWSXVALIDATE(PWSX_COPYCONTEXT, WsxCopyContext);
  769. TRACE((DEBUG_TSHRSRV_DEBUG,
  770. "TShrSRV: WsxCopyContext entry\n"));
  771. TRACE((DEBUG_TSHRSRV_DEBUG,
  772. "TShrSRV: pvDstContext=%p, pvSrcContext=%p\n",
  773. pvDstContext, pvSrcContext));
  774. ASSERT(pvDstContext != NULL);
  775. ASSERT(pvSrcContext != NULL);
  776. if (pvSrcContext && pvDstContext)
  777. {
  778. pWsxSrcContext = pvSrcContext;
  779. pWsxDstContext = pvDstContext;
  780. TRACE((DEBUG_TSHRSRV_DEBUG,
  781. "TShrSRV: pDst->pTSrvInfo=%p, pSrc->pTSrvInfo=%p\n",
  782. pWsxDstContext->pTSrvInfo, pWsxSrcContext->pTSrvInfo));
  783. // It's possible for pWsxDstContext->pTSrvInfo to be NULL since we
  784. // may have set it so in a WsxDuplicate() call above.
  785. //TS_ASSERT(pWsxDstContext->pTSrvInfo != NULL);
  786. TS_ASSERT(pWsxSrcContext->pTSrvInfo != NULL);
  787. pTSrvInfo = pWsxDstContext->pTSrvInfo;
  788. pWsxDstContext->pTSrvInfo = pWsxSrcContext->pTSrvInfo;
  789. pWsxSrcContext->pTSrvInfo = pTSrvInfo;
  790. }
  791. TRACE((DEBUG_TSHRSRV_DEBUG,
  792. "TShrSRV: WsxCopyContext exit - 0x%x\n", STATUS_SUCCESS));
  793. return (STATUS_SUCCESS);
  794. }
  795. //*************************************************************
  796. // WsxClearContext()
  797. //
  798. // Purpose: Clears the given context
  799. //
  800. // Parameters: OUT [pWsxContext] - * to destination context
  801. //
  802. // History: 07-17-97 BrianTa Created
  803. //*************************************************************
  804. NTSTATUS WsxClearContext(IN PVOID pvContext)
  805. {
  806. PWSX_CONTEXT pWsxContext;
  807. PWSXVALIDATE(PWSX_CLEARCONTEXT, WsxClearContext);
  808. TRACE((DEBUG_TSHRSRV_DEBUG,
  809. "TShrSRV: WsxClearContext entry\n"));
  810. TRACE((DEBUG_TSHRSRV_DEBUG,
  811. "TShrSRV: pWsxContext=%p\n",
  812. pvContext));
  813. TRACE((DEBUG_TSHRSRV_DEBUG,
  814. "TShrSRV: WsxClearContext exit - 0x%x\n", STATUS_SUCCESS));
  815. return (STATUS_SUCCESS);
  816. }
  817. //*************************************************************
  818. // WsxIcaStackIoControl()
  819. //
  820. // Purpose: Generic interface to an ICA stack
  821. //
  822. // Parameters: IN [pvContext] - * to context
  823. // IN [hIca] _ Ica handle
  824. // IN [hStack] - primary stack
  825. // IN [IoControlCode] - I/O control code
  826. // IN [pInBuffer] - * to input parameters
  827. // IN [InBufferSize] - Size of pInBuffer
  828. // OUT [pOutBuffer] - * to output buffer
  829. // IN [OutBufferSize] - Size of pOutBuffer
  830. // OUT [pBytesReturned]- * to number of bytes returned
  831. //
  832. // Return: STATUS_SUCCESS - success
  833. // other - failure
  834. //
  835. // History: 07-17-97 BrianTa Created
  836. //*************************************************************
  837. NTSTATUS WsxIcaStackIoControl(
  838. IN PVOID pvContext,
  839. IN HANDLE hIca,
  840. IN HANDLE hStack,
  841. IN ULONG IoControlCode,
  842. IN PVOID pInBuffer,
  843. IN ULONG InBufferSize,
  844. OUT PVOID pOutBuffer,
  845. IN ULONG OutBufferSize,
  846. OUT PULONG pBytesReturned)
  847. {
  848. NTSTATUS ntStatus;
  849. PWSX_CONTEXT pWsxContext;
  850. PTSRVINFO pTSrvInfo = NULL;
  851. PWSXVALIDATE(PWSX_ICASTACKIOCONTROL, WsxIcaStackIoControl);
  852. TRACE((DEBUG_TSHRSRV_DEBUG,
  853. "TShrSRV: WsxIcaStackIoControl entry\n"));
  854. TS_ASSERT(hIca);
  855. TS_ASSERT(hStack);
  856. pWsxContext = pvContext;
  857. TSrvDumpIoctlDetails(pvContext,
  858. hIca,
  859. hStack,
  860. IoControlCode,
  861. pInBuffer,
  862. InBufferSize,
  863. pOutBuffer,
  864. OutBufferSize,
  865. pBytesReturned);
  866. // Pass all IOCTLS on
  867. ntStatus = IcaStackIoControl(hStack,
  868. IoControlCode,
  869. pInBuffer,
  870. InBufferSize,
  871. pOutBuffer,
  872. OutBufferSize,
  873. pBytesReturned);
  874. TRACE((DEBUG_TSHRSRV_DEBUG,
  875. "TShrSRV: Return from IcaStackIoControl - 0x%x\n", ntStatus));
  876. // Perform post processing for specific IOCTLS
  877. if (NT_SUCCESS(ntStatus))
  878. {
  879. TS_ASSERT(pWsxContext);
  880. switch (IoControlCode)
  881. {
  882. // Process "connect" request
  883. case IOCTL_ICA_STACK_WAIT_FOR_ICA:
  884. if (pWsxContext->CheckMark != WSX_CONTEXT_CHECKMARK)
  885. {
  886. TS_ASSERT(pWsxContext->CheckMark == WSX_CONTEXT_CHECKMARK);
  887. // We cannot continue, the struct is corrupted.
  888. return STATUS_INVALID_HANDLE;
  889. }
  890. pTSrvInfo = NULL;
  891. ntStatus = TSrvStackConnect(hIca, hStack, &pTSrvInfo);
  892. pWsxContext->hIca = hIca;
  893. pWsxContext->hStack = hStack;
  894. pWsxContext->pTSrvInfo = pTSrvInfo;
  895. break;
  896. // Process request to connect to console session
  897. case IOCTL_ICA_STACK_CONSOLE_CONNECT:
  898. TS_ASSERT(pWsxContext);
  899. if (pWsxContext->CheckMark != WSX_CONTEXT_CHECKMARK)
  900. {
  901. TS_ASSERT(pWsxContext->CheckMark == WSX_CONTEXT_CHECKMARK);
  902. // We cannot continue, the struct is corrupted.
  903. return STATUS_INVALID_HANDLE;
  904. }
  905. pTSrvInfo = NULL;
  906. ntStatus = TSrvConsoleConnect(hIca, hStack, pInBuffer, InBufferSize, &pTSrvInfo);
  907. pWsxContext->hIca = hIca;
  908. pWsxContext->hStack = hStack;
  909. pWsxContext->pTSrvInfo = pTSrvInfo;
  910. //
  911. // @@@ Should we?
  912. // Tell VC Addins
  913. //
  914. // TRACE((DEBUG_TSHRSRV_NORMAL, "TShrSRV: Connect new session\n"));
  915. // TSrvNotifyVC(pWsxContext, TSRV_VC_SESSION_CONNECT);
  916. break;
  917. // Process Reconnect request
  918. case IOCTL_ICA_STACK_RECONNECT:
  919. TRACE((DEBUG_TSHRSRV_NORMAL,
  920. "TShrSRV: Reconnect session %d, stack %p (context stack %p)\n",
  921. pWsxContext->LogonId, hStack, pWsxContext->hStack));
  922. pWsxContext->hStack = hStack;
  923. break;
  924. // Process Disconnect request
  925. case IOCTL_ICA_STACK_DISCONNECT:
  926. TRACE((DEBUG_TSHRSRV_NORMAL,
  927. "TShrSRV: Disconnect session %d\n",
  928. pWsxContext->LogonId));
  929. break;
  930. // Process Shadow hotkey request (signifies entry and exit to/from
  931. // shadowing)
  932. case IOCTL_ICA_STACK_REGISTER_HOTKEY:
  933. TRACE((DEBUG_TSHRSRV_ERROR,
  934. "TShrSRV: Register Hotkey %d\n",
  935. (INT)(((PICA_STACK_HOTKEY)pInBuffer)->HotkeyVk)));
  936. if (((PICA_STACK_HOTKEY)pInBuffer)->HotkeyVk)
  937. {
  938. TRACE((DEBUG_TSHRSRV_ERROR,
  939. "TShrSRV: Start shadowing\n"));
  940. TSrvNotifyVC(pWsxContext, TSRV_VC_SESSION_SHADOW_START);
  941. }
  942. else
  943. {
  944. TRACE((DEBUG_TSHRSRV_ERROR,
  945. "TShrSRV: Stop shadowing\n"));
  946. TSrvNotifyVC(pWsxContext, TSRV_VC_SESSION_SHADOW_END);
  947. }
  948. break;
  949. // process a shadow connection request
  950. case IOCTL_ICA_STACK_SET_CONNECTED:
  951. // This is the shadow target stack so initialize, send the
  952. // server's random and certificate, wait for the client to
  953. // respond with an encrypted client random, decrypt it, then
  954. // make the session keys
  955. EnterCriticalSection( &pWsxContext->cs );
  956. if (pWsxContext->pTSrvInfo != NULL) {
  957. TSrvReferenceInfo(pWsxContext->pTSrvInfo);
  958. pTSrvInfo = pWsxContext->pTSrvInfo;
  959. }
  960. else {
  961. LeaveCriticalSection( &pWsxContext->cs );
  962. return STATUS_CTX_SHADOW_DENIED;
  963. }
  964. LeaveCriticalSection( &pWsxContext->cs );
  965. ASSERT(pTSrvInfo != NULL);
  966. EnterCriticalSection(&pTSrvInfo->cs);
  967. if ((pInBuffer != NULL) && (InBufferSize != 0)) {
  968. ntStatus = TSrvShadowTargetConnect(hStack,
  969. pTSrvInfo,
  970. pInBuffer,
  971. InBufferSize);
  972. }
  973. // Else, this is shadow client passthru stack so wait
  974. // for the server random & certicate, verify it, send
  975. // back an encrypted client random, then make the session
  976. // keys
  977. else {
  978. ntStatus = TSrvShadowClientConnect(hStack, pTSrvInfo);
  979. }
  980. // Free any output user data we may have generated
  981. if (pTSrvInfo->pUserDataInfo != NULL) {
  982. TSHeapFree(pTSrvInfo->pUserDataInfo);
  983. pTSrvInfo->pUserDataInfo = NULL;
  984. }
  985. LeaveCriticalSection(&pTSrvInfo->cs);
  986. TSrvDereferenceInfo(pTSrvInfo);
  987. break;
  988. }
  989. }
  990. TRACE((DEBUG_TSHRSRV_DEBUG,
  991. "TShrSRV: WsxIcaStackIoControl exit - 0x%x\n", ntStatus));
  992. return ntStatus;
  993. }
  994. //*************************************************************
  995. // WsxConnect()
  996. //
  997. // Purpose: Notification for client device mapping
  998. //
  999. // Parameters: IN [pvContext] - * to context
  1000. // IN [LogonId] - Logon Id
  1001. // IN [hIca] - Ica handle
  1002. //
  1003. // Return: STATUS_SUCCESS - success
  1004. // other - failure
  1005. //
  1006. // History: 10-27-98 AdamO Created
  1007. //*************************************************************
  1008. NTSTATUS WsxConnect(
  1009. IN PVOID pvContext,
  1010. IN ULONG LogonId,
  1011. IN HANDLE hIca)
  1012. {
  1013. PWSX_CONTEXT pWsxContext = (PWSX_CONTEXT)pvContext;
  1014. TRACE((DEBUG_TSHRSRV_FLOW,
  1015. "TShrSRV: WsxConnect - LogonId: %d\n", LogonId));
  1016. // The LogonId is not yet initialized
  1017. pWsxContext->LogonId = LogonId;
  1018. TSrvNotifyVC(pWsxContext, TSRV_VC_SESSION_CONNECT);
  1019. return STATUS_SUCCESS;
  1020. }
  1021. //*************************************************************
  1022. // WsxDisconnect()
  1023. //
  1024. // Purpose: Notification for client device mapping
  1025. //
  1026. // Parameters: IN [pvContext] - * to context
  1027. // IN [LogonId] - Logon Id
  1028. // IN [hIca] - Ica handle
  1029. //
  1030. // Return: STATUS_SUCCESS - success
  1031. // other - failure
  1032. //
  1033. // History: 10-27-98 AdamO Created
  1034. //*************************************************************
  1035. NTSTATUS WsxDisconnect(
  1036. IN PVOID pvContext,
  1037. IN ULONG LogonId,
  1038. IN HANDLE hIca)
  1039. {
  1040. PWSX_CONTEXT pWsxContext = (PWSX_CONTEXT)pvContext;
  1041. TRACE((DEBUG_TSHRSRV_FLOW,
  1042. "TShrSRV: WsxDisconnect - LogonId: %d\n", LogonId));
  1043. if (pWsxContext != NULL) {
  1044. // The LogonId is not yet initialized if WsxConnect/WsxLogonNotify is not called
  1045. pWsxContext->LogonId = LogonId;
  1046. TSrvNotifyVC(pWsxContext, TSRV_VC_SESSION_DISCONNECT);
  1047. } else {
  1048. TRACE((DEBUG_TSHRSRV_ERROR,
  1049. "TShrSRV: WsxDisconnect was passed a null context\n"));
  1050. }
  1051. return STATUS_SUCCESS;
  1052. }
  1053. //*************************************************************
  1054. // WsxVirtualChannelSecurity()
  1055. //
  1056. // Purpose: Notification for client device mapping
  1057. //
  1058. // Parameters: IN [pvContext] - * to context
  1059. // IN [hIca] - Ica handle
  1060. // IN [pUserConfig] - PUSERCONFIG
  1061. //
  1062. // Return: STATUS_SUCCESS - success
  1063. // other - failure
  1064. //
  1065. // History: 10-27-98 AdamO Created
  1066. //*************************************************************
  1067. NTSTATUS WsxVirtualChannelSecurity(
  1068. IN PVOID pvContext,
  1069. IN HANDLE hIca,
  1070. IN PUSERCONFIG pUserConfig)
  1071. {
  1072. PWSX_CONTEXT pWsxContext = (PWSX_CONTEXT)pvContext;
  1073. // pWsxContect->LogonId is not yet initialized
  1074. TRACE((DEBUG_TSHRSRV_FLOW,
  1075. "TShrSRV: WsxVirtualChannelSecurity\n"));
  1076. pWsxContext->fAutoClientDrives = pUserConfig->fAutoClientDrives;
  1077. pWsxContext->fAutoClientLpts = pUserConfig->fAutoClientLpts;
  1078. pWsxContext->fForceClientLptDef = pUserConfig->fForceClientLptDef;
  1079. pWsxContext->fDisableCpm = pUserConfig->fDisableCpm;
  1080. pWsxContext->fDisableCdm = pUserConfig->fDisableCdm;
  1081. pWsxContext->fDisableCcm = pUserConfig->fDisableCcm;
  1082. pWsxContext->fDisableLPT = pUserConfig->fDisableLPT;
  1083. pWsxContext->fDisableClip = pUserConfig->fDisableClip;
  1084. pWsxContext->fDisableExe = pUserConfig->fDisableExe;
  1085. pWsxContext->fDisableCam = pUserConfig->fDisableCam;
  1086. return STATUS_SUCCESS;
  1087. }
  1088. //*************************************************************
  1089. // WsxSetErrorInfo()
  1090. //
  1091. // Purpose: Sets last error info, used to indicate disconnect
  1092. // reason to client
  1093. //
  1094. // Parameters: IN [pWsxContext] - * to our WinStation
  1095. // context structure
  1096. // IN [errorInfo] - error information to pass to
  1097. // client
  1098. // IN [fStackLockHeld] - True if the stack lock
  1099. // is already held
  1100. //
  1101. // Return: STATUS_SUCCESS - Success
  1102. // Other - Failure
  1103. //
  1104. // History: 9-20-00 NadimA Created
  1105. //
  1106. // Notes: This is mainly being used to drive an
  1107. // IOCTL_TSHARE_SET_ERROR_INFO to the WD.
  1108. //*************************************************************
  1109. NTSTATUS WsxSetErrorInfo(
  1110. IN PWSX_CONTEXT pWsxContext,
  1111. IN UINT32 errorInfo,
  1112. IN BOOL fStackLockHeld)
  1113. {
  1114. NTSTATUS ntStatus;
  1115. ULONG ulBytesReturned;
  1116. PWSXVALIDATE(PWSX_SETERRORINFO, WsxSetErrorInfo);
  1117. TRACE((DEBUG_TSHRSRV_DEBUG,
  1118. "TShrSRV: WsxSetErrorInfo entry\n"));
  1119. TS_ASSERT(pWsxContext);
  1120. TS_ASSERT(pWsxContext->hStack);
  1121. TRACE((DEBUG_TSHRSRV_NORMAL,
  1122. "TShrSrv: %p:%p - SetErrorInfo 0x%x\n",
  1123. pWsxContext, pWsxContext->pTSrvInfo, errorInfo));
  1124. //
  1125. // Tell the WD
  1126. //
  1127. if(!fStackLockHeld)
  1128. {
  1129. ntStatus = IcaStackIoControl(
  1130. pWsxContext->hStack,
  1131. IOCTL_TSHARE_SET_ERROR_INFO,
  1132. &errorInfo,
  1133. sizeof(errorInfo),
  1134. NULL,
  1135. 0,
  1136. &ulBytesReturned);
  1137. }
  1138. else
  1139. {
  1140. //
  1141. // Stack lock already held so call
  1142. // version of IcaStackIoControl that
  1143. // will not try to reaquire it.
  1144. //
  1145. ntStatus = _IcaStackIoControl(
  1146. pWsxContext->hStack,
  1147. IOCTL_TSHARE_SET_ERROR_INFO,
  1148. &errorInfo,
  1149. sizeof(errorInfo),
  1150. NULL,
  1151. 0,
  1152. &ulBytesReturned);
  1153. }
  1154. TRACE((DEBUG_TSHRSRV_DEBUG,
  1155. "TShrSRV: WsxSetErrorInfo exit - 0x%x\n", STATUS_SUCCESS));
  1156. return ntStatus;
  1157. }
  1158. //*************************************************************
  1159. // WsxSendAutoReconnectStatus()
  1160. //
  1161. // Purpose: Sends autoreconnect status information to the client
  1162. //
  1163. // Parameters: IN [pWsxContext] - * to our WinStation
  1164. // context structure
  1165. // IN [arcStatus] - Autoreconnect status
  1166. //
  1167. // IN [fStackLockHeld] - True if the stack lock
  1168. // is already held
  1169. //
  1170. // Return: STATUS_SUCCESS - Success
  1171. // Other - Failure
  1172. //
  1173. // History: 10-29-01 NadimA Created
  1174. //
  1175. // Notes: This is mainly being used to drive an
  1176. // IOCTL_TSHARE_SEND_ARC_STATUS to the WD.
  1177. //*************************************************************
  1178. NTSTATUS WsxSendAutoReconnectStatus(
  1179. IN PWSX_CONTEXT pWsxContext,
  1180. IN UINT32 arcStatus,
  1181. IN BOOL fStackLockHeld)
  1182. {
  1183. NTSTATUS ntStatus;
  1184. ULONG ulBytesReturned;
  1185. PWSXVALIDATE(PWSX_SETERRORINFO, WsxSetErrorInfo);
  1186. TRACE((DEBUG_TSHRSRV_DEBUG,
  1187. "TShrSRV: WsxSetErrorInfo entry\n"));
  1188. TS_ASSERT(pWsxContext);
  1189. TS_ASSERT(pWsxContext->hStack);
  1190. TRACE((DEBUG_TSHRSRV_NORMAL,
  1191. "TShrSrv: %p:%p - SetErrorInfo 0x%x\n",
  1192. pWsxContext, pWsxContext->pTSrvInfo, arcStatus));
  1193. //
  1194. // Tell the WD
  1195. //
  1196. if(!fStackLockHeld)
  1197. {
  1198. ntStatus = IcaStackIoControl(
  1199. pWsxContext->hStack,
  1200. IOCTL_TSHARE_SEND_ARC_STATUS,
  1201. &arcStatus,
  1202. sizeof(arcStatus),
  1203. NULL,
  1204. 0,
  1205. &ulBytesReturned);
  1206. }
  1207. else
  1208. {
  1209. //
  1210. // Stack lock already held so call
  1211. // version of IcaStackIoControl that
  1212. // will not try to reaquire it.
  1213. //
  1214. ntStatus = _IcaStackIoControl(
  1215. pWsxContext->hStack,
  1216. IOCTL_TSHARE_SEND_ARC_STATUS,
  1217. &arcStatus,
  1218. sizeof(arcStatus),
  1219. NULL,
  1220. 0,
  1221. &ulBytesReturned);
  1222. }
  1223. TRACE((DEBUG_TSHRSRV_DEBUG,
  1224. "TShrSRV: WsxSendAutoReconnectStatus exit - 0x%x\n", STATUS_SUCCESS));
  1225. return ntStatus;
  1226. }
  1227. #if DBG
  1228. //*************************************************************
  1229. // TSrvDumpIoctlDetails()
  1230. //
  1231. // Purpose: Dumps out Ica Ioctl details
  1232. //
  1233. // Parameters: IN [pvContext] - * to context
  1234. // IN [hIca] _ Ica handle
  1235. // IN [hStack] - primary stack
  1236. // IN [IoControlCode] - I/O control code
  1237. // IN [pInBuffer] - * to input parameters
  1238. // IN [InBufferSize] - Size of pInBuffer
  1239. // IN [pOutBuffer] - * to output buffer
  1240. // IN [OutBufferSize] - Size of pOutBuffer
  1241. // IN [pBytesReturned]- * to number of bytes returned
  1242. //
  1243. // Return: void
  1244. //
  1245. // History: 07-17-97 BrianTa Created
  1246. //*************************************************************
  1247. void TSrvDumpIoctlDetails(
  1248. IN PVOID pvContext,
  1249. IN HANDLE hIca,
  1250. IN HANDLE hStack,
  1251. IN ULONG IoControlCode,
  1252. IN PVOID pInBuffer,
  1253. IN ULONG InBufferSize,
  1254. IN PVOID pOutBuffer,
  1255. IN ULONG OutBufferSize,
  1256. IN PULONG pBytesReturned)
  1257. {
  1258. int i;
  1259. PCHAR pszMessageText;
  1260. PWSX_CONTEXT pWsxContext = (PWSX_CONTEXT)pvContext;
  1261. pszMessageText = "UNKNOWN_ICA_IOCTL";
  1262. for (i=0; i<sizeof(IcaIoctlTBL) / sizeof(IcaIoctlTBL[0]); i++)
  1263. {
  1264. if (IcaIoctlTBL[i].IoControlCode == IoControlCode)
  1265. {
  1266. pszMessageText = IcaIoctlTBL[i].pszMessageText;
  1267. break;
  1268. }
  1269. }
  1270. TRACE((DEBUG_TSHRSRV_NORMAL,
  1271. "TShrSRV: %p:%p IoctlDetail: Ioctl 0x%x (%s)\n",
  1272. pWsxContext,
  1273. pWsxContext ? pWsxContext->pTSrvInfo : 0,
  1274. IoControlCode, pszMessageText));
  1275. TRACE((DEBUG_TSHRSRV_DEBUG,
  1276. "TShrSRV: pvContext=%p, hIca=%p, hStack=%p\n",
  1277. pvContext, hIca, hStack));
  1278. TRACE((DEBUG_TSHRSRV_DEBUG,
  1279. "TShrSRV: pInBuffer=%p, InBufferSize=0x%x, pOutBuffer=%p, OutBufferSize=0x%x\n",
  1280. pInBuffer, InBufferSize, pOutBuffer, OutBufferSize));
  1281. }
  1282. #endif // DBG