FltGetVolumeName does not get the complete "\Device\HarddiskVolume1" information

! Good afternoon,
! I’m developing a filter driver to read all the volumes in the system and get the GUID for the same, so that I can apply encryption/Decryption for the desired volume.
! First i’m working on getting all the volume in the system using FltGetVolumeName, below is the code for the same.

FLT_PREOP_CALLBACK_STATUS PreFileOperationCallback(__inout PFLT_CALLBACK_DATA Data,
	__in PCFLT_RELATED_OBJECTS FltObjects, __deref_out_opt PVOID* CompletionContext)
{
	DbgPrint("\n-------Inside ---PreFileOperationCallback--------");
	NTSTATUS							status, ntStatus;
	//PFLT_INSTANCE						retInstance = NULL;
	PFLT_VOLUME							pVolumeList[MAX_VOLUME_CHARS];
	ULONG								VolumeListSize = MAX_VOLUME_CHARS;
	ULONG 								VolumeNameLength, index = 0;
	PULONG								NumberVolumesReturned = NULL;
	WCHAR								wszNameBuffer[SHORT_NAME_LEN] = { 0 };
	FILTER_VOLUME_INFORMATION_CLASS		FilterVolumeStandardInformation;
	FILTER_VOLUME_STANDARD_INFORMATION	FltVolumeStdInfo;
	PULONG								BufferSizeNeeded;
	SIZE_T								bytesRequired;
	ULONG								MEMTAG_VOL_GUID = 0;
	PVOLUME_CONTEXT						volumeContext = NULL;
	UNICODE_STRING						volumeGuidName, VolumeNameString;
	PVOID								VolumeNameBuffer = NULL;

	DbgPrint("\n---------Before FltEnumerateVolumes--------");
	ntStatus = FltEnumerateVolumes(fileHandler, pVolumeList, VolumeListSize, &NumberVolumesReturned);   //Get volume information
	if (!NT_SUCCESS(ntStatus)) {
	 	return ntStatus;
	}
	DbgPrint("\n-------After  FltEnumerateVolumes---------");
	DbgPrint("\nNumberVolumesReturned - %d",NumberVolumesReturned);
	DbgPrint("\n-------------------------------------------");
	for (index = 1; index <= NumberVolumesReturned; index++)
	{
		if (index == NumberVolumesReturned) {
			break; //break from forLoop
		}
		VolumeNameString.Length = MAX_VOLUME_LENGTH;
		VolumeNameString.Buffer = wszNameBuffer;
		VolumeNameString.MaximumLength = SHORT_NAME_LEN * sizeof(WCHAR);
		DbgPrint("\n---------(1) Before FltGetVolumeName --------");
		//  Query the volume name length.
		ntStatus = FltGetVolumeName(pVolumeList[index], NULL, &VolumeNameLength);   
		DbgPrint("\n-------------------------------------------");
		if ((!NT_SUCCESS(ntStatus) && ntStatus != STATUS_BUFFER_TOO_SMALL)) {
			return FLT_PREOP_SUCCESS_NO_CALLBACK;
		}
		//  Allocate a buffer for the name.
		ntStatus = STATUS_SUCCESS;
		VolumeNameLength += (VolumeNameLength + VolumeNameLength); //increase size to allocate more PagePool memory
		VolumeNameString.Length = (ULONG)VolumeNameLength;
		VolumeNameBuffer = ExAllocatePoolWithTag(PagedPool, VolumeNameLength, MEMTAG_VOL_GUID);

		if (VolumeNameBuffer == NULL) {
			ntStatus = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}
		RtlInitEmptyUnicodeString(&VolumeNameString, VolumeNameBuffer, (ULONG)VolumeNameLength);

		ntStatus = FltGetVolumeName(pVolumeList[index], &VolumeNameString, NULL);   //Get name using volume information & with max pagePool memory
		DbgPrint("\n-------- Buffered FltGetVolumeName ---------");
		DbgPrint("\nVolumeNameString Length - %ld",VolumeNameString.Length);
		DbgPrint("\nVolumeNameString Buffer - %s", (PWCH)VolumeNameString.Buffer);   // Please review this point
		DbgPrint("\nVolumeNameString MaximumLength-%ld",VolumeNameString.MaximumLength);
		DbgPrint("\n------------------------------");
	}//End of Index forLoop

	for (index = 0; index < NumberVolumesReturned; index++)
	{
		FltObjectDereference(pVolumeList[index]);
	}
	//return pInstance;   
	return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

! --------------------- The output is -----------------
! VolumeNameString Length - 36
! VolumeNameString Buffer -
! VolumeNameString MaximumLength- 36
! ----------------------------------------------------------
! But the Microsoft documentation for FltGetVolumeName function says,
! //A pointer to a caller-allocated UNICODE_STRING structure that contains the volume’s non-persistent device object name (for example, “\Device\HarddiskVolume1”)
! Im unable to get the complete “\Device\HarddiskVolume1” information.
! I need help on this.

The buffer is of WIDE CHARACTERS, not characters. Its also not zero terminated to %s or %S are deeply innappropiate.

There is a %wZ which takes a PUNICODE_STRING, try that

DbgPrint("\nVolumeNameString Buffer - %wZ ",(PWCH)VolumeNameString.Buffer);
With the above changes

! -------After FltEnumerateVolumes---------
! NumberVolumesReturned - 6
! -------------------------------------------
! --------(1) Before FltGetVolumeName --------!!!Driver FilterLoad !!!
! --------!!!MiniFilter: Filter was started and configured. !!!
! -------- Buffered FltGetVolumeName ---------
! VolumeNameString Length - 46
! VolumeNameString Buffer -
! VolumeNameString MaximumLength-138

My target system is Windows2016

No. It takes a PUNICODE_STRING, not a PWCHAR. You want &VolumeNameString

Hi Rod, thank you very much your valuable comments, I’m sorry, I’m basically from Linux background, this is the first time, I’m working on windows environment.

Hi Rod, thank you very much, you have helped me in resolving the issues.
DbgPrint(“\nVolumeNameString - %wZ”, & VolumeNameString);

-------- Buffered FltGetVolumeName ---------
VolumeNameString - \Device\HarddiskVolume1
VolumeNameString Length - 46
VolumeNameString MaximumLength-46

Hi Rod, can you kindly give direction on this …

https://community.osr.com/discussion/291791/kernel-crash-while-calling-fltgetvolumeguidname-in-windows2016#latest