336 lines
6.9 KiB
C
336 lines
6.9 KiB
C
/*++
|
||
|
||
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;
|
||
}
|
||
|