|
|
/*++
Copyright (C) Microsoft Corporation, 2000
Module Name:
utils.c
Abstract:
Utility routines for iScsi Port driver
Environment:
kernel mode only
Revision History:
--*/
#include "port.h"
PVOID iSpAllocatePool( IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag ) { PVOID Block; Block = ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag); if (Block != NULL) { RtlZeroMemory(Block, NumberOfBytes); }
return Block; }
NTSTATUS iSpAllocateMdlAndIrp( IN PVOID Buffer, IN ULONG BufferLen, IN CCHAR StackSize, IN BOOLEAN NonPagedPool, OUT PIRP *Irp, OUT PMDL *Mdl ) { PMDL localMdl = NULL; PIRP localIrp = NULL; NTSTATUS status;
//
// Allocate an MDL for this request
//
localMdl = IoAllocateMdl(Buffer, BufferLen, FALSE, FALSE, NULL); if (localMdl == NULL) { DebugPrint((1, "iSpAllocateMdlAndIrp : Failed to allocate MDL\n")); return STATUS_INSUFFICIENT_RESOURCES; }
//
// Initialize the MDL. If the buffer is from NonPaged pool
// use MmBuildMdlForNonPagedPool. Else, use MmProbeAndLockPages
//
if (NonPagedPool == TRUE) { MmBuildMdlForNonPagedPool(localMdl); } else {
try { MmProbeAndLockPages(localMdl, KernelMode, IoModifyAccess); } except(EXCEPTION_EXECUTE_HANDLER) {
DebugPrint((1, "iSpAllocateMdlAndIrp : Failed to Lockpaged\n")); IoFreeMdl(localMdl); return STATUS_INSUFFICIENT_RESOURCES; } }
//
// Allocate an IRP
//
localIrp = IoAllocateIrp(StackSize, FALSE); if (localIrp == NULL) { DebugPrint((1, "iSpAllocateMdlAndIrp. Failed to allocate IRP\n")); IoFreeMdl(localMdl); return STATUS_INSUFFICIENT_RESOURCES; }
DebugPrint((3, "Allocated IRP 0x%08x and MDL 0x%08x\n", localIrp, localMdl));
*Irp = localIrp; *Mdl = localMdl;
return STATUS_SUCCESS; }
VOID iSpFreeMdlAndIrp( IN PMDL Mdl, IN PIRP Irp, BOOLEAN UnlockPages ) { PMDL tmpMdlPtr = NULL;
if (Irp == NULL) { return; }
//
// Free any MDLs allocated for this IRP
//
if (Mdl != NULL) { while ((Irp->MdlAddress) != NULL) { tmpMdlPtr = (Irp->MdlAddress)->Next;
if (UnlockPages) { MmUnlockPages(Irp->MdlAddress); }
IoFreeMdl(Irp->MdlAddress); Irp->MdlAddress = tmpMdlPtr; } }
IoFreeIrp(Irp); }
NTSTATUS iScsiPortStringArrayToMultiString( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING MultiString, PCSTR StringArray[] )
/*++
Routine Description:
This routine will take a null terminated array of ascii strings and merge them together into a unicode multi-string block.
This routine allocates memory for the string buffer - is the caller's responsibility to free it.
Arguments:
MultiString - a UNICODE_STRING structure into which the multi string will be built.
StringArray - a NULL terminated list of narrow strings which will be combined together. This list may not be empty.
Return Value:
status
--*/
{ ANSI_STRING ansiEntry;
UNICODE_STRING unicodeEntry; PWSTR unicodeLocation;
UCHAR i;
NTSTATUS status;
PAGED_CODE();
//
// Make sure we aren't going to leak any memory
//
ASSERT(MultiString->Buffer == NULL);
RtlInitUnicodeString(MultiString, NULL);
for(i = 0; StringArray[i] != NULL; i++) {
RtlInitAnsiString(&ansiEntry, StringArray[i]);
MultiString->Length += (USHORT) RtlAnsiStringToUnicodeSize(&ansiEntry); }
ASSERT(MultiString->Length != 0);
MultiString->MaximumLength = MultiString->Length + sizeof(UNICODE_NULL);
MultiString->Buffer = iSpAllocatePool(PagedPool, MultiString->MaximumLength, ISCSI_TAG_PNP_ID);
if(MultiString->Buffer == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(MultiString->Buffer, MultiString->MaximumLength);
unicodeEntry = *MultiString;
for(i = 0; StringArray[i] != NULL; i++) {
RtlInitAnsiString(&ansiEntry, StringArray[i]);
status = RtlAnsiStringToUnicodeString( &unicodeEntry, &ansiEntry, FALSE);
//
// Since we're not allocating any memory the only failure possible
// is if this function is bad
//
ASSERT(NT_SUCCESS(status));
//
// Push the buffer location up and reduce the maximum count
//
((PSTR) unicodeEntry.Buffer) += unicodeEntry.Length + sizeof(WCHAR); unicodeEntry.MaximumLength -= unicodeEntry.Length + sizeof(WCHAR);
};
//
// Stick the final NUL on the end of the multisz
//
// RtlZeroMemory(unicodeEntry.Buffer, unicodeEntry.MaximumLength);
return STATUS_SUCCESS; }
NTSTATUS iSpMultiStringToStringArray( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING MultiString, OUT PWSTR *StringArray[], BOOLEAN Forward )
{ ULONG stringCount = 0; ULONG stringNumber; ULONG i; PWSTR *stringArray;
PAGED_CODE();
//
// Pass one: count the number of string elements.
//
for(i = 0; i < (MultiString->MaximumLength / sizeof(WCHAR)); i++) { if(MultiString->Buffer[i] == UNICODE_NULL) { stringCount++; } }
//
// Allocate the memory for a NULL-terminated string array.
//
stringArray = iSpAllocatePool(PagedPool, (stringCount + 1) * sizeof(PWSTR), ISCSI_TAG_PNP_ID);
if(stringArray == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
RtlZeroMemory(stringArray, (stringCount + 1) * sizeof(PWSTR));
//
// Pass two : Put the string pointers in place.
//
i = 0;
for(stringNumber = 0; stringNumber < stringCount; stringNumber++) {
ULONG arrayNumber;
if(Forward) { arrayNumber = stringNumber; } else { arrayNumber = stringCount - stringNumber - 1; }
//
// Put a pointer to the head of the string into the array.
//
stringArray[arrayNumber] = &MultiString->Buffer[i];
//
// Scan for the end of the string.
//
while((i < (MultiString->MaximumLength / sizeof(WCHAR))) && (MultiString->Buffer[i] != UNICODE_NULL)) { i++; }
//
// Jump past the NULL.
//
i++; }
*StringArray = stringArray; return STATUS_SUCCESS; }
|