windows-nt/Source/XPSP1/NT/drivers/storage/iscsiprt/client/utils.c

336 lines
6.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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;
}