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.

464 lines
14 KiB

  1. //////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // utils.cpp
  7. //
  8. // Abstract:
  9. // This module contains general utility functions.
  10. //
  11. //////////////////////////////////////////////////////////////////////////
  12. #include "stdafx.h"
  13. // ---------------------------------------------------------
  14. //
  15. // Function: TdiLibStatusMessage
  16. //
  17. // Arguments: ulGeneralStatus -- NTSTATUS value to search
  18. //
  19. // Returns: String with message to print
  20. //
  21. // Descript: This function finds and returns a string corresponding
  22. // to the status passed in..
  23. //
  24. // ----------------------------------------------------------
  25. TCHAR *
  26. TdiLibStatusMessage(NTSTATUS lStatus)
  27. {
  28. static TCHAR UnknownMess[64];
  29. TCHAR *Message;
  30. switch(lStatus)
  31. {
  32. case STATUS_SUCCESS:
  33. Message = TEXT("STATUS_SUCCESS");
  34. break;
  35. case STATUS_UNSUCCESSFUL:
  36. Message = TEXT("STATUS_UNSUCCESSFUL");
  37. break;
  38. case STATUS_NOT_IMPLEMENTED:
  39. Message = TEXT("STATUS_NOT_IMPLEMENTED");
  40. break;
  41. case STATUS_INVALID_HANDLE:
  42. Message = TEXT("STATUS_INVALID_HANDLE");
  43. break;
  44. case STATUS_INVALID_PARAMETER:
  45. Message = TEXT("STATUS_INVALID_PARAMETER");
  46. break;
  47. case STATUS_INVALID_DEVICE_REQUEST:
  48. Message = TEXT("STATUS_INVALID_DEVICE_REQUEST");
  49. break;
  50. case STATUS_INSUFFICIENT_RESOURCES:
  51. Message = TEXT("STATUS_INSUFFICIENT_RESOURCES");
  52. break;
  53. case STATUS_NOT_SUPPORTED:
  54. Message = TEXT("STATUS_NOT_SUPPORTED");
  55. break;
  56. case STATUS_BUFFER_OVERFLOW:
  57. Message = TEXT("STATUS_BUFFER_OVERFLOW");
  58. break;
  59. case STATUS_PENDING:
  60. Message = TEXT("STATUS_PENDING");
  61. break;
  62. case STATUS_CONNECTION_REFUSED:
  63. Message = TEXT("STATUS_CONNECTION_REFUSED");
  64. break;
  65. case STATUS_GRACEFUL_DISCONNECT:
  66. Message = TEXT("STATUS_GRACEFUL_DISCONNECT");
  67. break;
  68. case STATUS_ADDRESS_ALREADY_ASSOCIATED:
  69. Message = TEXT("STATUS_ADDRESS_ALREADY_ASSOCIATED");
  70. break;
  71. case STATUS_ADDRESS_NOT_ASSOCIATED:
  72. Message = TEXT("STATUS_ADDRESS_NOT_ASSOCIATED");
  73. break;
  74. case STATUS_INVALID_CONNECTION:
  75. Message = TEXT("STATUS_INVALID_CONNECTION");
  76. break;
  77. case STATUS_CONNECTION_INVALID:
  78. Message = TEXT("STATUS_CONNECTION_INVALID");
  79. break;
  80. case STATUS_CONNECTION_DISCONNECTED:
  81. Message = TEXT("STATUS_CONNECTION_DISCONNECTED");
  82. break;
  83. case STATUS_INVALID_ADDRESS_COMPONENT:
  84. Message = TEXT("STATUS_INVALID_ADDRESS_COMPONENT");
  85. break;
  86. case STATUS_LOCAL_DISCONNECT:
  87. Message = TEXT("STATUS_LOCAL_DISCONNECT");
  88. break;
  89. case STATUS_LINK_TIMEOUT:
  90. Message = TEXT("STATUS_LINK_TIMEOUT");
  91. break;
  92. case STATUS_IO_TIMEOUT:
  93. Message = TEXT("STATUS_IO_TIMEOUT");
  94. break;
  95. case STATUS_REMOTE_NOT_LISTENING:
  96. Message = TEXT("STATUS_REMOTE_NOT_LISTENING");
  97. break;
  98. case STATUS_BAD_NETWORK_PATH:
  99. Message = TEXT("STATUS_BAD_NETWORK_PATH");
  100. break;
  101. case TDI_STATUS_TIMEDOUT:
  102. Message = TEXT("TDI_STATUS_TIMEDOUT");
  103. break;
  104. default:
  105. _stprintf(UnknownMess, TEXT("STATUS_UNKNOWN [0x%x]"), lStatus);
  106. Message = UnknownMess;
  107. break;
  108. };
  109. return Message;
  110. }
  111. // ---------------------------------------------------------
  112. //
  113. // Function: DoPrintAddress
  114. //
  115. // Arguments: pTransportAddress -- address to print
  116. //
  117. // Returns: none
  118. //
  119. // Descript: This function prints the address information
  120. // of the address passed in
  121. //
  122. // ----------------------------------------------------------
  123. VOID
  124. DoPrintAddress(PTRANSPORT_ADDRESS pTransportAddress)
  125. {
  126. switch(pTransportAddress->Address[0].AddressType)
  127. {
  128. case TDI_ADDRESS_TYPE_IP:
  129. {
  130. PTDI_ADDRESS_IP pTdiAddressIp
  131. = (PTDI_ADDRESS_IP)pTransportAddress->Address[0].Address;
  132. PUCHAR pucTemp
  133. = (PUCHAR)&pTdiAddressIp->in_addr;
  134. _tprintf(TEXT("TDI_ADDRESS_TYPE_IP\n")
  135. TEXT("sin_port = 0x%04x\n")
  136. TEXT("in_addr = %u.%u.%u.%u\n"),
  137. pTdiAddressIp->sin_port,
  138. pucTemp[0], pucTemp[1],
  139. pucTemp[2], pucTemp[3]);
  140. }
  141. break;
  142. case TDI_ADDRESS_TYPE_IPX:
  143. {
  144. PTDI_ADDRESS_IPX pTdiAddressIpx
  145. = (PTDI_ADDRESS_IPX)pTransportAddress->Address[0].Address;
  146. _tprintf(TEXT("TDI_ADDRESS_TYPE_IPX\n")
  147. TEXT("NetworkAddress = 0x%08x\n")
  148. TEXT("NodeAddress = %u.%u.%u.%u.%u.%u\n")
  149. TEXT("Socket = 0x%04x\n"),
  150. pTdiAddressIpx->NetworkAddress,
  151. pTdiAddressIpx->NodeAddress[0],
  152. pTdiAddressIpx->NodeAddress[1],
  153. pTdiAddressIpx->NodeAddress[2],
  154. pTdiAddressIpx->NodeAddress[3],
  155. pTdiAddressIpx->NodeAddress[4],
  156. pTdiAddressIpx->NodeAddress[5],
  157. pTdiAddressIpx->Socket);
  158. }
  159. break;
  160. case TDI_ADDRESS_TYPE_NETBIOS:
  161. {
  162. PTDI_ADDRESS_NETBIOS pTdiAddressNetbios
  163. = (PTDI_ADDRESS_NETBIOS)pTransportAddress->Address[0].Address;
  164. TCHAR pucName[17];
  165. //
  166. // make sure we have a zero-terminated name to print...
  167. //
  168. memcpy(pucName, pTdiAddressNetbios->NetbiosName, 16 * sizeof(TCHAR));
  169. pucName[16] = 0;
  170. _putts(TEXT("TDI_ADDRESS_TYPE_NETBIOS\n")
  171. TEXT("NetbiosNameType = TDI_ADDRESS_NETBIOS_TYPE_"));
  172. switch (pTdiAddressNetbios->NetbiosNameType)
  173. {
  174. case TDI_ADDRESS_NETBIOS_TYPE_UNIQUE:
  175. _putts(TEXT("UNIQUE\n"));
  176. break;
  177. case TDI_ADDRESS_NETBIOS_TYPE_GROUP:
  178. _putts(TEXT("GROUP\n"));
  179. break;
  180. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_UNIQUE:
  181. _putts(TEXT("QUICK_UNIQUE\n"));
  182. break;
  183. case TDI_ADDRESS_NETBIOS_TYPE_QUICK_GROUP:
  184. _putts(TEXT("QUICK_GROUP\n"));
  185. break;
  186. default:
  187. _tprintf(TEXT("INVALID [0x%04x]\n"),
  188. pTdiAddressNetbios->NetbiosNameType);
  189. break;
  190. }
  191. _tprintf(TEXT("NetbiosName = %s\n"), pucName);
  192. }
  193. break;
  194. }
  195. }
  196. // -----------------------------------------------------------------
  197. //
  198. // Function: TdiLibDeviceIO
  199. //
  200. // Arguments: ulCommandCode -- command code of operation to perform
  201. // pSendBuffer -- data structure containing arguments for driver
  202. // pReceiveBuffer-- data structure containing return values from
  203. // driver
  204. // NOTE: all are passed thru unchanged to DeviceIoControl
  205. //
  206. // Returns: Final status of operation -- STATUS_SUCCESS or failure code
  207. //
  208. // Descript: This function acts as a "wrapper" for DeviceIoControl, and is
  209. // used by those functions that really want a synchronous call,
  210. // but don't want to be hung up in the driver. If a call to
  211. // DeviceIoControl pends, this function waits for up to a minute
  212. // for it to complete. If it doesn't complete within a minute,
  213. // it assumes something is drastically wrong and returns a time-
  214. // out error. If a function completes before then, it gets the
  215. // final completion code and returns that. Hence,
  216. // STATUS_PENDING should never be returned by this function.
  217. //
  218. // Status: ok
  219. //
  220. // -----------------------------------------------------------------
  221. NTSTATUS
  222. TdiLibDeviceIO(ULONG ulCommandCode,
  223. PSEND_BUFFER pSendBuffer,
  224. PRECEIVE_BUFFER pReceiveBuffer)
  225. {
  226. NTSTATUS lStatus; // final status from command
  227. OVERLAPPED *pOverLapped // structure for asynchronous completion
  228. = (OVERLAPPED *)LocalAllocateMemory(sizeof(OVERLAPPED));
  229. //
  230. // create the event to wait on
  231. //
  232. pOverLapped->hEvent = CreateEvent(NULL, // non-inheritable
  233. TRUE, // manually signalled
  234. TRUE, // initially signalled
  235. NULL); // un-named
  236. //
  237. // need the event object to do asynchronous calls
  238. //
  239. if (pOverLapped->hEvent != NULL)
  240. {
  241. pOverLapped->Offset = 0;
  242. pOverLapped->OffsetHigh = 0;
  243. lStatus = TdiLibStartDeviceIO(ulCommandCode,
  244. pSendBuffer,
  245. pReceiveBuffer,
  246. pOverLapped);
  247. if (lStatus == STATUS_PENDING)
  248. {
  249. ULONG ulTimeOut = 60; // 60 seconds
  250. for (;;)
  251. {
  252. lStatus = TdiLibWaitForDeviceIO(pOverLapped);
  253. if (lStatus == STATUS_SUCCESS)
  254. {
  255. lStatus = pReceiveBuffer->lStatus;
  256. break;
  257. }
  258. else if (lStatus == TDI_STATUS_TIMEDOUT)
  259. {
  260. if (--ulTimeOut == 0)
  261. {
  262. SEND_BUFFER SendBuffer;
  263. RECEIVE_BUFFER ReceiveBuffer;
  264. TdiLibDeviceIO(ulABORT_COMMAND,
  265. &SendBuffer,
  266. &ReceiveBuffer);
  267. ulTimeOut = 60;
  268. }
  269. }
  270. else // some type of error case
  271. {
  272. lStatus = STATUS_UNSUCCESSFUL;
  273. break;
  274. }
  275. }
  276. }
  277. CloseHandle(pOverLapped->hEvent);
  278. }
  279. //
  280. // get here if CreateEvent failed
  281. //
  282. else
  283. {
  284. OutputDebugString(TEXT("TdiLibDeviceIo: CreateEvent failed\n"));
  285. lStatus = STATUS_UNSUCCESSFUL;
  286. }
  287. if (lStatus != TDI_STATUS_TIMEDOUT)
  288. {
  289. LocalFreeMemory(pOverLapped);
  290. }
  291. if (lStatus == STATUS_SUCCESS)
  292. {
  293. lStatus = pReceiveBuffer->lStatus;
  294. }
  295. return lStatus;
  296. }
  297. // -----------------------------------------------------------------
  298. //
  299. // Function: TdiLibStartDeviceIO
  300. //
  301. // Arguments: ulCommandCode -- control code of operation to perform
  302. // pSendBuffer -- data structure containing arguments for driver
  303. // pReceiveBuffer-- data structure containing return values from
  304. // driver
  305. // pOverlapped -- overlapped structure
  306. // NOTE: all are passed thru unchanged to DeviceIoControl
  307. //
  308. // Returns: Status of operation -- STATUS_PENDING, STATUS_SUCCESS, or failure code
  309. //
  310. // Descript: This function acts as a "wrapper" for DeviceIoControl, and is
  311. // used by those functions that need an asynchronous call. It
  312. // is used in association with TdiWaitForDeviceIO (which
  313. // checks to see if it is complete)
  314. //
  315. // Status: ok
  316. //
  317. // -----------------------------------------------------------------
  318. NTSTATUS
  319. TdiLibStartDeviceIO(ULONG ulCommandCode,
  320. PSEND_BUFFER pSendBuffer,
  321. PRECEIVE_BUFFER pReceiveBuffer,
  322. OVERLAPPED *pOverLapped)
  323. {
  324. NTSTATUS lStatus; // final status...
  325. ULONG ulBytesReturned; // bytes stored in OutBuffer
  326. ULONG fResult; // immediate result of DeviceIoControl
  327. //
  328. // following call to the driver will return TRUE on SUCCESS_SUCCESS,
  329. // FALSE on everything else
  330. //
  331. EnterCriticalSection(&LibCriticalSection);
  332. fResult = DeviceIoControl(hTdiSampleDriver,
  333. ulTdiCommandToIoctl(ulCommandCode),
  334. pSendBuffer,
  335. sizeof(SEND_BUFFER),
  336. pReceiveBuffer,
  337. sizeof(RECEIVE_BUFFER),
  338. &ulBytesReturned,
  339. pOverLapped);
  340. LeaveCriticalSection(&LibCriticalSection);
  341. if (!fResult)
  342. {
  343. lStatus = GetLastError();
  344. if (lStatus != ERROR_IO_PENDING)
  345. {
  346. OutputDebugString(TEXT("TdiLibStartDeviceIO: DeviceIoControl failed!\n"));
  347. return STATUS_UNSUCCESSFUL;
  348. }
  349. return STATUS_PENDING;
  350. }
  351. //
  352. // gets to here if DeviceIoControl returned SUCCESS
  353. //
  354. return STATUS_SUCCESS;
  355. }
  356. // ----------------------------------------------------------------
  357. //
  358. // Function: TdiLibWaitForDeviceIO
  359. //
  360. // Arguments: hEvent -- event handle associated with asynchronous
  361. // deviceio
  362. // pOverlapped -- overlap structure (so we can get at results)
  363. //
  364. // Returns: final ntstatus of asynchronous operation
  365. //
  366. // Descript: This function is used to wait for the completion of an
  367. // asynchronous deviceio call started by TdiStartDeviceIO
  368. //
  369. // Status: ok
  370. //
  371. // ----------------------------------------------------------------
  372. const ULONG ulONE_SECOND = 1000; // milliseconds in a second
  373. NTSTATUS
  374. TdiLibWaitForDeviceIO(OVERLAPPED *pOverLapped)
  375. {
  376. NTSTATUS lStatus; // final status
  377. ULONG ulBytesReturned; // bytes written to outputbuffer
  378. //
  379. // DeviceIoControl in TdiStartDeviceIO pended.
  380. // Will wait for 1 second before timing out....
  381. //
  382. lStatus = WaitForSingleObject(pOverLapped->hEvent, ulONE_SECOND);
  383. if (lStatus == WAIT_OBJECT_0)
  384. {
  385. if (GetOverlappedResult(hTdiSampleDriver,
  386. pOverLapped,
  387. &ulBytesReturned,
  388. TRUE))
  389. {
  390. return STATUS_SUCCESS;
  391. }
  392. else // unexpected error case
  393. {
  394. OutputDebugString(TEXT("TdiLibWaitForDeviceIO: Pended DeviceIoControl failed\n"));
  395. }
  396. }
  397. else if (lStatus == WAIT_TIMEOUT)
  398. {
  399. return TDI_STATUS_TIMEDOUT;
  400. }
  401. //
  402. // unexpected return from WaitForSingleObject. Assume an error
  403. //
  404. else
  405. {
  406. OutputDebugString(TEXT("TdiLibWaitForDeviceIO: Pended DeviceIoControl had an error..\n"));
  407. }
  408. return STATUS_UNSUCCESSFUL;
  409. }
  410. ////////////////////////////////////////////////////////////////////////////
  411. // end of file utils.cpp
  412. ////////////////////////////////////////////////////////////////////////////