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.

539 lines
17 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract: Contains routines to support ioctl queries for the SMB Back Light
  6. device.
  7. Environment:
  8. Kernel mode
  9. Author:
  10. Michael Tsang (MikeTs) 20-Nov-2000
  11. Revision History:
  12. --*/
  13. #include "pch.h"
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(PAGE, SmbLiteIoctl)
  16. #pragma alloc_text(PAGE, GetBackLightBrightness)
  17. #pragma alloc_text(PAGE, RegQueryDeviceParam)
  18. #endif
  19. /*++
  20. @doc EXTERNAL
  21. @func NTSTATUS | SmbLiteIoctl |
  22. Process the Device Control IRPs sent to this device.
  23. @parm IN PDRIVER_OBJECT | DevObj | Points to the driver object.
  24. @parm IN PIRP | Irp | Points to an I/O Request Packet.
  25. @rvalue SUCCESS | returns STATUS_SUCCESS
  26. @rvalue FAILURE | returns NT status code
  27. --*/
  28. NTSTATUS EXTERNAL
  29. SmbLiteIoctl(
  30. IN PDEVICE_OBJECT DevObj,
  31. IN PIRP Irp
  32. )
  33. {
  34. PROCNAME("SmbLiteIoctl")
  35. NTSTATUS status;
  36. PIO_STACK_LOCATION irpsp;
  37. PSMBLITE_DEVEXT devext;
  38. PAGED_CODE();
  39. irpsp = IoGetCurrentIrpStackLocation(Irp);
  40. ENTER(1, ("(DevObj=%p,Irp=%p,IrpSp=%p,Ioctl=%s)\n",
  41. DevObj, Irp, irpsp,
  42. LookupName(irpsp->Parameters.DeviceIoControl.IoControlCode,
  43. IoctlNames)));
  44. devext = DevObj->DeviceExtension;
  45. status = IoAcquireRemoveLock(&devext->RemoveLock, Irp);
  46. if (NT_SUCCESS(status))
  47. {
  48. BOOLEAN fNeedCompletion = TRUE;
  49. ASSERT(devext->dwfSmbLite & SMBLITEF_DEVICE_STARTED);
  50. Irp->IoStatus.Information = 0;
  51. switch(irpsp->Parameters.DeviceIoControl.IoControlCode)
  52. {
  53. case IOCTL_SMBLITE_GETBRIGHTNESS:
  54. if (irpsp->Parameters.DeviceIoControl.OutputBufferLength <
  55. sizeof(SMBLITE_BRIGHTNESS))
  56. {
  57. status = STATUS_BUFFER_TOO_SMALL;
  58. WARNPRINT(("GetBrightness buffer too small (len=%d,required=%d).\n",
  59. irpsp->Parameters.DeviceIoControl.OutputBufferLength,
  60. sizeof(SMBLITE_BRIGHTNESS)));
  61. }
  62. else
  63. {
  64. PSMBLITE_BRIGHTNESS Brightness = Irp->UserBuffer;
  65. try
  66. {
  67. ProbeForWrite(Brightness,
  68. sizeof(*Brightness),
  69. sizeof(UCHAR));
  70. }
  71. except (EXCEPTION_EXECUTE_HANDLER)
  72. {
  73. status = GetExceptionCode();
  74. WARNPRINT(("Invalid GetBrightness buffer (status=%x,Buff=%p).\n",
  75. status, Brightness));
  76. }
  77. if (NT_SUCCESS(status))
  78. {
  79. status = GetBackLightBrightness(devext, Brightness);
  80. if (NT_SUCCESS(status))
  81. {
  82. Irp->IoStatus.Information = sizeof(*Brightness);
  83. }
  84. }
  85. }
  86. break;
  87. case IOCTL_SMBLITE_SETBRIGHTNESS:
  88. if (irpsp->Parameters.DeviceIoControl.InputBufferLength !=
  89. sizeof(SMBLITE_SETBRIGHTNESS))
  90. {
  91. status = STATUS_INFO_LENGTH_MISMATCH;
  92. WARNPRINT(("SetBrightness buffer length mismatch (len=%d,required=%d).\n",
  93. irpsp->Parameters.DeviceIoControl.InputBufferLength,
  94. sizeof(SMBLITE_SETBRIGHTNESS)));
  95. }
  96. else
  97. {
  98. PSMBLITE_SETBRIGHTNESS SetBrightness = (PSMBLITE_SETBRIGHTNESS)
  99. irpsp->Parameters.DeviceIoControl.Type3InputBuffer;
  100. try
  101. {
  102. ProbeForRead(SetBrightness,
  103. sizeof(*SetBrightness),
  104. sizeof(UCHAR));
  105. }
  106. except (EXCEPTION_EXECUTE_HANDLER)
  107. {
  108. status = GetExceptionCode();
  109. WARNPRINT(("Invalid SetBrightness buffer (status=%x,Buff=%p).\n",
  110. status, SetBrightness));
  111. }
  112. if (NT_SUCCESS(status))
  113. {
  114. status = SetBackLightBrightness(
  115. devext,
  116. &SetBrightness->Brightness,
  117. SetBrightness->fSaveSettings);
  118. }
  119. }
  120. break;
  121. #ifdef SYSACC
  122. case IOCTL_SYSACC_MEM_REQUEST:
  123. status = STATUS_NOT_SUPPORTED;
  124. break;
  125. case IOCTL_SYSACC_IO_REQUEST:
  126. status = STATUS_NOT_SUPPORTED;
  127. break;
  128. case IOCTL_SYSACC_PCICFG_REQUEST:
  129. status = STATUS_NOT_SUPPORTED;
  130. break;
  131. case IOCTL_SYSACC_SMBUS_REQUEST:
  132. if ((irpsp->Parameters.DeviceIoControl.InputBufferLength <
  133. sizeof(SMB_REQUEST)) ||
  134. (irpsp->Parameters.DeviceIoControl.OutputBufferLength <
  135. sizeof(SMB_REQUEST)))
  136. {
  137. status = STATUS_BUFFER_TOO_SMALL;
  138. WARNPRINT(("SMBusRequest buffer too small (len=%d,required=%d).\n",
  139. irpsp->Parameters.DeviceIoControl.InputBufferLength,
  140. sizeof(SMB_REQUEST)));
  141. }
  142. else
  143. {
  144. PSMB_REQUEST SmbReqIn = (PSMB_REQUEST)
  145. Irp->AssociatedIrp.SystemBuffer;
  146. PSMB_REQUEST SmbReqOut = (PSMB_REQUEST)
  147. Irp->UserBuffer;
  148. try
  149. {
  150. ProbeForWrite(SmbReqOut,
  151. sizeof(*SmbReqOut),
  152. sizeof(UCHAR));
  153. }
  154. except (EXCEPTION_EXECUTE_HANDLER)
  155. {
  156. status = GetExceptionCode();
  157. WARNPRINT(("Invalid SMBRequest buffer (status=%x,Buff=%p).\n",
  158. status, SmbReqOut));
  159. }
  160. if (NT_SUCCESS(status))
  161. {
  162. status = SMBRequest(devext, SmbReqIn);
  163. if (NT_SUCCESS(status))
  164. {
  165. RtlCopyMemory(SmbReqOut,
  166. SmbReqIn,
  167. sizeof(*SmbReqOut));
  168. Irp->IoStatus.Information = sizeof(*SmbReqOut);
  169. }
  170. }
  171. }
  172. break;
  173. #endif
  174. default:
  175. WARNPRINT(("unsupported ioctl code (ioctl=%s)\n",
  176. LookupName(irpsp->Parameters.DeviceIoControl.IoControlCode,
  177. IoctlNames)));
  178. status = STATUS_NOT_SUPPORTED;
  179. break;
  180. }
  181. IoReleaseRemoveLock(&devext->RemoveLock, Irp);
  182. }
  183. Irp->IoStatus.Status = status;
  184. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  185. EXIT(1, ("=%x\n", status));
  186. return status;
  187. } //SmbLiteIoctl
  188. /*++
  189. @doc INTERNAL
  190. @func NTSTATUS | GetBackLightBrightness |
  191. Query the Backlight brightness via the SMBus driver.
  192. @parm IN PSMBLITE_DEVEXT | devext | Points to the device extension.
  193. @parm OUT PSMBLITE_BRIGHTNESS | Brightness | To hold the brightness value.
  194. @rvalue Always returns STATUS_SUCCESS
  195. --*/
  196. NTSTATUS INTERNAL
  197. GetBackLightBrightness(
  198. IN PSMBLITE_DEVEXT devext,
  199. OUT PSMBLITE_BRIGHTNESS Brightness
  200. )
  201. {
  202. PROCNAME("GetBackLightBrightness")
  203. PAGED_CODE();
  204. ENTER(2, ("(devext=%p,Brightness=%p)\n", devext, Brightness));
  205. *Brightness = devext->BackLightBrightness;
  206. EXIT(2, ("=%x (ACValue=%d,DCValue=%d)\n",
  207. STATUS_SUCCESS, Brightness->bACValue, Brightness->bDCValue));
  208. return STATUS_SUCCESS;
  209. } //GetBackLightBrightness
  210. /*++
  211. @doc INTERNAL
  212. @func NTSTATUS | SetBackLightBrightness |
  213. Set the Backlight brightness via the SMBus driver.
  214. @parm IN PSMBLITE_DEVEXT | devext | Points to the device extension.
  215. @parm IN PSMBLITE_BRIGHTNESS | Brightness | The backlight brightness
  216. values.
  217. @parm IN BOOL | fSaveSettings | TRUE if need to save setting in the
  218. registry.
  219. @rvalue SUCCESS | returns STATUS_SUCCESS
  220. @rvalue FAILURE | returns NT status code
  221. --*/
  222. NTSTATUS INTERNAL
  223. SetBackLightBrightness(
  224. IN PSMBLITE_DEVEXT devext,
  225. IN PSMBLITE_BRIGHTNESS Brightness,
  226. IN BOOLEAN fSaveSettings
  227. )
  228. {
  229. PROCNAME("SetBackLightBrightness")
  230. NTSTATUS status;
  231. SMB_REQUEST SmbReq;
  232. UCHAR bBrightness;
  233. ENTER(2, ("(devext=%p,Brightness=%p,fSave=%x,ACValue=%d,DCValue=%d)\n",
  234. devext, Brightness, fSaveSettings, Brightness->bACValue,
  235. Brightness->bDCValue));
  236. //
  237. // Note: this routine must not be pageable because it could be called
  238. // by PowerStateCallbackProc which could be called at DPC.
  239. //
  240. bBrightness = (devext->dwfSmbLite & SMBLITEF_SYSTEM_ON_AC)?
  241. Brightness->bACValue: Brightness->bDCValue;
  242. DBGPRINT(1, ("Set Brightness level=%d (%s).\n",
  243. bBrightness,
  244. (devext->dwfSmbLite & SMBLITEF_SYSTEM_ON_AC)? "AC": "DC"));
  245. SmbReq.Protocol = SMB_WRITE_BYTE;
  246. SmbReq.Address = SMBADDR_BACKLIGHT;
  247. SmbReq.Command = SMBCMD_BACKLIGHT_NORMAL;
  248. SmbReq.Data[0] = (UCHAR)(bBrightness << 2);
  249. status = SMBRequest(devext, &SmbReq);
  250. if (NT_SUCCESS(status))
  251. {
  252. devext->BackLightBrightness = *Brightness;
  253. if (fSaveSettings)
  254. {
  255. RegSetDeviceParam(devext->PDO,
  256. gcwstrACBrightness,
  257. &Brightness->bACValue,
  258. sizeof(Brightness->bACValue));
  259. RegSetDeviceParam(devext->PDO,
  260. gcwstrDCBrightness,
  261. &Brightness->bDCValue,
  262. sizeof(Brightness->bDCValue));
  263. }
  264. }
  265. EXIT(2, ("=%x\n", status));
  266. return status;
  267. } //SetBackLightBrightness
  268. /*++
  269. @doc INTERNAL
  270. @func NTSTATUS | SMBRequest |
  271. Make a request to the SMBus driver.
  272. @parm IN PSMBLITE_DEVEXT | devext | Points to the device extension.
  273. @parm IN OUT PSMB_REQUEST | SmbReq | Points to the SMB request.
  274. @rvalue SUCCESS | returns STATUS_SUCCESS
  275. @rvalue FAILURE | returns NT status code
  276. --*/
  277. NTSTATUS INTERNAL
  278. SMBRequest(
  279. IN PSMBLITE_DEVEXT devext,
  280. IN OUT PSMB_REQUEST SmbReq
  281. )
  282. {
  283. PROCNAME("SMBRequest")
  284. NTSTATUS status;
  285. PIRP irp;
  286. KEVENT Event;
  287. IO_STATUS_BLOCK iosb;
  288. ENTER(2, ("(devext=%p,Req=%p,Protocol=%s,Addr=%x,Cmd=%x,Data0=%x,Data1=%x)\n",
  289. devext, SmbReq, LookupName(SmbReq->Protocol, ProtocolNames),
  290. SmbReq->Address, SmbReq->Command, SmbReq->Data[0],
  291. SmbReq->Data[1]));
  292. //
  293. // Note: this routine must not be pageable because it could be called
  294. // by SetBackLightBrightness and then PowerStateCallbackProc which could
  295. // be called at DPC.
  296. //
  297. KeInitializeEvent(&Event, NotificationEvent, FALSE);
  298. irp = IoBuildDeviceIoControlRequest(SMB_BUS_REQUEST,
  299. devext->LowerDevice,
  300. SmbReq,
  301. sizeof(SMB_REQUEST),
  302. NULL,
  303. 0,
  304. TRUE,
  305. &Event,
  306. &iosb);
  307. if (irp != NULL)
  308. {
  309. status = IoCallDriver(devext->LowerDevice, irp);
  310. if (status == STATUS_PENDING)
  311. {
  312. KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
  313. status = iosb.Status;
  314. }
  315. if (!NT_SUCCESS(status))
  316. {
  317. ERRPRINT(("failed SMB request ioctl (status=%x).\n", status));
  318. }
  319. }
  320. else
  321. {
  322. ERRPRINT(("failed to build smb request ioctl request.\n"));
  323. status = STATUS_INSUFFICIENT_RESOURCES;
  324. }
  325. EXIT(2, ("=%x\n", status));
  326. return status;
  327. } //SMBRequest
  328. /*++
  329. @doc INTERNAL
  330. @func NTSTATUS | RegQueryDeviceParam | Query the registry for a device
  331. parameter.
  332. @parm IN PDEVICE_OBJECT | DevObj | Points to the device object.
  333. @parm IN PCWSTR | pwstrParamName | Points to the param name string.
  334. @parm OUT PVOID | pbBuff | Points to the buffer to hold the result.
  335. @parm IN ULONG | dwcbLen | Specifies the length of the buffer.
  336. @rvalue SUCCESS | Returns STATUS_SUCCESS
  337. @rvalue FAILURE | Returns NT status code
  338. --*/
  339. NTSTATUS INTERNAL
  340. RegQueryDeviceParam(
  341. IN PDEVICE_OBJECT DevObj,
  342. IN PCWSTR pwstrParamName,
  343. OUT PVOID pbBuff,
  344. IN ULONG dwcbLen
  345. )
  346. {
  347. PROCNAME("RegQueryDeviceParam")
  348. NTSTATUS status;
  349. ULONG dwSize;
  350. PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
  351. PAGED_CODE();
  352. ENTER(2, ("(DevObj=%p,ParamName=%S,pbBuff=%p,Len=%d)\n",
  353. DevObj, pwstrParamName, pbBuff, dwcbLen));
  354. dwSize = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + dwcbLen;
  355. ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(
  356. NonPagedPool,
  357. dwSize,
  358. SMBLITE_POOLTAG);
  359. if (ValueInfo != NULL)
  360. {
  361. HANDLE hkey;
  362. status = IoOpenDeviceRegistryKey(DevObj,
  363. PLUGPLAY_REGKEY_DEVICE,
  364. STANDARD_RIGHTS_READ,
  365. &hkey);
  366. if (NT_SUCCESS(status))
  367. {
  368. UNICODE_STRING ucKeyName;
  369. RtlInitUnicodeString(&ucKeyName, pwstrParamName);
  370. status = ZwQueryValueKey(hkey,
  371. &ucKeyName,
  372. KeyValuePartialInformation,
  373. ValueInfo,
  374. dwSize,
  375. &dwSize);
  376. if (NT_SUCCESS(status))
  377. {
  378. ASSERT(ValueInfo->DataLength == dwcbLen);
  379. RtlCopyMemory(pbBuff, ValueInfo->Data, dwcbLen);
  380. }
  381. else
  382. {
  383. WARNPRINT(("failed to read parameter %S (status=%x)\n",
  384. pwstrParamName, status));
  385. }
  386. ZwClose(hkey);
  387. }
  388. else
  389. {
  390. ERRPRINT(("failed to open device registry key (status=%x)\n",
  391. status));
  392. }
  393. ExFreePool(ValueInfo);
  394. }
  395. else
  396. {
  397. status = STATUS_INSUFFICIENT_RESOURCES;
  398. ERRPRINT(("failed to allocate registry value buffer (size=%d)\n",
  399. dwSize));
  400. }
  401. EXIT(2, ("=%x\n", status));
  402. return status;
  403. } //RegQueryDeviceParam
  404. /*++
  405. @doc INTERNAL
  406. @func NTSTATUS | RegSetDeviceParam | Set a device parameter into the
  407. registry.
  408. @parm IN PDEVICE_OBJECT | DevObj | Points to the device object.
  409. @parm IN PCWSTR | pwstrParamName | Points to the param name string.
  410. @parm IN PVOID | pbBuff | Points to the buffer containing data.
  411. @parm IN ULONG | dwcbLen | Specifies the length of the buffer.
  412. @rvalue SUCCESS | Returns STATUS_SUCCESS
  413. @rvalue FAILURE | Returns NT status code
  414. --*/
  415. NTSTATUS INTERNAL
  416. RegSetDeviceParam(
  417. IN PDEVICE_OBJECT DevObj,
  418. IN PCWSTR pwstrParamName,
  419. IN PVOID pbBuff,
  420. IN ULONG dwcbLen
  421. )
  422. {
  423. PROCNAME("RegSetDeviceParam")
  424. NTSTATUS status;
  425. HANDLE hkey;
  426. ENTER(2, ("(DevObj=%p,ParamName=%S,pbBuff=%p,Len=%d)\n",
  427. DevObj, pwstrParamName, pbBuff, dwcbLen));
  428. //
  429. // Note: this routine must not be pageable because it could be called
  430. // by SetBackLightBrightness and then PowerStateCallbackProc which could
  431. // be called at DPC.
  432. //
  433. status = IoOpenDeviceRegistryKey(DevObj,
  434. PLUGPLAY_REGKEY_DEVICE,
  435. STANDARD_RIGHTS_WRITE,
  436. &hkey);
  437. if (NT_SUCCESS(status))
  438. {
  439. UNICODE_STRING ucKeyName;
  440. RtlInitUnicodeString(&ucKeyName, pwstrParamName);
  441. status = ZwSetValueKey(hkey,
  442. &ucKeyName,
  443. 0,
  444. REG_BINARY,
  445. pbBuff,
  446. dwcbLen);
  447. if (!NT_SUCCESS(status))
  448. {
  449. WARNPRINT(("failed to write device parameter %S (status=%x)\n",
  450. pwstrParamName, status));
  451. }
  452. ZwClose(hkey);
  453. }
  454. else
  455. {
  456. ERRPRINT(("failed to open device registry key (status=%x)\n",
  457. status));
  458. }
  459. EXIT(2, ("=%x\n", status));
  460. return status;
  461. } //RegSetDeviceParam