Skip to content

Commit 8ea192b

Browse files
committed
Add checksums (for resume) and decompression on FTP uploads
1 parent 1fe401b commit 8ea192b

File tree

1 file changed

+136
-40
lines changed

1 file changed

+136
-40
lines changed

src/cVncServer.cls

+136-40
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ Private Declare Function IPropertyBag2_Write_Proxy Lib "windowscodecs" (ByVal pP
188188
#End If
189189
Private Declare Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpBuffer As Long, ByVal nSize As Long) As Long
190190
Private Declare Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableW" (ByVal lpName As Long, ByVal lpValue As Long) As Long
191+
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileW" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
192+
Private Declare Function SetFilePointerEx Lib "kernel32" (ByVal hFile As Long, ByVal liDistanceToMove As Currency, ByVal lpNewFilePointer As Long, ByVal dwMoveMethod As Long) As Long
193+
Private Declare Function SetEndOfFile Lib "kernel32" (ByVal hFile As Long) As Long
194+
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
191195
#End If
192196
Private Declare Function D3D11CreateDevice Lib "d3d11" (ByVal pAdapter As IUnknown, ByVal DriverType As D3D_DRIVER_TYPE, ByVal Software As Long, ByVal Flags As D3D11_CREATE_DEVICE_FLAG, pFeatureLevels As Any, ByVal FeatureLevels As Long, ByVal SDKVersion As Long, ppDevice As ID3D11Device, pFeatureLevel As D3D_FEATURE_LEVEL, ppImmediateContext As ID3D11DeviceContext) As VBHRESULT
193197
Private Declare Function CreateDXGIFactory1 Lib "dxgi" (riid As VBD3D11.VBGUID, ppFactory As IDXGIFactory1) As VBHRESULT
@@ -476,20 +480,24 @@ Private Enum RfbFileTransferProtocolEnum
476480
rfbFtpADirRecursiveListItem = 10
477481
rfbFtpADirRecursiveSize = 11
478482

479-
' Content params -- rfbFtpCommand Command
483+
' Content params -- rfbFtpCommand
480484
rfbFtpCDirCreate = 1 ' Request the server to create the given directory
481485
rfbFtpCDirDelete = 2 ' Request the server to delete the given directory
482486
rfbFtpCFileCreate = 3 ' Request the server to create the given file
483487
rfbFtpCFileDelete = 4 ' Request the server to delete the given file
484488
rfbFtpCFileRename = 5 ' Request the server to rename the given file
485489
rfbFtpCDirRename = 6 ' Request the server to rename the given directory
486490

