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.

335 lines
6.9 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 2000
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. Utility routines for iScsi Port driver
  7. Environment:
  8. kernel mode only
  9. Revision History:
  10. --*/
  11. #include "port.h"
  12. PVOID
  13. iSpAllocatePool(
  14. IN POOL_TYPE PoolType,
  15. IN SIZE_T NumberOfBytes,
  16. IN ULONG Tag
  17. )
  18. {
  19. PVOID Block;
  20. Block = ExAllocatePoolWithTag(PoolType,
  21. NumberOfBytes,
  22. Tag);
  23. if (Block != NULL) {
  24. RtlZeroMemory(Block, NumberOfBytes);
  25. }
  26. return Block;
  27. }
  28. NTSTATUS
  29. iSpAllocateMdlAndIrp(
  30. IN PVOID Buffer,
  31. IN ULONG BufferLen,
  32. IN CCHAR StackSize,
  33. IN BOOLEAN NonPagedPool,
  34. OUT PIRP *Irp,
  35. OUT PMDL *Mdl
  36. )
  37. {
  38. PMDL localMdl = NULL;
  39. PIRP localIrp = NULL;
  40. NTSTATUS status;
  41. //
  42. // Allocate an MDL for this request
  43. //
  44. localMdl = IoAllocateMdl(Buffer,
  45. BufferLen,
  46. FALSE,
  47. FALSE,
  48. NULL);
  49. if (localMdl == NULL) {
  50. DebugPrint((1, "iSpAllocateMdlAndIrp : Failed to allocate MDL\n"));
  51. return STATUS_INSUFFICIENT_RESOURCES;
  52. }
  53. //
  54. // Initialize the MDL. If the buffer is from NonPaged pool
  55. // use MmBuildMdlForNonPagedPool. Else, use MmProbeAndLockPages
  56. //
  57. if (NonPagedPool == TRUE) {
  58. MmBuildMdlForNonPagedPool(localMdl);
  59. } else {
  60. try {
  61. MmProbeAndLockPages(localMdl, KernelMode, IoModifyAccess);
  62. } except(EXCEPTION_EXECUTE_HANDLER) {
  63. DebugPrint((1,
  64. "iSpAllocateMdlAndIrp : Failed to Lockpaged\n"));
  65. IoFreeMdl(localMdl);
  66. return STATUS_INSUFFICIENT_RESOURCES;
  67. }
  68. }
  69. //
  70. // Allocate an IRP
  71. //
  72. localIrp = IoAllocateIrp(StackSize, FALSE);
  73. if (localIrp == NULL) {
  74. DebugPrint((1, "iSpAllocateMdlAndIrp. Failed to allocate IRP\n"));
  75. IoFreeMdl(localMdl);
  76. return STATUS_INSUFFICIENT_RESOURCES;
  77. }
  78. DebugPrint((3, "Allocated IRP 0x%08x and MDL 0x%08x\n",
  79. localIrp, localMdl));
  80. *Irp = localIrp;
  81. *Mdl = localMdl;
  82. return STATUS_SUCCESS;
  83. }
  84. VOID
  85. iSpFreeMdlAndIrp(
  86. IN PMDL Mdl,
  87. IN PIRP Irp,
  88. BOOLEAN UnlockPages
  89. )
  90. {
  91. PMDL tmpMdlPtr = NULL;
  92. if (Irp == NULL) {
  93. return;
  94. }
  95. //
  96. // Free any MDLs allocated for this IRP
  97. //
  98. if (Mdl != NULL) {
  99. while ((Irp->MdlAddress) != NULL) {
  100. tmpMdlPtr = (Irp->MdlAddress)->Next;
  101. if (UnlockPages) {
  102. MmUnlockPages(Irp->MdlAddress);
  103. }
  104. IoFreeMdl(Irp->MdlAddress);
  105. Irp->MdlAddress = tmpMdlPtr;
  106. }
  107. }
  108. IoFreeIrp(Irp);
  109. }
  110. NTSTATUS
  111. iScsiPortStringArrayToMultiString(
  112. IN PDRIVER_OBJECT DriverObject,
  113. PUNICODE_STRING MultiString,
  114. PCSTR StringArray[]
  115. )
  116. /*++
  117. Routine Description:
  118. This routine will take a null terminated array of ascii strings and merge
  119. them together into a unicode multi-string block.
  120. This routine allocates memory for the string buffer - is the caller's
  121. responsibility to free it.
  122. Arguments:
  123. MultiString - a UNICODE_STRING structure into which the multi string will
  124. be built.
  125. StringArray - a NULL terminated list of narrow strings which will be combined
  126. together. This list may not be empty.
  127. Return Value:
  128. status
  129. --*/
  130. {
  131. ANSI_STRING ansiEntry;
  132. UNICODE_STRING unicodeEntry;
  133. PWSTR unicodeLocation;
  134. UCHAR i;
  135. NTSTATUS status;
  136. PAGED_CODE();
  137. //
  138. // Make sure we aren't going to leak any memory
  139. //
  140. ASSERT(MultiString->Buffer == NULL);
  141. RtlInitUnicodeString(MultiString, NULL);
  142. for(i = 0; StringArray[i] != NULL; i++) {
  143. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  144. MultiString->Length += (USHORT) RtlAnsiStringToUnicodeSize(&ansiEntry);
  145. }
  146. ASSERT(MultiString->Length != 0);
  147. MultiString->MaximumLength = MultiString->Length + sizeof(UNICODE_NULL);
  148. MultiString->Buffer = iSpAllocatePool(PagedPool,
  149. MultiString->MaximumLength,
  150. ISCSI_TAG_PNP_ID);
  151. if(MultiString->Buffer == NULL) {
  152. return STATUS_INSUFFICIENT_RESOURCES;
  153. }
  154. RtlZeroMemory(MultiString->Buffer, MultiString->MaximumLength);
  155. unicodeEntry = *MultiString;
  156. for(i = 0; StringArray[i] != NULL; i++) {
  157. RtlInitAnsiString(&ansiEntry, StringArray[i]);
  158. status = RtlAnsiStringToUnicodeString(
  159. &unicodeEntry,
  160. &ansiEntry,
  161. FALSE);
  162. //
  163. // Since we're not allocating any memory the only failure possible
  164. // is if this function is bad
  165. //
  166. ASSERT(NT_SUCCESS(status));
  167. //
  168. // Push the buffer location up and reduce the maximum count
  169. //
  170. ((PSTR) unicodeEntry.Buffer) += unicodeEntry.Length + sizeof(WCHAR);
  171. unicodeEntry.MaximumLength -= unicodeEntry.Length + sizeof(WCHAR);
  172. };
  173. //
  174. // Stick the final NUL on the end of the multisz
  175. //
  176. // RtlZeroMemory(unicodeEntry.Buffer, unicodeEntry.MaximumLength);
  177. return STATUS_SUCCESS;
  178. }
  179. NTSTATUS
  180. iSpMultiStringToStringArray(
  181. IN PDRIVER_OBJECT DriverObject,
  182. IN PUNICODE_STRING MultiString,
  183. OUT PWSTR *StringArray[],
  184. BOOLEAN Forward
  185. )
  186. {
  187. ULONG stringCount = 0;
  188. ULONG stringNumber;
  189. ULONG i;
  190. PWSTR *stringArray;
  191. PAGED_CODE();
  192. //
  193. // Pass one: count the number of string elements.
  194. //
  195. for(i = 0; i < (MultiString->MaximumLength / sizeof(WCHAR)); i++) {
  196. if(MultiString->Buffer[i] == UNICODE_NULL) {
  197. stringCount++;
  198. }
  199. }
  200. //
  201. // Allocate the memory for a NULL-terminated string array.
  202. //
  203. stringArray = iSpAllocatePool(PagedPool,
  204. (stringCount + 1) * sizeof(PWSTR),
  205. ISCSI_TAG_PNP_ID);
  206. if(stringArray == NULL) {
  207. return STATUS_INSUFFICIENT_RESOURCES;
  208. }
  209. RtlZeroMemory(stringArray, (stringCount + 1) * sizeof(PWSTR));
  210. //
  211. // Pass two : Put the string pointers in place.
  212. //
  213. i = 0;
  214. for(stringNumber = 0; stringNumber < stringCount; stringNumber++) {
  215. ULONG arrayNumber;
  216. if(Forward) {
  217. arrayNumber = stringNumber;
  218. } else {
  219. arrayNumber = stringCount - stringNumber - 1;
  220. }
  221. //
  222. // Put a pointer to the head of the string into the array.
  223. //
  224. stringArray[arrayNumber] = &MultiString->Buffer[i];
  225. //
  226. // Scan for the end of the string.
  227. //
  228. while((i < (MultiString->MaximumLength / sizeof(WCHAR))) &&
  229. (MultiString->Buffer[i] != UNICODE_NULL)) {
  230. i++;
  231. }
  232. //
  233. // Jump past the NULL.
  234. //
  235. i++;
  236. }
  237. *StringArray = stringArray;
  238. return STATUS_SUCCESS;
  239. }