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.

626 lines
15 KiB

  1. /*************************************************************************
  2. *
  3. * init.c
  4. *
  5. * This module performs initialization for the ICA device driver.
  6. *
  7. * Copyright 1998, Microsoft.
  8. *
  9. *************************************************************************/
  10. /*
  11. * Includes
  12. */
  13. #include <precomp.h>
  14. #pragma hdrstop
  15. ULONG
  16. IcaReadSingleParameter(
  17. IN HANDLE ParametersHandle,
  18. IN PWCHAR ValueName,
  19. IN LONG DefaultValue
  20. );
  21. NTSTATUS
  22. IcaOpenRegistry(
  23. IN PUNICODE_STRING BaseName,
  24. OUT PHANDLE ParametersHandle
  25. );
  26. VOID
  27. IcaReadRegistry (
  28. VOID
  29. );
  30. BOOLEAN
  31. IsPtDrvInstalled(
  32. IN PUNICODE_STRING RegistryPath
  33. );
  34. VOID
  35. IcaUnload (
  36. IN PDRIVER_OBJECT DriverObject
  37. );
  38. NTSTATUS
  39. DriverEntry (
  40. IN PDRIVER_OBJECT DriverObject,
  41. IN PUNICODE_STRING RegistryPath
  42. );
  43. #include "ptdrvcom.h"
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text( INIT, DriverEntry )
  46. #pragma alloc_text( PAGE, IcaUnload )
  47. #endif
  48. extern PERESOURCE IcaTraceResource;
  49. extern PERESOURCE g_pKeepAliveResource;
  50. NTSTATUS
  51. DriverEntry (
  52. IN PDRIVER_OBJECT DriverObject,
  53. IN PUNICODE_STRING RegistryPath
  54. )
  55. /*++
  56. Routine Description:
  57. This is the initialization routine for the ICA device driver.
  58. Arguments:
  59. DriverObject - Pointer to driver object created by the system.
  60. Return Value:
  61. The function value is the final status from the initialization operation.
  62. --*/
  63. {
  64. NTSTATUS status;
  65. UNICODE_STRING deviceName;
  66. CLONG i;
  67. BOOLEAN success;
  68. HANDLE ThreadHandle;
  69. PAGED_CODE( );
  70. //
  71. // Initialize global data.
  72. //
  73. success = IcaInitializeData( );
  74. if ( !success ) {
  75. IcaUnload(DriverObject);
  76. return STATUS_INSUFFICIENT_RESOURCES;
  77. }
  78. g_pKeepAliveResource = ICA_ALLOCATE_POOL( NonPagedPool, sizeof(* g_pKeepAliveResource) );
  79. if ( g_pKeepAliveResource == NULL ) {
  80. return STATUS_INSUFFICIENT_RESOURCES;
  81. }
  82. ExInitializeResource( g_pKeepAliveResource );
  83. //
  84. // Create the device object. (IoCreateDevice zeroes the memory
  85. // occupied by the object.)
  86. //
  87. // !!! Apply an ACL to the device object.
  88. //
  89. RtlInitUnicodeString( &deviceName, ICA_DEVICE_NAME );
  90. /*
  91. * The device extension stores the device type, which is used
  92. * to fan out received IRPs in IcaDispatch.
  93. */
  94. status = IoCreateDevice(
  95. DriverObject, // DriverObject
  96. sizeof(ULONG), // DeviceExtension
  97. &deviceName, // DeviceName
  98. FILE_DEVICE_TERMSRV, // DeviceType
  99. 0, // DeviceCharacteristics
  100. FALSE, // Exclusive
  101. &IcaDeviceObject // DeviceObject
  102. );
  103. if ( !NT_SUCCESS(status) ) {
  104. IcaUnload(DriverObject);
  105. KdPrint(( "ICA DriverEntry: unable to create device object: %X\n", status ));
  106. return status;
  107. }
  108. //
  109. // Set up the device type
  110. //
  111. *((ULONG *)(IcaDeviceObject->DeviceExtension)) = DEV_TYPE_TERMDD;
  112. //IcaDeviceObject->Flags |= DO_DIRECT_IO;
  113. //
  114. // Initialize the driver object for this file system driver.
  115. //
  116. DriverObject->DriverUnload = IcaUnload;
  117. DriverObject->FastIoDispatch = NULL;
  118. //
  119. // We handle all possible IRPs in IcaDispatch and then fan them out
  120. // to the Port Driver or ICA components based on the device type stored
  121. // as the first ULONG's worth of the device extension
  122. //
  123. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  124. DriverObject->MajorFunction[i] = IcaDispatch;
  125. }
  126. #ifdef notdef
  127. //
  128. // Read registry information.
  129. //
  130. IcaReadRegistry( );
  131. #endif
  132. //
  133. // Initialize our device object.
  134. //
  135. IcaDeviceObject->StackSize = IcaIrpStackSize;
  136. //
  137. // Remember a pointer to the system process. We'll use this pointer
  138. // for KeAttachProcess() calls so that we can open handles in the
  139. // context of the system process.
  140. //
  141. IcaSystemProcess = IoGetCurrentProcess( );
  142. //
  143. // Tell MM that it can page all of ICA it is desires.
  144. //
  145. //MmPageEntireDriver( DriverEntry );
  146. //
  147. // Now see if the port driver component has been installed.
  148. // Initialise it if so.
  149. //
  150. if ( NT_SUCCESS(status) ) {
  151. if (IsPtDrvInstalled(RegistryPath)) {
  152. //
  153. // Initialise the mouse/keyboard port driver component.
  154. //
  155. Print(DBG_PNP_TRACE, ( "TermDD DriverEntry: calling PtEntry\n" ));
  156. status = PtEntry(DriverObject, RegistryPath);
  157. if ( NT_SUCCESS(status) ) {
  158. //
  159. // Set up the port driver's plug and play entry points.
  160. //
  161. Print(DBG_PNP_TRACE, ( "TermDD DriverEntry: PtEntry succeeded Status=%#x\n", status ));
  162. DriverObject->DriverStartIo = PtStartIo;
  163. DriverObject->DriverExtension->AddDevice = PtAddDevice;
  164. PortDriverInitialized = TRUE;
  165. } else {
  166. //
  167. // This means that remote input will not be available when
  168. // shadowing the console session - but that's no reason to
  169. // fail the rest of the initialisation
  170. //
  171. Print(DBG_PNP_ERROR, ( "TermDD DriverEntry: PtEntry failed Status=%#x\n", status ));
  172. status = STATUS_SUCCESS;
  173. }
  174. } else {
  175. Print(DBG_PNP_INFO | DBG_PNP_TRACE, ( "TermDD DriverEntry: Port driver not installed\n" ));
  176. }
  177. }
  178. if (!NT_SUCCESS(status)) {
  179. IcaUnload(DriverObject);
  180. }
  181. return (status);
  182. }
  183. VOID
  184. IcaUnload (
  185. IN PDRIVER_OBJECT DriverObject
  186. )
  187. {
  188. DriverObject;
  189. PAGED_CODE( );
  190. KdPrint(( "IcaUnload called for termdd.sys.\n" ));
  191. // Set IcaKeepAliveEvent to wake up KeepAlive thread
  192. if (pIcaKeepAliveEvent != NULL ) {
  193. KeSetEvent(pIcaKeepAliveEvent, 0, FALSE);
  194. }
  195. // Wait for the thread to exit
  196. if (pKeepAliveThreadObject != NULL ) {
  197. KeWaitForSingleObject(pKeepAliveThreadObject, Executive, KernelMode, TRUE, NULL);
  198. // Deference the thread object
  199. ObDereferenceObject(pKeepAliveThreadObject);
  200. pKeepAliveThreadObject = NULL;
  201. }
  202. // Now we can free the KeepAlive Event
  203. if (pIcaKeepAliveEvent != NULL) {
  204. ICA_FREE_POOL(pIcaKeepAliveEvent);
  205. pIcaKeepAliveEvent = NULL;
  206. }
  207. // Call onto the port driver component, if it was ever initialised.
  208. if (PortDriverInitialized) {
  209. Print(DBG_PNP_TRACE, ( "TermDD IcaUnload: calling RemotePrt PtUnload\n" ));
  210. PtUnload(DriverObject);
  211. PortDriverInitialized = FALSE;
  212. Print(DBG_PNP_TRACE, ( "TermDD IcaUnload: RemotePrt PtUnload done\n" ));
  213. }
  214. // Free resources
  215. if (IcaReconnectResource != NULL) {
  216. ExDeleteResourceLite(IcaReconnectResource );
  217. ICA_FREE_POOL(IcaReconnectResource);
  218. IcaReconnectResource = NULL;
  219. }
  220. if (IcaSdLoadResource != NULL) {
  221. ExDeleteResourceLite(IcaSdLoadResource );
  222. ICA_FREE_POOL(IcaSdLoadResource);
  223. IcaSdLoadResource = NULL;
  224. }
  225. if (IcaTraceResource != NULL) {
  226. ExDeleteResourceLite(IcaTraceResource );
  227. ICA_FREE_POOL(IcaTraceResource);
  228. IcaTraceResource = NULL;
  229. }
  230. if (g_pKeepAliveResource != NULL) {
  231. ExDeleteResource(g_pKeepAliveResource );
  232. ICA_FREE_POOL(g_pKeepAliveResource);
  233. g_pKeepAliveResource = NULL;
  234. }
  235. //
  236. // Delete the main device object.
  237. //
  238. if (IcaDeviceObject != NULL) {
  239. IoDeleteDevice (IcaDeviceObject);
  240. IcaDeviceObject = NULL;
  241. }
  242. //
  243. // Cleanup handle table, if necessary.
  244. //
  245. IcaCleanupHandleTable();
  246. KdPrint(("Finish TermDD.sys unload\n"));
  247. return;
  248. }
  249. BOOLEAN
  250. IsPtDrvInstalled(
  251. IN PUNICODE_STRING RegistryPath
  252. )
  253. {
  254. NTSTATUS status;
  255. RTL_QUERY_REGISTRY_TABLE paramTable[2];
  256. ULONG value = 0;
  257. ULONG defaultValue = 0;
  258. BOOLEAN rc = FALSE;
  259. PAGED_CODE( );
  260. RtlZeroMemory (&paramTable[0], sizeof(paramTable));
  261. paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  262. paramTable[0].Name = L"PortDriverEnable";
  263. paramTable[0].EntryContext = &value; // where to put the result
  264. paramTable[0].DefaultType = REG_DWORD;
  265. paramTable[0].DefaultData = &defaultValue;
  266. paramTable[0].DefaultLength = sizeof(ULONG);
  267. //
  268. // The second (blank) entry in paramTable signals the end of the table.
  269. //
  270. status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
  271. RegistryPath->Buffer,
  272. &paramTable[0],
  273. NULL,
  274. NULL );
  275. if (!NT_SUCCESS(status)) {
  276. value = defaultValue;
  277. }
  278. if (value != 0) {
  279. rc = TRUE;
  280. }
  281. return(rc);
  282. }
  283. #ifdef notdef
  284. VOID
  285. IcaReadRegistry (
  286. VOID
  287. )
  288. /*++
  289. Routine Description:
  290. Reads the ICA section of the registry. Any values listed in the
  291. registry override defaults.
  292. Arguments:
  293. None.
  294. Return Value:
  295. None -- if anything fails, the default value is used.
  296. --*/
  297. {
  298. HANDLE parametersHandle;
  299. NTSTATUS status;
  300. ULONG stackSize;
  301. ULONG priorityBoost;
  302. ULONG ignorePushBit;
  303. UNICODE_STRING registryPath;
  304. CLONG i;
  305. PAGED_CODE( );
  306. RtlInitUnicodeString( &registryPath, REGISTRY_ICA_INFORMATION );
  307. status = IcaOpenRegistry( &registryPath, &parametersHandle );
  308. if (status != STATUS_SUCCESS) {
  309. return;
  310. }
  311. //
  312. // Read the stack size and priority boost values from the registry.
  313. //
  314. stackSize = IcaReadSingleParameter(
  315. parametersHandle,
  316. REGISTRY_IRP_STACK_SIZE,
  317. (ULONG)IcaIrpStackSize
  318. );
  319. if ( stackSize > 255 ) {
  320. stackSize = 255;
  321. }
  322. IcaIrpStackSize = (CCHAR)stackSize;
  323. priorityBoost = IcaReadSingleParameter(
  324. parametersHandle,
  325. REGISTRY_PRIORITY_BOOST,
  326. (ULONG)IcaPriorityBoost
  327. );
  328. if ( priorityBoost > 16 ) {
  329. priorityBoost = ICA_DEFAULT_PRIORITY_BOOST;
  330. }
  331. IcaPriorityBoost = (CCHAR)priorityBoost;
  332. //
  333. // Read other config variables from the registry.
  334. //
  335. for ( i = 0; i < ICA_CONFIG_VAR_COUNT; i++ ) {
  336. *IcaConfigInfo[i].Variable =
  337. IcaReadSingleParameter(
  338. parametersHandle,
  339. IcaConfigInfo[i].RegistryValueName,
  340. *IcaConfigInfo[i].Variable
  341. );
  342. }
  343. ignorePushBit = IcaReadSingleParameter(
  344. parametersHandle,
  345. REGISTRY_IGNORE_PUSH_BIT,
  346. (ULONG)IcaIgnorePushBitOnReceives
  347. );
  348. IcaIgnorePushBitOnReceives = (BOOLEAN)( ignorePushBit != 0 );
  349. ZwClose( parametersHandle );
  350. return;
  351. }
  352. NTSTATUS
  353. IcaOpenRegistry(
  354. IN PUNICODE_STRING BaseName,
  355. OUT PHANDLE ParametersHandle
  356. )
  357. /*++
  358. Routine Description:
  359. This routine is called by ICA to open the registry. If the registry
  360. tree exists, then it opens it and returns an error. If not, it
  361. creates the appropriate keys in the registry, opens it, and
  362. returns STATUS_SUCCESS.
  363. Arguments:
  364. BaseName - Where in the registry to start looking for the information.
  365. LinkageHandle - Returns the handle used to read linkage information.
  366. ParametersHandle - Returns the handle used to read other
  367. parameters.
  368. Return Value:
  369. The status of the request.
  370. --*/
  371. {
  372. HANDLE configHandle;
  373. NTSTATUS status;
  374. PWSTR parametersString = REGISTRY_PARAMETERS;
  375. UNICODE_STRING parametersKeyName;
  376. OBJECT_ATTRIBUTES objectAttributes;
  377. ULONG disposition;
  378. PAGED_CODE( );
  379. //
  380. // Open the registry for the initial string.
  381. //
  382. InitializeObjectAttributes(
  383. &objectAttributes,
  384. BaseName, // name
  385. OBJ_CASE_INSENSITIVE, // attributes
  386. NULL, // root
  387. NULL // security descriptor
  388. );
  389. status = ZwCreateKey(
  390. &configHandle,
  391. KEY_WRITE,
  392. &objectAttributes,
  393. 0, // title index
  394. NULL, // class
  395. 0, // create options
  396. &disposition // disposition
  397. );
  398. if (!NT_SUCCESS(status)) {
  399. return STATUS_UNSUCCESSFUL;
  400. }
  401. //
  402. // Now open the parameters key.
  403. //
  404. RtlInitUnicodeString (&parametersKeyName, parametersString);
  405. InitializeObjectAttributes(
  406. &objectAttributes,
  407. &parametersKeyName, // name
  408. OBJ_CASE_INSENSITIVE, // attributes
  409. configHandle, // root
  410. NULL // security descriptor
  411. );
  412. status = ZwOpenKey(
  413. ParametersHandle,
  414. KEY_READ,
  415. &objectAttributes
  416. );
  417. if (!NT_SUCCESS(status)) {
  418. ZwClose( configHandle );
  419. return status;
  420. }
  421. //
  422. // All keys successfully opened or created.
  423. //
  424. ZwClose( configHandle );
  425. return STATUS_SUCCESS;
  426. }
  427. ULONG
  428. IcaReadSingleParameter(
  429. IN HANDLE ParametersHandle,
  430. IN PWCHAR ValueName,
  431. IN LONG DefaultValue
  432. )
  433. /*++
  434. Routine Description:
  435. This routine is called by ICA to read a single parameter
  436. from the registry. If the parameter is found it is stored
  437. in Data.
  438. Arguments:
  439. ParametersHandle - A pointer to the open registry.
  440. ValueName - The name of the value to search for.
  441. DefaultValue - The default value.
  442. Return Value:
  443. The value to use; will be the default if the value is not
  444. found or is not in the correct range.
  445. --*/
  446. {
  447. static ULONG informationBuffer[32]; // declare ULONG to get it aligned
  448. PKEY_VALUE_FULL_INFORMATION information =
  449. (PKEY_VALUE_FULL_INFORMATION)informationBuffer;
  450. UNICODE_STRING valueKeyName;
  451. ULONG informationLength;
  452. LONG returnValue;
  453. NTSTATUS status;
  454. PAGED_CODE( );
  455. RtlInitUnicodeString( &valueKeyName, ValueName );
  456. status = ZwQueryValueKey(
  457. ParametersHandle,
  458. &valueKeyName,
  459. KeyValueFullInformation,
  460. (PVOID)information,
  461. sizeof (informationBuffer),
  462. &informationLength
  463. );
  464. if ((status == STATUS_SUCCESS) && (information->DataLength == sizeof(ULONG))) {
  465. RtlMoveMemory(
  466. (PVOID)&returnValue,
  467. ((PUCHAR)information) + information->DataOffset,
  468. sizeof(ULONG)
  469. );
  470. if (returnValue < 0) {
  471. returnValue = DefaultValue;
  472. }
  473. } else {
  474. returnValue = DefaultValue;
  475. }
  476. return returnValue;
  477. }
  478. #endif