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.

455 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. #if defined(SPECIAL_WIN98SE_BUILD) || defined(SPECIAL_WINME_BUILD)
  268. buf = MmGetSystemAddressForMdl(MdlAddress);
  269. #else
  270. buf = MmGetSystemAddressForMdlSafe(MdlAddress, NormalPoolPriority);
  271. #endif
  272. MdlAddress->MdlFlags &= (oldFlags | ~MDL_MAPPING_CAN_FAIL);
  273. }
  274. else {
  275. ASSERT(MdlAddress);
  276. buf = NULL;
  277. }
  278. return buf;
  279. }
  280. ULONG CopyMdlToBuffer(PUCHAR buf, PMDL mdl, ULONG bufLen)
  281. {
  282. ULONG totalLen = 0;
  283. while (mdl){
  284. ULONG thisBufLen = MmGetMdlByteCount(mdl);
  285. if (totalLen+thisBufLen <= bufLen){
  286. PVOID thisBuf = GetSystemAddressForMdlSafe(mdl);
  287. if (thisBuf){
  288. RtlCopyMemory(buf+totalLen, thisBuf, thisBufLen);
  289. totalLen += thisBufLen;
  290. mdl = mdl->Next;
  291. }
  292. else {
  293. break;
  294. }
  295. }
  296. else {
  297. DBGERR(("CopyMdlToBuffer: mdl @ %ph is too large for buffer size %xh.", mdl, bufLen));
  298. break;
  299. }
  300. }
  301. return totalLen;
  302. }
  303. ULONG GetMdlListTotalByteCount(PMDL mdl)
  304. {
  305. ULONG totalBytes = 0;
  306. do {
  307. totalBytes += MmGetMdlByteCount(mdl);
  308. mdl = mdl->Next;
  309. } while (mdl);
  310. return totalBytes;
  311. }
  312. VOID ByteSwap(PUCHAR buf, ULONG len)
  313. {
  314. while (len >= 2){
  315. UCHAR tmp = buf[0];
  316. buf[0] = buf[1];
  317. buf[1] = tmp;
  318. buf += 2;
  319. len -= 2;
  320. }
  321. }
  322. #if SPECIAL_WIN98SE_BUILD
  323. PIO_WORKITEM MyIoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
  324. {
  325. PIO_WORKITEM ioWorkItem;
  326. PWORK_QUEUE_ITEM exWorkItem;
  327. ioWorkItem = ExAllocatePool(NonPagedPool, sizeof(IO_WORKITEM));
  328. if (ioWorkItem) {
  329. ioWorkItem->DeviceObject = DeviceObject;
  330. exWorkItem = &ioWorkItem->WorkItem;
  331. #if DBG
  332. ioWorkItem->Size = sizeof(IO_WORKITEM);
  333. #endif
  334. ExInitializeWorkItem(exWorkItem, MyIopProcessWorkItem, ioWorkItem);
  335. }
  336. return ioWorkItem;
  337. }
  338. VOID MyIoFreeWorkItem(PIO_WORKITEM IoWorkItem)
  339. {
  340. ASSERT(IoWorkItem->Size == sizeof(IO_WORKITEM));
  341. ExFreePool( IoWorkItem );
  342. }
  343. VOID MyIoQueueWorkItem(IN PIO_WORKITEM IoWorkItem, IN PIO_WORKITEM_ROUTINE WorkerRoutine, IN WORK_QUEUE_TYPE QueueType, IN PVOID Context)
  344. {
  345. PWORK_QUEUE_ITEM exWorkItem;
  346. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  347. ASSERT(IoWorkItem->Size == sizeof(IO_WORKITEM));
  348. ObReferenceObject( IoWorkItem->DeviceObject );
  349. IoWorkItem->Routine = WorkerRoutine;
  350. IoWorkItem->Context = Context;
  351. exWorkItem = &IoWorkItem->WorkItem;
  352. ExQueueWorkItem( exWorkItem, QueueType );
  353. }
  354. VOID MyIopProcessWorkItem(IN PVOID Parameter)
  355. {
  356. PIO_WORKITEM ioWorkItem;
  357. PDEVICE_OBJECT deviceObject;
  358. PAGED_CODE();
  359. ioWorkItem = (PIO_WORKITEM)Parameter;
  360. deviceObject = ioWorkItem->DeviceObject;
  361. ioWorkItem->Routine(deviceObject, ioWorkItem->Context);
  362. ObDereferenceObject(deviceObject);
  363. }
  364. #endif