487-
' Errors -- content params or "size" field
491+
' Size param - Errors
488492
rfbFtpSErrorUnknownCmd = 1 ' Unknown FileTransfer command.
489493
rfbFtpSErrorCmd = -1 ' Error when a command fails on remote side (ret in "size" field)
490-
rfbFtpSProtocolEnabled = 1 ' for rfbFtpAbortFileTransfer
494+
495+
' Size param - rfbFtpAbortFileTransfer
496+
rfbFtpSProtocolEnabled = 1
491497
rfbFtpSProtocolDisabled = -1
492-
rfbFtpSPacketUncompressed = 0 ' for rfbFtpFilePacket
498+
499+
' Size param - rfbFtpFilePacket
500+
rfbFtpSPacketUncompressed = 0
493501
rfbFtpSPacketCompressed = 1
494502
rfbFtpSPacketAlreadyThere = 2
495503
End Enum
@@ -1731,7 +1739,7 @@ Private Function pvSendFileTransferFileContent(uOutput As UcsBuffer, pStream As
17311739
On Error GoTo EH
17321740
ReDim baBuffer(0 To rfbFtpProtocolPacketSize - 1) As Byte
17331741
Do While Not m_oSocket.HasPendingEvent
1734-
If pvCheckHResult(IStream_Read(pStream, pvArrayPtr(baBuffer), pvArraySize(baBuffer), lRead)) < 0 Then
1742+
If pvCheckHResult(IStream_Read(pStream, pvArrayPtr(baBuffer), pvArraySize(baBuffer), lRead), FUNC_NAME) < 0 Then
17351743
If Not pvSendFileTransfer(uOutput, rfbFtpAbortFileTransfer) Then
17361744
GoTo QH
17371745
End If
@@ -1749,7 +1757,7 @@ Cleanup:
17491757
End If
17501758
If pChecksums Is Nothing Then
17511759
lChecksum = 0
1752-
ElseIf IStream_Read(pChecksums, VarPtr(lChecksum), 4) < 0 Then
1760+
ElseIf IStream_Read(pChecksums, VarPtr(lChecksum), 4) < 0 Then '-- don't check hResult
17531761
lChecksum = 0
17541762
Set pChecksums = Nothing
17551763
ElseIf lChecksum <> pvCalcAdler32(1, baBuffer, 0, lRead) Then
@@ -1797,6 +1805,8 @@ Private Function pvHandleFileTransfer(uOutput As UcsBuffer, uMsg As RfbFileTrans
17971805
Dim sFile As String
17981806
Dim lBufferSize As Long
17991807
Dim bDelaySend As Boolean
1808+
Dim aChecksum() As Long
1809+
Dim pStream As stdole.IUnknown
18001810

18011811
On Error GoTo EH
18021812
If uMsg.ContentType <> rfbFtpFilePacket And uMsg.ContentType <> rfbFtpFileChecksums Then
@@ -1934,9 +1944,9 @@ Private Function pvHandleFileTransfer(uOutput As UcsBuffer, uMsg As RfbFileTrans
19341944
#End If
19351945
If SHCreateStreamOnFile(StrPtr(sPath), STGM_READ, m_pFtpSendStream) < 0 Then
19361946
cStreamSize = ERROR_VALUE
1937-
ElseIf pvCheckHResult(IStream_Seek(m_pFtpSendStream, 0, STREAM_SEEK_END, cStreamSize)) < 0 Then
1947+
ElseIf pvCheckHResult(IStream_Seek(m_pFtpSendStream, 0, STREAM_SEEK_END, cStreamSize), FUNC_NAME) < 0 Then
19381948
cStreamSize = ERROR_VALUE
1939-
ElseIf pvCheckHResult(IStream_Seek(m_pFtpSendStream, 0, STREAM_SEEK_SET)) < 0 Then
1949+
ElseIf pvCheckHResult(IStream_Seek(m_pFtpSendStream, 0, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
19401950
cStreamSize = ERROR_VALUE
19411951
Else
19421952
sPath = sPath & "," & Format$(pvGetFileDateTime(sPath), FORMAT_FILEDATETIME)
@@ -1960,7 +1970,33 @@ Private Function pvHandleFileTransfer(uOutput As UcsBuffer, uMsg As RfbFileTrans
19601970
End If
19611971
Case rfbFtpFileTransferOffer
19621972
m_sFtpRecvFileName = Split(sPath, ",", Limit:=2)(0)
1963-
If pvCheckHResult(pvCreateStreamOnFile(m_sFtpRecvFileName, STGM_WRITE Or STGM_CREATE, m_pFtpRecvStream)) < 0 Then
1973+
If pvCreateStreamOnFile(m_sFtpRecvFileName, STGM_READ, pStream) < 0 Then '--- don't check hResult
1974+
GoTo SkipChecksums
1975+
End If
1976+
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_END, cStreamSize), FUNC_NAME) < 0 Then
1977+
GoTo SkipChecksums
1978+
End If
1979+
cStreamSize = cStreamSize * 10000@
1980+
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
1981+
GoTo SkipChecksums
1982+
End If
1983+
ReDim baBuffer(0 To rfbFtpProtocolPacketSize - 1) As Byte
1984+
ReDim aChecksum(0 To Int((cStreamSize + rfbFtpProtocolPacketSize - 1) / rfbFtpProtocolPacketSize)) As Long
1985+
For lIdx = 0 To UBound(aChecksum)
1986+
If IStream_Read(pStream, pvArrayPtr(baBuffer), pvArraySize(baBuffer), lSize) < 0 Or lSize = 0 Then '--- don't check hResult
1987+
Exit For
1988+
End If
1989+
aChecksum(lIdx) = pvCalcAdler32(1, baBuffer, 0, lSize)
1990+
Next
1991+
If lIdx > 0 Then
1992+
If Not pvSendFileTransfer(uOutput, rfbFtpFileChecksums, Ptr:=VarPtr(aChecksum(0)), Size:=lIdx * 4) Then
1993+
GoTo QH
1994+
End If
1995+
End If
1996+
SkipChecksums:
1997+
lIdx = IIf(pStream Is Nothing, STGM_CREATE, 0)
1998+
Set pStream = Nothing
1999+
If pvCheckHResult(pvCreateStreamOnFile(m_sFtpRecvFileName, STGM_WRITE Or lIdx, m_pFtpRecvStream), FUNC_NAME) < 0 Then
19642000
eStatus = rfbFtpSErrorCmd
19652001
End If
19662002
baBuffer = StrConv(m_sFtpRecvFileName, vbFromUnicode, GetSystemDefaultLCID())
@@ -1969,13 +2005,55 @@ Private Function pvHandleFileTransfer(uOutput As UcsBuffer, uMsg As RfbFileTrans
19692005
GoTo QH
19702006
End If
19712007
Case rfbFtpFilePacket
1972-
If IStream_Write(m_pFtpRecvStream, pvArrayPtr(baData), pvArraySize(baData)) < 0 Then
1973-
If Not pvSendFileTransfer(uOutput, rfbFtpAbortFileTransfer) Then
1974-
GoTo QH
2008+
If m_pFtpRecvStream Is Nothing Then
2009+
GoTo QH
2010+
End If
2011+
If uMsg.Size = rfbFtpSPacketAlreadyThere Then
2012+
If pvCheckHResult(IStream_Seek(m_pFtpRecvStream, uMsg.Length / 10000@, STREAM_SEEK_CUR), FUNC_NAME) < 0 Then
2013+
GoTo AbortRecv
2014+
End If
2015+
ElseIf uMsg.Size = rfbFtpSPacketCompressed Then
2016+
#If ImplZlib Then
2017+
Dim hCtx As Long
2018+
Dim lOutputPtr As Long
2019+
Dim lOutputSize As Long
2020+
With New cZipArchive
2021+
hCtx = .InflateInit()
2022+
'--- skip prefix (2 bytes zlib header) and suffix (4 bytes adler32 checksum)
2023+
.InflateBlob hCtx, VarPtr(baData(2)), pvArraySize(baData) - 2 - 4, lOutputPtr, lOutputSize
2024+
.InflateEnd hCtx
2025+
If lOutputSize = 0 Then
2026+
GoTo AbortRecv
2027+
End If
2028+
ReDim baData(0 To lOutputSize - 1) As Byte
2029+
Call CopyMemory(baData(0), ByVal lOutputPtr, lOutputSize)
2030+
Call CoTaskMemFree(lOutputPtr)
2031+
End With
2032+
#Else
2033+
#If ImplUseDebugLog Then
2034+
DebugLog MODULE_NAME, FUNC_NAME, "Compression not compiled (VNC_NO_ZLIB = 1)", vbLogEventTypeError
2035+
#End If
2036+
GoTo AbortRecv
2037+
#End If
2038+
uMsg.Size = rfbFtpSPacketUncompressed
2039+
End If
2040+
If uMsg.Size = rfbFtpSPacketUncompressed Then
2041+
If pvCheckHResult(IStream_Write(m_pFtpRecvStream, pvArrayPtr(baData), pvArraySize(baData)), FUNC_NAME) < 0 Then
2042+
AbortRecv:
2043+
Set m_pFtpRecvStream = Nothing
2044+
If Not pvSendFileTransfer(uOutput, rfbFtpAbortFileTransfer) Then
2045+
GoTo QH
2046+
End If
19752047
End If
19762048
End If
19772049
Case rfbFtpEndOfFile
2050+
If pvCheckHResult(IStream_Seek(m_pFtpRecvStream, 0, STREAM_SEEK_CUR, cStreamSize), FUNC_NAME) < 0 Then
2051+
cStreamSize = -1
2052+
End If
19782053
Set m_pFtpRecvStream = Nothing
2054+
If cStreamSize >= 0 Then
2055+
SetFileLen m_sFtpRecvFileName, cStreamSize * 10000@
2056+
End If
19792057
#If ImplZlib Then
19802058
If Right$(m_sFtpRecvFileName, sizeof_ZIP_SUFFIX) = STR_ZIP_SUFFIX Then
19812059
sPath = Mid$(m_sFtpRecvFileName, InStrRev(m_sFtpRecvFileName, "\") + 1)
@@ -2082,15 +2160,15 @@ Private Function pvHandleTightFileTransfer(uOutput As UcsBuffer, uMsg As UcsTigh
20822160
pvBufferWriteBlob uOutput, pvArrayPtr(uList.Data), uList.Size
20832161
Case rfbMsgTightUploadStartRequest
20842162
sFile = Mid$(uMsg.Path, 2)
2085-
If pvCheckHResult(pvCreateStreamOnFile(sFile, STGM_WRITE Or IIf((uMsg.Flags And 1) <> 0, STGM_CREATE, 0), m_pFtpRecvStream)) < 0 Then
2163+
If pvCheckHResult(pvCreateStreamOnFile(sFile, STGM_WRITE Or IIf((uMsg.Flags And 1) <> 0, STGM_CREATE, 0), m_pFtpRecvStream), FUNC_NAME) < 0 Then
20862164
GoTo Failed
20872165
End If
2088-
If pvCheckHResult(IStream_Seek(m_pFtpRecvStream, uMsg.Offset, STREAM_SEEK_SET)) < 0 Then
2166+
If pvCheckHResult(IStream_Seek(m_pFtpRecvStream, uMsg.Offset, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
20892167
GoTo Failed
20902168
End If
20912169
pvBufferWriteLong uOutput, rfbMsgTightUploadStartReply, Size:=4
20922170
Case rfbMsgTightUploadDataRequest
2093-
If pvCheckHResult(IStream_Write(m_pFtpRecvStream, pvArrayPtr(baData), pvArraySize(baData))) < 0 Then
2171+
If pvCheckHResult(IStream_Write(m_pFtpRecvStream, pvArrayPtr(baData), pvArraySize(baData)), FUNC_NAME) < 0 Then
20942172
GoTo Failed
20952173
End If
20962174
pvBufferWriteLong uOutput, rfbMsgTightUploadDataReply, Size:=4
@@ -2099,16 +2177,16 @@ Private Function pvHandleTightFileTransfer(uOutput As UcsBuffer, uMsg As UcsTigh
20992177
pvBufferWriteLong uOutput, rfbMsgTightUploadEndReply, Size:=4
21002178
Case rfbMsgTightDownloadStartRequest
21012179
m_sFtpRecvFileName = Mid(uMsg.Path, 2)
2102-
If pvCheckHResult(pvCreateStreamOnFile(m_sFtpRecvFileName, STGM_READ, m_pFtpSendStream)) < 0 Then
2180+
If pvCheckHResult(pvCreateStreamOnFile(m_sFtpRecvFileName, STGM_READ, m_pFtpSendStream), FUNC_NAME) < 0 Then
21032181
GoTo Failed
21042182
End If
2105-
If pvCheckHResult(IStream_Seek(m_pFtpSendStream, uMsg.Offset, STREAM_SEEK_SET)) < 0 Then
2183+
If pvCheckHResult(IStream_Seek(m_pFtpSendStream, uMsg.Offset, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
21062184
GoTo Failed
21072185
End If
21082186
pvBufferWriteLong uOutput, rfbMsgTightDownloadStartReply, Size:=4
21092187
Case rfbMsgTightDownloadDataRequest
21102188
pvArrayAllocate baBuffer, Clamp(uMsg.DataSize, , 2 ^ 20), FUNC_NAME & ".baBuffer"
2111-
If pvCheckHResult(IStream_Read(m_pFtpSendStream, pvArrayPtr(baBuffer), pvArraySize(baBuffer), lSize)) < 0 Then
2189+
If pvCheckHResult(IStream_Read(m_pFtpSendStream, pvArrayPtr(baBuffer), pvArraySize(baBuffer), lSize), FUNC_NAME) < 0 Then
21122190
GoTo Failed
21132191
End If
21142192
If lSize = 0 Then
@@ -2839,14 +2917,14 @@ Private Function pvCaptureSend(uFrame As UcsCaptureFrame, uOutput As UcsBuffer)
28392917
#If ImplUseDebugLog Then
28402918
sDebugInfo = sDebugInfo & " H=" & Format$(cTemp, "0.00") & " QL=" & lQualityLevel
28412919
#End If
2842-
If pvCheckHResult(IStream_Seek(m_pImageStream, 0, STREAM_SEEK_SET)) < 0 Then
2920+
If pvCheckHResult(IStream_Seek(m_pImageStream, 0, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
28432921
GoTo QH
28442922
End If
28452923
If Not pvWicConvertImage(m_pImageStream, m_aWicFormatJpeg, Clamp(lQualityLevel, 1, 100), _
28462924
uTile.Data, .Tiles(lIdx).Width, .Tiles(lIdx).Height, m_aWicFormat32bppBGR) Then
28472925
GoTo QH
28482926
End If
2849-
If pvCheckHResult(IStream_Seek(m_pImageStream, 0, STREAM_SEEK_CUR, cTemp)) < 0 Then
2927+
If pvCheckHResult(IStream_Seek(m_pImageStream, 0, STREAM_SEEK_CUR, cTemp), FUNC_NAME) < 0 Then
28502928
GoTo QH
28512929
End If
28522930
lSize = cTemp * 10000
@@ -3081,43 +3159,43 @@ Private Function pvWicConvertImage( _
30813159
Dim aBag(0 To 7) As Long
30823160

30833161
On Error GoTo EH
3084-
If pvCheckHResult(IWICImagingFactory_CreateBitmapFromMemory_Proxy(m_pWicFactory, lWidth, lHeight, aPixelFormat(0), lWidth * 4, UBound(baInput) + 1, baInput(0), pBitmap)) < 0 Then
3162+
If pvCheckHResult(IWICImagingFactory_CreateBitmapFromMemory_Proxy(m_pWicFactory, lWidth, lHeight, aPixelFormat(0), lWidth * 4, UBound(baInput) + 1, baInput(0), pBitmap), FUNC_NAME) < 0 Then
30853163
GoTo QH
30863164
End If
3087-
If pvCheckHResult(IWICImagingFactory_CreateStream_Proxy(m_pWicFactory, pWicStream)) < 0 Then
3165+
If pvCheckHResult(IWICImagingFactory_CreateStream_Proxy(m_pWicFactory, pWicStream), FUNC_NAME) < 0 Then
30883166
GoTo QH
30893167
End If
3090-
If pvCheckHResult(IWICStream_InitializeFromIStream_Proxy(pWicStream, pOutput)) < 0 Then
3168+
If pvCheckHResult(IWICStream_InitializeFromIStream_Proxy(pWicStream, pOutput), FUNC_NAME) < 0 Then
30913169
GoTo QH
30923170
End If
3093-
If pvCheckHResult(IWICImagingFactory_CreateEncoder_Proxy(m_pWicFactory, aContainerFormat(0), ByVal 0, pEncoder)) < 0 Then
3171+
If pvCheckHResult(IWICImagingFactory_CreateEncoder_Proxy(m_pWicFactory, aContainerFormat(0), ByVal 0, pEncoder), FUNC_NAME) < 0 Then
30943172
GoTo QH
30953173
End If
3096-
If pvCheckHResult(IWICBitmapEncoder_Initialize_Proxy(pEncoder, pWicStream, WICBitmapEncoderNoCache)) < 0 Then
3174+
If pvCheckHResult(IWICBitmapEncoder_Initialize_Proxy(pEncoder, pWicStream, WICBitmapEncoderNoCache), FUNC_NAME) < 0 Then
30973175
GoTo QH
30983176
End If
3099-
If pvCheckHResult(IWICBitmapEncoder_CreateNewFrame_Proxy(pEncoder, pFrame, pPropBag)) < 0 Then
3177+
If pvCheckHResult(IWICBitmapEncoder_CreateNewFrame_Proxy(pEncoder, pFrame, pPropBag), FUNC_NAME) < 0 Then
31003178
GoTo QH
31013179
End If
31023180
If lImageQuality <> 0 Then
31033181
aBag(3) = StrPtr("ImageQuality")
3104-
If pvCheckHResult(IPropertyBag2_Write_Proxy(pPropBag, 1, aBag(0), CSng(lImageQuality) / 100!)) < 0 Then
3182+
If pvCheckHResult(IPropertyBag2_Write_Proxy(pPropBag, 1, aBag(0), CSng(lImageQuality) / 100!), FUNC_NAME) < 0 Then
31053183
GoTo QH
31063184
End If
31073185
End If
3108-
If pvCheckHResult(IWICBitmapFrameEncode_Initialize_Proxy(pFrame, pPropBag)) < 0 Then
3186+
If pvCheckHResult(IWICBitmapFrameEncode_Initialize_Proxy(pFrame, pPropBag), FUNC_NAME) < 0 Then
31093187
GoTo QH
31103188
End If
3111-
If pvCheckHResult(IWICBitmapFrameEncode_SetSize_Proxy(pFrame, lWidth, lHeight)) < 0 Then
3189+
If pvCheckHResult(IWICBitmapFrameEncode_SetSize_Proxy(pFrame, lWidth, lHeight), FUNC_NAME) < 0 Then
31123190
GoTo QH
31133191
End If
3114-
If pvCheckHResult(IWICBitmapFrameEncode_WriteSource_Proxy(pFrame, pBitmap, ByVal 0)) < 0 Then
3192+
If pvCheckHResult(IWICBitmapFrameEncode_WriteSource_Proxy(pFrame, pBitmap, ByVal 0), FUNC_NAME) < 0 Then
31153193
GoTo QH
31163194
End If
3117-
If pvCheckHResult(IWICBitmapFrameEncode_Commit_Proxy(pFrame)) < 0 Then
3195+
If pvCheckHResult(IWICBitmapFrameEncode_Commit_Proxy(pFrame), FUNC_NAME) < 0 Then
31183196
GoTo QH
31193197
End If
3120-
If pvCheckHResult(IWICBitmapEncoder_Commit_Proxy(pEncoder)) < 0 Then
3198+
If pvCheckHResult(IWICBitmapEncoder_Commit_Proxy(pEncoder), FUNC_NAME) < 0 Then
31213199
GoTo QH
31223200
End If
31233201
'--- success
@@ -3128,18 +3206,16 @@ EH:
31283206
PrintError FUNC_NAME
31293207
End Function
31303208

3131-
Private Function pvCheckHResult(ByVal hResult As Long, Optional vErrSource As Variant) As Long
3132-
Const FUNC_NAME As String = "pvCheckHResult"
3133-
3209+
Private Function pvCheckHResult(ByVal hResult As Long, sFunction As String) As Long
31343210
On Error GoTo EH
31353211
If hResult < 0 Then
3136-
Err.Raise hResult, vErrSource
3212+
Err.Raise hResult
31373213
End If
31383214
QH:
31393215
pvCheckHResult = hResult
31403216
Exit Function
31413217
EH:
3142-
PrintError IIf(IsMissing(vErrSource), FUNC_NAME, vErrSource)
3218+
PrintError sFunction
31433219
Resume QH
31443220
End Function
31453221

@@ -3334,19 +3410,20 @@ Private Sub pvBufferWriteCurrency(uOutput As UcsBuffer, cValue As Currency)
33343410
End Sub
33353411

33363412
Private Sub pvBufferWriteStream(uOutput As UcsBuffer, pStream As stdole.IUnknown)
3413+
Const FUNC_NAME As String = "pvBufferWriteStream"
33373414
Dim cTemp As Currency
33383415
Dim lSize As Long
33393416

3340-
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_CUR, cTemp)) < 0 Then
3417+
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_CUR, cTemp), FUNC_NAME) < 0 Then
33413418
GoTo QH
33423419
End If
33433420
lSize = cTemp * 10000
33443421
If lSize > 0 Then
33453422
pvBufferWriteBlob uOutput, 0, lSize
3346-
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_SET)) < 0 Then
3423+
If pvCheckHResult(IStream_Seek(pStream, 0, STREAM_SEEK_SET), FUNC_NAME) < 0 Then
33473424
GoTo QH
33483425
End If
3349-
If pvCheckHResult(IStream_Read(pStream, VarPtr(uOutput.Data(uOutput.Size - lSize)), lSize)) < 0 Then
3426+
If pvCheckHResult(IStream_Read(pStream, VarPtr(uOutput.Data(uOutput.Size - lSize)), lSize), FUNC_NAME) < 0 Then
33503427
GoTo QH
33513428
End If
33523429
End If
@@ -3703,6 +3780,25 @@ End Property
37033780
Private Function Zn(sText As String, Optional IfEmptyString As Variant = Null, Optional EmptyString As String) As Variant
37043781
Zn = IIf(sText = EmptyString, IfEmptyString, sText)
37053782
End Function
3783+
3784+
Private Function SetFileLen(sFile As String, ByVal cFileSize As Currency, Optional ByVal Exclusive As Boolean) As Boolean
3785+
Const GENERIC_WRITE As Long = &H40000000
3786+
Const OPEN_EXISTING As Long = 3
3787+
Const FILE_SHARE_READ As Long = &H1
3788+
Const FILE_BEGIN As Long = 0
3789+
Dim hFile As Long
3790+
3791+
hFile = CreateFile(StrPtr(sFile), GENERIC_WRITE, IIf(Exclusive, 0, FILE_SHARE_READ), 0, OPEN_EXISTING, 0, 0)
3792+
If hFile <> 0 Then
3793+
If SetFilePointerEx(hFile, cFileSize / 10000@, 0, FILE_BEGIN) <> 0 Then
3794+
If SetEndOfFile(hFile) <> 0 Then
3795+
'--- success
3796+
SetFileLen = True
3797+
End If
3798+
End If
3799+
Call CloseHandle(hFile)
3800+
End If
3801+
End Function
37063802
#End If
37073803

37083804
'=========================================================================

0 commit comments

Comments
 (0)