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.

622 lines
18 KiB

  1. #define UNICODE
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <windows.h>
  8. #include <mmsystem.h>
  9. #include <winsock2.h>
  10. #include <af_irda.h>
  11. #include <irioctl.h>
  12. #include <irtypes.h>
  13. #include <resrc1.h>
  14. #include "internal.h"
  15. #define MAX_ATTRIB_LEN 64
  16. #define DEVICE_LIST_LEN 5
  17. #define IRDA_DEVICE_NAME TEXT("\\Device\\IrDA")
  18. #define DISCOVERY_BUFFER_SIZE (sizeof(DEVICELIST) - \
  19. sizeof(IRDA_DEVICE_INFO) + \
  20. (sizeof(IRDA_DEVICE_INFO) * DEVICE_LIST_LEN))
  21. typedef struct _IR_DISCOVERY_OBJECT {
  22. BOOL Closing;
  23. LONG ReferenceCount;
  24. HANDLE DeviceHandle;
  25. SOCKET Socket;
  26. HWND WindowHandle;
  27. UINT DiscoveryWindowMessage;
  28. UINT LinkWindowMessage;
  29. HANDLE TimerHandle;
  30. IO_STATUS_BLOCK DiscoveryStatusBlock;
  31. IO_STATUS_BLOCK LinkStateStatusBlock;
  32. BYTE IoDeviceListBuffer[DISCOVERY_BUFFER_SIZE];
  33. BYTE CurrentDeviceListBuffer[DISCOVERY_BUFFER_SIZE];
  34. IRLINK_STATUS IoLinkStatus;
  35. IRLINK_STATUS CurrentLinkStatus;
  36. } IR_DISCOVERY_OBJECT, *PIR_DISCOVERY_OBJECT;
  37. VOID WINAPI
  38. TimerApcRoutine(
  39. PIR_DISCOVERY_OBJECT DiscoveryObject,
  40. DWORD LowTime,
  41. DWORD HighTime
  42. );
  43. VOID
  44. WINAPI
  45. DiscoverComplete(
  46. PVOID ApcContext,
  47. PIO_STATUS_BLOCK IoStatusBlock,
  48. DWORD Reserved
  49. );
  50. VOID
  51. WINAPI
  52. LinkStatusComplete(
  53. PVOID ApcContext,
  54. PIO_STATUS_BLOCK IoStatusBlock,
  55. DWORD Reserved
  56. );
  57. int
  58. QueryIASForInteger(SOCKET QuerySock,
  59. u_char *pirdaDeviceID,
  60. char *pClassName,
  61. int ClassNameLen, // including trailing NULL
  62. char *pAttribute,
  63. int AttributeLen, // including trailing NULL
  64. int *pValue)
  65. {
  66. BYTE IASQueryBuff[sizeof(IAS_QUERY) - 3 + MAX_ATTRIB_LEN];
  67. int IASQueryLen = sizeof(IASQueryBuff);
  68. PIAS_QUERY pIASQuery = (PIAS_QUERY) &IASQueryBuff[0];
  69. #if DBG
  70. if (!((ClassNameLen > 0 && ClassNameLen <= IAS_MAX_CLASSNAME) &&
  71. (AttributeLen > 0 && AttributeLen <= IAS_MAX_ATTRIBNAME)))
  72. {
  73. DEBUGMSG(("IRMON2: QueryIASForInteger, bad parms\n"));
  74. return(SOCKET_ERROR);
  75. }
  76. #endif
  77. RtlCopyMemory(&pIASQuery->irdaDeviceID[0], pirdaDeviceID, 4);
  78. RtlCopyMemory(&pIASQuery->irdaClassName[0], pClassName, ClassNameLen);
  79. RtlCopyMemory(&pIASQuery->irdaAttribName[0], pAttribute, AttributeLen);
  80. if (getsockopt(QuerySock, SOL_IRLMP, IRLMP_IAS_QUERY,
  81. (char *) pIASQuery, &IASQueryLen) == SOCKET_ERROR)
  82. {
  83. #if 0
  84. DEBUGMSG(("IRMON2: IAS Query [\"%s\",\"%s\"] failed %ws\n",
  85. pIASQuery->irdaClassName,
  86. pIASQuery->irdaAttribName,
  87. GetLastErrorText()));
  88. #endif
  89. return SOCKET_ERROR;
  90. }
  91. if (pIASQuery->irdaAttribType != IAS_ATTRIB_INT)
  92. {
  93. DEBUGMSG(("IRMON2: IAS Query [\"%s\",\"%s\"] irdaAttribType not int (%d)\n",
  94. pIASQuery->irdaClassName,
  95. pIASQuery->irdaAttribName,
  96. pIASQuery->irdaAttribType));
  97. return SOCKET_ERROR;
  98. }
  99. *pValue = pIASQuery->irdaAttribute.irdaAttribInt;
  100. return(0);
  101. }
  102. HANDLE
  103. CreateIrDiscoveryObject(
  104. HWND WindowHandle,
  105. UINT DiscoveryWindowMessage,
  106. UINT LinkWindowMessage
  107. )
  108. {
  109. PIR_DISCOVERY_OBJECT DiscoveryObject;
  110. LONGLONG DueTime=Int32x32To64(2000,-10000);
  111. DiscoveryObject=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*DiscoveryObject));
  112. if (DiscoveryObject == NULL) {
  113. return NULL;
  114. }
  115. DiscoveryObject->WindowHandle=WindowHandle;
  116. DiscoveryObject->DiscoveryWindowMessage=DiscoveryWindowMessage;
  117. DiscoveryObject->LinkWindowMessage=LinkWindowMessage;
  118. DiscoveryObject->DeviceHandle=INVALID_HANDLE_VALUE;
  119. DiscoveryObject->Socket=INVALID_SOCKET;
  120. DiscoveryObject->TimerHandle=CreateWaitableTimer(NULL,FALSE,NULL);
  121. if (DiscoveryObject->TimerHandle == NULL) {
  122. HeapFree(GetProcessHeap(),0,DiscoveryObject);
  123. return NULL;
  124. }
  125. DiscoveryObject->ReferenceCount=1;
  126. SetWaitableTimer(
  127. DiscoveryObject->TimerHandle,
  128. (LARGE_INTEGER*)&DueTime,
  129. 0,
  130. TimerApcRoutine,
  131. DiscoveryObject,
  132. FALSE
  133. );
  134. return (HANDLE)DiscoveryObject;
  135. }
  136. VOID
  137. RemoveRefCount(
  138. PIR_DISCOVERY_OBJECT DiscoveryObject
  139. )
  140. {
  141. LONG Count=InterlockedDecrement(&DiscoveryObject->ReferenceCount);
  142. if (Count == 0) {
  143. CancelWaitableTimer(DiscoveryObject->TimerHandle);
  144. CloseHandle(DiscoveryObject->TimerHandle);
  145. if (DiscoveryObject->DeviceHandle != INVALID_HANDLE_VALUE) {
  146. CancelIo(DiscoveryObject->DeviceHandle);
  147. CloseHandle(DiscoveryObject->DeviceHandle);
  148. }
  149. if (DiscoveryObject->Socket != INVALID_SOCKET) {
  150. closesocket(DiscoveryObject->Socket);
  151. }
  152. DbgPrint("IRMON2: discovery object closed\n");
  153. HeapFree(GetProcessHeap(),0,DiscoveryObject);
  154. }
  155. return;
  156. }
  157. VOID
  158. CloseIrDiscoveryObject(
  159. HANDLE Object
  160. )
  161. {
  162. PIR_DISCOVERY_OBJECT DiscoveryObject=Object;
  163. DiscoveryObject->Closing=TRUE;
  164. if (DiscoveryObject->DeviceHandle != INVALID_HANDLE_VALUE) {
  165. CancelIo(DiscoveryObject->DeviceHandle);
  166. }
  167. return;
  168. }
  169. VOID WINAPI
  170. TimerApcRoutine(
  171. PIR_DISCOVERY_OBJECT DiscoveryObject,
  172. DWORD LowTime,
  173. DWORD HighTime
  174. )
  175. {
  176. IO_STATUS_BLOCK IoStatusBlock;
  177. UNICODE_STRING DeviceName;
  178. OBJECT_ATTRIBUTES ObjAttr;
  179. NTSTATUS Status;
  180. LONGLONG DueTime=Int32x32To64(10000,-10000);
  181. if (DiscoveryObject->Closing) {
  182. RemoveRefCount(DiscoveryObject);
  183. return;
  184. }
  185. if (DiscoveryObject->DeviceHandle == INVALID_HANDLE_VALUE) {
  186. // Open the stack and issue lazy discovery and status ioctls
  187. RtlInitUnicodeString(&DeviceName, IRDA_DEVICE_NAME);
  188. InitializeObjectAttributes(
  189. &ObjAttr,
  190. &DeviceName,
  191. OBJ_CASE_INSENSITIVE,
  192. NULL,
  193. NULL
  194. );
  195. Status = NtCreateFile(
  196. &DiscoveryObject->DeviceHandle, // PHANDLE FileHandle
  197. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, // ACCESS_MASK DesiredAccess
  198. &ObjAttr, // POBJECT_ATTRIBUTES ObjAttr
  199. &IoStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  200. NULL, // PLARGE_INTEGER AllocationSize
  201. FILE_ATTRIBUTE_NORMAL, // ULONG FileAttributes
  202. FILE_SHARE_READ |
  203. FILE_SHARE_WRITE, // ULONG ShareAccess
  204. FILE_OPEN_IF, // ULONG CreateDisposition
  205. 0, // ULONG CreateOptions
  206. NULL, // PVOID EaBuffer
  207. 0); // ULONG EaLength
  208. if (!NT_SUCCESS(Status)) {
  209. DEBUGMSG(("IRMON2: NtCreateFile irda.sys failed %08lx\n",Status));
  210. DiscoveryObject->DeviceHandle=INVALID_HANDLE_VALUE;
  211. SetWaitableTimer(
  212. DiscoveryObject->TimerHandle,
  213. (LARGE_INTEGER*)&DueTime,
  214. 0,
  215. TimerApcRoutine,
  216. DiscoveryObject,
  217. FALSE
  218. );
  219. return;
  220. }
  221. // Flush IrDA's discovery cache because the user may log out
  222. // and devices will remain in the cache. When they log back in
  223. // the device would then appear briefly.
  224. NtDeviceIoControlFile(
  225. DiscoveryObject->DeviceHandle, // HANDLE FileHandle
  226. NULL, // HANDLE Event OPTIONAL
  227. NULL, // PIO_APC_ROUTINE ApcRoutine
  228. NULL, // PVOID ApcContext
  229. &IoStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  230. IOCTL_IRDA_FLUSH_DISCOVERY_CACHE,// ULONG IoControlCode
  231. NULL, // PVOID InputBuffer
  232. 0, // ULONG InputBufferLength
  233. NULL, // PVOID OutputBuffer
  234. 0); // ULONG OutputBufferLength
  235. DiscoveryObject->Socket = socket(AF_IRDA, SOCK_STREAM, 0);
  236. if (DiscoveryObject->Socket == INVALID_SOCKET) {
  237. // DEBUGMSG(("IRMON2: socket() error: %ws\n", GetLastErrorText()));
  238. CloseHandle(DiscoveryObject->DeviceHandle);
  239. DiscoveryObject->DeviceHandle=INVALID_HANDLE_VALUE;
  240. SetWaitableTimer(
  241. DiscoveryObject->TimerHandle,
  242. (LARGE_INTEGER*)&DueTime,
  243. 0,
  244. TimerApcRoutine,
  245. DiscoveryObject,
  246. FALSE
  247. );
  248. return;
  249. } else {
  250. DEBUGMSG(("IRMON2: socket created (%d).\n", DiscoveryObject->Socket));
  251. }
  252. }
  253. Status = NtDeviceIoControlFile(
  254. DiscoveryObject->DeviceHandle, // HANDLE FileHandle
  255. NULL, // HANDLE Event OPTIONAL
  256. DiscoverComplete,// PIO_APC_ROUTINE ApcRoutine
  257. DiscoveryObject, // PVOID ApcContext
  258. &DiscoveryObject->DiscoveryStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  259. IOCTL_IRDA_LAZY_DISCOVERY,
  260. NULL, // PVOID InputBuffer
  261. 0, // ULONG InputBufferLength
  262. &DiscoveryObject->IoDeviceListBuffer[0], // PVOID OutputBuffer
  263. sizeof(DiscoveryObject->IoDeviceListBuffer) // ULONG OutputBufferLength
  264. );
  265. if (!NT_SUCCESS(Status)) {
  266. SetWaitableTimer(
  267. DiscoveryObject->TimerHandle,
  268. (LARGE_INTEGER*)&DueTime,
  269. 0,
  270. TimerApcRoutine,
  271. DiscoveryObject,
  272. FALSE
  273. );
  274. }
  275. InterlockedIncrement(&DiscoveryObject->ReferenceCount);
  276. Status = NtDeviceIoControlFile(
  277. DiscoveryObject->DeviceHandle, // HANDLE FileHandle
  278. NULL, // HANDLE Event OPTIONAL
  279. LinkStatusComplete,// PIO_APC_ROUTINE ApcRoutine
  280. DiscoveryObject, // PVOID ApcContext
  281. &DiscoveryObject->LinkStateStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  282. IOCTL_IRDA_LINK_STATUS, // ULONG IoControlCode
  283. NULL, // PVOID InputBuffer
  284. 0, // ULONG InputBufferLength
  285. &DiscoveryObject->IoLinkStatus, // PVOID OutputBuffer
  286. sizeof(DiscoveryObject->IoLinkStatus) // ULONG OutputBufferLength
  287. );
  288. if (!NT_SUCCESS(Status)) {
  289. RemoveRefCount(DiscoveryObject);
  290. }
  291. return;
  292. }
  293. VOID
  294. WINAPI
  295. DiscoverComplete(
  296. PVOID ApcContext,
  297. PIO_STATUS_BLOCK IoStatusBlock,
  298. DWORD Reserved
  299. )
  300. {
  301. NTSTATUS Status;
  302. LONGLONG DueTime=Int32x32To64(10000,-10000);
  303. PIR_DISCOVERY_OBJECT DiscoveryObject=ApcContext;
  304. PDEVICELIST devices=(PDEVICELIST)&DiscoveryObject->CurrentDeviceListBuffer[0];
  305. CopyMemory(
  306. &DiscoveryObject->CurrentDeviceListBuffer[0],
  307. &DiscoveryObject->IoDeviceListBuffer[0],
  308. sizeof(DiscoveryObject->IoDeviceListBuffer)
  309. );
  310. if (DiscoveryObject->Closing) {
  311. RemoveRefCount(DiscoveryObject);
  312. return;
  313. }
  314. if (NT_SUCCESS(IoStatusBlock->Status) && (IoStatusBlock->Information >= sizeof(ULONG))) {
  315. PostMessage(
  316. DiscoveryObject->WindowHandle,
  317. DiscoveryObject->DiscoveryWindowMessage,
  318. 0,
  319. 0
  320. );
  321. } else {
  322. devices->numDevice=0;
  323. }
  324. Status = NtDeviceIoControlFile(
  325. DiscoveryObject->DeviceHandle, // HANDLE FileHandle
  326. NULL, // HANDLE Event OPTIONAL
  327. DiscoverComplete,// PIO_APC_ROUTINE ApcRoutine
  328. DiscoveryObject, // PVOID ApcContext
  329. &DiscoveryObject->DiscoveryStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  330. IOCTL_IRDA_LAZY_DISCOVERY,
  331. NULL, // PVOID InputBuffer
  332. 0, // ULONG InputBufferLength
  333. &DiscoveryObject->IoDeviceListBuffer[0], // PVOID OutputBuffer
  334. sizeof(DiscoveryObject->IoDeviceListBuffer) // ULONG OutputBufferLength
  335. );
  336. if (!NT_SUCCESS(Status)) {
  337. SetWaitableTimer(
  338. DiscoveryObject->TimerHandle,
  339. (LARGE_INTEGER*)&DueTime,
  340. 0,
  341. TimerApcRoutine,
  342. DiscoveryObject,
  343. FALSE
  344. );
  345. }
  346. return;
  347. }
  348. VOID
  349. WINAPI
  350. LinkStatusComplete(
  351. PVOID ApcContext,
  352. PIO_STATUS_BLOCK IoStatusBlock,
  353. DWORD Reserved
  354. )
  355. {
  356. NTSTATUS Status;
  357. PIR_DISCOVERY_OBJECT DiscoveryObject=ApcContext;
  358. CopyMemory(
  359. &DiscoveryObject->CurrentLinkStatus,
  360. &DiscoveryObject->IoLinkStatus,
  361. sizeof(DiscoveryObject->IoLinkStatus)
  362. );
  363. PostMessage(
  364. DiscoveryObject->WindowHandle,
  365. DiscoveryObject->LinkWindowMessage,
  366. 0,
  367. 0
  368. );
  369. Status = NtDeviceIoControlFile(
  370. DiscoveryObject->DeviceHandle, // HANDLE FileHandle
  371. NULL, // HANDLE Event OPTIONAL
  372. LinkStatusComplete,// PIO_APC_ROUTINE ApcRoutine
  373. DiscoveryObject, // PVOID ApcContext
  374. &DiscoveryObject->LinkStateStatusBlock, // PIO_STATUS_BLOCK IoStatusBlock
  375. IOCTL_IRDA_LINK_STATUS, // ULONG IoControlCode
  376. NULL, // PVOID InputBuffer
  377. 0, // ULONG InputBufferLength
  378. &DiscoveryObject->IoLinkStatus, // PVOID OutputBuffer
  379. sizeof(DiscoveryObject->IoLinkStatus) // ULONG OutputBufferLength
  380. );
  381. if (!NT_SUCCESS(Status)) {
  382. RemoveRefCount(DiscoveryObject);
  383. }
  384. }
  385. LONG
  386. GetDeviceList(
  387. HANDLE Object,
  388. OBEX_DEVICE_LIST * List,
  389. ULONG *ListBufferSize
  390. )
  391. {
  392. PIR_DISCOVERY_OBJECT DiscoveryObject=Object;
  393. ULONG BufferSizeNeeded;
  394. ULONG i;
  395. PDEVICELIST devices=(PDEVICELIST)&DiscoveryObject->CurrentDeviceListBuffer[0];
  396. BufferSizeNeeded=(devices->numDevice * sizeof(OBEX_DEVICE)) + FIELD_OFFSET(OBEX_DEVICE_LIST,DeviceList);
  397. if (*ListBufferSize < BufferSizeNeeded) {
  398. *ListBufferSize= BufferSizeNeeded;
  399. return ERROR_INSUFFICIENT_BUFFER;
  400. }
  401. ZeroMemory(List,*ListBufferSize);
  402. for (i=0; i<devices->numDevice; i++) {
  403. //
  404. // the irda device name buffer is 23 bytes in size and may ahve either ascii or
  405. // unicode chars. Add enough bytes to round up the an even number of unicode chars
  406. // plus a null terminator.
  407. //
  408. UCHAR TempBuffer[sizeof(devices->Device[i].irdaDeviceName)+3];
  409. unsigned MaxCharCount;
  410. CopyMemory(
  411. &List->DeviceList[i].DeviceSpecific.s.Irda.DeviceId,
  412. &devices->Device[i].irdaDeviceID,
  413. sizeof(ULONG)
  414. );
  415. List->DeviceList[i].DeviceType=TYPE_IRDA;
  416. //
  417. // zero out the whole buffer and then copy the string from the device to make sure it
  418. // is null terminated
  419. //
  420. ZeroMemory(&TempBuffer[0],sizeof(TempBuffer));
  421. CopyMemory(&TempBuffer[0],devices->Device[i].irdaDeviceName,sizeof(devices->Device[i].irdaDeviceName));
  422. //
  423. // get the character count of unicode destination buffer
  424. //
  425. MaxCharCount = sizeof(List->DeviceList[i].DeviceName)/sizeof(wchar_t);
  426. if (devices->Device[i].irdaCharSet != LmCharSetUNICODE) {
  427. MultiByteToWideChar(CP_ACP, 0,
  428. &TempBuffer[0],
  429. -1, // NULL terminated string
  430. List->DeviceList[i].DeviceName,
  431. MaxCharCount
  432. );
  433. } else {
  434. //
  435. // the name is in unicode
  436. //
  437. wcsncpy( List->DeviceList[i].DeviceName,
  438. (wchar_t *)&TempBuffer[0],
  439. MaxCharCount
  440. );
  441. //
  442. // Assure that it is NULL-terminated.
  443. //
  444. List->DeviceList[i].DeviceName[ MaxCharCount-1 ] = 0;
  445. }
  446. List->DeviceCount++;
  447. }
  448. return ERROR_SUCCESS;
  449. }
  450. VOID
  451. GetLinkStatus(
  452. HANDLE Object,
  453. IRLINK_STATUS *LinkStatus
  454. )
  455. {
  456. PIR_DISCOVERY_OBJECT DiscoveryObject=Object;
  457. *LinkStatus=DiscoveryObject->CurrentLinkStatus;
  458. return;
  459. }