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.

451 lines
12 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Author:
  6. ervinp
  7. Environment:
  8. Kernel mode
  9. Revision History:
  10. --*/
  11. #include <WDM.H>
  12. #include <usbdi.h>
  13. #include <usbdlib.h>
  14. #include <usbioctl.h>
  15. #include "usb8023.h"
  16. #include "debug.h"
  17. #if DBG_WRAP_MEMORY
  18. /*
  19. * Memory Allocation:
  20. * To catch memory leaks, we will keep a count and list of all allocated memory
  21. * and then assert that the memory is all freed when we exit.
  22. */
  23. ULONG dbgTotalMemCount = 0;
  24. LIST_ENTRY dbgAllMemoryList;
  25. #define ALIGNBYTES 32
  26. struct memHeader {
  27. PUCHAR actualPtr;
  28. ULONG actualSize;
  29. LIST_ENTRY listEntry;
  30. };
  31. #endif
  32. PVOID AllocPool(ULONG size)
  33. /*
  34. *
  35. * Return a 32-byte aligned pointer.
  36. * Place a guard word at the end of the buffer.
  37. * Cache the actual allocated pointer and size before the returned pointer.
  38. *
  39. */
  40. {
  41. PUCHAR resultPtr;
  42. #if DBG_WRAP_MEMORY
  43. {
  44. PUCHAR actualPtr = ExAllocatePoolWithTag(
  45. NonPagedPool,
  46. size+ALIGNBYTES+sizeof(struct memHeader)+sizeof(ULONG),
  47. DRIVER_SIG);
  48. if (actualPtr){
  49. struct memHeader *memHdr;
  50. KIRQL oldIrql;
  51. RtlZeroMemory(actualPtr, size+32+sizeof(struct memHeader));
  52. *(PULONG)(actualPtr+size+ALIGNBYTES+sizeof(struct memHeader)) = GUARD_WORD;
  53. /*
  54. * ExAllocatePoolWithTag returns the 32-byte aligned pointer
  55. * from ExAllocatePool plus 8 bytes for the tag and kernel tracking info
  56. * (but don't depend on this).
  57. * Align the pointer we return, and cache away the actual pointer to free and
  58. * the buffer size.
  59. */
  60. // ASSERT(((ULONG_PTR)actualPtr & 0x1F) == 0x08); NT only
  61. resultPtr = (PUCHAR)((ULONG_PTR)(actualPtr+ALIGNBYTES+sizeof(struct memHeader)) & ~(ALIGNBYTES-1));
  62. memHdr = (struct memHeader *)(resultPtr-sizeof(struct memHeader));
  63. memHdr->actualPtr = actualPtr;
  64. memHdr->actualSize = size+ALIGNBYTES+sizeof(struct memHeader)+sizeof(ULONG);
  65. dbgTotalMemCount += memHdr->actualSize;
  66. KeAcquireSpinLock(&globalSpinLock, &oldIrql);
  67. InsertTailList(&dbgAllMemoryList, &memHdr->listEntry);
  68. KeReleaseSpinLock(&globalSpinLock, oldIrql);
  69. }
  70. else {
  71. resultPtr = NULL;
  72. }
  73. }
  74. #else
  75. resultPtr = ExAllocatePoolWithTag(NonPagedPool, size, DRIVER_SIG);
  76. if (resultPtr){
  77. RtlZeroMemory(resultPtr, size);
  78. }
  79. #endif
  80. return resultPtr;
  81. }
  82. VOID FreePool(PVOID ptr)
  83. {
  84. #if DBG_WRAP_MEMORY
  85. {
  86. KIRQL oldIrql;
  87. struct memHeader *memHdr;
  88. ASSERT(ptr);
  89. memHdr = (struct memHeader *)((PUCHAR)ptr - sizeof(struct memHeader));
  90. ASSERT(*(PULONG)(memHdr->actualPtr+memHdr->actualSize-sizeof(ULONG)) == GUARD_WORD);
  91. ASSERT(dbgTotalMemCount >= memHdr->actualSize);
  92. KeAcquireSpinLock(&globalSpinLock, &oldIrql);
  93. ASSERT(!IsListEmpty(&dbgAllMemoryList));
  94. RemoveEntryList(&memHdr->listEntry);
  95. KeReleaseSpinLock(&globalSpinLock, oldIrql);
  96. dbgTotalMemCount -= memHdr->actualSize;
  97. ExFreePool(memHdr->actualPtr);
  98. }
  99. #else
  100. ExFreePool(ptr);
  101. #endif
  102. }
  103. /*
  104. ********************************************************************************
  105. * MemDup
  106. ********************************************************************************
  107. *
  108. * Return a fresh copy of the argument.
  109. *
  110. */
  111. PVOID MemDup(PVOID dataPtr, ULONG length)
  112. {
  113. PVOID newPtr;
  114. newPtr = (PVOID)AllocPool(length);
  115. if (newPtr){
  116. RtlCopyMemory(newPtr, dataPtr, length);
  117. }
  118. ASSERT(newPtr);
  119. return newPtr;
  120. }
  121. VOID DelayMs(ULONG numMillisec)
  122. {
  123. LARGE_INTEGER deltaTime;
  124. /*
  125. * Get delay time into relative units of 100 nsec.
  126. */
  127. deltaTime.QuadPart = -10000 * numMillisec;
  128. KeDelayExecutionThread(KernelMode, FALSE, &deltaTime);
  129. }
  130. /*
  131. * AllocateCommonResources
  132. *
  133. * Allocate adapter resources that are common to RNDIS and NDIS interfaces
  134. * but which for some reason can't be allocated by NewAdapter().
  135. * These resources will be freed by FreeAdapter().
  136. */
  137. BOOLEAN AllocateCommonResources(ADAPTEREXT *adapter)
  138. {
  139. BOOLEAN result = TRUE;
  140. ULONG i;
  141. /*
  142. * Build the packet pool for this adapter.
  143. */
  144. for (i = 0; i < USB_PACKET_POOL_SIZE; i++){
  145. USBPACKET *packet = NewPacket(adapter);
  146. if (packet){
  147. EnqueueFreePacket(packet);
  148. }
  149. else {
  150. ASSERT(packet);
  151. result = FALSE;
  152. break;
  153. }
  154. }
  155. ASSERT(result);
  156. return result;
  157. }
  158. BOOLEAN GetRegValue(ADAPTEREXT *adapter, PWCHAR wValueName, OUT PULONG valuePtr, BOOLEAN hwKey)
  159. {
  160. BOOLEAN success = FALSE;
  161. NTSTATUS status;
  162. HANDLE hRegDevice;
  163. KIRQL oldIrql;
  164. *valuePtr = 0;
  165. status = IoOpenDeviceRegistryKey( adapter->physDevObj,
  166. hwKey ? PLUGPLAY_REGKEY_DEVICE : PLUGPLAY_REGKEY_DRIVER,
  167. KEY_READ,
  168. &hRegDevice);
  169. if (NT_SUCCESS(status)){
  170. UNICODE_STRING uValueName;
  171. PKEY_VALUE_FULL_INFORMATION keyValueInfo;
  172. ULONG keyValueTotalSize, actualLength;
  173. RtlInitUnicodeString(&uValueName, wValueName);
  174. keyValueTotalSize = sizeof(KEY_VALUE_FULL_INFORMATION) +
  175. uValueName.Length*sizeof(WCHAR) +
  176. sizeof(ULONG);
  177. keyValueInfo = AllocPool(keyValueTotalSize);
  178. if (keyValueInfo){
  179. status = ZwQueryValueKey( hRegDevice,
  180. &uValueName,
  181. KeyValueFullInformation,
  182. keyValueInfo,
  183. keyValueTotalSize,
  184. &actualLength);
  185. if (NT_SUCCESS(status)){
  186. ASSERT(keyValueInfo->Type == REG_DWORD);
  187. ASSERT(keyValueInfo->DataLength == sizeof(ULONG));
  188. *valuePtr = *((PULONG)(((PCHAR)keyValueInfo)+keyValueInfo->DataOffset));
  189. success = TRUE;
  190. }
  191. FreePool(keyValueInfo);
  192. }
  193. else {
  194. ASSERT(keyValueInfo);
  195. }
  196. ZwClose(hRegDevice);
  197. }
  198. else {
  199. DBGWARN(("IoOpenDeviceRegistryKey failed with %xh.", status));
  200. }
  201. return success;
  202. }
  203. BOOLEAN SetRegValue(ADAPTEREXT *adapter, PWCHAR wValueName, ULONG newValue, BOOLEAN hwKey)
  204. {
  205. BOOLEAN success = FALSE;
  206. NTSTATUS status;
  207. HANDLE hRegDevice;
  208. KIRQL oldIrql;
  209. status = IoOpenDeviceRegistryKey( adapter->physDevObj,
  210. hwKey ? PLUGPLAY_REGKEY_DEVICE : PLUGPLAY_REGKEY_DRIVER,
  211. KEY_READ,
  212. &hRegDevice);
  213. if (NT_SUCCESS(status)){
  214. UNICODE_STRING uValueName;
  215. PKEY_VALUE_FULL_INFORMATION keyValueInfo;
  216. ULONG keyValueTotalSize, actualLength;
  217. RtlInitUnicodeString(&uValueName, wValueName);
  218. keyValueTotalSize = sizeof(KEY_VALUE_FULL_INFORMATION) +
  219. uValueName.Length*sizeof(WCHAR) +
  220. sizeof(ULONG);
  221. keyValueInfo = AllocPool(keyValueTotalSize);
  222. if (keyValueInfo){
  223. status = ZwSetValueKey( hRegDevice,
  224. &uValueName,
  225. 0,
  226. REG_DWORD,
  227. &newValue,
  228. sizeof(ULONG));
  229. if (NT_SUCCESS(status)){
  230. success = TRUE;
  231. }
  232. else {
  233. DBGERR(("SetRegValue: ZwSetValueKey failed with %xh.", status));
  234. }
  235. FreePool(keyValueInfo);
  236. }
  237. else {
  238. ASSERT(keyValueInfo);
  239. }
  240. ZwClose(hRegDevice);
  241. }
  242. else {
  243. DBGOUT(("IoOpenDeviceRegistryKey failed with %xh.", status));
  244. }
  245. return success;
  246. }
  247. /*
  248. * MyInitializeMdl
  249. *
  250. * Wrapper for MmInitializeMdl, which doesn't compile under NDIS headers.
  251. */
  252. VOID MyInitializeMdl(PMDL mdl, PVOID buf, ULONG bufLen)
  253. {
  254. MmInitializeMdl(mdl, buf, bufLen);
  255. MmBuildMdlForNonPagedPool(mdl);
  256. }
  257. PVOID GetSystemAddressForMdlSafe(PMDL MdlAddress)
  258. {
  259. PVOID buf;
  260. /*
  261. * Note: we could use MmGetSystemAddressSafe here
  262. * but not for Win98SE
  263. */
  264. if (MdlAddress){
  265. CSHORT oldFlags = MdlAddress->MdlFlags;
  266. MdlAddress->MdlFlags |= MDL_MAPPING_CAN_FAIL;
  267. buf = MmGetSystemAddressForMdl(MdlAddress);
  268. MdlAddress->MdlFlags &= (oldFlags | ~MDL_MAPPING_CAN_FAIL);
  269. }
  270. else {
  271. ASSERT(MdlAddress);
  272. buf = NULL;
  273. }
  274. return buf;
  275. }
  276. ULONG CopyMdlToBuffer(PUCHAR buf, PMDL mdl, ULONG bufLen)
  277. {
  278. ULONG totalLen = 0;
  279. while (mdl){
  280. ULONG thisBufLen = MmGetMdlByteCount(mdl);
  281. if (totalLen+thisBufLen <= bufLen){
  282. PVOID thisBuf = GetSystemAddressForMdlSafe(mdl);
  283. if (thisBuf){
  284. RtlCopyMemory(buf+totalLen, thisBuf, thisBufLen);
  285. totalLen += thisBufLen;
  286. mdl = mdl->Next;
  287. }
  288. else {
  289. break;
  290. }
  291. }
  292. else {
  293. DBGERR(("CopyMdlToBuffer: mdl @ %ph is too large for buffer size %xh.", mdl, bufLen));
  294. break;
  295. }
  296. }
  297. return totalLen;
  298. }
  299. ULONG GetMdlListTotalByteCount(PMDL mdl)
  300. {
  301. ULONG totalBytes = 0;
  302. do {
  303. totalBytes += MmGetMdlByteCount(mdl);
  304. mdl = mdl->Next;
  305. } while (mdl);
  306. return totalBytes;
  307. }
  308. VOID ByteSwap(PUCHAR buf, ULONG len)
  309. {
  310. while (len >= 2){
  311. UCHAR tmp = buf[0];
  312. buf[0] = buf[1];
  313. buf[1] = tmp;
  314. buf += 2;
  315. len -= 2;
  316. }
  317. }
  318. #if SPECIAL_WIN98SE_BUILD
  319. PIO_WORKITEM MyIoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
  320. {
  321. PIO_WORKITEM ioWorkItem;
  322. PWORK_QUEUE_ITEM exWorkItem;
  323. ioWorkItem = ExAllocatePool(NonPagedPool, sizeof(IO_WORKITEM));
  324. if (ioWorkItem) {
  325. ioWorkItem->DeviceObject = DeviceObject;
  326. exWorkItem = &ioWorkItem->WorkItem;
  327. #if DBG
  328. ioWorkItem->Size = sizeof(IO_WORKITEM);
  329. #endif
  330. ExInitializeWorkItem(exWorkItem, MyIopProcessWorkItem, ioWorkItem);
  331. }
  332. return ioWorkItem;
  333. }
  334. VOID MyIoFreeWorkItem(PIO_WORKITEM IoWorkItem)
  335. {
  336. ASSERT(IoWorkItem->Size == sizeof(IO_WORKITEM));
  337. ExFreePool( IoWorkItem );
  338. }
  339. VOID MyIoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
  340. {
  341. PWORK_QUEUE_ITEM exWorkItem;
  342. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  343. ASSERT(IoWorkItem->Size == sizeof(IO_WORKITEM));
  344. ObReferenceObject( IoWorkItem->DeviceObject );
  345. IoWorkItem->Routine = WorkerRoutine;
  346. IoWorkItem->Context = Context;
  347. exWorkItem = &IoWorkItem->WorkItem;
  348. ExQueueWorkItem( exWorkItem, QueueType );
  349. }
  350. VOID MyIopProcessWorkItem(IN PVOID Parameter)
  351. {
  352. PIO_WORKITEM ioWorkItem;
  353. PDEVICE_OBJECT deviceObject;
  354. PAGED_CODE();
  355. ioWorkItem = (PIO_WORKITEM)Parameter;
  356. deviceObject = ioWorkItem->DeviceObject;
  357. ioWorkItem->Routine(deviceObject, ioWorkItem->Context);
  358. ObDereferenceObject(deviceObject);
  359. }
  360. #endif