Question return data question

nohairmonk

New member
Joined
Nov 28, 2020
Messages
1
Programming Experience
Beginner
Hi,
I am trying use NtfsUsnJournal to count folders and files,I've modified codes,there have a question about return code. I want to return the value of foldersCount,how to do that?
C#:
public UsnJournalReturnCode
            GetNtfsVolumeFolders(out List<Win32Api.UsnEntry> folders)
        {
            DateTime startTime = DateTime.Now;
            folders = new List<Win32Api.UsnEntry>();
            UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
           Int32 FoldersCount = 0;
            if (bNtfsVolume)
            {
              
                if (_usnJournalRootHandle.ToInt32() != Win32Api.INVALID_HANDLE_VALUE)
                {
                    usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;

                    Win32Api.USN_JOURNAL_DATA usnState = new Win32Api.USN_JOURNAL_DATA();
                    usnRtnCode = QueryUsnJournal(ref usnState);

                    if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                    {
                        //
                        // set up MFT_ENUM_DATA structure
                        //
                        Win32Api.MFT_ENUM_DATA med;
                        med.StartFileReferenceNumber = 0;
                        med.LowUsn = 0;
                        med.HighUsn = usnState.NextUsn;
                        Int32 sizeMftEnumData = Marshal.SizeOf(med);
                        IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
                        Win32Api.ZeroMemory(medBuffer, sizeMftEnumData);
                        Marshal.StructureToPtr(med, medBuffer, true);

                        //
                        // set up the data buffer which receives the USN_RECORD data
                        //
                        int pDataSize = sizeof(UInt64) + 10000;
                        IntPtr pData = Marshal.AllocHGlobal(pDataSize);
                        Win32Api.ZeroMemory(pData, pDataSize);
                        uint outBytesReturned = 0;
                        Win32Api.UsnEntry usnEntry = null;

                        //
                        // Gather up volume's directories
                        //
                        while (false != Win32Api.DeviceIoControl(
                            _usnJournalRootHandle,
                            Win32Api.FSCTL_ENUM_USN_DATA,
                            medBuffer,
                            sizeMftEnumData,
                            pData,
                            pDataSize,
                            out outBytesReturned,
                            IntPtr.Zero))
                        {
                            IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
                            while (outBytesReturned > 60)
                            {
                                usnEntry = new Win32Api.UsnEntry(pUsnRecord);
                                //
                                // check for directory entries
                                //
                                if (usnEntry.IsFolder)
                                {
                                    folders.Add(usnEntry);
                                    FoldersCount += 1;
                                }
                                pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);
                                outBytesReturned -= usnEntry.RecordLength;
                            }
                            Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0));
                        }

                        Marshal.FreeHGlobal(pData);
                        usnRtnCode = ConvertWin32ErrorToUsnError((Win32Api.GetLastErrorEnum)Marshal.GetLastWin32Error());
                        if (usnRtnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
                        {
                            usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
                        }
                    }
                }
                else
                {
                    usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
                }
            }
            folders.Sort();
            System.Windows.MessageBox.Show(Convert.ToString(FoldersCount));
            //return FoldersCount;
            return usnRtnCode;
        }

The attachment is the full code.
 

Attachments

  • NtfsUsnJournal.zip
    7.2 KB · Views: 22
Last edited by a moderator:
Please don't put your question in the code. The code should be the code. Comments in the code should be comments about the code. Ask the question in the post. That's what the post is for. We should not have to scroll through all your code to find the question.
 
Solution
I suspect part of the issue is that the OP looks to have transliterated some C style code into C# code, but is having some difficulty making the leap from C style procedural to C# object oriented.
 
if u need return "usnRtnCode" and this "FoldersCount", just put outside this function in same class

C#:
private int _FC;
public static int _FoldersCount { get { return _FC;} set{ _FC = value;}}

and in time to return your value, put this inside the code

C#:
_FoldersCount = FoldersCount;

this variable "_FoldersCount" it's appear like an static member and u see in another classes, after using your function u can get the value using

C#:
var Result = UsnJournalReturnCode._FoldersCount;
//or anything u want
_ =  UsnJournalReturnCode._FoldersCount;
 
if u need return "usnRtnCode" and this "FoldersCount", just put outside this function in same class

C#:
private int _FC;
public static int _FoldersCount { get { return _FC;} set{ _FC = value;}}

and in time to return your value, put this inside the code

C#:
_FoldersCount = FoldersCount;

this variable "_FoldersCount" it's appear like an static member and u see in another classes, after using your function u can get the value using

