How to create a SPARSE file in VB.NET
-
Hi, I am trying to create a SPARSE file that reflects the size of an original file. for excample, I would like to create a 33gb(Logical) file that is physically only a few bytes. I am able to create a 0(logical/physical) byte file only with the following code but I can't seem to get the Logical value assigned. Could someone tel me what I'm missing? Module Module1 Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _ ByVal lpFileName As String, _ ByVal dwDesiredAccess As Integer, _ ByVal dwShareMode As Integer, _ ByVal lpSecurityAttributes As Integer, _ ByVal dwCreationDisposition As Integer, _ ByVal dwFlagsAndAttributes As Integer, _ ByVal hTemplateFile As Integer) As Integer Public Declare Function SetFilePointer Lib "kernel32" Alias "SetFilePointer" ( _ ByVal hFile As Integer, _ ByVal lDistanceToMove As Integer, _ ByVal lpDistanceToMoveHigh As Integer, _ ByVal dwMoveMethod As Integer) As Integer Public Declare Function SetEndOfFile Lib "kernel32" ( _ ByVal hFile As Integer) As Integer Public Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Integer) As Integer Public Declare Function DeviceIoControl Lib "kernel32" ( _ ByVal hDevice As Long, _ ByVal dwIoControlCode As Long, _ |ByVal lpInBuffer As String, _ ByVal nInBufferSize As Long, _ ByVal lpOutBuffer As String, _ ByVal nOutBufferSize As Long, _ ByVal lpBytesReturned As Long, _ ByVal lpOverlapped As String) As Long End Module Public Class Form1 Inherits System.Windows.Forms.Form Const _WIN32_WINNT = 5 Public Const CREATE_ALWAYS = 2 Public Const CREATE_NEW = 1 Public Const OPEN_ALWAYS = 4 'Create if doesn't exist Public Const OPEN_EXISTING = 3 Public Const TRUNCATE_EXISTING = 5 Public Const FILE_ATTRIBUTE_ARCHIVE = &H20 Public Const FSCTL_SET_SPARSE = &H900C4 Public Const MOVEFILE_REPLACE_EXISTING = &H1 Public Const FILE_ATTRIBUTE_TEMPORARY = &H100 Public Const FILE_BEGIN = 0 Public Const FILE_SHARE_READ = &H1 Public Const FILE_SHARE_WRITE = &H2 Public Const GENERIC_READ = &H80000000 Public Const GENERIC_WRITE = &H40000000 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim h Dim d Dim n Dim dw As Integer Dim lDist As Integer h = CreateFile("D:\Wes.log", GENERIC_WRITE + GENERIC_READ, 0, 0, CREATE_ALWAYS, 0, 0) dw = 0 d = DeviceIoControl(h, FSCTL_SET_SPARSE, n, 0, n, 0, dw, 0) lDist = 8 MsgBox(h & " " & lDist) SetFilePointer(h, 0, lDist, FILE_BEGIN) CloseHandle(h)
-
Hi, I am trying to create a SPARSE file that reflects the size of an original file. for excample, I would like to create a 33gb(Logical) file that is physically only a few bytes. I am able to create a 0(logical/physical) byte file only with the following code but I can't seem to get the Logical value assigned. Could someone tel me what I'm missing? Module Module1 Public Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _ ByVal lpFileName As String, _ ByVal dwDesiredAccess As Integer, _ ByVal dwShareMode As Integer, _ ByVal lpSecurityAttributes As Integer, _ ByVal dwCreationDisposition As Integer, _ ByVal dwFlagsAndAttributes As Integer, _ ByVal hTemplateFile As Integer) As Integer Public Declare Function SetFilePointer Lib "kernel32" Alias "SetFilePointer" ( _ ByVal hFile As Integer, _ ByVal lDistanceToMove As Integer, _ ByVal lpDistanceToMoveHigh As Integer, _ ByVal dwMoveMethod As Integer) As Integer Public Declare Function SetEndOfFile Lib "kernel32" ( _ ByVal hFile As Integer) As Integer Public Declare Function CloseHandle Lib "kernel32" ( _ ByVal hObject As Integer) As Integer Public Declare Function DeviceIoControl Lib "kernel32" ( _ ByVal hDevice As Long, _ ByVal dwIoControlCode As Long, _ |ByVal lpInBuffer As String, _ ByVal nInBufferSize As Long, _ ByVal lpOutBuffer As String, _ ByVal nOutBufferSize As Long, _ ByVal lpBytesReturned As Long, _ ByVal lpOverlapped As String) As Long End Module Public Class Form1 Inherits System.Windows.Forms.Form Const _WIN32_WINNT = 5 Public Const CREATE_ALWAYS = 2 Public Const CREATE_NEW = 1 Public Const OPEN_ALWAYS = 4 'Create if doesn't exist Public Const OPEN_EXISTING = 3 Public Const TRUNCATE_EXISTING = 5 Public Const FILE_ATTRIBUTE_ARCHIVE = &H20 Public Const FSCTL_SET_SPARSE = &H900C4 Public Const MOVEFILE_REPLACE_EXISTING = &H1 Public Const FILE_ATTRIBUTE_TEMPORARY = &H100 Public Const FILE_BEGIN = 0 Public Const FILE_SHARE_READ = &H1 Public Const FILE_SHARE_WRITE = &H2 Public Const GENERIC_READ = &H80000000 Public Const GENERIC_WRITE = &H40000000 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim h Dim d Dim n Dim dw As Integer Dim lDist As Integer h = CreateFile("D:\Wes.log", GENERIC_WRITE + GENERIC_READ, 0, 0, CREATE_ALWAYS, 0, 0) dw = 0 d = DeviceIoControl(h, FSCTL_SET_SPARSE, n, 0, n, 0, dw, 0) lDist = 8 MsgBox(h & " " & lDist) SetFilePointer(h, 0, lDist, FILE_BEGIN) CloseHandle(h)
First, your declaration for DeviceIOControl is wrong. Your passing all variable in ByVal, but some of the parameters must be passed in ByRef. This is because DeviceIOControl is looking for the address of the variable, not it's value. The parameters that start with 'lp' are actually long pointers, which represent a 32-bit address, not a value. This is where you pass by reference.
Public Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Long, _
ByVal dwIoControlCode As Long, _
ByRef lpInBuffer As String, _
ByVal nInBufferSize As Long, _
ByRef lpOutBuffer As String, _
ByVal nOutBufferSize As Long, _
ByRef lpBytesReturned As Long, _
ByVal lpOverlapped As String) As LongTry that and see what happens... RageInTheMachine9532
-
First, your declaration for DeviceIOControl is wrong. Your passing all variable in ByVal, but some of the parameters must be passed in ByRef. This is because DeviceIOControl is looking for the address of the variable, not it's value. The parameters that start with 'lp' are actually long pointers, which represent a 32-bit address, not a value. This is where you pass by reference.
Public Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Long, _
ByVal dwIoControlCode As Long, _
ByRef lpInBuffer As String, _
ByVal nInBufferSize As Long, _
ByRef lpOutBuffer As String, _
ByVal nOutBufferSize As Long, _
ByRef lpBytesReturned As Long, _
ByVal lpOverlapped As String) As LongTry that and see what happens... RageInTheMachine9532
I've tried it but it dies with the following error..... ************** Exception Text ************** System.NullReferenceException: Object reference not set to an instance of an object. at WS_NTFS.Module1.DeviceIoControl(Int64 hDevice, Int64 dwIoControlCode, String& lpInBuffer, Int64 nInBufferSize, String& lpOutBuffer, Int64 nOutBufferSize, Int64& lpBytesReturned, String& lpOverlapped) at WS_NTFS.Form1.Button1_Click(Object sender, EventArgs e) in D:\@Projects\WeshillNTFS\NTFS_5_PT2_Src\WS_NTFS\Form1.vb:line 127 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
-
I've tried it but it dies with the following error..... ************** Exception Text ************** System.NullReferenceException: Object reference not set to an instance of an object. at WS_NTFS.Module1.DeviceIoControl(Int64 hDevice, Int64 dwIoControlCode, String& lpInBuffer, Int64 nInBufferSize, String& lpOutBuffer, Int64 nOutBufferSize, Int64& lpBytesReturned, String& lpOverlapped) at WS_NTFS.Form1.Button1_Click(Object sender, EventArgs e) in D:\@Projects\WeshillNTFS\NTFS_5_PT2_Src\WS_NTFS\Form1.vb:line 127 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Part of the problem is you are passing in strings for your buffers, don't. This is the example your looking for:
Imports System
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices
Module Module1
Private Const FILE_ANY_ACCESS = 0
Private Const FILE_READ_ACCESS = 1
Private Const FILE_WRITE_ACCESS = 2
Private Const FILE_DEVICE_FILE_SYSTEM = 9
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_READ = 1
Private Const FILE_SHARE_WRITE = 2
Private Const CREATE_NEW = 1
Private Const CREATE_ALWAYS = 2
Private Const OPEN_EXISTING = 3
Private Const OPEN_ALWAYS = 4
Private Const TRUNCATE_EXISTING = 5
Public Const FSCTL_SET_REPARSE_POINT = &H900A4
Public Const FSCTL_GET_REPARSE_POINT = &H900A8
Public Const FSCTL_DELETE_REPARSE_POINT = &H900AC
Public Const FSCTL_SET_SPARSE = &H900C4
Public Const FSCTL_SET_ZERO_DATA = &H980C8
Private Const INVALID_HANDLE_VALUE = -1
Private Declare Function GetLastError Lib "kernel32" Alias "GetLastError" () As Integer
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
ByVal lpFileName As String, _
ByVal dwDesiredAccess As Integer, _
ByVal dwShareMode As Integer, _
ByVal lpSecurityAttributes As Integer, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As Integer
Private Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" ( _
ByVal handle As Integer) As Integer
Private Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Integer, _
ByVal dwIoControlCode As Integer, _
ByRef lpInBuffer() As Byte, _
ByVal nInBufferSize As Integer, _
ByRef lpOutBuffer() As Byte, _
ByVal nOutBufferSize As Integer, _
ByRef lpBytesReturned As Integer, _
ByVal lpOverlapped As Long) As Integer
Sub Main()
Dim path As String = "D:\MyTest.dat"
Dim hFileHandle As Integer
Dim rc As Integer
Dim iBytesReturned As Integer
Dim inBuffer(512) As Byte
Dim outBuffer(512) As Byte
hFileHandle = CreateFile(path, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0) -
Part of the problem is you are passing in strings for your buffers, don't. This is the example your looking for:
Imports System
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices
Module Module1
Private Const FILE_ANY_ACCESS = 0
Private Const FILE_READ_ACCESS = 1
Private Const FILE_WRITE_ACCESS = 2
Private Const FILE_DEVICE_FILE_SYSTEM = 9
Private Const GENERIC_READ = &H80000000
Private Const GENERIC_WRITE = &H40000000
Private Const FILE_SHARE_READ = 1
Private Const FILE_SHARE_WRITE = 2
Private Const CREATE_NEW = 1
Private Const CREATE_ALWAYS = 2
Private Const OPEN_EXISTING = 3
Private Const OPEN_ALWAYS = 4
Private Const TRUNCATE_EXISTING = 5
Public Const FSCTL_SET_REPARSE_POINT = &H900A4
Public Const FSCTL_GET_REPARSE_POINT = &H900A8
Public Const FSCTL_DELETE_REPARSE_POINT = &H900AC
Public Const FSCTL_SET_SPARSE = &H900C4
Public Const FSCTL_SET_ZERO_DATA = &H980C8
Private Const INVALID_HANDLE_VALUE = -1
Private Declare Function GetLastError Lib "kernel32" Alias "GetLastError" () As Integer
Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" ( _
ByVal lpFileName As String, _
ByVal dwDesiredAccess As Integer, _
ByVal dwShareMode As Integer, _
ByVal lpSecurityAttributes As Integer, _
ByVal dwCreationDisposition As Integer, _
ByVal dwFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As Integer
Private Declare Function CloseHandle Lib "kernel32" Alias "CloseHandle" ( _
ByVal handle As Integer) As Integer
Private Declare Function DeviceIoControl Lib "kernel32" ( _
ByVal hDevice As Integer, _
ByVal dwIoControlCode As Integer, _
ByRef lpInBuffer() As Byte, _
ByVal nInBufferSize As Integer, _
ByRef lpOutBuffer() As Byte, _
ByVal nOutBufferSize As Integer, _
ByRef lpBytesReturned As Integer, _
ByVal lpOverlapped As Long) As Integer
Sub Main()
Dim path As String = "D:\MyTest.dat"
Dim hFileHandle As Integer
Dim rc As Integer
Dim iBytesReturned As Integer
Dim inBuffer(512) As Byte
Dim outBuffer(512) As Byte
hFileHandle = CreateFile(path, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0)I will give this a try. The reason for this is that I want to copy the original file to tape, for example, then create an empty file of the same name, to free up space. This file will act as a reference to remind me that I do have a file by that name on tape. I know that I could create a 0 byte file but I prefer to see the original size of the file without actually having it use the disk space. I am hoping that Sparsing would help with this. Thanks for your help.
-
I will give this a try. The reason for this is that I want to copy the original file to tape, for example, then create an empty file of the same name, to free up space. This file will act as a reference to remind me that I do have a file by that name on tape. I know that I could create a 0 byte file but I prefer to see the original size of the file without actually having it use the disk space. I am hoping that Sparsing would help with this. Thanks for your help.
I have tried this and it works beautifully. Thanks so much. I have another question... I notice when the file is sparsed I have access to that space, however, when I try to copy or delete the Sparsed file the OS treats it like a regular file. For example, instead of coping 8kb of data it tries to copy 33gb. Is there a way to view the logical size as 33gb but tell the OS to treat it as an 8kb file during these type of manipulations? Thanks, I am not sure if there is someway besig