CStreams 64bit?

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

CStreams 64bit?

Post by ErikJan »

I’ve been using CStreams code from Karl E. Peterson (https://classicvb.net/samples/Streams/) in Excel VBA.
I moved to MSO365 64-bit and I am getting errors in my code. I can fix some of these, but as I also use the CStreams Class module, I believe that one needs adoption for 64 bit as well.

Is that available somewhere maybe?

Any help would be very much appreciated!

User avatar
HansV
Administrator
Posts: 78566
Joined: 16 Jan 2010, 00:14
Status: Microsoft MVP
Location: Wageningen, The Netherlands

Re: CStreams 64bit?

Post by HansV »

You'll need to update the Declare lines in the (class) modules, and the code that calls Windows API functions.
See Office 2010 Help Files: Win32API_PtrSafe with 64-bit Support
Best wishes,
Hans

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

Great thanks... I was able to adjust some, but I couldn't find these (maybe they are OK? Maybe I messed them up already?)

Private Declare PtrSafe Function NtQueryInformationFile Lib "ntdll" (ByVal FileHandle As Long, ByRef ioStatusBlock As IO_STATUS_BLOCK, FileInformation As Any, ByVal StructureLength As Long, ByVal FileInformationClass As FILE_INFORMATION_CLASS) As Long

Private Declare PtrSafe Function lstrlenW Lib "kernel32" (ByVal lpString As Long) As Long

Private Declare PtrSafe Function FindFirstFileW Lib "kernel32.dll" (ByVal lpFileName As String, ByRef lpFindFileData As WIN32_FIND_DATA) As LongPtr

Private Declare PtrSafe Function FindNextFileW Lib "kernel32.dll" (ByVal hFindFile As LongPtr, ByRef lpFindFileData As WIN32_FIND_DATA) As LongPtr

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

The first argument to NtQueryInformationFile is a handle so should be LongPtr too.
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

Thanks...This ain't easy. I now have this piece:

Code: Select all

PointerToLargeInteger(lpBlock + 8)
lpBlock is a LongPrt and I seem to now get an error on the code line above...

<Edit> This is that routine (and something is probably wrong now):

Code: Select all

Private Sub GetStreams(InfoBlock() As Byte)
    Dim nIndex As Long
    Dim lpBlock As LongPtr

    ' Reset count to zero, and walk through information block.
    m_Count = 0
    nIndex = LBound(InfoBlock)
    Do
        ' Expand persisted storage for stream information
        ReDim Preserve m_Streams(0 To m_Count) _
              As FILE_STREAM_INFORMATION

        With m_Streams(m_Count)
            ' Calculate pointer to beginning of this block.
            lpBlock = VarPtr(InfoBlock(nIndex))

            ' Find offset to next record.
            .NextEntryOffset = PointerToDWord(lpBlock)

            ' Read each of the remaining attributes for this stream.
            .StreamNameLength = PointerToDWord(lpBlock + 4)
            .StreamSize = PointerToLargeInteger(lpBlock + 8)
            .StreamAllocationSize = PointerToLargeInteger(lpBlock + 16)
            If .StreamNameLength Then
                .StreamName = PointerToStringW(lpBlock + 24, .StreamNameLength)
            End If

            ' Increment count of streams.
            m_Count = m_Count + 1

            ' Bump up buffer pointer to next record.
            If .NextEntryOffset Then
                nIndex = nIndex + .NextEntryOffset
            Else
                Exit Do
            End If
        End With
    Loop
End Sub

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

I'm making slow progress. Now stuck here:

32 bit

Declares:

Code: Select all

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Code:

Code: Select all

   hFile = CreateFile(m_FileName, 0&, FILE_SHARE_READ, ByVal 0&, OPEN_EXISTING, Flags, 0&)
64 bit

Declares:

Code: Select all

Private Declare PtrSafe Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr
and

Code: Select all

Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As LongPtr
        bInheritHandle As Long
End Type
Code gives error in the "ByVal0&" part of the call. I get that as that changed from 0 to the SECURITY_ATTRIBUTES type. So what do I do here now?

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

Why did you change it from Any to SECURITY_ATTRIBUTES?
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

Hans pointed me to a Microsoft file that gives guidance in converting API calls from 32 to 64 bit. That file is called: Win32API_PtrSafe.TXT

I used this file to convert the STREAMS code to 64 bit and for the CreateFile call that was the 64-bit suggested format.

I could try to put ANY back but I'm not sure what that would do.

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

You could try simply removing the & from the end, since 64bit will be expecting a LongLong and & is the type character for Long (you'd need ^ for a LongLong).
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

rory wrote:
24 Jan 2024, 09:14
You could try simply removing the & from the end, since 64bit will be expecting a LongLong and & is the type character for Long (you'd need ^ for a LongLong).
"User-defined type may not be passed ByVal"

I think that makes sense as it's now expecting this user define type: SECURITY_ATTRIBUTES

Somehow I need to pass that and make it behave like the "0&" that was there in the 32 bit version

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

rory wrote:
23 Jan 2024, 09:39
Why did you change it from Any to SECURITY_ATTRIBUTES?
If I change it back to Any, I get a "Type Mismatch" error

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

How is hFile declared and are you still using 0&?
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

Long. And yes, still as 0& because changes still gave errors as I reported

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

hFile needs to be a LongPtr since your API declaration returns a LongPtr.
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

I made that adjustment, thank you.

But the error remains as a user type is still expected....

I'll also search myself for this call in 64 bit, see if I find something. Will post if I do

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

OK, some progress. I changed the declare as could (should)
be NULL most of the time:

Code: Select all

Private Declare PtrSafe Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As Any, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As LongPtr) As LongPtr
So the call becomes:

Code: Select all

   hFile = CreateFile(m_FileName, 0&, FILE_SHARE_READ, Null, OPEN_EXISTING, Flags, 0&)
No compile errors here anymore but a new series pops-up now.

Working on that and will update later

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

Next problem is here...

Code: Select all

      If LookupPrivilegeValue(vbNullString, SE_BACKUP_NAME, tkp.LUID) Then
The .LUID gives "Method or Datamember not found". I understand but don't know how to fix.

tkp is defined in this function: Dim tkp As TOKEN_PRIVILEGES

LookupPrivilegeValue is declared as

Code: Select all

Private Declare PtrSafe Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, lpLuid As LARGE_INTEGER) As Long
So I need to look at LUID in TOKEN_PRIVILEGES. It was there in 32-bit but 64-bit has this:

Code: Select all

Private Type TOKEN_PRIVILEGES
    PrivilegeCount As Long
    Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES
End Type
Therefore I need to find "LUID_AND_ATTRIBUTES", and it is there:

Code: Select all

Private Type LUID_AND_ATTRIBUTES
        pLuid As LUID
        Attributes As Long
End Type
So how to I fix the call?

Note that this is the definition of LUID:

Code: Select all

Private Type LUID
    LowPart As Long
    HighPart As Long
End Type

User avatar
rory
5StarLounger
Posts: 818
Joined: 24 Jan 2010, 15:56

Re: CStreams 64bit?

Post by rory »

The declaration means that the function is expecting a LARGE_INTEGER type, not a TOKEN_PRIVILEGES. How/where have you defined the type?
Regards,
Rory

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

OK, I'm clearly not an expert here but when I look in the call, I see that there "tkp.LUID" is used. So that should indeed be LARGE_INTEGER.
The structure 'tkp' is defined as "TOKEN_PRIVILEGES".
The latter is defined with two variables: "PrivilegeCount As Long" and "Privileges(ANYSIZE_ARRAY) As LUID_AND_ATTRIBUTES"
"LUID_AND_ATTRIBUTES" defines two variables "pLuid As LUID" and "Attributes As Long"
"LUID" also defines two variables: "LowPart As Long" and "HighPart As Long"

Indeed, you are right, none of the 'lower' variables are of the LARGE_INTEGER type...

I guess that call is wrong then maybe? I mean, I shouldn't use "tkp.LUID" but something else (but that has to be LARGE_INTEGER)...

Sofar I think I was able to adjust variable-types to make everything 'fit' the 64-bit model, seems that this time however I should actually go change a call itself (and unless someone understands what's going on here, I think I'd need more background and understanding to do that).

Let's not lose my goal out of sight: I'd like to be able to read/write NTFS Alternate Data Streams via VBA code in MSO365 (64bit). I'm doing that now by trying to 'adapt' existing 32-bit code that I found on the Internet and used successfully before.
I'm not 'stuck' to that approach however... any other VBA code that works for 64-bit Office will be more than fine as well (but I searched and couldn't find anything yet)...

User avatar
ErikJan
BronzeLounger
Posts: 1256
Joined: 03 Feb 2010, 19:59
Location: Terneuzen, the Netherlands

Re: CStreams 64bit?

Post by ErikJan »

So we're stuck I guess... and therefore there's no way (yet) to read/write ADS via VBA in a 64bit environment.

Any suggestions for other locations where I could post this question maybe then?
Last edited by ErikJan on 02 Feb 2024, 15:03, edited 1 time in total.