C#:
var Result = UsnJournalReturnCode._FoldersCount;
//or anything u want
_ =  UsnJournalReturnCode._FoldersCount;
The field would need to be static as well or the property couldn't access it. That said, if you were going to go that way, the field would be pointless and you should just use an auto-property.
 
u can try this.

creat an struct

C#:
public struct CodeResult { public UsnJournalReturnCode JornalResult; public int FoldersCount; }

and define value type return to this struct, in the example is "CodeResult".

inside your code u generate a new instace of this struct and return his.
C#:
CodeResult Result = new CodeResult
{
JornalResult = usnRtnCode,
FoldersCount = FoldersCount
};
return Result;
 
A ValueTuple would be so much more expedient:
C#:
public (UsnJournalReturnCode code, int folderCount)
       GetNtfsVolumeFolders(out List<Win32Api.UsnEntry> folders)
{
    DateTime startTime = DateTime.Now;
    folders = new List<Win32Api.UsnEntry>();
    UsnJournalReturnCode usnRtnCode = UsnJournalReturnCode.VOLUME_NOT_NTFS;
    Int32 FoldersCount = 0;
    if (bNtfsVolume)
    {
        if (_usnJournalRootHandle.ToInt32() != Win32Api.INVALID_HANDLE_VALUE)
        {
            usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;

            Win32Api.USN_JOURNAL_DATA usnState = new Win32Api.USN_JOURNAL_DATA();
            usnRtnCode = QueryUsnJournal(ref usnState);

            if (usnRtnCode == UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
            {
                //
                // set up MFT_ENUM_DATA structure
                //
                Win32Api.MFT_ENUM_DATA med;
                med.StartFileReferenceNumber = 0;
                med.LowUsn = 0;
                med.HighUsn = usnState.NextUsn;
                Int32 sizeMftEnumData = Marshal.SizeOf(med);
                IntPtr medBuffer = Marshal.AllocHGlobal(sizeMftEnumData);
                Win32Api.ZeroMemory(medBuffer, sizeMftEnumData);
                Marshal.StructureToPtr(med, medBuffer, true);

                //
                // set up the data buffer which receives the USN_RECORD data
                //
                int pDataSize = sizeof(UInt64) + 10000;
                IntPtr pData = Marshal.AllocHGlobal(pDataSize);
                Win32Api.ZeroMemory(pData, pDataSize);
                uint outBytesReturned = 0;
                Win32Api.UsnEntry usnEntry = null;

                //
                // Gather up volume's directories
                //
                while (false != Win32Api.DeviceIoControl(
                    _usnJournalRootHandle,
                    Win32Api.FSCTL_ENUM_USN_DATA,
                    medBuffer,
                    sizeMftEnumData,
                    pData,
                    pDataSize,
                    out outBytesReturned,
                    IntPtr.Zero))
                {
                    IntPtr pUsnRecord = new IntPtr(pData.ToInt32() + sizeof(Int64));
                    while (outBytesReturned > 60)
                    {
                        usnEntry = new Win32Api.UsnEntry(pUsnRecord);
                        //
                        // check for directory entries
                        //
                        if (usnEntry.IsFolder)
                        {
                            folders.Add(usnEntry);
                            FoldersCount += 1;
                        }
                        pUsnRecord = new IntPtr(pUsnRecord.ToInt32() + usnEntry.RecordLength);
                        outBytesReturned -= usnEntry.RecordLength;
                    }
                    Marshal.WriteInt64(medBuffer, Marshal.ReadInt64(pData, 0));
                }

                Marshal.FreeHGlobal(pData);
                usnRtnCode = ConvertWin32ErrorToUsnError((Win32Api.GetLastErrorEnum)Marshal.GetLastWin32Error());
                if (usnRtnCode == UsnJournalReturnCode.ERROR_HANDLE_EOF)
                {
                    usnRtnCode = UsnJournalReturnCode.USN_JOURNAL_SUCCESS;
                }
            }
        }
        else
        {
            usnRtnCode = UsnJournalReturnCode.INVALID_HANDLE_VALUE;
        }
    }
    folders.Sort();
    System.Windows.MessageBox.Show(Convert.ToString(FoldersCount));
    //return FoldersCount;
    return (usnRtnCode, FoldersCount);
}
but all that does is still perpetuate the poor transliteration of C style code into C# code. What is really needed is for the code to be written as a first class objected oriented C# method rather than a procedural C function.
 
Ah... so the code was authored by an OS geek over at DreamInCode. That would explain the general procedural style of the methods.
 
Back
Top Bottom