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;
|
|||
|
}
|
|||
|
|